release-v1.0 #1

Merged
panchichun merged 57 commits from release-v1.0 into main 2024-09-13 17:04:18 +08:00
101 changed files with 12707 additions and 3399 deletions

View File

@ -1,5 +1,5 @@
# 页面标题
VUE_APP_TITLE = 工具管理技术交流平台
VUE_APP_TITLE = 工具管理技术交流平台
# 开发环境配置
ENV = 'development'
@ -7,14 +7,14 @@ ENV = 'development'
VUE_APP_CONTEXT_PATH = '/tool-tech'
# 工具与技术交流管理系统/开发环境
VUE_APP_BASE_API = 'http://192.168.2.85:8080/tool-tech-admin'
VUE_APP_WS_URL = 'ws://192.168.2.85:8080/tool-tech-admin/websocket'
VUE_APP_BASE_API = 'http://localhost:8080/tool-tech-admin'
VUE_APP_WS_URL = 'ws://localhost:8080/tool-tech-admin/websocket'
# 文档在线预览服务
VUE_APP_TOOL_TECH_FILE_VIEW_API = 'http://192.168.1.2:8012/tool-tech-file-view'
VUE_APP_TOOL_TECH_FILE_VIEW_API = 'http://127.0.0.1:8012/tool-tech-file-view'
# 流程管理服务地址
VUE_APP_WORKFLOW_MANAGE_URL = 'http://192.168.1.2:8080/ebpm-process-manage'
VUE_APP_WORKFLOW_MANAGE_URL = '/ebpm-process-manage'
# 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true

View File

@ -1,5 +1,5 @@
# 页面标题
VUE_APP_TITLE = 工具管理技术交流平台
VUE_APP_TITLE = 工具管理技术交流平台
# 生产环境配置
ENV = 'production'
@ -7,11 +7,11 @@ ENV = 'production'
VUE_APP_CONTEXT_PATH = '/tool-tech'
# 工具与技术交流管理系统/生产环境
VUE_APP_BASE_API = '/prod-api'
VUE_APP_WS_URL = 'wss://www.rzdata.net/tool-tech-admin/websocket'
VUE_APP_BASE_API = '/tool-tech-admin'
VUE_APP_WS_URL = '/tool-tech-admin/websocket'
# 文档在线预览服务
VUE_APP_TOOL_TECH_FILE_VIEW_API = 'http://localhost:8012/tool-tech-file-view'
VUE_APP_TOOL_TECH_FILE_VIEW_API = '/tool-tech-file-view'
# 流程管理服务地址
VUE_APP_WORKFLOW_MANAGE_URL = 'http://localhost:8085/ebpm-process-manage'
VUE_APP_WORKFLOW_MANAGE_URL = '/ebpm-process-manage'

View File

@ -1,5 +1,5 @@
# 页面标题
VUE_APP_TITLE = 工具管理技术交流平台
VUE_APP_TITLE = 工具管理技术交流平台
NODE_ENV = production
@ -9,8 +9,8 @@ ENV = 'staging'
VUE_APP_CONTEXT_PATH = '/tool-tech'
# 工具与技术交流管理系统/测试环境
VUE_APP_BASE_API = 'https://www.rzdata.net/tool-tech-admin'
VUE_APP_WS_URL = 'wss://www.rzdata.net/tool-tech-admin/websocket'
VUE_APP_BASE_API = '/tool-tech-admin'
VUE_APP_WS_URL = '/tool-tech-admin/websocket'
# 文档在线预览服务
VUE_APP_TOOL_TECH_FILE_VIEW_API = '/tool-tech-file-view'

View File

@ -1,27 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JSCodeStyleSettings version="0">
<option name="USE_SEMICOLON_AFTER_STATEMENT" value="false" />
<option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="SPACE_BEFORE_GENERATOR_MULT" value="true" />
<option name="SPACE_BEFORE_FUNCTION_LEFT_PARENTH" value="false" />
<option name="USE_DOUBLE_QUOTES" value="false" />
<option name="FORCE_QUOTE_STYlE" value="true" />
<option name="ENFORCE_TRAILING_COMMA" value="Remove" />
<option name="SPACES_WITHIN_OBJECT_LITERAL_BRACES" value="true" />
<option name="SPACES_WITHIN_IMPORTS" value="true" />
<option name="SPACE_BEFORE_ASYNC_ARROW_LPAREN" value="false" />
</JSCodeStyleSettings>
<codeStyleSettings language="JavaScript">
<option name="KEEP_BLANK_LINES_IN_CODE" value="1" />
<option name="IF_BRACE_FORCE" value="1" />
<option name="DOWHILE_BRACE_FORCE" value="1" />
<option name="WHILE_BRACE_FORCE" value="1" />
<option name="FOR_BRACE_FORCE" value="1" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
</component>

View File

@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

View File

@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

6
.idea/misc.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

8
.idea/modules.xml generated
View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/tool-tech-front.iml" filepath="$PROJECT_DIR$/.idea/tool-tech-front.iml" />
</modules>
</component>
</project>

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

6
.idea/vcs.xml generated
View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

973
.idea/workspace.xml generated
View File

@ -1,973 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ChangeListManager">
<list default="true" id="880b2c9e-bb63-49b5-a9b3-35bf50aa9da8" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/.env.staging" beforeDir="false" afterPath="$PROJECT_DIR$/.env.staging" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/default.conf" beforeDir="false" afterPath="$PROJECT_DIR$/default.conf" afterDir="false" />
</list>
<ignored path="$PROJECT_DIR$/.tmp/" />
<ignored path="$PROJECT_DIR$/temp/" />
<ignored path="$PROJECT_DIR$/tmp/" />
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="FileEditorManager">
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/views/workstuff/message/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="722">
<caret line="38" column="4" selection-start-line="38" selection-start-column="4" selection-end-line="45" selection-end-column="40" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/views/tool/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2356">
<caret line="177" column="132" selection-start-line="177" selection-start-column="96" selection-end-line="177" selection-end-column="132" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
<element signature="n#style#0;n#el-select#0;n#el-form-item#2;n#div#0;n#div#0;n#div#0;n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#el-date-picker#0;n#el-form-item#3;n#div#0;n#div#0;n#div#0;n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#el-input#0;n#div#0;n#el-card#1;n#div#0;n#template#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#el-select#0;n#el-form-item#0;n#el-col#0;n#el-row#3;n#el-form#0;n#div#0;n#el-drawer#0;n#div#0;n#template#0;n#!!top" expanded="true" />
<element signature="n#el-drawer#2;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/views/tool/toolDetail.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2451">
<caret line="129" column="50" selection-start-line="129" selection-start-column="50" selection-end-line="129" selection-end-column="50" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/plugins/modal.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="266">
<caret line="14" column="2" selection-start-line="14" selection-start-column="2" selection-end-line="14" selection-end-column="2" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/views/document/editDocument.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2603">
<caret line="139" column="12" lean-forward="true" selection-start-line="139" selection-start-column="12" selection-end-line="139" selection-end-column="12" />
<folding>
<element signature="n#style#0;n#el-table#0;n#div#0;n#el-dialog#0;n#div#0;n#template#0;n#!!top" expanded="true" />
</folding>
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/.env.staging">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="342">
<caret line="18" column="31" selection-start-line="18" selection-start-column="31" selection-end-line="18" selection-end-column="31" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/default.conf">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="475">
<caret line="25" column="36" lean-forward="true" selection-start-line="25" selection-start-column="36" selection-end-line="25" selection-end-column="36" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/.env.development">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="228">
<caret line="12" selection-start-line="12" selection-end-line="16" selection-end-column="75" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/.env.production">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="19">
<caret line="1" column="27" selection-start-line="1" selection-start-column="27" selection-end-line="1" selection-end-column="27" />
</state>
</provider>
</entry>
</file>
<file pinned="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/src/views/workflow/config/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="247">
<caret line="13" column="103" selection-start-line="13" selection-start-column="72" selection-end-line="13" selection-end-column="103" />
</state>
</provider>
</entry>
</file>
</leaf>
</component>
<component name="FileTemplateManagerImpl">
<option name="RECENT_TEMPLATES">
<list>
<option value="Vue Single File Component" />
</list>
</option>
</component>
<component name="FindInProjectRecents">
<findStrings>
<find>deptName</find>
<find>peopleSelect</find>
<find>onChange</find>
<find>submitForm</find>
<find>initWebSocket</find>
<find>generateUniqueID</find>
<find>progress</find>
<find>listDocument</find>
<find>previewUrl</find>
<find>toolPrincipalsChoose</find>
<find>showOpenHandle</find>
<find>toolDetail</find>
<find>editDocumentRef</find>
<find>checkDuplicate</find>
<find>申请使用</find>
<find>applyDrawerOpen</find>
<find>cancelApply</find>
<find>submitApply</find>
<find>applyUse</find>
<find>handleDelete</find>
<find>监控</find>
<find>审批记录</find>
<find>tableData4</find>
<find>drawer2</find>
<find>tableData7</find>
<find>getClassName</find>
<find>已通过</find>
<find>el-dialog</find>
<find>ids</find>
<find>drawer1</find>
</findStrings>
<replaceStrings>
<replace>docList</replace>
<replace>toolList</replace>
<replace>handlePublish</replace>
<replace>applyDrawerOpen</replace>
<replace>exoportDrawerOpen</replace>
<replace>detailDrawerOpen</replace>
<replace>通过</replace>
</replaceStrings>
<dirStrings>
<dir>D:\rzdata\ToolTech\tool-tech-front</dir>
<dir>D:\rzdata\ToolTech\tool-tech-front\src</dir>
</dirStrings>
</component>
<component name="Git.Settings">
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/src/views/system/user/profile/userAvatar.vue" />
<option value="$PROJECT_DIR$/src/api/system/user.js" />
<option value="$PROJECT_DIR$/src/api/document/document.js" />
<option value="$PROJECT_DIR$/src/views/workflow/index.vue" />
<option value="$PROJECT_DIR$/src/views/workflow/config/index.vue" />
<option value="$PROJECT_DIR$/src/views/workflow/task/index.vue" />
<option value="$PROJECT_DIR$/src/api/tool/tool.js" />
<option value="$PROJECT_DIR$/public/css/poctstyle.css" />
<option value="$PROJECT_DIR$/src/components/userSelector/userSelect.vue" />
<option value="$PROJECT_DIR$/src/components/user-selector/src/user-selector.vue" />
<option value="$PROJECT_DIR$/vue.config.js" />
<option value="$PROJECT_DIR$/Dockerfile" />
<option value="$PROJECT_DIR$/public/css/index.css" />
<option value="$PROJECT_DIR$/src/main.js" />
<option value="$PROJECT_DIR$/src/utils/request.js" />
<option value="$PROJECT_DIR$/src/views/login.vue" />
<option value="$PROJECT_DIR$/src/views/statistic/index.vue" />
<option value="$PROJECT_DIR$/src/store/getters.js" />
<option value="$PROJECT_DIR$/src/store/modules/user.js" />
<option value="$PROJECT_DIR$/public/css/tool.css" />
<option value="$PROJECT_DIR$/.env.production" />
<option value="$PROJECT_DIR$/src/layout/components/Navbar.vue" />
<option value="$PROJECT_DIR$/src/components/Breadcrumb/index.vue" />
<option value="$PROJECT_DIR$/src/router/index.js" />
<option value="$PROJECT_DIR$/src/views/index.vue" />
<option value="$PROJECT_DIR$/src/views/system/user/index.vue" />
<option value="$PROJECT_DIR$/src/views/system/user/authRole.vue" />
<option value="$PROJECT_DIR$/src/views/system/role/index.vue" />
<option value="$PROJECT_DIR$/src/views/system/menu/index.vue" />
<option value="$PROJECT_DIR$/src/views/system/post/index.vue" />
<option value="$PROJECT_DIR$/src/views/system/dict/index.vue" />
<option value="$PROJECT_DIR$/src/views/system/config/index.vue" />
<option value="$PROJECT_DIR$/src/views/system/notice/index.vue" />
<option value="$PROJECT_DIR$/src/views/monitor/operlog/index.vue" />
<option value="$PROJECT_DIR$/src/views/monitor/logininfor/index.vue" />
<option value="$PROJECT_DIR$/src/views/system/tool/gen/index.vue" />
<option value="$PROJECT_DIR$/src/views/system/dict/data.vue" />
<option value="$PROJECT_DIR$/src/views/system/dept/index.vue" />
<option value="$PROJECT_DIR$/src/views/system/role/authUser.vue" />
<option value="$PROJECT_DIR$/src/views/document/addDocument.vue" />
<option value="$PROJECT_DIR$/src/views/tool/toolDetail.vue" />
<option value="$PROJECT_DIR$/src/views/document/uploadProgress.vue" />
<option value="$PROJECT_DIR$/src/views/document/index.vue" />
<option value="$PROJECT_DIR$/src/views/tool/index.vue" />
<option value="$PROJECT_DIR$/src/views/workstuff/apply/index.vue" />
<option value="$PROJECT_DIR$/src/views/workstuff/dispose/index.vue" />
<option value="$PROJECT_DIR$/src/views/workstuff/message/index.vue" />
<option value="$PROJECT_DIR$/src/views/document/editDocument.vue" />
<option value="$PROJECT_DIR$/.env.development" />
<option value="$PROJECT_DIR$/default.conf" />
<option value="$PROJECT_DIR$/.env.staging" />
</list>
</option>
</component>
<component name="ProjectFrameBounds" extendedState="6">
<option name="x" value="-12" />
<option name="y" value="-12" />
<option name="width" value="2904" />
<option name="height" value="1752" />
</component>
<component name="ProjectView">
<navigator proportions="" version="1">
<foldersAlwaysOnTop value="true" />
</navigator>
<panes>
<pane id="ProjectPane">
<subPane>
<expand>
<path>
<item name="tool-tech-front" type="b2602c69:ProjectViewProjectNode" />
<item name="tool-tech-front" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="tool-tech-front" type="b2602c69:ProjectViewProjectNode" />
<item name="tool-tech-front" type="462c0819:PsiDirectoryNode" />
<item name="public" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="tool-tech-front" type="b2602c69:ProjectViewProjectNode" />
<item name="tool-tech-front" type="462c0819:PsiDirectoryNode" />
<item name="public" type="462c0819:PsiDirectoryNode" />
<item name="images" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="tool-tech-front" type="b2602c69:ProjectViewProjectNode" />
<item name="tool-tech-front" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="tool-tech-front" type="b2602c69:ProjectViewProjectNode" />
<item name="tool-tech-front" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="views" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="tool-tech-front" type="b2602c69:ProjectViewProjectNode" />
<item name="tool-tech-front" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="views" type="462c0819:PsiDirectoryNode" />
<item name="document" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="tool-tech-front" type="b2602c69:ProjectViewProjectNode" />
<item name="tool-tech-front" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="views" type="462c0819:PsiDirectoryNode" />
<item name="tool" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="tool-tech-front" type="b2602c69:ProjectViewProjectNode" />
<item name="tool-tech-front" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="views" type="462c0819:PsiDirectoryNode" />
<item name="workflow" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="tool-tech-front" type="b2602c69:ProjectViewProjectNode" />
<item name="tool-tech-front" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="views" type="462c0819:PsiDirectoryNode" />
<item name="workflow" type="462c0819:PsiDirectoryNode" />
<item name="config" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="tool-tech-front" type="b2602c69:ProjectViewProjectNode" />
<item name="tool-tech-front" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="views" type="462c0819:PsiDirectoryNode" />
<item name="workstuff" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="tool-tech-front" type="b2602c69:ProjectViewProjectNode" />
<item name="tool-tech-front" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="views" type="462c0819:PsiDirectoryNode" />
<item name="workstuff" type="462c0819:PsiDirectoryNode" />
<item name="apply" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="tool-tech-front" type="b2602c69:ProjectViewProjectNode" />
<item name="tool-tech-front" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="views" type="462c0819:PsiDirectoryNode" />
<item name="workstuff" type="462c0819:PsiDirectoryNode" />
<item name="dispose" type="462c0819:PsiDirectoryNode" />
</path>
<path>
<item name="tool-tech-front" type="b2602c69:ProjectViewProjectNode" />
<item name="tool-tech-front" type="462c0819:PsiDirectoryNode" />
<item name="src" type="462c0819:PsiDirectoryNode" />
<item name="views" type="462c0819:PsiDirectoryNode" />
<item name="workstuff" type="462c0819:PsiDirectoryNode" />
<item name="message" type="462c0819:PsiDirectoryNode" />
</path>
</expand>
<select />
</subPane>
</pane>
<pane id="Scope" />
</panes>
</component>
<component name="PropertiesComponent">
<property name="SHARE_PROJECT_CONFIGURATION_FILES" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="editor.config.ad.shown" value="true" />
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
<property name="node.js.detected.package.eslint" value="true" />
<property name="node.js.path.for.package.eslint" value="project" />
<property name="node.js.selected.package.eslint" value="(autodetect)" />
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
<property name="nodejs_npm_path_reset_for_default_project" value="true" />
<property name="nodejs_package_manager_path" value="npm" />
<property name="ts.external.directory.path" value="D:\Program Files\JetBrains\WebStorm 2019.1.1\plugins\JavaScriptLanguage\jsLanguageServicesImpl\external" />
</component>
<component name="RecentsManager">
<key name="MoveFile.RECENT_KEYS">
<recent name="D:\rzdata\ToolTech\tool-tech-front\public" />
<recent name="D:\rzdata\ToolTech\tool-tech-front\public\css" />
<recent name="D:\rzdata\ToolTech\tool-tech-front\src\components" />
<recent name="D:\rzdata\ToolTech\tool-tech-front\src\components\userSelector" />
<recent name="D:\rzdata\ToolTech\tool-tech-front\src\views\workflow\config" />
</key>
<key name="CopyFile.RECENT_KEYS">
<recent name="D:\rzdata\ToolTech\tool-tech-front\src\views\workstuff\message" />
<recent name="D:\rzdata\ToolTech\tool-tech-front\src\views\workstuff\apply" />
<recent name="D:\rzdata\ToolTech\tool-tech-front\src\assets\logo" />
<recent name="D:\rzdata\ToolTech\tool-tech-front\public" />
<recent name="D:\rzdata\ToolTech\tool-tech-front\src\views\tool" />
</key>
</component>
<component name="RunDashboard">
<option name="ruleStates">
<list>
<RuleState>
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
</RuleState>
<RuleState>
<option name="name" value="StatusDashboardGroupingRule" />
</RuleState>
</list>
</option>
</component>
<component name="RunManager">
<configuration name="dev" type="js.build_tools.npm" temporary="true" nameIsGenerated="true">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="dev" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
<recent_temporary>
<list>
<item itemvalue="npm.dev" />
</list>
</recent_temporary>
</component>
<component name="SvnConfiguration">
<configuration />
</component>
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="880b2c9e-bb63-49b5-a9b3-35bf50aa9da8" name="Default Changelist" comment="" />
<created>1720405215626</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1720405215626</updated>
<workItem from="1720405216920" duration="31083000" />
<workItem from="1720607146890" duration="646000" />
<workItem from="1721005856925" duration="23394000" />
<workItem from="1721114973364" duration="3160000" />
<workItem from="1721185818138" duration="662000" />
<workItem from="1721611088644" duration="28182000" />
<workItem from="1721717492928" duration="8889000" />
<workItem from="1721783250517" duration="9602000" />
<workItem from="1721886425310" duration="2104000" />
<workItem from="1721896582395" duration="232000" />
</task>
<task id="LOCAL-00001" summary="update">
<created>1721110878122</created>
<option name="number" value="00001" />
<option name="presentableId" value="LOCAL-00001" />
<option name="project" value="LOCAL" />
<updated>1721110878122</updated>
</task>
<task id="LOCAL-00002" summary="update">
<created>1721118453675</created>
<option name="number" value="00002" />
<option name="presentableId" value="LOCAL-00002" />
<option name="project" value="LOCAL" />
<updated>1721118453676</updated>
</task>
<task id="LOCAL-00003" summary="update">
<created>1721122463517</created>
<option name="number" value="00003" />
<option name="presentableId" value="LOCAL-00003" />
<option name="project" value="LOCAL" />
<updated>1721122463517</updated>
</task>
<task id="LOCAL-00004" summary="update">
<created>1721123161293</created>
<option name="number" value="00004" />
<option name="presentableId" value="LOCAL-00004" />
<option name="project" value="LOCAL" />
<updated>1721123161293</updated>
</task>
<task id="LOCAL-00005" summary="update">
<created>1721632270841</created>
<option name="number" value="00005" />
<option name="presentableId" value="LOCAL-00005" />
<option name="project" value="LOCAL" />
<updated>1721632270841</updated>
</task>
<task id="LOCAL-00006" summary="update">
<created>1721886526500</created>
<option name="number" value="00006" />
<option name="presentableId" value="LOCAL-00006" />
<option name="project" value="LOCAL" />
<updated>1721886526500</updated>
</task>
<task id="LOCAL-00007" summary="update">
<created>1721888702083</created>
<option name="number" value="00007" />
<option name="presentableId" value="LOCAL-00007" />
<option name="project" value="LOCAL" />
<updated>1721888702083</updated>
</task>
<option name="localTasksCounter" value="8" />
<servers />
</component>
<component name="TimeTrackingManager">
<option name="totallyTimeSpent" value="107954000" />
</component>
<component name="TodoView">
<todo-panel id="selected-file">
<is-autoscroll-to-source value="true" />
</todo-panel>
<todo-panel id="all">
<are-packages-shown value="true" />
<is-autoscroll-to-source value="true" />
</todo-panel>
</component>
<component name="ToolWindowManager">
<frame x="-7" y="-7" width="1935" height="1167" extended-state="6" />
<editor active="true" />
<layout>
<window_info active="true" content_ui="combo" id="Project" order="0" sideWeight="0.4925865" visible="true" weight="0.24960506" />
<window_info id="Structure" order="1" side_tool="true" weight="0.25" />
<window_info id="npm" order="2" sideWeight="0.5074135" side_tool="true" weight="0.24960506" />
<window_info id="Favorites" order="3" side_tool="true" />
<window_info anchor="bottom" id="Message" order="0" />
<window_info anchor="bottom" id="Find" order="1" />
<window_info anchor="bottom" id="Run" order="2" weight="0.27439612" />
<window_info anchor="bottom" id="Debug" order="3" weight="0.4" />
<window_info anchor="bottom" id="Cvs" order="4" weight="0.25" />
<window_info anchor="bottom" id="Inspection" order="5" weight="0.4" />
<window_info anchor="bottom" id="TODO" order="6" weight="0.3291506" />
<window_info anchor="bottom" id="Docker" order="7" show_stripe_button="false" />
<window_info anchor="bottom" id="Version Control" order="8" />
<window_info anchor="bottom" id="TypeScript" order="9" />
<window_info anchor="bottom" id="Event Log" order="10" side_tool="true" />
<window_info anchor="bottom" id="Terminal" order="11" weight="0.3291506" />
<window_info anchor="right" id="Commander" internal_type="SLIDING" order="0" type="SLIDING" weight="0.4" />
<window_info anchor="right" id="Ant Build" order="1" weight="0.25" />
<window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" />
</layout>
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="1" />
</component>
<component name="VcsManagerConfiguration">
<MESSAGE value="update" />
<option name="LAST_COMMIT_MESSAGE" value="update" />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/src/views/tool/index2.vue" />
<entry file="file://D:/日常工作文件库/泛联睿展联合项目/工具管理及技术交流平台/昆明军工/原型静态页面/工具管理及技术交流平台/我的申请.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="213">
<caret line="167" column="3" lean-forward="true" selection-start-line="167" selection-start-column="3" selection-end-line="342" selection-end-column="6" />
<folding>
<element signature="n#div#0;n#div#0;n#body#0;n#html#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://D:/日常工作文件库/泛联睿展联合项目/工具管理及技术交流平台/昆明军工/原型静态页面/工具管理及技术交流平台/我的办理.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="211">
<caret line="178" column="4" selection-start-line="178" selection-start-column="4" selection-end-line="551" selection-end-column="5" />
<folding>
<element signature="n#div#0;n#div#0;n#body#0;n#html#0;n#!!top" />
<element signature="e#8535#15422#0" />
</folding>
</state>
</provider>
</entry>
<entry file="file://D:/日常工作文件库/泛联睿展联合项目/工具管理及技术交流平台/昆明军工/原型静态页面/工具管理及技术交流平台/消息中心.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="460">
<caret line="93" column="5" selection-start-line="53" selection-start-column="4" selection-end-line="93" selection-end-column="5" />
<folding>
<element signature="n#div#0;n#div#0;n#body#0;n#html#0;n#!!top" />
<element signature="e#1925#2492#0" />
</folding>
</state>
</provider>
</entry>
<entry file="file://D:/日常工作文件库/泛联睿展联合项目/工具管理及技术交流平台/昆明军工/原型静态页面/工具管理及技术交流平台/文档资源统计.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="228">
<caret line="44" column="30" lean-forward="true" selection-start-line="12" selection-start-column="4" selection-end-line="44" selection-end-column="30" />
<folding>
<element signature="n#div#0;n#div#0;n#body#0;n#html#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://D:/日常工作文件库/泛联睿展联合项目/工具管理及技术交流平台/昆明军工/原型静态页面/工具管理及技术交流平台/工具统计.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="228">
<caret line="44" column="30" lean-forward="true" selection-start-line="12" selection-start-column="4" selection-end-line="44" selection-end-column="30" />
<folding>
<element signature="n#div#0;n#div#0;n#body#0;n#html#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/statistic/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="19">
<caret line="1" column="27" selection-start-line="1" selection-start-column="27" selection-end-line="1" selection-end-column="27" />
<folding>
<element signature="n#div#0;n#el-tab-pane#1;n#el-tabs#0;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/store/getters.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="190">
<caret line="10" column="10" selection-start-line="10" selection-start-column="10" selection-end-line="10" selection-end-column="10" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/store/modules/user.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="190">
<caret line="70" column="47" selection-start-line="70" selection-start-column="47" selection-end-line="70" selection-end-column="47" />
<folding>
<element signature="e#0#52#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/layout/components/Sidebar/Logo.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="152">
<caret line="8" column="60" lean-forward="true" selection-start-line="8" selection-start-column="60" selection-end-line="8" selection-end-column="60" />
<folding>
<element signature="e#930#974#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/layout/components/Navbar.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="266">
<caret line="14" selection-start-line="14" selection-end-line="14" />
<folding>
<element signature="n#style#0;n#span#0;n#div#0;n#el-dropdown#0;n#div#0;n#div#0;n#template#0;n#!!top" expanded="true" />
<element signature="e#1293#1326#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/login.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="95">
<caret line="5" column="46" selection-start-line="5" selection-start-column="46" selection-end-line="5" selection-end-column="46" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/components/Breadcrumb/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="205">
<caret line="36" column="8" selection-start-line="36" selection-start-column="6" selection-end-line="38" selection-end-column="9" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/router/index.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="395">
<caret line="72" column="63" selection-start-line="71" selection-start-column="8" selection-end-line="72" selection-end-column="63" />
<folding>
<element signature="e#0#21#0" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="537">
<caret line="63" column="13" selection-start-line="63" selection-start-column="13" selection-end-line="63" selection-end-column="13" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/system/user/authRole.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="347">
<caret line="40" column="37" lean-forward="true" selection-start-line="40" selection-start-column="37" selection-end-line="40" selection-end-column="37" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/monitor/job/index.vue">
<provider selected="true" editor-type-id="text-editor" />
</entry>
<entry file="file://D:/日常工作文件库/泛联睿展联合项目/工具管理及技术交流平台/昆明军工/原型静态页面/工具管理及技术交流平台/用户管理.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="266">
<caret line="14" column="30" lean-forward="true" selection-start-line="14" selection-start-column="8" selection-end-line="14" selection-end-column="30" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/system/post/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="423">
<caret line="64" column="17" lean-forward="true" selection-start-line="64" selection-start-column="17" selection-end-line="64" selection-end-column="17" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/system/config/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="95">
<caret line="85" column="17" lean-forward="true" selection-start-line="85" selection-start-column="17" selection-end-line="85" selection-end-column="17" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/system/menu/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="133">
<caret line="30" column="29" lean-forward="true" selection-start-line="28" selection-start-column="4" selection-end-line="30" selection-end-column="29" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
<element signature="n#el-table#0;n#div#0;n#el-card#1;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/system/notice/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="494">
<caret line="57" column="17" lean-forward="true" selection-start-line="57" selection-start-column="17" selection-end-line="57" selection-end-column="17" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/monitor/operlog/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="119">
<caret line="82" column="29" lean-forward="true" selection-start-line="80" selection-start-column="4" selection-end-line="82" selection-end-column="29" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
<element signature="n#el-table#0;n#div#0;n#el-card#1;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/system/tool/gen/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="38">
<caret line="2" column="4" selection-start-line="2" selection-start-column="4" selection-end-line="2" selection-end-column="13" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/system/dict/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="152">
<caret line="57" column="29" lean-forward="true" selection-start-line="55" selection-start-column="4" selection-end-line="57" selection-end-column="29" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/system/dict/data.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="133">
<caret line="67" column="17" lean-forward="true" selection-start-line="67" selection-start-column="17" selection-end-line="67" selection-end-column="17" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
<element signature="n#el-table#0;n#div#0;n#el-card#1;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/system/dept/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="266">
<caret line="55" column="55" selection-start-line="55" selection-start-column="55" selection-end-line="55" selection-end-column="55" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/system/role/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="95">
<caret line="54" column="4" selection-start-line="54" selection-start-column="4" selection-end-line="56" selection-end-column="29" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/system/role/authUser.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="423">
<caret line="53" column="25" selection-start-line="53" selection-start-column="25" selection-end-line="53" selection-end-column="25" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
<element signature="n#el-table#0;n#div#0;n#el-card#1;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://D:/日常工作文件库/泛联睿展联合项目/工具管理及技术交流平台/昆明军工/原型静态页面/工具管理及技术交流平台/文档资源管理.html">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="195">
<caret line="85" selection-start-line="85" selection-end-line="143" />
<folding>
<element signature="n#style#0;n#el-table#0;n#div#1;n#el-card#0;n#div#0;n#div#0;n#body#0;n#html#0;n#!!top" expanded="true" />
<element signature="n#el-drawer#0;n#div#0;n#div#0;n#body#0;n#html#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/api/document/document.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="551">
<caret line="29" column="38" selection-start-line="29" selection-start-column="38" selection-end-line="29" selection-end-column="38" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/components/user-selector/src/user-selector.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="3040">
<caret line="164" column="6" selection-start-line="164" selection-start-column="6" selection-end-line="167" selection-end-column="8" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/public/css/tool.css">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="12996">
<caret line="684" column="37" selection-start-line="684" selection-start-column="31" selection-end-line="684" selection-end-column="37" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/public/css/poctstyle.css">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="114">
<caret line="6" column="14" selection-start-line="6" selection-start-column="14" selection-end-line="6" selection-end-column="14" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/monitor/logininfor/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="152">
<caret line="58" column="29" lean-forward="true" selection-start-line="58" selection-start-column="29" selection-end-line="58" selection-end-column="29" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
<element signature="n#el-table#0;n#div#0;n#el-card#1;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/system/user/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="3610">
<caret line="287" column="12" lean-forward="true" selection-start-line="284" selection-start-column="6" selection-end-line="287" selection-end-column="12" />
<folding>
<element signature="n#el-form#0;n#el-dialog#0;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/document/uploadProgress.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="722">
<caret line="38" column="32" selection-start-line="38" selection-start-column="10" selection-end-line="38" selection-end-column="32" />
<folding>
<element signature="n#style#0;n#el-button#0;n#div#0;n#el-card#0;n#div#0;n#div#0;n#template#0;n#!!top" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/document/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="1311">
<caret line="69" column="40" selection-start-line="69" selection-start-column="22" selection-end-line="69" selection-end-column="40" />
<folding>
<element signature="n#pagination#0;n#div#1;n#el-card#1;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/workstuff/apply/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="646">
<caret line="34" column="38" selection-start-line="34" selection-start-column="26" selection-end-line="34" selection-end-column="38" />
<folding>
<element signature="n#style#0;n#el-table#0;n#el-card#1;n#div#0;n#template#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#img#0;n#el-drawer#1;n#div#0;n#template#0;n#!!top" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/main.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="114">
<caret line="6" column="18" selection-start-line="6" selection-start-column="12" selection-end-line="6" selection-end-column="18" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/workstuff/dispose/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="6099">
<caret line="321" column="10" selection-start-line="298" selection-start-column="8" selection-end-line="321" selection-end-column="10" />
<folding>
<element signature="n#style#0;n#img#0;n#el-drawer#1;n#div#0;n#template#0;n#!!top" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/workstuff/message/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="722">
<caret line="38" column="4" selection-start-line="38" selection-start-column="4" selection-end-line="45" selection-end-column="40" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/tool/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2356">
<caret line="177" column="132" selection-start-line="177" selection-start-column="96" selection-end-line="177" selection-end-column="132" />
<folding>
<element signature="n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" />
<element signature="n#style#0;n#el-select#0;n#el-form-item#2;n#div#0;n#div#0;n#div#0;n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#el-date-picker#0;n#el-form-item#3;n#div#0;n#div#0;n#div#0;n#el-form#0;n#el-card#0;n#div#0;n#template#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#el-input#0;n#div#0;n#el-card#1;n#div#0;n#template#0;n#!!top" expanded="true" />
<element signature="n#style#0;n#el-select#0;n#el-form-item#0;n#el-col#0;n#el-row#3;n#el-form#0;n#div#0;n#el-drawer#0;n#div#0;n#template#0;n#!!top" expanded="true" />
<element signature="n#el-drawer#2;n#div#0;n#template#0;n#!!top" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/tool/toolDetail.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2451">
<caret line="129" column="50" selection-start-line="129" selection-start-column="50" selection-end-line="129" selection-end-column="50" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/plugins/modal.js">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="266">
<caret line="14" column="2" selection-start-line="14" selection-start-column="2" selection-end-line="14" selection-end-column="2" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/document/editDocument.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="2603">
<caret line="139" column="12" lean-forward="true" selection-start-line="139" selection-start-column="12" selection-end-line="139" selection-end-column="12" />
<folding>
<element signature="n#style#0;n#el-table#0;n#div#0;n#el-dialog#0;n#div#0;n#template#0;n#!!top" expanded="true" />
</folding>
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/.env.development">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="228">
<caret line="12" selection-start-line="12" selection-end-line="16" selection-end-column="75" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/.env.production">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="19">
<caret line="1" column="27" selection-start-line="1" selection-start-column="27" selection-end-line="1" selection-end-column="27" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/src/views/workflow/config/index.vue">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="247">
<caret line="13" column="103" selection-start-line="13" selection-start-column="72" selection-end-line="13" selection-end-column="103" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/default.conf">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="475">
<caret line="25" column="36" lean-forward="true" selection-start-line="25" selection-start-column="36" selection-end-line="25" selection-end-column="36" />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/.env.staging">
<provider selected="true" editor-type-id="text-editor">
<state relative-caret-position="342">
<caret line="18" column="31" selection-start-line="18" selection-start-column="31" selection-end-line="18" selection-end-column="31" />
</state>
</provider>
</entry>
</component>
</project>

View File

@ -15,20 +15,28 @@ server {
}
}
location /ebpm-process-manage/ {
proxy_pass http://192.168.1.2:8080/ebpm-process-manage/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
location ^~/tool-tech-admin/ {
proxy_pass http://124.223.108.21:8080/tool-tech-admin/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_ssl_verify off;
}
location /tool-tech-file-view/ {
proxy_pass http://192.168.1.2:8012/tool-tech-file-view/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
location ^~/tool-tech-file-view/ {
proxy_pass http://124.223.108.21:8012/tool-tech-file-view/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_ssl_verify off;
}
location ^~/ebpm-process-manage/ {
proxy_pass http://124.223.108.21:9080/ebpm-process-manage/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_ssl_verify off;
}
error_page 500 502 503 504 /50x.html;

View File

@ -32,30 +32,40 @@
],
"dependencies": {
"@riophae/vue-treeselect": "0.4.0",
"@vue-office/docx": "1.6.1",
"@vue-office/pdf": "1.6.5",
"axios": "0.24.0",
"clipboard": "2.0.8",
"core-js": "3.37.1",
"docxtemplater": "3.50.0",
"docxtemplater-image-module-free": "1.1.1",
"echarts": "5.4.0",
"element-ui": "2.15.14",
"file-save": "0.2.0",
"file-saver": "2.0.5",
"fuse.js": "6.4.3",
"highlight.js": "9.18.5",
"js-base64": "^3.7.7",
"js-cookie": "3.0.1",
"jsencrypt": "3.0.0-rc.1",
"jszip": "3.10.1",
"jszip-utils": "0.1.0",
"nprogress": "0.2.0",
"pizzip": "3.1.7",
"quill": "1.3.7",
"screenfull": "5.0.2",
"sockjs-client": "^1.6.1",
"sortablejs": "1.10.2",
"v-viewer": "1.6.4",
"vue": "2.6.12",
"vue-count-to": "1.0.13",
"vue-cropper": "0.5.5",
"vue-demi": "^0.14.10",
"vue-iframe": "0.0.0",
"vue-json-viewer": "2.2.22",
"vue-meta": "2.4.0",
"vue-router": "3.4.9",
"vuex": "3.6.0",
"websocket": "^1.0.35"
"vue-video-player": "5.0.1",
"vuex": "3.6.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "4.4.6",
@ -74,6 +84,7 @@
"sass-loader": "10.1.1",
"script-ext-html-webpack-plugin": "2.1.5",
"svg-sprite-loader": "5.1.1",
"@vue/composition-api": "1.7.2",
"vue-template-compiler": "2.6.12"
},
"engines": {

View File

@ -75,7 +75,7 @@ body #app .hideSidebar .sidebar-container {
width: 65px !important;
}
body #app .openSidebar .sidebar-container {
width:180px !important;
width:220px !important;
}
body #app .sidebar-container .nest-menu .el-sub-menu>.el-sub-menu__title,
body #app .sidebar-container .el-sub-menu .el-menu-item {
@ -344,7 +344,7 @@ body #app .hideSidebar .main-container {
margin-left: 65px;
}
body #app .main-container {
margin-left: 180px;
margin-left: 220px;
background:#f9fafe;
background-size:100%;
}
@ -440,6 +440,34 @@ body #app .main-container .navbar .right-menu{
float: inherit;
top: 8px;
right: 16px;
display: flex;
align-items: center;
}
body #app .main-container .navbar .right-menu .el-badge{
margin: 0 20px 0 0;
}
body #app .main-container .navbar .right-menu .el-badge .el-badge__content.is-fixed{
top: 5px;
right: 14px;
border: 0;
padding: 0 4px;
min-width: 18px;
text-align: center;
}
body #app .main-container .navbar .right-menu .el-badge .top-msg{
background: rgba(0 64 152 / 6%);
color: #004098;
font-size: 14px;
height: 36px;
display: block;
padding: 0 12px;
line-height: 36px;
border-radius: 2px;
cursor: pointer;
}
body #app .main-container .navbar .right-menu .top-version{
margin: 0 10px 0 0;
font-size: 14px;
}
body #app .main-container .navbar .right-menu>.el-select{
margin-right: 15px;
@ -876,7 +904,6 @@ body .el-form-border .el-form-item .el-cascader ,
body .el-form-border .el-form-item .el-select,
body .el-form-border .el-form-item .el-date-editor{
width: 100%;
max-width: 340px;
}
body .el-form-border .el-form-item .el-checkbox-group .el-checkbox{
min-width: 200px;
@ -1068,6 +1095,59 @@ body .el-drawer .el-drawer__body{
margin: 0;
padding-top: 0;
}
body .el-drawer .el-drawer__body .drawer-head{
display: flex;
padding: 10px 32px 10px 32px;
border-bottom: 1px solid rgba(0 0 0 / 5%);
margin: -16px -32px 0 -32px;
position: sticky;
top: -16px;
z-index: 2;
background: #fff;
}
body .el-drawer .el-drawer__body .drawer-head .cell-title{
display: block;
flex: 1;
color: #141414;
font-size: 18px;
font-weight: 500;
}
body .el-drawer .el-drawer__body .drawer-head .cell-title .title{
display: block;
color: #141414;
font-size: 18px;
font-weight: 500;
line-height: 34px;
}
body .el-drawer .el-drawer__body .drawer-head .cell-btn{
display: block;
}
body .iframe-drawer{
background: #fff;
}
body .iframe-drawer .drawer-head{
display: flex;
padding: 0 0 10px 0;
border-bottom: 1px solid rgba(0 0 0 / 5%);
position: sticky;
top: 0;
z-index: 2;
background: #fff;
}
body .iframe-drawer .drawer-head .cell-title{
display: block;
flex: 1;
color: #141414;
font-size: 18px;
font-weight: 500;
}
body .iframe-drawer .drawer-head .cell-title .title{
display: block;
color: #141414;
font-size: 18px;
font-weight: 500;
line-height: 34px;
}
/*pagination-container 分页*/
body .apparatus-card>.el-card__body .el-card.gray-card+.pagination-container{
@ -1437,13 +1517,17 @@ body .el-radio-button__inner:hover {
}
/*el-upload 上传按钮组件*/
body .el-upload+.el-button,
body .el-button+.el-upload{
margin-left: 10px;
}
body .el-upload,
body .registerbox .avatar-uploader .el-upload{
background:#fff;
border:1px solid #004098;
color:#004098 !important;
border-radius: 2px;
height: 36px;
height: 34px;
}
body .el-upload:hover,
body .registerbox .avatar-uploader .el-upload:hover{
@ -1464,6 +1548,8 @@ body .el-upload:hover .el-upload-dragger i{
}
body .el-upload .el-button,
body .el-upload .el-button:hover{
height: 32px;
line-height: 30px;
border: none !important;
background: transparent !important;
}
@ -1694,22 +1780,26 @@ body .el-card>.el-card__body .el-tabs--border-card{
body .el-card>.el-card__body .search-btn .el-tabs--border-card{
border: 0;
}
body .el-card>.el-card__body .search-btn .el-tabs--border-card>.el-tabs__header{
body .el-card>.el-card__body .search-btn .el-tabs--border-card>.el-tabs__header,
body .el-card>.el-card__body .search-btn .el-tabs--card>.el-tabs__header{
border-bottom: 1px solid #e6e6e6;
background: transparent;
}
body .el-card>.el-card__body .search-btn .el-tabs--border-card>.el-tabs__header .el-tabs__item{
body .el-card>.el-card__body .search-btn .el-tabs--border-card>.el-tabs__header .el-tabs__item,
body .el-card>.el-card__body .search-btn .el-tabs--card>.el-tabs__header .el-tabs__item{
margin: 0;
border: none;
}
body .el-card>.el-card__body .search-btn .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active{
body .el-card>.el-card__body .search-btn .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active,
body .el-card>.el-card__body .search-btn .el-tabs--card>.el-tabs__header .el-tabs__item.is-active{
border: 0;
background: transparent;
color: #034aac;
font-weight: bold;
position: relative;
}
body .el-card>.el-card__body .search-btn .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active::after{
body .el-card>.el-card__body .search-btn .el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active::after,
body .el-card>.el-card__body .search-btn .el-tabs--card>.el-tabs__header .el-tabs__item.is-active::after{
position: absolute;
left: 0;
bottom: 0;
@ -2022,7 +2112,7 @@ body .etable1.el-table .el-table__expanded-cell tr>td:nth-child(2){
.search .el-form-item>.el-form-item__content>.el-cascader,
.search .el-form-item>.el-form-item__content>.el-date-editor.el-range-editor,
.search .el-form-item>.el-form-item__content>.el-date-editor.el-date-editor{
width: 250px;
width: 230px;
}
.grab .filtrate{
display: none;
@ -2051,7 +2141,7 @@ body .etable1.el-table .el-table__expanded-cell tr>td:nth-child(2){
.filtrate .el-form-item>.el-form-item__content>.el-cascader,
.filtrate .el-form-item>.el-form-item__content>.el-date-editor.el-range-editor,
.filtrate .el-form-item>.el-form-item__content>.el-date-editor.el-date-editor{
width: 250px;
width: 230px;
}
/*operate 操作区域*/
@ -2072,7 +2162,7 @@ body .el-card.lrtt>.el-card__body{
.lrtt .lt{
display: block;
padding: 16px;
width: 310px;
width: 250px;
height: 700px;
overflow: auto;
}
@ -2494,7 +2584,11 @@ body .login-page .loright .locont .el-form--label-top .el-form-item .el-form-ite
.fbox1 .fr{
display: block;
padding: 16px 32px;
width: 420px;
}
body .el-drawer .el-drawer__body .fbox1 .fl,
body .el-drawer .el-drawer__body .fbox1 .fr{
height: calc(100vh - 57px);
overflow: auto;
}
/*pltextarea 评论框*/

19
public/document.docx Normal file
View File

@ -0,0 +1,19 @@
{#list}
{resName}
文档编号
{docCode}
文档名称
{docName}
文档类别
{docTypeName}
负责人
{docPrincipals}
归属单位
{docRespDeptName}
文档来源
{docSourceName}
文档状态
{statusName}
创建时间
{createTime}
{/list}

View File

@ -197,12 +197,12 @@
</head>
<body>
<div id="app">
<div id="loader-wrapper">
<!-- <div id="loader-wrapper">
<div id="loader"></div>
<div class="loader-section section-left"></div>
<div class="loader-section section-right"></div>
<div class="load_title">正在加载系统资源,请耐心等待</div>
</div>
</div>-->
</div>
</body>
</html>

19
public/tool.docx Normal file
View File

@ -0,0 +1,19 @@
{#list}
{resName}
工具名称
{toolName}
工具类别
{toolTypeName}
工具来源
{toolSourceName}
负责人
{toolPrincipalsName}
归属单位
{toolRespDeptName}
状态
{statusName}
流程状态
{recordStatusName}
创建时间
{createTime}
{/list}

View File

@ -7,6 +7,9 @@
<script>
import ThemePicker from "@/components/ThemePicker";
import store from '@/store'
import { Message } from 'element-ui'
import { getToken } from '@/utils/auth'
export default {
name: "App",
@ -18,6 +21,14 @@ export default {
return title ? `${title} - ${process.env.VUE_APP_TITLE}` : process.env.VUE_APP_TITLE
}
}
},
created() {
if (getToken()) {
store.dispatch('GetUserMsgCount').then(() => { })
}
},
methods:{
}
};
</script>

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询附件列表
export function listAttachment(query) {
return request({
url: '/system/attachment/list',
method: 'get',
params: query
})
}
// 查询附件详细
export function getAttachment(id) {
return request({
url: '/system/attachment/' + id,
method: 'get'
})
}
// 新增附件
export function addAttachment(data) {
return request({
url: '/system/attachment',
method: 'post',
data: data
})
}
// 修改附件
export function updateAttachment(data) {
return request({
url: '/system/attachment',
method: 'put',
data: data
})
}
// 删除附件
export function delAttachment(id) {
return request({
url: '/system/attachment/' + id,
method: 'delete'
})
}

View File

@ -42,3 +42,33 @@ export function delDocument(id) {
method: 'delete'
})
}
// 发布文档
export function pushDoc(id) {
return request({
url: '/document/pushDoc/' + id,
method: 'put'
})
}
// 获取统计信息
export function getStatistics(query) {
return request({
url: '/document/statistics',
method: 'get',
params: query
})
}
// 查询【请填写功能名称】列表
export function getExportWordList(query) {
return request({
url: '/document/export/word/list',
method: 'post',
data: query
})
}

View File

@ -0,0 +1,55 @@
import request from '@/utils/request'
// 查询文档资源分类管理列表
export function listCategory(query) {
return request({
url: '/system/category/list',
method: 'get',
params: query
})
}
// 查询文档资源分类管理详细
export function getCategory(id) {
return request({
url: '/system/category/' + id,
method: 'get'
})
}
// 新增文档资源分类管理
export function addCategory(data) {
return request({
url: '/system/category',
method: 'post',
data: data
})
}
// 修改文档资源分类管理
export function updateCategory(data) {
return request({
url: '/system/category',
method: 'put',
data: data
})
}
// 删除文档资源分类管理
export function delCategory(id) {
return request({
url: '/system/category/' + id,
method: 'delete'
})
}
// 获取文档分类树列表
export function documentTree(query) {
return request({
url: '/system/category/documentTree',
method: 'get',
params: query
})
}

View File

@ -1,45 +1,63 @@
import request from '@/utils/request'
/**
* 查询消息列表
* @returns
*/
export function getMessageList(params) {
return Promise.resolve({
total: 5,
rows: [
{ id: 1, msgContent: '测试1111', msgRecTime: '2024-08-05 12:31:59', msgStatus: 'unread' },
{ id: 2, msgContent: '测试2222', msgRecTime: '2024-08-05 13:32:01', msgStatus: 'readed' },
{ id: 3, msgContent: '测试333', msgRecTime: '2024-08-05 14:09:07', msgStatus: 'unread' },
{ id: 4, msgContent: '测试4444', msgRecTime: '2024-08-05 15:37:10', msgStatus: 'readed' },
{ id: 5, msgContent: '测试5555', msgRecTime: '2024-08-05 17:29:39', msgStatus: 'unread' }
],
code: 200,
msg: '操作成功'
// 查询消息列表
export function listMessage(query) {
return request({
url: '/system/message/list',
method: 'get',
params: query
})
}
/**
* 标记所有已读
* @returns
*/
export function markAllRead() {
return Promise.resolve({
result: {},
code: 200,
msg: '操作成功'
// 查询消息详细
export function getMessage(id) {
return request({
url: '/system/message/' + id,
method: 'get'
})
}
/**
* 根据id标记单个已读
* @returns
*/
export function markReadById(id) {
return Promise.resolve({
result: {},
code: 200,
msg: '操作成功'
// 新增消息
export function addMessage(data) {
return request({
url: '/system/message',
method: 'post',
data: data
})
}
// 修改消息
export function updateMessage(data) {
return request({
url: '/system/message',
method: 'put',
data: data
})
}
// 删除消息
export function delMessage(id) {
return request({
url: '/system/message/' + id,
method: 'delete'
})
}
// 全部标记已读
export function allMarkedRead(data) {
return request({
url: '/system/message/allMarkedRead',
method: 'post',
data: data
})
}
// 获取用户统计
export function getUserMsgCount(id) {
return request({
url: '/system/message/user/msg/count/' + id,
method: 'get'
})
}

View File

@ -0,0 +1,195 @@
import request from '@/utils/request'
// 审批记录
export function workflowGetLog(data) {
return request({
url: '/workflow/getLog',
method: 'post',
data: data
})
}
//流程实例撤回到拟稿人环节
export function workflowbacktostart(data) {
return request({
url: '/workflow/backtostart',
method: 'post',
data: data,
timeout: 30*60*1000
})
}
// 获取流程环节定义信息
export function activitydefinition(procDefId, actDefId) {
return request({
url: '/workflow/activitydefinition/' + procDefId + '/' + actDefId,
method: 'get',
})
}
// 查询列表
export function workflowToDoList(data) {
return request({
url: '/workflow/toDoList',
method: 'post',
data: data
})
}
// 新建流程,获取下一环节流程定义信息
export function workflowNextactsNew(data) {
return request({
url: '/workflow/nextacts/new',
method: 'post',
data: data
})
}
// 新建流程,获取下一环节流程定义信息
// 获取下一环节集合,并可以标识已办和自动将未办理环节优先排序
export function workflowNextactsNew2(data) {
return request({
url: '/workflow/nextacts/new2',
method: 'post',
data: data
})
}
// 查询流程审批记录列表
export function processWorkflowGetList(businessId) {
return request({
url: '/process/workflowLog/list' + '?pageNum=1&pageSize=100&businessId=' + businessId,
method: 'get',
})
}
export function getNextactuserByPending(query) {
return request({
url: '/workflow/nextactuser/pending',
method: 'get',
params: query
})
}
export function getNextActUsersByNew(query) {
return request({
url: '/workflow/nextactuser/new',
method: 'get',
params: query
})
}
export function workflowSubmit(data) {
return request({
url: '/workflow/submit',
method: 'post',
data: data
})
}
export function workflowCancel(data) {
return request({
url: '/workflow/cancel',
method: 'post',
data: data
})
}
export function workflowReject(data) {
return request({
url: '/workflow/reject',
method: 'post',
data: data
})
}
export function workflowBacktoprev(data) {
return request({
url: '/workflow/backtoprev',
method: 'post',
data: data
})
}
export function getHistAskLogUrl(procInstId) {
return request({
url: '/workflow/histasklogurl/' + procInstId,
method: 'get',
})
}
export function getExtAttributeModel(procDefId, actDefId) {
return request({
url: '/workflow/getExtAttributeModel/?procDefId=' + procDefId + "&actDefId=" + actDefId,
method: 'get',
})
}
export function selectLogByBusinessId(query) {
return request({
url: '/process/workflowLog/selectLogByBusinessId?businessId' + query,
method: 'get',
})
}
export function workflowprocesskey(query) {
return request({
url: '/workflow/process/key/' + query,
method: 'get',
})
}
export function getStartActdef(procDefId) {
return request({
url: '/workflow/startactdef/' + procDefId,
method: 'get',
})
}
// 根据流程实例id获取流程实例信息和流程状态
export function procInstInfoAndStatus(procInstId) {
return request({
url: '/workflow/procInstInfoAndStatus/' + procInstId,
method: 'get',
})
}
// 根据流程实例id获取流程实例信息
export function getProcInstInfo(procInstId) {
return request({
url: '/workflow/procInstInfo/' + procInstId,
method: 'get',
})
}
export function selectLogByProcInstId(query) {
return request({
url: '/web/log/list',
method: 'get',
params: query
})
}
// 获取流程待选人员展示方式
export function selectUserStyle() {
return request({
url: '/workflow/selectUserStyle',
method: 'get',
})
}
// 根据流程实例id获取流程实例信息
export function getRecordbyPorcInstId(procInstId) {
return request({
url: '/workflow/getRecord/' + procInstId,
method: 'get',
})
}
export function getUserMsgCount() {
return request({
url: '/workflow/msg/count/',
method: 'get',
})
}

View File

@ -9,6 +9,15 @@ export function listType(query) {
})
}
// 查询业务字典类型列表(扩展)
export function bizListType(query) {
return request({
url: '/system/dict/type/bizlist',
method: 'get',
params: query
})
}
// 查询字典类型详细
export function getType(dictId) {
return request({

View File

@ -127,10 +127,11 @@ export function updateAuthRole(data) {
}
// 查询部门下拉树结构
export function deptTreeSelect() {
export function deptTreeSelect(query) {
return request({
url: '/system/user/deptTree',
method: 'get'
method: 'get',
params: query
})
}

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询讨论列表
export function listDiscussions(query) {
return request({
url: '/discussions/list',
method: 'get',
params: query
})
}
// 查询讨论详细
export function getDiscussions(id) {
return request({
url: '/discussions/' + id,
method: 'get'
})
}
// 新增讨论
export function addDiscussions(data) {
return request({
url: '/discussions',
method: 'post',
data: data
})
}
// 修改讨论
export function updateDiscussions(data) {
return request({
url: '/discussions',
method: 'put',
data: data
})
}
// 删除讨论
export function delDiscussions(id) {
return request({
url: '/discussions/' + id,
method: 'delete'
})
}

View File

@ -0,0 +1,65 @@
import request from '@/utils/request'
// 查询工具下载统计列表
export function listCount(query) {
return request({
url: '/system/count/list',
method: 'get',
params: query
})
}
// 查询工具下载统计列表
export function listDocCount(query) {
return request({
url: '/system/count/doc/list',
method: 'get',
params: query
})
}
// 根据详情统计
export function userDownList(query) {
return request({
url: '/system/count/user/down/list',
method: 'get',
params: query
})
}
// 查询工具下载统计详细
export function getCount(id) {
return request({
url: '/system/count/' + id,
method: 'get'
})
}
// 新增工具下载统计
export function addCount(data) {
return request({
url: '/system/count',
method: 'post',
data: data
})
}
// 修改工具下载统计
export function updateCount(data) {
return request({
url: '/system/count',
method: 'put',
data: data
})
}
// 删除工具下载统计
export function delCount(id) {
return request({
url: '/system/count/' + id,
method: 'delete'
})
}

44
src/api/tool/replies.js Normal file
View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询回复列表
export function listReplies(query) {
return request({
url: '/system/replies/list',
method: 'get',
params: query
})
}
// 查询回复详细
export function getReplies(id) {
return request({
url: '/replies/' + id,
method: 'get'
})
}
// 新增回复
export function addReplies(data) {
return request({
url: '/replies',
method: 'post',
data: data
})
}
// 修改回复
export function updateReplies(data) {
return request({
url: '/replies',
method: 'put',
data: data
})
}
// 删除回复
export function delReplies(id) {
return request({
url: '/replies/' + id,
method: 'delete'
})
}

View File

@ -17,20 +17,29 @@ export function getTool(toolId) {
})
}
export function getInfoByBpmcId(bpmcId) {
return request({
url: '/tool/bpmc/' + bpmcId,
method: 'get'
})
}
// 新增工具信息
export function addTool(data) {
return request({
url: '/tool',
method: 'post',
data: data
data: data,
timeout: 30*60*1000
})
}
// 修改工具信息
export function updateTool(data) {
return request({
url: '/tool',
method: 'put',
url: '/tool/edit',
method: 'post',
data: data
})
}
@ -42,3 +51,30 @@ export function delTool(toolId) {
method: 'delete'
})
}
export function checkToolExist(params) {
return request({
url: '/tool/checkToolExist',
method: 'get',
params: params
})
}
// 获取统计信息
export function getStatistics(query) {
return request({
url: '/tool/statistics',
method: 'get',
params: query
})
}
// get导出word字段
export function exportWordList(query) {
return request({
url: '/tool/export/word/list',
method: 'post',
data: query
})
}

51
src/api/tool/toolApply.js Normal file
View File

@ -0,0 +1,51 @@
import request from '@/utils/request'
// 查询使用申请列表
export function listApply(query) {
return request({
url: '/tool/apply/list',
method: 'get',
params: query
})
}
// 查询使用申请详细
export function getApply(id) {
return request({
url: '/tool/apply/' + id,
method: 'get'
})
}
export function getInfoByBpmcId(bpmcId) {
return request({
url: '/tool/apply/bpmc/' + bpmcId,
method: 'get'
})
}
// 新增使用申请
export function addApply(data) {
return request({
url: '/tool/apply',
method: 'post',
data: data
})
}
// 修改使用申请
export function updateApply(data) {
return request({
url: '/tool/apply/edit',
method: 'post',
data: data
})
}
// 删除使用申请
export function delApply(id) {
return request({
url: '/tool/apply/' + id,
method: 'delete'
})
}

View File

@ -0,0 +1,53 @@
import request from '@/utils/request'
// 查询tool_relation列表
export function listRelation(query) {
return request({
url: '/system/relation/list',
method: 'get',
params: query
})
}
// 查询tool_relation详细
export function getRelation(id) {
return request({
url: '/system/relation/' + id,
method: 'get'
})
}
// 新增tool_relation
export function addRelation(data) {
return request({
url: '/system/relation',
method: 'post',
data: data
})
}
// 修改tool_relation
export function updateRelation(data) {
return request({
url: '/system/relation',
method: 'put',
data: data
})
}
// 删除tool_relation
export function delRelation(id) {
return request({
url: '/system/relation/' + id,
method: 'delete'
})
}
// 获取关联树列表
export function getDataThree(data) {
return request({
url: '/system/relation/get/three',
method: 'post',
data: data
})
}

View File

@ -0,0 +1,44 @@
import request from '@/utils/request'
// 查询使用申请详情列表
export function listItem(query) {
return request({
url: '/use/apply/item/list',
method: 'get',
params: query
})
}
// 查询使用申请详情详细
export function getItem(id) {
return request({
url: '/use/apply/item/' + id,
method: 'get'
})
}
// 新增使用申请详情
export function addItem(data) {
return request({
url: '/use/apply/item',
method: 'post',
data: data
})
}
// 修改使用申请详情
export function updateItem(data) {
return request({
url: '/use/apply/item',
method: 'put',
data: data
})
}
// 删除使用申请详情
export function delItem(id) {
return request({
url: '/use/apply/item/' + id,
method: 'delete'
})
}

View File

@ -25,7 +25,7 @@
<el-form-item>
<el-radio v-model='radioValue' :label="4">
指定
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple style="width:100%">
<el-select clearable v-model="checkboxList" placeholder="可多选" multiple ·>
<el-option v-for="item in 24" :key="item" :value="item-1">{{item-1}}</el-option>
</el-select>
</el-radio>

View File

@ -0,0 +1,107 @@
<template>
<div>
<el-drawer
:wrapperClosable="false"
:visible.sync="visible"
:append-to-body="true"
direction="rtl"
size="80%"
:with-header="false"
:show-close="false"
modal-append-to-body
:destroy-on-close="true"
>
<div style="width:100%; height:100%;overflow: hidden">
<iframe :src="src" width="100%" name="dmsDrawer" height="100%" title="myFrame" style="border: 0"></iframe>
</div>
</el-drawer>
<el-drawer
:visible.sync="drawerShow"
direction="rtl"
size="80%"
:append-to-body="true"
:with-header="false"
:wrapperClosable="false"
:show-close="false"
modal-append-to-body
:destroy-on-close="true"
>
<main-component ref="mainComponent" :code="path" :data="data" @close="handleCodeCloseChange"></main-component>
</el-drawer>
</div>
</template>
<script>
/*
流程处理抽屉组件
*/
import MainComponent from '@/components/mainComponent/index.vue'
export default {
name: 'DealDrawer',
components: { MainComponent },
data() {
return {
workflowMessageCbAdded: false,
visible: false,
drawerShow: false,
data: undefined,
path: '',
src: ''
}
},
activated() {
this.setupMessageListener()
},
created() {
this.setupMessageListener()
},
deactivated() {
this.removeMessageListener()
},
beforeDestroy() {
this.removeMessageListener()
},
methods: {
//addEventListener
setupMessageListener() {
if (!this.workflowMessageCbAdded) {
window.addEventListener('message', this.handleMsg)
this.workflowMessageCbAdded = true
}
},
//addEventListener
removeMessageListener() {
window.removeEventListener('message', this.handleMsg)
this.workflowMessageCbAdded = false
},
handleMsg(event) {
let _this = this
let data = event.data
if (data.type === 'close') {
_this.visible = false
if (data.msgType) {
_this.$modal[data.msgType](data.msg)
}
_this.$emit('closeDrawer')
}else if(data.type === 'pdfPreview'){
this.pdfPreview(data.pdfId)
}
},
pdfPreview(pdfId){
this.path = 'views/components/pdfPreview/index'
this.data = pdfId
this.drawerShow = true
},
init(url) {
let _this = this
_this.visible = true
// iframeURL
_this.src = url
},
handleCodeCloseChange() {
this.drawerShow = false
},
}
}
</script>

View File

@ -15,7 +15,7 @@
ref="fileUpload"
>
<!-- 上传按钮 -->
<el-button size="mini" type="primary">选取文件</el-button>
<el-button size="mini" type="primary">上传文件</el-button>
<!-- 上传提示 -->
<div class="el-upload__tip" slot="tip" v-if="showTip">
请上传

View File

@ -0,0 +1,649 @@
<template>
<div>
<el-upload class="upload-demo" ref="upload" action="#"
:before-upload="beforeUpload"
:on-change="onChange"
:on-remove="handleRemove"
:multiple="false"
:on-exceed="handleExceed"
:accept="acceptType"
:file-list="fileList"
:auto-upload="true"
:http-request="uploadFile"
show-file-list>
<el-button slot="trigger" size="small" type="primary" @click="isFolder = false">上传文件</el-button>
<el-button size="small" type="primary" @click="handleUploadFile" >
上传文件夹
</el-button>
<!-- 上传-->
<input v-show="false" ref="fileRef" id="fileFolder" type="file" @change="handleFolderUpload" webkitdirectory
multiple="multiple" />
<div slot="tip" class="el-upload__tip" >只能上传{{acceptType}}格式</div>
</el-upload>
<div v-show="progressFlag" class="head-img">
<el-progress :text-inside="true" :stroke-width="14" :percentage="progressPercent" status="success"></el-progress>
</div>
</div>
</template>
<script>
import axios from 'axios'
import {
getToken
} from "@/utils/auth";
export default {
props: {
uploadUrl: {
type: String,
required: false
},
//
isMultiple: {
type: Boolean,
default() {
return false
},
required: false
},
//
type: {
type: Array,
default() {
return []
},
required: false
},
//
acceptType: {
type: String,
required: false
},
//
limit: {
type: Number,
default() {
return 1
},
required: false
},
//
dataFile: {
type: [Object, Array, String],
default() {
return ''
},
required: false
},
isDetail: {
type: Boolean,
default: false
},
},
data() {
return {
fileList: [],
progress: 0,
isUploading: false,
progressFlag: false, //
progressPercent: 0, //
partSize: 5 * 1024 * 1024,
fileDetailName: null,
uploadedNum: 0,
_shardCount: null, //
isFolder: false,
totalFiles: 0, //
uploadedCount: 0, //
};
},
watch: {
dataFile: {
handler(newValue, oldValue) {
if (newValue && newValue.length > 0) {
this.fileList = Array.isArray(newValue) ? newValue : [newValue]
this.fileDetailName = this.fileList[0].name
} else {
this.fileList = []
}
},
immediate: true
}
},
methods: {
created(){
this.clearFile()
},
//
beforeUpload(file) {
/* const fileType = file.type.toLowerCase()
console.info("fileType=======", fileType)
const typeFlag = this.type.some(item => {
return fileType.indexOf(item) != -1
})
if (!typeFlag) {
this.$message.error('上传类型有误,请重新上传')
return false
}*/
},
//
onChange(file, fileList) {
this.fileList = fileList;
},
handleRemove(file, fileList) {
this.fileList = fileList;
},
handleExceed(files, fileList) {
/* this.$message.warning(
"最多之能上传"+ this.limit +"个附件"
); */
},
async uploadFile({ data, file }) {
let self = this
//
if (file.size < this.partSize) {
let formData = new FormData()
formData.append("file", file)
self.progressFlag = true;
axios({
url: self.uploadUrl,
method: 'post',
data: formData,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
onUploadProgress: progressEvent => {
// progressEvent.loaded:
// progressEvent.total:
//
self.progressPercent = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
}
}).then(res => {
setTimeout(() => {
if (res.data.code == 200) {
setTimeout(function () {
//
if(self.isFolder){
self.fileList.push(file)
}
self.$message({
message: '上传成功!',
type: 'success',
duration: '2000'
});
self.progressFlag = false;
self.progressPercent = 0
self.handleResult(res,file);
}, 500);
} else {
self.progressFlag = false;
self.progressPercent = 0
if(self.$refs.upload){
self.$refs.upload.clearFiles();
}
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
}
}, 1000);
}).catch(error => {
console.error(error)
self.progressFlag = false;
self.progressPercent = 0
if(self.$refs.upload){
self.$refs.upload.clearFiles();
}
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
})
} else {
self.uploadIdSharding(file);
}
},
uploadIdSharding(file){
let self = this
self.uploadedNum = 0
file._shardCount = Math.ceil(file.size / this.partSize) //
file.uploaded = 0
let formData = new FormData()
formData.append('fileName', file.name)
//,uploadId initUpload(formData)
axios({
url: process.env.VUE_APP_BASE_API + "/common/initUpload",
method: 'post',
data: formData,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(function (res) {
if (res.status == 200) {
//0
file.uploadId = res.data.uploadId
file.objectKey = res.data
file.chunkId = 0
self.uploadByChunk(file)
} else {
this.progress--
self.$message.error(res.msg)
}
}).catch(error => {
self.progressPercent = 0
self.progressFlag = false;
console.error(error)
})
},
//
uploadByChunk(file) {
this._start = file.chunkId * this.partSize
this._end = Math.min(file.size, this._start + this.partSize)// +
let self = this
let fileData = file.slice(this._start, this._end)
//MD5
let reader = new FileReader()
reader.readAsBinaryString(fileData)
let form1 = new FormData()//newform
form1.append('chunkFile', fileData) //slice
form1.append('uploadId', file.uploadId)
form1.append('chunkId', (file.chunkId + 1).toString())
form1.append('shardCount', file._shardCount.toString()) //
self.progressFlag = true;
//Chunk chunkMD5 uploadChunk(form1)
axios({
url: process.env.VUE_APP_BASE_API + "/common/uploadChunk",
method: 'post',
data: form1,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(response => {
if (response.status == 200) {
//MD5MD5
// self.md5Str[index] === response.msg ||
if (true) {
// this.$message.success('' + (index + 1).toString() + '')
self.uploadedNum++
let percent = Math.floor((self.uploadedNum / file._shardCount) * 100)
self.percentageSend(file, percent)
//
file.chunkId++
if (file.chunkId < file._shardCount) {
this.uploadByChunk(file)
}
} else {
//
this.$message.success('第' + (file.chunkId + 1).toString() + '块文件上传不成功,重新上传')
this.uploadByChunk(file.chunkId)
}
} else {
//
this.progress--
this.$message.error(response.msg)
}
})
},
//
percentageSend(file, perNum) {
let self = this
self.progressPercent = perNum
//
if (perNum === 100) {
let form2 = new FormData()//newform
form2.append('uploadId', file.uploadId)
form2.append('fileName', file.name)
//
// 访URL
axios({
url: process.env.VUE_APP_BASE_API + "/common/mergeFile",
method: 'post',
data: form2,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(res => {
if (res.status == 200) {
setTimeout(function () {
self.$message({
message: '上传成功!',
type: 'success',
duration: '2000'
});
self.progressFlag = false;
self.progressPercent = 0
self.handleResult(res,file);
}, 500);
//
if(self.isFolder){
self.fileList.push(file)
}
} else {
self.progressFlag = false;
self.progressPercent = 0
if(self.$refs.upload){
self.$refs.upload.clearFiles();
}
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
}
}).catch(error => {
self.progressFlag = false;
self.progressPercent = 0
if(self.$refs.upload){
self.$refs.upload.clearFiles();
}
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
});
}
},
resetData() {
this.progress = 0;
},
handleResult(res, file) {
let self = this
const data = {
fileName: file.name,
fileSize: file.size,
fileUrl: res.data.url,
filePath: res.data.filePath,
fileOldName: res.data.originalFilename,
fileNewName: res.data.newFileName,
suffixType: res.data.suffixType
}
self.$emit("handleSuccess", data)
self.clearFile()
},
/** 清空文件 **/
clearFile(){
if(this.$refs.upload){
this.$refs.upload.clearFiles();
}
this.fileList = []
},
handleUploadFile() {
document.getElementById("fileFolder").value = null;
this.$refs.fileRef.dispatchEvent(new MouseEvent("click"));
},
/* async handleFolderUpload(event) {
let self = this;
self.isFolder = true
const files = event.target.files;
self.fileslength = files.length;
let filesper = Math.floor( 100 / files.length * 100)/100;
self.progressShow = true;
if (self.fileslength == 0) {
self.progressShow = false;
self.$modal.msg("上传完成0个未完成0个");
}
for (const file of files) {
let temp = {
"data": null,
"file": file
}
await self.uploadFile(temp);
}
}, */
/* // 处理文件夹上传
async handleFolderUpload(event) {
const files = event.target.files;
this.isFolder = true;
this.progressFlag = true;
if (files.length === 0) {
this.$message.warning('没有选择文件');
return;
}
let successCount = 0;
let failCount = 0;
for (const file of files) {
try {
await this.uploadFolderFile({ file });
successCount++;
} catch (error) {
failCount++;
}
}
this.$message.success(`上传完成!成功:${successCount},失败:${failCount}`);
this.progressFlag = false;
this.progressPercent = 0;
}, */
//
uploadFolderFile({ data, file }) {
let self = this
//
if (file.size < this.partSize) {
return new Promise((resolve, reject) => {
const formData = new FormData();
formData.append("file", file);
this.progressFlag = true;
axios({
url: self.uploadUrl,
method: 'post',
data: formData,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
/* onUploadProgress: progressEvent => {
this.progressPercent = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
} */
}).then(res => {
setTimeout(() => {
if (res.data.code === 200) {
// self.progressFlag = false;
// self.progressPercent = 0;
self.handleResult(res,file);
resolve(); // resolve
} else {
// self.progressFlag = false;
self.$message.error(file.name + '上传失败!');
reject(); // reject
}
}, 500);
}).catch(error => {
// self.progressFlag = false;
// self.progressPercent = 0;
self.$message.error(file.name + '上传失败!');
reject(error); // reject
});
});
}else{
return new Promise((resolve, reject) => {
self.uploadIdShardingFolder(file)
.then(() => {
resolve(); //
})
.catch(error => {
reject(error); // reject
});
});
}
},
async handleFolderUpload(event) {
let self = this
const files = Array.from(event.target.files);
this.totalFiles = files.length;
this.uploadedCount = 0;
this.progressFlag = true;
let failCount = 0;
for (let i = 0; i < files.length; i++) {
const file = files[i];
const fileExtension = file.name.slice(file.name.lastIndexOf('.')).toLowerCase();
//
if (!self.acceptType.includes(fileExtension)) {
failCount++;
this.$message.error('文件格式不支持: ' + file.name);
continue;
}
try {
await this.uploadFolderFile(
{
data: null,
file: file
}
);
this.uploadedCount++;
this.updateProgress();
} catch (error) {
failCount++;
}
}
setTimeout(function () {
self.$message.success('上传完成!成功:' + this.uploadedCount+',失败:' + failCount);
self.progressFlag = false;
self.progressPercent = 0;
}, 500);
},
updateProgress() {
if (this.uploadedCount === this.totalFiles) {
this.progressPercent = 100;
} else {
this.progressPercent = Math.min(100, Math.floor((this.uploadedCount / this.totalFiles) * 100));
}
/*
if (this.uploadedCount % 10 === 0 || this.uploadedCount === this.totalFiles) {
this.$message.success(`已上传 ${this.uploadedCount} 个文件`);
} */
},
//
uploadIdShardingFolder(file) {
let self = this
return new Promise((resolve, reject) => {
file._shardCount = Math.ceil(file.size / this.partSize); //
file.uploaded = 0;
const formData = new FormData();
formData.append('fileName', file.name);
// , uploadId
axios({
url: process.env.VUE_APP_BASE_API + "/common/initUpload",
method: 'post',
data: formData,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(res => {
if (res.status === 200) {
file.uploadId = res.data.uploadId;
file.chunkId = 0;
this.uploadByChunkFolder(file)
.then(() => resolve()) // resolve
.catch(error => reject(error)); // reject
} else {
reject(new Error('初始化上传失败'));
}
}).catch(error => {
reject(error);
});
});
},
//
uploadByChunkFolder(file) {
let self = this
return new Promise((resolve, reject) => {
const uploadChunk = (chunkId) => {
const _start = chunkId * this.partSize;
const _end = Math.min(file.size, _start + this.partSize);
const fileData = file.slice(_start, _end);
const form1 = new FormData();
form1.append('chunkFile', fileData);
form1.append('uploadId', file.uploadId);
form1.append('chunkId', (chunkId + 1).toString());
form1.append('shardCount', file._shardCount.toString());
axios({
url: process.env.VUE_APP_BASE_API + "/common/uploadChunk",
method: 'post',
data: form1,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(response => {
if (response.status === 200) {
file.uploadedNum++;
// const percent = Math.floor((file.uploadedNum / file._shardCount) * 100);
// this.percentageSend(file, percent);
if (chunkId + 1 < file._shardCount) {
//
uploadChunk(chunkId + 1);
} else {
//
this.mergeFileFolder(file).then(() => resolve()).catch(error => reject(error));
}
} else {
reject(new Error('分片上传失败'));
}
}).catch(error => {
reject(error);
});
};
// 0
uploadChunk(0);
});
},
//
mergeFileFolder(file) {
let self = this
return new Promise((resolve, reject) => {
const form2 = new FormData();
form2.append('uploadId', file.uploadId);
form2.append('fileName', file.name);
axios({
url: process.env.VUE_APP_BASE_API + "/common/mergeFile",
method: 'post',
data: form2,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(res => {
if (res.status === 200) {
self.handleResult(res,file);
resolve(); //
} else {
reject(new Error('文件合并失败'));
}
}).catch(error => {
reject(error);
});
});
}
}
};
</script>

View File

@ -1,5 +1,5 @@
<template>
<div>
<div v-if="!isDetail">
<el-upload class="upload-demo" ref="upload" action="#"
:before-upload="beforeUpload"
:on-change="onChange"
@ -12,283 +12,143 @@
:auto-upload="true"
:http-request="uploadFile"
show-file-list>
<el-button slot="trigger" size="small" type="primary">选取文件</el-button>
<div slot="tip" class="el-upload__tip">只能上传{{acceptType}}文件</div>
<el-button slot="trigger" size="small" type="primary" >上传文件</el-button>
<el-button size="small" type="primary" @click="handleUploadFile" >
上传文件夹
</el-button>
<!-- 上传-->
<input v-show="false" ref="fileRef" id="fileFolder" type="file" @change="handleFolderUpload" webkitdirectory
multiple="multiple" />
<!-- <input v-show="false" type="file" ref="fileRef" webkitdirectory @change="handleFolderUpload">
<el-button slot="trigger" size="small" type="primary">上传文件夹</el-button>-->
</el-upload>
<div slot="tip" class="el-upload__tip" >只能上传{{acceptType}}文件</div>
<div v-show="progressFlag" class="head-img">
<el-progress :text-inside="true" :stroke-width="14" :percentage="progressPercent" status="success"></el-progress>
<el-progress :text-inside="true" :stroke-width="14" :percentage="progressPercent" status="success"></el-progress>
</div>
</div>
</div>
<div v-else>
{{fileDetailName}}
<!-- {{fileList[0].name}}-->
</div>
</template>
<script>
import axios from 'axios'
import {
getToken
getToken
} from "@/utils/auth";
import JSZip from 'jszip'
export default {
props: {
uploadUrl: {
type: String,
required: true
},
headers: {
type: Object,
default: () => ({})
},
extraData: {
type: Object,
default: () => ({})
},
onSuccess: {
type: Function,
default: () => {}
},
onError: {
type: Function,
default: () => {}
},
//
isMultiple: {
type: Boolean,
default() {
return false
}
},
//
type: {
type: Array,
default() {
return []
}
},
//
acceptType: {
type: String,
required: true
},
//
limit: {
type: Number,
default() {
return 1
}
},
props: {
uploadUrl: {
type: String,
required: false
},
data() {
return {
fileList: [],
progress: 0,
isUploading: false,
progressFlag: false, //
progressPercent: 0, //
partSize: 5 * 1024 * 1024,
};
},
methods: {
//
beforeUpload(file) {
/* const fileType = file.type.toLowerCase()
console.info("fileType=======", fileType)
const typeFlag = this.type.some(item => {
return fileType.indexOf(item) != -1
})
if (!typeFlag) {
this.$message.error('上传类型有误,请重新上传')
return false
}*/
//
isMultiple: {
type: Boolean,
default() {
return false
},
/* //上传函数
submitUpload(file) {
// 便setTimeout --setTimeoutvue
var that = this;
// that.$refs.upload.submit();
//
if (this.fileList.length == 0) {
that.$message({
message: '请选择导入的文件',
type: 'warning',
duration: '2000'
});
return;
}
//FormData();
let paramFormData = new FormData();
// fileList
that.fileList.forEach(file => {
paramFormData.append("file", file.raw);
});
//progressFlag
that.progressFlag = true;
//axios
axios({
url: that.uploadUrl,
method: 'post',
data: paramFormData,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
onUploadProgress: progressEvent => {
// progressEvent.loaded:
// progressEvent.total:
//
that.progressPercent = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
}
}).then(res => {
console.info("res===========", res)
if (res.data.code == 200 && that.progressPercent === 100) {
setTimeout(function () {
that.$message({
message: '上传成功!',
type: 'success',
duration: '2000'
});
that.progressFlag = false;
that.progressPercent = 0
}, 500);
}
}).catch(error => {
that.progressFlag = false;
that.progressPercent = 0
that.$refs.upload.clearFiles();
that.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
})
},*/
//
onChange(file, fileList) {
this.fileList = fileList;
},
handleRemove(file, fileList) {
this.fileList = fileList;
},
handleExceed(files, fileList) {
this.$message.warning(
"最多之能上传"+ this.limit +"个附件"
);
},
async uploadFile({ data, file }) {
let self = this
//
this.progress++
if (file.size < this.partSize) {
let formData = new FormData()
formData.append("file", file)
self.progressFlag = true;
axios({
url: self.uploadUrl,
method: 'post',
data: formData,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
onUploadProgress: progressEvent => {
// progressEvent.loaded:
// progressEvent.total:
//
self.progressPercent = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
}
}).then(res => {
setTimeout(() => {
if (res.data.code == 200 && self.progressPercent === 100) {
setTimeout(function () {
self.$message({
message: '上传成功!',
type: 'success',
duration: '2000'
});
self.progressFlag = false;
self.progressPercent = 0
}, 500);
} else {
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
}
}, 1000);
}).catch(error => {
console.error(error)
self.progressFlag = false;
self.progressPercent = 0
self.$refs.upload.clearFiles();
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
})
required: false
},
//
type: {
type: Array,
default() {
return []
},
required: false
},
//
acceptType: {
type: String,
required: false
},
//
limit: {
type: Number,
default() {
return 1
},
required: false
},
//
dataFile: {
type: [Object, Array, String],
default() {
return ''
},
required: false
},
isDetail: {
type: Boolean,
default: false
},
},
data() {
return {
fileList: [{name:null}],
progress: 0,
isUploading: false,
progressFlag: false, //
progressPercent: 0, //
partSize: 5 * 1024 * 1024,
fileDetailName: null
};
},
watch: {
dataFile: {
handler(newValue, oldValue) {
if (newValue && newValue.length > 0) {
this.fileList = Array.isArray(newValue) ? newValue : [newValue]
this.fileDetailName = this.fileList[0].name
} else {
console.info("111111111111")
file._shardCount = Math.ceil(file.size / this.partSize) //
file.uploaded = 0
let formData = new FormData()
formData.append('fileName', file.name)
let self = this
//,uploadId initUpload(formData)
axios({
url: process.env.VUE_APP_BASE_API + "/common/initUpload",
method: 'post',
data: formData,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(function (res) {
console.info("res=====initUpload=======", res)
if (res.status == 200) {
//0
file.uploadId = res.data.uploadId
file.objectKey = res.data
file.chunkId = 0
self.uploadByChunk(file)
} else {
this.progress--
self.$message.error(res.msg)
}
}).catch(error => {
self.progressPercent = 0
self.progressFlag = false;
console.error(error)
})
this.fileList = [{name:null}]
}
},
//
uploadByChunk(file) {
this._start = file.chunkId * this.partSize
this._end = Math.min(file.size, this._start + this.partSize)// +
let self = this
let fileData = file.slice(this._start, this._end)
//MD5
let reader = new FileReader()
reader.readAsBinaryString(fileData)
//
// reader.onloadend = function(e) {
// hex_md5md5OSSmd5-js
// self.md5Str[index] = (CryptoJS(this.result)).toLocaleUpperCase()
// self.md5Str[index] = CryptoJS.MD5(e.target.result)
// }
let form1 = new FormData()//newform
form1.append('chunkFile', fileData) //slice
form1.append('uploadId', file.uploadId)
form1.append('chunkId', (file.chunkId + 1).toString())
form1.append('shardCount', file._shardCount.toString()) //
immediate: true
}
},
methods: {
//
beforeUpload(file) {
/* const fileType = file.type.toLowerCase()
console.info("fileType=======", fileType)
const typeFlag = this.type.some(item => {
return fileType.indexOf(item) != -1
})
if (!typeFlag) {
this.$message.error('上传类型有误,请重新上传')
return false
}*/
},
//
onChange(file, fileList) {
this.fileList = fileList;
},
handleRemove(file, fileList) {
this.fileList = fileList;
},
handleExceed(files, fileList) {
this.$message.warning(
"最多之能上传"+ this.limit +"个附件"
);
},
async uploadFile({ data, file }) {
let self = this
//
if (file.size < this.partSize) {
let formData = new FormData()
formData.append("file", file)
self.progressFlag = true;
//Chunk chunkMD5 uploadChunk(form1)
axios({
url: process.env.VUE_APP_BASE_API + "/common/uploadChunk",
url: self.uploadUrl,
method: 'post',
data: form1,
data: formData,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
@ -299,55 +159,9 @@ export default {
//
self.progressPercent = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
}
}).then(response => {
console.info("response=======uploadChunk=====", response)
if (response.status == 200) {
//MD5MD5
// self.md5Str[index] === response.msg ||
if (true) {
// this.$message.success('' + (index + 1).toString() + '')
file.uploaded++
self.percentageSend(file)
//
file.chunkId++
if (file.chunkId < file._shardCount) {
this.uploadByChunk(file)
}
} else {
//
this.$message.success('第' + (file.chunkId + 1).toString() + '块文件上传不成功,重新上传')
this.uploadByChunk(file.chunkId)
}
} else {
//
this.progress--
this.$message.error(response.msg)
}
})
},
//
percentageSend(file) {
let self = this
let perNum = Math.floor((file.uploaded / file._shardCount) * 100)
this.progressPercent = perNum
//
if (perNum === 100) {
let form2 = new FormData()//newform
form2.append('uploadId', file.uploadId)
form2.append('fileName', file.name)
//
// 访URL
axios({
url: process.env.VUE_APP_BASE_API + "/common/mergeFile",
method: 'post',
data: form2,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(response => {
console.info("response====mergeFile========", response)
if (response.status == 200) {
}).then(res => {
setTimeout(() => {
if (res.data.code == 200 && self.progressPercent === 100) {
setTimeout(function () {
self.$message({
message: '上传成功!',
@ -356,21 +170,315 @@ export default {
});
self.progressFlag = false;
self.progressPercent = 0
self.handleResult(res,file);
}, 500);
} else {
self.progressFlag = false;
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
}
console.info("file===============", file)
})
}, 1000);
}).catch(error => {
console.error(error)
self.progressFlag = false;
self.progressPercent = 0
self.$refs.upload.clearFiles();
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
})
} else {
file._shardCount = Math.ceil(file.size / this.partSize) //
file.uploaded = 0
let formData = new FormData()
formData.append('fileName', file.name)
let self = this
//,uploadId initUpload(formData)
axios({
url: process.env.VUE_APP_BASE_API + "/common/initUpload",
method: 'post',
data: formData,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(function (res) {
if (res.status == 200) {
//0
file.uploadId = res.data.uploadId
file.objectKey = res.data
file.chunkId = 0
self.uploadByChunk(file)
} else {
this.progress--
self.$message.error(res.msg)
}
}).catch(error => {
self.progressPercent = 0
self.progressFlag = false;
console.error(error)
})
}
},
//
uploadByChunk(file) {
this._start = file.chunkId * this.partSize
this._end = Math.min(file.size, this._start + this.partSize)// +
let self = this
let fileData = file.slice(this._start, this._end)
//MD5
let reader = new FileReader()
reader.readAsBinaryString(fileData)
let form1 = new FormData()//newform
form1.append('chunkFile', fileData) //slice
form1.append('uploadId', file.uploadId)
form1.append('chunkId', (file.chunkId + 1).toString())
form1.append('shardCount', file._shardCount.toString()) //
self.progressFlag = true;
//Chunk chunkMD5 uploadChunk(form1)
axios({
url: process.env.VUE_APP_BASE_API + "/common/uploadChunk",
method: 'post',
data: form1,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
onUploadProgress: progressEvent => {
// progressEvent.loaded:
// progressEvent.total:
//
self.progressPercent = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
}
},
resetData() {
this.progress = 0;
},
}
}).then(response => {
if (response.status == 200) {
//MD5MD5
// self.md5Str[index] === response.msg ||
if (true) {
// this.$message.success('' + (index + 1).toString() + '')
file.uploaded++
self.percentageSend(file)
//
file.chunkId++
if (file.chunkId < file._shardCount) {
this.uploadByChunk(file)
}
} else {
//
this.$message.success('第' + (file.chunkId + 1).toString() + '块文件上传不成功,重新上传')
this.uploadByChunk(file.chunkId)
}
} else {
//
this.progress--
this.$message.error(response.msg)
}
})
},
//
percentageSend(file) {
let self = this
let perNum = Math.floor((file.uploaded / file._shardCount) * 100)
this.progressPercent = perNum
//
if (perNum === 100) {
let form2 = new FormData()//newform
form2.append('uploadId', file.uploadId)
form2.append('fileName', file.name)
//
// 访URL
axios({
url: process.env.VUE_APP_BASE_API + "/common/mergeFile",
method: 'post',
data: form2,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(res => {
if (res.status == 200) {
setTimeout(function () {
self.$message({
message: '上传成功!',
type: 'success',
duration: '2000'
});
self.progressFlag = false;
self.progressPercent = 0
self.handleResult(res,file);
}, 500);
} else {
self.progressFlag = false;
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
}
})
}
},
resetData() {
this.progress = 0;
},
handleResult(res, file) {
let self = this
const data = {
fileName: file.name,
fileSize: file.size,
fileUrl: res.data.url,
filePath: res.data.filePath,
fileOldName: res.data.originalFilename,
fileNewName: res.data.newFileName,
suffixType: res.data.suffixType
}
self.$emit("handleSuccess", data)
},
/** 清空文件 **/
clearFile(){
this.progressFlag = false;
if(this.$refs.upload){
this.$refs.upload.clearFiles();
}
this.fileList = []
},
handleUploadFile() {
document.getElementById("fileFolder").value = null;
this.$refs.fileRef.dispatchEvent(new MouseEvent("click"));
},
async handleFolderUpload(event) {
let self = this;
const files = event.target.files;
this.fileslength = files.length;
//
let folderName = "";
if (files.length > 0) {
let relativePath = files[0].webkitRelativePath;
folderName = relativePath.split("/")[0];
}
const zip = new JSZip();
// ZIP
Array.from(files).forEach(file => {
zip.file(file.webkitRelativePath, file);
});
// ZIP
const zipBlob = await zip.generateAsync({ type: "blob" });
// FormData
/* const formData = new FormData();
formData.append("file", zipBlob, folderName + ".zip");*/
let formData = new FormData()
formData.append('fileName', folderName + ".zip")
// shardCount
const _shardCount = Math.ceil(zipBlob.size / this.partSize);
const fileObj = {
_shardCount,
size: zipBlob.size,
file: zipBlob // zipBlob fileObj
};
self.$set(fileObj.file, '_shardCount', _shardCount);
self.$set(fileObj.file, 'uploaded', 0);
self.$set(fileObj.file, 'name', folderName + ".zip");
self.fileList.push(fileObj.file)
if (zipBlob.size < this.partSize) {
let formDataSign = new FormData()
formDataSign.append("file", zipBlob, folderName + ".zip")
self.progressFlag = true;
axios({
url: self.uploadUrl,
method: 'post',
data: formDataSign,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
onUploadProgress: progressEvent => {
// progressEvent.loaded:
// progressEvent.total:
//
self.progressPercent = ((progressEvent.loaded / progressEvent.total) * 100) | 0;
}
}).then(res => {
setTimeout(() => {
if (res.data.code == 200 && self.progressPercent === 100) {
setTimeout(function () {
self.$message({
message: '上传成功!',
type: 'success',
duration: '2000'
});
self.progressFlag = false;
self.progressPercent = 0
self.handleResult(res,fileObj.file);
}, 500);
} else {
self.progressFlag = false;
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
}
}, 1000);
}).catch(error => {
console.error(error)
self.progressFlag = false;
self.progressPercent = 0
self.$refs.upload.clearFiles();
self.$message({
message: '上传失败!',
type: 'error',
duration: '2000'
});
})
} else {
// uploadId
axios({
url: process.env.VUE_APP_BASE_API + "/common/initUpload",
method: 'post',
data: formData,
headers: {
'Authorization': 'Bearer ' + getToken(),
'Content-Type': 'multipart/form-data'
},
}).then(function (res) {
if (res.status === 200) {
self.$set(fileObj.file, 'uploadId', res.data.uploadId);
self.$set(fileObj.file, 'chunkId', 0);
self.$set(fileObj.file, 'objectKey', res.data);
/*//从第0块开始上传
fileObj.uploadId = res.data.uploadId;
fileObj.chunkId = 0;
fileObj.objectKey = res.data*/
self.uploadByChunk(fileObj.file);
} else {
self.progress--;
self.$message.error(res.msg);
}
}).catch(error => {
self.progressPercent = 0;
self.progressFlag = false;
console.error(error);
});
}
},
}
};
</script>

View File

@ -0,0 +1,133 @@
<template>
<div :class="$options.name" @click="show = !show" :placement="placement">
<div class="collapse-btns">
<div class="collapse-btn" v-if="show">
<i class="el-icon-caret-top"></i>
<div class="label">折叠{{ collapseLabel || expandLabel || `` }}</div>
</div>
<div class="collapse-btn" v-else>
<i class="el-icon-caret-bottom"></i>
<div class="label">展开{{ expandLabel || collapseLabel || `` }}</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "sgCollapseBtn",
components: {},
data() {
return {
show: false,
};
},
props: ["data", "value", "collapseLabel", "expandLabel", "placement"],
watch: {
value: {
handler(d) {
this.show = d;
},
deep: true,
immediate: true,
},
show(d) {
this.$emit("input", d);
},
},
created() {},
mounted() {},
computed: {},
methods: {},
};
</script>
<style lang="scss" scoped>
.sgCollapseBtn {
position: relative;
z-index: 1;
/*禁止选中文本*/
user-select: none;
width: 100%;
height: 30px;
line-height: 30px;
background-color: white;
cursor: pointer;
&[placement="bottom"] {
position: absolute;
top: revert;
bottom: 0;
left: 0;
right: 0;
}
.collapse-btns {
width: 100%;
$side: 20%; //
/*左右渐变遮罩(兼容IOS)*/
-webkit-mask-image: linear-gradient(
to right,
transparent,
white $side,
white calc(100% - #{$side}),
transparent
);
display: flex;
justify-content: center;
align-items: center;
font-size: 14px;
background-color: white;
&::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
background: linear-gradient(white, #e2f0ff);
opacity: 0;
transition: 1s ease !important;
z-index: -1;
}
.collapse-btn {
transition: 0.4s !important;
display: flex;
align-items: center;
transform: translateX(40%);
i {
transition: 0.4s !important;
color: #d3dce6;
}
.label {
transition: 0.2s !important;
margin-left: 25px;
color: #409eff;
opacity: 0;
}
}
}
&:active,
&:hover {
.collapse-btns {
&::after {
opacity: 1;
}
.collapse-btn {
transform: translateX(0%);
i {
color: #409eff;
}
.label {
margin-left: 5px;
color: #409eff;
opacity: 1;
// width: 100%;
}
}
}
}
}
</style>

View File

@ -0,0 +1,255 @@
<template>
<div :class="$options.name"></div>
</template>
<script>
export default {
name: "sgDragMove",
data() {
return {
offset: { x: 0, y: 0 }, //
style: { top: "0px", left: "0px" },
canDragDom: null, //
moveDom: null, //
};
},
props: [
"data", //()
/* data
[
...
{
canDragDom: elementDOM,//or
moveDom: elementDOM,//or
},
...
]
*/
"disabled", //
"mousedownNearSide", //
"mousemoveNearSide", //
"mouseupNearSide", //
"nearPadding", //mousedownNearSide||mousemoveNearSide||mouseupNearSide=truenumberarray5[5,5,5,5],[,,,]
"stopBoundary", //mousedownNearSide||mousemoveNearSide||mouseupNearSide=truenumberarray5[5,5,5,5],[,,,]
"cursor", //
/*cursor{
grab:'default',//
grabbing:'default',//
} */
],
watch: {
data: {
handler(newValue, oldValue) {
newValue ? this.__addDragsEvents(newValue) : this.__removeDragsEvents(oldValue);
},
deep: true,
immediate: true,
},
disabled: {
handler(newValue, oldValue) {
newValue ? this.__removeAllEvents() : this.__addAllEvents();
},
deep: true,
immediate: true,
},
style: {
handler(newValue, oldValue) {
if (this.moveDom && newValue && Object.keys(newValue).length) {
let d = newValue;
Object.keys(d).forEach((k) => (this.moveDom.style[k] = d[k]));
this.moveDom.style.right = "revert";
this.moveDom.style.bottom = "revert";
this.$emit(`getStyle`, d); //DOM
}
},
deep: true, //
immediate: true, //
},
},
destroyed() {
this.__removeAllEvents();
},
mounted() {
this.$parent.$el.style.setProperty(
"--sgDragMove-grab",
(this.cursor || {}).grab || "grab"
); //jscss
this.$parent.$el.style.setProperty(
"--sgDragMove-grabbing",
(this.cursor || {}).grabbing || "grabbing"
); //jscss
},
methods: {
__addAllEvents() {
this.__addDragsEvents(this.data);
},
__removeAllEvents() {
this.__removeWindowEvents();
this.__removeDragsEvents(this.data);
},
__addWindowEvents() {
this.__removeWindowEvents();
addEventListener("mousemove", this.mousemove_window);
addEventListener("mouseup", this.mouseup_window);
},
__removeWindowEvents() {
removeEventListener("mousemove", this.mousemove_window);
removeEventListener("mouseup", this.mouseup_window);
},
// DIV
__addDragsEvents(doms) {
(doms || []).forEach((dom) => {
this.__removeDraggedEvents(dom.canDragDom);
this.__addDraggedEvents(dom.canDragDom);
});
},
__removeDragsEvents(doms) {
(doms || []).forEach((dom) => {
this.__removeDraggedEvents(dom.canDragDom);
});
},
__addDraggedEvents(dom) {
dom.setAttribute("sgDragMove_grab", "ready");
dom.addEventListener("dragstart", this.dragstart);
dom.addEventListener("mousedown", this.mousedown);
},
__removeDraggedEvents(dom) {
dom.removeEventListener("dragstart", this.dragstart);
dom.removeEventListener("mousedown", this.mousedown);
},
dragstart(e) {
e.stopPropagation();
e.preventDefault();
return false;
},
mousedown(e) {
if (this.disabled) return this.mouseup_window(e);
if (e.button === 2) return this.mouseup_window(e); //
this.canDragDom = e.currentTarget;
this.moveDom = this.data.find((v) => v.canDragDom == this.canDragDom).moveDom;
this.canDragDom.setAttribute("sgDragMove_grab", "down");
this.moveDom.setAttribute("sgDragMove_move", "ready");
let or = this.moveDom.getBoundingClientRect();
this.offset = { x: e.clientX - or.x, y: e.clientY - or.y };
(this.mousedownNearSide || this.mousedownNearSide === "") && this.nearSide();
this.$emit("dragStart", this.getResult(e));
this.__addWindowEvents();
},
setOffset(d) {
this.offset = {
...this.offset,
...d,
};
},
mousemove_window(e) {
this.canDragDom.setAttribute("sgDragMove_grab", "down");
this.moveDom.setAttribute("sgDragMove_move", "ing");
let x = e.clientX - this.offset.x;
let y = e.clientY - this.offset.y;
this.style = { left: x + "px", top: y + "px" };
this.style["transition-property"] = "left,top";
this.style["transition-duration"] = "0s,0s";
this.$nextTick(() => {
(this.mousemoveNearSide || this.mousemoveNearSide === "") && this.nearSide();
this.$emit("dragging", this.getResult(e));
});
},
mouseup_window(e) {
this.$emit("dragEnd", this.getResult(e));
(this.mouseupNearSide || this.mouseupNearSide === "") && this.nearSide();
this.offset = null;
this.style = null;
this.canDragDom.setAttribute("sgDragMove_grab", "ready");
this.moveDom.setAttribute("sgDragMove_move", "end");
setTimeout(() => {
this.moveDom && this.moveDom.removeAttribute("sgDragMove_move");
}, 100);
this.canDragDom = null;
this.moveDom = null;
this.__removeWindowEvents();
},
//
nearSide() {
let arr = this.nearPadding ? JSON.parse(JSON.stringify(this.nearPadding)) : 0;
Array.isArray(arr) || (arr = [...Array(4)].map((v) => arr));
let [dis_top, dis_right, dis_bottom, dis_left] = arr;
arr = this.stopBoundary ? JSON.parse(JSON.stringify(this.stopBoundary)) : 0;
Array.isArray(arr) || (arr = [...Array(4)].map((v) => arr));
let [
stopBoundary_top,
stopBoundary_right,
stopBoundary_bottom,
stopBoundary_left,
] = arr;
let x = parseFloat(this.moveDom.style.left);
let y = parseFloat(this.moveDom.style.top);
let rect = this.moveDom.getBoundingClientRect();
let min_side_x = 0,
min_x = min_side_x + dis_left,
min_left = min_side_x + stopBoundary_left;
let min_side_y = 0,
min_y = min_side_y + dis_top,
min_top = min_side_y + stopBoundary_top;
x < min_x && (this.moveDom.style.left = `${min_left}px`);
y < min_y && (this.moveDom.style.top = `${min_top}px`);
let max_side_x = innerWidth - rect.width,
max_x = max_side_x - dis_right,
max_right = max_side_x - stopBoundary_right;
let max_side_y = innerHeight - rect.height,
max_y = max_side_y - dis_bottom,
max_bottom = max_side_y - stopBoundary_bottom;
x > max_x && (this.moveDom.style.left = `${max_right}px`);
y > max_y && (this.moveDom.style.top = `${max_bottom}px`);
},
getResult(e) {
return {
$event: e,
canDragDom: this.canDragDom,
moveDom: this.moveDom,
canDragDomRect: this.canDragDom ? this.canDragDom.getBoundingClientRect() : null,
moveDomRect: this.moveDom ? this.moveDom.getBoundingClientRect() : null,
};
},
},
};
</script>
<style lang="scss">
[sgDragMove_grab="ready"] {
cursor: var(--sgDragMove-grab); //cssjs
* {
cursor: var(--sgDragMove-grab); //cssjs
}
&:hover {
opacity: 1;
}
&:active {
opacity: 0.9;
}
}
[sgDragMove_grab="down"] {
cursor: var(--sgDragMove-grabbing); //cssjs
* {
cursor: var(--sgDragMove-grabbing); //cssjs
}
}
[sgDragMove_move="ready"] {
opacity: 1;
}
[sgDragMove_move="ing"] {
opacity: 0.9;
}
[sgDragMove_move="end"] {
transition: 0.1s;
}
</style>

View File

@ -0,0 +1,281 @@
<template>
<div :class="$options.name" :disabled="disabled" draggable="false">
<div :class="`resize-handle resize-${a}`" draggable="false" @mousedown.stop="clickResizeHandle(a)"
@dblclick="dblclickResizeHandle(a, $event)" v-for="(a, i) in sizeIndexs" :key="i"></div>
</div>
</template>
<script>
export default {
name: 'sgDragSize',
data() {
return {
tbHeight: 0,
dragSizeIndex: '',
originRect: {},
dblclickOriginRect: {},
sizeIndexs: [
'top',
'right',
'bottom',
'left',
'top-left',
'top-right',
'bottom-left',
'bottom-right',
],
}
},
props: [
"disabled",//
"taskbarHeight",//
"minWidth",//
"minHeight",//
"maxWidth",//
"maxHeight",//
],
watch: {
disabled: {
handler(newValue, oldValue) {
newValue && this.__removeWindowEvents();
}, deep: true, immediate: true,
},
taskbarHeight: {
handler(d) {
this.tbHeight = d || 0;
}, deep: true, immediate: true,
},
},
destroyed() {
this.__removeWindowEvents();
},
methods: {
view_innerHeight() {
return innerHeight - this.tbHeight;
},
clickResizeHandle(d) {
this.dragSizeIndex = d;
this.mousedown(d);
},
dblclickResizeHandle(d, $event) {
let rect = this.$el.getBoundingClientRect();
rect.width < innerWidth && rect.height < this.view_innerHeight() && (this.dblclickOriginRect = rect);
this.dblResize(d, rect, $event);
},
__addWindowEvents() {
this.__removeWindowEvents();
addEventListener('mousemove', this.mousemove_window);
addEventListener('mouseup', this.mouseup_window);
},
__removeWindowEvents() {
removeEventListener('mousemove', this.mousemove_window);
removeEventListener('mouseup', this.mouseup_window);
},
mousedown(e) {
this.originRect = this.$el.getBoundingClientRect();
this.originRect.bottomRightX = this.originRect.x + this.originRect.width;//.x
this.originRect.bottomRightY = this.originRect.y + this.originRect.height;//.y
this.$emit('dragStart', e);
this.__addWindowEvents();
},
mousemove_window(e) {
let { x, y } = e;
let minWidth = this.minWidth || 50, minHeight = this.minHeight || 50, maxWidth = this.maxWidth || innerWidth, maxHeight = this.maxHeight || innerHeight;
x < 0 && (x = 0), y < 0 && (y = 0), x > innerWidth && (x = innerWidth), y > this.view_innerHeight() && (y = this.view_innerHeight());
let style = {};
switch (this.dragSizeIndex) {
case 'top-left':
style.left = x;
style.top = y;
style.width = this.originRect.bottomRightX - x;
style.width <= minWidth && (style.width = minWidth, style.left = this.originRect.bottomRightX - minWidth);
style.height = this.originRect.bottomRightY - y;
style.height <= minHeight && (style.height = minHeight, style.top = this.originRect.bottomRightY - minHeight);
break;
case 'top':
style.left = this.originRect.x;
style.top = y;
style.width = this.originRect.width;
style.height = this.originRect.bottomRightY - y;
style.height <= minHeight && (style.height = minHeight, style.top = this.originRect.bottomRightY - minHeight);
break;
case 'top-right':
style.left = this.originRect.x;
style.top = y;
style.width = x - this.originRect.x;
style.width <= minWidth && (style.width = minWidth, style.left = this.originRect.x);
style.height = this.originRect.bottomRightY - y;
style.height <= minHeight && (style.height = minHeight, style.top = this.originRect.bottomRightY - minHeight);
break;
case 'left':
style.left = x;
style.top = this.originRect.y;
style.width = this.originRect.bottomRightX - x;
style.width <= minWidth && (style.width = minWidth, style.left = this.originRect.bottomRightX - minWidth);
style.height = this.originRect.height;
break;
case 'right':
style.left = this.originRect.x;
style.top = this.originRect.y;
style.width = x - this.originRect.x;
style.width <= minWidth && (style.width = minWidth, style.left = this.originRect.x);
style.height = this.originRect.height;
break;
case 'bottom-left':
style.left = x;
style.top = this.originRect.y;
style.width = this.originRect.bottomRightX - x;
style.width <= minWidth && (style.width = minWidth, style.left = this.originRect.bottomRightX - minWidth);
style.height = y - this.originRect.y;
style.height <= minHeight && (style.height = minHeight, style.top = this.originRect.y);
break;
case 'bottom':
style.left = this.originRect.x;
style.top = this.originRect.y;
style.width = this.originRect.width;
style.height = y - this.originRect.y;
style.height <= minHeight && (style.height = minHeight, style.top = this.originRect.y);
break;
case 'bottom-right':
style.left = this.originRect.x;
style.top = this.originRect.y;
style.width = x - this.originRect.x;
style.width <= minWidth && (style.width = minWidth, style.left = this.originRect.x);
style.height = y - this.originRect.y;
style.height <= minHeight && (style.height = minHeight, style.top = this.originRect.y);
break;
default:
}
style.width > maxWidth && (style.width = maxWidth);
style.height > maxHeight && (style.height = maxHeight);
Object.keys(style).forEach(k => style[k] = `${style[k]}px`);
style['transition-property'] = 'width,height';
style['transition-duration'] = '0,0';
this.$emit('dragging', { e, style });
},
dblResize(d, rect, e) {
let style = {};
switch (d) {
case 'top-left':
break;
case 'top':
case 'bottom':
style.left = this.originRect.x;
style.top = rect.height >= this.view_innerHeight() ? this.dblclickOriginRect.y : 0;
style.width = this.originRect.width;
style.height = rect.height >= this.view_innerHeight() ? this.dblclickOriginRect.height : this.view_innerHeight();
break;
case 'top-right':
break;
case 'left':
case 'right':
style.left = rect.width >= innerWidth ? this.dblclickOriginRect.x : 0;
style.top = this.originRect.y;
style.width = rect.width >= innerWidth ? this.dblclickOriginRect.width : innerWidth;
style.height = this.originRect.height;
break;
case 'bottom-left':
break;
case 'bottom-right':
break;
default:
}
Object.keys(style).forEach(k => style[k] = `${style[k]}px`);
style['transition-property'] = 'width,height';
style['transition-duration'] = '0.1s,0.1s';
this.$emit('dragging', { e, style });
},
mouseup_window(e) {
this.$emit('dragEnd', e);
this.__removeWindowEvents();
},
}
};
</script>
<style lang="scss">
.sgDragSize {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
pointer-events: none;
.resize-handle {
position: absolute;
z-index: 100;
display: block;
pointer-events: auto;
}
&[disabled] {
.resize-handle {
pointer-events: none;
}
}
.resize-top {
cursor: n-resize;
top: -3px;
left: 0px;
height: 7px;
width: 100%;
}
.resize-right {
cursor: e-resize;
right: -3px;
top: 0px;
width: 7px;
height: 100%;
}
.resize-bottom {
cursor: s-resize;
bottom: -3px;
left: 0px;
height: 7px;
width: 100%;
}
.resize-left {
cursor: w-resize;
left: -3px;
top: 0px;
width: 7px;
height: 100%;
}
.resize-top-right {
cursor: ne-resize;
width: 16px;
height: 16px;
right: -8px;
top: -8px;
}
.resize-bottom-right {
cursor: se-resize;
width: 20px;
height: 20px;
right: -8px;
bottom: -8px;
background: url('/static/img/desktop/Windows7/sgDragSize/resize_corner.png') no-repeat;
}
.resize-bottom-left {
cursor: sw-resize;
width: 16px;
height: 16px;
left: -8px;
bottom: -8px;
}
.resize-top-left {
cursor: nw-resize;
width: 16px;
height: 16px;
left: -8px;
top: -8px;
}
}
</style>

View File

@ -0,0 +1,999 @@
<template>
<div :class="$options.name" :show="show" :size="size" :style="style">
<div class="upload-list-tray">
<!-- 托盘头部 -->
<div class="header" ref="header" @dblclick.stop.prevent="dblclickHeader">
<div class="left">
<div class="title">
<span class="upload-count" slot="reference">上传队列</span>
<div class="upload-info" v-if="liveSpeed && liveSpeed > 0">
<el-divider :direction="`vertical`" />
<div class="info-item live-speed">
<label>速度</label>
<span>{{ $g.getSize(liveSpeed) }}/s</span>
</div>
<div class="info-item taken-time" v-if="takenTime && takenTime > 0">
<label>已耗时</label>
<span>{{
$g.date.toHourMinuteSecondByMillisecond(takenTime * 1000, {
zh: true,
hideMilliSecond: true,
hideZero: true,
})
}}</span>
</div>
<div class="info-item remain-time" v-if="remainTime && remainTime > 0">
<label>剩余</label
><span>{{
$g.date.toHourMinuteSecondByMillisecond(remainTime * 1000, {
zh: true,
hideMilliSecond: true,
hideZero: true,
})
}}</span>
</div>
</div>
</div>
</div>
<div class="right" @mousedown.stop>
<!-- 控制文件的图标按钮 -->
<div class="file-btns" v-if="showDelSuccessIconBtn || showErrorIconBtn">
<div
class="icon-btn"
v-if="showDelSuccessIconBtn"
@click.stop="clearAllSuccessFile"
title="清除所有已经成功的上传记录"
>
<i class="el-icon-delete" style="color: #67c23a"></i>
</div>
<div
class="icon-btn"
v-if="showErrorIconBtn"
@click.stop="clearAllErrorFile"
title="清除所有失败的上传记录"
>
<i class="el-icon-delete-solid" style="color: #f56c6c"></i>
</div>
<div
class="icon-btn"
v-if="showErrorIconBtn"
@click.stop="uploadAllErrorFile"
title="重新上传所有失败的文件"
>
<i class="el-icon-upload2" style="color: #409eff"></i>
</div>
<template v-if="uploadList.length > maxShowUploadFileCount">
<div
class="icon-btn"
v-if="expandAllUploadList"
@click.stop="expandAllUploadList = false"
title="折叠只显示前10条上传记录"
>
<i class="el-icon-folder" style="color: #409eff"></i>
</div>
<el-tooltip
v-else
:content="`请谨慎展开列表,这将导致您的网页很卡!`"
:effect="`dark`"
:enterable="false"
:placement="`top-start`"
:popper-class="`sg-el-tooltip`"
:transition="`none`"
:disabled="uploadList.length < 200"
>
<div
class="icon-btn"
@click.stop="expandAllUploadList = true"
title="展开所有上传记录"
>
<i class="el-icon-folder-opened" style="color: #409eff"></i>
</div>
</el-tooltip>
</template>
</div>
<!-- 控制托盘的图标按钮 -->
<div class="tray-btns">
<div
class="icon-btn"
v-if="size !== 'lg' && showRightBottomBtn"
@click.stop="toRightBottomPosition"
title="回到原来的位置"
>
<i class="el-icon-bottom-right"></i>
</div>
<div
class="icon-btn"
v-if="size !== 'mn'"
@click.stop="size = 'mn'"
title="最小化"
>
<i class="el-icon-minus"></i>
</div>
<div
class="icon-btn"
v-if="size !== 'md'"
@click.stop="size = 'md'"
title="还原"
>
<i :class="size === 'lg' ? 'el-icon-copy-document' : 'el-icon-d-caret'"></i>
</div>
<div
class="icon-btn"
v-if="size !== 'lg'"
@click.stop="size = 'lg'"
title="全屏"
>
<i class="el-icon-full-screen"></i>
</div>
<div class="icon-btn" @click.stop="close">
<i class="el-icon-close"></i>
</div>
</div>
</div>
</div>
<!-- 上传中的文件列表 -->
<div class="upload-file-list">
<ul>
<li
v-for="(a, i) in expandAllUploadList ? uploadList : uploadList.slice(0, 10)"
:key="i"
:title="
a.size > 1024 * 1024 * 500
? `超大文件上传中,请耐心等待,切勿关闭或刷新浏览器!`
: ''
"
>
<div class="left">
<div class="icon-btns">
<el-button
title="移出上传队列"
:show="a.status === 'error'"
class="remove-icon-btn icon-btn"
type="danger"
icon="el-icon-delete-solid"
size="mini"
plain
circle
@click.stop="removeUploadFile(a)"
></el-button>
</div>
<!-- 动画加载旋转 -->
<div
class="fileLoading"
v-loading="a.percent < 100"
v-if="a.percent < 100 && a.status !== 'error'"
></div>
<!-- 上传成功icon -->
<div class="loadingSuccessIcon" v-if="a.percent === 100">
<i class="el-icon-success" style="color: #67c23a"></i>
</div>
<!-- 上传失败icon -->
<div class="loadingEorrorIcon" v-if="a.status === 'error'">
<i class="el-icon-error" style="color: #f56c6c"></i>
</div>
<span class="name" :title="a.filePath || a.name">
{{ a.filePath || a.name }}
<!-- {{ a.filePath && a.filePath.includes(`/`) ? `[路径:${a.filePath}]` : "" }} -->
</span>
<el-tag class="size" size="mini"
>{{ $g.getSize(a.size * (a.percent / 100)) }}/{{
$g.getSize(a.size)
}}</el-tag
>
<!-- <el-progress class="progress" :percentage="a.percent"></el-progress> -->
<el-progress
class="progress"
style="width: 100%"
type="line"
:percentage="parseInt(a.percent)"
:show-text="true"
:stroke-width="10"
:text-inside="false"
:color="'#409EFF'"
:define-back-color="'#eee'"
/>
</div>
<div class="right">
<span class="tip" :color="a.color">{{ a.tip }}</span>
<div class="icon-btns">
<el-button
:show="a.status === 'error'"
title="重新上传"
class="upload-icon-btn icon-btn"
type="primary"
icon="el-icon-upload2"
size="mini"
plain
circle
@click.stop="startUploadFile(a)"
></el-button>
</div>
</div>
</li>
</ul>
</div>
<!-- 折叠按钮 -->
<sgCollapseBtn
style="z-index: 1"
:collapseLabel="`上传记录`"
v-model="expandAllUploadList"
v-if="uploadList.length > maxShowUploadFileCount"
/>
<div class="footer">
<div class="text" v-html="popoverContent"></div>
<div class="progress" v-if="uploadList.length > 1 && totalPercentage < 100">
<label>总进度</label>
<el-progress
style="width: 100%"
type="line"
:percentage="parseInt(totalPercentage)"
:show-text="true"
:stroke-width="10"
:text-inside="false"
:color="'#409EFF'"
:define-back-color="'#eee'"
/>
</div>
</div>
</div>
<!-- 拖拽移动窗体 -->
<sgDragMove
:data="dragMoveDoms"
:cursor="{
grab: 'default',
grabbing: 'default',
}"
nearPadding="10"
:disabled="size === 'lg' && disabledDragMove"
@dragStart="$emit(`dragStart`, dragMoveDoms)"
@dragging="
showRightBottomBtn = true;
$emit(`dragging`, dragMoveDoms);
"
@dragEnd="$emit(`dragEnd`, dragMoveDoms)"
mousemoveNearSide
/>
<!-- 拖拽改变窗体尺寸 -->
<sgDragSize
v-if="resizeable_"
:disabled="size === 'lg'"
@dragStart="disabledDragMove = true"
@dragging="draggingSize"
@dragEnd="disabledDragMove = false"
:minWidth="minWidth"
:minHeight="minHeight"
/>
</div>
</template>
<script>
import sgCollapseBtn from "./sgCollapseBtn";
import sgDragMove from "./sgDragMove";
import sgDragSize from "./sgDragSize";
export default {
name: "sgUploadTray",
components: {
sgCollapseBtn,
sgDragMove,
sgDragSize,
},
data() {
return {
maxShowUploadFileCount: 10, //
expandAllUploadList: false, //
minWidth: 800,
minHeight: 40,
style_bk: null,
style: {},
resizeable_: true,
disabledDragMove: false, //
show: false,
showRightBottomBtn: false,
size: "md", //lgmdmn
uploadList: [],
dragMoveDoms: [
/* {
canDragDom: elementDOM,//
moveDom: elementDOM,//
} */
], //
lastUploadedTotalSize: 0, //
liveSpeed: 0, //(B)
takenTime: 0, //
remainTime: 0, //
interval: null,
second: 1, //
successFileList: [], //
errorFileList: [], //
remainFileList: [], //
};
},
props: ["data", "value", "resizeable", "position"],
watch: {
value: {
handler(d) {
this.show = d;
},
deep: true,
immediate: true,
},
show: {
handler(d) {
this.$emit(`input`, d);
},
deep: true,
immediate: true,
},
data: {
handler(d) {
this.uploadList = d || [];
},
deep: true,
immediate: true,
},
uploadList: {
handler(newValue, oldValue) {
if (newValue && Object.keys(newValue).length) {
this.interval || this.startUploadCalcLiveSpeed();
this.successFileList = newValue.filter((v) => v.percent == 100);
this.errorFileList = newValue.filter((v) => v.status === "error");
this.remainFileList = newValue.filter(
(v) => v.status !== "error" && v.status !== "success"
);
} else {
this.successFileList = [];
this.errorFileList = [];
this.remainFileList = [];
}
},
deep: true, //
immediate: true, //
},
resizeable: {
handler(newValue, oldValue) {
this.resizeable_ = newValue === "" || newValue;
},
deep: true, //
immediate: true, //
},
size: {
handler(newValue, oldValue) {
switch (newValue) {
case "lg":
case "mn":
this.style_bk = JSON.parse(JSON.stringify(this.style));
delete this.style.width, delete this.style.height;
break;
case "md":
this.style_bk && (this.style = JSON.parse(JSON.stringify(this.style_bk)));
break;
}
},
deep: true, //
immediate: true, //
},
},
computed: {
showDelSuccessIconBtn(d) {
return this.uploadList.some((v) => v.percent == 100);
},
showErrorIconBtn(d) {
return this.uploadList.some((v) => v.status == "error");
},
popoverContent(d) {
let r = [];
this.successFileList.length &&
r.push(
`已上传成功<span style="color: #67C23A;">${this.successFileList.length}</span>个`
);
this.errorFileList.length &&
r.push(`失败<span style="color: #F56C6C;">${this.errorFileList.length}</span>个`);
this.remainFileList.length &&
r.push(
`剩余<span style="color: #409EFF;">${this.remainFileList.length}</span>个`
);
if (this.uploadList.length) {
return `共计${this.uploadList.length}个文件,${
r.length ? `${r.join("")}文件` : ``
}`;
} else {
return `暂无待上传文件`;
}
},
//
totalPercentage() {
if (this.uploadList.length) {
return parseFloat(
((this.successFileList.length / this.uploadList.length) * 100).toFixed(2)
);
} else {
return 0;
}
},
//
uploadingFiles(d) {
let uploadingFiles_ = (this.uploadList || []).filter(
(v) => v.percent < 100 && v.status !== "error" && v.status !== "success"
);
if (uploadingFiles_.length) {
this.$emit(`changeUploadingListClose`, {
path: this.position,
close: this.close,
});
} else {
this.$emit(`changeUploadingListClose`, null);
}
return uploadingFiles_;
},
},
mounted() {
this.$el.style.setProperty("--minWidth", `${this.minWidth}px`); //jscss
this.$el.style.setProperty("--minHeight", `${this.minHeight}px`); //jscss
this.dragMoveDoms = [
{
canDragDom: this.$refs.header, //
moveDom: this.$el, //
},
];
},
destroyed() {
clearInterval(this.interval);
},
methods: {
//
startUploadCalcLiveSpeed() {
clearInterval(this.interval);
this.interval = setInterval(() => {
this.calcLiveSpeed();
}, 1000 * this.second);
},
//
endUploadCalcLiveSpeed(d) {
clearInterval(this.interval);
this.interval = null;
this.liveSpeed = 0;
this.takenTime = 0;
this.remainTime = 0;
},
//
ifNoUploadingFile_EndCalcLiveSpeed(d) {
this.uploadingFiles.length || this.endUploadCalcLiveSpeed();
},
//
calcLiveSpeed(d) {
this.takenTime++;
let uploadList = this.uploadList;
if (uploadList.length) {
let totalSize = uploadList.reduce(
(prevResult, current) => prevResult + current.size,
0
); //
let uploadedTotalSize = uploadList.reduce(
(prevResult, current) => prevResult + current.size * (0.01 * current.percent),
0
); //
let remainTotalSize = totalSize - uploadedTotalSize; //
if (this.lastUploadedTotalSize) {
this.liveSpeed = (uploadedTotalSize - this.lastUploadedTotalSize) / this.second; //
this.remainTime = remainTotalSize / this.liveSpeed; //
} else {
this.liveSpeed = 0;
}
this.lastUploadedTotalSize = uploadedTotalSize; //
} else {
this.endUploadCalcLiveSpeed();
}
},
clearAllSuccessFile() {
let successFileList = this.uploadList.filter((v) => v.percent == 100);
if (successFileList.length === 0)
return this.$message(`暂无可以移除的成功记录,请稍后再试!`);
this.$emit(`clearAllSuccessFile`, successFileList);
this.$nextTick(() => {
successFileList.forEach((file) => {
file.removeFile(); //
});
this.uploadList = this.uploadList.filter((v) => v.percent < 100);
});
},
clearAllErrorFile() {
let errorFileList = this.uploadList.filter((v) => v.status == "error");
if (errorFileList.length === 0)
return this.$message(`暂无可以移除的失败记录,请稍后再试!`);
this.$emit(`clearAllErrorFile`, errorFileList);
this.$nextTick(() => {
errorFileList.forEach((file) => {
file.removeFile(); //
});
this.uploadList = this.uploadList.filter((v) => v.status !== "error");
});
},
uploadAllErrorFile(d) {
let errorFileList = this.uploadList.filter((v) => v.status == "error");
errorFileList.forEach((fileData) => this.startUploadFile(fileData));
if (errorFileList.length === 0) return this.$message(`暂无失败记录,请稍后再试!`);
this.$emit(`uploadAllErrorFile`, errorFileList);
},
draggingSize({ style }) {
this.disabledDragMove = true;
this.style = style;
},
toRightBottomPosition(d) {
this.showRightBottomBtn = false;
let rect = this.$el.getBoundingClientRect();
this.$el.style.left = `${innerWidth - rect.width}px`;
this.$el.style.top = `${innerHeight - rect.height}px`;
// setProperty
/* this.$el.style = {
left: innerWidth - rect.width + "px",
top: innerHeight - rect.height + "px",
}; */
},
dblclickHeader(d) {
switch (this.size) {
case "lg":
this.size = "md";
break;
case "md":
this.size = "mn";
break;
case "mn":
this.size = "md";
break;
default:
}
},
removeAllFilesFromList() {
this.uploadList.forEach((file) => {
file.removeFile(); //
});
this.uploadList = []; //
},
removeFileFromList(d) {
let file = this.uploadList.find((v) => v.uid == d.uid);
file.removeFile(); //
this.uploadList.splice(
this.uploadList.findIndex((v) => v.uid == d.uid),
1
); //
},
//
startUploadFile(fileData) {
fileData.startUpload({ handleTrigger: true });
},
//
removeUploadFile(d) {
if (d.status === "error" || d.status === "success") {
this.removeFileFromList(d);
} else if (d.percent < 100) {
this.$confirm(`${d.name}正在上传中,确定要取消吗?`, `提示`, {
dangerouslyUseHTMLString: true,
confirmButtonText: `确定`,
cancelButtonText: `取消`,
type: "warning",
})
.then(() => {
this.$emit(`stopUpload`, [d]);
this.$nextTick(() => {
this.removeFileFromList(d);
this.ifNoUploadingFile_EndCalcLiveSpeed();
});
})
.catch(() => {});
} else {
this.removeFileFromList(d);
}
},
//
close({ cb } = {}) {
let stopUploadList = this.uploadingFiles;
if (stopUploadList.length) {
this.$confirm(`您还有正在上传中的文件,确定要取消吗?`, `提示`, {
dangerouslyUseHTMLString: true,
confirmButtonText: `确定`,
cancelButtonText: `取消`,
type: "warning",
})
.then(() => {
this.show = false;
this.$emit(`stopUpload`, stopUploadList);
this.$nextTick(() => {
this.endUploadCalcLiveSpeed();
this.removeAllFilesFromList();
cb && cb(stopUploadList); //
});
})
.catch(() => {});
} else {
this.show = false;
}
},
},
};
</script>
<style lang="scss" scoped>
.sgUploadTray {
$headerHeight: 40px; //
$footerHeight: 40px; //
$collapseBtnHeight: 30px; //
$minWidth: var(--minWidth); //
$minHeight: var(--minHeight); //
$loadingWidth: 30px; //
$rightWidth: 200px; //
$sizeWidth: 200px; //
$progressWidth: 100px; //
$tipWidth: 100px; //
// ----------------------------------------
z-index: 2001; //(element)v-loading2000z-index
user-select: none;
position: fixed;
right: 10px;
bottom: 10px;
width: $minWidth;
background-color: white;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
border-radius: 4px;
overflow: hidden;
border: 1px solid #eee;
font-size: 14px;
display: none;
&[show] {
display: block;
}
&[size="lg"] {
left: 0 !important;
top: 0 !important;
width: 100vw;
height: 100vh;
transition: none;
.upload-file-list {
max-height: calc(100vh - 60px) !important;
}
}
&[size="md"] {
width: $minWidth;
height: revert;
}
&[size="mn"] {
width: $minWidth;
height: $minHeight;
}
.upload-list-tray {
display: flex;
flex-direction: column;
box-sizing: border-box;
padding-bottom: 20px;
width: 100%;
height: 100%;
position: relative;
.header {
flex-shrink: 0;
font-size: 16px;
font-weight: bold;
width: 100%;
height: $headerHeight;
box-sizing: border-box;
padding: 10px 20px;
/*从上往下线性渐变背景*/
background: linear-gradient(#409eff11, white);
color: #409eff;
display: flex;
justify-content: space-between;
align-items: center;
.left {
display: flex;
align-items: center;
flex-grow: 1;
.title {
display: flex;
align-items: center;
flex-wrap: nowrap;
.upload-info {
display: flex;
align-items: center;
color: black;
flex-shrink: 0;
align-items: center;
font-weight: normal;
.info-item {
margin-right: 5px;
&:last-of-type {
margin-right: 0;
}
span {
font-family: DIN-Light;
color: #409eff;
}
&.live-speed {
span {
font-family: DIN-Black;
}
}
}
}
}
.icon-btns {
display: flex;
align-items: center;
flex-wrap: nowrap;
.icon-btn {
cursor: pointer;
margin-right: 5px;
&:last-of-type {
margin-right: 0;
}
i {
pointer-events: none;
}
&:hover {
opacity: 0.618;
}
}
}
}
.right {
display: flex;
align-items: center;
justify-content: flex-end;
flex-shrink: 0;
pointer-events: auto;
.icon-btn {
margin-left: 10px;
cursor: pointer;
i {
pointer-events: none;
}
&:hover {
opacity: 0.618;
}
&:first-of-type {
margin-left: 0;
}
}
.file-btns {
margin-left: 10px;
display: flex;
flex-wrap: nowrap;
justify-content: flex-end;
box-sizing: border-box;
padding: 0 10px;
border-right: 1px solid #eee;
}
.tray-btns {
margin-left: 10px;
display: flex;
flex-wrap: nowrap;
justify-content: flex-end;
}
}
}
.upload-file-list {
width: 100%;
flex-grow: 1;
overflow-y: auto;
height: max-content;
max-height: calc(
100vh - #{$headerHeight} - #{$footerHeight} - #{$collapseBtnHeight} - 40px
);
box-sizing: border-box;
padding: 0 20px;
ul {
width: 100%;
li {
line-height: 1.6;
box-sizing: border-box;
padding: 10px;
border-radius: 4px;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
.left {
width: calc(100% - #{$rightWidth});
display: flex;
align-items: center;
flex-grow: 1;
flex-shrink: 0;
//
.icon-btns {
display: flex;
flex-wrap: nowrap;
.icon-btn {
display: none;
&[show] {
margin-right: 15px;
display: block;
}
}
}
.fileLoading {
flex-shrink: 0;
width: 30px;
margin-right: 5px;
height: 0;
transform: scale(0.5);
}
.loadingSuccessIcon,
.loadingEorrorIcon {
margin-right: 5px;
width: 30px;
height: 30px;
display: flex;
justify-content: center;
align-items: center;
flex-shrink: 0;
}
.name {
text-align: left;
margin-right: 10px;
width: calc(
100% - #{$loadingWidth} - #{$sizeWidth} - #{$progressWidth} - #{$rightWidth} -
20px
);
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
flex-shrink: 0;
flex-grow: 1;
}
.size {
margin-right: 10px;
max-width: $sizeWidth;
/*单行省略号*/
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
flex-shrink: 0;
}
.progress {
max-width: $progressWidth;
display: flex;
align-items: center;
flex-wrap: nowrap;
flex-shrink: 0;
}
}
.right {
display: flex;
align-items: center;
justify-content: flex-end;
width: $rightWidth;
.tip {
width: $tipWidth;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
flex-shrink: 0;
text-align: right;
&[color="red"] {
color: #f56c6c;
}
&[color="green"] {
color: #67c23a;
}
&[color="blue"] {
color: #409eff;
}
}
//
.icon-btns {
display: flex;
flex-wrap: nowrap;
.icon-btn {
display: none;
&[show] {
margin-left: 15px;
display: block;
}
}
}
}
&:hover {
background-color: #409eff11;
color: #409eff;
.left {
//
.icon-btns {
.icon-btn {
display: block;
&:last-of-type {
margin-right: 10px;
}
}
}
}
.right {
.tip {
margin-right: 15px;
}
//
.icon-btns {
.icon-btn {
display: block;
&:first-of-type {
margin-left: 0;
}
}
}
}
}
}
}
}
.footer {
font-weight: normal;
flex-shrink: 0;
font-size: 14px;
font-weight: bold;
width: 100%;
height: $footerHeight;
box-sizing: border-box;
padding: 10px 20px;
margin-bottom: -20px;
background: linear-gradient(white, #eff2f7);
color: #909399;
display: flex;
align-items: center;
flex-wrap: nowrap;
white-space: nowrap;
* {
font-weight: normal;
}
.text {
white-space: nowrap;
}
.progress {
max-width: 200px;
flex-grow: 1;
white-space: nowrap;
display: flex;
align-items: center;
flex-wrap: nowrap;
label {
white-space: nowrap;
flex-shrink: 0;
margin-right: 5px;
}
>>> .el-progress {
white-space: nowrap;
.el-progress__text {
font-weight: normal;
font-size: 14px !important;
}
}
}
}
}
}
</style>

View File

@ -0,0 +1,47 @@
<template>
<el-drawer
:wrapperClosable='false'
size="65%"
:modal="true"
:visible.sync="visible"
:show-close="false"
:append-to-body="true"
>
<template #title>
<span>流程监控</span>
<div class="drawer-head-btn">
<el-button @click="visible = false"><i class="el-icon-close"></i> 关闭</el-button>
</div><!--drawer-head-btn 抽屉顶部按钮区域-->
</template>
<div style="width:100%;height:100%">
<iframe :src="src" width="100%" height="100%" title="myFrame" style="border: 0;"></iframe>
</div>
</el-drawer>
</template>
<script>
import { getHistAskLogUrl } from "@/api/my_business/workflow";
export default {
data() {
return {
visible: false,
src: ''
};
},
methods: {
init(procInstId) {
this.visible = true
let protocol = window.location.protocol
let hostname = window.location.hostname;
let workflowManageUrl = protocol + '//' + hostname + ':9080' + process.env.VUE_APP_WORKFLOW_MANAGE_URL
workflowManageUrl = 'http://124.223.108.21:9080/ebpm-process-manage'
this.src = workflowManageUrl + '/workflow/trace/traceProcess.do?processInstanceId=' + procInstId
}
}
}
</script>
<style>
.el-drawer .el-drawer__body{
padding: 0px 0px !important;
}
</style>

View File

@ -0,0 +1,238 @@
<template>
<el-dialog
:close-on-click-modal="false"
title="预览文件"
:visible.sync="dialogVisible"
width="70%"
:destroy-on-close="true"
:append-to-body="true"
:close-on-press-escape="false"
@close="handleClose"
style="height: 100%"
>
<template v-if="isTxt">
<!-- 在文本框中预览文件内容 -->
<el-input type="textarea" :rows="30" v-model="resultContentObj" >
</el-input>
</template>
<template v-if="isDocx">
<vue-office-docx
:src="docxData"
style="height: 600px;"
@rendered="rendered"
/>
</template>
<template v-if="isPdf">
<vue-office-pdf
:src="pdfFileData"
style="height: 600px;"
@rendered="renderedHandler"
@error="errorHandler"
/>
</template>
<template v-if="isVideos">
<div class="input_video">
<video-player class="video-player vjs-custom-skin"
ref="videoPlayer"
:playsinline="true"
:options="playerOptions"
></video-player>
</div>
</template>
</el-dialog>
</template>
<script>
import axios from 'axios'
import {
getToken
} from "@/utils/auth";
import { videoPlayer } from "vue-video-player";
export default {
components: { videoPlayer},
props: {
uploadUrl: {
type: String,
required: false
},
//
isMultiple: {
type: Boolean,
default() {
return false
},
required: false
},
//
type: {
type: Array,
default() {
return []
},
required: false
},
//
acceptType: {
type: String,
required: false
},
//
limit: {
type: Number,
default() {
return 1
},
required: false
},
//
dataFile: {
type: [Object, Array, String],
default() {
return ''
},
required: false
},
isDetail: {
type: Boolean,
default: false
},
},
data() {
return {
// txt
dialogVisible:false,
isTxt:false,
resultContentObj:'',
// docx
isDocx:false,
docxData: null,
//pdf
isPdf:false,
pdfFileData: null, //
previewLoading:false,
previewUseFront: "txt,doc,docx,pdf",
isVideos:false,
//
playerOptions : {
playbackRates : [ 0.5, 1.0, 1.5, 2.0 ], //
autoplay : false, //true,
muted : false, //
loop : false, //
preload : 'auto', // <video>auto,
language : 'zh-CN',
aspectRatio : '16:9', // 使 - "16:9""4:3"
fluid : true, // trueVideo.js player
sources : [],
poster : "", //
// width: document.documentElement.clientWidth,
notSupportedMessage : '此视频暂无法播放,请稍后再试', //Video.js
controlBar : {
timeDivider : true,//
durationDisplay : true,//
remainingTimeDisplay : false,//
fullscreenToggle : true //
}
}
};
},
watch: {
},
methods: {
//
frontModulePreview(row){
let self = this
self.initPreviewData()
self.previewLoading = true
if(row.fileName.endsWith(".jpg") || row.fileName.endsWith(".png")){
this.$viewerApi({images: [row.fileUrl]})
self.previewLoading = false
self.$emit('previewLoadingClose')
return
}
if(row.fileName.endsWith(".mp4")){
this.playerOptions.sources = [
{
src: row.fileUrl,
type: 'video/mp4'
}
]
self.dialogVisible = true
self.isVideos = true;
self.previewLoading = false
self.$emit('previewLoadingClose')
return
}
axios({
method: 'post',
url: process.env.VUE_APP_BASE_API + "/common/preview/download",
responseType: 'blob',
data: {
'filePath': row.filePath,
'fileOldName': row.fileOldName
},
headers: { 'Authorization': 'Bearer ' + getToken() }
}).then(res => {
const content = res.data;
if(row.fileName.endsWith(".txt")){
self.dialogVisible = true
self.previewLoading = false
let blob = new Blob([res.data]);
blob.text().then(data =>{
self.resultContentObj = data;
self.isTxt = true;
self.previewLoading = false; //
self.$emit('previewLoadingClose')
})
// self.previewLoading = false
}else if (row.fileName.endsWith(".docx")) {
// renderAsync(response.data, self.$refs.file);
self.isDocx = true
self.dialogVisible = true; //
content.arrayBuffer().then(res=>{
self.docxData = res
})
self.previewLoading = false
self.$emit('previewLoadingClose')
}else if(row.fileName.endsWith(".doc") || row.fileName.endsWith(".pdf")){
self.isPdf = true
self.dialogVisible = true; //
content.arrayBuffer().then(res=>{
self.pdfFileData = res
})
self.previewLoading = false
self.$emit('previewLoadingClose')
}
}).catch(err => {
console.info("err===============", err)
self.previewLoading = false
self.$emit('previewLoadingClose')
});
},
//
initPreviewData(){
this.isTxt = false
this.isDocx = false
this.isPdf = false
this.resultcontentObj = ''
this.docxData = null
this.pdfFileData = null
},
rendered(){
console.log("渲染完成1")
},
renderedHandler(){
console.log("pdf渲染完成2")
},
errorHandler(){
console.log("pdf渲染失败3")
},
handleClose(){
this.$emit("previewClose");
}
}
};
</script>

View File

@ -0,0 +1,36 @@
<template>
<component :is="dashboard" ref="component" :data="data" :dataType="dataType" @close="close" style="padding: 16px 32px">
<slot></slot>
</component>
</template>
<script>
export default {
name: 'MainComponent',
props: ['code','data','dataType'],
data () {
return {
dashboard: null,
}
},
watch: {
code (val) {
this.init(val)
},
},
mounted () {
this.init(this.code)
},
methods: {
init (val) {
try {
if (val) {
this.dashboard = resolve => require(['@/' + val + '.vue'], resolve)
}
}catch (e) {}
},
close (value) {
this.$emit('close', value)
},
}
}
</script>

View File

@ -0,0 +1,189 @@
<template>
<el-dialog
title="工具选择"
:visible.sync="visible"
:close-on-click-modal="false"
width="80%"
append-to-body
:show-close="false"
>
<div class="el-card__body">
<el-form :model="queryParams" ref="queryForm" v-show="showSearch" label-width="68px" :inline="true">
<el-form-item label="工具编号" prop="toolCode">
<el-input
v-model.trim="queryParams.toolCode"
placeholder="请输入"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="工具名称" prop="toolName">
<el-input
v-model.trim="queryParams.toolName"
placeholder="请输入"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-card class="gray-card">
<el-table
v-loading="loading"
:data="dataList"
border
@selection-change="handleSelectionChange"
ref="multipleTable"
header-align="left"
>
<el-table-column type="selection" width="50" align="center" v-if="multiple" :selectable="(row,index)=>selectableFun(row,index,toolData,selectInfoData)"/>
<el-table-column label="工具编号" key="toolCode" prop="toolCode"/>
<el-table-column label="工具名称" key="toolName" prop="toolName":show-overflow-tooltip="true" />
<el-table-column label="工具类别" key="toolType" prop="toolType" :show-overflow-tooltip="true" >
<template slot-scope="scope">
<dict-tag :options="dict.type.tool_type" :value="scope.row.toolType"/>
</template>
</el-table-column>
<el-table-column label="归属单位" key="toolRespDeptName" prop="toolRespDeptName" :show-overflow-tooltip="true" />
<el-table-column label="负责人" key="toolPrincipalsName" prop="toolPrincipalsName" width="120" />
<el-table-column label="操作" v-if="!multiple" width="100px" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="selectHandle(scope.row)"
>选择</el-button>
</template>
</el-table-column>
</el-table>
</el-card>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
<div slot="footer" v-if="multiple">
<el-button @click="visible = false"> </el-button>
<el-button type="primary" @click="selectHandle(selectInfoData)"> </el-button>
</div>
</el-dialog>
</template>
<script>
import { listTool } from '@/api/tool/tool'
export default {
name: "ToolSelector",
components: {},
dicts:['tool_type'],
props: {
toolData: {
type: Array,
default: ()=>[],
},
selectableFun: {
type: Function,
default: (row, index, toolData, selectInfoData)=>{
if (toolData) {
return toolData.findIndex(item=>item.toolId===row.toolId)<0
}else {
return true
}
},
},
selectValidate:{
type: Boolean,
default: false,
}
},
data() {
return {
visible: false,
source: undefined,
index: undefined,
multiple: false,
//
loading: true,
//
ids: [],
//
single: true,
//
showSearch: true,
//
total: 0,
//
dataList: [],
//
title: "",
//
queryParams: {
pageNum: 1,
pageSize: 10,
toolCode: undefined,
toolName: undefined,
status: undefined,
recordStatus: 'done',
},
selectInfoData: [],
//ids
filterToolIds: [],
};
},
methods: {
//
init(source,index,multiple,ids){
this.filterToolIds = []
this.visible = true
this.source = source
this.index = index
this.multiple= multiple
this.filterToolIds = ids
this.resetQuery()
},
/** 查询列表 */
getList() {
this.loading = true;
if(this.filterToolIds && this.filterToolIds.length > 0){
this.$set(this.queryParams, "filterToolIds", this.filterToolIds )
}
listTool(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.dataList = response.rows;
this.total = response.total;
this.loading = false;
}
);
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm')
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.selectInfoData = selection;
},
selectHandle(data){
let _this = this
if (_this.selectValidate) {
this.$emit("selectHandle", this.source, this.index, data,(res)=>{_this.visible = !res})
}else{
this.$emit("selectHandle", this.source, this.index, data)
_this.visible = false
}
},
},
};
</script>

View File

@ -6,6 +6,9 @@
:width="width || '900px'"
:height="height || '650px'"
:before-close="handleClose"
:show-close="false"
:close-on-press-escape="false"
:close-on-click-modal="false"
append-to-body
>
@ -25,18 +28,6 @@
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="手机号码" prop="phonenumber">
<el-input
v-model="queryParams.phonenumber"
placeholder="请输入手机号码"
clearable
style="width: 200px"
size="mini"
@keyup.enter.native="getList"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="getList">搜索</el-button>
@ -177,6 +168,10 @@
open: {
type: Boolean,
default:false,
},
deptFilter: {
type: Boolean,
default:false,
}
// value: {
// type: Object,
@ -191,9 +186,7 @@
},
data() {
return {
loading: false,
// open: false,
activeName: 'first',
defaultProps: {
@ -204,7 +197,7 @@
deptOptions: undefined,
deptName: '',
showSearch: true,
userInfo: this.$store.getters.userInfo,
userList: [],
allUserList: [],
allUserMap: new Map(),
@ -240,11 +233,7 @@
},
methods: {
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
this.cancel();
})
.catch(_ => {});
this.cancel();
},
handleClick(tab, event) {
console.log(tab, event);
@ -276,15 +265,16 @@
return result;
},
submitForm() {
let checkedUserArr = []
let checkedUser = {}
this.checkedUsers.forEach(userName => {
checkedUser['userName'] = userName
checkedUser['userId'] = this.getUserIdByUserName(userName)
checkedUser['nickName'] = this.getNickNameByUserName(userName)
checkedUserArr.push(checkedUser)
})
this.$emit("submit", checkedUserArr); //usernamenickname
// let checkedUserArr = []
// let checkedUser = {}
// this.checkedUsers.forEach(userName => {
// checkedUser['userName'] = userName
// checkedUser['userId'] = this.getUserIdByUserName(userName)
// checkedUser['nickName'] = this.getNickNameByUserName(userName)
// checkedUserArr.push(checkedUser)
// })
// this.$emit("submit", checkedUserArr); //usernamenickname
this.$emit("submit", JSON.parse(JSON.stringify(this.selectedUserList)));
},
cancel() {
this.$emit('cancel');
@ -301,7 +291,8 @@
},
/** 查询部门下拉树结构 */
getDeptTree() {
deptTreeSelect().then(response => {
let deptId = this.deptFilter ? this.userInfo.dept.deptId : ''
deptTreeSelect({deptId: deptId}).then(response => {
this.deptOptions = response.data;
});
},
@ -309,18 +300,15 @@
// checkedUsers ['admin','ry']
getAllUserList(checkedUsers = []) {
//
listUser({pageNum: 1,pageSize: 2147483647,status: "0"}).then(response => {
let deptId = this.deptFilter ? this.userInfo.dept.deptId : ''
listUser({pageNum: 1, pageSize: 2147483647, status: "0", deptId: deptId}).then(response => {
this.allUserList = response.rows;
this.allUserMap = new Map();
this.checkedUsers = checkedUsers;
this.allUserList.forEach(item => {
this.allUserMap.set(item.userName, item);
});
this.updateCheckedUsers();
// console.log(this.allUserList, this.allUserMap);
this.getList();
}
);
@ -328,6 +316,7 @@
/** 查询用户列表 */
getList() {
this.queryParams.deptId = this.deptFilter ? this.userInfo.dept.deptId : ''
listUser(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.userList = response.rows;
// console.log(this.userList);

View File

@ -5,13 +5,55 @@
<breadcrumb id="breadcrumb-container" class="breadcrumb-container" v-if="!topNav"/>
<top-nav id="topmenu-container" class="topmenu-container" v-if="topNav"/>
<div class="right-menu">
<!--<template v-if="device!=='mobile'">
<search id="header-search" class="right-menu-item" />
<!-- <span @click="toMyCartPage">
<el-badge :value="totalCartCount >= 99 ? '99+' : totalCartCount" class="item">
<span class="top-msg">消息</span>
</el-badge>
</span>-->
<span class="top-version">v1.0.0</span>
<el-popover
placement="right"
width="400"
trigger="hover">
<el-table
:data="msgTableData"
border
style="width: 100%">
<el-table-column
prop="name"
label="消息通知类型">
</el-table-column>
<el-table-column
prop="count"
label="消息通知数量">
</el-table-column>
<el-table-column label="操作" width="100" >
<template slot-scope="scope">
<el-button type="text" @click="handleToMsgView(scope.row)">前往查看</el-button>
</template>
</el-table-column>
</el-table>
<span style="cursor: pointer;" @mouseover="toMyCartPage" slot="reference">
<template v-if="totalCartCount == 0">
<el-badge value="" class="item">
<el-tooltip class="item" effect="light" content="消息通知" placement="bottom">
<i class="el-icon-bell"></i>
</el-tooltip>
</el-badge>
</template>
<template v-else>
<el-badge :value="totalCartCount >= 99 ? '99+' : totalCartCount" class="item">
<el-tooltip class="item" effect="light" content="消息通知" placement="bottom">
<i class="el-icon-bell"></i>
</el-tooltip>
</el-badge>
</template>
</span>
</el-popover>
<screenfull id="screenfull" class="right-menu-item hover-effect" />
</template>-->
<el-dropdown class="avatar-container right-menu-item hover-effect" trigger="click">
<div class="avatar-wrapper">
<span style="font-size: 16px"><i class="el-icon-user"/> {{nickName}}</span>
@ -26,6 +68,7 @@
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
</div>
</template>
@ -37,6 +80,7 @@ import TopNav from '@/components/TopNav'
import Hamburger from '@/components/Hamburger'
import Screenfull from '@/components/Screenfull'
import Search from '@/components/HeaderSearch'
import { getUserMsgCount } from '@/api/my_business/workflow'
export default {
components: {
@ -68,6 +112,15 @@ export default {
get() {
return this.$store.state.settings.topNav
}
},
totalCartCount() {
return this.$store.state.user.unreadMsgNumber ? this.$store.state.user.unreadMsgNumber : 0
},
},
data() {
return {
msgVisible: false,
msgTableData: []
}
},
methods: {
@ -84,6 +137,32 @@ export default {
location.href = '/index';
})
}).catch(() => {});
},
//
toMyCartPage() {
getUserMsgCount().then(res => {
this.msgTableData = [];
let msgItem = {};
msgItem['type'] = 'msg';
msgItem['name'] = '消息中心数量';
msgItem['count'] = res.msgCount;
let taskItem = {};
taskItem['type'] = 'task';
taskItem['name'] = '待办消息数量';
taskItem['count'] = res.taskCount;
this.msgTableData.push(msgItem);
this.msgTableData.push(taskItem);
}).catch(error => {
})
this.msgVisible = true;
},
handleToMsgView(row){
this.msgVisible = false;
if(row.type === 'msg'){
this.$router.push({ path: '/message', query: {'states':'1'} })
} else {
this.$router.push({ path: '/workstuff/dispose'})
}
}
}
}

View File

@ -35,6 +35,7 @@ export default {
},
data() {
return {
// title: "",
title: process.env.VUE_APP_TITLE,
logo: logoImg
}

View File

@ -45,7 +45,7 @@ export default {
},
computed: {
visitedViews() {
return this.$store.state.tagsView.visitedViews
return this.$store.state.tagsView.visitedViews ? this.$store.state.tagsView.visitedViews : []
},
routes() {
return this.$store.state.permission.routes
@ -140,14 +140,15 @@ export default {
return false
},
moveToCurrentTag() {
let self = this
const tags = this.$refs.tag
this.$nextTick(() => {
self.$nextTick(() => {
for (const tag of tags) {
if (tag.to.path === this.$route.path) {
this.$refs.scrollPane.moveToTarget(tag)
self.$refs.scrollPane.moveToTarget(tag)
// when query is different then update
if (tag.to.fullPath !== this.$route.fullPath) {
this.$store.dispatch('tagsView/updateVisitedView', this.$route)
self.$store.dispatch('tagsView/updateVisitedView', self.$route)
}
break
}

View File

@ -8,6 +8,7 @@ import '../public/css/poctstyle.css'
import '../public/css/tool.css'
import '@/assets/styles/index.scss' // global css
import '@/assets/styles/ruoyi.scss' // ruoyi css
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import App from './App'
import store from './store'
import router from './router'
@ -38,6 +39,17 @@ import DictTag from '@/components/DictTag'
import VueMeta from 'vue-meta'
// 字典数据组件
import DictData from '@/components/DictData'
// 图形监控组件
import MonitorDrawer from "@/components/MonitorDrawer"
//引入VueOfficeDocx组件
import VueOfficeDocx from '@vue-office/docx'
//引入相关样式
import '@vue-office/docx/lib/index.css'
import VueOfficePdf from '@vue-office/pdf'
//视频组件
import 'video.js/dist/video-js.css'
import 'vue-video-player/src/custom-theme.css'
// 全局方法挂载
Vue.prototype.getDicts = getDicts
@ -49,6 +61,9 @@ Vue.prototype.selectDictLabel = selectDictLabel
Vue.prototype.selectDictLabels = selectDictLabels
Vue.prototype.download = download
Vue.prototype.handleTree = handleTree
import 'viewerjs/dist/viewer.css'
import Viewer from 'v-viewer'
// 全局组件挂载
Vue.component('DictTag', DictTag)
@ -58,7 +73,15 @@ Vue.component('Editor', Editor)
Vue.component('FileUpload', FileUpload)
Vue.component('ImageUpload', ImageUpload)
Vue.component('ImagePreview', ImagePreview)
Vue.component('MonitorDrawer', MonitorDrawer)
Vue.component('VueOfficeDocx', VueOfficeDocx)
Vue.component('VueOfficePdf', VueOfficePdf)
Vue.use(Viewer, {
defaultOptions: {
zIndex: 9999
}
})
Vue.use(directive)
Vue.use(plugins)
Vue.use(VueMeta)

View File

@ -8,7 +8,7 @@ import { isRelogin } from '@/utils/request'
NProgress.configure({ showSpinner: false })
const whiteList = ['/login', '/register']
const whiteList = ['/login', '/register', '/workflow/msg/count/']
router.beforeEach((to, from, next) => {
NProgress.start()
@ -37,6 +37,7 @@ router.beforeEach((to, from, next) => {
next({ path: '/' })
})
})
store.dispatch('GetUserMsgCount').then(() => { })
} else {
next()
}

View File

@ -9,7 +9,7 @@ const baseURL = process.env.VUE_APP_BASE_API
let downloadLoadingInstance;
export default {
name(name, isDelete = true) {
downloadByName(name, isDelete) {
var url = baseURL + "/common/download?fileName=" + encodeURIComponent(name) + "&delete=" + isDelete
axios({
method: 'get',

View File

@ -41,6 +41,12 @@ export const constantRoutes = [
}
]
},
{
// 统一流程处理前端页面(涉及待办、已办、办结)
path: '/workflowRouter',
component: (resolve) => require(['@/views/workflowList/workflowRouter.vue'], resolve),
hidden: true
},
{
path: '/login',
component: () => import('@/views/login'),

View File

@ -7,8 +7,11 @@ const getters = {
cachedViews: state => state.tagsView.cachedViews,
token: state => state.user.token,
avatar: state => state.user.avatar,
userId: state => state.user.id,
userInfo: state => state.user.info,
name: state => state.user.name,
nickName: state => state.user.nickName,
unreadMsgNumber: state => state.user.unreadMsgNumber,
introduction: state => state.user.introduction,
roles: state => state.user.roles,
permissions: state => state.user.permissions,

View File

@ -1,5 +1,6 @@
import { login, logout, getInfo } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { getUserMsgCount } from '@/api/my_business/workflow'
const user = {
state: {
@ -7,9 +8,11 @@ const user = {
id: '',
name: '',
nickName: '',
info: {},
avatar: '',
roles: [],
permissions: []
permissions: [],
unreadMsgNumber: 0,
},
mutations: {
@ -33,6 +36,12 @@ const user = {
},
SET_PERMISSIONS: (state, permissions) => {
state.permissions = permissions
},
SET_INFO:(state, info) => {
state.info = info
},
SET_UNREAD_MSG_NUMBER:(state, info) => {
state.unreadMsgNumber = info
}
},
@ -67,9 +76,12 @@ const user = {
commit('SET_ROLES', ['ROLE_DEFAULT'])
}
commit('SET_ID', user.userId)
commit('SET_UNREAD_MSG_NUMBER', res.unMsgNumber)
commit('SET_NAME', user.userName)
commit('SET_NICK_NAME', user.nickName)
commit('SET_AVATAR', avatar)
commit('SET_INFO', user)
resolve(res)
}).catch(error => {
reject(error)
@ -91,6 +103,16 @@ const user = {
})
})
},
GetUserMsgCount({ commit, state }) {
return new Promise((resolve, reject) => {
getUserMsgCount().then(res => {
commit('SET_UNREAD_MSG_NUMBER', res.totalMsgCount)
resolve()
}).catch(error => {
reject(error)
})
})
},
// 前端 登出
FedLogOut({ commit }) {

View File

@ -1,6 +1,6 @@
import Cookies from 'js-cookie'
const TokenKey = 'Admin-Token'
const TokenKey = 'Admin-Token-Tool'
export function getToken() {
return Cookies.get(TokenKey)

View File

@ -0,0 +1,58 @@
import docxtemplater from 'docxtemplater';
import PizZip from 'pizzip';
import JSZipUtils from 'jszip-utils';
import {saveAs} from 'file-saver';
/**
导出docx,导出word
@param { String } tempDocxPath 模板文件路径
@param { Object } data 文件中传入的数据
@param { String } fileName 导出文件名称
*/
export const exportDocx = (tempDocxPath, data, fileName) => {
// 读取并获得模板文件的二进制内容
JSZipUtils.getBinaryContent(tempDocxPath, (error, content) => {
// input.docx是模板。我们在导出的时候会根据此模板来导出对应的数据
// 抛出异常
if (error) {
throw error
}
// 创建一个JSZip实例内容为模板的内容
const zip = new PizZip(content)
// 创建并加载docxtemplater实例对象
const doc = new docxtemplater().loadZip(zip)
// 设置模板变量的值
doc.setData({
...data.form,
list: data.list
})
// 模板导出word,去除未定义值所显示的undefined
doc.setOptions({nullGetter: function() {
return "";
}}); // 设置角度解析器
try {
// render the document (replace all occurences of {first_name} by John, {last_name} by Doe, ...)
doc.render()
} catch (error) {
const e = {
message: error.message,
name: error.name,
stack: error.stack,
properties: error.properties
}
console.log({
error: e
})
// The error thrown here contains additional information when logged with JSON.stringify (it contains a property object).
throw error
}
const out = doc.getZip().generate({
type: 'blob',
mimeType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
}) // Output the document using Data-URI
saveAs(out, fileName)
})
}

View File

@ -17,7 +17,7 @@ const service = axios.create({
// axios中请求配置有baseURL选项表示请求URL公共部分
baseURL: process.env.VUE_APP_BASE_API,
// 超时
timeout: 10000
timeout: 200000
})
// request拦截器

View File

@ -0,0 +1,624 @@
<template>
<div class="fbox1">
<div class="fl" v-loading="detailLoading">
<el-tabs v-model="detailActiveName">
<el-tab-pane label="基本信息" name="first">
<div class="el-form-border">
<el-form ref="form" label-width="150px">
<el-row>
<el-col :span="24"> <el-form-item label="文件分类">{{form.docCategoryName}}</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="文档编号">{{form.docCode}}</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="文档名称">{{form.docName}}</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="文档类别"><dict-tag :options="dict.type.doc_class" :value="form.docType"/></el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="文档来源"><dict-tag :options="dict.type.doc_source" :value="form.docSource"/></el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="负责人">{{form.docPrincipalsName}}</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="归属单位">{{form.docRespDeptName}}</el-form-item> </el-col>
<el-col :span="24"> <el-form-item label="备注">{{form.remark}}</el-form-item> </el-col>
</el-row>
</el-form><!--el-form-->
</div><!--el-form-border 表单-->
</el-tab-pane><!--el-tab-pane-->
<el-tab-pane label="关联附件" name="second" v-loading="previewLoading" element-loading-text="预览转换中,请耐心等待">
<el-table :data="attachmentList" style="width: 100%">
<el-table-column label="序号" width="60" type="index" align="center"></el-table-column>
<el-table-column label="附件名称" prop="fileName" :show-overflow-tooltip="true" />
<el-table-column label="操作" align="center" width="150px">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
v-if="previewAuth(scope.row)"
@click="handlePreview(scope.row)"
>预览</el-button>
<el-button type="text" icon="el-icon-download" v-if="form.downloadStatus"
@click="handleDownload(scope.row)" v-loading="loadingDownload">下载</el-button>
</template>
</el-table-column>
</el-table><!--el-table-->
<!-- 分页组件 -->
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getAttachmentList"
/>
</el-tab-pane><!--el-tab-pane-->
</el-tabs><!--el-tabs-->
</div><!--fl 左侧页签-->
<div class="fr" v-if="isComment && form.docStatus == 'yfb'">
<div class="tboper">
<div class="tit">评论{{ reviewTotal }}</div>
</div><!--tboper 标题与操作按钮-->
<div class="pltextarea">
<el-input v-model="discussionContent" type="textarea" placeholder="请输入您的意见" :rows="4" maxlength="1000" show-word-limit></el-input>
<div class="plbtn"><el-button @click="handleDiscussions">发布</el-button></div>
</div><!--pltextarea-->
<div class="pllist">
<template v-if="discussionsList && discussionsList.length > 0">
<div class="list" v-for="(item,index) in discussionsList" :key="item.id">
<div class="luser"><span class="xuser" :style="{backgroundColor: extractColorByName(item.nickName)}">{{getFirstChar(item.nickName)}}</span></div>
<div class="ltext">
<div class="nt"><span class="name">{{item.nickName}}</span><span class="time">{{ parseTime(item.createTime, '{y}-{m}-{d} {h}:{i}') }}</span></div>
<div class="te">{{item.content}}</div>
<div class="hb">
<a class="btn" @click="toggleReplyForm(index)">
<i class="el-icon-chat-line-round"></i>回复
</a>
</div>
<div class="pltextarea" v-if="showReplyForm[index]">
<el-input type="textarea" v-model="replyContent[index]" placeholder="请输入您的意见" :rows="2" maxlength="1000" show-word-limit></el-input>
<div class="plbtn">
<el-button @click="cancelReply(index)">取消</el-button>
<el-divider direction="vertical"></el-divider>
<el-button @click="submitReply(index, item)">发布</el-button>
</div>
</div>
<!--第二层级-->
<template v-if="item.repliesList && item.repliesList.length > 0">
<div class="list" v-for="(repItem,repIdex) in item.repliesList" :key="repItem.id">
<div class="luser">
<span class="xuser" :style="{width:'28px',height:'28px',lineHeight:'28px',backgroundColor: extractColorByName(repItem.nickName)}">{{getFirstChar(repItem.nickName)}}</span>
</div>
<div class="ltext">
<div class="nt">
<span class="name">{{repItem.nickName}}</span>
<template v-if="repItem.repTargetNickName">
<span>回复</span>
<span class="name">{{ repItem.repTargetNickName }}</span>
</template>
<span class="time">{{ parseTime(repItem.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
</div>
<div class="te">{{repItem.content}}</div>
<div class="hb"><a class="btn" @click="toggleReplyFormSon(index,repIdex)"><i class="el-icon-chat-line-round"></i>回复</a></div>
<div class="pltextarea" v-if="item.showReplyFormSon[repIdex]">
<el-input type="textarea" v-model="item.replyContentSon[repIdex]" placeholder="请输入您的意见" :rows="2" maxlength="1000" show-word-limit></el-input>
<div class="plbtn">
<el-button @click="cancelReplySon(index,repIdex)">取消</el-button>
<el-divider direction="vertical"></el-divider>
<el-button @click="submitReplySon(index, repIdex, item, repItem.id)">发布</el-button>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</template>
</div>
</div>
<preview-util v-if="isPreviewDisable" ref="previewForm" @previewClose="previewClose" @previewLoadingClose="previewLoadingClose"></preview-util>
</div><!--el-form-border 表单-->
</template>
<script>
import { addDocument, updateDocument, getDocument } from "@/api/document/document";
import { deptTreeSelect } from "@/api/system/user";
import { documentTree } from "@/api/documentCategory/documentCategory.js";
import { listReplies, addReplies} from "@/api/tool/replies.js";
import { listAttachment } from "@/api/attachment/attachment";
import { addCount } from "@/api/tool/downloadCount";
import previewUtil from '@/components/PreviewUtil/previewUtil.vue'
import { listDiscussions, addDiscussions } from "@/api/tool/discussions.js";
export default {
name: 'editDocument',
components: {previewUtil},
dicts:['doc_class','doc_source'],
props: {
tooId: {
type: String,
default: "",
required: false
},
relatedTool: {
type: Boolean,
default: true,
},
//
isDownload: {
type: Boolean,
default() {
return true
},
required: false
},
//
isComment: {
type: Boolean,
default() {
return true
},
required: false
},
},
data(){
return{
detailActiveName: 'first',
templateSelection: '',
drawer1: false,
reviewTotal: 0,
checkList: [],
//
form: {
docId: undefined,
docCategoryId: undefined,
docCode: '',
docName: '',
docType: '',
docPrincipals: null,
docPrincipalsName: null,
docRespDept: this.$store.getters.userInfo.deptId,
docSource: '',
toolId: '',
remark: undefined,
docCategoryName: undefined,
},
fileList: [],
progress: 0,
//
rules: {
},
docCategory:[],
deptOptions:[],
uploadFileUrl: process.env.VUE_APP_BASE_API + "/common/upload", //
fileData: null,
editStatus: true,
toolDataInfo: [],
dataFile: [],
//
detailBoolean: false,
discussionContent: null, //
repliesContent: null, //
//
discussionsList: [],
//
repliesList: [],
showReplyForm: [],
replyContent: [],
detailLoading: false,
attachmentList: [],
attFileType: "zip,rar,7z",
isPreviewDisable: false,
loadingDownload: false,
userInfo: this.$store.getters.userInfo,
toolPrincipalsChoose: false,
docQueryParams: {
pageNum: 1,
pageSize: 10,
},
queryParams: {
pageNum: 1,
pageSize: 10,
},
total: 0,
previewLoading: false,
}
},
computed: {
},
created(){
// this.getDeptTree();
this.getDocumentTree();
this.getDiscussionsList()
},
mounted(){
},
methods:{
chooseToolConfirm(){
this.$set(this.form, "toolId", this.templateSelection)
this.drawer1 = false;
},
getCurrentRow(row){
// row
},
showOpenHandle(){
this.reset();
this.title = "上传文档";
},
//
reset() {
this.form = {
docName: '',
docType: '',
docPrincipals: '',
docRespDept: '',
docSource: '',
toolId: ''
};
this.fileList = []
this.resetForm("form");
},
//
cancel() {
this.drawer1 = false;
this.reset();
},
generateUniqueID() {
// 使ID
const timestamp = new Date().getTime();
// IDID
const uniqueID = 'file_' + timestamp;
return uniqueID;
},
/** 查询部门下拉树结构 */
getDeptTree() {
deptTreeSelect().then(response => {
this.deptOptions = response.data;
});
},
/** 查询树形下拉树结构 */
getDocumentTree() {
documentTree().then(res => {
this.docCategory = res.data;
});
},
/**初始化 **/
resetForm() {
let self = this
self.form.docPrincipalsName = null
this.$refs.form.resetFields();
this.toolDataInfo = []
this.fileList = []
this.attachmentList = []
this.detailBoolean = false
this.setAllRequiredTrue(true)
this.$nextTick(()=>{
if(self.$refs.uploadFile){
self.$refs.uploadFile.clearFile();
}
})
},
editInit(docId, type){
let self = this
if(type == "detail"){
this.detailBoolean = true
self.setAllRequiredTrue(false)
}
self.$refs.form.resetFields();
self.toolDataInfo = []
self.$nextTick(()=>{
if(self.$refs.uploadFile){
self.$refs.uploadFile.clearFile();
}
getDocument(docId).then(res => {
self.form = res.data
self.toolDataInfo = []
let toolInfo = {toolId:self.form.toolId,toolName:self.form.toolName}
self.toolDataInfo.push(toolInfo)
self.dataFile = []
/* let fileData = res.data.attachment
self.$set(fileData, "name", fileData.fileOldName)
self.$set(fileData, "size", fileData.fileSize)
self.dataFile.push(fileData) */
self.getAttachmentList()
self.getDiscussionsList()
setTimeout(() => {
self.$set(self.form, "docCategoryName" , self.findLabelById(self.docCategory, self.form.docCategoryId) )
}, 300);
});
})
},
/** 评论 **/
handleDiscussions(){
let self = this
if (this.discussionContent == '' || this.discussionContent == null || this.discussionContent == undefined) {
self.$message({
message: '内容不能为空',//
type:'warning',  //
duration:1200,  //, 0 1200
});
return;
}
let data = {
businessId: this.form.docId,
content: this.discussionContent,
type: "doc",
}
self.$modal.confirm('是否确认发布?').then(()=> {
addDiscussions(data).then(res => {
this.discussionContent = null
self.$message({
message: '发布成功',//
type:'success',  //
duration:1200,  //, 0 1200
});
self.getDiscussionsList()
}).catch(err =>{
this.discussionContent = null
console.error("handleDiscussions==err==", err)
self.$modal.msgError("发布失败");
});
})
},
getAttachmentList() {
let self = this
this.$set(this.queryParams,'del',"0")
this.$set(this.queryParams,'businessId',this.form.docId)
listAttachment(this.queryParams).then(res => {
self.attachmentList = res.rows;
self.total = res.total;
self.loading = false;
});
},
getFirstChar(value) {
if(!value){return ''}
return value.charAt(0);
},
toggleReplyForm(index) {
this.$set(this.showReplyForm, index, !this.showReplyForm[index]);
},
cancelReply(index) {
this.$set(this.showReplyForm, index, false);
this.$set(this.replyContent, index, '');
},
extractColorByName(name) {
let temp = [];
temp.push("#");
for (let index = 0; index < name.length; index++) {
temp.push(parseInt(name[index].charCodeAt(0), 10).toString(16));
}
return temp.slice(0, 5).join('').slice(0, 4);
},
/** 第二级 **/
toggleReplyFormSon(parentIndex, repIndex) {
const parentItem = this.discussionsList[parentIndex];
this.$set(parentItem.showReplyFormSon, repIndex, !parentItem.showReplyFormSon[repIndex]);
// this.$set(this.showReplyFormSon, index, !this.showReplyFormSon[index]);
},
/** 第二级,取消回复 **/
cancelReplySon(parentIndex, repIndex) {
const parentItem = this.discussionsList[parentIndex];
this.$set(parentItem.showReplyFormSon, repIndex, false);
this.$set(parentItem.replyContentSon, repIndex, '');
},
/** 第二级回复 **/
submitReplySon(parentIndex, repIndex, repItem, repId) {
let self = this
const parentItem = this.discussionsList[parentIndex];
const content = parentItem.replyContentSon[repIndex];
if (content.trim() == '' || content == null || content == undefined) {
self.$message({
message: '回复内容不能为空',//
type:'warning',  //
duration:1200,  //, 0 1200
});
return;
}
let data = {
"discussionId": repItem.id,
"repId": repId,
"content": content,
}
self.$modal.confirm('是否确认发布?').then(()=> {
addReplies(data).then(res => {
self.$message({
message: '发布成功',//
type:'success',  //
duration:1200,  //, 0 1200
});
self.cancelReplySon(parentIndex, repIndex)
self.getDiscussionsList()
//
this.$set(parentItem.replyContentSon, repIndex, '');
this.$set(parentItem.showReplyFormSon, repIndex, false);
}).catch(err =>{
console.error("submitReplySon==err==", err)
self.$modal.msgError("发布失败");
});
})
},
/** 回复 **/
submitReply(index, item) {
let self = this
const content = this.replyContent[index];
if (content == '' || content == null || content == undefined) {
self.$message({
message: '回复内容不能为空',//
type:'warning',  //
duration:1200,  //, 0 1200
});
return;
}
let data = {
"discussionId": item.id,
"content": content,
}
self.$modal.confirm('是否确认发布?').then(()=> {
addReplies(data).then(res => {
self.$message({
message: '发布成功',//
type:'success',  //
duration:1200,  //, 0 1200
});
self.cancelReply(index)
self.getDiscussionsList()
}).catch(err =>{
console.error("handleDiscussions==err==", err)
self.$modal.msgError("发布失败");
});
})
//
this.replyContent[index] = '';
this.showReplyForm[index] = false;
},
previewAuth(row){
if(row.fileUrl == null || row.fileUrl == '' || row.fileUrl == undefined){
return false
}
let extension = this.getExtension(row.fileUrl);
const acceptedExtensions = this.attFileType.toLowerCase().split(',');
if(acceptedExtensions.includes(extension)){
return false
}
return true
},
getExtension(filePath) {
// '.'
const parts = filePath.split('.');
//
const extension = parts.pop();
return extension;
},
handlePreview(row){
this.isPreviewDisable = true
this.previewLoading = true
this.$nextTick(() => {
this.$refs.previewForm.frontModulePreview(row)
})
},
/** 关闭预览 **/
previewClose(){
this.isPreviewDisable = false
},
/** 关闭预览遮罩 **/
previewLoadingClose(){
this.previewLoading = false
},
/**
* 处理下载
* **/
handleDownload(row){
let self = this
self.loadingDownload = true
this.$download.resource(row.fileUrl);
//
if(row.businessId){
let formData = {
'businessId': row.businessId,
'businessType': 'doc',
'attId': row.id,
'attName': row.fileOldName
}
addCount(formData).then(res => {
});
}
setTimeout(()=>{
self.loadingDownload = false
},1000)
},
handleDelete(row){
const index = this.attachmentList.findIndex(item => item.fileNewName == row.fileNewName);
if (index !== -1) {
// attachmentList
this.attachmentList.splice(index, 1);
//
if (this.paginatedData.length === 0 && this.currentPage > 1) {
this.currentPage--;
}
}
// this.attachmentList.splice(row,1)
},
handleBeforeClose() {
this.viewDialogOpen = false
},
handleUploadSuccess(res) {
this.attachmentList.push(res)
//
},
handleUploadError(error) {
//
},
isShowOperation(row){
let self = this
if(row.businessId == null || row.businessId == undefined || row.businessId == ''){
return false
}
return true
},
submitPeople(peopleList){
this.$set(this.form,'docPrincipals',peopleList[0]['userId'])
this.$set(this.form,'docPrincipalsName',peopleList[0]['nickName'])
this.toolPrincipalsChoose = false;
},
setAllRequiredTrue(value) {
Object.keys(this.rules).forEach(key => {
this.rules[key].forEach(rule => {
rule.required = value;
});
});
},
handlePageChange(newPage) {
this.currentPage = newPage;
},
//
findLabelById(treeData, id) {
for (let i = 0; i < treeData.length; i++) {
let item = treeData[i];
if (item.id == id) {
return item.label;
}
if (item.children && item.children.length) {
const label = this.findLabelById(item.children, id);
if (label) {
return label;
}
}
}
return null;
},
getDiscussionsList() {
let _this = this
_this.reviewTotal = 0
listDiscussions({businessId:_this.form.docId}).then(res => {
_this.discussionsList = res.rows
let reviewTotal = 0
_this.discussionsList.forEach(item => {
if(item.repliesList && item.repliesList.length > 0){
reviewTotal += item.repliesList.length
_this.$set(item, 'showReplyFormSon', new Array(item.repliesList.length).fill(false))
_this.$set(item, 'replyContentSon', new Array(item.repliesList.length).fill(''))
}else{
_this.$set(item, 'showReplyFormSon', false)
_this.$set(item, 'replyContentSon', '')
}
});
_this.reviewTotal = _this.discussionsList.length + reviewTotal
});
},
}
}
</script>
<style scoped>
</style>

View File

@ -0,0 +1,164 @@
<template>
<div class="fbox1">
<div class="fl">
<el-tabs v-model="detailActiveName">
<el-tab-pane label="附件信息" name="first" v-loading="previewLoading" element-loading-text="预览转换中,请耐心等待">
<el-table :data="attachmentList" style="width: 100%">
<el-table-column label="序号" width="60" align="center" type="index"></el-table-column>
<el-table-column label="附件名称" prop="fileName" :show-overflow-tooltip="true" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createDate) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="180" v-if="docDetail.downloadStatus">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handlePreview(scope.row)"
>预览</el-button>
<el-button type="text" icon="el-icon-download" @click="handleDownload(scope.row)" v-loading="loadingDownload">下载</el-button>
</template>
</el-table-column>
</el-table><!--el-table-->
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getAttachmentList"
/>
</el-tab-pane><!--el-tab-pane-->
</el-tabs><!--el-tabs-->
</div><!--fl 左侧页签-->
<preview-util v-if="isPreviewDisable" ref="previewForm" @previewClose="previewClose" @previewLoadingClose="previewLoadingClose"></preview-util>
</div><!--fbox1 左右分栏-->
</template>
<script>
import previewUtil from '@/components/PreviewUtil/previewUtil.vue'
import { listAttachment } from "@/api/attachment/attachment";
import { addCount } from "@/api/tool/downloadCount";
export default {
name: 'docDetailFile',
components: { previewUtil},
dicts:[],
props: {
docDetail: {
type: Object,
default: {},
}
},
data(){
return{
detailActiveName: 'first',
attachmentList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
docId: ''
},
previewUrl: '',
viewDialogTitle: "",
viewDialogOpen: false,
open: false,
loadingDownload: false,
discussionContent: null, //
repliesContent: null, //
//
discussionsList: [],
//
repliesList: [],
showReplyForm: [],
replyContent: [],
isPreviewDisable: false,
attFileType: "zip,rar,7z",
total: 0,
previewLoading: false,
}
},
created(){
this.previewLoading = false
this.getAttachmentList()
},
methods:{
getAttachmentList() {
this.loading = true;
this.$set(this.queryParams,'del',"0")
this.$set(this.queryParams,'businessId',this.docDetail.docId)
listAttachment(this.queryParams).then(response => {
this.attachmentList = response.rows;
this.total = response.total;
this.loading = false;
}
);
},
handlePreview(row){
this.isPreviewDisable = true
this.previewLoading = true
this.$nextTick(() => {
this.$refs.previewForm.frontModulePreview(row)
})
},
/** 关闭预览 **/
previewClose(){
this.isPreviewDisable = false
},
/** 关闭预览遮罩 **/
previewLoadingClose(){
this.previewLoading = false
},
previewAuth(row){
if(row.fileUrl == null || row.fileUrl == '' || row.fileUrl == undefined){
return false
}
let extension = this.getExtension(row.fileUrl);
const acceptedExtensions = this.attFileType.toLowerCase().split(',');
if(acceptedExtensions.includes(extension)){
return false
}
return true
},
getExtension(filePath) {
// '.'
const parts = filePath.split('.');
//
const extension = parts.pop();
return extension;
},
/**
* 处理下载
* **/
handleDownload(row){
let self = this
self.loadingDownload = true
this.$download.resource(row.fileUrl);
//
if(row.businessId){
let formData = {
'businessId': row.businessId,
'businessType': 'doc',
'attId': row.id,
'attName': row.fileOldName
}
addCount(formData).then(res => {
});
}
setTimeout(()=>{
self.loadingDownload = false
},1000)
},
}
}
</script>
<style scoped>
</style>

View File

@ -1,133 +1,294 @@
<template>
<div class="el-form-border">
<el-form ref="form" :model="form" :rules="rules" label-width="150px">
<el-row>
<el-col :span="24">
<el-form-item label="文件分类" prop="docCode">
<treeselect v-model="form.categoryId" :options="docCategory" :show-count="true" placeholder="请选择文件分类"/>
</el-form-item>
</el-col>
<div class="fbox1">
<div class="fl">
<div class="el-form-border">
<el-form ref="form" :model="form" :rules="rules" label-width="150px">
<el-row>
<el-col :span="24">
<el-form-item label="文件分类" prop="docCategoryId">
<treeselect v-model="form.docCategoryId" :options="docCategory" :show-count="true" @input="inputSelect"
:disabled="detailBoolean"
placeholder="请选择文件分类"/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="文档编号" prop="docCode">
<el-input v-model="form.docCode" placeholder="请输入文档编号" maxlength="50" show-word-limit/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="文档编号" prop="docCode">
<template v-if="detailBoolean">{{form.docCode}}</template>
<template v-else>
<el-input v-model="form.docCode" placeholder="请输入文档编号" maxlength="50" show-word-limit/>
</template>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="文档名称" prop="docName">
<el-input v-model="form.docName" placeholder="请输入文档名称" maxlength="200" show-word-limit/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="文档名称" prop="docName">
<template v-if="detailBoolean">{{form.docName}}</template>
<template v-else>
<el-input v-model="form.docName" placeholder="请输入文档名称" maxlength="200" show-word-limit/>
</template>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="文档类别" prop="docType">
<el-input v-model="form.docType" placeholder="请输入文档类别" maxlength="50" show-word-limit/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="文档类别" prop="docType" style="width: 100%">
<el-select v-model="form.docType" placeholder="请选择文档来源" style="width: 100% !important;"
:disabled="detailBoolean">
<el-option style="width: 100%"
v-for="dict in dict.type.doc_class"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="文档来源" prop="docSource">
<el-input v-model="form.docSource" placeholder="请输入文档来源" maxlength="50" show-word-limit/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="关联工具" prop="toolId">
<el-input v-model="form.toolId" placeholder="请选择关联工具" @focus="drawer1 = true"/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="负责人" prop="docPrincipals">
<el-input v-model="form.docPrincipals" placeholder="请输入负责人" maxlength="50" show-word-limit/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="归属单位" prop="docRespDept">
<treeselect v-model="form.docRespDept" :options="deptOptions" :show-count="true" placeholder="请输入归属单位" />
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="文件" required>
<el-col :span="24">
<el-form-item label="文档来源" prop="docSource">
<el-select v-model="form.docSource" placeholder="请选择文档来源" style="width: 100%" :disabled="detailBoolean">
<el-option
v-for="dict in dict.type.doc_source"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
<!-- <el-input v-model="form.docSource" placeholder="请输入文档来源" maxlength="50" show-word-limit/>-->
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="负责人" prop="docPrincipals">
<template v-if="detailBoolean">{{form.docPrincipalsName}}</template>
<template v-else>
<el-input v-model="form.docPrincipalsName" placeholder="请选择负责人" maxlength="11" @focus="toolPrincipalsChoose = true"/>
<!-- <el-input v-model="form.docPrincipals" placeholder="请输入负责人" maxlength="50" show-word-limit/>-->
</template>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="归属单位" prop="docRespDept">
{{userInfo.dept.deptName}}
<!-- <treeselect v-model="form.docRespDept" :options="deptOptions" :show-count="true"
:disabled="detailBoolean" placeholder="请输入归属单位"/>-->
</el-form-item>
</el-col>
<!-- <el-col :span="24" v-if="relatedTool">
<el-form-item label="关联工具" prop="toolId">
<el-select
v-model="toolDataInfo"
ref="selectHeadTool"
multiple
value-key="toolId"
filterable
remote
placeholder="请选择关联工具"
:disabled="detailBoolean"
@focus="toolSelect">
<el-option
v-for="item in toolDataInfo"
:key="item.toolId"
:label="item.toolName"
:value="item">
</el-option>
</el-select>
</el-form-item>
</el-col>-->
<!-- <el-col :span="24">
<el-form-item label="文件" required>
<uploadVue
:display="editStatus"
:uploadUrl="uploadFileUrl"
:type="['.txt','.doc','.docx','.pdf','.mp4','.zip','.rar','.7z','.png','.jpg','.jpeg']"
:acceptType="acceptType"
:limit="1"
:dataFile="dataFile"
:isDetail="detailBoolean"
ref="uploadFile"
@handleSuccess="handleUploadSuccess"
@handleError="handleUploadError"
/>
</el-form-item>
</el-col>-->
<el-col :span="24">
<el-form-item label="备注" prop="remark">
<template v-if="detailBoolean">{{form.remark}}</template>
<template v-else>
<el-input v-model="form.remark" type="textarea" :rows="3" maxlength="500" show-word-limit></el-input>
</template>
</el-form-item>
</el-col>
</el-row>
</el-form><!--el-form-->
</div>
<div class="divide double"></div><!--divide 分隔-->
<div class="tboper">
<div class="tit">关联附件</div>
</div>
<div class="el-form-border" v-loading="previewLoading" element-loading-text="预览转换中,请耐心等待">
<div class="operate">
<template v-if="editStatus && !detailBoolean">
<uploadVue
:display="editStatus"
:uploadUrl="uploadFileUrl"
:type="['.txt','.doc','.docx','.pdf','.mp4','.zip','.rar','.7z','.png','.jpg','.jpeg']"
:acceptType="acceptType"
:limit="1"
:onSuccess="handleUploadSuccess"
:onError="handleUploadError"
:isMultiple="true"
:dataFile="dataFile"
:isDetail="detailBoolean"
ref="uploadFile"
@handleSuccess="handleUploadSuccess"
@handleError="handleUploadError"
/>
<!-- <uploadVue-->
<!-- <upload-progress/>
<el-upload
class="upload-component"
ref="upload"
:auto-upload="false"
:file-list="fileList"
:on-change="onChange"
:on-remove="onRemove"
:multiple="true"
action=""
>
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件且不超过500kb</div>
<div slot="tip" class="el-upload__tip"><el-progress :percentage="progress"></el-progress></div>
</el-upload>-->
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">
<el-input v-model="form.remark" type="textarea" :rows="3" maxlength="500" show-word-limit></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form><!--el-form-->
<el-dialog title="选择关联工具" :visible.sync="drawer1" width="75%" append-to-body>
<div>
<el-table :data="tableData2" @row-click="singleElection" highlight-current-row style="width: 100%">
<!--<el-table-column label="选择" align="center" width="65">
</template>
<!-- <el-button icon="el-icon-delete">删除</el-button>-->
</div><!--operate 操作按钮-->
<el-table :data="paginatedData" style="width: 100%">
<!-- <el-table-column type="selection" width="50" align="center"> </el-table-column>-->
<el-table-column label="序号" width="60" type="index" align="center"></el-table-column>
<el-table-column label="附件名称" prop="fileName" :show-overflow-tooltip="true" />
<el-table-column label="操作" align="center" width="180" v-if="!detailBoolean">
<template slot-scope="scope">
<el-radio :label="scope.row.prop1" v-model="radio" @change.native="getCurrentRow(scope.row)" />
</template>
</el-table-column>-->
<el-table-column align="center" width="55">
<template slot-scope="scope">
<el-radio v-model="templateSelection" :label="scope.row.prop1"></el-radio>
<el-button
size="mini"
type="text"
icon="el-icon-view"
v-if="previewAuth(scope.row)"
@click="handlePreview(scope.row)"
>预览</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
v-if="editStatus"
@click="handleDelete(scope.row)"
>删除</el-button>
<el-button type="text" icon="el-icon-download" v-if="isShowOperation(scope.row)"
@click="handleDownload(scope.row)" v-loading="loadingDownload">下载</el-button>
</template>
</el-table-column>
<el-table-column prop="prop1" label="工具编号"></el-table-column>
<el-table-column prop="prop2" label="工具名称"></el-table-column>
<el-table-column prop="prop5" label="工具类别" ></el-table-column>
<el-table-column prop="prop3" label="归属单位" width="180"> </el-table-column>
<el-table-column prop="prop4" label="负责人" width="100" ></el-table-column>
</el-table><!--el-table-->
<!-- 分页组件 -->
<el-pagination
v-show="total > 0"
:current-page.sync="currentPage"
:page-size.sync="pageSize"
:total="total"
@current-change="handlePageChange"
layout="total, prev, pager, next"
/>
</div>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="chooseToolConfirm()"> </el-button>
<el-button @click="cancel()"> </el-button>
</div><!--fl 左侧页签-->
<div class="fr" v-if="detailBoolean && isComment">
<div class="tboper">
<div class="tit">评论</div>
</div><!--tboper 标题与操作按钮-->
<div class="pltextarea">
<el-input v-model="discussionContent" type="textarea" placeholder="请输入您的意见" :rows="4" maxlength="1000" show-word-limit></el-input>
<div class="plbtn"><el-button @click="handleDiscussions">发布</el-button></div>
</div><!--pltextarea-->
<div class="pllist">
<template v-if="discussionsList && discussionsList.length > 0">
<div class="list" v-for="(item,index) in discussionsList" :key="item.id">
<div class="luser"><span class="xuser">{{getFirstChar(item.nickName)}}</span></div>
<div class="ltext">
<div class="nt"><span class="name">{{item.nickName}}</span><span class="time">{{ parseTime(item.createTime, '{y}-{m}-{d} {h}:{i}') }}</span></div>
<div class="te">{{item.content}}</div>
<div class="hb">
<a class="btn" @click="toggleReplyForm(index)">
<i class="el-icon-chat-line-round"></i>回复
</a>
</div>
<div class="pltextarea" v-if="showReplyForm[index]">
<el-input type="textarea" v-model="replyContent[index]" placeholder="请输入您的意见" :rows="2" maxlength="1000" show-word-limit></el-input>
<div class="plbtn">
<el-button @click="cancelReply(index)">取消</el-button>
<el-divider direction="vertical"></el-divider>
<el-button @click="submitReply(index, item)">发布</el-button>
</div>
</div>
<!--第二层级-->
<template v-if="item.repliesList && item.repliesList.length > 0">
<div class="list" v-for="(repItem,repIdex) in item.repliesList" :key="repItem.id">
<div class="luser"><span class="xuser">{{getFirstChar(repItem.nickName)}}</span></div>
<div class="ltext">
<div class="nt"><span class="name">{{repItem.nickName}}</span><span class="time">{{ parseTime(repItem.createTime, '{y}-{m}-{d} {h}:{i}') }}</span></div>
<div class="te">{{repItem.content}}</div>
<!-- <div class="hb"><a class="btn" @click="toggleReplyFormSon(index,repIdex)"><i class="el-icon-chat-line-round"></i>回复</a></div>
<div class="pltextarea" v-if="item.showReplyFormSon[repIdex]">
<el-input type="textarea" v-model="item.replyContentSon[repIdex]" placeholder="请输入您的意见" :rows="2" maxlength="1000" show-word-limit></el-input>
<div class="plbtn">
<el-button @click="cancelReplySon(index,repIdex)">取消</el-button>
<el-divider direction="vertical"></el-divider>
<el-button @click="submitReplySon(index,repIdex, item)">发布</el-button>
</div>
</div>-->
</div>
</div>
</template>
</div>
</div>
</template>
</div>
</el-dialog><!--el-drawer 流程监控-抽屉-->
</div>
<preview-util v-if="isPreviewDisable" ref="previewForm" @previewClose="previewClose" @previewLoadingClose="previewLoadingClose"></preview-util>
<tool-selector ref="toolSelect" @selectHandle="selectHandle"></tool-selector>
<bl-user-selector ref="peopleSelect" :type="'single'" :isCheck="true" :open="toolPrincipalsChoose" :deptFilter="true" @cancel="toolPrincipalsChoose=false" @submit="submitPeople"></bl-user-selector>
</div><!--el-form-border 表单-->
</template>
<script>
import { addDocument, updateDocument } from "@/api/document/document";
import axios from 'axios';
import { getToken } from '@/utils/auth'
import { addDocument, updateDocument, getDocument } from "@/api/document/document";
import { deptTreeSelect } from "@/api/system/user";
import { documentTree } from "@/api/documentCategory/documentCategory.js";
import Treeselect from "@riophae/vue-treeselect";
import uploadProgress from "./uploadProgress";
import uploadVue from '@/components/FileUpload/optimizeUpload.vue'
import uploadVue from '@/components/FileUpload/optimizeToolUpload.vue'
import ToolSelector from '@/components/tool-selector/index.vue'
import { listDiscussions, addDiscussions } from "@/api/tool/discussions.js";
import { listReplies, addReplies} from "@/api/tool/replies.js";
import previewUtil from '@/components/PreviewUtil/previewUtil.vue'
import blUserSelector from '@/components/user-selector/src/user-selector.vue'
import { listAttachment } from "@/api/attachment/attachment";
import { addCount } from "@/api/tool/downloadCount";
export default {
name: 'editDocument',
components: { Treeselect, uploadProgress, uploadVue},
components: { Treeselect, uploadProgress, uploadVue, ToolSelector, previewUtil, blUserSelector},
dicts:['doc_class','doc_source'],
props: {
tooId: {
type: String,
default: "",
}
required: false
},
relatedTool: {
type: Boolean,
default: true,
},
//
isDownload: {
type: Boolean,
default() {
return true
},
required: false
},
//
isComment: {
type: Boolean,
default() {
return true
},
required: false
},
},
data(){
return{
@ -152,19 +313,25 @@
],
//
form: {
categoryId: undefined,
docId: undefined,
docCategoryId: undefined,
docCode: '',
docName: '',
docType: '',
docPrincipals: '',
docRespDept: undefined,
docPrincipals: null,
docPrincipalsName: null,
docRespDept: this.$store.getters.userInfo.deptId,
docSource: '',
toolId: ''
toolId: '',
remark: undefined,
},
fileList: [],
progress: 0,
//
rules: {
docCategoryId: [
{ required: true, message: "文档分类不能为空", trigger: "input" }
],
docCode: [
{ required: true, message: "文档编号不能为空", trigger: "blur" }
],
@ -172,19 +339,69 @@
{ required: true, message: "文档名称不能为空", trigger: "blur" }
],
docType: [
{ required: true, message: "类别不能为空", trigger: "blur" }
{ required: true, message: "类别不能为空", trigger: "change" }
],
docSource: [
{ required: true, message: "文档来源不能为空", trigger: "blur" }
]
{ required: true, message: "文档来源不能为空", trigger: "change" }
],
docPrincipals: [
{ required: true, message: "负责人不能为空", trigger: ['change','blur'] }
],
docRespDept: [
{ required: true, message: "请选择归属部门", trigger: ['change','change'] }
],
},
docCategory:[],
deptOptions:[],
uploadFileUrl: process.env.VUE_APP_BASE_API + "/common/upload", //
fileData: null,
acceptType: ".txt,.doc,.docx,.pdf,.mp4,.zip,.rar,.7z,.png,.jpg,.jpeg"
acceptType: ".txt,.docx,.pdf,.mp4,.zip,.rar,.7z,.png,.jpg",
editStatus: true,
toolDataInfo: [],
dataFile: [],
//
detailBoolean: false,
discussionContent: null, //
repliesContent: null, //
//
discussionsList: [],
//
repliesList: [],
showReplyForm: [],
replyContent: [],
detailLoading: false,
attachmentList: [],
attFileType: "zip,rar,7z",
isPreviewDisable: false,
loadingDownload: false,
userInfo: this.$store.getters.userInfo,
toolPrincipalsChoose: false,
docQueryParams: {
pageNum: 1,
pageSize: 10,
},
queryParams: {
pageNum: 1,
pageSize: 99999,
},
currentPage: 1, //
pageSize: 10, //
previewLoading: false,
}
},
computed: {
//
paginatedData() {
const start = (this.currentPage - 1) * this.pageSize;
const end = this.currentPage * this.pageSize;
return this.attachmentList.slice(start, end);
},
//
total() {
return this.attachmentList.length;
},
},
created(){
this.getDeptTree();
this.getDocumentTree();
@ -229,21 +446,6 @@
this.drawer1 = false;
this.reset();
},
onChange(file, fileList) {
// valid the suffix of file
/*let validSuffix = ['pdf', 'docx', 'doc', 'txt', 'eml', 'mp4']
let splits = file.name.split('.')
let suffix = splits[splits.length - 1]
if (!validSuffix.includes(suffix)) {
this.$message.error(`只能上传 ${validSuffix.join(',')} 类型的文件!`)
this.fileList = fileList.filter(item => item.uid !== file.uid)
return
}*/
this.fileList = fileList
},
onRemove(file, fileList) {
this.fileList = fileList.filter(item => item.uid !== file.uid)
},
generateUniqueID() {
// 使ID
const timestamp = new Date().getTime();
@ -251,84 +453,102 @@
const uniqueID = 'file_' + timestamp;
return uniqueID;
},
inputSelect(){
this.$refs.form.validateField('docCategoryId')
},
/** 提交按钮 */
submitForm: function() {
let self = this
let fileName = []
//
/* if(self.form.docId && (self.fileList == null || self.fileList.length <= 0 )){
fileName = self.$refs.uploadFile.fileList[0]
self.fileList = self.$refs.uploadFile.fileList
}else{
fileName = self.fileList[0]
self.fileList = self.fileList
} */
//
if (this.fileList.length === 0) {
return this.$message.warning('请选取文件后再上传')
if (self.attachmentList.length <= 0) {
return self.$message.warning('最少上传一个附件')
}
this.fileList.map(file =>{
/*this.fileList.map(file =>{
this.form.docName = file.name
})
this.form.toolId = this.toolId
})*/
/* if(fileName){
self.$set(self.form,"docUrl", fileName.filePath)
self.$set(self.form,"docStatus", "ysc")
} */
self.$set(self.form,"docStatus", "ysc")
if(self.toolDataInfo && self.toolDataInfo.length > 0){
self.$set(self.form,"toolId", self.toolDataInfo[0].toolId)
}
self.$set(self.form,'attachmentList',self.attachmentList)
self.$refs["form"].validate(valid => {
if (valid) {
let tipName = '';
if (self.form.docId){
tipName = '更新'
}else{
tipName = '保存'
}
this.$modal.confirm('是否确认' + tipName+ '').then(() => {
if (self.form.docId) {
updateDocument(self.form).then(res => {
self.$modal.msgSuccess("修改成功");
self.open = false;
self.$emit("submit");
});
} else {
addDocument(self.form).then(res => {
self.$modal.msgSuccess("新增成功");
self.open = false;
// self.confirmSubmit(response.data);
self.$emit("submit");
});
}
}).catch((err) => {
console.error(err)
});
}
});
},
/** 提交按钮 */
assembleSubmit: function() {
let self = this
let fileName = []
//
if(this.form.docId && (this.fileList == null || this.fileList.length <= 0 )){
fileName = this.$refs.uploadFile.fileList[0]
this.fileList = this.$refs.uploadFile.fileList
}else{
fileName = this.fileList[0]
}
//
if (this.fileList.length == 0) {
return self.$message.warning('最少上传一个附件')
}
/*this.fileList.map(file =>{
this.form.docName = file.name
})*/
if(fileName){
this.$set(this.form,"docUrl", fileName.filePath)
this.$set(this.form,"docStatus", "ysc")
this.$set(this.form,"attachment", fileName)
}
if(this.toolDataInfo && this.toolDataInfo.length > 0){
this.$set(this.form,"toolId", this.toolDataInfo[0].toolId)
}
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.id != undefined) {
updateDocument(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.$emit("submit");
});
} else {
addDocument(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.confirmSubmit(response.data);
this.$emit("submit");
});
}
self.$emit("docSubmitData",self.form)
}
});
},
testUpdate(docId){
// formData
const formData = new FormData()
// upload FormData
this.fileList.forEach((file) => {
formData.append('folder', file.raw)
})
formData.append('docId', '')
formData.append('requestId', this.generateUniqueID())
axios.post(process.env.VUE_APP_BASE_API + '/document/upload/folder', formData, {
headers: {
'Content-Type': 'multipart/form-data',
'Authorization': 'Bearer ' + getToken(),
}
}).then((response) => {
if(response.data.code===200){
this.$emit("submit");
}else{
// response.data.message
}
}).catch((error) => {
console.error('Failed to upload file:', error);
});
},
confirmSubmit(docId) {
// formData
const formData = new FormData()
// upload FormData
this.fileList.forEach((file) => {
formData.append('files', file.raw)
})
formData.append('docId', docId)
formData.append('requestId', this.generateUniqueID())
//ajax
axios.post(process.env.VUE_APP_BASE_API + '/document/upload', formData, {
headers: {
'Content-Type': 'multipart/form-data',
'Authorization': 'Bearer ' + getToken(),
}
}).then((response) => {
if(response.data.code===200){
this.$emit("submit");
}else{
// response.data.message
}
}).catch((error) => {
console.error('Failed to upload file:', error);
});
},
/** 查询部门下拉树结构 */
getDeptTree() {
deptTreeSelect().then(response => {
@ -354,21 +574,306 @@
},
// flag true
getData(data, flag, index) {
console.info("data============", data)
console.info("flag============", flag)
console.info("index============", index)
},
getError(message) {
this.$message.error(message);
},
handleUploadSuccess(response) {
alert('File uploaded successfully');
toolSelect(){
this.$refs.selectHeadTool.blur();
this.$nextTick(()=>{
this.$refs.toolSelect.init(null,null,false)
})
},
selectHandle(source,index,data){
this.toolDataInfo = []
let toolInfo = {toolId:data.toolId,toolCode:data.toolCode,toolName:data.toolName}
this.toolDataInfo.push(toolInfo)
},
/**初始化 **/
resetForm() {
let self = this
self.form.docPrincipalsName = null
this.$refs.form.resetFields();
this.toolDataInfo = []
this.fileList = []
this.attachmentList = []
this.detailBoolean = false
this.setAllRequiredTrue(true)
this.$nextTick(()=>{
if(self.$refs.uploadFile){
self.$refs.uploadFile.clearFile();
}
})
},
editInit(docId, type){
let self = this
if(type == "detail"){
this.detailBoolean = true
self.setAllRequiredTrue(false)
}
self.$refs.form.resetFields();
self.toolDataInfo = []
self.$nextTick(()=>{
if(self.$refs.uploadFile){
self.$refs.uploadFile.clearFile();
}
getDocument(docId).then(res => {
self.form = res.data
self.toolDataInfo = []
let toolInfo = {toolId:self.form.toolId,toolName:self.form.toolName}
self.toolDataInfo.push(toolInfo)
self.dataFile = []
/* let fileData = res.data.attachment
self.$set(fileData, "name", fileData.fileOldName)
self.$set(fileData, "size", fileData.fileSize)
self.dataFile.push(fileData) */
self.getAttachmentList()
});
})
},
/** 评论 **/
handleDiscussions(){
let self = this
if (this.discussionContent == '' || this.discussionContent == null || this.discussionContent == undefined) {
self.$message({
message: '内容不能为空',//
type:'warning',  //
duration:1200,  //, 0 1200
});
return;
}
let data = {
businessId: this.form.docId,
content: this.discussionContent,
type: "doc",
}
self.$modal.confirm('是否确认发布?').then(()=> {
addDiscussions(data).then(res => {
this.discussionContent = null
self.$message({
message: '发布成功',//
type:'success',  //
duration:1200,  //, 0 1200
});
self.getAttachmentList()
}).catch(err =>{
this.discussionContent = null
console.error("handleDiscussions==err==", err)
self.$modal.msgError("发布失败");
});
})
},
getAttachmentList() {
let self = this
this.$set(this.queryParams,'del',"0")
this.$set(this.queryParams,'businessId',this.form.docId)
listAttachment(this.queryParams).then(res => {
self.attachmentList = res.rows;
// self.total = res.total;
self.loading = false;
});
},
getFirstChar(value) {
if(!value){return ''}
return value.charAt(0);
},
toggleReplyForm(index) {
this.$set(this.showReplyForm, index, !this.showReplyForm[index]);
},
cancelReply(index) {
this.$set(this.showReplyForm, index, false);
this.$set(this.replyContent, index, '');
},
/** 第二级 **/
toggleReplyFormSon(parentIndex, repIndex) {
const parentItem = this.discussionsList[parentIndex];
this.$set(parentItem.showReplyFormSon, repIndex, !parentItem.showReplyFormSon[repIndex]);
// this.$set(this.showReplyFormSon, index, !this.showReplyFormSon[index]);
},
/** 第二级,取消回复 **/
cancelReplySon(parentIndex, repIndex) {
const parentItem = this.discussionsList[parentIndex];
this.$set(parentItem.showReplyFormSon, repIndex, false);
this.$set(parentItem.replyContentSon, repIndex, '');
},
/** 第二级回复 **/
submitReplySon(parentIndex, repIndex, repItem) {
let self = this
const parentItem = this.discussionsList[parentIndex];
const content = parentItem.replyContentSon[repIndex];
if (content.trim() == '' || content == null || content == undefined) {
self.$message({
message: '回复内容不能为空',//
type:'warning',  //
duration:1200,  //, 0 1200
});
return;
}
let data = {
"discussionId": repItem.id,
"content": content,
}
self.$modal.confirm('是否确认发布?').then(()=> {
addReplies(data).then(res => {
self.$message({
message: '发布成功',//
type:'success',  //
duration:1200,  //, 0 1200
});
self.cancelReplySon(parentIndex, repIndex)
self.getAttachmentList()
}).catch(err =>{
console.error("submitReplySon==err==", err)
self.$modal.msgError("发布失败");
});
})
//
this.$set(parentItem.replyContentSon, repIndex, '');
this.$set(parentItem.showReplyFormSon, repIndex, false);
},
/** 回复 **/
submitReply(index, item) {
let self = this
const content = this.replyContent[index];
if (content == '' || content == null || content == undefined) {
self.$message({
message: '回复内容不能为空',//
type:'warning',  //
duration:1200,  //, 0 1200
});
return;
}
let data = {
"discussionId": item.id,
"content": content,
}
self.$modal.confirm('是否确认发布?').then(()=> {
addReplies(data).then(res => {
self.$message({
message: '发布成功',//
type:'success',  //
duration:1200,  //, 0 1200
});
self.cancelReply(index)
self.getAttachmentList()
}).catch(err =>{
console.error("handleDiscussions==err==", err)
self.$modal.msgError("发布失败");
});
})
//
this.replyContent[index] = '';
this.showReplyForm[index] = false;
},
previewAuth(row){
if(row.fileUrl == null || row.fileUrl == '' || row.fileUrl == undefined){
return false
}
let extension = this.getExtension(row.fileUrl);
const acceptedExtensions = this.attFileType.toLowerCase().split(',');
if(acceptedExtensions.includes(extension)){
return false
}
return true
},
getExtension(filePath) {
// '.'
const parts = filePath.split('.');
//
const extension = parts.pop();
return extension;
},
handlePreview(row){
this.isPreviewDisable = true
this.previewLoading = true
this.$nextTick(() => {
this.$refs.previewForm.frontModulePreview(row)
})
},
/** 关闭预览 **/
previewClose(){
this.isPreviewDisable = false
},
/** 关闭预览遮罩 **/
previewLoadingClose(){
this.previewLoading = false
},
/**
* 处理下载
* **/
handleDownload(row){
let self = this
self.loadingDownload = true
this.$download.resource(row.fileUrl);
//
if(row.businessId){
let formData = {
'businessId': row.businessId,
'businessType': 'doc',
'attId': row.id,
'attName': row.fileOldName
}
addCount(formData).then(res => {
});
}
setTimeout(()=>{
self.loadingDownload = false
},1000)
},
handleDelete(row){
const index = this.attachmentList.findIndex(item => item.fileNewName == row.fileNewName);
if (index !== -1) {
// attachmentList
this.attachmentList.splice(index, 1);
//
if (this.paginatedData.length === 0 && this.currentPage > 1) {
this.currentPage--;
}
}
// this.attachmentList.splice(row,1)
},
handleBeforeClose() {
this.viewDialogOpen = false
},
handleUploadSuccess(res) {
this.attachmentList.push(res)
//
},
handleUploadError(error) {
alert('Failed to upload file');
//
}
},
isShowOperation(row){
let self = this
if(row.businessId == null || row.businessId == undefined || row.businessId == ''){
return false
}
return true
},
submitPeople(peopleList){
this.$set(this.form,'docPrincipals',peopleList[0]['userId'])
this.$set(this.form,'docPrincipalsName',peopleList[0]['nickName'])
this.toolPrincipalsChoose = false;
},
setAllRequiredTrue(value) {
Object.keys(this.rules).forEach(key => {
this.rules[key].forEach(rule => {
rule.required = value;
});
});
},
handlePageChange(newPage) {
this.currentPage = newPage;
},
}
}
</script>

View File

@ -1,18 +1,84 @@
<template>
<div class="app-container">
<el-card>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="70px">
<div class="search">
<div class="sl">
<el-form-item label="文档名称" prop="roleName">
<el-form-item label="文档编号" prop="docCode">
<el-input
v-model="queryParams.docCode"
placeholder="请输入文档名称"
clearable
@clear="handleQuery"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="文档名称" prop="docName">
<el-input
v-model="queryParams.docName"
placeholder="请输入文档名称"
clearable
style="width: 240px"
@clear="handleQuery"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="文档类别" prop="docType">
<el-select v-model="queryParams.docType" placeholder="请选择" @change="handleQuery">
<el-option
v-for="dict in dict.type.doc_class"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="文档来源" prop="docSource">
<el-select v-model="queryParams.docSource" placeholder="请选择" @change="handleQuery">
<el-option
v-for="dict in dict.type.doc_source"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
@change="handleQuery"
></el-date-picker>
</el-form-item>
<el-form-item label="负责人" prop="docPrincipalsName">
<el-input
v-model="queryParams.docPrincipalsName"
placeholder="请输入负责人名称"
clearable
@clear="handleQuery"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<!-- <el-form-item label="归属单位" prop="docRespDept">
<treeselect v-model="queryParams.docRespDept" :options="deptOptions"
placeholder="请选择归属单位"
:show-count="true" style="width: 150px"/>
</el-form-item>-->
<el-form-item label="状态" prop="docStatus">
<el-select v-model="queryParams.docStatus" placeholder="请选择" @change="handleQuery">
<el-option
v-for="dict in dict.type.doc_upload_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
></el-option>
</el-select>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@ -23,17 +89,33 @@
</el-card>
<el-card class="lrtt">
<div class="lt">
<el-input placeholder="请输入..." prefix-icon="el-icon-search"></el-input>
<el-input
v-model="categoryNameParam"
placeholder="请输入文档分类名称"
clearable
size="small"
prefix-icon="el-icon-search"
style="margin-bottom: 20px"
/>
<!-- <el-input placeholder="请输入..." prefix-icon="el-icon-search"
clearable size="small" style="margin-bottom: 20px"
v-model="categoryNameParam"></el-input>-->
<div class="divide"></div><!--divide 分隔-->
<el-tree :data="docCategory" :props="docCategoryProps" @node-click="handleNodeClick">
<el-tree :data="docCategory" :props="docCategoryProps"
ref="tree" :expand-on-click-node="false"
:filter-node-method="filterNode"
node-key="id"
default-expand-all
highlight-current
@node-click="handleNodeClick">
<span class="custom-tree-node" slot-scope="{ node, data }">
<span>{{ node.label }}</span>
<el-dropdown>
<span class="el-dropdown-link"><i class="el-icon-more"></i></span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="handleDocCategoryAdd(data)"><i class="el-icon-plus"></i>添加</el-dropdown-item>
<el-dropdown-item v-if="data.types != 'system'" @@click.native="handleDocCategoryUpdate(data)"><i class="el-icon-edit"></i>编辑</el-dropdown-item>
<el-dropdown-item v-if="data.types != 'system'" @@click.native="handleDocCategoryDelete(data)"><i class="el-icon-delete"></i>删除</el-dropdown-item>
<el-dropdown-item v-if="data.types != 'system'" @click.native="handleDocCategoryUpdate(data)"><i class="el-icon-edit"></i>编辑</el-dropdown-item>
<el-dropdown-item v-if="data.types != 'system'" @click.native="handleDocCategoryDelete(data)"><i class="el-icon-delete"></i>删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</span>
@ -47,46 +129,89 @@
icon="el-icon-upload2"
size="mini"
@click="handleAdd"
v-hasPermi="['document:add']"
>上传文档</el-button>
<el-button type="primary" icon="el-icon-position">发布</el-button>
<el-button icon="el-icon-delete" @click="handleDelete">批量删除</el-button>
<el-button type="primary" icon="el-icon-position" @click="handlePush" v-hasPermi="['document:push']">发布</el-button>
<el-button type="primary" icon="el-icon-download" @click="handleOpenExport()" v-hasPermi="['document:export']">全量导出</el-button>
<el-button type="primary" icon="el-icon-download" @click="handleOpenBatchExport()" v-hasPermi="['document:batch:export']">批量导出</el-button>
<el-button icon="el-icon-delete" @click="handleDelete" v-hasPermi="['document:batch:remove']">批量删除</el-button>
</div><!--operate 操作按钮-->
<el-table v-loading="loading" :data="docList" @selection-change="handleSelectionChange">
<el-table v-loading="loading" :data="docList" ref="tableRef" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="文档编号" prop="docCode" width="120" />
<el-table-column label="文档名称" prop="docName" :show-overflow-tooltip="true" />
<el-table-column label="类别" prop="docType" :show-overflow-tooltip="true" width="80" />
<el-table-column label="负责人" prop="docPrincipals" :show-overflow-tooltip="true" width="80" />
<el-table-column label="归属部门" prop="docRespDept" :show-overflow-tooltip="true" width="150" />
<el-table-column label="来源" prop="docSource" width="100" />
<el-table-column label="关联工具" prop="roleSort" width="100" />
<el-table-column label="上传状态" prop="docUploadProgress" width="100" >
<el-table-column label="文档编号" prop="docCode" width="120" />
<el-table-column label="文档名称" prop="docName" :show-overflow-tooltip="true" />
<el-table-column label="文档类别" prop="docType" :show-overflow-tooltip="true" width="80">
<template slot-scope="scope">
<el-tag type="success" v-if="scope.row.docStatus == 'ysc'">已上传</el-tag>
<el-tag type="danger" v-else>上传失败</el-tag>
<dict-tag :options="dict.type.doc_class" :value="scope.row.docType"/>
</template>
</el-table-column>·
<el-table-column label="负责人" prop="docPrincipalsName" :show-overflow-tooltip="true" width="100" />
<el-table-column label="归属单位" prop="docRespDeptName" :show-overflow-tooltip="true" width="80" />
<el-table-column label="文档来源" prop="docSource" width="100">
<template slot-scope="scope">
<dict-tag :options="dict.type.doc_source" :value="scope.row.docSource"/>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<!-- <el-table-column label="关联工具" align="center" prop="toolName" width="100" />-->
<el-table-column label="文档状态" align="center" prop="docStatus" width="100" >
<template slot-scope="scope">
<dict-tag :options="dict.type.doc_upload_status" :value="scope.row.docStatus"/>
</template>
<!--
<template slot-scope="scope">
<el-tag type="info" v-if="scope.row.docStatus == 'ysc'">已上传</el-tag>
<el-tag type="success" v-else-if="scope.row.docStatus == 'yfb'">已发布</el-tag>
<el-tag type="warning" v-else-if="scope.row.docStatus == 'shz'">审核中</el-tag>
</template>-->
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="180" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="180">
<template slot-scope="scope" v-if="scope.row.roleId !== 1">
<el-button
<el-table-column label="操作" align="center" width="160px" fixed="right">
<template slot-scope="scope">
<!-- <el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handlePriew(scope.row)"
>预览</el-button>
v-if="previewAuth(scope.row)"
@click="handlePreview(scope.row)"
v-hasPermi="['document:preview']"
>预览</el-button>-->
<el-button type="text" icon="el-icon-download" @click="handleDownload(scope.row)"
v-if="scope.row.downloadStatus"
v-loading="loadingDownload">下载</el-button>
<!-- <el-button
size="mini"
type="text"
icon="el-icon-edit"
v-if="scope.row.docStatus != 'yfb' && scope.row.docStatus != 'shz'"
@click="handleEdit(scope.row)"
v-hasPermi="['document:edit']"
>编辑</el-button>
<el-button type="text" icon="el-icon-info" @click="handleDetail(scope.row)">详情</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
v-if="scope.row.docStatus != 'yfb' && scope.row.docStatus != 'shz'"
@click="handleDelete(scope.row)"
>删除</el-button>
<el-button type="text" icon="el-icon-download">下载</el-button>
v-hasPermi="['document:remove']"
>删除</el-button>-->
<el-dropdown size="mini" @command="(command) => handleCommand(command, scope.row)">
<el-button size="mini" type="text" icon="el-icon-d-arrow-right" >更多</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="handleDetail" icon="el-icon-info" >详情</el-dropdown-item>
<el-dropdown-item command="handleEdit" icon="el-icon-edit" v-if="scope.row.docStatus != 'yfb' && scope.row.docStatus != 'shz'">编辑</el-dropdown-item>
<el-dropdown-item command="handleDelete" icon="el-icon-delete" v-if="scope.row.docStatus != 'yfb' && scope.row.docStatus != 'shz'">删除</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
</el-table-column>
</el-table>
@ -103,10 +228,13 @@
<el-dialog :title="docCategoryTitle" :visible.sync="docCategoryOpen" width="50%" append-to-body>
<el-form ref="docCategoryForm" :model="docCategoryForm" :rules="docCategoryRules" label-width="80px">
<el-dialog :title="docCategoryTitle" :visible.sync="docCategoryOpen" width="50%"
:close-on-press-escape="false" :close-on-click-modal="false" :destroy-on-close="true"
:show-close="false" :wrapperClosable="false"
append-to-body>
<el-form ref="docCategoryFormRefs" :model="docCategoryForm" :rules="docCategoryRules" label-width="80px">
<el-form-item label="父分类" prop="parentId">
<treeselect v-model="docCategoryForm.parentId" :options="docCategory" :show-count="true" placeholder="如果不选择,默认为顶级节点" />
<treeselect v-if="docCategoryOpen" v-model="docCategoryForm.parentId" :options="docCategory" :show-count="true" placeholder="如果不选择,默认为一级分类" />
</el-form-item>
<el-form-item label="分类名称" prop="categoryName">
<el-input v-model="docCategoryForm.categoryName" placeholder="请输入分类名称" maxlength="50" show-word-limit/>
@ -123,40 +251,124 @@
</span>
</el-dialog>
<el-dialog :title="viewDialogTitle" :visible.sync="viewDialogOpen" fullscreen width="500px" append-to-body>
<i-frame :src="previewUrl" />
</el-dialog>
<el-drawer :visible.sync="open" :modal-append-to-body="false" size="75%">
<!--文档修改-->
<el-drawer :visible.sync="open"
:wrapperClosable="false"
:modal-append-to-body="false" :show-close="false" :close-on-press-escape="false"
size="75%">
<template #title>
<span class="title">新增文档资源</span>
<div class="drawer-head-btn">
<el-button type="primary" @click="$refs.editDocumentRef.submitForm()"> </el-button>
<el-button @click="$refs.editDocumentRef.cancel()"> </el-button>
<span class="title">{{docTitle}}</span>
<div class="drawer-head-btn" v-if="docDetailDisable">
<el-button icon="el-icon-check" type="primary" @click="docConfrim()"> </el-button>
<el-button icon="el-icon-close" @click="docCancel()"> </el-button>
</div><!--drawer-head-btn 抽屉顶部按钮区域-->
<div class="drawer-head-btn" v-else>
<el-button icon="el-icon-close" @click="docCancel()"> </el-button>
</div><!--drawer-head-btn 抽屉顶部按钮区域-->
</template>
<edit-document ref="editDocumentRef" @submit="editDocumentSubmit"/>
<edit-document v-if="open" ref="editDocumentRef" @submit="editDocumentSubmit"/>
</el-drawer>
<upload-progress/>
<!--文档详情-->
<el-drawer :visible.sync="detailDocOpen"
:wrapperClosable="false"
:modal-append-to-body="false" :show-close="false" :close-on-press-escape="false"
size="75%">
<template #title>
<span class="title">{{docTitle}}</span>
<div class="drawer-head-btn">
<el-button icon="el-icon-close" @click="docDetailCancel()"> </el-button>
</div><!--drawer-head-btn 抽屉顶部按钮区域-->
</template>
<template v-if="detailOpen">
<doc-detail ref="docDetailRef" @submit="docDetailFormSubmit"/>
</template>
</el-drawer>
<!-- 文档导出对话框 -->
<el-dialog :title="exportTitle" :visible.sync="exportDrawerOpen"
:wrapperClosable="false"
:modal-append-to-body="false" :show-close="false" :close-on-press-escape="false"
v-loading="wordLoading" element-loading-text="正在下载数据,请稍候"
width="980px" append-to-body>
<div class="el-form-border">
<el-form ref="exportFrom" label-width="180px">
<el-row>
<el-col :span="24">
<el-form-item label="导出格式">
<el-radio-group v-model="statevalue">
<el-radio v-for="item in stateoptions" :key="item.value" :label="item.value" >{{item.label}}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div><!--el-form-border 表单-->
<div class="el-form-border">
<el-form ref="form" label-width="180px">
<el-row>
<el-col :span="24">
<el-form-item label="导出字段">
<el-checkbox-group v-model="checkList">
<el-checkbox label="docCode">文档编号</el-checkbox>
<el-checkbox label="docName">文档名称</el-checkbox>
<el-checkbox label="docType">文档类别</el-checkbox>
<el-checkbox label="docPrincipalsName">负责人</el-checkbox>
<el-checkbox label="docRespDeptName">归属单位</el-checkbox>
<el-checkbox label="docSource">文档来源</el-checkbox>
<el-checkbox label="docStatus">文档状态</el-checkbox>
<el-checkbox label="createTime">创建时间</el-checkbox>
</el-checkbox-group>
</el-form-item>
</el-col>
</el-row>
</el-form><!--el-form-->
</div><!--el-form-border 表单-->
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleExport"> </el-button>
<el-button @click="exportDrawerOpen=false"> </el-button>
</span>
</el-dialog>
<!-- 文档下载对话框 -->
<el-drawer :visible.sync="fileDetailDrawerOpen"
:wrapperClosable="false"
:modal-append-to-body="false" :show-close="false" :close-on-press-escape="false"
size="80%" class="no-padding" @close="handleFileCloseDetail()">
<template #title>
<span>文档附件下载</span>
<div class="drawer-head-btn">
<el-button icon="el-icon-close" @click="fileDetailDrawerOpen = false"> </el-button>
</div><!--drawer-head-btn 抽屉顶部按钮区域-->
</template>
<template v-if="fileDetailOpen">
<download-file-detail ref="downloadFileDetailRef" :docDetail="docDetail"/>
</template>
</el-drawer><!--el-drawer 详情-抽屉-->
</div>
</template>
<script>
import { listDocument, getDocument, delDocument, addDocument, updateDocument } from "@/api/document/document";
import { listDocument, getDocument, delDocument, addDocument, updateDocument,pushDoc, getExportWordList} from "@/api/document/document";
import { deptTreeSelect } from "@/api/system/user";
import { documentTree,addCategory,updateCategory,delCategory,getCategory } from "@/api/documentCategory/documentCategory.js";
import { Base64 } from 'js-base64';
import iFrame from "@/components/iFrame/index"
import editDocument from "./editDocument";
import uploadProgress from "./uploadProgress";
import { w3cwebsocket as WebSocket } from 'websocket';
import Treeselect from "@riophae/vue-treeselect";
import { exportDocx } from '@/utils/docUtil/docutil.js';
import downloadFileDetail from "./downloadFileDetail.vue";
import docDetail from "@/views/document/detail";
import store from "@/store";
export default {
name: "Document",
components: { iFrame, editDocument, uploadProgress, Treeselect},
components: { editDocument, uploadProgress, Treeselect, downloadFileDetail, docDetail},
dicts:['doc_class','doc_source','doc_upload_status'],
data() {
return {
//
@ -202,7 +414,22 @@ export default {
queryParams: {
pageNum: 1,
pageSize: 10,
docName: undefined
docName: '',
docCode: '',
docType: '',
docPrincipalsName: '',
docSource: '',
docStatus: '',
createById: this.$store.getters.userId,
permissionCheck: true,
downloadCheck:true
},
//
queryCategoryParams: {
pageNum: 1,
pageSize: 10,
docCategoryId: '',
categoryName: '',
},
//
form: {
@ -243,8 +470,50 @@ export default {
categoryDescription: null,
parentId: null
},
loadingDownload: false,
acceptType: "zip,rar,7z",
//
columnList: ['docCode', 'docName', 'docType', 'docPrincipalsName', 'docRespDeptName', 'docSource', 'docStatus', 'createTime'],
checkList: [],
exportDrawerOpen: false,
docTitle: '',
//
docDetailDisable: true,
//
statevalue: 1,
stateoptions: [
{
value: 1,
label: 'excel'
},
{
value: 2,
label: 'word'
}
],
docTipAddOrEdit: null,
//
fileDetailDrawerOpen: false,
fileDetailOpen: false,
toolDetail: {},
//
exportTitle:'',
batchExportFlag: false,
//
selection: undefined,
docDetail: {},
detailDocOpen: false,
detailOpen: false,
categoryNameParam: undefined,
wordLoading: false,
};
},
watch: {
//
categoryNameParam(val) {
this.$refs.tree.filter(val);
}
},
created() {
this.getList();
this.getDeptTree();
@ -270,18 +539,22 @@ export default {
},
//
handleNodeClick(data) {
this.queryParams.toolRespDept = data.id;
this.queryParams.docCategoryId = data.id;
this.handleQuery();
},
/** 查询列表 */
getList() {
this.loading = true;
let self = this
self.loading = true;
listDocument(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.docList = response.rows;
this.total = response.total;
this.loading = false;
self.docList = response.rows;
self.total = response.total;
self.loading = false;
}
);
).catch(err=>{
console.error("getList=======", err)
self.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
@ -291,21 +564,51 @@ export default {
/** 重置按钮操作 */
resetQuery() {
this.dateRange = [];
this.queryParams.docCategoryId = '';
this.resetForm("queryForm");
this.$refs.tree.setCurrentKey(null);
this.handleQuery();
},
/** 新增按钮操作 */
handleAdd() {
this.docTitle="新增文档资源"
this.docTipAddOrEdit = 'add'
this.docDetailDisable=true
this.open = true
this.$nextTick(()=>{
this.$refs.editDocumentRef.resetForm();
})
},
handlePriew(row){
console.log('mmmmmmmmmmm',process.env.VUE_APP_BASE_API + row.docUrl)
this.previewUrl = process.env.VUE_APP_TOOL_TECH_FILE_VIEW_API + '/onlinePreview?url=' + encodeURIComponent(Base64.encode(process.env.VUE_APP_BASE_API + row.docUrl));
this.viewDialogTitle = '文档在线预览'
handleEdit(row){
this.docTitle="编辑文档资源"
this.docTipAddOrEdit = 'edit'
this.docDetailDisable=true
this.open = true
this.$nextTick(()=>{
this.$refs.editDocumentRef.editInit(row.docId, "edit");
})
},
handleDetail(row){
this.docTitle="文档详情"
this.docTipAddOrEdit = 'detail'
this.docDetailDisable=false
this.detailDocOpen = true
this.detailOpen = true
this.$nextTick(()=>{
this.$refs.docDetailRef.editInit(row.docId, "detail");
})
},
handlePreview(row){
this.viewDialogOpen = true;
let protocol = window.location.protocol
let hostname = window.location.hostname;
let getDocUrl = protocol + '//' + hostname + ':8080' + process.env.VUE_APP_BASE_API
this.previewUrl = process.env.VUE_APP_TOOL_TECH_FILE_VIEW_API + '/onlinePreview?url=' + encodeURIComponent(Base64.encode(getDocUrl + row.docUrl));
this.viewDialogTitle = '文档在线预览'
},
//
handleSelectionChange(selection) {
this.selection=selection
this.ids = selection.map(item => item.docId)
this.single = selection.length!=1
this.multiple = !selection.length
@ -314,19 +617,45 @@ export default {
this.open = false;
this.getList();
},
docDetailFormSubmit: function() {
this.detailDocOpen = false;
this.detailOpen = false;
this.getList();
},
/** 删除按钮操作 */
handleDelete(row) {
let self = this
const docIds = row.docId || this.ids;
if(docIds == null || docIds == undefined || docIds =='' || docIds.length < 0){
this.$modal.msgWarning(`最少选择一条数据`);
return;
}
//
let delFlag = false;
if(self.selection){
for(let item of self.selection){
if(!(item.docStatus == 'ysc')){
delFlag = true;
}
}
}
if(row.docStatus && row.docStatus != 'ysc'){
delFlag = true;
}
if(delFlag){
this.$modal.msgError(`只能删除文档状态为[已上传]数据,请重新选择`);
return
}
this.$modal.confirm('是否确认删除?').then(function() {
return delDocument(docIds);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
}).catch((err) => {console.error(err)});
},
/** 新增按钮操作 */
handleDocCategoryAdd(data) {
console.info("data================", data)
this.docCategoryOpen = true;
// this.docCategoryForm.parentId = data.id;
this.$nextTick(() => {
@ -343,22 +672,25 @@ export default {
this.getDocumentTree();
this.$modal.msgSuccess("删除成功");
}).catch((err) => {
console.info("err============", err)
console.error("err============", err)
});
},
/** 修改按钮操作 */
handleDocCategoryUpdate(row) {
this.resetDocCategoryForm();
let self = this
self.docCategoryOpen = true;
self.$nextTick(() => {
self.resetDocCategoryForm();
})
const id = row.id;
getCategory(id).then(response => {
this.docCategoryForm = response.data;
this.docCategoryOpen = true;
this.docCategoryTitle = "修改文档资源分类";
self.docCategoryForm = response.data;
self.docCategoryTitle = "修改文档资源分类";
});
},
/** 提交按钮 */
docCategorySubmitForm() {
this.$refs["docCategoryForm"].validate(valid => {
this.$refs["docCategoryFormRefs"].validate(valid => {
if (valid) {
if (this.docCategoryForm.id != null) {
updateCategory(this.docCategoryForm).then(response => {
@ -367,7 +699,7 @@ export default {
this.getDocumentTree();
});
} else {
this.$set(this.docCategoryForm, "type", "user")
this.$set(this.docCategoryForm, "types", "user")
addCategory(this.docCategoryForm).then(response => {
this.$modal.msgSuccess("新增成功");
this.docCategoryOpen = false;
@ -384,8 +716,206 @@ export default {
},
/** 重置 **/
resetDocCategoryForm(){
this.$refs.docCategoryForm.resetFields();
}
this.docCategoryForm = {
categoryName: null,
categoryDescription: null,
parentId: null
},
this.$refs.docCategoryFormRefs.resetFields();
},
/**
* 处理下载
* **/
handleDownload(row){
this.fileDetailDrawerOpen = true
this.fileDetailOpen = true
this.docDetail = row
},
/** 发布操作 */
handlePush(row) {
let self = this
const docIds = row.docId || this.ids;
if(docIds == null || docIds == undefined || docIds =='' || docIds.length < 0){
this.$modal.msgWarning(`最少选择一条数据`);
return;
}
//
let delFlag = false;
for(let item of self.selection){
if(!(item.docStatus == 'ysc')){
delFlag = true;
}
}
if(delFlag){
this.$modal.msgError(`只能发布文档状态为[已上传]数据,请重新选择`);
return
}
this.$modal.confirm('是否确认发布?').then(function() {
return pushDoc(docIds);
}).then(() => {
self.getList();
store.commit('SET_UNREAD_MSG_NUMBER', this.$store.state.user.unreadMsgNumber+1);
self.$modal.msgSuccess("发布成功");
}).catch((err) => {
console.error(err)
});
},
/**
* 确认
*/
docConfrim(){
this.$refs.editDocumentRef.submitForm();
},
docCancel(){
this.$refs.editDocumentRef.resetForm();
this.open = false
},
docDetailCancel(){
this.$refs.docDetailRef.resetForm();
this.detailDocOpen = false
this.detailOpen = false
},
previewAuth(row){
if(row.docUrl == null || row.docUrl == '' || row.docUrl == undefined){
return false
}
let extension = this.getExtension(row.docUrl);
const acceptedExtensions = this.acceptType.toLowerCase().split(',');
if(acceptedExtensions.includes(extension)){
return false
}
return true
},
getExtension(filePath) {
// '.'
const parts = filePath.split('.');
//
const extension = parts.pop();
return extension;
},
isSelectable(row) {
return row.docStatus !== 'yfb' && row.docStatus !== 'shz';
},
/** 批量导出 */
handleOpenBatchExport() {
let self = this
if(self.selection == null || self.selection == '' || self.selection == undefined || self.selection.length <= 0){
this.$modal.msgWarning(`最少选择一条数据`);
return;
}
if (this.checkList.length<1) {
this.checkList = JSON.parse(JSON.stringify(this.columnList))
}
this.exportTitle = '批量导出'
this.batchExportFlag = true
this.exportDrawerOpen = true
},
/** 导出按钮操作 */
handleOpenExport() {
if (this.checkList.length<1) {
this.checkList = JSON.parse(JSON.stringify(this.columnList))
}
this.exportTitle = '全量导出'
this.exportDrawerOpen = true
this.batchExportFlag = false
},
/** 导出按钮操作 */
handleExport() {
let self = this
if(this.checkList.length == 0){
this.$modal.msgWarning(`最少选择一个字段`);
return
}
if (this.statevalue == 1) {
let excludeFields = this.columnList.filter(item=>!this.checkList.includes(item))
let params = {
...this.queryParams,
downloadCheck:false,
excludeFields:excludeFields,
}
if(this.batchExportFlag){
params = {
downloadCheck:false,
docIdList: self.selection.map(item=>item.docId),
excludeFields:excludeFields,
}
}
this.download('/document/export', params , `document_${new Date().getTime()}.xlsx`)
}
if (this.statevalue == 2) {
let params = {
...this.queryParams
}
if(this.batchExportFlag){
params = {
docIdList: self.selection.map(item=>item.docId)
}
}
self.wordLoading = true
getExportWordList(params).then(r => {
if (r.data.length != 0) {
const data = {
form: null,
list: r.data
}
exportDocx('document.docx', data, `document_${new Date().getTime()}.docx`)
setTimeout(() => {
if(self.batchExportFlag){
self.clearSelected()
}
self.wordLoading = false
self.exoportDrawerOpen = false;
}, 1000);
} else {
self.wordLoading = false
self.exportDrawerOpen = false
this.$message.error('没有数据');
}
}).catch((err) => {
console.error("err=============", err)
self.wordLoading = false
self.exportDrawerOpen = false
})
}
},
handleBeforeClose() {
this.viewDialogOpen = false
},
//
handleCommand(command, row) {
switch (command) {
case "handleEdit":
this.handleEdit(row);
break;
case "handleUpdate":
this.handleUpdate(row);
break;
case "handleDelete":
this.handleDelete(row);
break;
case "handleDetail":
this.handleDetail(row);
break;
default:
break;
}
},
clearSelected() {
// tab
this.$refs.tableRef.clearSelection();
},
/** 关闭详情 **/
handleFileCloseDetail(){
this.fileDetailDrawerOpen = false;
this.fileDetailOpen = false;
this.$refs.downloadFileDetailRef.$destroy(); //
this.$nextTick(() => {
this.$refs.downloadFileDetailRef = null; //
});
},
}
};

View File

@ -30,10 +30,10 @@
}
},
created(){
this.initWebSocket();
// this.initWebSocket();
},
methods: {
initWebSocket() {
/* initWebSocket() {
this.websocket = new WebSocket(process.env.VUE_APP_WS_URL);
this.websocket.onmessage = (event) => {
this.uploading = true;
@ -52,8 +52,8 @@
}
})
console.log('this.progressArr=' + this.progressArr);
/* let progress = msgStr.substring(msgStr.indexOf("/") + 1, msgStr.length);
this.progress = parseInt(msgArr[2])*/
/!* let progress = msgStr.substring(msgStr.indexOf("/") + 1, msgStr.length);
this.progress = parseInt(msgArr[2])*!/
// if (progress === '100%') {
// this.websocket.close();
// }
@ -61,7 +61,7 @@
this.websocket.onclose = () => {
console.log('WebSocket connection closed');
};
},
}, */
checkDuplicate(docId) {
return this.progressArr.findIndex(t => t['docId'] == docId) == -1
}

View File

@ -0,0 +1,87 @@
<template>
<el-dialog
:title="`${toolName}下载详情统计`"
:visible.sync="visible"
width="85%"
append-to-body
@open="openEvent"
@close="visible = false"
>
<el-table v-loading="loading" :data="toolDownDetailStatList">
<el-table-column label="下载用户" align="center" key="userName" prop="userName" min-width="120" />
<el-table-column label="下载次数" align="center" key="toolDownNum" prop="toolDownNum" min-width="120" />
<el-table-column label="下载时间" align="center" key="donwTime" prop="donwTime" min-width="120" />
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="detailQueryParams.pageNum"
:limit.sync="detailQueryParams.pageSize"
@pagination="getToolDownDetailStatistics"
/>
</el-dialog>
</template>
<script>
import { getToolDownDetailStatistics } from '@/api/statistic/statistic'
export default {
props: {
/**
* 控制显示/隐藏
*/
show: {
type: Boolean,
default: false
},
/**
* 工具id
*/
toolId: {
type: String,
default: ''
},
/**
* 工具名称
*/
toolName: {
type: String,
default: ''
}
},
computed: {
visible: {
get() {
return this.show
},
set(val) {
this.$emit('update:show', false)
}
}
},
data () {
return {
toolDownDetailStatList: [],
total: 0,
loading: false,
//
detailQueryParams: {
pageNum: 1,
pageSize: 10
}
}
},
methods: {
openEvent(){
this.visible = false
this.getToolDownDetailStatistics()
},
getToolDownDetailStatistics() {
this.loading = true
getToolDownDetailStatistics({ ...this.detailQueryParams, toolId: this.toolId }).then(response => {
this.total = response?.total
this.toolDownDetailStatList = response?.rows || []
this.loading = false
}).catch(() => { this.loading = false });
}
}
}
</script>

View File

@ -0,0 +1,102 @@
<template>
<div :class="className" :style="{height:height,width:width}" />
</template>
<script>
import * as echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import resize from '@/views/dashboard/mixins/resize'
export default {
mixins: [resize],
props: {
className: {
type: String,
default: 'chart'
},
width: {
type: String,
default: '100%'
},
height: {
type: String,
default: '300px'
},
/**
* 饼图数据
*/
data: {
type: Array,
default: () => []
},
/**
* 底部提示数据
*/
legendData: {
type: Array,
default: () => []
},
/**
* 底部提示距底部距离
*/
legendBottom: {
type: String,
default: '5'
},
roseType: {
type: String,
default: 'radius'
},
radius: {
type: Array | String | Number,
default: 50
}
},
data() {
return {
chart: null
}
},
mounted() {
this.$nextTick(() => {
this.initChart()
})
},
beforeDestroy() {
if (!this.chart) {
return
}
this.chart.dispose()
this.chart = null
},
methods: {
initChart() {
this.chart = echarts.init(this.$el, 'macarons')
this.chart.setOption({
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
left: 'center',
bottom: this.legendBottom,
data: this.legendData
},
series: [
{
name: '',
type: 'pie',
roseType: this.roseType,
radius: this.radius,
center: ['50%', '50%'],
data: this.data,
animationEasing: 'cubicInOut',
animationDuration: 2600
}
]
})
}
}
}
</script>

View File

@ -0,0 +1,301 @@
<template>
<div class="app-container" v-loading="pageloading">
<el-row :gutter="24">
<el-col :span="12">
<el-card>
<div slot="header" class="clearfix"><span class="tline">文档类别统计</span></div>
<!-- -->
<div class="tjbox2" v-if="isPieChart">
<PieChart
height="285px"
:data="toolTypeData"
:legendData="toolTypeLegendData"
legendBottom="5"
chartRef="toolType"
:radius="['40%', '70%']"
/>
</div>
</el-card><!--el-card-->
</el-col><!--el-col-->
<el-col :span="12">
<el-card>
<div slot="header" class="clearfix"><span class="tline">文档来源统计</span></div>
<div class="tjbox2" v-if="isPieChart">
<PieChart
height="285px"
:data="toolSourceData"
:legendData="toolSourceLegendData"
legendBottom="5"
:radius="['40%', '70%']"
chartRef="toolStatus"
/>
</div>
</el-card><!--el-card-->
</el-col><!--el-col-->
</el-row><!--el-row-->
<el-row :gutter="20">
<el-col :span="24">
<el-card>
<div slot="header" class="clearfix"><span class="tline">文档下载统计</span></div>
<div class="tjbox2">
<el-form label-width="70px" ref="queryForm" :model="queryParams">
<div class="search">
<div class="sl">
<el-form-item label="下载时间">
<el-date-picker
v-model="dateRange"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item label="文档编号" prop="docCode">
<el-input
v-model="queryParams.docCode"
placeholder="请输入文档编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="文档名称" prop="docName">
<el-input
v-model="queryParams.docName"
placeholder="请输入文档名称"
clearable
@clear="handleQuery"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh-left" @click="reset">重置</el-button>
</div>
</div>
</el-form>
<!-- <img src="images/tjt6.jpg" /> -->
</div>
<div class="rt">
<el-table v-loading="downLoading" :data="toolDownStatList">
<el-table-column type="index" label="序号" width="50" align="center"/>
<el-table-column label="文档编号" key="docCode" prop="docCode" />
<el-table-column label="文档名称" key="docName" prop="docName" :show-overflow-tooltip="true" />
<el-table-column label="下载次数" align="center" key="docDownNum" prop="docDownNum"/>
<el-table-column
label="操作"
align="center"
width="100"
class-name="small-padding fixed-width"
>
<template slot-scope="scope">
<el-button type="text" icon="el-icon-info" @click="handleDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="downTotal>0"
:total="downTotal"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getDocDownStatistics"
/>
</div><!--rt -->
</el-card><!--el-card-->
</el-col><!--el-col-->
</el-row><!--el-row-->
<!-- <DownStatDetail :show.sync="detailDrawerOpen" :toolId="toolId" :toolName="toolName" /> -->
<el-dialog
:title="`${toolName}下载详情统计`"
:visible.sync="detailDrawerOpen"
width="85%"
append-to-body
@open="openEvent"
@close="detailDrawerOpen = false"
>
<el-table :data="toolDownDetailStatList" v-loading="loading">
<el-table-column type="index" label="序号" width="50" align="center"/>
<el-table-column label="附件名称" key="attName" prop="attName" :show-overflow-tooltip="true" />
<el-table-column label="下载用户" key="nickName" prop="nickName" width="120" />
<el-table-column label="下载次数" align="center" key="toolDownNum" prop="toolDownNum" width="120" />
<el-table-column label="下载时间" align="center" key="createTime" prop="createTime" width="200" />
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams1.pageNum"
:limit.sync="queryParams1.pageSize"
@pagination="getDocDownDetailStatistics"
/>
</el-dialog>
</div>
</template>
<script>
import { getStatistics } from "@/api/document/document";
import { listDocCount,userDownList } from "@/api/tool/downloadCount";
import PieChart from './PieChart'
export default {
name: 'statistic',
dicts: ['tool_type', 'flow_status', 'tool_source'],
components: {
PieChart
},
data() {
return {
toolDownDetailStatList: [],
activeName: 'first',
toolTypeData: [
/*{ value: 320, name: '' },
{ value: 240, name: '服务型' }*/
],
// toolTypeLegendData:['', ''],
toolTypeLegendData:[],
toolStatusData: [
/* { value: 212, name: '' },
{ value: 76, name: '审批中' },
{ value: 32, name: '审批不通过' },
{ value: 971, name: '已发布' }*/
],
// toolStatusLegendData: ['','','',''],
toolStatusLegendData: [],
toolSourceData: [
/*{ value: 20, name: 'QQ' },
{ value: 60, name: '微信' },
{ value: 18, name: '官网' },
{ value: 47, name: '熟人介绍' }*/
],
// toolSourceLegendData: ['QQ', '', '', ''],
toolSourceLegendData: [],
//
dateRange: [],
toolDownStatList: [],
downTotal: 0,
downLoading: false,
//
queryParams: {
pageNum: 1,
pageSize: 10,
docCode: null,
docName: null,
},
queryParams1: {
pageNum: 1,
pageSize: 10,
businessId: ''
},
//
detailDrawerOpen: false,
// id
toolId: '',
//
toolName: '',
total: 0,
loading: false,
isPieChart: false,
}
},
created () {
this.getCountData()
this.getDocDownStatistics()
},
methods: {
openEvent() {
this.getDocDownDetailStatistics()
},
getDocDownDetailStatistics() {
let self = this
this.loading = true
userDownList(this.addDateRange(this.queryParams1)).then(res => {
self.total = res?.total
self.toolDownDetailStatList = res?.rows || []
self.loading = false
}).catch(() => { self.loading = false });
},
//
reset() {
this.toolDownStatList = []
this.dateRange = []
this.resetForm("queryForm")
this.handleQuery()
},
/**
* 工具下载搜索
*/
handleQuery() {
this.queryParams.pageNum = 1
this.getDocDownStatistics()
},
/** 统计类型、类别、状态**/
getCountData(){
let self = this
//
self.toolTypeData = []
self.toolTypeLegendData = []
//
self.toolSourceData = []
self.toolSourceLegendData = []
self.pageloading = true
getStatistics(this.queryParams).then(res => {
if(res.data){
const countType = JSON.parse(JSON.stringify(res.data.countType)).filter(item => item.name)
//
self.toolTypeData = countType
self.toolTypeData.forEach(item => {
if(item && item.name){
self.toolTypeLegendData.push(item.name)
}
})
const countSource = JSON.parse(JSON.stringify(res.data.countSource)).filter(item => item.name)
//
self.toolSourceData = countSource
self.toolSourceData.forEach(item => {
if(item && item.name){
self.toolSourceLegendData.push(item.name)
}
})
self.isPieChart= true
self.pageloading= false
}
/* console.info("countToolType==============", this.dict.type.tool_type)
console.info("res===========", res)*/
}).catch((err) => {
self.isPieChart= true
self.pageloading= false
console.error(err)
});
},
handleDetail(row){
this.$set(this.queryParams1, "businessId", row.businessId)
this.detailDrawerOpen = true
},
/**
* 获取工具下载列表数据
*/
getDocDownStatistics() {
let self = this
this.downLoading = true
listDocCount(this.addDateRange(this.queryParams, this.dateRange)).then(res => {
self.downTotal = res.total
self.toolDownStatList = res?.rows || []
self.downLoading = false
}).catch(() => { self.downLoading = false });
},
}
}
</script>
<style scoped>
</style>

View File

@ -155,7 +155,6 @@ import { getToken } from "@/utils/auth";
import { Base64 } from 'js-base64'
import Treeselect from "@riophae/vue-treeselect";
import blUserSelector from "@/components/user-selector/src/user-selector";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import toolDetail from "./toolDetail";
export default {

View File

@ -41,8 +41,8 @@ export default {
return {
codeUrl: "",
loginForm: {
username: "admin",
password: "admin123",
username: "",
password: "",
rememberMe: false,
code: "",
uuid: ""

View File

@ -4,15 +4,37 @@
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<div class="search">
<div class="sl">
<el-form-item label="消息内容" prop="mesContent">
<el-form-item label="消息内容" prop="content">
<el-input
v-model="queryParams.mesContent"
v-model="queryParams.content"
placeholder="请输入消息内容"
clearable
style="width: 240px"
@clear="handleQuery"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="消息类型" prop="businessType">
<el-select v-model="queryParams.businessType" placeholder="请选择消息类型" clearable @change="handleQuery">
<el-option
v-for="dict in dict.type.msg_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="states">
<el-select v-model="queryParams.states" placeholder="请选择状态" clearable @change="handleQuery">
<el-option
v-for="dict in dict.type.msg_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
@ -22,50 +44,44 @@
</el-form>
</el-card>
<el-card class="lrtt">
<div class="lt">
<el-input
v-model="deptName"
placeholder="请输入部门名称"
clearable
size="small"
prefix-icon="el-icon-search"
style="margin-bottom: 20px"
/>
<div class="divide"></div><!--divide 分隔-->
<el-tree
:data="deptOptions"
:props="defaultProps"
:expand-on-click-node="false"
:filter-node-method="filterNode"
ref="tree"
node-key="id"
default-expand-all
highlight-current
@node-click="handleNodeClick"
/>
</div><!--lt -->
<div class="rt">
<div class="operate">
<el-button type="primary" @click="markRead(null)">全部标记已读</el-button>
<el-button type="primary" v-if="tableList && tableList.length > 0" @click="setAllMarkedRead" icon="el-icon-check">全部标记已读</el-button>
</div><!--operate 操作按钮-->
<el-table v-loading="loading" :data="tableList">
<el-table-column label="消息内容" prop="msgContent" min-width="120" />
<el-table-column label="接收时间" prop="msgRecTime" :show-overflow-tooltip="true" min-width="120"/>
<el-table-column label="消息状态" prop="msgStatus" :show-overflow-tooltip="true" min-width="80" >
<el-table-column type="index" label="序号" width="50" align="center" />
<el-table-column label="消息内容" prop="content" min-width="120">
<template v-slot="{ row }">
<template v-for="dict in dict.type.msg_status">
<el-link target="_blank" @click="handleDetail(row)">
{{ row.content }}
</el-link>
</template>
</el-table-column>
<el-table-column label="消息类型" align="center" prop="businessType" width="80px">
<template v-slot="{ row }">
<template v-for="dict in dict.type.msg_type">
<!-- {{ dict }} -->
<el-tag :type="dict.raw.listClass" v-if="row.msgStatus == dict.value" :key="dict.value">{{ dict.label }}</el-tag>
<el-tag :type="dict.raw.listClass" v-if="row.businessType == dict.value" :key="dict.value">{{ dict.label }}</el-tag>
</template>
</template>
</el-table-column>
<el-table-column label="操作" align="center" min-width="100">
<el-table-column label="接收时间" prop="createTime" :show-overflow-tooltip="true" width="160px"/>
<el-table-column label="消息状态" prop="states" align="center" :show-overflow-tooltip="true" width="80px" >
<template v-slot="{ row }">
<template v-for="dict in dict.type.msg_status">
<!-- {{ dict }} -->
<el-tag :type="dict.raw.listClass" v-if="row.states == dict.value" :key="dict.value">{{ dict.label }}</el-tag>
</template>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="160px" fixed="right">
<template v-slot="{ row }">
<el-button
size="mini"
type="text"
v-if="row.msgStatus === 'unread'"
@click="markRead(row.id)"
icon="el-icon-check"
v-if="row.states == '1'"
@click="markRead(row)"
>标记已读</el-button>
</template>
</el-table-column>
@ -79,16 +95,53 @@
/>
</div>
</el-card>
<!-- 工具详情对话框 -->
<el-drawer :visible.sync="detailDrawerOpen" :modal-append-to-body="false" :show-close="false" :wrapperClosable="false"
size="80%" class="no-padding" :close-on-press-escape="false" @close="handleCloseDetail()">
<template #title>
<span>{{toolTitle}}</span>
<div class="drawer-head-btn">
<el-button icon="el-icon-close" @click="detailDrawerOpen = false"> </el-button>
</div><!--drawer-head-btn 抽屉顶部按钮区域-->
</template>
<template v-if="detailOpen">
<tool-detail ref="toolDetailRef" :toolDetail="toolDetail" :isDownload="false" :isComment="false"/>
</template>
</el-drawer><!--el-drawer 详情-抽屉-->
<!--文档详情-->
<el-drawer :visible.sync="detailDocOpen"
:modal-append-to-body="false" :show-close="false" :close-on-press-escape="false"
size="75%">
<template #title>
<span class="title">{{docTitle}}</span>
<div class="drawer-head-btn">
<el-button icon="el-icon-close" @click="docCancel()"> </el-button>
</div><!--drawer-head-btn 抽屉顶部按钮区域-->
</template>
<doc-detail ref="editDocumentRef" @submit="editDocumentSubmit" :isDownload="false" :isComment="false"/>
</el-drawer>
</div>
</template>
<script>
import { markAllRead, markReadById, getMessageList } from "@/api/message/message"
import { listMessage, updateMessage,allMarkedRead } from "@/api/message/message"
import { deptTreeSelect } from "@/api/system/user";
import docDetail from "@/views/document/detail";
import toolDetail from "@/views/tool/toolDetail";
import { getUserMsgCount } from "@/api/message/message"
import store from '@/store'
export default {
name: "Document",
dicts: ['msg_status'],
dicts: ['msg_status', 'msg_type'],
components: { docDetail, toolDetail},
data() {
return {
//
@ -123,18 +176,34 @@ export default {
previewUrl: '',
progress: 0,
fileList: [],
websocket: null,
// websocket: null,
//
queryParams: {
pageNum: 1,
pageSize: 10,
mesContent: ''
content: '',
states: '',
businessType: '',
},
//
detailDrawerOpen: false,
toolTitle:'',
detailOpen: false,
toolDetail: {},
//
docTitle: '',
detailDocOpen: false,
docTipAddOrEdit: null,
docDetailDisable: true,
};
},
created() {
if(this.$route.query.states){
this.queryParams.states = this.$route.query.states
}
this.getList();
this.getDeptTree();
},
methods: {
/** 查询部门下拉树结构 */
@ -145,7 +214,8 @@ export default {
},
getList() {
this.loading = true
getMessageList(this.queryParams).then(response => {
this.$set(this.queryParams,"receiverId", this.$store.getters.userId)
listMessage(this.queryParams).then(response => {
this.total = response?.total
this.tableList = response?.rows || []
this.loading = false
@ -160,6 +230,7 @@ export default {
resetQuery() {
this.tableList = []
this.resetForm("queryForm")
this.queryParams.states = null
this.handleQuery()
},
//
@ -176,24 +247,76 @@ export default {
* 标记已读id为null时表示标记全部已读
* @param id
*/
markRead(id) {
this.$confirm('确认标记已读吗?', '提示', {
markRead(row) {
let self = this
self.$confirm('确认标记已读吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
if(id) {
markReadById(id).then(response => {
this.$modal.msgSuccess(response?.msg || '操作成功')
this.getList();
})
} else {
markAllRead().then(response => {
this.$modal.msgSuccess(response?.msg || '操作成功')
this.getList();
let formData = JSON.parse(JSON.stringify(row))
self.$set(formData, "states", 2)
updateMessage(formData).then(response => {
self.$modal.msgSuccess(response?.msg || '操作成功')
store.dispatch('GetUserMsgCount').then(() => { })
self.getList();
})
}).catch((err) => {console.error(err)});
},
/**
* 标记已读id为null时表示标记全部已读
* @param id
*/
setAllMarkedRead() {
let self = this
self.$confirm('确认全部标记已读吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
let formData = {
"states": 2
}
}).catch(() => {});
allMarkedRead(formData).then(response => {
self.$modal.msgSuccess(response?.msg || '操作成功')
store.dispatch('GetUserMsgCount').then(() => { })
self.getList();
})
}).catch((err) => {console.error(err)});
},
/** 查看详情 **/
handleDetail(row){
if(row.businessType == 'tool'){
this.detailDrawerOpen = true
this.detailOpen = true
this.toolDetail = {toolId: row.businessId}
this.toolTitle = '工具详情'
}else if(row.businessType == 'doc'){
this.docTitle="文档详情"
this.docTipAddOrEdit = 'detail'
this.docDetailDisable=false
this.detailDocOpen = true
this.$nextTick(()=>{
this.$refs.editDocumentRef.editInit(row.businessId, "detail");
})
}
},
/** 关闭详情 **/
handleCloseDetail(){
this.detailDrawerOpen = false;
this.detailOpen = false;
this.$refs.toolDetailRef.$destroy(); //
this.$nextTick(() => {
this.$refs.toolDetailRef = null; //
});
},
docCancel(){
this.$refs.editDocumentRef.resetForm();
this.detailDocOpen = false
},
editDocumentSubmit: function() {
this.detailDocOpen = false;
},
}
};

View File

@ -23,6 +23,7 @@
<el-table-column
label="序号"
width="60"
align="center"
type="index"
></el-table-column>
@ -81,6 +82,7 @@
<el-table-column
label="序号"
width="60"
align="center"
type="index"
></el-table-column>
<el-table-column

View File

@ -284,7 +284,7 @@
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="openView = false"> </el-button>
<el-button icon="el-icon-close" @click="openView = false"> </el-button>
</div>
</el-dialog>
</div>

View File

@ -173,7 +173,7 @@
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="open = false"> </el-button>
<el-button icon="el-icon-close" @click="open = false"> </el-button>
</div>
</el-dialog>
</div>

View File

@ -195,7 +195,7 @@
</el-row>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="open = false"> </el-button>
<el-button icon="el-icon-close" @click="open = false"> </el-button>
</div>
</el-dialog>
</div>

View File

@ -85,7 +85,7 @@ export default {
},
series: [
{
name: 'WEEKLY WRITE ARTICLES',
name: '',
type: 'pie',
roseType: this.roseType,
radius: this.radius,

View File

@ -1,28 +1,28 @@
<template>
<div class="app-container">
<el-row :gutter="20">
<el-col :span="12">
<div class="app-container" v-loading="pageloading">
<el-row :gutter="24">
<el-col :span="8">
<el-card>
<div slot="header" class="clearfix"><span class="tline">工具类别统计</span></div>
<!-- -->
<div class="tjbox2">
<div class="tjbox2" v-if="isPieChart">
<PieChart
height="207px"
height="285px"
:data="toolTypeData"
:legendData="toolTypeLegendData"
legendBottom="5"
chartRef="toolType"
:radius="50"
:radius="['40%', '70%']"
/>
</div>
</el-card><!--el-card-->
</el-col><!--el-col-->
<el-col :span="12">
<el-col :span="8">
<el-card>
<div slot="header" class="clearfix"><span class="tline">工具状态统计</span></div>
<div class="tjbox2">
<div class="tjbox2" v-if="isPieChart">
<PieChart
height="207px"
height="285px"
:data="toolStatusData"
:legendData="toolStatusLegendData"
legendBottom="5"
@ -33,15 +33,12 @@
</div>
</el-card><!--el-card-->
</el-col><!--el-col-->
</el-row><!--el-row-->
<el-row :gutter="20">
<el-col :span="12">
<el-col :span="8">
<el-card>
<div slot="header" class="clearfix"><span class="tline">工具来源统计</span></div>
<div class="tjbox2">
<div class="tjbox2" v-if="isPieChart">
<PieChart
height="207px"
height="285px"
:data="toolSourceData"
:legendData="toolSourceLegendData"
legendBottom="5"
@ -51,19 +48,19 @@
</div>
</el-card><!--el-card-->
</el-col><!--el-col-->
</el-row>
</el-row><!--el-row-->
<el-row :gutter="20">
<el-col :span="24">
<el-card>
<div slot="header" class="clearfix"><span class="tline">工具下载</span></div>
<div slot="header" class="clearfix"><span class="tline">工具下载统计</span></div>
<div class="tjbox2">
<el-form label-width="80px" ref="queryForm">
<el-form label-width="70px" ref="queryForm" :model="queryParams" >
<div class="search">
<div class="sl">
<el-form-item label="下载时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
@ -71,6 +68,23 @@
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item label="工具编号" prop="toolCode">
<el-input
v-model="queryParams.toolCode"
placeholder="请输入工具编号"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="工具名称" prop="toolName">
<el-input
v-model="queryParams.toolName"
placeholder="请输入工具名称"
clearable
@clear="handleQuery"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
@ -82,13 +96,14 @@
</div>
<div class="rt">
<el-table v-loading="downLoading" :data="toolDownStatList">
<el-table-column label="工具编号" align="center" key="toolCode" prop="toolCode" />
<el-table-column label="工具名称" align="center" key="toolName" prop="toolName" :show-overflow-tooltip="true" />
<el-table-column label="下载数量" align="center" key="toolDownNum" prop="toolDownNum" width="120" />
<el-table-column type="index" label="序号" width="50" align="center"/>
<el-table-column label="工具编号" key="toolCode" prop="toolCode" />
<el-table-column label="工具名称" key="toolName" prop="toolName" :show-overflow-tooltip="true" />
<el-table-column label="下载次数" align="center" key="toolDownNum" prop="toolDownNum" />
<el-table-column
label="操作"
align="center"
width="250"
width="100"
class-name="small-padding fixed-width"
>
<template slot-scope="scope">
@ -116,10 +131,12 @@
@open="openEvent"
@close="detailDrawerOpen = false"
>
<el-table :data="toolDownDetailStatList" v-loading="loading">
<el-table-column label="下载用户" align="center" key="userName" prop="userName" min-width="120" />
<el-table-column label="下载次数" align="center" key="toolDownNum" prop="toolDownNum" min-width="120" />
<el-table-column label="下载时间" align="center" key="donwTime" prop="donwTime" min-width="120" />
<el-table :data="toolDownDetailStatList" v-loading="loading" height="500px">
<el-table-column label="序号" width="60" type="index" align="center"></el-table-column>
<el-table-column label="附件名称" key="attName" prop="attName" :show-overflow-tooltip="true" />
<el-table-column label="下载用户" key="nickName" prop="nickName" width="120" />
<el-table-column label="下载次数" align="center" key="toolDownNum" prop="toolDownNum" width="120" />
<el-table-column label="下载时间" align="center" key="createTime" prop="createTime" width="220" />
</el-table>
<pagination
v-show="total>0"
@ -129,15 +146,20 @@
@pagination="getToolDownDetailStatistics"
/>
</el-dialog>
</div>
</template>
<script>
import { getStatistics } from "@/api/tool/tool";
import { listCount,userDownList } from "@/api/tool/downloadCount";
import PieChart from './PieChart'
import DownStatDetail from './DownStatDetail'
import { getToolDownStat, getToolDownDetailStatistics } from '@/api/statistic/statistic'
export default {
name: 'statistic',
dicts: ['tool_type', 'flow_status', 'tool_source'],
components: {
PieChart,
DownStatDetail
@ -147,24 +169,27 @@ export default {
toolDownDetailStatList: [],
activeName: 'first',
toolTypeData: [
{ value: 320, name: '检测型' },
{ value: 240, name: '服务型' }
/*{ value: 320, name: '' },
{ value: 240, name: '服务型' }*/
],
toolTypeLegendData:['检测型', '服务型'],
// toolTypeLegendData:['', ''],
toolTypeLegendData:[],
toolStatusData: [
{ value: 212, name: '已保存' },
/* { value: 212, name: '' },
{ value: 76, name: '审批中' },
{ value: 32, name: '审批不通过' },
{ value: 971, name: '已发布' }
{ value: 971, name: '已发布' }*/
],
toolStatusLegendData: ['已保存','审批中','审批不通过','已发布'],
// toolStatusLegendData: ['','','',''],
toolStatusLegendData: [],
toolSourceData: [
{ value: 20, name: 'QQ' },
/*{ value: 20, name: 'QQ' },
{ value: 60, name: '微信' },
{ value: 18, name: '官网' },
{ value: 47, name: '熟人介绍' }
{ value: 47, name: '熟人介绍' }*/
],
toolSourceLegendData: ['QQ', '微信', '官网', '熟人介绍'],
// toolSourceLegendData: ['QQ', '', '', ''],
toolSourceLegendData: [],
//
dateRange: [],
toolDownStatList: [],
@ -174,12 +199,13 @@ export default {
queryParams: {
pageNum: 1,
pageSize: 10,
mesContent: ''
toolCode: null,
toolName: null,
},
queryParams1: {
pageNum: 1,
pageSize: 10,
mesContent: ''
businessId: ''
},
//
detailDrawerOpen: false,
@ -188,10 +214,12 @@ export default {
//
toolName: '',
total: 0,
loading: false
loading: false,
isPieChart: false,
}
},
created () {
this.getCountData()
this.getToolDownStatistics()
},
methods: {
@ -199,16 +227,18 @@ export default {
this.getToolDownDetailStatistics()
},
getToolDownDetailStatistics() {
let self = this
this.loading = true
getToolDownDetailStatistics({ ...this.detailQueryParams, toolId: this.toolId }).then(response => {
this.total = response?.total
this.toolDownDetailStatList = response?.rows || []
this.loading = false
}).catch(() => { this.loading = false });
userDownList(this.addDateRange(this.queryParams1)).then(res => {
self.total = res?.total
self.toolDownDetailStatList = res?.rows || []
self.loading = false
}).catch(() => { self.loading = false });
},
//
reset() {
this.toolDownStatList = []
this.dateRange = []
this.resetForm("queryForm")
this.handleQuery()
},
@ -223,18 +253,71 @@ export default {
* 获取工具下载列表数据
*/
getToolDownStatistics() {
let self = this
this.downLoading = true
getToolDownStat(this.queryParams).then(response => {
this.downTotal = response?.total
this.toolDownStatList = response?.rows || []
this.downLoading = false
}).catch(() => { this.downLoading = false });
listCount(this.addDateRange(this.queryParams, this.dateRange)).then(res => {
self.downTotal = res?.total
self.toolDownStatList = res?.rows || []
self.downLoading = false
}).catch(() => { self.downLoading = false });
},
handleDetail(row){
this.toolId = row.id
this.toolName = row.toolName
this.$set(this.queryParams1, "businessId", row.businessId)
this.detailDrawerOpen = true
},
/** 统计类型、类别、状态**/
getCountData(){
let self = this
self.toolTypeData = []
self.toolTypeLegendData = []
self.toolStatusData = []
self.toolStatusLegendData = []
self.toolSourceData = []
self.toolSourceLegendData = []
self.pageloading = true
getStatistics(this.queryParams).then(res => {
if(res.data){
const countToolType = JSON.parse(JSON.stringify(res.data.countToolType)).filter(item => item.name)
//
self.toolTypeData = countToolType
self.toolTypeData.forEach(item => {
if(item && item.name){
self.toolTypeLegendData.push(item.name)
}
})
const recordStatus = JSON.parse(JSON.stringify(res.data.recordStatus)).filter(item => item.name)
//
self.toolStatusData = recordStatus
self.toolStatusData.forEach(item => {
if(item && item.name){
self.toolStatusLegendData.push(item.name)
}
})
const toolSource = JSON.parse(JSON.stringify(res.data.toolSource)).filter(item => item.name)
//
self.toolSourceData = toolSource
self.toolSourceData.forEach(item => {
if(item && item.name){
self.toolSourceLegendData.push(item.name)
}
})
self.isPieChart= true
self.pageloading= false
}
/* console.info("countToolType==============", this.dict.type.tool_type)
console.info("res===========", res)*/
}).catch((err) => {
self.isPieChart= true
self.pageloading= false
console.error(err)
});
}
}
}
</script>

View File

@ -0,0 +1,392 @@
<template>
<div class="app-container">
<el-card>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="字典名称" prop="dictType">
<el-select v-model="queryParams.dictType">
<el-option
v-for="item in typeOptions"
:key="item.dictId"
:label="item.dictName"
:value="item.dictType"
/>
</el-select>
</el-form-item>
<el-form-item label="字典标签" prop="dictLabel">
<el-input
v-model="queryParams.dictLabel"
placeholder="请输入字典标签"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="数据状态" clearable>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</el-card>
<el-card class="lrtt">
<div class="rt">
<div class="operate">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['system:dict:add']"
>新增</el-button>
<el-button
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['system:dict:edit']"
>修改</el-button>
<el-button
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['system:dict:remove']"
>删除</el-button>
<el-button
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['system:dict:export']"
>导出</el-button>
<el-button
plain
icon="el-icon-close"
size="mini"
@click="handleClose"
>关闭</el-button>
</div>
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="字典编码" align="center" prop="dictCode" />
<el-table-column label="字典标签" align="center" prop="dictLabel">
<template slot-scope="scope">
<span v-if="(scope.row.listClass == '' || scope.row.listClass == 'default') && (scope.row.cssClass == '' || scope.row.cssClass == null)">{{ scope.row.dictLabel }}</span>
<el-tag v-else :type="scope.row.listClass == 'primary' ? '' : scope.row.listClass" :class="scope.row.cssClass">{{ scope.row.dictLabel }}</el-tag>
</template>
</el-table-column>
<el-table-column label="字典键值" align="center" prop="dictValue" />
<el-table-column label="字典排序" align="center" prop="dictSort" />
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['system:dict:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:dict:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</el-card>
<!-- 添加或修改参数配置对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="字典类型">
<el-input v-model="form.dictType" :disabled="true" />
</el-form-item>
<el-form-item label="数据标签" prop="dictLabel">
<el-input v-model="form.dictLabel" placeholder="请输入数据标签" />
</el-form-item>
<el-form-item label="数据键值" prop="dictValue">
<el-input v-model="form.dictValue" placeholder="请输入数据键值" />
</el-form-item>
<el-form-item label="样式属性" prop="cssClass">
<el-input v-model="form.cssClass" placeholder="请输入样式属性" />
</el-form-item>
<el-form-item label="显示排序" prop="dictSort">
<el-input-number v-model="form.dictSort" controls-position="right" :min="0" />
</el-form-item>
<el-form-item label="回显样式" prop="listClass">
<el-select v-model="form.listClass">
<el-option
v-for="item in listClassOptions"
:key="item.value"
:label="item.label + '(' + item.value + ')'"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { listData, getData, delData, addData, updateData } from "@/api/system/dict/data";
import { optionselect as getDictOptionselect, getType } from "@/api/system/dict/type";
export default {
name: "Data",
dicts: ['sys_normal_disable'],
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
dataList: [],
//
defaultDictType: "",
//
title: "",
//
open: false,
//
listClassOptions: [
{
value: "default",
label: "默认"
},
{
value: "primary",
label: "主要"
},
{
value: "success",
label: "成功"
},
{
value: "info",
label: "信息"
},
{
value: "warning",
label: "警告"
},
{
value: "danger",
label: "危险"
}
],
//
typeOptions: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
dictType: undefined,
dictLabel: undefined,
status: undefined
},
//
form: {},
//
rules: {
dictLabel: [
{ required: true, message: "数据标签不能为空", trigger: "blur" }
],
dictValue: [
{ required: true, message: "数据键值不能为空", trigger: "blur" }
],
dictSort: [
{ required: true, message: "数据顺序不能为空", trigger: "blur" }
]
}
};
},
created() {
const dictId = this.$route.params && this.$route.params.dictId;
this.getType(dictId);
this.getTypeList();
},
methods: {
/** 查询字典类型详细 */
getType(dictId) {
getType(dictId).then(response => {
this.queryParams.dictType = response.data.dictType;
this.defaultDictType = response.data.dictType;
this.getList();
});
},
/** 查询字典类型列表 */
getTypeList() {
getDictOptionselect().then(response => {
this.typeOptions = response.data;
});
},
/** 查询字典数据列表 */
getList() {
this.loading = true;
listData(this.queryParams).then(response => {
this.dataList = response.rows;
this.total = response.total;
this.loading = false;
});
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {
dictCode: undefined,
dictLabel: undefined,
dictValue: undefined,
cssClass: undefined,
listClass: 'default',
dictSort: 0,
status: "0",
remark: undefined
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 返回按钮操作 */
handleClose() {
const obj = { path: "/system/dict" };
this.$tab.closeOpenPage(obj);
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.queryParams.dictType = this.defaultDictType;
this.handleQuery();
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加字典数据";
this.form.dictType = this.queryParams.dictType;
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.dictCode)
this.single = selection.length!=1
this.multiple = !selection.length
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const dictCode = row.dictCode || this.ids
getData(dictCode).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改字典数据";
});
},
/** 提交按钮 */
submitForm: function() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.dictCode != undefined) {
updateData(this.form).then(response => {
this.$store.dispatch('dict/removeDict', this.queryParams.dictType);
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addData(this.form).then(response => {
this.$store.dispatch('dict/removeDict', this.queryParams.dictType);
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const dictCodes = row.dictCode || this.ids;
this.$modal.confirm('是否确认删除字典编码为"' + dictCodes + '"的数据项?').then(function() {
return delData(dictCodes);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
this.$store.dispatch('dict/removeDict', this.queryParams.dictType);
}).catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download('system/dict/data/export', {
...this.queryParams
}, `data_${new Date().getTime()}.xlsx`)
}
}
};
</script>

View File

@ -0,0 +1,349 @@
<template>
<div class="app-container">
<el-card>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<div class="search">
<div class="sl">
<el-form-item label="字典名称" prop="dictName">
<el-input
v-model="queryParams.dictName"
placeholder="请输入字典名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="字典类型" prop="dictType">
<el-input
v-model="queryParams.dictType"
placeholder="请输入字典类型"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="字典状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</div>
</div>
<!-- <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>-->
</el-form>
</el-card>
<el-card class="lrtt">
<div class="rt">
<div class="operate">
<!--
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['system:dict:add']"
>新增</el-button>
<el-button
plain
icon="el-icon-edit"
size="mini"
:disabled="single"
@click="handleUpdate"
v-hasPermi="['system:dict:edit']"
>修改</el-button>
<el-button
plain
icon="el-icon-delete"
size="mini"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['system:dict:remove']"
>删除</el-button>-->
<!--
<el-button
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['system:dict:export']"
>导出</el-button>-->
<el-button
plain
icon="el-icon-refresh"
size="mini"
@click="handleRefreshCache"
v-hasPermi="['system:dict:remove']"
>刷新缓存</el-button>
</div>
<el-table v-loading="loading" :data="typeList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="字典编号" align="center" prop="dictId" />
<el-table-column label="字典名称" align="center" prop="dictName" :show-overflow-tooltip="true" />
<el-table-column label="字典类型" align="center" :show-overflow-tooltip="true">
<template slot-scope="scope">
<router-link :to="'/system/dict-data/index/' + scope.row.dictId" class="link-type">
<span>{{ scope.row.dictType }}</span>
</router-link>
</template>
</el-table-column>
<el-table-column label="状态" align="center" prop="status">
<template slot-scope="scope">
<dict-tag :options="dict.type.sys_normal_disable" :value="scope.row.status"/>
</template>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" :show-overflow-tooltip="true" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<!--
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleUpdate(scope.row)"
v-hasPermi="['system:dict:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
v-hasPermi="['system:dict:remove']"
>删除</el-button>
</template>
</el-table-column>
-->
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</el-card>
<!-- 添加或修改参数配置对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="字典名称" prop="dictName">
<el-input v-model="form.dictName" placeholder="请输入字典名称" />
</el-form-item>
<el-form-item label="字典类型" prop="dictType">
<el-input v-model="form.dictType" placeholder="请输入字典类型" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="form.status">
<el-radio
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitForm"> </el-button>
<el-button @click="cancel"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { bizListType, getType, delType, addType, updateType, refreshCache } from "@/api/system/dict/type";
export default {
name: "Dict",
dicts: ['sys_normal_disable'],
data() {
return {
//
loading: true,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
typeList: [],
//
title: "",
//
open: false,
//
dateRange: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
dictName: undefined,
dictType: undefined,
status: undefined
},
//
form: {},
//
rules: {
dictName: [
{ required: true, message: "字典名称不能为空", trigger: "blur" }
],
dictType: [
{ required: true, message: "字典类型不能为空", trigger: "blur" }
]
}
};
},
created() {
this.getList();
},
methods: {
/** 查询字典类型列表 */
getList() {
this.loading = true;
bizListType(this.addDateRange(this.queryParams, this.dateRange)).then(response => {
this.typeList = response.rows;
this.total = response.total;
this.loading = false;
}
);
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {
dictId: undefined,
dictName: undefined,
dictType: undefined,
status: "0",
remark: undefined
};
this.resetForm("form");
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = [];
this.resetForm("queryForm");
this.handleQuery();
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = "添加字典类型";
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.dictId)
this.single = selection.length!=1
this.multiple = !selection.length
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const dictId = row.dictId || this.ids
getType(dictId).then(response => {
this.form = response.data;
this.open = true;
this.title = "修改字典类型";
});
},
/** 提交按钮 */
submitForm: function() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.dictId != undefined) {
updateType(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.getList();
});
} else {
addType(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.getList();
});
}
}
});
},
/** 删除按钮操作 */
handleDelete(row) {
const dictIds = row.dictId || this.ids;
this.$modal.confirm('是否确认删除字典编号为"' + dictIds + '"的数据项?').then(function() {
return delType(dictIds);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
this.download('system/dict/type/export', {
...this.queryParams
}, `type_${new Date().getTime()}.xlsx`)
},
/** 刷新缓存按钮操作 */
handleRefreshCache() {
refreshCache().then(() => {
this.$modal.msgSuccess("刷新成功");
this.$store.dispatch('dict/cleanDict');
});
}
}
};
</script>

View File

@ -2,49 +2,53 @@
<div class="app-container">
<el-card>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="参数名称" prop="configName">
<el-input
v-model="queryParams.configName"
placeholder="请输入参数名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="参数键名" prop="configKey">
<el-input
v-model="queryParams.configKey"
placeholder="请输入参数键名"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="系统内置" prop="configType">
<el-select v-model="queryParams.configType" placeholder="系统内置" clearable>
<el-option
v-for="dict in dict.type.sys_yes_no"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
<div class="search">
<div class="sl">
<el-form-item label="参数名称" prop="configName">
<el-input
v-model="queryParams.configName"
placeholder="请输入参数名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="参数键名" prop="configKey">
<el-input
v-model="queryParams.configKey"
placeholder="请输入参数键名"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="系统内置" prop="configType">
<el-select v-model="queryParams.configType" placeholder="系统内置" clearable>
<el-option
v-for="dict in dict.type.sys_yes_no"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</div>
</div>
</el-form>
</el-card>

View File

@ -2,28 +2,32 @@
<div class="app-container">
<el-card>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="部门名称" prop="deptName">
<el-input
v-model="queryParams.deptName"
placeholder="请输入部门名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="部门状态" clearable>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
<div class="search">
<div class="sl">
<el-form-item label="部门名称" prop="deptName">
<el-input
v-model="queryParams.deptName"
placeholder="请输入部门名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="部门状态" clearable>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</div>
</div>
</el-form>
</el-card>
<el-card class="lrtt">
@ -96,7 +100,10 @@
</el-card>
<!-- 添加或修改部门对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
<el-dialog :title="title" :visible.sync="open" width="600px"
:close-on-press-escape="false" :close-on-click-modal="false"
:show-close="false" :wrapperClosable="false"
append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-row>
<el-col :span="24" v-if="form.parentId !== 0">
@ -108,7 +115,7 @@
<el-row>
<el-col :span="12">
<el-form-item label="部门名称" prop="deptName">
<el-input v-model="form.deptName" placeholder="请输入部门名称" />
<el-input v-model="form.deptName" placeholder="请输入部门名称" maxlength="50" show-word-limit/>
</el-form-item>
</el-col>
<el-col :span="12">
@ -120,19 +127,19 @@
<el-row>
<el-col :span="12">
<el-form-item label="负责人" prop="leader">
<el-input v-model="form.leader" placeholder="请输入负责人" maxlength="20" />
<el-input v-model="form.leader" placeholder="请输入负责人" maxlength="50" show-word-limit/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="联系电话" prop="phone">
<el-input v-model="form.phone" placeholder="请输入联系电话" maxlength="11" />
<el-input v-model="form.phone" placeholder="请输入联系电话" maxlength="11" show-word-limit/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" />
<el-input v-model="form.email" placeholder="请输入邮箱" maxlength="50" show-word-limit/>
</el-form-item>
</el-col>
<el-col :span="12">
@ -159,7 +166,6 @@
<script>
import { listDept, getDept, delDept, addDept, updateDept, listDeptExcludeChild } from "@/api/system/dept";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
name: "Dept",

View File

@ -71,12 +71,12 @@
@click="handleExport"
v-hasPermi="['system:dict:export']"
>导出</el-button>
<el-button
<!-- <el-button
plain
icon="el-icon-close"
size="mini"
@click="handleClose"
>关闭</el-button>
>关闭</el-button>-->
</div>
<el-table v-loading="loading" :data="dataList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" />

View File

@ -2,54 +2,62 @@
<div class="app-container">
<el-card>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="字典名称" prop="dictName">
<el-input
v-model="queryParams.dictName"
placeholder="请输入字典名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="字典类型" prop="dictType">
<el-input
v-model="queryParams.dictType"
placeholder="请输入字典类型"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="字典状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<div class="search">
<div class="sl">
<el-form-item label="字典名称" prop="dictName">
<el-input
v-model="queryParams.dictName"
placeholder="请输入字典名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="字典类型" prop="dictType">
<el-input
v-model="queryParams.dictType"
placeholder="请输入字典类型"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="字典状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</div>
</div>
<!-- <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form-item>-->
</el-form>
</el-card>
@ -80,13 +88,14 @@
@click="handleDelete"
v-hasPermi="['system:dict:remove']"
>删除</el-button>
<!--
<el-button
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['system:dict:export']"
>导出</el-button>
>导出</el-button>-->
<el-button
plain
icon="el-icon-refresh"

View File

@ -2,28 +2,36 @@
<div class="app-container">
<el-card>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="菜单名称" prop="menuName">
<el-input
v-model="queryParams.menuName"
placeholder="请输入菜单名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="菜单状态" clearable>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<div class="search">
<div class="sl">
<el-form-item label="菜单名称" prop="menuName">
<el-input
v-model="queryParams.menuName"
placeholder="请输入菜单名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="菜单状态" clearable>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</div>
</div>
<!-- <el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form-item>-->
</el-form>
</el-card>
<el-card class="lrtt">
@ -275,7 +283,6 @@
<script>
import { listMenu, getMenu, delMenu, addMenu, updateMenu } from "@/api/system/menu";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
import IconSelect from "@/components/IconSelect";
export default {

View File

@ -2,36 +2,41 @@
<div class="app-container">
<el-card>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="公告标题" prop="noticeTitle">
<el-input
v-model="queryParams.noticeTitle"
placeholder="请输入公告标题"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="操作人员" prop="createBy">
<el-input
v-model="queryParams.createBy"
placeholder="请输入操作人员"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="类型" prop="noticeType">
<el-select v-model="queryParams.noticeType" placeholder="公告类型" clearable>
<el-option
v-for="dict in dict.type.sys_notice_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
<div class="search">
<div class="sl">
<el-form-item label="公告标题" prop="noticeTitle">
<el-input
v-model="queryParams.noticeTitle"
placeholder="请输入公告标题"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="操作人员" prop="createBy">
<el-input
v-model="queryParams.createBy"
placeholder="请输入操作人员"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="类型" prop="noticeType">
<el-select v-model="queryParams.noticeType" placeholder="公告类型" clearable>
<el-option
v-for="dict in dict.type.sys_notice_type"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</div>
</div>
</el-form>
</el-card>

View File

@ -2,36 +2,40 @@
<div class="app-container">
<el-card>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="岗位编码" prop="postCode">
<el-input
v-model="queryParams.postCode"
placeholder="请输入岗位编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="岗位名称" prop="postName">
<el-input
v-model="queryParams.postName"
placeholder="请输入岗位名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="岗位状态" clearable>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
<div class="search">
<div class="sl">
<el-form-item label="岗位编码" prop="postCode">
<el-input
v-model="queryParams.postCode"
placeholder="请输入岗位编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="岗位名称" prop="postName">
<el-input
v-model="queryParams.postName"
placeholder="请输入岗位名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="岗位状态" clearable>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</div>
</div>
</el-form>
</el-card>
<el-card class="lrtt">

View File

@ -2,54 +2,58 @@
<div class="app-container">
<el-card>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch">
<el-form-item label="角色名称" prop="roleName">
<el-input
v-model="queryParams.roleName"
placeholder="请输入角色名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="权限字符" prop="roleKey">
<el-input
v-model="queryParams.roleKey"
placeholder="请输入权限字符"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="角色状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
<div class="search">
<div class="sl">
<el-form-item label="角色名称" prop="roleName">
<el-input
v-model="queryParams.roleName"
placeholder="请输入角色名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="权限字符" prop="roleKey">
<el-input
v-model="queryParams.roleKey"
placeholder="请输入权限字符"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="角色状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</div>
</div>
</el-form>
</el-card>
<el-card class="lrtt">
@ -79,13 +83,14 @@
@click="handleDelete"
v-hasPermi="['system:role:remove']"
>删除</el-button>
<!--
<el-button
plain
icon="el-icon-download"
size="mini"
@click="handleExport"
v-hasPermi="['system:role:export']"
>导出</el-button>
>导出</el-button>-->
</div>
<el-table v-loading="loading" :data="roleList" @selection-change="handleSelectionChange">
@ -149,10 +154,13 @@
</el-card>
<!-- 添加或修改角色配置对话框 -->
<el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
<el-dialog :title="title" :visible.sync="open" width="500px"
append-to-body :close-on-press-escape="false" :close-on-click-modal="false"
:show-close="false" :wrapperClosable="false"
append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
<el-form-item label="角色名称" prop="roleName">
<el-input v-model="form.roleName" placeholder="请输入角色名称" />
<el-input v-model="form.roleName" placeholder="请输入角色名称" maxlength="50" show-word-limit/>
</el-form-item>
<el-form-item prop="roleKey">
<span slot="label">
@ -161,7 +169,7 @@
</el-tooltip>
权限字符
</span>
<el-input v-model="form.roleKey" placeholder="请输入权限字符" />
<el-input v-model="form.roleKey" placeholder="请输入权限字符" maxlength="70" show-word-limit/>
</el-form-item>
<el-form-item label="角色顺序" prop="roleSort">
<el-input-number v-model="form.roleSort" controls-position="right" :min="0" />
@ -201,7 +209,10 @@
</el-dialog>
<!-- 分配角色数据权限对话框 -->
<el-dialog :title="title" :visible.sync="openDataScope" width="500px" append-to-body>
<el-dialog :title="title" :visible.sync="openDataScope" width="500px"
:close-on-press-escape="false" :close-on-click-modal="false"
:show-close="false" :wrapperClosable="false"
append-to-body>
<el-form :model="form" label-width="80px">
<el-form-item label="角色名称">
<el-input v-model="form.roleName" :disabled="true" />
@ -292,7 +303,8 @@ export default {
{
value: "3",
label: "本部门数据权限"
},
}
,
{
value: "4",
label: "本部门及以下数据权限"

View File

@ -224,7 +224,6 @@
<script>
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
components: { Treeselect },

View File

@ -2,54 +2,58 @@
<div class="app-container">
<el-card>
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="用户名称" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input
v-model="queryParams.phonenumber"
placeholder="请输入手机号码"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="用户状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
<div class="search">
<div class="sl">
<el-form-item label="用户名称" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input
v-model="queryParams.phonenumber"
placeholder="请输入手机号码"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select
v-model="queryParams.status"
placeholder="用户状态"
clearable
style="width: 240px"
>
<el-option
v-for="dict in dict.type.sys_normal_disable"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</div>
</div>
</el-form>
</el-card>
<el-card class="lrtt">
@ -101,6 +105,7 @@
@click="handleDelete"
v-hasPermi="['system:user:remove']"
>删除</el-button>
<!--
<el-button
plain
icon="el-icon-upload2"
@ -114,7 +119,7 @@
size="mini"
@click="handleExport"
v-hasPermi="['system:user:export']"
>导出</el-button>
>导出</el-button>-->
</div>
<el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
@ -183,7 +188,10 @@
</el-card>
<!-- 添加或修改用户配置对话框 -->
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
<el-dialog :title="title" :visible.sync="open" width="600px"
:close-on-press-escape="false" :close-on-click-modal="false"
:show-close="false" :wrapperClosable="false"
append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-row>
<el-col :span="12">
@ -261,7 +269,7 @@
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="角色">
<el-form-item label="角色" prop="roleIds">
<el-select v-model="form.roleIds" multiple placeholder="请选择角色">
<el-option
v-for="item in roleOptions"
@ -289,7 +297,10 @@
</el-dialog>
<!-- 用户导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px"
:close-on-press-escape="false" :close-on-click-modal="false"
:show-close="false" :wrapperClosable="false"
append-to-body>
<el-upload
ref="upload"
:limit="1"
@ -325,7 +336,6 @@ import { listUser, getUser, delUser, addUser, updateUser, resetUserPwd, changeUs
import { getToken } from "@/utils/auth";
import { Base64 } from 'js-base64'
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
name: "User",
@ -412,6 +422,9 @@ export default {
nickName: [
{ required: true, message: "用户昵称不能为空", trigger: "blur" }
],
deptId: [
{ required: true, message: "归属部门不能为空", trigger: "blur" }
],
password: [
{ required: true, message: "用户密码不能为空", trigger: "blur" },
{ min: 5, max: 20, message: '用户密码长度必须介于 5 和 20 之间', trigger: 'blur' },
@ -430,7 +443,10 @@ export default {
message: "请输入正确的手机号码",
trigger: "blur"
}
]
],
roleIds: [
{ required: true, message: "角色不能为空", trigger: "blur" }
],
}
};
},

View File

@ -7,9 +7,9 @@
<span>个人信息</span>
</div>
<div>
<div class="text-center">
<!-- <div class="text-center">
<userAvatar />
</div>
</div>-->
<ul class="list-group list-group-striped">
<li class="list-group-item">
<svg-icon icon-class="user" />用户名称
@ -19,10 +19,10 @@
<svg-icon icon-class="phone" />手机号码
<div class="pull-right">{{ user.phonenumber }}</div>
</li>
<li class="list-group-item">
<!-- <li class="list-group-item">
<svg-icon icon-class="email" />用户邮箱
<div class="pull-right">{{ user.email }}</div>
</li>
</li>-->
<li class="list-group-item">
<svg-icon icon-class="tree" />所属部门
<div class="pull-right" v-if="user.dept">{{ user.dept.deptName }} / {{ postGroup }}</div>

View File

@ -2,13 +2,13 @@
<el-form ref="form" :model="form" :rules="rules" label-width="80px">
<el-form-item label="用户昵称" prop="nickName">
<el-input v-model="form.nickName" maxlength="30" />
</el-form-item>
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input v-model="form.phonenumber" maxlength="11" />
</el-form-item>
<el-form-item label="邮箱" prop="email">
<!-- <el-form-item label="邮箱" prop="email">
<el-input v-model="form.email" maxlength="50" />
</el-form-item>
</el-form-item>-->
<el-form-item label="性别">
<el-radio-group v-model="form.sex">
<el-radio label="0"></el-radio>

View File

@ -1,9 +1,9 @@
<template>
<el-dialog title="新增文档" :visible.sync="visible" width="85%" append-to-body>
<edit-document ref="editDocumentRef" :toolId="toolId" @submit="editDocumentSubmit"/>
<el-dialog title="新增附件信息" :visible.sync="visible" width="85%" append-to-body>
<edit-document ref="editDocumentRef" :toolId="toolId" @docSubmitData="editDocumentSubmit" :relatedTool="false"/>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="$refs.editDocumentRef.submitForm()"> </el-button>
<el-button @click="cancel()"></el-button>
<el-button type="primary" icon="el-icon-check" @click="submitForm()"> </el-button>
<el-button icon="el-icon-close" @click="cancel()"></el-button>
</div>
</el-dialog>
</template>
@ -26,7 +26,7 @@ export default {
*/
toolId: {
type: String,
default: true
default: ''
}
},
computed: {
@ -45,13 +45,19 @@ export default {
}
},
methods: {
editDocumentSubmit(){
this.$emit('callback')
editDocumentSubmit(data){
this.$emit("addFileData", data)
this.visible = false
},
cancel() {
this.$refs.editDocumentRef.cancel()
this.visible = false
},
submitForm(){
this.$refs.editDocumentRef.assembleSubmit()
},
resetForm(){
this.$refs.editDocumentRef.resetForm()
}
}
}

View File

@ -0,0 +1,165 @@
<template>
<div class="fbox1">
<div class="fl">
<el-tabs v-model="detailActiveName">
<el-tab-pane label="附件信息" name="first" v-loading="previewLoading" element-loading-text="预览转换中,请耐心等待">
<el-table :data="attachmentList" style="width: 100%">
<el-table-column label="序号" width="60" align="center" type="index"></el-table-column>
<el-table-column label="附件名称" prop="fileName" :show-overflow-tooltip="true" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createDate) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="180" v-if="toolDetail.downloadStatus">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
v-if="previewAuth(scope.row)"
@click="handlePreview(scope.row)"
>预览</el-button>
<el-button type="text" icon="el-icon-download" @click="handleDownload(scope.row)" v-loading="loadingDownload">下载</el-button>
</template>
</el-table-column>
</el-table><!--el-table-->
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getAttachmentList"
/>
</el-tab-pane><!--el-tab-pane-->
</el-tabs><!--el-tabs-->
</div><!--fl 左侧页签-->
<preview-util v-if="isPreviewDisable" ref="previewForm" @previewClose="previewClose" @previewLoadingClose="previewLoadingClose"></preview-util>
</div><!--fbox1 左右分栏-->
</template>
<script>
import { addCount } from "@/api/tool/downloadCount";
import { listAttachment } from "@/api/attachment/attachment";
import previewUtil from '@/components/PreviewUtil/previewUtil.vue'
export default {
name: 'toolDetail',
components: { previewUtil},
dicts:[],
props: {
toolDetail: {
type: Object,
default: {},
}
},
data(){
return{
detailActiveName: 'first',
attachmentList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
toolId: ''
},
previewUrl: '',
viewDialogTitle: "",
viewDialogOpen: false,
title: '新增文档',
open: false,
loadingDownload: false,
discussionContent: null, //
repliesContent: null, //
//
discussionsList: [],
//
repliesList: [],
showReplyForm: [],
replyContent: [],
isPreviewDisable: false,
attFileType: "zip,rar,7z",
total: 0,
previewLoading:false,
}
},
created(){
this.getAttachmentList()
},
methods:{
getAttachmentList() {
this.loading = true;
this.$set(this.queryParams,'del',"0")
this.$set(this.queryParams,'businessId',this.toolDetail.toolId)
listAttachment(this.queryParams).then(response => {
this.attachmentList = response.rows;
this.total = response.total;
this.loading = false;
}
);
},
handlePreview(row){
this.isPreviewDisable = true
this.previewLoading = true
this.$nextTick(() => {
this.$refs.previewForm.frontModulePreview(row)
})
},
/** 关闭预览 **/
previewClose(){
this.isPreviewDisable = false
},
/** 关闭预览遮罩 **/
previewLoadingClose(){
this.previewLoading = false
},
previewAuth(row){
if(row.fileUrl == null || row.fileUrl == '' || row.fileUrl == undefined){
return false
}
let extension = this.getExtension(row.fileUrl);
const acceptedExtensions = this.attFileType.toLowerCase().split(',');
if(acceptedExtensions.includes(extension)){
return false
}
return true
},
getExtension(filePath) {
// '.'
const parts = filePath.split('.');
//
const extension = parts.pop();
return extension;
},
/**
* 处理下载
* **/
handleDownload(row){
let self = this
self.loadingDownload = true
this.$download.resource(row.fileUrl);
//
if(row.businessId){
let formData = {
'businessId': row.businessId,
'businessType': 'tool',
'attId': row.id,
'attName': row.fileOldName
}
addCount(formData).then(res => {
});
}
setTimeout(()=>{
self.loadingDownload = false
},1000)
},
}
}
</script>
<style scoped>
</style>

File diff suppressed because it is too large Load Diff

View File

@ -1,109 +1,296 @@
<template>
<div class="fbox1">
<div class="fl">
<div class="fl" v-loading="detailLoading">
<el-tabs v-model="detailActiveName">
<el-tab-pane label="基本信息" name="first">
<div class="el-form-border">
<el-form ref="form" label-width="150px">
<el-row>
<el-col :span="12"> <el-form-item label="工具名称">工具名称2</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="工具类别">网络工具</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="工具来源">单位自建</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="负责人">赵宁宇</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="归属单位">人力资源部/员工关系组</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="状态"><span class="green">启用中</span></el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="工具用途">主要用于单位网络使用</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="测评情况">运行良好可正常使用</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="功能描述">单位网络使用</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="适用条件">网络正常</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="操作说明">正常开启即可用</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="备注">工具使用完成后请做好保养工作</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="工具名称">{{detailData.toolName}}</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="工具类别"><dict-tag :options="dict.type.tool_type" :value="detailData.toolType"/></el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="工具来源"><dict-tag :options="dict.type.tool_source" :value="detailData.toolSource"/></el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="负责人">{{detailData.toolPrincipalsName}}</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="归属单位">{{detailData.toolRespDeptName}}</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="工具状态"><dict-tag :options="dict.type.tool_status" :value="detailData.status"/></el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="工具用途">{{detailData.toolUse}}</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="测评情况">{{detailData.testSituation}}</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="功能描述">{{detailData.functionDesc}}</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="适用条件">{{detailData.applyCondition}}</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="操作说明">{{detailData.operateExplain}}</el-form-item> </el-col>
<el-col :span="12"> <el-form-item label="备注">{{detailData.remark}}</el-form-item> </el-col>
<el-col :span="24">
<el-form-item label="关联工具">
<span v-if="detailData.association != null && detailData.association != '' && detailData.association != undefined">
<el-tag :key="tag.toolId" v-for="tag in detailData.association" type="info" style="margin-right: 5px">{{tag.toolName}}</el-tag>
</span>
</el-form-item>
</el-col>
</el-row>
</el-form><!--el-form-->
</div><!--el-form-border 表单-->
</el-tab-pane><!--el-tab-pane-->
<el-tab-pane label="关联文件" name="second">
<div class="operate">
<el-button type="primary" icon="el-icon-upload2" @click="handleAdd">上传</el-button>
<el-button icon="el-icon-delete">删除</el-button>
</div><!--operate 操作按钮-->
<el-table :data="docList" style="width: 100%">
<el-table-column type="selection" width="50" align="center"> </el-table-column>
<el-table-column label="文档名称" prop="docName" :show-overflow-tooltip="true" />
<el-table-column label="类别" prop="docType" :show-overflow-tooltip="true" width="80" />
<el-table-column label="负责人" prop="docPrincipals" :show-overflow-tooltip="true" width="80" />
<el-table-column label="归属部门" prop="docRespDept" :show-overflow-tooltip="true" width="150" />
<el-table-column label="来源" prop="docSource" width="100" />
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<el-tab-pane label="关联附件" name="second" v-loading="previewLoading" element-loading-text="预览转换中,请耐心等待">
<el-table :data="attachmentList" style="width: 100%">
<el-table-column label="附件名称" prop="fileName" :show-overflow-tooltip="true" />
<!-- <el-table-column label="类别" prop="docType" :show-overflow-tooltip="true" width="80" >
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
<dict-tag :options="dict.type.doc_class" :value="scope.row.docType"/>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="180">
<template slot-scope="scope" v-if="scope.row.roleId !== 1">
<el-table-column label="负责人" prop="docPrincipals" :show-overflow-tooltip="true" width="80" />
<el-table-column label="归属单位" align="center" prop="docRespDeptName" :show-overflow-tooltip="true" width="80" />
<el-table-column label="来源" prop="docSource" width="100" >
<template slot-scope="scope">
<dict-tag :options="dict.type.doc_source" :value="scope.row.docSource"/>
</template>
</el-table-column>-->
<el-table-column label="创建时间" align="center" prop="createTime" width="180">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createDate) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="150px">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-view"
@click="handlePriew(scope.row)"
v-if="previewAuth(scope.row)"
@click="handlePreview(scope.row)"
>预览</el-button>
<el-button
size="mini"
type="text"
icon="el-icon-delete"
@click="handleDelete(scope.row)"
>删除</el-button>
<el-button type="text" icon="el-icon-download">下载</el-button>
<el-button type="text" icon="el-icon-download" v-if="detailData.downloadStatus" @click="handleDownload(scope.row)" v-loading="loadingDownload">
下载
</el-button>
</template>
</el-table-column>
</el-table><!--el-table-->
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getAttachmentList"
/>
</el-tab-pane><!--el-tab-pane-->
</el-tabs><!--el-tabs-->
</div><!--fl 左侧页签-->
<div class="fr" v-if="isComment">
<div class="tboper">
<div class="tit">评论{{ reviewTotal }}</div>
</div><!--tboper 标题与操作按钮-->
<div class="pltextarea">
<el-input v-model="discussionContent" type="textarea" placeholder="请输入您的意见" :rows="4" maxlength="1000" show-word-limit></el-input>
<div class="plbtn"><el-button @click="handleDiscussions">发布</el-button></div>
</div><!--pltextarea-->
<div class="pllist">
<template v-if="discussionsList && discussionsList.length > 0">
<div class="list" v-for="(item,index) in discussionsList" :key="item.id">
<div class="luser"><span class="xuser" :style="{backgroundColor: extractColorByName(item.nickName)}">{{getFirstChar(item.nickName)}}</span></div>
<div class="ltext">
<div class="nt"><span class="name">{{item.nickName}}</span><span class="time">{{ parseTime(item.createTime, '{y}-{m}-{d} {h}:{i}') }}</span></div>
<div class="te">{{item.content}}</div>
<div class="hb">
<a class="btn" @click="toggleReplyForm(index)">
<i class="el-icon-chat-line-round"></i>回复
</a>
</div>
<div class="pltextarea" v-if="showReplyForm[index]">
<el-input type="textarea" v-model="replyContent[index]" placeholder="请输入您的意见" :rows="2" maxlength="1000" show-word-limit></el-input>
<div class="plbtn">
<el-button @click="cancelReply(index)">取消</el-button>
<el-divider direction="vertical"></el-divider>
<el-button @click="submitReply(index, item)">发布</el-button>
</div>
</div>
<!--第二层级-->
<template v-if="item.repliesList && item.repliesList.length > 0">
<div class="list" v-for="(repItem, repIdex) in item.repliesList" :key="repItem.id">
<div class="luser">
<span class="xuser" :style="{width:'28px',height:'28px',lineHeight:'28px',backgroundColor: extractColorByName(repItem.nickName)}">{{getFirstChar(repItem.nickName)}}</span>
</div>
<div class="ltext">
<div class="nt">
<span class="name">{{repItem.nickName}}</span>
<template v-if="repItem.repTargetNickName">
<span>回复</span>
<span class="name">{{ repItem.repTargetNickName }}</span>
</template>
<span class="time">{{ parseTime(repItem.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
</div>
<div class="te">{{repItem.content}}</div>
<div class="hb"><a class="btn" @click="toggleReplyFormSon(index,repIdex)"><i class="el-icon-chat-line-round"></i>回复</a></div>
<div class="pltextarea" v-if="item.showReplyFormSon[repIdex]">
<el-input type="textarea" v-model="item.replyContentSon[repIdex]" placeholder="请输入您的意见" :rows="2" maxlength="1000" show-word-limit></el-input>
<div class="plbtn">
<el-button @click="cancelReplySon(index,repIdex)">取消</el-button>
<el-divider direction="vertical"></el-divider>
<el-button @click="submitReplySon(index, repIdex, item, repItem.id)">发布</el-button>
</div>
</div>
</div>
</div>
</template>
</div>
</div>
</template>
</div>
</div>
<el-dialog :title="viewDialogTitle" :visible.sync="viewDialogOpen" fullscreen width="500px" append-to-body :before-close="handleBeforeClose">
<i-frame :src="previewUrl" v-if="viewDialogOpen"/>
</el-dialog>
<preview-util v-if="isPreviewDisable" ref="previewForm" @previewClose="previewClose" @previewLoadingClose="previewLoadingClose"></preview-util>
<!-- 关联工具展示 -->
<el-dialog title="关联工具" :visible.sync="toolTreeVisible" width="980px" append-to-body :close-on-press-escape="false" :close-on-click-modal="false"
:show-close="false" :wrapperClosable="false" v-loading="toolTreeLoading">
<el-tree :data="toolRelationOptions" :props="defaultProps"></el-tree>
<!-- <el-table
:data="relationToolData"
border
ref="multipleTable"
header-align="left"
>
<el-table-column label="序号" width="60" type="index" align="center"></el-table-column>
<el-table-column label="工具编号" key="toolCode" prop="toolCode"/>
<el-table-column label="工具名称" key="toolName" prop="toolName":show-overflow-tooltip="true" />
<el-table-column label="操作" width="100px" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="selectDelete(scope.row)"
>删除</el-button>
</template>
</el-table-column>
</el-table>
&lt;!&ndash; 分页组件 &ndash;&gt;
<el-pagination
v-show="relationToolTotal > 0"
:current-page.sync="currentToolPage"
:page-size.sync="pageToolSize"
:total="relationToolTotal"
@current-change="handlePageToolChange"
layout="total, prev, pager, next"
/>-->
<span slot="footer" class="dialog-footer">
<el-button icon="el-icon-close" @click="toolTreeVisible = false"> </el-button>
</span>
</el-dialog>
<!-- 上传 -->
<AddDoc :show.sync="open" :toolId="toolDetail.toolId" @callback="getDocList"/>
<!-- <AddDoc :show.sync="open" :toolId="detailData.toolId" @callback="getAttachmentList"/>-->
</div><!--fbox1 左右分栏-->
</template>
<script>
import { listDocument, getDocument, delDocument, addDocument, updateDocument } from "@/api/document/document";
import AddDoc from './AddDoc'
import editDocument from "../document/editDocument";
import { Base64 } from 'js-base64';
import { listDiscussions, addDiscussions } from "@/api/tool/discussions.js";
import { listReplies, addReplies} from "@/api/tool/replies.js";
import { getTool } from "@/api/tool/tool.js";
import iFrame from "@/components/iFrame/index"
import { addCount } from "@/api/tool/downloadCount";
import { listAttachment } from "@/api/attachment/attachment";
import previewUtil from '@/components/PreviewUtil/previewUtil.vue'
import { getDataThree } from '@/api/tool/toolRelation'
export default {
name: 'toolDetail',
components: { editDocument, AddDoc },
components: { iFrame, previewUtil },
dicts:['sys_normal_disable','tool_type','tool_source','tool_status','doc_class','doc_source'],
props: {
toolDetail: {
type: Object,
default: {},
}
required: false
},
//
isDownload: {
type: Boolean,
default: true,
required: false
},
//
isComment: {
type: Boolean,
default: true,
required: false
},
},
data(){
return{
detailActiveName: 'first',
docList: [],
attachmentList: [],
queryParams: {
pageNum: 1,
pageSize: 10,
toolId: ''
},
reviewTotal: 0,
previewUrl: '',
viewDialogTitle: "",
viewDialogOpen: false,
title: '新增文档',
open: false,
loadingDownload: false,
discussionContent: null, //
repliesContent: null, //
//
discussionsList: [],
//
repliesList: [],
showReplyForm: [],
replyContent: [],
detailLoading: false,
//
detailData:{},
attFileType: "zip,rar,7z",
// json
dialogVisible:false,
isJson:false,
resultContentObj:[],
// docx
isDocx:false,
docxData: null,
//pdf
isPdf:false,
pdfFileData: null, //
previewLoading:false,
previewUseFront: "txt,doc,docx,pdf",
isPreviewDisable: false,
total: 0,
//
toolTreeVisible: false,
toolTreeLoading: false,
toolDataList: [],
defaultProps: {
children: 'children',
label: 'label'
},
//
toolRelationOptions: [],
}
},
created(){
this.getDocList()
this.getDetail()
this.getAttachmentList()
this.getDiscussionsList()
},
watch: {
discussionsList(newList) {
this.showReplyForm = new Array(newList.length).fill(false);
this.replyContent = new Array(newList.length).fill('');
}
},
methods:{
getDocList() {
getAttachmentList() {
this.loading = true;
this.queryParams.toolId = this.toolDetail.toolId
listDocument(this.queryParams).then(response => {
this.docList = response.rows;
this.$set(this.queryParams,'del',"0")
this.$set(this.queryParams,'businessId',this.toolDetail.toolId)
listAttachment(this.queryParams).then(response => {
this.attachmentList = response.rows;
this.total = response.total;
this.loading = false;
}
@ -114,12 +301,21 @@
},
editDocumentSubmit(){
this.open = false
this.getDocList()
this.getAttachmentList()
},
handlePriew(row){
this.previewUrl = process.env.VUE_APP_TOOL_TECH_FILE_VIEW_API + '/onlinePreview?url=' + encodeURIComponent(Base64.encode(process.env.VUE_APP_BASE_API + row.docUrl));
this.viewDialogTitle = '文档在线预览'
this.viewDialogOpen = true;
handlePreview(row){
this.isPreviewDisable = true
this.$nextTick(() => {
this.$refs.previewForm.frontModulePreview(row)
})
},
/** 关闭预览 **/
previewClose(){
this.isPreviewDisable = false
},
/** 关闭预览遮罩 **/
previewLoadingClose(){
this.previewLoading = false
},
/** 删除按钮操作 */
handleDelete(row) {
@ -130,7 +326,263 @@
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
}
},
/**
* 处理下载
* **/
handleDownload(row){
let self = this
self.loadingDownload = true
this.$download.resource(row.fileUrl);
//
if(row.businessId){
let formData = {
'businessId': row.businessId,
'businessType': 'tool',
'attId': row.id,
'attName': row.fileOldName
}
addCount(formData).then(res => {
});
}
setTimeout(()=>{
self.loadingDownload = false
},1000)
},
getDiscussionsList() {
let _this = this
_this.reviewTotal = 0
listDiscussions({businessId: _this.toolDetail.toolId}).then(res => {
_this.discussionsList = res.rows
let reviewTotal = 0
_this.discussionsList.forEach(item => {
if(item.repliesList && item.repliesList.length > 0){
reviewTotal += item.repliesList.length
_this.$set(item, 'showReplyFormSon', new Array(item.repliesList.length).fill(false))
_this.$set(item, 'replyContentSon', new Array(item.repliesList.length).fill(''))
}else{
_this.$set(item, 'showReplyFormSon', false)
_this.$set(item, 'replyContentSon', '')
}
});
_this.reviewTotal = _this.discussionsList.length + reviewTotal
});
},
/** 评论 **/
handleDiscussions(){
let self = this
if (this.discussionContent == '' || this.discussionContent == null || this.discussionContent == undefined) {
self.$message({
message: '内容不能为空',//
type:'warning',  //
duration:1200,  //, 0 1200
});
return;
}
let data = {
businessId: this.toolDetail.toolId,
content: this.discussionContent,
type: "tool",
}
self.$modal.confirm('是否确认发布?').then(()=> {
addDiscussions(data).then(res => {
this.discussionContent = null
self.$message({
message: '发布成功',//
type:'success',  //
duration:1200,  //, 0 1200
});
self.getDiscussionsList()
}).catch(err =>{
this.discussionContent = null
console.error("handleDiscussions==err==", err)
self.$modal.msgError("发布失败");
});
})
},
extractColorByName(name) {
let temp = [];
temp.push("#");
for (let index = 0; index < name.length; index++) {
temp.push(parseInt(name[index].charCodeAt(0), 10).toString(16));
}
return temp.slice(0, 5).join('').slice(0, 4);
},
getFirstChar(value) {
if(!value){return ''}
return value.charAt(0);
},
toggleReplyForm(index) {
this.$set(this.showReplyForm, index, !this.showReplyForm[index]);
},
cancelReply(index) {
this.$set(this.showReplyForm, index, false);
this.$set(this.replyContent, index, '');
},
/** 回复 **/
submitReply(index, item) {
let self = this
const content = this.replyContent[index];
if (content == '' || content == null || content == undefined) {
self.$message({
message: '回复内容不能为空',//
type:'warning',  //
duration:1200,  //, 0 1200
});
return;
}
let data = {
"discussionId": item.id,
"content": content,
}
self.$modal.confirm('是否确认发布?').then(()=> {
addReplies(data).then(res => {
self.$message({
message: '发布成功',//
type:'success',  //
duration:1200,  //, 0 1200
});
self.cancelReply(index)
self.getDiscussionsList()
}).catch(err =>{
console.error("handleDiscussions==err==", err)
self.$modal.msgError("发布失败");
});
})
//
this.replyContent[index] = '';
this.showReplyForm[index] = false;
},
/** 第二级 **/
toggleReplyFormSon(parentIndex, repIndex) {
const parentItem = this.discussionsList[parentIndex];
this.$set(parentItem.showReplyFormSon, repIndex, !parentItem.showReplyFormSon[repIndex]);
// this.$set(this.showReplyFormSon, index, !this.showReplyFormSon[index]);
},
/** 第二级,取消回复 **/
cancelReplySon(parentIndex, repIndex) {
const parentItem = this.discussionsList[parentIndex];
this.$set(parentItem.showReplyFormSon, repIndex, false);
this.$set(parentItem.replyContentSon, repIndex, '');
},
/** 第二级回复 **/
submitReplySon(parentIndex, repIndex, repItem, repId) {
let self = this
const parentItem = this.discussionsList[parentIndex];
const content = parentItem.replyContentSon[repIndex];
if (content.trim() == '' || content == null || content == undefined) {
self.$message({
message: '回复内容不能为空',//
type:'warning',  //
duration:1200,  //, 0 1200
});
return;
}
let data = {
"discussionId": repItem.id,
"repId": repId,
"content": content,
}
self.$modal.confirm('是否确认发布?').then(()=> {
addReplies(data).then(res => {
self.$message({
message: '发布成功',//
type:'success',  //
duration:1200,  //, 0 1200
});
self.cancelReplySon(parentIndex, repIndex)
self.getDiscussionsList()
//
this.$set(parentItem.replyContentSon, repIndex, '');
this.$set(parentItem.showReplyFormSon, repIndex, false);
}).catch(err =>{
console.error("submitReplySon==err==", err)
self.$modal.msgError("发布失败");
});
})
},
handleBeforeClose() {
this.viewDialogOpen = false
},
/** 获取详情信息 **/
getDetail(){
let self = this
self.detailLoading = true
getTool(self.toolDetail.toolId).then((res) => {
self.detailData = res.data
self.detailData.association = JSON.parse(res.data.association)
/*let formData = res.data;
formData.type = _this.form.type
_this.form = formData*/
}).finally(()=>{
self.detailLoading = false
});
},
previewAuth(row){
if(row.fileUrl == null || row.fileUrl == '' || row.fileUrl == undefined){
return false
}
let extension = this.getExtension(row.fileUrl);
const acceptedExtensions = this.attFileType.toLowerCase().split(',');
if(acceptedExtensions.includes(extension)){
return false
}
return true
},
getExtension(filePath) {
// '.'
const parts = filePath.split('.');
//
const extension = parts.pop();
return extension;
},
/** 获取工具关联树展示 */
getToolRelationTree() {
let self = this
let toolRelation ={
resourceId: "",
}
let toolIds = []
if(self.detailData.toolId){
self.$set(toolRelation,"resourceIds",[self.detailData.toolId])
}else if(self.detailData.association && self.detailData.association.length > 0){
self.detailData.association.forEach(item=>{
toolIds.push(item.toolId)
})
self.$set(toolRelation,"resourceIds",toolIds)
}
self.toolTreeVisible = true;
self.toolTreeLoading = true;
getDataThree(toolRelation).then(res => {
if(self.detailData.toolName){
let treeArray = []
let treeData = {
"id": "20240908001",
"label": self.detailData.toolName,
"types": null,
"children": res.data
}
treeArray.push(treeData)
this.toolRelationOptions = treeArray;
self.toolTreeLoading = false;
return
}
this.toolRelationOptions = res.data;
self.toolTreeLoading = false;
}).catch(err => {
console.error("err========", err)
self.toolTreeLoading = false;
});
},
}
}
</script>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,665 @@
<template>
<div v-loading="loading || detailLoading">
<div class="drawer-head">
<div class="cell-title">
<div>
<p class="title">申请使用</p>
</div>
</div>
<div class="cell-btn">
<el-button type="primary" v-if="pListData&&pListData.procInstId" @click="handleMonitor" icon="el-icon-data-line">流程监控</el-button>
<el-button v-if="editStatus&&pListData.procInstId" type="danger" @click="deleteForm" icon="el-icon-close">撤销</el-button>
<el-button v-if="(editStatus||workflowStatus)" type="primary" @click="submitForm" icon="el-icon-finished">提交</el-button>
<el-button @click="close" icon="el-icon-close">关闭</el-button>
</div>
</div>
<template v-if="attributeModelBool('approve') && workflowStatus">
<div class="tboper">
<div class="tit"> {{submitLabel}}</div>
</div><!--tboper 标题与操作按钮-->
<div class="el-form-border">
<el-form>
<el-row>
<el-col :span="24">
<el-form-item :label="submitLabel+'结论:'" prop="pass">
<el-radio-group v-model.trim="formSubmit.pass">
<el-radio
v-for="dict in passoptions"
:key="dict.value"
:label="dict.value"
>{{ dict.label }}</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
</el-row>
<el-row >
<el-col :span="24">
<el-form-item :label="submitLabel+'意见:'">
<el-input
v-model="formSubmit.summary"
type="textarea"
:placeholder="'请输入'+submitLabel+'意见'"
maxlength="200"
:autosize="{ minRows: 4, maxRows: 4 }"
:style="{ width: '100%' }"
></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</template>
<div class="divide double"></div><!--divide 分隔-->
<div class="tboper">
<div class="tit">申请信息</div>
</div>
<div class="el-form-border">
<el-form ref="eForm" :model="form" :rules="rules" label-width="150px">
<div>
<el-row>
<el-col :span="24">
<el-form-item label="申请人">
<span>{{form.nickName}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="申请部门" prop="deptId">
<span>{{form.deptName}}</span>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="申请理由" prop="reason">
<el-input :readonly="!editStatus" v-model="form.reason" type="textarea" :rows="3" maxlength="1000" show-word-limit></el-input>
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
</div><!--el-form-border 表单-->
<div class="divide double"></div><!--divide 分隔-->
<div class="tboper">
<div class="tit">申请工具</div>
</div><!--tboper 标题与操作按钮-->
<div class="el-form-border">
<el-form ref="form" label-width="150px">
<el-row>
<el-col :span="12">
<el-form-item label="工具编号">{{applyToolDetail ? applyToolDetail.toolCode:''}}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工具名称">{{applyToolDetail ? applyToolDetail.toolName:''}}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="负责人">{{applyToolDetail ? applyToolDetail.toolPrincipalsName:''}}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="归属部门">{{applyToolDetail ? applyToolDetail.toolRespDeptName:''}}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工具来源">
<dict-tag :options="dict.type.tool_source" :value="applyToolDetail.toolSource"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工具用途">{{applyToolDetail ? applyToolDetail.toolUse:''}}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工具类别">
<dict-tag :options="dict.type.tool_type" :value="applyToolDetail.toolType"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工具状态">
<dict-tag :options="dict.type.tool_status" :value="applyToolDetail.status"/>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="测试情况">{{applyToolDetail ? applyToolDetail.testSituation:''}}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="功能描述">{{applyToolDetail ? applyToolDetail.functionDesc:''}}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="适用条件">{{applyToolDetail ? applyToolDetail.applyCondition:''}}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="操作说明">{{applyToolDetail ? applyToolDetail.operateExplain:''}}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">{{applyToolDetail ? applyToolDetail.remark:''}}</el-form-item>
</el-col>
</el-row>
</el-form><!--el-form-->
</div>
<!-- 流程选择下一环节及人员 开始 -->
<el-dialog
title="选择下一环节及人员"
v-if="dialogVisible" :visible.sync="dialogVisible"
width="60%"
append-to-body
v-loading = flowStepLoading
:close-on-click-modal="false"
:close-on-press-escape="false"
:show-close="false"
>
<processcode
ref="prochild"
:searchQuery="searchQuery"
:pListData="pListData"
:isSummary="isSummary"
></processcode>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="handleWorkflowSubmit"
> </el-button
>
</span>
</el-dialog>
<!-- 流程选择下一环节及人员 结束 -->
<monitor-drawer
v-if="monitorDrawerVisible"
ref="monitorDrawer"
></monitor-drawer>
<bl-user-selector ref="peopleSelect" :type="'single'" :isCheck="true" :open="toolPrincipalsChoose" @cancel="toolPrincipalsChoose=false" @submit="submitPeople"></bl-user-selector>
</div>
</template>
<script>
import { listDocument } from "@/api/document/document";
import processcode from "@/views/workflowList/processcode/index.vue";
import {
workflowprocesskey,
getStartActdef,
getExtAttributeModel,
procInstInfoAndStatus,
} from '@/api/my_business/workflow'
import WorkflowLogs from '@/views/workflowList/workflowLogs/index.vue'
import AddDoc from '@/views/tool/AddDoc.vue'
import Treeselect from '@riophae/vue-treeselect'
import { deptTreeSelect } from "@/api/system/user";
import { addApply, getInfoByBpmcId, updateApply } from '@/api/tool/toolApply'
import { listItem } from '@/api/tool/userApplyItem'
import blUserSelector from '@/components/user-selector/src/user-selector.vue'
import { getTool } from "@/api/tool/tool";
import store from "@/store";
// PDF
export default {
dicts: ['sys_normal_disable','tool_type', 'tool_source', 'tool_status'],
components: {
blUserSelector,
Treeselect, AddDoc,
WorkflowLogs,
processcode,
},
name: "Borrow_doc",
props: ['data'],
data() {
return {
toolPrincipalsChoose: false,
//
dataList: [],
applyToolDetail: {},
addDocShow: false,
defaultStaff: [],
yes: 'Y',
searchQuery: {},
deptList: [],
companyList: [],
deptOptions: [],
docClassList: [],
submitLabel:undefined,
passoptions: [
{ value: true, label: "通过" },
{ value: false, label: "不通过" },
],
formSubmit: { summary: "", actionType: "", pass: true },
isSummary: false,
activeName: "info",
nodeDetail: [],
procDefKey: undefined,
viewId: "",
userInfo: this.$store.getters.userInfo,
viewShow: false,
monitorDrawerVisible:false,
form: {},
rules: {
userId: [
{ required: true, message: "申请人不能为空", trigger: "blur" }
],
reason: [
{ required: true, message: '申请理由不能为空', trigger: 'blur' }
]
},
kuozhanshuju: {},
kuozhanshujuBool: {},
kuozhanshujuLabel: {},
pListData: {},
editStatus:false,
workflowStatus: false,
dialogVisible: false,
loading: false,
detailLoading: false,
flowStepLoading : false,
//
initPassword: undefined,
};
},
computed: {},
watch: {
data (val) {
if (val) {
this.init(val)
}
},
},
mounted() {
if (this.data) {
this.init(this.data)
}
this.getConfigKey("sys.user.initPassword").then(response => {
this.initPassword = response.msg;
});
this.getDeptTree()
},
methods: {
/** 查询部门下拉树结构 */
getDeptTree() {
deptTreeSelect().then(response => {
this.deptOptions = response.data;
});
},
async init(row) {
let _this = this
_this.rest(row)
_this.loading = true
_this.procDefKey = 'Process_DCMGS6M9'
_this.form.type = row.type
//
_this.$nextTick(() => {
if (row && row.procInstId) {
let procInstId = row.procInstId
_this.workflowStatus = row.status == '1'
_this.procInstInfoAndStatus(procInstId)
_this.getDetail(procInstId)
} else {
_this.workflowStatus = true
_this.loading = false
_this.editStatus = true
_this.getWorkflowprocesskey();
}
});
},
getDetail(procInstId) {
let _this = this
_this.detailLoading = true
getInfoByBpmcId(procInstId).then(async (res) => {
let formData = res.data;
formData.type = _this.form.type
_this.form = formData
this.getItemList(res.data.id);
}).finally(()=>{
_this.detailLoading = false
});
},
getItemList(id){
let _this = this
listItem({applyId:id}).then(res=>{
_this.dataList = res.data
})
getTool(_this.form.toolId).then((response) => {
_this.applyToolDetail = response.data;
});
},
rest(data){
let _this = this
_this.activeName = "info"
_this.dataList = [{...data}]
_this.applyToolDetail = {...data}
_this.form={
userId:_this.userInfo.userId,
nickName:_this.userInfo.nickName,
deptId:_this.userInfo.deptId,
deptName:_this.userInfo.dept.deptName,
reason: ""
}
},
procInstInfoAndStatus(procInstId){
let _this = this
procInstInfoAndStatus(procInstId).then((res) => {
if (res) {
_this.pListData = res
}else {
_this.pListData = {procInstId:procInstId}
}
_this.getExtAttributeModel()
});
},
getWorkflowprocesskey() {
let _this = this
_this.loading = true
_this.pListData = {}
if (_this.procDefKey) {
workflowprocesskey(_this.procDefKey).then((data) => {
getStartActdef(data.data.procDefId).then((res) => {
_this.pListData = res.data;
this.getExtAttributeModel()
});
});
}else {
_this.$message.warning("该文件类型尚未进行流程设置,将无法发起流程!");
}
},
getExtAttributeModel(){
let _this = this
let procDefId = _this.pListData.procDefId
let curActDefId = _this.pListData.curActDefId || _this.pListData.actDefId
if (procDefId&&curActDefId) {
getExtAttributeModel(
procDefId,
curActDefId
).then((res) => {
let kuozhanshujuBool = {}
let kuozhanshuju = {}
let kuozhanshujuLabel = {}
res.data.forEach(item=>{
kuozhanshujuLabel[item.objKey] = item.objName
if (item.objType==='Boolean') {
kuozhanshujuBool[item.objKey] = item.objValue
} else {
kuozhanshuju[item.objKey] = item.objValue
}
})
_this.kuozhanshujuBool = kuozhanshujuBool;
_this.kuozhanshuju = kuozhanshuju;
_this.kuozhanshujuLabel = kuozhanshujuLabel;
_this.editStatus =_this.attributeModelBool('edit')&&_this.workflowStatus
_this.submitLabel = _this.attributeModelLabel('approve')
}).finally(()=>{
_this.loading = false
});
}else {
_this.kuozhanshujuBool = {}
_this.kuozhanshuju = {}
_this.loading = false
}
},
attributeModelBool(val){
if (this.kuozhanshujuBool&&this.kuozhanshujuBool!=={}) {
let obj = this.kuozhanshujuBool[val]
return obj?obj==='true':false
}else {
return false
}
},
attributeModel(val){
return this.kuozhanshuju[val]
},
attributeModelLabel(val){
return this.kuozhanshujuLabel[val]
},
close() {
this.viewShow = false;
this.$emit("close")
},
//
async saveForm() {
let _this = this
//
_this.activeName = 'info'
if (!_this.procDefKey) {
_this.$message.warning("尚未进行流程设置,将无法发起流程!");
return;
}
let dialogVisible = true
if (!!_this.$refs["eForm"]) {
let valid = await _this.$refs["eForm"].validate()
if (!valid) {
dialogVisible = false
}
}
_this.tempForm()
},
//
tempForm() {
let _this = this
if (!_this.procDefKey) {
_this.$message.warning("尚未进行流程设置,将无法发起流程!");
return;
}
_this.loading = true
let formData = JSON.parse(JSON.stringify(_this.form))
formData.itemList = _this.dataList
formData.recordStatus = "draft";
formData.editStatus = _this.editStatus
if (formData.id) {
updateApply(formData).then((res) => {
if (res.code===200) {
_this.$message({
message: '保存成功',//
type:'success',  //
duration:1200,  //, 0 1200
});
}
}).finally(()=>{
_this.loading = false
});
} else {
let wf_receivers = [];
wf_receivers.push({
receiveUserId: _this.userInfo.userName,
receiveUserOrgId: _this.userInfo.deptId
});
let wf_procTitle = "【使用申请】"+_this.dataList[0].toolName
formData.bpmClientInputModel = {
model: {
wf_procDefId: _this.pListData.procDefId,
wf_procDefKey: _this.procDefKey,
wf_procTitle: wf_procTitle,
wf_sendUserId: _this.userInfo.userName,
wf_sendUserOrgId: _this.userInfo.deptId,
wf_receivers: wf_receivers,
wf_curActDefName: _this.pListData.actDefName,
wf_curActDefId: _this.pListData.actDefId,
wf_nextActDefName: _this.pListData.actDefName,
wf_nextActDefId: _this.pListData.actDefId,
},
type: formData.type,
review: _this.attributeModelBool('approve'),
};
formData.editStatus = _this.editStatus
addApply(formData).then((res) => {
if (res.code===200) {
_this.form.id = res.data.businessKey;
_this.procInstInfoAndStatus(res.data.procInstId)
_this.$message({
message: '保存成功',//
type:'success',  //
duration:1200,  //, 0 1200
});
}
}).finally(()=>{
_this.loading = false
});
}
},
deleteForm(){
let _this = this
_this.$modal.confirm('撤销后,该流程待办任务将会被删除,请谨慎操作。是否确认执行?')
.then(()=> {
_this.loading = true
let formData = {
id: _this.form.id,
bpmClientInputModel: {
model: {
wf_procDefKey: _this.procDefKey,
wf_procDefId: _this.pListData.procDefId,
wf_procInstId: _this.pListData.procInstId,
wf_sendUserId: _this.userInfo.userName,
wf_sendUserOrgId: _this.userInfo.deptId,
wf_curActDefName: _this.pListData.curActDefName,
wf_curActDefId: _this.pListData.curActDefId,
},
},
review: false,
recordStatus: 'cancel',
editStatus: false
}
addApply(formData).then((res) => {
if (res.code === 200) {
this.$modal.msgSuccess("撤销成功");
this.close(true);
}
});
})
},
//
async submitForm() {
let _this = this
//
_this.activeName = 'info'
if (!_this.procDefKey) {
_this.$message.warning("尚未进行流程设置,将无法发起流程!");
return;
}
let dialogVisible = true
//
if (_this.attributeModelBool('approve')) {
if (_this.formSubmit.pass==='') {
_this.$modal.msgError(_this.submitLabel+"结论不能为空!");
return true;
} else if (!_this.formSubmit.pass&&!_this.formSubmit.summary) {
_this.$modal.msgError("请填写"+_this.submitLabel+"意见");
return true;
}
}
if (!!_this.$refs["eForm"]) {
let valid = await _this.$refs["eForm"].validate()
if (!valid) {
dialogVisible = false
}
}
_this.searchQuery.pass = _this.formSubmit.pass
let defaultStaff = []
this.defaultStaff=defaultStaff
this.dialogVisible = true;
},
//
handleWorkflowSubmit() {
let _this = this
let formData = JSON.parse(JSON.stringify(_this.form))
formData.itemList = _this.dataList
let wf_receivers = [];
if (_this.$refs.prochild.receiveUserList.length < 1 &&_this.$refs.prochild.nextData.actDefType!=='endEvent') {
_this.$message.warning("请选择人员!");
return;
}
_this.$refs.prochild.receiveUserList.forEach((element) => {
wf_receivers.push({
receiveUserId: element.id,
receiveUserOrgId: element.parentId,
});
});
let wf_nextActDefId = _this.$refs.prochild.nextData.actDefId;
let wf_nextActDefName = _this.$refs.prochild.nextData.actDefName;
//
_this.flowStepLoading = true
_this.detailLoading = true
let wf_procTitle = "【使用申请】"+_this.dataList[0].toolName
if (_this.pListData && _this.pListData.procInstId) {
//
formData.bpmClientInputModel = {
model: {
wf_procDefKey: _this.procDefKey,
wf_procDefId: _this.pListData.procDefId,
wf_procTitle: wf_procTitle,
wf_curActInstId: _this.pListData.curActInstId,
wf_sendUserId: _this.userInfo.userName,
wf_sendUserOrgId: _this.userInfo.deptId,
wf_receivers: wf_receivers,
wf_nextActDefId: wf_nextActDefId,
wf_curComment: _this.formSubmit.summary,
wf_curActDefId: _this.pListData.curActDefId,
wf_curActDefName: _this.pListData.curActDefName,
wf_nextActDefName: wf_nextActDefName,
},
applyStatus: _this.formSubmit.pass,
review: _this.attributeModelBool('approve'),
type: formData.type
};
}else{
//
formData.bpmClientInputModel = {
model: {
wf_procTitle: wf_procTitle,
wf_nextActDefId: wf_nextActDefId,
wf_procDefId: _this.pListData.procDefId,
wf_procDefKey: _this.procDefKey,
wf_sendUserId: _this.userInfo.userName,
wf_sendUserOrgId: _this.userInfo.deptId,
wf_receivers: wf_receivers,
wf_curActDefName: _this.pListData.actDefName,
wf_curActDefId: _this.pListData.actDefId,
wf_nextActDefName: wf_nextActDefName,
},
review: _this.attributeModelBool('approve'),
type: formData.type,
};
}
if (_this.$refs.prochild.nextData.actDefType==='endEvent') {
//
formData.recordStatus = 'done'
} else {
//
formData.recordStatus = 'doing'
}
formData.editStatus = _this.editStatus
addApply(formData).then((res) => {
if (res.code===200) {
_this.$message({
message: '流程提交成功',//
type:'success',  //
duration:1200,  //, 0 1200
onClose:()=>{
_this.flowStepLoading = false
_this.detailLoading = false
_this.dialogVisible = false;
_this.close();
}
});
store.dispatch('GetUserMsgCount').then(() => { })
}
});
},
handleMonitor() {
this.monitorDrawerVisible = true;
this.$nextTick(() => {
this.$refs.monitorDrawer.init(this.pListData.procInstId);
});
},
handleDelete(dataList,index){
dataList.splice(index,1)
},
/**
* 新增上传附件
*/
handleDocAdd() {
this.addDocShow = true
},
submitPeople(peopleList){
this.$set(this.form,'userId',peopleList[0]['userId'])
this.$set(this.form,'nickName',peopleList[0]['nickName'])
this.$set(this.form,'deptId',peopleList[0]['deptId'])
this.$set(this.form,'deptName',peopleList[0].dept.deptName)
this.toolPrincipalsChoose = false;
this.$refs['eForm'].validateField("userId");
},
},
};
</script>

View File

@ -0,0 +1,505 @@
<template>
<div class="maincss" v-loading="loading">
<div class="title-box">
<div class="draw-title">
{{ title }}
</div>
<div class="draw-title">
</div>
<el-form
:model="formSubmit"
ref="formSubmit"
class="mt10"
:rules="formrules"
label-position="top"
label-width="120px"
>
<el-row :gutter="20">
<el-col :span="8">
<div class="h28">办理步骤</div>
<el-tree
ref="myTree"
:data="processList"
:props="processProps"
node-key="actDefName"
@node-click="processNodeClick"
style="border: 1px solid rgb(230, 235, 245); height: 314px;overflow: auto"
highlight-current
>
</el-tree>
</el-col>
<el-col :span="8" v-show="processList && processList.length>0 &&nextData&&nextData.actDefType != 'endEvent'">
<div class="h28">待选用户
<!-- <el-button type="primary" style="float: right" size="mini" @click="handleSelect">通讯录</el-button>-->
</div>
<div>
<el-input
v-model.trim="userTreeName"
placeholder="请输入"
clearable
size="small"
prefix-icon="el-icon-search"
/>
</div>
<el-tree
ref="userTree"
:data="userList"
:props="userProps"
:filter-node-method="filterNode"
:highlight-current="true"
:default-expand-all="true"
@node-click="userNodeClick"
style="border: 1px solid rgb(230, 235, 245); height: 282px;overflow: auto"
>
</el-tree>
</el-col>
<el-col :span="8" v-show="processList&&processList.length>0&&nextData&&nextData.actDefType != 'endEvent'">
<div class="h28">已选用户</div>
<div
class="wordbox"
style="border: 1px solid rgb(230, 235, 245); height: 314px;overflow: auto"
>
<ul>
<li v-for="(item, index) in receiveUserList" :key="index">
<div class="inli">
<i class="el-icon-s-custom"></i>
<span>{{ item.name }}</span>
<i v-if="editStatus" class="el-icon-close" @click="removeData(item)"></i>
</div>
</li>
</ul>
</div>
</el-col>
<el-col :span="24" class="mt10" v-if="istongguo">
<el-form-item label="是否通过" prop="pass">
<el-radio-group v-model.trim="pass">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24" class="mt10">
<el-form-item
label="是否加入档案:"
prop="joinDoc"
v-if="formSubmit.actDefId == 'EndEvent_0qwgu4i'"
>
<el-radio-group v-model.trim="formSubmit.joinDoc">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24" v-if="isSummary" class="mt10">
<el-form-item label="审核意见:">
<el-input
v-model.trim="formSubmit.summary"
type="textarea"
placeholder="请输入审核意见"
maxlength="200"
:autosize="{ minRows: 4, maxRows: 4 }"
:style="{ width: '100%' }"
></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</div>
</div>
</template>
<script>
import {
workflowNextactsNew2,
getNextactuserByPending,
getNextActUsersByNew,
getExtAttributeModel,
selectUserStyle
} from "@/api/my_business/workflow";
export default {
props: {
searchQuery:{
type: Object,
default: {},
},
hideNodeCode: {
type: Array,
default: ()=>[],
},
isSummary: {
type: Boolean,
default: true,
},
defaultStaff: {
type: Object,
default: undefined,
},
pListData: {},
data: {},
title: {},
detatailsData: {},
promptContent: {
type: Boolean,
default: false,
},
},
data() {
return {
userInfo: this.$store.getters.userInfo,
summary: "",
editStatus: true,
formSubmit: { summary: "" },
processList: [],
processProps: {
children: "children",
label: "actDefName",
},
userProps: {
children: "children",
label: function (data, node) {
if (data.type == "USER") {
return data.id+' '+data.name
} else {
return data.name
}
}
},
formrules: {
summary: [{ required: true, message: " ", trigger: "change" }],
pass: [{ required: true, message: " ", trigger: "change" }],
},
userTreeName:undefined,
receiveUserList: [],
userList: [],
loading: true,
nextData: {},
procDefKey: "",
actionType: "",
wf_actionType: "",
actDefType: "", //actDefType: "endEvent"
pass: "", //
kuozhanshuju: "",
istongguo: false,
morendta: undefined,
};
},
created() {
this.getOptionsList();
if (this.pListData.procDefKey != "") {
this.procDefKey = this.pListData.procDefKey;
}
//this.$emit("yingchanbohui", false);
},
watch: {
actionType: function (val) {
this.wf_actionType = val;
},
"formSubmit.summary": function (val) {
this.summary = val;
//console.log(val);
},
pass(val) {
console.log(val);
},
//
userTreeName(val) {
this.$refs.userTree.filter(val);
}
},
mounted() {
},
methods: {
getOptionsList() {
let _this = this
let searchQuery = this.searchQuery
searchQuery.procDefId = _this.pListData.procDefId
if (!!_this.pListData.curActInstId) {
searchQuery.curActInstId= _this.pListData.curActInstId
// ID
searchQuery.curActDefId = _this.pListData.curActDefId
}else{
searchQuery.curActDefId= _this.pListData.actDefId
}
// ID
searchQuery.procInstId = _this.pListData.procInstId
_this.loading = true
workflowNextactsNew2(searchQuery)
.then((res) => {
_this.processList = res.data.filter(item=>!_this.hideNodeCode.includes(item.actDefId));
//
_this.loading = false
//
if(_this.processList.length > 0) {
//
//
_this.processNodeClick(_this.processList[0]);
_this.actDefType = res.data[0].actDefType;
_this.$nextTick(() => {
//
_this.$refs.myTree.setCurrentKey(_this.processList[0].actDefName);
});
}
})
.catch((e) => {
_this.loading = false;
});
},
processNodeClick(val){
let _this = this
if (!!_this.pListData.curActInstId) {
_this.processNodeClick1(val);
}else {
_this.processNodeClick2(val);
}
},
//
processNodeClick1(val) {
let _this = this
if (this.nextData != "") {
if (val.actDefName == this.nextData.actDefName) {
return;
}
}
this.nextData = val;
this.userList = []; //
this.receiveUserList = []; //
let params = {
userOrgId: _this.userInfo.deptId,
curActInstId: this.pListData.curActInstId,
destActDefId: val.actDefId,
// IDIDID
curActDefId: this.pListData.curActDefId,
procDefKey: this.pListData.procDefKey,
procInstId: this.pListData.procInstId,
};
_this.loading = true
getNextactuserByPending(params)
.then((res) => {
//
_this.loading = true
selectUserStyle(params).then((selectRes) => {
if(selectRes.data == 'tree') {
//
_this.userList = this.handleTree(res.data, "id");
} else {
//
_this.userList = res.data.filter(item => item.type==='USER')
if (_this.defaultStaff&&_this.defaultStaff.length>0) {
let item=_this.defaultStaff.find(item=>item.nodeCode===val.actDefId)
if (item&&item.users) {
JSON.parse(item.users).forEach(item=>{
let user = _this.userList.find(user=>user.id===item.userName)
if (!user) {
_this.userList.push({
type: 'USER',
id:item.userName,
realId: item.userName,
parentId: item.deptId,
name: item.nickName,
})
}
})
}
}
}
let defaultStaffIds = []
if (_this.defaultStaff&&_this.defaultStaff.length>0) {
//
let item=_this.defaultStaff.find(item=>item.nodeCode===val.actDefId)
if (item&&item.users) {
defaultStaffIds = JSON.parse(item.users).map(user=>user.userName)
}
}
if (defaultStaffIds.length>0) {
let userList = []
_this.defaultUserList(userList,defaultStaffIds,_this.userList)
userList.forEach(user=>{
_this.userNodeClick(user);
})
_this.editStatus = true
} else {
_this.editStatus = true
//z
this.rtuserList(res.data);
if (this.morendta) {
this.userNodeClick(this.morendta);
}
}
//
_this.loading = false;
});
})
.catch((e) => {
console.log(e)
_this.loading = false;
});
},
processNodeClick2(val) {
let _this = this
if (this.nextData != "") {
if (val.actDefName == this.nextData.actDefName) {
return;
}
}
this.nextData = val;
this.userList = []; //
this.receiveUserList = []; //
let params = {
procDefId:this.pListData.procDefId,
userOrgId: this.userInfo.deptId,
curActDefId: this.pListData.actDefId,
destActDefId: val.actDefId,
};
_this.loading = true
getNextActUsersByNew(params).then((res) => {
//
selectUserStyle(params).then((selectRes) => {
if(selectRes.data == 'tree') {
//
_this.userList = this.handleTree(res.data, "id");
} else {
//
_this.userList = res.data.filter(item => item.type==='USER')
if (_this.defaultStaff&&_this.defaultStaff.length>0) {
let item=_this.defaultStaff.find(item=>item.nodeCode===val.actDefId)
if (item&&item.users) {
JSON.parse(item.users).forEach(item=>{
let user = _this.userList.find(user=>user.id===item.userName)
if (!user) {
_this.userList.push({
type: 'USER',
id:item.userName,
realId: item.userName,
parentId: item.deptId,
name: item.nickName,
})
}
})
}
}
}
let defaultStaffIds = []
if (_this.defaultStaff) {
//
let item=_this.defaultStaff.find(item=>item.nodeCode===val.actDefId)
if (item&&item.users) {
defaultStaffIds = JSON.parse(item.users).map(user=>user.userName)
}
}
if (defaultStaffIds.length>0) {
let userList = []
_this.defaultUserList(userList,defaultStaffIds,_this.userList)
userList.forEach(user=>{
this.userNodeClick(user);
})
_this.editStatus = false
} else {
_this.editStatus = true
//z
this.rtuserList(res.data);
if (this.morendta) {
this.userNodeClick(this.morendta);
}
}
_this.loading = false
});
})
.catch((e) => {
this.loading = false;
});
},
//
userNodeClick(val) {
// console.log("val", val);
if (val.type == "USER"&&this.editStatus) {
if (this.nextData.multi){
//
let arr = this.receiveUserList.filter((x) => x.id === val.id);
if (arr.length <= 0) {
this.receiveUserList.push(val);
}
}else {
//
this.receiveUserList = [val]
}
}
},
//
removeData(item) {
var arr = [];
this.receiveUserList.forEach((element) => {
if (element.id != item.id) {
arr.push(element);
}
});
this.receiveUserList = arr;
},
defaultUserList(userList,ids,data) {
data.forEach(item=>{
if (ids.includes(item.id)) {
userList.push(item)
}
})
},
rtuserList(originalData) {
let userList = originalData.filter(item => item.type==='USER')
if (userList.length == 1) {
//
this.morendta = userList[0];
} else {
this.morendta = undefined
}
},
//
filterUserNode(data) {
if(data.type == "USER") {
//
return data
} else if(data.hasOwnProperty("children")) {
let list = data.children;
for(var i=0;i<list.length;i++) {
let item = list[i];
if(item.type != "USER") {
let res = this.filterUserNode(item)
if(res != null) {
//
return res;
}
} else {
//
return item;
}
}
}
},
filterNode(value, data) {
if (!value) return true;
return data.id.toLowerCase().indexOf(value.toLowerCase()) !== -1||data.name.toLowerCase().indexOf(value.toLowerCase()) !== -1
},
handleSelect() {
let _this = this
_this.$nextTick(()=>{
_this.$refs.userList.init(null,null,null)
})
},
handleSubmitUser(source,index,user) {
let val = {
type: 'USER',
id: user.userName,
name: user.nickName,
parentId: user.dept.deptId,
realId: user.userName,
}
this.userNodeClick(val);
},
},
};
</script>
<style scoped>
.h28{
height: 28px;line-height: 28px
}
</style>

View File

@ -0,0 +1,60 @@
<template>
<div class="app-container document_changeindex el-card is-always-shadow">
<el-card class="gray-card" style="width: 60%">
<el-table v-loading="loading" :data="dataList">
<el-table-column label="环节" align="left" prop="actDefName" width="200px"/>
<el-table-column label="意见" align="left" prop="opinion" >
<template slot-scope="scope">
<span :style="{color:passList[scope.row.pass].color}">{{ passList[scope.row.pass].label }}</span><br/>
<span>{{ scope.row.opinion }}</span>
</template>
</el-table-column>
<el-table-column label="操作信息" align="left" prop="createTime" >
<template slot-scope="scope">
<span>{{ scope.row.deptName }}</span>
<span style="margin-left:10px;">{{ scope.row.nickName }}</span>
<span style="margin-left:20px;color:#AAAAAA">{{ parseTime(scope.row.createTime, '{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
</el-table>
</el-card>
</div>
</template>
<script>
import { selectLogByProcInstId } from "@/api/my_business/workflow";
export default {
name: "WorkflowLogs",
props: ["procInstId"],
data() {
return {
loading: true,
dataList: [],
passList: { 'true':{label:'通过',color:'#70B603'},'false':{label:'不通过',color:'#D9001B'}},
};
},
watch: {
procInstId (val) {
if (val) {
this.getList(val)
}
},
},
mounted() {
if (this.procInstId) {
this.getList(this.procInstId)
}
},
methods: {
/** 查询岗位列表 */
getList(procInstId) {
this.loading = true;
selectLogByProcInstId({procInstId:procInstId,review:true}).then(response => {
this.dataList = response.data;
this.loading = false;
});
},
}
};
</script>

View File

@ -0,0 +1,51 @@
<template>
<main-component ref="mainComponent" :code="code" :data="data" @close="handleCloseChange" class="iframe-drawer" style="padding: 16px 32px"></main-component>
</template>
<script>
import MainComponent from "@/components/mainComponent/index.vue";
export default {
name: "workflowRouter",
dicts: [],
components: {
MainComponent,
},
data() {
return {
path: 'views/workflowList/addWorkflow/',
code: '',
data: undefined,
status: true,
}
},
created() {
this.$nextTick(()=>{
this.handleDetails(this.$route.query);
})
},
methods: {
/** 详情按钮操作 */
handleDetails(row) {
let _this = this
if (row.type&&_this.status) {
_this.code = _this.path + row.type
_this.data = row
}
},
init(row){
let _this = this
_this.code = _this.path + row.type
_this.data = row
_this.status = false
},
handleCloseChange() {
let _this = this
if (_this.status) {
window.parent.postMessage({type:"close"})
}else{
_this.$emit("closeDrawer")
}
}
},
};
</script>

View File

@ -2,290 +2,280 @@
<div class="app-container"><!--从这一层开始嵌入页面-->
<el-card>
<el-form label-width="80px">
<el-form ref="queryForm" label-width="80px">
<div class="search">
<div class="sl">
<el-form-item label="流程标题">
<el-input placeholder="输入流程标题"></el-input>
<el-input
v-model="queryParams.procTitle"
placeholder="输入流程标题"
clearable
@clear="handleQuery"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="流程状态">
<el-select placeholder="请选择">
<el-option label="进行中" value=""></el-option>
<el-option label="已办结" value=""></el-option>
<el-select placeholder="请选择" v-model="queryParams.recordStatus" @change="handleQuery">
<el-option label="全部" value=""></el-option>
<el-option label="审核中" value="doing"></el-option>
<el-option label="已审核" value="done"></el-option>
<el-option label="拟稿" value="draft"></el-option>
</el-select>
</el-form-item>
<el-form-item label="发起时间">
<el-date-picker type="daterange" range-separator="" start-placeholder="开始日期" end-placeholder="结束日期"></el-date-picker>
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search">搜索</el-button>
<el-button icon="el-icon-refresh-left">重置</el-button>
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh-left" @click="resetQuery">重置</el-button>
</div>
</div><!--search 搜索-->
</el-form><!--el-form-->
</el-card><!--el-card-->
<el-card>
<el-table :data="tableData1" style="width: 100%" height="529">
<el-table-column prop="prop1" label="申请类型"></el-table-column>
<el-table-column prop="prop2" label="流程标题">使用申请工具名称11</el-table-column>
<el-table-column prop="prop2" label="流程状态" width="150">
<el-table :data="tableData1" style="width: 100%" height="529" v-loading="loading">
<el-table-column label="序号" width="60" type="index" align="center"></el-table-column>
<el-table-column label="申请类型">
<template slot-scope="scope">
<span :class="getClassName(scope.row.prop2)"><a @click="drawer2 = true">{{ scope.row.prop2 }}</a></span>
<span v-if="scope.row.applyType === 'publish'">发布申请</span>
<span v-if="scope.row.applyType === 'use'">使用申请</span>
</template>
</el-table-column>
<el-table-column prop="prop5" label="发起时间"></el-table-column>
<el-table-column prop="prop6" label="结束时间"></el-table-column>
<el-table-column prop="procTitle" label="流程标题"></el-table-column>
<el-table-column label="流程状态" width="150">
<template slot-scope="scope">
<el-tag v-if="scope.row.recordStatus === 'doing'">审核中</el-tag>
<el-tag type="success" v-if="scope.row.recordStatus === 'done'">已审核</el-tag>
<el-tag type="info" v-if="scope.row.recordStatus === 'draft'">拟稿</el-tag>
</template>
</el-table-column>
<el-table-column prop="createTime" label="发起时间"></el-table-column>
<el-table-column prop="endTime" label="结束时间"></el-table-column>
<el-table-column label="操作" width="100" >
<el-button type="text" icon="el-icon-info" @click="drawer1 = true">详情</el-button>
<template slot-scope="scope">
<el-button type="text" icon="el-icon-info" @click="handleDetail(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table><!--el-table-->
<el-pagination :current-page="currentPage4" :page-sizes="[100, 200, 300, 400]" :page-size="100" layout="total, sizes, prev, pager, next, jumper" :total="400"></el-pagination>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getListData"
/>
</el-card><!--el-card-->
<el-drawer :visible.sync="drawer1" :direction="direction" :before-close="handleClose" size="75%">
<el-drawer :visible.sync="drawer1" size="80%" :show-close="false">
<template #title>
<span>申请使用</span>
<div class="drawer-head-btn">
<el-button @click="drawer2 = true">流程监控</el-button>
<el-button type="primary" @click="handleMonitor"><i class="el-icon-data-line"></i> 流程监控</el-button>
<el-button @click="drawer1 = false"><i class="el-icon-close"></i> 关闭</el-button>
</div><!--drawer-head-btn 抽屉顶部按钮区域-->
</template>
<el-tabs v-model="activeName1" @tab-click="handleClick">
<el-tab-pane label="信息内容" name="first">
<div class="el-form-border">
<el-form ref="form" label-width="150px">
<el-row>
<el-col :span="24">
<el-form-item label="申请人">张莹</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="申请部门">信息部</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="申请理由">
<el-input type="textarea" maxlength="1000" placeholder="工作需要额外申请,请批准!" :disabled="true"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form><!--el-form-->
</div><!--el-form-border 表单-->
<div class="divide double"></div><!--divide 分隔-->
<div class="tboper">
<div class="tit">申请工具</div>
</div><!--tboper 标题与操作按钮-->
<el-table :data="tableData2" style="width: 100%">
<el-table-column prop="prop1" label="工具编号"></el-table-column>
<el-table-column prop="prop2" label="工具名称"></el-table-column>
<el-table-column prop="prop3" label="归属单位" width="200"> </el-table-column>
<el-table-column prop="prop4" label="负责人" width="100" ></el-table-column>
<el-table-column prop="prop5" label="工具类别" ></el-table-column>
</el-table><!--el-table-->
<div class="divide double"></div><!--divide 分隔-->
</el-tab-pane><!--el-tab-pane-->
<el-tab-pane label="审批记录" name="second">
<el-table :data="tableData3" style="width: 100%">
<el-table-column prop="prop4" label="处理人"></el-table-column>
<el-table-column prop="prop3" label="处理环节"> </el-table-column>
<el-table-column prop="prop2" label="接收人"></el-table-column>
<el-table-column prop="prop1" label="接收环节"></el-table-column>
<el-table-column prop="prop7" label="处理时间" ></el-table-column>
<el-table-column prop="prop5" label="审批意见" ></el-table-column>
</el-table><!--el-table-->
</el-tab-pane><!--el-tab-pane-->
</el-tabs><!--el-tabs-->
<div class="tboper">
<div class="tit">基本信息</div>
</div><!--tboper 标题与操作按钮-->
<div class="el-form-border">
<el-form ref="form" label-width="150px">
<el-row>
<el-col :span="24">
<el-form-item label="申请人">{{applyDetail.nickName}}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="申请部门">{{applyDetail.deptName}}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="申请理由">
<el-input type="textarea" maxlength="1000" :placeholder="applyDetail.reason" :disabled="true"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form><!--el-form-->
</div><!--el-form-border 表单-->
<div class="divide double"></div><!--divide 分隔-->
<div class="tboper">
<div class="tit">申请工具</div>
</div><!--tboper 标题与操作按钮-->
<div class="el-form-border">
<el-form ref="form" label-width="150px">
<el-row>
<el-col :span="12">
<el-form-item label="工具编号">{{applyToolDetail.toolCode}}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工具名称">{{applyToolDetail.toolName}}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="负责人">{{applyToolDetail.toolPrincipalsName}}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="归属部门">{{applyToolDetail.toolRespDept}}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工具来源">{{applyToolDetail.toolSource}}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工具用途">{{applyToolDetail.toolUse}}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="工具类别">{{applyToolDetail.toolType}}</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="状态">{{applyToolDetail.status}}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="测试情况">{{applyToolDetail.testSituation}}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="功能描述">{{applyToolDetail.functionDesc}}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="适用条件">{{applyToolDetail.applyCondition}}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="操作说明">{{applyToolDetail.operateExplain}}</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="备注">{{applyToolDetail.remark}}</el-form-item>
</el-col>
</el-row>
</el-form><!--el-form-->
</div>
<div class="divide double"></div><!--divide 分隔-->
</el-drawer><!--el-drawer 申请详情-抽屉-->
<el-drawer :visible.sync="drawer2" :direction="direction" :before-close="handleClose" size="75%">
<template #title>
<span>流程监控</span>
</template>
<div class="lctitle">流程标题申请使用工具名称1 流程定义名称申请使用流程</div><!--lctitle-->
<img style="width:auto; max-width: 100%;" src="../../../../public/images/lcjk1.jpg" />
</el-drawer><!--el-drawer 流程监控-抽屉-->
<el-drawer
:visible.sync="drawerShow"
direction="rtl"
size="80%"
:with-header="false"
:wrapperClosable="false"
:show-close="false"
modal-append-to-body
:destroy-on-close="true"
>
<main-component ref="mainComponent" :code="path + code" :data="data" @close="handleClose"></main-component>
</el-drawer>
<monitor-drawer
v-if="drawer2"
ref="monitorDrawer"
></monitor-drawer>
</div><!--app-container-->
</template>
<script>
import { listApply } from "@/api/tool/toolApply";
import { getTool } from "@/api/tool/tool";
import DealDrawer from '@/components/DealDrawer/index.vue'
import mainComponent from '@/components/mainComponent/index.vue'
export default {
name: 'apply',
components: { mainComponent, DealDrawer },
data() {
return {
drawer1: false,
drawer2: false,
activeName1: 'first',
activeName2: 'second',
radio1: '',
tableData1: [
{
prop1: '使用申请',
prop2: '进行中',
prop3: '直接领导审核',
prop4: '赵宇',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '已办结',
prop3: '直接领导审核',
prop4: '钱多多',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '进行中',
prop3: '直接领导审核',
prop4: '赵宇',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '已办结',
prop3: '直接领导审核',
prop4: '钱多多',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '进行中',
prop3: '直接领导审核',
prop4: '赵宇',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '已办结',
prop3: '直接领导审核',
prop4: '钱多多',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '进行中',
prop3: '直接领导审核',
prop4: '赵宇',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '已办结',
prop3: '直接领导审核',
prop4: '钱多多',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '进行中',
prop3: '直接领导审核',
prop4: '赵宇',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '已办结',
prop3: '直接领导审核',
prop4: '钱多多',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
}
],
tableData2: [
{
prop1: '0021',
prop2: '工具名称1',
prop3: '人力资源部/培训组',
prop4: '赵宇',
prop5: '网络工具',
},
{
prop1: '0022',
prop2: '工具名称2',
prop3: '人力资源部/招聘组',
prop4: '钱多多',
prop5: '网络工具',
},
{
prop1: '0023',
prop2: '工具名称3',
prop3: '人力资源部/薪资组',
prop4: '孙瑶',
prop5: '网络工具',
}
],
tableData3: [
{
prop1: '部门领导审核',
prop2: '张宇',
prop3: '管理员审核 ',
prop4: '赵定',
prop5: '同意',
prop6: '2024/02/09 12:00',
prop7: '2024/02/09 12:03',
prop8: '耗时0天',
prop9: '已完成',
},
{
prop1: '管理员审核',
prop2: '赵定',
prop3: '直接领导审核 ',
prop4: '钱多多',
prop5: '同意',
prop6: '2024/02/09 12:00',
prop7: '2024/02/09 12:03',
prop8: '耗时0天',
prop9: '已完成',
}
],
tableData4: [
{
prop1: '部门领导审核',
prop2: '张宇',
prop3: '管理员审核 ',
prop4: '赵定',
prop5: '同意',
prop6: '2024/02/09 12:00',
prop7: '2024/02/09 12:03',
prop8: '耗时0天',
prop9: '已完成',
},
{
prop1: '管理员审核',
prop2: '赵定',
prop3: '直接领导审核 ',
prop4: '钱多多',
prop5: '同意',
prop6: '2024/02/09 12:00',
prop7: '2024/02/09 12:03',
prop8: '耗时0天',
prop9: '已完成',
}
],
drawerShow: false,
loading: false,
tableData1: [],
path: 'views/workflowList/addWorkflow/',
code: '',
data: undefined,
//
dateRange: [],
pageSizes: [10,20,50,100],
//
total: 0,
//
queryParams: {
pageNumber: 1,
pageSize: 10,
procTitle: "",
recordStatus: "",
},
applyDetail: {},
applyToolDetail: {}
}
},
created() {
//
this.getListData()
},
methods: {
getClassName(prop2) {
//
if (prop2 === '进行中') {
return 'blue';
} else if (prop2 === '已办结') {
return 'green';
}else if (prop2 === '不通过') {
return 'red';
} else if (prop2 === '通过') {
return 'green';
}
handleDeal(row) {
this.dealDrawerShow = true;
let flowUrl = this.buildFlowUrl(row)
this.$nextTick(() => {
this.$refs.dealDrawer.init(flowUrl);
});
},
/** 查询列表 */
getListData() {
this.loading = true;
this.tableData1 = [];
listApply(this.addDateRange(this.queryParams, this.dateRange)).then((response) => {
this.total = response.total;
this.tableData1 = response.rows;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getListData();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = [];
this.resetForm("queryForm");
this.queryParams.procTitle = "";
this.queryParams.recordStatus = "";
this.handleQuery();
},
showDetail(row){
getTool(row.toolId).then((response) => {
this.applyToolDetail = response.data;
});
this.drawer1 = true;
this.applyDetail = row;
},
handleOpen(row){
let _this = this
_this.code = row.type
_this.data = row
_this.drawerShow = true
},
handleDetail(row) {
let _this = this
if(row.applyType === 'use'){
_this.handleOpen({type:'use_apply', procInstId:row.procInstId, status:'2'})
} else {
_this.handleOpen({type:'tool_release', procInstId:row.procInstId, status:'2'})
}
},
handleClose(){
this.drawerShow = false
},
handleMonitor() {
this.drawer2 = true;
this.$nextTick(() => {
this.$refs.monitorDrawer.init(this.applyDetail.procInstId);
});
},
},
}
</script>

View File

@ -1,542 +1,328 @@
<template>
<div class="app-container"><!--从这一层开始嵌入页面-->
<el-card>
<el-form label-width="80px">
<div class="search">
<el-form-item label="流程标题">
<el-input placeholder="输入流程标题"></el-input>
</el-form-item>
<el-button type="primary" icon="el-icon-search">搜索</el-button>
<el-button icon="el-icon-refresh-left">重置</el-button>
<div class="sl">
<el-form-item label="流程标题">
<el-input
placeholder="输入流程标题"
v-model.trim="queryParams.title"
clearable
@clear="handleQuery"
/>
</el-form-item>
</div>
<div class="sr">
<el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh-left" @click="resetQuery">重置</el-button>
</div>
</div><!--search 搜索-->
</el-form><!--el-form-->
</el-card><!--el-card-->
<el-card>
<el-tabs v-model="activeName3" @tab-click="handleClick">
<el-tab-pane label="待办(4)" name="first">
<el-table :data="tableData5" style="width: 100%" height="529">
<el-table-column prop="prop1" label="流程类型"></el-table-column>
<el-table-column prop="prop2" label="流程标题">使用申请工具名称11</el-table-column>
<el-table-column prop="prop3" label="当前环节"></el-table-column>
<el-table-column prop="prop4" label="上一环节"></el-table-column>
<el-table-column prop="prop5" label="上一环节处理人"></el-table-column>
<el-table-column prop="prop6" label="发起人"></el-table-column>
<el-table-column prop="prop7" label="接收时间"></el-table-column>
<el-table-column label="操作" width="100" >
<el-button type="text" icon="el-icon-info" @click="drawer1 = true">详情</el-button>
</el-table-column>
</el-table><!--el-table-->
<el-pagination :current-page="currentPage4" :page-sizes="[100, 200, 300, 400]" :page-size="100" layout="total, sizes, prev, pager, next, jumper" :total="400"></el-pagination>
</el-tab-pane><!--el-tab-pane-->
<el-tab-pane label="已办(10)" name="second">
<el-table :data="tableData6" style="width: 100%" height="529">
<el-table-column prop="prop1" label="流程类型"></el-table-column>
<el-table-column prop="prop2" label="流程标题"><a>使用申请工具名称1</a></el-table-column>
<el-table-column prop="prop8" label="流程状态">
<el-tabs v-model="activeName" @tab-click="state">
<el-tab-pane :label="'待办('+ statustotal+')'" name="taskToDo">
<el-table :data="postList" style="width: 100%" height="529" v-loading="loading">
<el-table-column label="序号" width="60" type="index" align="center"></el-table-column>
<el-table-column prop="procDefName" label="流程类型"></el-table-column>
<el-table-column prop="title" label="流程标题"></el-table-column>
<el-table-column prop="curActDefName" label="当前环节"></el-table-column>
<el-table-column prop="prevActDefName" label="上一环节">
<template slot-scope="scope">
<span :class="getClassName(scope.row.prop8)">{{ scope.row.prop8 }}</span>
<span v-if="!scope.row.prevActDefName">/</span>
<span v-else>{{ scope.row.prevActDefName }}</span>
</template>
</el-table-column>
<el-table-column prop="prop3" label="处理环节"></el-table-column>
<el-table-column prop="prop4" label="上一环节"></el-table-column>
<el-table-column prop="prop5" label="上一环节处理人"></el-table-column>
<el-table-column prop="prop6" label="发起人"></el-table-column>
<el-table-column prop="prop7" label="接收时间"></el-table-column>
<el-table-column label="操作" width="100" >
<el-button type="text" icon="el-icon-info" @click="drawer1 = true">详情</el-button>
</el-table-column>
</el-table><!--el-table-->
<el-pagination :current-page="currentPage4" :page-sizes="[100, 200, 300, 400]" :page-size="100" layout="total, sizes, prev, pager, next, jumper" :total="400"></el-pagination>
</el-tab-pane><!--el-tab-pane-->
<el-tab-pane label="办结(10)" name="third">
<el-table :data="tableData7" style="width: 100%" height="529">
<el-table-column prop="prop1" label="流程类型"></el-table-column>
<el-table-column prop="prop2" label="流程标题">使用申请工具名称1</el-table-column>
<el-table-column label="流程状态">
<el-table-column prop="sendUserName" label="上一环节处理人"></el-table-column>
<el-table-column prop="startUserName" label="发起人"></el-table-column>
<el-table-column prop="sendTime" label="接收时间">
<template slot-scope="scope">
<span :class="getClassName(scope.row.prop3)">{{ scope.row.prop3 }}</span>
<span>{{ parseTime(scope.row.sendTime,'{y}-{m}-{d}')}}</span>
</template>
</el-table-column>
<el-table-column prop="prop4" label="发起人"></el-table-column>
<el-table-column prop="prop5" label="发起时间"></el-table-column>
<el-table-column prop="prop6" label="接收时间"></el-table-column>
<el-table-column label="操作" width="100" >
<el-button type="text" icon="el-icon-info" @click="drawer1 = true">详情</el-button>
<template slot-scope="scope">
<el-button type="text" icon="el-icon-info" @click="handleDeal(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table><!--el-table-->
<el-pagination :current-page="currentPage4" :page-sizes="[100, 200, 300, 400]" :page-size="100" layout="total, sizes, prev, pager, next, jumper" :total="400"></el-pagination>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getListData"
/>
</el-tab-pane><!--el-tab-pane-->
<el-tab-pane :label="'已办('+doneTotal+')'" name="taskDealed">
<el-table :data="postList" style="width: 100%" height="529" v-loading="loading">
<el-table-column label="序号" width="60" type="index" align="center"></el-table-column>
<el-table-column prop="procDefName" label="流程类型"></el-table-column>
<el-table-column prop="title" label="流程标题"></el-table-column>
<el-table-column prop="curActDefName" label="处理环节"></el-table-column>
<el-table-column label="上一环节">
<template slot-scope="scope">
<span v-if="!scope.row.prevActDefName">/</span>
<span v-else>{{ scope.row.prevActDefName }}</span>
</template>
</el-table-column>
<el-table-column prop="sendUserName" label="上一环节处理人"></el-table-column>
<el-table-column prop="startUserName" label="发起人"></el-table-column>
<el-table-column prop="sendTime" label="接收时间">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.sendTime,'{y}-{m}-{d}')}}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="100" >
<template slot-scope="scope">
<el-button type="text" icon="el-icon-info" @click="handleDeal(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table><!--el-table-->
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getListData"
/>
</el-tab-pane><!--el-tab-pane-->
<el-tab-pane :label="'办结('+finishedTotal+')'" name="taskFinish">
<el-table :data="postList" style="width: 100%" height="529" v-loading="loading">
<el-table-column label="序号" width="60" type="index" align="center"></el-table-column>
<el-table-column prop="procDefName" label="流程类型"></el-table-column>
<el-table-column prop="title" label="流程标题"></el-table-column>
<el-table-column prop="startUserName" label="发起人"></el-table-column>
<el-table-column prop="startTime" label="发起时间">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.startTime,'{y}-{m}-{d}')}}</span>
</template>
</el-table-column>
<el-table-column prop="sendTime" label="接收时间">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.sendTime,'{y}-{m}-{d}')}}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="100" >
<template slot-scope="scope">
<el-button type="text" icon="el-icon-info" @click="handleDeal(scope.row)">详情</el-button>
</template>
</el-table-column>
</el-table><!--el-table-->
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getListData"
/>
</el-tab-pane><!--el-tab-pane-->
</el-tabs><!--el-tabs-->
</el-card><!--el-card-->
<el-drawer :visible.sync="drawer1" :direction="direction" :before-close="handleClose" size="75%">
<template #title>
<span>申请使用</span>
<div class="drawer-head-btn">
<el-button @click="drawer2 = true">流程监控</el-button>
<el-button type="primary" v-if="activeName3 == 'first'">提交</el-button>
<el-button>取消</el-button>
</div><!--drawer-head-btn 抽屉顶部按钮区域-->
</template>
<el-tabs v-model="activeName1" @tab-click="handleClick">
<el-tab-pane label="信息内容" name="first">
<div class="el-form-border">
<el-form ref="form" label-width="150px">
<el-row>
<el-col :span="24">
<el-form-item label="申请人">张莹</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="申请部门">信息部</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="申请理由">
<el-input type="textarea" maxlength="1000" placeholder="工作需要额外申请,请批准!" :disabled="true"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form><!--el-form-->
</div><!--el-form-border 表单-->
<div class="divide double"></div><!--divide 分隔-->
<div class="tboper">
<div class="tit">申请工具</div>
</div><!--tboper 标题与操作按钮-->
<el-table :data="tableData2" style="width: 100%">
<el-table-column prop="prop1" label="工具编号"></el-table-column>
<el-table-column prop="prop2" label="工具名称"></el-table-column>
<el-table-column prop="prop5" label="工具类别" ></el-table-column>
<el-table-column prop="prop3" label="归属单位"> </el-table-column>
<el-table-column prop="prop4" label="负责人"></el-table-column>
</el-table><!--el-table-->
<div class="divide double"></div><!--divide 分隔-->
<div class="tboper" v-if="activeName3 == 'first'">
<div class="tit">审批信息</div>
</div><!--tboper 标题与操作按钮-->
<div class="el-form-border" v-if="activeName3 == 'first'">
<el-form ref="form" label-width="150px">
<el-row>
<el-col :span="24">
<el-form-item label="审批结论">
<el-radio-group v-model="radio1">
<el-radio label="1">通过</el-radio>
<el-radio label="2" >不通过</el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24">
<el-form-item label="审批理由">
<el-input type="textarea" rows="4" maxlength="1000" placeholder="请输入" show-word-limit></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form><!--el-form-->
</div><!--el-form-border 表单-->
</el-tab-pane><!--el-tab-pane-->
<el-tab-pane label="审批记录" name="second">
<el-table :data="tableData4" style="width: 100%">
<el-table-column prop="prop4" label="处理人"></el-table-column>
<el-table-column prop="prop3" label="处理环节"> </el-table-column>
<el-table-column prop="prop2" label="接收人"></el-table-column>
<el-table-column prop="prop1" label="接收环节"></el-table-column>
<el-table-column prop="prop7" label="处理时间" ></el-table-column>
<el-table-column prop="prop5" label="审批意见" ></el-table-column>
</el-table><!--el-table-->
</el-tab-pane><!--el-tab-pane-->
</el-tabs><!--el-tabs-->
</el-drawer><!--el-drawer 申请详情-抽屉-->
<el-drawer :visible.sync="drawer2" :direction="direction" :before-close="handleClose" size="75%">
<template #title>
<span>流程监控</span>
</template>
<div class="lctitle">流程标题申请使用工具名称1 流程定义名称申请使用流程</div><!--lctitle-->
<img style="width:auto; max-width: 100%;" src="../../../../public/images/lcjk1.jpg" />
</el-drawer><!--el-drawer 流程监控-抽屉-->
</div><!--app-container-->
</el-card>
<!-- 流程处理抽屉组件 -->
<DealDrawer v-if="dealDrawerShow" ref="dealDrawer" @closeDrawer="handleCloseChange"></DealDrawer>
</div>
</template>
<script>
export default {
name: 'dispose',
data() {
return {
drawer1: false,
drawer2: false,
activeName1: 'first',
activeName2: 'second',
activeName3: 'first',
radio1: '1',
tableData1: [
{
prop1: '使用申请',
prop2: '进行中',
prop3: '直接领导审核',
prop4: '赵宇',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '已办结',
prop3: '直接领导审核',
prop4: '钱多多',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '进行中',
prop3: '直接领导审核',
prop4: '赵宇',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '已办结',
prop3: '直接领导审核',
prop4: '钱多多',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '进行中',
prop3: '直接领导审核',
prop4: '赵宇',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '已办结',
prop3: '直接领导审核',
prop4: '钱多多',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '进行中',
prop3: '直接领导审核',
prop4: '赵宇',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '已办结',
prop3: '直接领导审核',
prop4: '钱多多',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '进行中',
prop3: '直接领导审核',
prop4: '赵宇',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
},
{
prop1: '使用申请',
prop2: '已办结',
prop3: '直接领导审核',
prop4: '钱多多',
prop5: '2024/02/09 12:00',
prop6: '2024/02/09 12:00',
}
],
tableData2: [
{
prop1: '0021',
prop2: '工具名称1',
prop3: '人力资源部/培训组',
prop4: '赵宇',
prop5: '网络工具',
},
{
prop1: '0022',
prop2: '工具名称2',
prop3: '人力资源部/招聘组',
prop4: '钱多多',
prop5: '网络工具',
},
{
prop1: '0023',
prop2: '工具名称3',
prop3: '人力资源部/薪资组',
prop4: '孙瑶',
prop5: '网络工具',
}
],
tableData3: [
{
prop1: '总监批准',
prop2: '不通过',
prop3: '赵宇 ',
prop4: '总裁办',
prop5: '2024/02/09 12:00',
},
{
prop1: '部门领导审核',
prop2: '通过',
prop3: '钱多多',
prop4: '设备部',
prop5: '2024/02/09 12:00',
},
{
prop1: '管理员审核',
prop2: '通过',
prop3: '孙瑶',
prop4: '人力资源部',
prop5: '2024/02/09 12:00',
}
],
tableData4: [
{
prop1: '部门领导审核',
prop2: '张宇',
prop3: '管理员审核 ',
prop4: '赵定',
prop5: '同意',
prop6: '2024/02/09 12:00',
prop7: '2024/02/09 12:03',
prop8: '耗时0天',
prop9: '已完成',
},
{
prop1: '管理员审核',
prop2: '赵定',
prop3: '直接领导审核 ',
prop4: '钱多多',
prop5: '同意',
prop6: '2024/02/09 12:00',
prop7: '2024/02/09 12:03',
prop8: '耗时0天',
prop9: '已完成',
}
],
tableData5: [
{
prop1: '使用申请',
prop3: '部门经理审核',
prop4: '直接领导审核',
prop5: '张鑫辉',
prop6: '张慧玉',
prop7: '2022/10/10 12:00',
},
{
prop1: '使用申请',
prop3: '管理员审核',
prop4: '总监审核',
prop5: '柳青',
prop6: '刘青',
prop7: '2022/10/10 12:00',
},
{
prop1: '使用申请',
prop3: '总经理审核',
prop4: '直接领导审核',
prop5: '张庆幸',
prop6: '王慧',
prop7: '2022/10/10 12:00',
},
{
prop1: '使用申请',
prop3: '总监审核',
prop4: '部门经理审核',
prop5: '刘宁',
prop6: '赵媛',
prop7: '2022/10/10 12:00',
}
],
tableData6: [
{
prop1: '使用申请',
prop8: '通过',
prop3: '部门经理审核',
prop4: '直接领导审核',
prop5: '张鑫辉',
prop6: '张慧玉',
prop7: '2022/10/10 12:00',
},
{
prop1: '使用申请',
prop8: '通过',
prop3: '管理员审核',
prop4: '总监审核',
prop5: '柳青',
prop6: '刘青',
prop7: '2022/10/10 12:00',
},
{
prop1: '使用申请',
prop8: '通过',
prop3: '总经理审核',
prop4: '直接领导审核',
prop5: '张庆幸',
prop6: '王慧',
prop7: '2022/10/10 12:00',
},
{
prop1: '使用申请',
prop8: '通过',
prop3: '总监审核',
prop4: '部门经理审核',
prop5: '刘宁',
prop6: '赵媛',
prop7: '2022/10/10 12:00',
},
{
prop1: '使用申请',
prop8: '不通过',
prop3: '部门经理审核',
prop4: '直接领导审核',
prop5: '张鑫辉',
prop6: '张慧玉',
prop7: '2022/10/10 12:00',
},
{
prop1: '使用申请',
prop8: '通过',
prop3: '管理员审核',
prop4: '总监审核',
prop5: '柳青',
prop6: '刘青',
prop7: '2022/10/10 12:00',
},
{
prop1: '使用申请',
prop8: '不通过',
prop3: '总经理审核',
prop4: '直接领导审核',
prop5: '张庆幸',
prop6: '王慧',
prop7: '2022/10/10 12:00',
},
{
prop1: '使用申请',
prop8: '通过',
prop3: '总监审核',
prop4: '部门经理审核',
prop5: '刘宁',
prop6: '赵媛',
prop7: '2022/10/10 12:00',
},
{
prop1: '使用申请',
prop8: '通过',
prop3: '部门经理审核',
prop4: '直接领导审核',
prop5: '张鑫辉',
prop6: '张慧玉',
prop7: '2022/10/10 12:00',
},
{
prop1: '使用申请',
prop8: '通过',
prop3: '管理员审核',
prop4: '总监审核',
prop5: '柳青',
prop6: '刘青',
prop7: '2022/10/10 12:00',
},
],
tableData7: [
{
prop1: '使用申请',
prop3: '通过',
prop4: '张鑫辉',
prop5: '2024/02/08 07:00',
prop6: '2024/02/10 12:00',
},
{
prop1: '使用申请',
prop3: '不通过',
prop4: '柳青',
prop5: '2024/02/08 07:00',
prop6: '2024/02/10 12:00',
},
{
prop1: '使用申请',
prop3: '通过',
prop4: '张庆幸',
prop5: '2024/02/08 07:00',
prop6: '2024/02/10 12:00',
},
{
prop1: '使用申请',
prop3: '通过',
prop4: '刘宁',
prop5: '2024/02/08 07:00',
prop6: '2024/02/10 12:00',
},
{
prop1: '使用申请',
prop3: '不通过',
prop4: '张鑫辉',
prop5: '2024/02/08 07:00',
prop6: '2024/02/10 12:00',
},
{
prop1: '使用申请',
prop3: '通过',
prop4: '柳青',
prop5: '2024/02/08 07:00',
prop6: '2024/02/10 12:00',
},
{
prop1: '使用申请',
prop3: '通过',
prop4: '张庆幸',
prop5: '2024/02/08 07:00',
prop6: '2024/02/10 12:00',
},
{
prop1: '使用申请',
prop3: '通过',
prop4: '刘宁',
prop5: '2024/02/08 07:00',
prop6: '2024/02/10 12:00',
},
{
prop1: '使用申请',
prop3: '通过',
prop4: '张鑫辉',
prop5: '2024/02/08 07:00',
prop6: '2024/02/10 12:00',
},
{
prop1: '使用申请',
prop3: '通过',
prop4: '柳青',
prop5: '2024/02/08 07:00',
prop6: '2024/02/10 12:00',
},
],
}
},
methods: {
getClassName(prop2) {
//
if (prop2 === '进行中') {
return 'blue';
} else if (prop2 === '已办结') {
return 'green';
}else if (prop2 === '不通过') {
return 'red';
} else if (prop2 === '通过') {
return 'green';
}
import { workflowToDoList } from "@/api/my_business/workflow";
import DealDrawer from "@/components/DealDrawer";
import { getUserMsgCount } from "@/api/message/message"
export default {
name: "Post",
dicts: ["sys_normal_disable", "sys_operterType"],
components: {
DealDrawer
},
data() {
return {
pageSizes: [10,20,50,100],
dealDrawerShow: false,
boxClass: false,
//
loading: true,
//
showSearch: true,
//
total: 0,
//
postList: [],
//
title: "",
//
open: false,
//
queryParams: {
pageNumber: 1,
pageSize: 10,
title: "",
status: 1,
},
}
}
//
rules: {
postName: [
{
required: true,
message: "不能为空",
trigger: "blur",
},
],
postCode: [
{
required: true,
message: "不能为空",
trigger: "blur",
},
],
postSort: [
{
required: true,
message: "不能为空",
trigger: "blur",
},
],
},
doneTotal: 0,
finishedTotal: 0,
taskData: [], //
deptOptions: [],
drawer: false,
taskFormData: {},
varChangeColor1: true,
varChangeColor2: false,
pListData: {},
statustotal: "",
adUpdateDisuseDetails: "",
userInfo: this.$store.getters.userInfo,
activeName: "taskToDo",
classLevelOptions: [],
};
},
created() {
//
this.getListData()
//
this.getOtherActiveCount()
},
methods: {
//
handleDeal(row) {
this.dealDrawerShow = true;
let flowUrl = this.buildFlowUrl(row)
this.$nextTick(() => {
this.$refs.dealDrawer.init(flowUrl);
});
//
},
buildFlowUrl(row) {
let res = row.url;
//=1=2=3
res += "&invokeFrom=list&status="+row.status
return res;
},
getOtherActiveCount() {
//
this.loading = true
let params = {
pageNumber: 1,
pageSize: 10,
status: 2,
};
workflowToDoList(params).then((response) => {
this.doneTotal = response.data.totalCount || 0;
this.loading = false
});
//
this.loading = true
let params2 = {
pageNumber: 1,
pageSize: 10,
status: 3,
};
workflowToDoList(params2).then((response) => {
this.finishedTotal = response.data.totalCount || 0;
this.loading = false
});
},
/** 查询列表 */
getListData() {
let self = this
self.loading = true;
self.postList = [];
workflowToDoList(self.queryParams).then((response) => {
if (self.activeName == "taskToDo") {
//
self.statustotal = response.data.totalCount;
// this.$store.commit("SET_THINGNUMBER", response.data.totalCount || 0);
self.total = response.data.totalCount;
}
if (self.activeName == "taskDealed") {
//
self.doneTotal = response.data.totalCount;
self.total = response.data.totalCount;
}
if (self.activeName == "taskFinish") {
//
self.finishedTotal = response.data.totalCount;
self.total = response.data.totalCount;
}
self.postList = response.data.result;
setTimeout(function () {
self.loading = false;
}, 500);
}).catch(err => {
console.info("err=============", err)
setTimeout(function () {
self.loading = false;
}, 500);
});
},
//
handleCloseChange() {
this.dealDrawerShow = false
getUserMsgCount(this.$store.getters.userId).then(res => {
this.$store.commit("SET_UNREAD_MSG_NUMBER", res.data);
});
this.getListData();
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNumber = 1;
this.getListData();
},
/** 重置按钮操作 */
resetQuery() {
this.queryParams.pageNumber = 1;
this.queryParams.pageSize = 10;
this.queryParams.title = "";
this.handleQuery();
},
/** 详情按钮操作 */
handleDetails(row) {
},
state(tab) {
let p = Number(tab.index) + 1;
if (p == 1) {
this.varChangeColor1 = true;
this.varChangeColor2 = false;
}
if (p == 2 || p == 3) {
this.varChangeColor1 = false;
this.varChangeColor2 = true;
}
this.queryParams.status = p;
this.queryParams.pageNumber = 1;
this.queryParams.title = "";
this.total = 0;
this.getListData();
// this.getshulian();
},
},
};
</script>
<style scoped>
</style>

Some files were not shown because too many files have changed in this diff Show More