b4a53d0cf96ee1520a942d092762fabaf9471e5b..65ce2e4b82f2400493fc55b1a8685bbbc1ba30dd
2025-06-24 cuijian
流程页面样式
65ce2e 对比 | 目录
2025-06-23 cuijian
系统管理、工作流
f9c608 对比 | 目录
已添加24个文件
已修改7个文件
5161 ■■■■■ 文件已修改
.env.development 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.production 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json 273 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main.js 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/request.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/api/definition.js 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/api/finished.js 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/api/process.js 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/api/todo.js 65 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/components/ActApplyBtn.vue 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/components/ActCancelBtn.vue 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/components/ActHandleBtn.vue 235 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/components/ActHistoricDetailBtn.vue 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/components/HistoricDetail.vue 343 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/mixin/FlowableMixin.js 68 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/modeler/modelerDesign.vue 402 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/workflow/FlowCompleted.vue 182 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/workflow/FlowLedger.vue 209 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/workflow/FlowTodo.vue 424 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/workflow/assignFileStream/AssignFileStreamHandle.vue 434 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/workflow/assignFileStream/AssignFileStreamXq.vue 389 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/workflow/dispatchFile/DispatchFileBachHandleForm.vue 216 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/workflow/dispatchFile/DispatchFileBachHandleStyle#Drawer.vue 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/workflow/dispatchFile/DispatchFileHandle.vue 415 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/flowable/workflow/dispatchFile/DispatchFileXq.vue 364 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/SysBusinessCodeRuleList.vue 177 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/SysParamsList.vue 214 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/modules/SysBusinessCodeRuleModal.vue 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/system/modules/SysParamsModal.vue 124 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vue.config.js 12 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.development
@@ -1,5 +1,5 @@
NODE_ENV=development
VUE_APP_API_BASE_URL=http://192.168.124.118:9989
VUE_APP_API_BASE_URL=http://127.0.0.1:9989/jeecg-boot
VUE_APP_CAS_BASE_URL=http://cas.example.org:8443/cas
VUE_APP_ONLINE_BASE_URL=http://fileview.jeecg.com/onlinePreview
.env.production
@@ -1,4 +1,4 @@
NODE_ENV=production
VUE_APP_API_BASE_URL=http://192.168.124.118:9989
VUE_APP_API_BASE_URL=http://127.0.0.1:9989
VUE_APP_CAS_BASE_URL=http://localhost:8888/cas
VUE_APP_ONLINE_BASE_URL=http://fileview.jeecg.com/onlinePreview
package-lock.json
@@ -1403,6 +1403,56 @@
      "resolved": "https://registry.npmmirror.com/@jeecg/antd-online-mini/-/antd-online-mini-3.4.3-beta2.tgz",
      "integrity": "sha512-uZLjtQG/vAcBsCEysE1HceUyzwiHwU+JlNzvHxNnenNDHeaawZa9CfILUImNFJ5JQVqE5J11QpQNb6i5Boo3Gw=="
    },
    "@jiaminghi/bezier-curve": {
      "version": "0.0.9",
      "resolved": "https://registry.npmmirror.com/@jiaminghi/bezier-curve/-/bezier-curve-0.0.9.tgz",
      "integrity": "sha512-u9xJPOEl6Dri2E9FfmJoGxYQY7vYJkURNX04Vj64tdi535tPrpkuf9Sm0lNr3QTKdHQh0DdNRsaa62FLQNQEEw==",
      "requires": {
        "@babel/runtime": "^7.5.5"
      }
    },
    "@jiaminghi/c-render": {
      "version": "0.4.3",
      "resolved": "https://registry.npmmirror.com/@jiaminghi/c-render/-/c-render-0.4.3.tgz",
      "integrity": "sha512-FJfzj5hGj7MLqqqI2D7vEzHKbQ1Ynnn7PJKgzsjXaZpJzTqs2Yw5OSeZnm6l7Qj7jyPAP53lFvEQNH4o4j6s+Q==",
      "requires": {
        "@babel/runtime": "^7.5.5",
        "@jiaminghi/bezier-curve": "*",
        "@jiaminghi/color": "*",
        "@jiaminghi/transition": "*"
      }
    },
    "@jiaminghi/charts": {
      "version": "0.2.18",
      "resolved": "https://registry.npmmirror.com/@jiaminghi/charts/-/charts-0.2.18.tgz",
      "integrity": "sha512-K+HXaOOeWG9OOY1VG6M4mBreeeIAPhb9X+khG651AbnwEwL6G2UtcAQ8GWCq6GzhczcLwwhIhuaHqRygwHC0sA==",
      "requires": {
        "@babel/runtime": "^7.5.5",
        "@jiaminghi/c-render": "^0.4.3"
      }
    },
    "@jiaminghi/color": {
      "version": "1.1.3",
      "resolved": "https://registry.npmmirror.com/@jiaminghi/color/-/color-1.1.3.tgz",
      "integrity": "sha512-ZY3hdorgODk4OSTbxyXBPxAxHPIVf9rPlKJyK1C1db46a50J0reFKpAvfZG8zMG3lvM60IR7Qawgcu4ZDO3+Hg=="
    },
    "@jiaminghi/data-view": {
      "version": "2.10.0",
      "resolved": "https://registry.npmmirror.com/@jiaminghi/data-view/-/data-view-2.10.0.tgz",
      "integrity": "sha512-Cud2MTiMcqc5k2KWabR/svuVQmXHANqURo+yj40370/LdI/gyUJ6LG203hWXEnT1nMCeiv/SLVmxv3PXLScCeA==",
      "requires": {
        "@babel/runtime": "^7.5.5",
        "@jiaminghi/charts": "*"
      }
    },
    "@jiaminghi/transition": {
      "version": "1.1.11",
      "resolved": "https://registry.npmmirror.com/@jiaminghi/transition/-/transition-1.1.11.tgz",
      "integrity": "sha512-owBggipoHMikDHHDW5Gc7RZYlVuvxHADiU4bxfjBVkHDAmmck+fCkm46n2JzC3j33hWvP9nSCAeh37t6stgWeg==",
      "requires": {
        "@babel/runtime": "^7.5.5"
      }
    },
    "@mrmlnc/readdir-enhanced": {
      "version": "2.2.1",
      "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
@@ -5134,6 +5184,33 @@
      "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
      "dev": true
    },
    "bpmn-js": {
      "version": "7.5.0",
      "resolved": "https://registry.npmmirror.com/bpmn-js/-/bpmn-js-7.5.0.tgz",
      "integrity": "sha512-0ANaE6Bikg1GmkcvO7RK0MQPX+EKYKBc+q7OWk39/16NcCdNZ/4UiRcCr9n0u1VUCIDsSU/jJ79TIZFnV5CNjw==",
      "requires": {
        "bpmn-moddle": "^7.0.4",
        "css.escape": "^1.5.1",
        "diagram-js": "^6.8.2",
        "diagram-js-direct-editing": "^1.6.1",
        "ids": "^1.0.0",
        "inherits": "^2.0.4",
        "min-dash": "^3.5.2",
        "min-dom": "^3.1.3",
        "object-refs": "^0.3.0",
        "tiny-svg": "^2.2.2"
      }
    },
    "bpmn-moddle": {
      "version": "7.1.3",
      "resolved": "https://registry.npmmirror.com/bpmn-moddle/-/bpmn-moddle-7.1.3.tgz",
      "integrity": "sha512-ZcBfw0NSOdYTSXFKEn7MOXHItz7VfLZTrFYKO8cK6V8ZzGjCcdiLIOiw7Lctw1PJsihhLiZQS8Htj2xKf+NwCg==",
      "requires": {
        "min-dash": "^3.5.2",
        "moddle": "^5.0.2",
        "moddle-xml": "^9.0.6"
      }
    },
    "brace-expansion": {
      "version": "1.1.11",
      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@@ -6112,6 +6189,11 @@
      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
      "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg=="
    },
    "component-event": {
      "version": "0.1.4",
      "resolved": "https://registry.npmmirror.com/component-event/-/component-event-0.1.4.tgz",
      "integrity": "sha512-GMwOG8MnUHP1l8DZx1ztFO0SJTFnIzZnBDkXAj8RM2ntV2A6ALlDxgbMY1Fvxlg6WPQ+5IM/a6vg4PEYbjg/Rw=="
    },
    "component-indexof": {
      "version": "0.0.3",
      "resolved": "https://registry.npmmirror.com/component-indexof/-/component-indexof-0.0.3.tgz",
@@ -6821,6 +6903,11 @@
      "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.3.0.tgz",
      "integrity": "sha512-pv9JPyatiPaQ6pf4OvD/dbfm0o5LviWmwxNWzblYf/1u9QZd0ihV+PMwy5jdQWQ3349kZmKEx9WXuSka2dM4cg==",
      "dev": true
    },
    "css.escape": {
      "version": "1.5.1",
      "resolved": "https://registry.npmmirror.com/css.escape/-/css.escape-1.5.1.tgz",
      "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="
    },
    "cssesc": {
      "version": "3.0.0",
@@ -7735,8 +7822,7 @@
    "deepmerge": {
      "version": "1.5.2",
      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz",
      "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==",
      "dev": true
      "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ=="
    },
    "default-gateway": {
      "version": "5.0.5",
@@ -7988,6 +8074,36 @@
      "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.0.4.tgz",
      "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw=="
    },
    "diagram-js": {
      "version": "6.8.2",
      "resolved": "https://registry.npmmirror.com/diagram-js/-/diagram-js-6.8.2.tgz",
      "integrity": "sha512-5EKYHjW2mmGsn9/jSenSkm8cScK5sO9eETBRQNIIzgZjxBDJn6eX964L2d7/vrAW9SeuijGUsztL9+NUinSsNg==",
      "requires": {
        "css.escape": "^1.5.1",
        "didi": "^4.0.0",
        "hammerjs": "^2.0.1",
        "inherits": "^2.0.1",
        "min-dash": "^3.5.0",
        "min-dom": "^3.1.2",
        "object-refs": "^0.3.0",
        "path-intersection": "^2.2.0",
        "tiny-svg": "^2.2.1"
      }
    },
    "diagram-js-direct-editing": {
      "version": "1.8.0",
      "resolved": "https://registry.npmmirror.com/diagram-js-direct-editing/-/diagram-js-direct-editing-1.8.0.tgz",
      "integrity": "sha512-B4Xj+PJfgBjbPEzT3uZQEkZI5xHFB0Izc+7BhDFuHidzrEMzQKZrFGdA3PqfWhReHf3dp+iB6Tt11G9eGNjKMw==",
      "requires": {
        "min-dash": "^3.5.2",
        "min-dom": "^3.1.3"
      }
    },
    "didi": {
      "version": "4.0.0",
      "resolved": "https://registry.npmmirror.com/didi/-/didi-4.0.0.tgz",
      "integrity": "sha512-AzMElh8mCHOPWPCWfGjoJRla31fMXUT6+287W5ef3IPmtuBcyG9+MkFS7uPP6v3t2Cl086KwWfRB9mESa0OsHQ=="
    },
    "diffie-hellman": {
      "version": "5.0.3",
      "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
@@ -8127,6 +8243,11 @@
        "domelementtype": "1"
      }
    },
    "domify": {
      "version": "1.4.2",
      "resolved": "https://registry.npmmirror.com/domify/-/domify-1.4.2.tgz",
      "integrity": "sha512-m4yreHcUWHBncGVV7U+yQzc12vIlq0jMrtHZ5mW6dQMiL/7skSYNVX9wqKwOtyO9SGCgevrAFEgOCAHmamHTUA=="
    },
    "domutils": {
      "version": "1.7.0",
      "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
@@ -8262,6 +8383,29 @@
      "version": "1.3.495",
      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.495.tgz",
      "integrity": "sha512-cIPX+4Y3RH/+SoqYd168Rx//CnjsZSdF3XTUhwMf3dwYuTfvWIgmmy6s1ipptGaOA+scH2Vj57Mc9fqp/ho22Q=="
    },
    "element-ui": {
      "version": "2.15.14",
      "resolved": "https://registry.npmmirror.com/element-ui/-/element-ui-2.15.14.tgz",
      "integrity": "sha512-2v9fHL0ZGINotOlRIAJD5YuVB8V7WKxrE9Qy7dXhRipa035+kF7WuU/z+tEmLVPBcJ0zt8mOu1DKpWcVzBK8IA==",
      "requires": {
        "async-validator": "~1.8.1",
        "babel-helper-vue-jsx-merge-props": "^2.0.0",
        "deepmerge": "^1.2.0",
        "normalize-wheel": "^1.0.1",
        "resize-observer-polyfill": "^1.5.0",
        "throttle-debounce": "^1.0.1"
      },
      "dependencies": {
        "async-validator": {
          "version": "1.8.5",
          "resolved": "https://registry.npmmirror.com/async-validator/-/async-validator-1.8.5.tgz",
          "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==",
          "requires": {
            "babel-runtime": "6.x"
          }
        }
      }
    },
    "elliptic": {
      "version": "6.5.3",
@@ -9975,6 +10119,11 @@
        }
      }
    },
    "hammerjs": {
      "version": "2.0.8",
      "resolved": "https://registry.npmmirror.com/hammerjs/-/hammerjs-2.0.8.tgz",
      "integrity": "sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ=="
    },
    "handle-thing": {
      "version": "2.0.1",
      "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
@@ -10523,6 +10672,11 @@
        }
      }
    },
    "ids": {
      "version": "1.0.5",
      "resolved": "https://registry.npmmirror.com/ids/-/ids-1.0.5.tgz",
      "integrity": "sha512-XQ0yom/4KWTL29sLG+tyuycy7UmeaM/79GRtSJq6IG9cJGIPeBz5kwDCguie3TwxaMNIc3WtPi0cTa1XYHicpw=="
    },
    "ieee754": {
      "version": "1.1.13",
      "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
@@ -10621,6 +10775,11 @@
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
      "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc="
    },
    "indexof": {
      "version": "0.0.1",
      "resolved": "https://registry.npmmirror.com/indexof/-/indexof-0.0.1.tgz",
      "integrity": "sha512-i0G7hLJ1z0DE8dsqJa2rycj9dBmNKgXBvotXtZYXakU9oivfB9Uj2ZBC27qqef2U58/ZLwalxa1X/RDCdkHtVg=="
    },
    "infer-owner": {
      "version": "1.0.4",
@@ -11519,6 +11678,11 @@
      "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
      "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY="
    },
    "lodash.clonedeep": {
      "version": "4.5.0",
      "resolved": "https://registry.npmmirror.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
      "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
    },
    "lodash.defaults": {
      "version": "4.2.0",
      "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
@@ -11576,6 +11740,11 @@
      "version": "4.1.2",
      "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
      "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4="
    },
    "lodash.merge": {
      "version": "4.6.2",
      "resolved": "https://registry.npmmirror.com/lodash.merge/-/lodash.merge-4.6.2.tgz",
      "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="
    },
    "lodash.pick": {
      "version": "4.4.0",
@@ -11705,6 +11874,11 @@
      "requires": {
        "object-visit": "^1.0.0"
      }
    },
    "matches-selector": {
      "version": "1.2.0",
      "resolved": "https://registry.npmmirror.com/matches-selector/-/matches-selector-1.2.0.tgz",
      "integrity": "sha512-c4vLwYWyl+Ji+U43eU/G5FwxWd4ZH0ePUsFs5y0uwD9HUEFBXUQ1zUUan+78IpRD+y4pUfG0nAzNM292K7ItvA=="
    },
    "math-expression-evaluator": {
      "version": "1.2.22",
@@ -12039,6 +12213,23 @@
      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
    },
    "min-dash": {
      "version": "3.8.1",
      "resolved": "https://registry.npmmirror.com/min-dash/-/min-dash-3.8.1.tgz",
      "integrity": "sha512-evumdlmIlg9mbRVPbC4F5FuRhNmcMS5pvuBUbqb1G9v09Ro0ImPEgz5n3khir83lFok1inKqVDjnKEg3GpDxQg=="
    },
    "min-dom": {
      "version": "3.2.1",
      "resolved": "https://registry.npmmirror.com/min-dom/-/min-dom-3.2.1.tgz",
      "integrity": "sha512-v6YCmnDzxk4rRJntWTUiwggLupPw/8ZSRqUq0PDaBwVZEO/wYzCH4SKVBV+KkEvf3u0XaWHly5JEosPtqRATZA==",
      "requires": {
        "component-event": "^0.1.4",
        "domify": "^1.3.1",
        "indexof": "0.0.1",
        "matches-selector": "^1.2.0",
        "min-dash": "^3.8.1"
      }
    },
    "mini-css-extract-plugin": {
      "version": "0.8.2",
      "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.2.tgz",
@@ -12174,6 +12365,24 @@
      "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
      "requires": {
        "minimist": "^1.2.5"
      }
    },
    "moddle": {
      "version": "5.0.4",
      "resolved": "https://registry.npmmirror.com/moddle/-/moddle-5.0.4.tgz",
      "integrity": "sha512-Kjb+hjuzO+YlojNGxEUXvdhLYTHTtAABDlDcJTtTcn5MbJF9Zkv4I1Fyvp3Ypmfgg1EfHDZ3PsCQTuML9JD6wg==",
      "requires": {
        "min-dash": "^3.0.0"
      }
    },
    "moddle-xml": {
      "version": "9.0.6",
      "resolved": "https://registry.npmmirror.com/moddle-xml/-/moddle-xml-9.0.6.tgz",
      "integrity": "sha512-tl0reHpsY/aKlLGhXeFlQWlYAQHFxTkFqC8tq8jXRYpQSnLVw13T6swMaourLd7EXqHdWsc+5ggsB+fEep6xZQ==",
      "requires": {
        "min-dash": "^3.5.2",
        "moddle": "^5.0.2",
        "saxen": "^8.1.2"
      }
    },
    "moment": {
@@ -12428,6 +12637,11 @@
        "sort-keys": "^1.0.0"
      }
    },
    "normalize-wheel": {
      "version": "1.0.1",
      "resolved": "https://registry.npmmirror.com/normalize-wheel/-/normalize-wheel-1.0.1.tgz",
      "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA=="
    },
    "npm-run-path": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@@ -12520,6 +12734,11 @@
      "version": "0.9.2",
      "resolved": "https://registry.npmjs.org/object-path/-/object-path-0.9.2.tgz",
      "integrity": "sha1-D9mnT8X60a45aLWGvaXGMr1sBaU="
    },
    "object-refs": {
      "version": "0.3.0",
      "resolved": "https://registry.npmmirror.com/object-refs/-/object-refs-0.3.0.tgz",
      "integrity": "sha512-eP0ywuoWOaDoiake/6kTJlPJhs+k0qNm4nYRzXLNHj6vh+5M3i9R1epJTdxIPGlhWc4fNRQ7a6XJNCX+/L4FOQ=="
    },
    "object-visit": {
      "version": "1.0.1",
@@ -12921,6 +13140,11 @@
      "version": "3.0.0",
      "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
      "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
    },
    "path-intersection": {
      "version": "2.2.1",
      "resolved": "https://registry.npmmirror.com/path-intersection/-/path-intersection-2.2.1.tgz",
      "integrity": "sha512-9u8xvMcSfuOiStv9bPdnRJQhGQXLKurew94n4GPQCdH1nj9QKC9ObbNoIpiRq8skiOBxKkt277PgOoFgAt3/rA=="
    },
    "path-is-absolute": {
      "version": "1.0.1",
@@ -15444,6 +15668,11 @@
      "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
      "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
    },
    "saxen": {
      "version": "8.1.2",
      "resolved": "https://registry.npmmirror.com/saxen/-/saxen-8.1.2.tgz",
      "integrity": "sha512-xUOiiFbc3Ow7p8KMxwsGICPx46ZQvy3+qfNVhrkwfz3Vvq45eGt98Ft5IQaA1R/7Tb5B5MKh9fUR9x3c3nDTxw=="
    },
    "schema-utils": {
      "version": "0.3.0",
      "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-0.3.0.tgz",
@@ -16654,6 +16883,11 @@
        "neo-async": "^2.6.0"
      }
    },
    "throttle-debounce": {
      "version": "1.1.0",
      "resolved": "https://registry.npmmirror.com/throttle-debounce/-/throttle-debounce-1.1.0.tgz",
      "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg=="
    },
    "through": {
      "version": "2.3.8",
      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
@@ -16697,6 +16931,11 @@
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
      "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
    },
    "tiny-svg": {
      "version": "2.2.4",
      "resolved": "https://registry.npmmirror.com/tiny-svg/-/tiny-svg-2.2.4.tgz",
      "integrity": "sha512-NOi39lBknf4UdDEahNkbEAJnzhu1ZcN2j75IS2vLRmIhsfxdZpTChfLKBcN1ShplVmPIXJAIafk6YY5/Aa80lQ=="
    },
    "tinycolor2": {
      "version": "1.6.0",
@@ -17264,6 +17503,14 @@
      "version": "0.5.4",
      "resolved": "https://registry.npmjs.org/vue-cropper/-/vue-cropper-0.5.4.tgz",
      "integrity": "sha512-9wwHOk1eHdl+nyq2fnIFDeDMjaXPh1dqfY+FdeEGU7Z/cKVOyH0pLrW0/5NH3xnRzqrU3DAQ8LjC/9/eHdvqKA=="
    },
    "vue-drag-resize": {
      "version": "1.5.4",
      "resolved": "https://registry.npmmirror.com/vue-drag-resize/-/vue-drag-resize-1.5.4.tgz",
      "integrity": "sha512-SR3U7n6TAZEBgP7zw7bR9mjtAlYBjqIoaWTDPz5HXN/nYhOxKSA31aD7p71fmq1jtyt9reAnCx62valNL9ZAcg==",
      "requires": {
        "vue-drag-resize": "^1.5.0-rc3"
      }
    },
    "vue-eslint-parser": {
      "version": "2.0.3",
@@ -18306,6 +18553,17 @@
        "errno": "~0.1.7"
      }
    },
    "workflow-bpmn-modeler": {
      "version": "0.2.8",
      "resolved": "https://registry.npmmirror.com/workflow-bpmn-modeler/-/workflow-bpmn-modeler-0.2.8.tgz",
      "integrity": "sha512-7Y2+YMx5mFDrpDAMoEK2EMVp5Z4585tYBLuqOxcbB5cdY6Vt1VjE1OBhzcwlFU6MWfpeisMGKbYtlPSHAOzsGg==",
      "requires": {
        "bpmn-js": "^7.2.1",
        "element-ui": "^2.12.0",
        "vue": "^2.6.10",
        "xcrud": "0.4.1"
      }
    },
    "wrap-ansi": {
      "version": "2.1.0",
      "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
@@ -18351,6 +18609,17 @@
        "async-limiter": "~1.0.0"
      }
    },
    "xcrud": {
      "version": "0.4.1",
      "resolved": "https://registry.npmmirror.com/xcrud/-/xcrud-0.4.1.tgz",
      "integrity": "sha512-aUbZZDARyNhbdBqT5nrHsXkYMM3Bo0i8EFvVgEyq444cxvYkqz4I71XWN2bPVhK/axfX4RawmIHjOQTz2v/apw==",
      "requires": {
        "element-ui": "^2.13.2",
        "lodash.clonedeep": "^4.5.0",
        "lodash.merge": "^4.6.2",
        "vue": "^2.6.11"
      }
    },
    "xe-utils": {
      "version": "2.4.8",
      "resolved": "https://registry.npmmirror.com/xe-utils/-/xe-utils-2.4.8.tgz",
package.json
@@ -24,6 +24,7 @@
    "dayjs": "^1.8.0",
    "dom-align": "1.12.0",
    "echarts": "^5.5.0",
    "element-ui": "^2.15.14",
    "enquire.js": "^2.1.6",
    "jquery": "^3.7.1",
    "js-cookie": "^2.2.0",
@@ -50,6 +51,7 @@
    "vuex": "^3.1.0",
    "vxe-table": "2.9.13",
    "vxe-table-plugin-antd": "1.8.10",
    "workflow-bpmn-modeler": "^0.2.8",
    "xe-utils": "2.4.8",
    "xss": "^1.0.13"
  },
src/main.js
@@ -47,6 +47,7 @@
import VueAreaLinkage from 'vue-area-linkage'
import '@/components/jeecg/JVxeTable/install'
import '@/components/JVxeCells/install'
import ElementUI from 'element-ui';
//表单验证
import { rules } from '@/utils/rules'
import * as echarts from 'echarts'
@@ -72,6 +73,7 @@
Vue.use(vueBus);
Vue.use(JeecgComponents);
Vue.use(VueAreaLinkage);
Vue.use(ElementUI);
SSO.init(() => {
  main()
src/utils/request.js
@@ -15,7 +15,7 @@
//console.log("apiBaseUrl= ",apiBaseUrl)
// åˆ›å»º axios å®žä¾‹
const service = axios.create({
  baseURL: '/api',
  baseURL: apiBaseUrl,
  // baseURL: apiBaseUrl, // api base_url
  timeout: 500000 // è¯·æ±‚è¶…æ—¶æ—¶é—´
})
src/views/flowable/api/definition.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,134 @@
import {axios as request} from '@/utils/request'
// æŸ¥è¯¢æµç¨‹å®šä¹‰åˆ—表
export function listDefinition(query) {
  return request({
    url: '/flowable/definition/list',
    method: 'get',
    params: query
  })
}
// éƒ¨ç½²æµç¨‹å®žä¾‹
export function definitionStartByDefId(procDefId,data) {
  return request({
    url: '/flowable/definition/startByProcDefId/' + procDefId,
    method: 'post',
    data: JSON.stringify(data)
  })
}
// éƒ¨ç½²æµç¨‹å®žä¾‹
export function definitionStartByDefKey(procDefKey,data) {
  return request({
    url: '/flowable/definition/startByProcDefKey/' + procDefKey,
    method: 'post',
    data: JSON.stringify(data)
  })
}
// éƒ¨ç½²æµç¨‹å®žä¾‹
export function definitionStartByDataId(dataId,data) {
  return request({
    url: '/flowable/definition/startByDataId/' + dataId,
    method: 'post',
    data: data
  })
}
// èŽ·å–æµç¨‹å˜é‡
export function getProcessVariables(taskId) {
  return request({
    url: '/flowable/task/processVariables/' + taskId,
    method: 'get'
  })
}
// æ¿€æ´»/挂起流程
export function updateState(params) {
  return request({
    url: '/flowable/definition/updateState',
    method: 'put',
    params: params
  })
}
// æŒ‡å®šæµç¨‹åŠžç†äººå‘˜åˆ—è¡¨
export function userList(query) {
  return request({
    url: '/flowable/definition/userList',
    method: 'get',
    params: query
  })
}
// æŒ‡å®šæµç¨‹åŠžç†ç»„åˆ—è¡¨
export function roleList(query) {
  return request({
    url: '/flowable/definition/roleList',
    method: 'get',
    params: query
  })
}
// æŒ‡å®šæµç¨‹åˆ†ç±»åˆ—表
export function categoryList(query) {
  return request({
    url: '/flowable/definition/categoryList',
    method: 'get',
    params: query
  })
}
// è¯»å–xml文件
export function readXml(deployId) {
  return request({
    url: '/flowable/definition/readXml/' + deployId,
    method: 'get'
  })
}
// è¯»å–xml文件
export function readXmlByDataId(dataId) {
  return request({
    url: '/flowable/definition/readXmlByDataId/' + dataId,
    method: 'get'
  })
}
// è¯»å–image文件
export function readImage(deployId) {
  return request({
    url: '/flowable/definition/readImage/' + deployId,
    method: 'get'
  })
}
// è¯»å–image文件
export function getFlowViewer(procInsId) {
  return request({
    url: '/flowable/task/flowViewer/' + procInsId,
    method: 'get'
  })
}
// è¯»å–image文件
export function getFlowViewerByDataId(dataId) {
  return request({
    url: '/flowable/task/flowViewerByDataId/' + dataId,
    method: 'get'
  })
}
// è¯»å–xml文件
export function saveXml(data) {
  return request({
    url: '/flowable/definition/save',
    method: 'post',
    data: data
  })
}
// åˆ é™¤æµç¨‹å®šä¹‰
export function delDeployment(query) {
  return request({
    url: '/flowable/definition/delete/',
    method: 'delete',
    params: query
  })
}
src/views/flowable/api/finished.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,37 @@
import {axios as request} from '@/utils/request'
// æŸ¥è¯¢å·²åŠžä»»åŠ¡åˆ—è¡¨
export function finishedList(query) {
  return request({
    url: '/flowable/task/finishedList',
    method: 'get',
    params: query
  })
}
// ä»»åŠ¡æµè½¬è®°å½•
export function flowRecord(query) {
  return request({
    url: '/flowable/task/flowRecord',
    method: 'get',
    params: query
  })
}
// æ’¤å›žä»»åŠ¡
export function revokeProcess(data) {
  return request({
    url: '/flowable/task/revokeProcess',
    method: 'post',
    data: data
  })
}
// éƒ¨ç½²æµç¨‹å®žä¾‹
export function deployStart(deployId) {
  return request({
    url: '/flowable/process/startFlow/' + deployId,
    method: 'get',
  })
}
src/views/flowable/api/process.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,34 @@
import {axios as request} from '@/utils/request'
// æˆ‘的发起的流程
export function myProcessList(query) {
  return request({
    url: '/flowable/task/myProcess',
    method: 'get',
    params: query
  })
}
// å–消申请
export function deleteByDataId(dataId,deleteReason) {
  const data = {
    dataId:dataId,
    deleteReason:deleteReason
  }
  return request({
    url: '/flowable/instance/deleteByDataId',
    method: 'post',
    params: data
  })
}
// éƒ¨ç½²æµç¨‹å®žä¾‹
export function deployStart(deployId) {
  return request({
    url: '/flowable/process/startFlow/' + deployId,
    method: 'get',
  })
}
src/views/flowable/api/todo.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,65 @@
import {axios as request} from '@/utils/request'
// æŸ¥è¯¢å¾…办任务列表
export function todoList(query) {
  return request({
    url: '/flowable/task/todoList',
    method: 'get',
    params: query
  })
}
// å®Œæˆä»»åŠ¡
export function completeTask(data) {
  return request({
    url: '/flowable/task/completeByDateId',
    method: 'post',
    data: data
  })
}
// å§”派任务
export function delegate(data) {
  return request({
    url: '/flowable/task/delegate',
    method: 'post',
    data: data
  })
}
// é€€å›žä»»åŠ¡
export function returnTask(data) {
  return request({
    url: '/flowable/task/taskReturnByDataId',
    method: 'post',
    data: data
  })
}
// é©³å›žä»»åŠ¡
export function rejectTask(data) {
  return request({
    url: '/flowable/task/taskRejectByDataId',
    method: 'post',
    data: data
  })
}
// å¯é€€å›žä»»åŠ¡åˆ—è¡¨
export function returnList(data) {
  return request({
    url: '/flowable/task/findReturnTaskListByDataId',
    method: 'post',
    data: data
  })
}
// ä¸‹ä¸€èŠ‚ç‚¹ todo ç›®å‰ç›´æŽ¥è‡ªåŠ¨åˆ†é…åˆ°å€™é€‰äººï¼Œä¸ç”¨ä¸»åŠ¨é€‰äººï¼Œå¦‚æœ‰éœ€è¦å†å¼€å‘
export function getNextFlowNode(data) {
  return request({
    url: '/flowable/task/nextFlowNode',
    method: 'post',
    data: data
  })
}
src/views/flowable/components/ActApplyBtn.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,73 @@
<style lang="less">
</style>
<template>
  <span>
      <a-button :loading="submitLoading" :type="btnType" @click="applySubmit()" >{{text}}</a-button>
  </span>
</template>
<script>
  import {definitionStartByDataId} from "@views/flowable/api/definition";
export default {
    name: 'ActApplyBtn',
    components: {},
    props: {
        btnType: { type: String, default: 'link', required: false },
        /**/
        dataId: {
            type: String,
            default: '',
            required: true
        },
        variables:{
          type: Object,
          default: {},
        },
        text: {
            type: String,
            default: '提交申请',
            required: false
        }
    },
    data() {
        return {
            modalVisible: false,
            submitLoading: false,
            form: {
            },
        };
    },
    created() {
    },
    watch: {
    },
    methods: {
        applySubmit() {
            if (this.dataId && this.dataId.length < 1) {
                this.error = '必须传入参数dataId';
                this.$message.error(this.error);
                return;
            } else {
                this.error = '';
            }
            this.submitLoading = true;
            var params = Object.assign({
                dataId: this.dataId
            }, this.variables);
          definitionStartByDataId(this.dataId, params)
                .then(res => {
                    if (res.success) {
                        this.$message.success('操作成功');
                        this.$emit('success');
                    } else {
                        this.$message.error(res.message);
                    }
                })
                .finally(() => (this.submitLoading = false));
        }
    }
};
</script>
src/views/flowable/components/ActCancelBtn.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,74 @@
<style lang="less">
</style>
<template>
  <span>
      <a-button :type="btnType" @click="cancel()" >{{text}}</a-button>
      <a-modal title="确认撤回" v-model="modalCancelVisible" :mask-closable="false" :width="500">
            <a-form ref="delForm" v-model="cancelForm" :label-width="70" v-if="modalCancelVisible">
                <a-form-item label="撤回原因" prop="reason">
                    <a-input type="textarea" v-model="cancelForm.reason" :rows="4" />
                </a-form-item>
            </a-form>
            <div slot="footer">
                <a-button type="text" @click="modalCancelVisible = false">取消</a-button>
                <a-button type="primary" :disabled="submitLoading" @click="handelSubmitCancel">提交</a-button>
            </div>
        </a-modal>
  </span>
</template>
<script>
import {deleteByDataId} from "@views/flowable/api/process";
export default {
    name: 'ActCancelBtn',
    components: {},
    props: {
        btnType: { type: String, default: 'link', required: false },
        /**/
        dataId: {
            type: String,
            default: '',
            required: true
        },
        text: {
            type: String,
            default: '撤回',
            required: false
        }
    },
    data() {
        return {
            modalCancelVisible: false,
            cancelForm: {
                reason: ''
            },
            submitLoading: false,
        };
    },
    created() {
    },
    watch: {
    },
    methods: {
        cancel() {
            this.modalCancelVisible = true;
        },
        handelSubmitCancel() {
            this.submitLoading = true;
          deleteByDataId(this.dataId, this.cancelForm.reason)
                .then(res => {
                    if (res.success) {
                        this.$message.success('操作成功');
                        this.modalCancelVisible = false;
                        this.$emit('success');
                    } else {
                        this.$message.error(res.message);
                    }
                })
                .finally(() => (this.submitLoading = false));
        }
    }
};
</script>
src/views/flowable/components/ActHandleBtn.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,235 @@
<style lang="less">
</style>
<template>
  <span>
      <a-button :type="btnType" @click="handle()" >{{text}}</a-button>
      <a-modal :title="modalTaskTitle" v-model="modalTaskVisible" :mask-closable="false" :width="500">
      <div  v-if="modalTaskVisible">
        <div v-if="type==handleType.reApply">
          ç¡®è®¤æ— è¯¯å¹¶é‡æ–°æäº¤ï¼Ÿ
        </div>
        <a-form ref="form" :model="form" :label-width="85" >
          <a-form-item v-if="type!==handleType.reApply" label="处理意见" prop="reason">
            <a-input type="textarea" v-model="form.comment" :rows="4" />
          </a-form-item>
          <div v-show="type==2">
            <a-form-item label="退回节点" prop="targetKey" v-if="returnTaskList.length">
              <a-radio-group v-model="form.targetKey" @change="targetKeyChange">
                <a-radio-button
                  v-for="item in returnTaskList"
                  :key="item.id"
                  :value="item.id"
                >{{item.name}}</a-radio-button>
              </a-radio-group>
            </a-form-item>
            <span v-else>无可退回节点!</span>
          </div>
            <div v-if="form.targetKey !== 'start' && candidateUsers.length">
                <a-form-item label="下个节点审批候选人">
                    <a-select
                        mode="multiple"
                        v-model="candidateUsersSelecteds"
                        style="width: 100%"
                        placeholder="请选择下个节点审批候选人"
                    >
                    <a-select-option v-for="user in candidateUsers" :key="user.username" :value="user.username">
                        {{user.realname}}
                    </a-select-option>
                  </a-select>
                </a-form-item>
            </div>
        </a-form>
      </div>
      <div slot="footer">
        <a-button type="text" @click="modalTaskVisible=false">取消</a-button>
        <a-button type="primary" :loading="submitLoading" @click="handelSubmit">提交</a-button>
      </div>
    </a-modal>
  </span>
</template>
<script>
  import {completeTask, rejectTask, returnList, returnTask} from "@views/flowable/api/todo";
export default {
    name: 'ActHandleBtn',
    components: {},
    props: {
        btnType: { type: String, default: 'link', required: false },
        /* handleType 0通过 1驳回 2退回  */
        type: {
            type: String|Number,
            default: '0',
            required: true
        },
        dataId: {
            type: String,
            default: '',
            required: true
        },
      /*流程变量*/
        variables:{
          type: Object,
          default: ()=>{},
        },
        candidateUsers:{
          type: Array,
          default: ()=>[],
        },
        text: {
            type: String,
            default: '处理',
            required: false
        }
    },
    data() {
        return {
          handleType:{
            // é€šè¿‡
            pass: 0,
            // é©³å›ž
            back: 1,
            // é€€å›ž
            return: 2,
            // é‡æ–°æäº¤
            reApply: 3
            },
            returnTaskList: [],
            candidateUsersSelecteds:[],
            modalTaskVisible: false,
            submitLoading: false,
            form: {
              comment:'',
              targetKey:''
            },
            modalTaskTitle: '',
        };
    },
    created() {
    },
    watch: {
    },
    methods: {
        handle() {
          this.form.comment = ''
          this.candidateUsersSelecteds = []
            if (this.type === this.handleType.delegate) {
                // this.delegateTask();
            } else if (this.type === this.handleType.pass) {
                this.passTask();
            } else if (this.type === this.handleType.back) {
                this.backTask();
            } else if(this.type === this.handleType.return){
                this.returnTask();
            } else if(this.type === this.handleType.reApply){
                this.reApply();
            }
            else {
                this.$message.warn('未知类型type,参见 handleType');
            }
        },
        reApply() {
            const v = this;
            this.modalTaskTitle = '确认重新提交';
            this.modalTaskVisible = true;
        },
        passTask() {
            const v = this;
            this.modalTaskTitle = '审批通过';
            this.modalTaskVisible = true;
        },
        backTask() {
          const v = this;
          this.modalTaskTitle = '审批驳回';
          this.modalTaskVisible = true;
        },
        returnTask() {
            const v = this;
            this.modalTaskTitle = '审批退回';
            this.modalTaskVisible = true;
            returnList({dataId:this.dataId}).then(res => {
              this.returnTaskList = res.result||[];
              // console.log(this.returnTaskList)
            })
        },
        handelSubmit() {
            console.log('提交');
            this.submitLoading = true;
            var formData = Object.assign({
                dataId:this.dataId,
                candidateUsers:this.candidateUsersSelecteds,
                values:Object.assign({dataId:this.dataId},this.variables)
            }, this.form);
            if (this.type==this.handleType.reApply){
              formData.comment = '重新提交'
            }
            if (!formData.comment){
              this.$message.error('请输入审批意见!');
              this.submitLoading=false
              return;
            }
            // æœ‰ä¸‹ä¸ªèŠ‚ç‚¹å®¡æ‰¹äººé€‰æ‹©ï¼Œä½†æ˜¯æœªé€‰
            if (this.candidateUsers.length &&
              this.candidateUsersSelecteds.length==0 &&
              this.form.targetKey !== 'start'
            ){
              this.$message.error('请选择下个节点审批人!');
              this.submitLoading=false
              return;
            }
            if (this.type == this.handleType.reApply || this.type == this.handleType.pass) {
                // é€šè¿‡
              completeTask(formData).then(res => {
                    this.submitLoading = false;
                    if (res.success) {
                        this.$message.success('操作成功');
                        this.modalTaskVisible = false;
                        this.$emit('success');
                    } else {
                        this.$message.error('操作失败');
                    }
                }).finally(()=>{this.submitLoading=false});
            } else if (this.type == this.handleType.back) {
                // é©³å›ž
                  rejectTask(formData).then(res => {
                        this.submitLoading = false;
                        if (res.success) {
                            this.$message.success('操作成功');
                            this.modalTaskVisible = false;
                            this.$emit('success');
                        } else {
                            this.$message.error('操作失败');
                        }
                    }).finally(()=>{this.submitLoading=false});
            } else if (this.type == this.handleType.return){
              if (!formData.targetKey){
                this.$message.error('请选择退回节点!');
                this.submitLoading=false
                return;
              }
              //退回
              returnTask(formData).then(res => {
                this.submitLoading = false;
                if (res.success) {
                  this.$message.success('操作成功');
                  this.modalTaskVisible = false;
                  this.$emit('success');
                } else {
                  this.$message.error('操作失败');
                }
              }).finally(()=>{this.submitLoading=false});
            }
        },
        targetKeyChange() {
            this.candidateUsersSelecteds = []
            this.$emit('targetKeyChange',this.form.targetKey)
        }
    }
};
</script>
src/views/flowable/components/ActHistoricDetailBtn.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,53 @@
<style lang="less">
</style>
<template>
  <span>
      <a-button :type="btnType"  @click="history()" >{{text}}</a-button>
      <a-modal title="审批历史" v-model="modalLsVisible" :mask-closable="true" :width="'80%'" :footer="null">
          <div v-if="modalLsVisible">
              <HistoricDetail ref="historicDetail" :data-id="dataId"></HistoricDetail>
          </div>
      </a-modal>
  </span>
</template>
<script>
import HistoricDetail from './HistoricDetail';
export default {
    name: 'ActHistoricDetailBtn',
    components: { HistoricDetail },
    props: {
        btnType: { type: String, default: 'link', required: false },
        /**/
        dataId: {
            type: String,
            default: '',
            required: true
        },
        text: {
            type: String,
            default: '审批历史',
            required: false
        }
    },
    data() {
        return {
            modalLsVisible: false
        };
    },
    created() {
    },
    watch: {
    },
    methods: {
        history() {
            if (!this.dataId) {
                this.$message.error('流程实例ID不存在');
                return;
            }
            this.modalLsVisible = true;
        }
    }
};
</script>
src/views/flowable/components/HistoricDetail.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,343 @@
<style lang="less">
</style>
<template>
  <div class="search">
    <a-card>
      <p slot="title">
        <span>流程图</span>
      </p>
      <div :style="{height: svgHeight}" v-if="svgShow">
        <bpmnModeler class="svg" ref="bpm" :xml="xmlData" :is-view="true"></bpmnModeler>
      </div>
    </a-card>
    <a-card style="margin-top:10px;">
      <p slot="title">
        <span>流程审批进度历史</span>
      </p>
      <a-row style="position:relative">
        <div class="block">
          <a-timeline>
            <a-timeline-item
              v-for="(item,index ) in flowRecordList"
              :key="index"
              :color="setColor(item.finishTime)"
            >
              <p style="font-weight: 700;">{{item.taskName}}
                <i v-if="!item.finishTime" style="color: orange">(待办中。。。)</i>
              </p>
              <a-card :body-style="{ padding: '10px' }">
                <label v-if="item.assigneeName&&item.finishTime" style="font-weight: normal;margin-right: 30px;">实际办理人: {{item.assigneeName}} <a-tag type="info" size="mini">{{item.deptName}}</a-tag></label>
                <label v-if="item.candidate" style="font-weight: normal;margin-right: 30px;">候选办理人: {{item.candidate}}</label>
                <label style="font-weight: normal">接收时间: </label><label style="color:#8a909c;font-weight: normal">{{item.createTime}}</label>
                <label v-if="item.finishTime" style="margin-left: 30px;font-weight: normal">办结时间: </label><label style="color:#8a909c;font-weight: normal">{{item.finishTime}}</label>
                <label v-if="item.duration" style="margin-left: 30px;font-weight: normal">耗时: </label><label style="color:#8a909c;font-weight: normal">{{item.duration}}</label>
                <p  v-if="item.comment">
<!--  1 æ­£å¸¸æ„è§  2 é€€å›žæ„è§ 3 é©³å›žæ„è§                -->
                  <a-tag color="green" v-if="item.comment.type === '1'">
                    <span v-if="item.comment.comment!='重新提交'">通过:</span>
                    {{item.comment.comment}}
                  </a-tag>
                  <a-tag color="orange" v-if="item.comment.type === '2'">退回:  {{item.comment.comment}}</a-tag>
                  <a-tag color="red" v-if="item.comment.type === '3'">驳回:  {{item.comment.comment}}</a-tag>
                </p>
              </a-card>
            </a-timeline-item>
          </a-timeline>
        </div>
      </a-row>
    </a-card>
  </div>
</template>
<script>
import {flowRecord} from "@views/flowable/api/finished";
import {getFlowViewerByDataId, readXmlByDataId} from "@views/flowable/api/definition";
import bpmnModeler from "workflow-bpmn-modeler";
export default {
    name: 'HistoricDetail',
  components: {
    bpmnModeler,
  },
    props: {
    /**/
        dataId: {
            type: String,
            default: '',
            required: true
        },
    },
    data() {
        return {
            taskList:[],
            flowRecordList: [], // æµç¨‹æµè½¬æ•°æ®
            formData:{},
            xmlData:'',
            type: 0,
            loading: false, // è¡¨å•加载状态
            loadingImg: false,
            data: [],
            id: '',
            imgUrl: '',
            backRoute: '',
          svgHeight:'',
          svgShow: true
        };
    },
    created() {
        this.init();
    },
    watch: {
      dataId: function(newval, oldName) {
            this.init();
        }
    },
    methods: {
        init() {
          this.getFlowRecordList()
          this.getModelDetail()
        },
      /** xml æ–‡ä»¶ */
      getModelDetail() {
        // å‘送请求,获取xml
        readXmlByDataId(this.dataId).then(res => {
          this.xmlData = res.result
          this.getFlowViewer()
          setTimeout(()=>{
            this.fitViewport()
          })
        })
      },
      // æµç¨‹è¿›è¡Œæƒ…况
      getFlowViewer() {
        getFlowViewerByDataId(this.dataId).then(res => {
          this.taskList = res.result || []
          this.fillColor();
        })
      },
      /** æµç¨‹æµè½¬è®°å½• */
      getFlowRecordList() {
        const params = {dataId: this.dataId}
        flowRecord(params).then(res => {
          // console.log(res)
          this.flowRecordList = res.result.flowList;
          this.finishOrder()
          // æµç¨‹è¿‡ç¨‹ä¸­ä¸å­˜åœ¨åˆå§‹åŒ–表单 ç›´æŽ¥è¯»å–的流程变量中存储的表单值
          if (res.result.formData) {
            this.formData = res.result.formData;
          }
        }).catch(res => {
          console.log(res)
        })
      },
        //整理顺序,把待办放最上面,并且只留一个(不然会签时会乱)
      finishOrder(){
        const list = []
        let noFinish = null
        for (const flow of this.flowRecordList) {
          if (flow.finishTime){
            // åŠžç»“çš„èŠ‚ç‚¹åŒæ—¶å–æœ‰å®žé™…åŠžç†äººçš„ï¼Œå› ä¸ºä¼šç­¾ä¼šå°†æ‰€æœ‰çš„å¤šå®žä¾‹éƒ½è¿”å›žï¼Œéœ€è¦è¿‡æ»¤
            if (flow.assigneeId){
              list.push(flow)
            }
          } else {
            noFinish = flow
          }
        }
        if (noFinish){
          const find = list.find(obj=>obj.taskDefKey == noFinish.taskDefKey);
          if (find){
            noFinish.taskName = '【会签中】'+noFinish.taskName
          }
          this.flowRecordList = [noFinish,...list];
        } else {
          this.flowRecordList = list;
        }
      },
        setColor(val) {
          if (val) {
            return "#2bc418";
          } else {
            return "#b3bdbb";
          }
        },
      fillColor() {
        const modeler = this.$refs.bpm.modeler;
        const canvas = modeler.get('canvas')
        modeler._definitions.rootElements[0].flowElements.forEach(n => {
          const completeTask = this.taskList.find(m => m.key === n.id)
          const todoTask = this.taskList.find(m => !m.completed)
          const endTask = this.taskList[this.taskList.length - 1]
          //用户任务
          if (n.$type === 'bpmn:UserTask') {
            if (completeTask) {
              canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo')
              canvas.addMarker(n.id, completeTask.back ? 'highlight-back' : 'highlight-noback')
              n.outgoing.forEach(nn => {
                const targetTask = this.taskList.find(m => m.key === nn.targetRef.id)
                if (targetTask) {
                  if (todoTask && completeTask.key === todoTask.key && !todoTask.completed){
                    canvas.addMarker(nn.id, todoTask.completed ? 'highlight' : 'highlight-todo')
                    canvas.addMarker(nn.targetRef.id, todoTask.completed ? 'highlight' : 'highlight-todo')
                  }else {
                    canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo')
                    canvas.addMarker(nn.targetRef.id, targetTask.completed ? 'highlight' : 'highlight-todo')
                  }
                }
              })
            }
          }
          // æŽ’他网关
          else if (n.$type === 'bpmn:ExclusiveGateway') {
            if (completeTask) {
              canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo')
              n.outgoing.forEach(nn => {
                const targetTask = this.taskList.find(m => m.key === nn.targetRef.id)
                if (targetTask) {
                  canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo')
                  canvas.addMarker(nn.targetRef.id, targetTask.completed ? 'highlight' : 'highlight-todo')
                }
              })
            }
          }
          // å¹¶è¡Œç½‘å…³
          else if (n.$type === 'bpmn:ParallelGateway') {
            if (completeTask) {
              canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo')
              n.outgoing.forEach(nn => {
                debugger
                const targetTask = this.taskList.find(m => m.key === nn.targetRef.id)
                if (targetTask) {
                  canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo')
                  canvas.addMarker(nn.targetRef.id, targetTask.completed ? 'highlight' : 'highlight-todo')
                }
              })
            }
          }
          else if (n.$type === 'bpmn:StartEvent') {
            n.outgoing.forEach(nn => {
              const completeTask = this.taskList.find(m => m.key === nn.targetRef.id)
              if (completeTask) {
                canvas.addMarker(nn.id, 'highlight')
                canvas.addMarker(n.id, 'highlight')
                return
              }
            })
          }
          else if (n.$type === 'bpmn:EndEvent') {
            if (endTask.key === n.id && endTask.completed) {
              canvas.addMarker(n.id, 'highlight')
              return
            }
          }
        })
      },
      // è®©å›¾èƒ½è‡ªé€‚应屏幕
      fitViewport() {
        const modeler = this.$refs.bpm.modeler;
        const canvas = modeler.get('canvas')
        // this.zoom = this.modeler.get('canvas').zoom('fit-viewport')
        if (this.svgHeight){
          document.querySelector('.canvas').style.height = this.svgHeight;
        }
        const bbox = document.querySelector('.flow-containers .viewport').getBBox()
        const currentViewbox = modeler.get('canvas').viewbox()
        if (!this.svgHeight){
          this.svgHeight = currentViewbox.inner.height + 'px'
          this.svgShow = false
          this.$nextTick(()=>{
            this.svgShow = true
          })
          // this.fitViewport()
          setTimeout(()=>{
            this.fitViewport()
          })
        }
        const elementMid = {
          x: bbox.x + bbox.width / 2 - 65,
          y: bbox.y + bbox.height / 2
        }
        // è°ƒèŠ‚ä½ç½®
        modeler.get('canvas').viewbox({
          x: elementMid.x - currentViewbox.width / 2 + 70,
          y: elementMid.y - currentViewbox.height/2,
          width: currentViewbox.width,
          height: currentViewbox.height
        })
        // è°ƒèŠ‚å¤§å°ç¼©æ”¾
        const zoom = currentViewbox.outer.width /(currentViewbox.inner.width+200)
        console.log('********',zoom,elementMid,currentViewbox.inner,currentViewbox.outer)
        // modeler.get('canvas').zoom(zoom)
      },
    }
};
</script>
<style lang="less">
   .highlight.djs-shape .djs-visual > :nth-child(1) {
     fill: green !important;
     stroke: green !important;
     fill-opacity: 0.2 !important;
   }
   .highlight.djs-shape .djs-visual > :nth-child(2) {
     fill: green !important;
   }
   .highlight.djs-shape .djs-visual > path {
     fill: green !important;
     fill-opacity: 0.2 !important;
     stroke: green !important;
   }
   .highlight.djs-connection > .djs-visual > path {
     stroke: green !important;
   }
   // .djs-connection > .djs-visual > path {
   //   stroke: orange !important;
   //   stroke-dasharray: 4px !important;
   //   fill-opacity: 0.2 !important;
   // }
   // .djs-shape .djs-visual > :nth-child(1) {
   //   fill: orange !important;
   //   stroke: orange !important;
   //   stroke-dasharray: 4px !important;
   //   fill-opacity: 0.2 !important;
   // }
   .highlight-todo.djs-connection > .djs-visual > path {
     stroke: orange !important;
     stroke-dasharray: 4px !important;
     fill-opacity: 0.2 !important;
   }
   .highlight-todo.djs-shape .djs-visual > :nth-child(1) {
     fill: orange !important;
     stroke: orange !important;
     stroke-dasharray: 4px !important;
     fill-opacity: 0.2 !important;
   }
   .highlight-back.djs-connection > .djs-visual > path {
     stroke: red !important;
     stroke-dasharray: 4px !important;
     fill-opacity: 0.2 !important;
   }
   .highlight-back.djs-shape .djs-visual > :nth-child(1) {
     fill: red !important;
     stroke: red !important;
     stroke-dasharray: 4px !important;
     fill-opacity: 0.2 !important;
   }
   .overlays-div {
     font-size: 10px;
     color: red;
     width: 100px;
     top: -20px !important;
   }
</style>
src/views/flowable/mixin/FlowableMixin.js
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,68 @@
import Vue from "vue";
import {USER_INFO} from "@/store/mutation-types";
/**
 *
 */
export const FlowableMixin = {
  data(){
    return {
      loginUser:{}
    }
  },
  created() {
    this.loginUser = Vue.ls.get(USER_INFO);
  },
  methods:{
    // å½“前数据是否可提交
    isCanApply(row){
      // æ²¡æœ‰æµç¨‹å®žä¾‹çš„即可提交
      return !Boolean(row.processInstanceId);
    },
    // å½“前数据是否可撤回
    isCanRecall(row){
      // è¿›è¡Œä¸­çš„æµç¨‹&&当前节点不是开始节点&&状态不是通过
      return Boolean(row.processInstanceId)&&row.taskNameId!=='start'&&row.actStatus!=='审批通过';
    },
    // é‡æ–°æäº¤æŒ‰é’®
    isCanReApply(row){
      return row.taskNameId=='start'&&this.isTodoUsers(row);
    },
    // é€šè¿‡æŒ‰é’®
    isCanPass(row){
      return row.taskNameId!=='start'&& this.isTodoUsers(row);
    },
    // é©³å›žé€€å›žæŒ‰é’®
    isCanBacke(row){
      // ä¸æ˜¯start节点&&在可操作人员列表
      return row.taskNameId!=='start'&&this.isTodoUsers(row);
    },
    // æŸ¥çœ‹å®¡æ‰¹åŽ†å²æŒ‰é’®
    isCanHistoric(row){
      // æœ‰å®žä¾‹id就能查看
      return Boolean(row.processInstanceId);
    },
    // å½“前登录人是否在处理人列表
    isTodoUsers(row){
      const todoUsers = row.todoUsers;
      if (todoUsers&&todoUsers.length){
        const parse = JSON.parse(todoUsers)||[];
        return parse.includes(this.loginUser.username);
      }else {
        return false;
      }
    },
    // å½“前登录人是否是处理过的人列表
    isDoneUsers(row){
      const doneUsers = row.doneUsers;
      if (doneUsers&&doneUsers.length){
        const parse = JSON.parse(doneUsers)||[];
        return parse.includes(this.loginUser.username);
      }else {
        return false;
      }
    },
  }
}
src/views/flowable/modeler/modelerDesign.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,402 @@
<template>
  <div>
<!--  ==================流程定义列表===============  -->
    <a-card v-if="!xmlFrame.open||xmlView">
    <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="68px">
      <el-form-item label="流程名称" prop="name">
        <el-input
          v-model="queryParams.name"
          placeholder="请输入名称"
          clearable
          size="small"
          @keyup.enter.native="handleQuery"
        />
      </el-form-item>
      <el-form-item label="流程分类" prop="category">
        <el-select @change="handleQuery" v-model="queryParams.category" placeholder="请选择流程分类" clearable prop="category">
          <el-option label="请选择" value="" />
          <el-option v-for="category in categorys" :key="category.id" :label="category.name" :value="category.id" />
        </el-select>
      </el-form-item>
      <el-form-item label="激活" prop="active">
        <el-switch
          v-model="queryParams.active"
          active-color="#13ce66"
          inactive-color="#ff4949"
          @change="handleQuery"
        >
        </el-switch>
      </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-item style="float:right">
        <el-button
          type="primary"
          icon="el-icon-plus"
          size="mini"
          @click="handleLoadXml"
        >新增流程定义</el-button>
      </el-form-item>
    </el-form>
      <el-table
        v-loading="loading" fit
        :data="definitionList"
        row-key="id"
        border
        lazy
        :load="load"
        :tree-props="{children: 'children', hasChildren: 'hasChildren'}">
      <el-table-column label="流程定义id" align="center" prop="id" />
      <el-table-column label="流程标识Key" align="center" prop="key"  />
      <el-table-column label="流程分类" align="center" >
        <template slot-scope="scope">
            <span>{{ getCategoryName(scope.row.category) }}</span>
        </template>
      </el-table-column>
      <el-table-column label="流程名称" align="center" :show-overflow-tooltip="true">
        <template slot-scope="scope">
          <el-button type="text" @click="handleReadImage(scope.row.deploymentId)">
            <span>{{ scope.row.name }}</span>
          </el-button>
        </template>
      </el-table-column>
      <el-table-column label="流程版本" align="center">
        <template slot-scope="scope">
          <el-tag size="medium" >v{{ scope.row.version }}</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="状态" align="center">
        <template slot-scope="scope">
          <el-tag type="success" v-if="scope.row.suspensionState === 1">激活</el-tag>
          <el-tag type="warning" v-if="scope.row.suspensionState === 2">挂起</el-tag>
        </template>
      </el-table-column>
      <el-table-column label="部署时间" align="center" prop="deploymentTime" width="180"/>
      <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
        <template slot-scope="scope">
          <el-dropdown>
            <span class="el-dropdown-link">
              æ›´å¤šæ“ä½œ<i class="el-icon-arrow-down el-icon--right"></i>
            </span>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item icon="el-icon-edit-outline" @click.native="handleLoadXml(scope.row)">
                ç¼–辑
              </el-dropdown-item>
<!--              <el-dropdown-item icon="el-icon-connection" @click.native="handleAddForm(scope.row)" v-if="scope.row.formId == null">
                é…ç½®è¡¨å•
              </el-dropdown-item>-->
              <el-dropdown-item icon="el-icon-video-pause" @click.native="handleUpdateSuspensionState(scope.row)" v-if="scope.row.suspensionState === 1">
                æŒ‚èµ·
              </el-dropdown-item>
              <el-dropdown-item icon="el-icon-video-play" @click.native="handleUpdateSuspensionState(scope.row)" v-if="scope.row.suspensionState === 2">
                æ¿€æ´»
              </el-dropdown-item>
              <el-dropdown-item icon="el-icon-delete" @click.native="handleDelete(scope.row)" >
                åˆ é™¤
              </el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      v-show="total>0"
      :total="total"
      :current-page.sync="queryParams.pageNum"
      :page-size.sync="queryParams.pageSize"
      @size-change="getList"
      @current-change="getList"
    />
    </a-card>
      <!-- æµç¨‹å›¾ -->
    <a-card v-if="xmlFrame.open&&!xmlView" :title="xmlFrame.title">
      <a slot="extra" href="#" @click="()=>{xmlFrame.open=false}">返回</a>
      <bpmn-modeler
        v-if="xmlShow"
        ref="refNode"
        :xml="xmlData"
        :users="users"
        :groups="groups"
        :categorys="categorys"
        :is-view="xmlView"
        @save="save"
      />
    </a-card>
<!--  å¼¹çª—预览  -->
      <a-modal :title="xmlFrame.title" :visible.sync="xmlView&&xmlFrame.open" :width="xmlFrame.width"
        :footer="null" closable @cancel="()=>{xmlView=false,xmlFrame.open=false}"
      >
        <bpmn-modeler
          v-if="xmlShow"
          ref="refNode"
          :xml="xmlData"
          :users="users"
          :groups="groups"
          :categorys="categorys"
          :is-view="xmlView"
          @save="save"
        />
      </a-modal>
  </div>
</template>
<script>
import bpmnModeler from "workflow-bpmn-modeler";
import 'element-ui/lib/theme-chalk/index.css';
import 'ant-design-vue/dist/antd.css';
import {
  categoryList,
  delDeployment,
  listDefinition,
  readXml,
  roleList,
  saveXml,
  updateState,
  userList
} from "@views/flowable/api/definition";
export default {
  components: {
    bpmnModeler,
  },
  data() {
    return {
      /*===================设计器属性======================*/
      users: [],
      groups: [],
      categorys: [],
      /*=================页面属性===================*/
      loading: true,
      // æ€»æ¡æ•°
      total: 0,
      // æµç¨‹å®šä¹‰è¡¨æ ¼æ•°æ®
      definitionList: [],
      allDefinitionList: [],
      // æŸ¥è¯¢å‚æ•°
      queryParams: {
        pageNum: 1,
        pageSize: 10,
        name: null,
        category: null,
        key: null,
        tenantId: null,
        deployTime: null,
        derivedFrom: null,
        derivedFromRoot: null,
        parentDeploymentId: null,
        engineVersion: null
      },
      xmlFrame:{
        width:'70%',
        title:'流程图',
        open: false,
        src: "",
      },
      // xml
      xmlData:"",
      xmlShow: true,
      xmlView: false,
    };
  },
  created() {
    this.initUserAndRole();
    this.getList();
  },
  methods: {
    /*===============设计器===============*/
    initUserAndRole(){
      userList({}).then(res=>{
        this.users = res.result||[]
        this.users.map(o=>{
          o.id = o.username
          o.name = o.realname
        })
      })
      roleList({}).then(res=>{
        this.groups = res.result||[]
        this.groups.map(o=>{
          o.name = o.roleName
        })
      })
      categoryList({}).then(res=>{
        this.categorys = res.result||[]
      })
    },
    getModelDetail(deployId) {
      // å‘送请求,获取xml
      readXml(deployId).then(res =>{
        this.xmlData = res.result;
      })
    },
    getCategoryName(category){
      let find = this.categorys.find(o=>o.id==category);
      if (find){
        return find.name
      }
      return ''
    },
    /*保存流程定义*/
    save(data) {
      console.log(data);  // { process: {...}, xml: '...', svg: '...' }
      const params = {
        name: data.process.name,
        category: data.process.category,
        xml: data.xml
      }
      saveXml(params).then(res => {
        this.$message.success(res.message)
        // å…³é—­å½“前标签页并返回上个页面
        this.getList()
        this.xmlFrame.open = false
      })
    },
    /*================页面===============*/
    handleQuery() {
      this.queryParams.pageNum = 1;
      this.queryParams.suspensionState = this.queryParams.active?1:0;
      this.getList();
    },
    /** æŸ¥è¯¢æµç¨‹å®šä¹‰åˆ—表 */
    getList() {
      this.loading = true;
      // æœ€æ–°ç‰ˆæœ¬
      const param1 = Object.assign({
        isLastVersion:1,
      },this.queryParams)
      listDefinition(param1).then(response => {
        this.definitionList = response.result.records;
        this.total = response.result.total;
        this.loading = false;
        for (const definition of this.definitionList) {
          definition.hasChildren = true
        }
      });
      // // æ‰€æœ‰
      // const param2 = Object.assign({
      //   isLastVersion:0
      // },this.queryParams,{
      //   pageSize: 9999,
      //   pageNum:1
      // })
      // listDefinition(param2).then(response => {
      //   console.log(response)
      //   this.allDefinitionList = response.result.records;
      // });
    },
    /** é‡ç½®æŒ‰é’®æ“ä½œ */
    resetQuery() {
      this.resetForm("queryForm");
      this.handleQuery();
    },
    resetForm(formName) {
      this.$refs[formName].resetFields()
    },
    /** æ‰“开流程设计弹窗页面 */
    handleLoadXml(row){
      if (row&&row.deploymentId){
        console.log(row.deploymentId)
        this.handleReadImage(row.deploymentId)
        this.xmlView = false
        this.xmlFrame.title = "编辑流程图";
      } else {
        //新增
        this.xmlData = ''
        this.xmlView = false
        this.xmlFrame.open = true
        this.xmlFrame.title = '新增流程'
        this.xmlShow = false
        this.$nextTick(()=>{
          this.xmlShow = true
        })
      }
      this.xmlFrame.width = '90%'
    },
    /** æµç¨‹å›¾æŸ¥çœ‹ */
    handleReadImage(deploymentId){
      this.xmlFrame.title = "流程图";
      this.xmlFrame.open = true;
      this.xmlFrame.width = '70%';
      // this.xmlFrame.src = process.env.VUE_APP_BASE_API + "/flowable/definition/xmlFrame/" + deploymentId;
      // å‘送请求,获取xml
      this.xmlView = true
      readXml(deploymentId).then(res =>{
        if (res.success){
          this.xmlData = res.result
          /*this.xmlShow = false
          this.$nextTick(()=>{
            this.xmlShow = true
          })*/
        } else {
          this.$message.error("获取流程图失败!")
        }
      })
    },
    // æ‰“开业务表单
    handleForm() {
    },
    // é…ç½®ä¸šåŠ¡è¡¨å•
    handleAddForm(row) {
    },
    /** æŒ‚èµ·/激活流程 */
    handleUpdateSuspensionState(row){
      let state = 1;
      if (row.suspensionState === 1) {
        state = 2
      }
      const params = {
        deployId: row.deploymentId,
        state: state
      }
      updateState(params).then(res => {
        this.$message.success(res.message);
        this.getList();
      });
    },
    /** åˆ é™¤æŒ‰é’®æ“ä½œ */
    handleDelete(row) {
      // const ids = row.deploymentId || this.ids;
      const params = {
        deployId: row.deploymentId
      }
      this.$confirm({
        title:"警告",
        content:'是否确认删除流程定义编号为"' + params.deployId + '"的数据项?',
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
        onOk:()=>{
          delDeployment(params).then(res=>{
            this.getList();
            if (res.success){
              this.$message.success('删除成功');
            } else {
              this.$message.success('删除失败');
            }
          })
        }
      })
    },
    load(tree, treeNode, resolve) {
      const key = tree.key;
      const childrens = []
      for (const one of this.allDefinitionList) {
        if (one.key==key&&one.id!=tree.id){
          childrens.push(one)
        }
      }
      console.log(tree, treeNode,this.allDefinitionList,childrens)
      resolve(childrens)
    }
  },
  computed: {
    getContainer() {
      return document.querySelector('#app')
    }
  }
};
</script>
src/views/flowable/workflow/FlowCompleted.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,182 @@
<!--
 Description: å·¥ä½œæµ-我的已办 List
 Author: ä½œè€… liuyh
 Date:   2025-02-27
-->
<template>
  <a-card :bordered="false">
    <!-- æŸ¥è¯¢åŒºåŸŸ -->
    <div class="table-page-search-wrapper">
      <a-form layout="inline" @keyup.enter.native="searchQuery">
        <a-row :gutter="24">
          <a-col :xl="6" :lg="7" :md="8" :sm="24">
            <a-form-item label="流程分类">
              <j-dict-select-tag placeholder="请选择流程分类" v-model="queryParam.category"
                                 dictCode="flow_type"></j-dict-select-tag>
            </a-form-item>
          </a-col>
          <a-col :xl="10" :lg="11" :md="12" :sm="24">
            <a-form-item label="操作时间">
              <j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始时间"
                      class="query-group-cust"
                      v-model="queryParam.startTime"></j-date>
              <span class="query-group-split-cust"></span>
              <j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择结束时间"
                      class="query-group-cust"
                      v-model="queryParam.endTime"></j-date>
            </a-form-item>
          </a-col>
          <a-col :xl="6" :lg="7" :md="8" :sm="24">
            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
              <a-button @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
            </span>
          </a-col>
        </a-row>
      </a-form>
    </div>
    <!-- æŸ¥è¯¢åŒºåŸŸ-END -->
    <!-- table区域-begin -->
    <div>
      <a-table
        ref="table"
        size="middle"
        :scroll="{x:true}"
        bordered
        rowKey="id"
        :columns="columns"
        :dataSource="dataSource"
        :pagination="ipagination"
        :loading="loading"
        class="j-table-force-nowrap"
        @change="handleTableChange">
        <span slot="action" slot-scope="text, record">
            <a @click="handelDetial(record,text)">详情</a>
        </span>
      </a-table>
    </div>
  </a-card>
</template>
<script>
import '@/assets/less/TableExpand.less'
import { mixinDevice } from '@/utils/mixin'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import JDictSelectTag from '@/components/dict/JDictSelectTag.vue'
export default {
  name: 'NcDeviceCharactersList',
  mixins: [JeecgListMixin, mixinDevice],
  components: {
    JDictSelectTag
  },
  data() {
    return {
      description: '工作流-已办',
      // è¡¨å¤´
      columns: [
        {
          title: '序号',
          dataIndex: '',
          key: 'rowIndex',
          width: 200,
          align: 'center',
          customRender: function(t, r, index) {
            return parseInt(index) + 1
          }
        },
        {
          title: '流程分类',
          align: 'center',
          dataIndex: 'category_dictText',
          width: 200
        },
        {
          title: '流程名称',
          align: 'center',
          dataIndex: 'procDefName',
          width: 200
        },
        {
          title: '流程业务简要描述',
          align: 'center',
          dataIndex: 'description',
          width: 300
        },
        {
          title: '流程发起人名称',
          align: 'center',
          dataIndex: 'startUserName',
          width: 250
        },
        {
          title: '任务名称',
          align: 'center',
          dataIndex: 'taskName',
          width: 250
        },
        {
          title: '操作时间',
          align: 'center',
          dataIndex: 'finishTime',
          width: 300
        },
        {
          title: '操作',
          dataIndex: 'action',
          scopedSlots: { customRender: 'action' },
          align: 'center',
          width: 200,
          fixed: 'right'
        }
      ],
      url: {
        list: '/assign/flow/finishedList'
      },
      dictOptions: {},
      selectShenpiData: {},
      selectDispatchFileXqData: {},
      selectWeekMaintenanceData: {},
      selectInspectionOrderXqData: {},
      selectRepairOrderData: {},
      selectOutBoundOrderData: {},
      selectLossBoundOrderData: {},
      selectStocktakingBoundOrderData: {}
    }
  },
  created() {
  },
  computed: {
    importExcelUrl: function() {
      return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`
    }
  },
  methods: {
    handelDetial(item, index) {
      console.log('点击了详情')
      console.log('item----->', item)
      console.log('index----->', index)
      let approcesstype = this.splitAprocessType(item.category)
      console.log('approcesstype--->', approcesstype)
      switch (approcesstype) {
        default:
          alert('没找到该流程')
      }
    },
    splitAprocessType(title) {
      let parts = title.split(':') // æ³¨æ„å†’号是全角字符,使用对应的字进行分割
      let result = parts[0]
      return result
    },
  }
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
src/views/flowable/workflow/FlowLedger.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,209 @@
<!--
 Description: å·¥ä½œæµ-总台账 List
 Author: ä½œè€… liuyh
 Date:   2025-02-27
-->
<template>
  <a-card :bordered="false">
    <!-- æŸ¥è¯¢åŒºåŸŸ -->
    <div class="table-page-search-wrapper">
      <a-form layout="inline" @keyup.enter.native="searchQuery">
        <a-row :gutter="24">
          <a-col :xl="6" :lg="7" :md="8" :sm="24">
            <a-form-item label="流程分类">
              <j-dict-select-tag placeholder="请选择流程分类" v-model="queryParam.category"
                                 dictCode="flow_type"></j-dict-select-tag>
            </a-form-item>
          </a-col>
          <a-col :xl="6" :lg="7" :md="8" :sm="24">
            <a-form-item label="流程名称">
              <a-input placeholder="请输入流程名称" v-model="queryParam.flowName"></a-input>
            </a-form-item>
          </a-col>
          <a-col :xl="6" :lg="7" :md="8" :sm="24">
            <a-form-item label="简要描述">
              <a-input placeholder="请输入简要描述" v-model="queryParam.title"></a-input>
            </a-form-item>
          </a-col>
          <a-col :xl="10" :lg="11" :md="12" :sm="24">
            <a-form-item label="操作时间">
              <j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择开始时间" class="query-group-cust"
                      v-model="queryParam.startTime"></j-date>
              <span class="query-group-split-cust"></span>
              <j-date :show-time="true" date-format="YYYY-MM-DD HH:mm:ss" placeholder="请选择结束时间" class="query-group-cust"
                      v-model="queryParam.endTime"></j-date>
            </a-form-item>
          </a-col>
          <a-col :xl="6" :lg="7" :md="8" :sm="24">
            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
              <a-button @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
            </span>
          </a-col>
        </a-row>
      </a-form>
    </div>
    <!-- æŸ¥è¯¢åŒºåŸŸ-END -->
    <!-- æ“ä½œæŒ‰é’®åŒºåŸŸ -->
    <!-- table区域-begin -->
    <div>
      <a-table
        ref="table"
        size="middle"
        :scroll="{x:true}"
        bordered
        rowKey="id"
        :columns="columns"
        :dataSource="dataSource"
        :pagination="ipagination"
        :loading="loading"
        class="j-table-force-nowrap"
        @change="handleTableChange">
        <span slot="action" slot-scope="text, record">
            <a @click="handelDetail(record,text)">详情</a>
        </span>
      </a-table>
    </div>
  </a-card>
</template>
<script>
import '@/assets/less/TableExpand.less'
import { mixinDevice } from '@/utils/mixin'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import JDictSelectTag from '@/components/dict/JDictSelectTag.vue'
  export default {
    name: 'FlowLedger',
    mixins: [JeecgListMixin, mixinDevice],
    components: {
      JDictSelectTag
    },
    data() {
      return {
        description: '流程管理',
        // è¡¨å¤´
        columns: [
          {
            title: '序号',
            dataIndex: '',
            key: 'rowIndex',
            align: 'center',
            customRender: function(t, r, index) {
              return parseInt(index) + 1
            }
          },
          {
            title: '流程分类',
            align: 'center',
            dataIndex: 'category_dictText',
            width: 200
          },
          {
            title: '流程名称',
            align: 'center',
            dataIndex: 'flowName'
          },
          {
            title: '流程业务简要描述',
            align: 'center',
            dataIndex: 'description',
          },
          {
            title: '申请人',
            align: 'center',
            dataIndex: 'proposer_dictText'
          },
          {
            title: '前驱节点',
            align: 'center',
            dataIndex: 'preNode'
          },
          {
            title: '当前节点',
            align: 'center',
            dataIndex: 'taskName'
          },
          {
            title: '流程开始时间',
            align: 'center',
            dataIndex: 'startTime'
          },
          {
            title: '流程结束时间',
            align: 'center',
            dataIndex: 'endTime'
          },
          {
            title: '处理时长',
            align: 'center',
            dataIndex: 'duration'
          },
          {
            title: '当前任务人',
            align: 'center',
            dataIndex: 'todoUsers_dictText'
          },
          {
            title: '处理过的人',
            align: 'center',
            dataIndex: 'doneUsers_dictText'
          },
          {
            title: '操作',
            dataIndex: 'action',
            scopedSlots: { customRender: 'action' },
            align: 'center',
            width: 200,
            fixed: 'right'
          }
        ],
        url: {
          list: '/assign/flow/list'
        },
        dictOptions: {},
        selectShenpiData: {},
        selectDispatchFileXqData: {},
        selectInspectionOrderXqData: {}
      }
    },
    created() {
    },
    computed: {
      importExcelUrl: function() {
        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`
      }
    },
    methods: {
      handelDetail(item, index) {
        console.log('点击了详情')
        console.log('item----->', item)
        console.log('index----->', index)
        let approcesstype = this.splitAprocessType(item.category)
        console.log('approcesstype--->', approcesstype)
        switch (approcesstype) {
          case 'drApproval':
            item.description=item.description
            this.handDrDetial(item)
            break
          default:
            alert('没找到该流程')
        }
      },
      splitAprocessType(title) {
        let parts = title.split(':') // æ³¨æ„å†’号是全角字符,使用对应的字进行分割
        let result = parts[0]
        return result
      },
    }
  }
</script>
<style scoped>
  @import '~@assets/less/common.less';
</style>
src/views/flowable/workflow/FlowTodo.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,424 @@
<!--
 Description: å·¥ä½œæµ-我的待办 List
 Author: ä½œè€… liuyh
 Date:   2025-02-27
-->
<template>
  <a-card :bordered='false'>
    <!-- æŸ¥è¯¢åŒºåŸŸ -->
    <div class='table-page-search-wrapper'>
      <a-form
        layout='inline'
        @keyup.enter.native='searchQuery'
      >
        <a-row :gutter='24'>
          <a-col
            :lg='6'
            :md='8'
            :sm='24'
            :xl='4'
          >
            <a-form-item label='流程分类'>
              <j-dict-select-tag
                v-model='queryParam.category'
                dictCode='flow_type'
                placeholder='请选择流程分类'
              ></j-dict-select-tag>
            </a-form-item>
          </a-col>
          <!--<a-col :xl="4" :lg="6" :md="8" :sm="24">-->
          <!--<a-form-item label="流程名称">-->
          <!--<a-input placeholder="请输入流程名称" v-model="queryParam.flowName"></a-input>-->
          <!--</a-form-item>-->
          <!--</a-col>-->
          <a-col
            :lg='6'
            :md='8'
            :sm='24'
            :xl='4'
          >
            <a-form-item label='当前节点'>
              <a-input
                v-model='queryParam.name'
                placeholder='请输入当前节点精确查询'
              ></a-input>
            </a-form-item>
          </a-col>
          <a-col
            :lg='6'
            :md='8'
            :sm='24'
            :xl='4'
          >
            <a-form-item label='简要描述'>
              <a-input
                v-model='queryParam.title'
                placeholder='请输入简要描述'
              ></a-input>
            </a-form-item>
          </a-col>
          <template v-if='toggleSearchStatus'>
            <a-col
              :lg='8'
              :md='12'
              :sm='24'
              :xl='8'
            >
              <a-form-item label='任务时间范围'>
                <j-date
                  v-model='queryParam.startTime'
                  :show-time='false'
                  class='query-group-cust'
                  date-format='YYYY-MM-DD HH:mm:ss'
                  placeholder='请选择开始时间'
                ></j-date>
                <span class='query-group-split-cust'></span>
                <j-date
                  v-model='queryParam.endTime'
                  :show-time='false'
                  class='query-group-cust'
                  date-format='YYYY-MM-DD HH:mm:ss'
                  placeholder='请选择结束时间'
                ></j-date>
              </a-form-item>
            </a-col>
          </template>
          <a-col
            :lg='6'
            :md='8'
            :sm='24'
            :xl='4'
          >
            <span
              class='table-page-search-submitButtons'
              style='float: left;overflow: hidden;'
            >
              <a-button
                icon='search'
                type='primary'
                @click='searchQuery'
              >查询</a-button>
              <a-button
                icon='reload'
                style='margin-left: 8px'
                @click='searchReset'
              >重置</a-button>
              <a
                style='margin-left: 8px'
                @click='handleToggleSearch'
              >
                {{ toggleSearchStatus ? '收起' : '展开' }}
                <a-icon :type="toggleSearchStatus ? 'up' : 'down'" />
              </a>
            </span>
          </a-col>
        </a-row>
      </a-form>
    </div>
    <!-- æŸ¥è¯¢åŒºåŸŸ-END -->
    <!-- æ“ä½œæŒ‰é’®åŒºåŸŸ -->
    <div class='table-operator'>
      <a-dropdown v-if='selectedRowKeys.length > 0 '>
        <a-menu slot='overlay'>
          <a-menu-item
            key='1'
            @click='batchHandle'
          >
            <a-icon type='delete' />
            æ‰¹é‡å¤„理
          </a-menu-item>
        </a-menu>
        <a-button style='margin-left: 8px'> æ‰¹é‡æ“ä½œ
          <a-icon type='down' />
        </a-button>
      </a-dropdown>
    </div>
    <!-- table区域-begin -->
    <div>
      <div
        class='ant-alert ant-alert-info'
        style='margin-bottom: 16px;'
      >
        <i class='anticon anticon-info-circle ant-alert-icon'></i>已选择&nbsp;<a style='font-weight: 600'>{{
          selectedRowKeys.length }}</a>项&nbsp;&nbsp;
        <a
          style='margin-left: 24px'
          @click='onClearSelected'
        >清空</a>
      </div>
      <a-table
        ref='table'
        :columns='columns'
        :dataSource='dataSource'
        :loading='loading'
        :pagination='ipagination'
        :rowSelection='{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}'
        :scroll='{x:getTableColumnsTotalWidth,y:465}'
        bordered
        rowKey='id'
        size='middle'
        @change='handleTableChange'
      >
        <span
          slot='action'
          slot-scope='text, record'
        >
          <a @click='handelDetail(record,text)'>执行/审批</a>
        </span>
      </a-table>
    </div>
    <AssignFileStreamHandle
      ref='modalFormApproval'
      :selectShenpiData='selectShenpiData'
      @searchReset='searchReset'
    ></AssignFileStreamHandle>
    <DispatchFileHandle
      ref='modalFormDispatchFileXq'
      :selectShenpiData='selectDispatchFileXqData'
      @searchReset='searchReset'
    ></DispatchFileHandle>
    <DispatchFileBachHandleStyle
      ref='modalFormDispatchFileBatch'
      @ok='modalFormOk'
      @searchReset='searchReset'
    ></DispatchFileBachHandleStyle>
  </a-card>
</template>
<script>
import '@/assets/less/TableExpand.less'
import { mixinDevice } from '@/utils/mixin'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import JDictSelectTag from '@/components/dict/JDictSelectTag.vue'
import { getAction } from '@api/manage'
import AssignFileStreamHandle from '@views/flowable/workflow/assignFileStream/AssignFileStreamHandle.vue'
import DispatchFileHandle from '@views/flowable/workflow/dispatchFile/DispatchFileHandle.vue'
import DispatchFileBachHandleStyle from '@views/flowable/workflow/dispatchFile/DispatchFileBachHandleStyle#Drawer.vue'
export default {
  name: 'NcDeviceCharactersList',
  mixins: [JeecgListMixin, mixinDevice],
  components: {
    AssignFileStreamHandle,
    DispatchFileHandle,
    DispatchFileBachHandleStyle,
    JDictSelectTag
  },
  data() {
    return {
      description: '工作流-我的待办',
      // è¡¨å¤´
      columns: [
        {
          title: '序号',
          dataIndex: '',
          key: 'rowIndex',
          width: 60,
          align: 'center',
          customRender: function (t, r, index) {
            return parseInt(index) + 1
          }
        },
        {
          title: '流程分类',
          align: 'center',
          dataIndex: 'category_dictText',
          width: 100
        },
        {
          title: '流程名称',
          align: 'center',
          dataIndex: 'flowName',
          width: 200
        },
        {
          title: '流程业务简要描述',
          align: 'center',
          dataIndex: 'description',
          width: 350,
          ellipsis: true
        },
        {
          title: '上一步处理人',
          align: 'center',
          dataIndex: 'preNodeAssignee_dictText',
          width: 150
        },
        {
          title: '前驱节点',
          align: 'center',
          dataIndex: 'preNode',
          width: 200
        },
        {
          title: '当前节点',
          align: 'center',
          dataIndex: 'name',
          width: 200
        },
        {
          title: '当前节点开始时间',
          align: 'center',
          dataIndex: 'createTime',
          width: 200
        },
        {
          title: '操作',
          dataIndex: 'action',
          scopedSlots: { customRender: 'action' },
          align: 'center',
          width: 150,
          fixed: 'right'
        }
      ],
      url: {
        list: '/assign/flow/toTaskBySelf',
        isSameNode: '/assign/flow/isSameNode'
      },
      dictOptions: {},
      selectShenpiData: {},
      selectDispatchFileXqData: {},
      selectInspectionOrderData: {},
      selectWeekMaintenanceData: {},
      selectSecondMaintenanceData: {},
      selectThirdMaintenanceData: {},
      selectBachData: {},
      selectRepairOrderData: {},
      selectOutBoundOrderData: {},
      selectLossBoundOrderData: {},
      selectStocktakingBoundOrderData: {},
      selectInboundOrderData: {},
      selectSparePartApplyData: {},
      selectGuideCardData:{},
      //业务信息ID
      dataId: undefined
    }
  },
  created() {
  },
  computed: {
    importExcelUrl: function () {
      return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`
    },
    getTableColumnsTotalWidth() {
      return this.columns.reduce((total, item) => total + item.width, 0)
    }
  },
  methods: {
    loadData(arg) {
      if (!this.url.list) {
        this.$message.error('请设置url.list属性!')
        return
      }
      //加载数据 è‹¥ä¼ å…¥å‚æ•°1则加载第一页的内容
      if (arg === 1) {
        this.ipagination.current = 1
      }
      var params = this.getQueryParams()//查询条件
      if (!params) {
        return false
      }
      this.loading = true
      getAction(this.url.list, params).then((res) => {
        if (res.success) {
          // console.log(res)
          //update-begin---author:zhangyafei    Date:20201118  for:适配不分页的数据列表------------
          this.dataSource = res.result.records || res.result
          if (res.result.total) {
            this.ipagination.total = res.result.total
          } else {
            this.ipagination.total = 0
          }
          if (this.selectedRowKeys.length > 0) this.selectedRowKeys = this.selectionRows = []
          //update-end---author:zhangyafei    Date:20201118  for:适配不分页的数据列表------------
        } else {
          this.$message.warning(res.message)
        }
      }).finally(() => {
        this.loading = false
      })
    },
    handelDetail(item, index) {
      console.log('点击了详情')
      console.log('item----->', item)
      console.log('index----->', index)
      let processType = this.splitAprocessType(item.category)
      console.log('processType--->', processType)
      switch (processType) {
        case 'drApproval':
          this.handDrDetial(item)
          break
        case 'ggApproval':
          this.handDispatchFileDetial(item)
          break
        default:
          alert('没找到该流程')
      }
    },
    batchHandle() {
      const categorySet = new Set(this.selectionRows.map(item => item.category))
      const nameSet = new Set(this.selectionRows.map(item => item.name))
      if (categorySet.size !== 1 || nameSet.size !== 1) {
        this.$notification.info({
          message: '消息',
          description: '请选择同一流程分类下的同一当前节点'
        })
        return
      }
      if (categorySet.has('eam_repair')) {
        this.$notification.info({
          message: '消息',
          description: '设备维修流程无法批量处理'
        })
        return
      }
      if (categorySet.has('sbdjApproval')) {
        this.$refs.inspectionOrderBatchHandleRef.visible = true
        this.$refs.inspectionOrderBatchHandleRef.title = this.selectionRows[0].name
        this.$refs.inspectionOrderBatchHandleRef.getAllApproveData(this.selectionRows[0])
        this.$refs.inspectionOrderBatchHandleRef.getBasicInformation(this.selectionRows[0])
      } else if (categorySet.has('WEEK_MAINTENANCE')) {
        this.$refs.weenMaintenanceBatchApprovalModalRef.handleDetail(this.selectionRows[0])
        this.$refs.weenMaintenanceBatchApprovalModalRef.title = this.selectionRows[0].name
      }
    },
    splitAprocessType(title) {
      let parts = title.split(':') // æ³¨æ„å†’号是全角字符,使用对应的字进行分割
      let result = parts[0]
      return result
    },
    handDrDetial(item) {
      this.selectShenpiData = item
      this.$refs.modalFormApproval.clearTableSource()
      this.$refs.modalFormApproval.getAllApproveData(item)
    },
    handDispatchFileDetial(item) {
      console.log('item----->', item)
      this.selectDispatchFileXqData = item
      this.$refs.modalFormDispatchFileXq.clearTableSource()
      this.$refs.modalFormDispatchFileXq.getAllApproveData(item)
    },
  }
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
src/views/flowable/workflow/assignFileStream/AssignFileStreamHandle.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,434 @@
<!--
 Description: å·¥ä½œæµ-指派设备处理页面 List
 Author: ä½œè€… liuyh
 Date:   2025-02-27
-->
<template>
  <a-modal
    :title="title"
    :width="width"
    :visible="visible"
    :footer="null"
    @cancel="handCancel"
  >
    <a-card :bordered="false">
      <div>
        <b>{{ selectShenpiData.description }}</b>
        <br>
        <br>
        <a-tag color="blue">
          å¤„理人 {{ selectShenpiData.assignee }}
        </a-tag>
        <a-tag color="blue">
          åˆ›å»ºæ—¶é—´ {{ selectShenpiData.createTime }}
        </a-tag>
        <br>
        <br>
        <button @click="fetchAndShowBmp" class="btn-custom">打开流程图</button>
        <div v-if="imageSrc">
          <img :src="imageSrc" alt="Fetched Image" />
        </div>
        <hr class="shallow-hr">
      </div>
      <div>
        <b>指派详情</b>
        <br>
        <a-form :form='form'>
          <a-spin :spinning="spinning">
            <a-tabs default-active-key='1' @change='callback'>
              <a-tab-pane key='1' tab='基本信息'>
                <a-form-model ref='form' :model='tableRowRecord' :rules='validatorRules'>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='产品名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='productName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.productName'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='部件名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='componentId'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.componentName'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='零件名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='partsName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.partsName'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='工序名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='processName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.processName'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='工步名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='stepName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.stepName'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='设备名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='deviceName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.deviceName'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='数控系统类别' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='deviceManagementCode'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.deviceManagementCode'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='数控系统类别' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='deviceManagementName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.deviceManagementName'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='文档名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='docName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.docName'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='文档版本' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='version'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.version'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                </a-form-model>
              </a-tab-pane>
              <a-tab-pane key='2' tab='流程节点'>
                <a-card>
                  <a-timeline style="padding:0 1% 0 12%" >
                    <a-timeline-item color='white' v-for="(item,index1) in hitaskDataSource" :key="index1">
                      <div class="bottom">
                        <p>处理人:{{item.assignee_dictText}}</p>
                        <p v-if="index1 !==0">处理时长:{{item.duration}}</p>
                        <p v-if="item.name !== '提交申请'">处理类型:{{item.sequenceFlowName}}</p>
                        <p v-if="item.description != null">处理意见:{{item.description}}</p>
                        <div class="left_qiu"><span>{{item.taskName}}</span></div>
                      </div>
                    </a-timeline-item>
                  </a-timeline>
                </a-card>
              </a-tab-pane>
            </a-tabs>
          </a-spin>
        </a-form>
      </div>
      <div>
        <hr class="shallow-hr">
        <br>
        <b>审批详情</b>
        <br>
        <a-form-model ref="form" :model="approveData" :rules="validatorRules" slot="detail">
          <a-row>
            <a-col ::span='span'>
              <a-form-model-item  label="申请人" :labelCol="labelCol" :wrapperCol="wrapperCol" prop='applyUser'>
                <a-input :disabled='coldisabled' v-model='tableRowRecord.applyUser'></a-input>
              </a-form-model-item >
            </a-col>
            <a-col ::span='span'>
              <a-form-model-item  label="申请原因" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="applyReason">
                <a-textarea :disabled='coldisabled'  v-model="tableRowRecord.applyReason" rows="4" />
              </a-form-model-item >
            </a-col>
            <a-col ::span='span'>
              <a-form-model-item  label="申请时间" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="applyTime">
                <a-input :disabled='coldisabled' v-model='tableRowRecord.applyTime'></a-input>
              </a-form-model-item >
            </a-col>
<!--            <a-col :span="24">-->
<!--              <a-form-item label="密级为" :labelCol="labelCol" :wrapperCol="wrapperCol">-->
<!--                <j-dict-select-tag  type='list' v-model='assignFileStream.secretLevel' dictCode='dnc_secret_level' placeholder="请选择密级"  />-->
<!--              </a-form-item>-->
<!--            </a-col>-->
            <a-col :span="24" class="btxx">
              <a-form-item label="审批状态" :labelCol="labelCol" :wrapperCol="wrapperCol">
                <j-dict-select-tag  type='list' v-model='assignFileStream.status' dictCode='dnc_assign_stream_status' placeholder="请选择审批状态"  />
              </a-form-item>
            </a-col>
            <a-col :span="24" class="btxx">
              <a-form-model-item  label="审批意见" :labelCol="labelCol" :wrapperCol="wrapperCol">
                <a-textarea v-model="assignFileStream.approveContent" rows="4" placeholder="请输入审批意见"/>
              </a-form-model-item >
            </a-col>
          </a-row>
          <div class="table-operator" style="text-align: right;">
            <a-button  @click="handleQueXiaoTask" type="primary" icon="close">取消</a-button>
            <a-button @click="submitForm">提 äº¤</a-button>
          </div>
        </a-form-model>
      </div>
    </a-card>
  </a-modal>
</template>
<script>
import '@assets/less/TableExpand.less'
import { mixinDevice } from '@/utils/mixin'
import { getAction, deleteAction, postAction, downFile, httpAction } from '@api/manage'
export default {
  name: 'FlowShenPi',
  mixins: [mixinDevice],
  props: {
    selectShenpiData: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      form: this.$form.createForm(this),
      span: 12,
      span1: 8,
      coldisabled: true,
      spinning: false,
      tableRowRecord: {},
      assignFileStream:{},
      tableDataSource: [],
      usageDataSource: [],
      hitaskDataSource:[],
      bomForm: {},
      approveContent:"",
      imageSrc: null,
      drawerVisible: true,
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 }
      },
      wrapperCol: {
        xs: { span: 30 },
        sm: { span: 16 }
      },
      validatorRules: {
        version: {
          rules: [
            { required: true, message: '请输入文档版本!'},
          ]
        },
        applyUser: {
          rules: [
            { required: true, message: '请选择申请人!'},
          ]
        },
        approveContent: {
          rules: [
            { required: true, message: '请输入审批意见!'},
          ]
        },
        docName: {
          rules: [
            { required: true, message: '请输入文档名称!'},
          ]
        },
        status: {
          rules: [
            { required: true, message: '请选择审批状态!'},
          ]
        },
      },
      approveData: {},
      flowData: {},
      title: '审批页面',
      width: 1000,
      visible: false,
      // è¡¨å¤´
      url: {
        queryBomDataById: '/nc/activit/selectVoById',
        diagramView: '/assign/flow/diagramView',
        queryHisTaskList:'/dncFlow/dispatchFile/queryHisTaskList',
        approve:"/nc/activit/assign/file/approve",
      },
      dictOptions: {},
      superFieldList: [],
      workflowSource: []
    }
  },
  created() {
  },
  computed: {},
  methods: {
    callback() {
    },
    handCancel() {
      this.visible = false
    },
    clearTableSource() {
      this.tableDataSource = []
      this.usageDataSource = []
    },
    fetchAndShowBmp() {
      console.log('flowData----->', this.flowData)
      try {
        let parm = {
          processDefinitionId: this.flowData.processDefinitionId,
          processInstanceId:this.flowData.processInstanceId,
          TaskDefinitionKey:this.flowData.processDefinitionKey
        }
        downFile(this.url.diagramView,parm,'get').then((res=>{
          console.log('Pica------>',res)
          const urlObject = window.URL.createObjectURL(new Blob([res]))
          this.imageSrc = urlObject
        }))
      } catch (error) {
        console.error('Error fetching image blob:', error)
        alert('无法加载图片,请稍后再试。')
      }
    },
    handleQueXiaoTask(){
      this.visible = false
      this.routeReload()
    },
    submitForm () {
      const that = this;
      if (!that.assignFileStream.status==null || that.assignFileStream.status===undefined){
        this.$message.warning('请选择审批状态!')
        return false;
      }
      if (!that.assignFileStream.approveContent==null || that.assignFileStream.approveContent===undefined) {
        this.$message.warning('请输入审批意见!')
        return false;
      }
      // è§¦å‘表单验证
      this.form.validateFields((err, values) => {
        if (!err) {
          that.confirmLoading = true;
          let url=this.url.approve
          let method = 'post';
          let flowTaskVo = {}
          flowTaskVo.status=that.assignFileStream.status;
          flowTaskVo.approveContent =that.assignFileStream.approveContent;
          flowTaskVo.comment =that.assignFileStream.approveContent;
          flowTaskVo.secretLevel = that.assignFileStream.secretLevel;
          flowTaskVo.dataId = this.selectShenpiData.dataId
          flowTaskVo.taskId = this.selectShenpiData.id
          flowTaskVo.userId = this.selectShenpiData.assignee
          flowTaskVo.instanceId = this.selectShenpiData.procInstId
          flowTaskVo.targetKey = this.selectShenpiData.taskDefKey
          flowTaskVo.values = this.selectShenpiData.variables
          flowTaskVo.assignee = this.selectShenpiData.assignee
          flowTaskVo.secretLevel = that.assignFileStream.secretLevel;
          console.log("表单提交数据",flowTaskVo)
          httpAction(url,flowTaskVo,method).then((res)=>{
            if(res.success){
              that.$message.success(res.message);
              that.visible = false
              //刷新表格
              that.$emit('searchReset')
            }else{
              that.$message.warning(res.message);
            }
          }).finally(() => {
            that.confirmLoading = false;
          })
        }
      })
    },
    getAllApproveData(item) {
      console.log('selectShenpiData----->', this.selectShenpiData)
      this.flowData = item
      let param = {
        'id': item.dataId
      }
      let parmhis={
        'procInstId': item.procInstId
      }
      getAction(this.url.queryHisTaskList,parmhis).then(res=>{
        this.hitaskDataSource=res.result
        getAction(this.url.queryBomDataById, param).then((res => {
          if (res.success) {
            this.tableRowRecord = res.result
            console.log('this.tableRowRecord----->', this.tableRowRecord)
          }
        }))
      }).finally(
        this.visible = true,
        console.log('this.approveData---->', this.approveData)
      )
    }
  }
}
</script>
<style scoped>
.shallow-hr {
  border: 0;
  height: 1px; /* åˆ†ç•Œçº¿çš„高度 */
  background-color: rgba(0, 0, 0, 0.1); /* ä½¿ç”¨ RGBA é¢œè‰²ï¼Œå¹¶è®¾ç½®è¾ƒä½Žçš„透明度 */
  margin: 20px 0; /* åˆ†ç•Œçº¿ä¸Šä¸‹çš„外边距 */
}
.btn-custom {
  background-color: #4CAF50; /* ç»¿è‰²èƒŒæ™¯ */
  color: white; /* ç™½è‰²æ–‡å­— */
  border: none; /* æ— è¾¹æ¡† */
  padding: 5px 15px; /* å†…边距 */
  text-align: center; /* æ–‡å­—居中 */
  text-decoration: none; /* æ— ä¸‹åˆ’线 */
  display: inline-block; /* è¡Œå†…块元素 */
  font-size: 12px; /* å­—体大小 */
  margin: 4px 2px; /* å¤–边距 */
  cursor: pointer; /* é¼ æ ‡æ‚¬åœæ—¶æ˜¾ç¤ºæ‰‹åž‹ */
  border-radius: 4px; /* åœ†è§’边框 */
}
.bold-large-label {
  font-weight: bold;
  font-size: 20px; /* æˆ–你需要的任何大小 */
}
.left_qiu{
  position: absolute;
  left: -74px;
  top: 0;
  width:54px;
  border-radius: 50%;
  height:54px;
  font-size: 13px;
  margin: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  background: #0099ff;
  transform: translate(0, 0);
}
/deep/ .ant-timeline-item-tail{
  left: -29px !important;
}
.left_qiu span{
  width: 3em;
  display: block;
  color: #fff;
  text-align: center;
}
.img{
  width: 75%;
}
.wrap{
  clear: both;
  width: 100%;
  display: flex;
  height: 50px;
  border: 1px solid #ccc;
  /* background-color: aqua; */
}
.box{
  width:21%;
  height:50px;
  border-right: 1px solid #ccc;
  line-height: 50px;
  /* background: red; */
  text-align:center;
  margin: auto;
}
@import '~@assets/less/common.less';
</style>
src/views/flowable/workflow/assignFileStream/AssignFileStreamXq.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,389 @@
<!--
 Description: å·¥ä½œæµ-指派设备详情页面 List
 Author: ä½œè€… liuyh
 Date:   2025-02-27
-->
<template>
  <a-modal
    :title="title"
    :width="width"
    :visible="visible"
    :footer="null"
    @cancel="handCancel"
  >
    <a-card :bordered="false">
      <div>
        <b>{{ selectShenpiData.description }}</b>
        <br>
        <br>
        <a-tag color="blue">
          å¤„理人 {{ selectShenpiData.assignee }}
        </a-tag>
        <a-tag color="blue">
          åˆ›å»ºæ—¶é—´ {{ selectShenpiData.createTime }}
        </a-tag>
        <br>
        <br>
        <button @click="fetchAndShowBmp" class="btn-custom">打开流程图</button>
        <div v-if="imageSrc">
          <img :src="imageSrc" alt="Fetched Image" />
        </div>
        <hr class="shallow-hr">
      </div>
      <div>
        <b>指派详情</b>
        <br>
        <a-form :form='form'>
          <a-spin :spinning="spinning">
            <a-tabs default-active-key='1' @change='callback'>
              <a-tab-pane key='1' tab='基本信息'>
                <a-form-model ref='form' :model='tableRowRecord' :rules='validatorRules'>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='产品名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='productName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.productName'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='部件名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='componentId'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.componentName'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='零件名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='partsName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.partsName'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='工序名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='processName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.processName'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='工步名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='stepName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.stepName'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='设备名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='deviceName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.deviceName'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='数控系统类别' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='deviceManagementCode'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.deviceManagementCode'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='数控系统类别' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='deviceManagementName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.deviceManagementName'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='文档名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='docName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.docName'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='文档版本' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='version'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.version'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                </a-form-model>
              </a-tab-pane>
              <a-tab-pane key='2' tab='流程节点'>
                <a-card>
                  <a-timeline style="padding:0 1% 0 12%" >
                    <a-timeline-item color='white' v-for="(item,index1) in hitaskDataSource" :key="index1">
                      <div class="bottom">
                        <p>处理人:{{item.assignee_dictText}}</p>
                        <p v-if="index1 !==0">处理时长:{{item.duration}}</p>
                        <p v-if="item.name !== '提交申请'">处理类型:{{item.sequenceFlowName}}</p>
                        <p v-if="item.description != null">处理意见:{{item.description}}</p>
                        <div class="left_qiu"><span>{{item.taskName}}</span></div>
                      </div>
                    </a-timeline-item>
                  </a-timeline>
                </a-card>
              </a-tab-pane>
            </a-tabs>
          </a-spin>
        </a-form>
      </div>
    </a-card>
  </a-modal>
</template>
<script>
import '@assets/less/TableExpand.less'
import { mixinDevice } from '@/utils/mixin'
import { getAction, deleteAction, postAction, downFile, httpAction } from '@api/manage'
export default {
  name: 'FlowShenPi',
  mixins: [mixinDevice],
  props: {
    selectShenpiData: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      form: this.$form.createForm(this),
      span: 12,
      span1: 8,
      coldisabled: true,
      spinning: false,
      tableRowRecord: {},
      assignFileStream:{},
      tableDataSource: [],
      usageDataSource: [],
      hitaskDataSource:[],
      bomForm: {},
      approveContent:"",
      imageSrc: null,
      drawerVisible: true,
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 }
      },
      wrapperCol: {
        xs: { span: 30 },
        sm: { span: 16 }
      },
      validatorRules: {
        version: {
          rules: [
            { required: true, message: '请输入文档版本!'},
          ]
        },
        applyUser: {
          rules: [
            { required: true, message: '请选择申请人!'},
          ]
        },
        approveContent: {
          rules: [
            { required: true, message: '请输入审批意见!'},
          ]
        },
        docName: {
          rules: [
            { required: true, message: '请输入文档名称!'},
          ]
        },
        status: {
          rules: [
            { required: true, message: '请选择审批状态!'},
          ]
        },
      },
      approveData: {},
      flowData: {},
      title: '详情页面',
      width: 1000,
      visible: false,
      // è¡¨å¤´
      url: {
        queryBomDataById: '/nc/activit/selectVoById',
        diagramView: '/assign/flow/diagramView',
        queryHisTaskList:'/dncFlow/dispatchFile/queryHisTaskList',
        approve:"/activit/assign/file/approve",
      },
      dictOptions: {},
      superFieldList: [],
      workflowSource: []
    }
  },
  created() {
  },
  computed: {},
  methods: {
    callback() {
    },
    handCancel() {
      this.visible = false
    },
    clearTableSource() {
      this.tableDataSource = []
      this.usageDataSource = []
    },
    fetchAndShowBmp() {
      console.log('flowData----->', this.flowData)
      try {
        let parm = {
          processDefinitionId: this.flowData.processDefinitionId,
          processInstanceId:this.flowData.processInstanceId,
          TaskDefinitionKey:this.flowData.processDefinitionKey
        }
        downFile(this.url.diagramView,parm,'get').then((res=>{
          console.log('Pica------>',res)
          const urlObject = window.URL.createObjectURL(new Blob([res]))
          this.imageSrc = urlObject
        }))
      } catch (error) {
        console.error('Error fetching image blob:', error)
        alert('无法加载图片,请稍后再试。')
      }
    },
    handleQueXiaoTask(){
      this.visible = false
      this.routeReload()
    },
    submitForm () {
      const that = this;
      if (!that.assignFileStream.status==null || that.assignFileStream.status===undefined){
        this.$message.warning('请选择审批状态!')
        return false;
      }
      if (!that.assignFileStream.approveContent==null || that.assignFileStream.approveContent===undefined) {
        this.$message.warning('请输入审批意见!')
        return false;
      }
      // è§¦å‘表单验证
      this.form.validateFields((err, values) => {
        if (!err) {
          that.confirmLoading = true;
          let url=this.url.approve
          let method = 'post';
          let flowTaskVo = {}
          flowTaskVo.status=that.assignFileStream.status;
          flowTaskVo.approveContent =that.assignFileStream.approveContent;
          flowTaskVo.comment =that.assignFileStream.approveContent;
          flowTaskVo.secretLevel = that.assignFileStream.secretLevel;
          flowTaskVo.dataId = this.selectShenpiData.dataId
          flowTaskVo.taskId = this.selectShenpiData.id
          flowTaskVo.userId = this.selectShenpiData.assignee
          flowTaskVo.instanceId = this.selectShenpiData.procInstId
          flowTaskVo.targetKey = this.selectShenpiData.taskDefKey
          flowTaskVo.values = this.selectShenpiData.variables
          flowTaskVo.assignee = this.selectShenpiData.assignee
          flowTaskVo.secretLevel = that.assignFileStream.secretLevel;
          console.log("表单提交数据",flowTaskVo)
          httpAction(url,flowTaskVo,method).then((res)=>{
            if(res.success){
              that.$message.success(res.message);
              that.$emit('ok');
            }else{
              that.$message.warning(res.message);
            }
          }).finally(() => {
            that.confirmLoading = false;
          })
        }
      })
    },
    getAllApproveData(item) {
      console.log('selectShenpiData----->', this.selectShenpiData)
      console.log('item----->', item)
      this.flowData = item
      let param = {
        'id': item.dataId
      }
      let parmhis={
        'procInstId': item.procInstId
      }
      getAction(this.url.queryHisTaskList,parmhis).then(res=>{
        this.hitaskDataSource=res.result
        getAction(this.url.queryBomDataById, param).then((res => {
          if (res.success) {
            this.tableRowRecord = res.result
            console.log('this.tableRowRecord----->', this.tableRowRecord)
          }
        }))
      }).finally(
        this.visible = true,
        console.log('this.approveData---->', this.approveData)
      )
    }
  }
}
</script>
<style scoped>
.shallow-hr {
  border: 0;
  height: 1px; /* åˆ†ç•Œçº¿çš„高度 */
  background-color: rgba(0, 0, 0, 0.1); /* ä½¿ç”¨ RGBA é¢œè‰²ï¼Œå¹¶è®¾ç½®è¾ƒä½Žçš„透明度 */
  margin: 20px 0; /* åˆ†ç•Œçº¿ä¸Šä¸‹çš„外边距 */
}
.btn-custom {
  background-color: #4CAF50; /* ç»¿è‰²èƒŒæ™¯ */
  color: white; /* ç™½è‰²æ–‡å­— */
  border: none; /* æ— è¾¹æ¡† */
  padding: 5px 15px; /* å†…边距 */
  text-align: center; /* æ–‡å­—居中 */
  text-decoration: none; /* æ— ä¸‹åˆ’线 */
  display: inline-block; /* è¡Œå†…块元素 */
  font-size: 12px; /* å­—体大小 */
  margin: 4px 2px; /* å¤–边距 */
  cursor: pointer; /* é¼ æ ‡æ‚¬åœæ—¶æ˜¾ç¤ºæ‰‹åž‹ */
  border-radius: 4px; /* åœ†è§’边框 */
}
.bold-large-label {
  font-weight: bold;
  font-size: 20px; /* æˆ–你需要的任何大小 */
}
.left_qiu{
  position: absolute;
  left: -74px;
  top: 0;
  width:54px;
  border-radius: 50%;
  height:54px;
  font-size: 13px;
  margin: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  background: #0099ff;
  transform: translate(0, 0);
}
/deep/ .ant-timeline-item-tail{
  left: -29px !important;
}
.left_qiu span{
  width: 3em;
  display: block;
  color: #fff;
  text-align: center;
}
.img{
  width: 75%;
}
.wrap{
  clear: both;
  width: 100%;
  display: flex;
  height: 50px;
  border: 1px solid #ccc;
  /* background-color: aqua; */
}
.box{
  width:21%;
  height:50px;
  border-right: 1px solid #ccc;
  line-height: 50px;
  /* background: red; */
  text-align:center;
  margin: auto;
}
@import '~@assets/less/common.less';
</style>
src/views/flowable/workflow/dispatchFile/DispatchFileBachHandleForm.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,216 @@
<template>
    <a-spin :spinning="confirmLoading">
        <j-form-container >
            <a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
                <a-row>
          <a-col :span="24" v-if="selectBachData.taskDefKey ==='task_proofread'" class="btxx">
            <a-form-model-item  label="处理类型" :labelCol="labelCol" :wrapperCol="wrapperCol" prop='status'>
              <j-dict-select-tag  type='list' v-model='model.status' dictCode='nc_sq_handle_type_jd' placeholder="请选择处理类型"  />
            </a-form-model-item >
          </a-col>
          <a-col :span="24" v-if="selectBachData.taskDefKey ==='task_approve' || selectBachData.taskDefKey ==='task_cut' || selectBachData.taskDefKey ==='task_finalize'" class="btxx">
            <a-form-model-item  label="处理类型" :labelCol="labelCol" :wrapperCol="wrapperCol" prop='status'>
              <j-dict-select-tag  type='list' v-model='model.status' dictCode='nc_sq_handle_type' placeholder="请选择处理类型"  />
            </a-form-model-item >
          </a-col>
          <a-col :span="24" class="btxx">
            <a-form-model-item  label="处理意见" :labelCol="labelCol" :wrapperCol="wrapperCol">
              <a-textarea v-model="model.approveContent" rows="4" placeholder="请输入处理意见"/>
            </a-form-model-item >
          </a-col>
                </a-row>
            </a-form-model>
        </j-form-container>
    </a-spin>
</template>
<script>
    import axios from 'axios';
    import {
        httpAction,
        getAction
    } from '@/api/manage'
    import {
        validateDuplicateValue
    } from '@/utils/util'
    export default {
        name: 'ChCfForm',
        components: {},
        props: {
            //表单禁用
            disabled: {
                type: Boolean,
                default: false,
                required: false
            }
        },
        data() {
            return {
                principalList: [],
                model: {},
                labelCol: {
                    xs: {
                        span: 24
                    },
                    sm: {
                        span: 5
                    },
                },
                wrapperCol: {
                    xs: {
                        span: 24
                    },
                    sm: {
                        span: 16
                    },
                },
                confirmLoading: false,
                validatorRules: {
                    address: [{
                        required: true,
                        message: '请选择地址!'
                    }, ],
                    bt: [{
                        required: true,
                        message: '请输入标题!'
                    }, ],
                },
                url: {
          approvalBatch: "/dncFlow/dispatchFile/approvalBatch",
                },
        selectBachData:{}
            }
        },
        computed: {
            formDisabled() {
                return this.disabled
            },
        },
        created() {
            //备份model原始值
            this.modelDefault = JSON.parse(JSON.stringify(this.model));
        },
        methods: {
            handleChange(e) {
                console.log(e);
                let sss = e.split('||||')
                console.log(sss);
                this.model.jd = sss[0]
                this.model.address = sss[1]
                console.log(sss)
            },
            handleSearch(e) {
                if (e === '') {
                    return
                }
                const that = this;
                axios.get('/s-api/api/index/lsdz?input=' + e)
                    .then(response => {
                        that.principalList = []
                        console.log(that.principalList)
                        for (var i = 0; i < response.data.data.length; i++) {
                            that.principalList.push({
                                value: response.data.data[i].inputValueId + '||||' + response.data.data[i].setout,
                                label: response.data.data[i].setout,
                            });
                        }
                        // that.principalList = response.data.data
                        console.log(that.principalList, '8888'); // è¾“出返回的数据
                    })
                    .catch(error => {
                        console.error(error); // å¤„理错误情况
                    });
            },
            add() {
                this.edit(this.modelDefault);
            },
            edit(record) {
                this.selectBachData=record
                this.visible = true;
            },
      submitForm () {
        const that = this;
        if (that.selectBachData.taskDefKey ==='task_prepare'){
          // è§¦å‘表单验证-重新启动
          this.$refs.form.validate(valid => {
            if (valid) {
              that.confirmLoading = true;
              let url=this.url.approvalBatch;
              let method = 'post';
              let flowTaskVo = {}
              flowTaskVo.comment =this.model.approveContent;
              flowTaskVo.taskIds=that.selectBachData.taskIds
              flowTaskVo.targetKey=that.selectBachData.taskDefKey
              console.log("表单提交数据",flowTaskVo)
              httpAction(url,flowTaskVo,method).then((res)=>{
                if(res.success){
                  that.$message.success(res.message);
                  that.valid = false
                  //刷新表格
                  that.$emit('searchReset')
                }else{
                  that.$message.warning(res.message);
                }
              }).finally(() => {
                that.confirmLoading = false;
              })
            }
          })
          //跳出方法
          return false;
        }else {
          if (!that.model.status==null || that.model.status===undefined){
            this.$message.warning('请选择处理类型!')
            return false;
          }
        }
        if (!that.model.approveContent==null || that.model.approveContent===undefined) {
          this.$message.warning('请输入处理意见!')
          return false;
        }
        // è§¦å‘表单验证
        this.$refs.form.validate(valid => {
          if (valid) {
            that.confirmLoading = true;
            let url=this.url.approvalBatch
            let method = 'post';
            let handle =this.model.status === '1';
            let flowTaskVo = {}
            switch (that.selectBachData.taskDefKey){
              case "task_approve":
                flowTaskVo.ratify=handle;
                break;
              case "task_cut":
                flowTaskVo.cut=handle;
                break;
              case "task_finalize":
                flowTaskVo.stereotype=handle;
                break;
            }
            if (that.selectBachData.taskDefKey ==='task_proofread'){
              flowTaskVo.proofreadStatus =that.model.status;
            }
            flowTaskVo.comment =that.model.approveContent;
            flowTaskVo.taskIds=that.selectBachData.taskIds
            flowTaskVo.targetKey=that.selectBachData.taskDefKey
            console.log("表单提交数据",flowTaskVo)
            httpAction(url,flowTaskVo,method).then((res)=>{
              if(res.success){
                that.$message.success(res.message);
                that.valid = false
                that.close();
                //刷新表格
                that.$emit('ok')
              }else{
                that.$message.warning(res.message);
              }
            }).finally(() => {
              that.confirmLoading = false;
            })
          }
        })
      },
        }
    }
</script>
src/views/flowable/workflow/dispatchFile/DispatchFileBachHandleStyle#Drawer.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,62 @@
<template>
  <j-modal
    :title="title"
    :width="width"
    :visible="visible"
    switchFullscreen
    @ok="handleOk"
    :okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
    @cancel="handleCancel"
    cancelText="关闭">
    <DispatchFileBachHandleForm ref="realForm" @ok="submitCallback" :disabled="disableSubmit" normal></DispatchFileBachHandleForm>
  </j-modal>
</template>
<script>
  import DispatchFileBachHandleForm from './DispatchFileBachHandleForm.vue'
  export default {
    name: 'DispatchFileBachHandleStyle',
    components: {
      DispatchFileBachHandleForm
    },
    data () {
      return {
        title:'',
        width:800,
        visible: false,
        disableSubmit: false
      }
    },
    methods: {
      add () {
        this.visible=true
        this.$nextTick(()=>{
          this.$refs.realForm.add();
        })
      },
      edit (record) {
        this.visible=true
        this.$nextTick(()=>{
          this.$refs.realForm.edit(record);
        });
      },
      close () {
        this.$emit('close');
        this.visible = false;
      },
      submitCallback(){
        this.$emit('ok');
        this.visible = false;
      },
      handleOk () {
        this.$refs.realForm.submitForm();
      },
      handleCancel () {
        this.close()
      }
    }
  }
</script>
src/views/flowable/workflow/dispatchFile/DispatchFileHandle.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,415 @@
<!--
 Description: å·¥ä½œæµ-NC审签处理页面 List
 Author: ä½œè€… liuyh
 Date:   2025-02-27
-->
<template>
  <a-modal
    :title="title"
    :width="width"
    :visible="visible"
    :footer="null"
    @cancel="handCancel"
  >
    <a-card :bordered="false">
      <div>
        <b>{{ selectShenpiData.description }}</b>
        <br>
        <br>
        <a-tag color="blue">
          å½“前处理人 {{ selectShenpiData.assignee_dictText }}
        </a-tag>
        <a-tag color="blue">
          ä»»åŠ¡åˆ›å»ºæ—¶é—´ {{ selectShenpiData.createTime }}
        </a-tag>
        <br>
        <br>
        <button @click="fetchAndShowBmp" class="btn-custom">打开流程图</button>
        <div v-if="imageSrc">
          <img :src="imageSrc" alt="Fetched Image" />
        </div>
        <hr class="shallow-hr">
      </div>
      <div>
        <b>审签详情</b>
        <br>
        <a-form :form='form'>
          <a-spin :spinning="spinning">
            <a-tabs default-active-key='1' @change='callback'>
              <a-tab-pane key='1' tab='基本信息'>
                <a-form-model ref='form' :model='tableRowRecord' :rules='validatorRules'>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='文档名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='docName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.docName'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='文档版本' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='publishVersion'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.publishVersion'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='文档后缀' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='docSuffix'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.docSuffix'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='系统指定版本' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='componentId'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.componentName'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='出库状态' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='pullStatus_dictText'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.pullStatus_dictText'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='出库人' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='pullUser_dictText'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.pullUser_dictText'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                </a-form-model>
              </a-tab-pane>
              <a-tab-pane key='2' tab='流程节点'>
                <a-card>
                  <a-timeline style="padding:0 1% 0 12%" >
                    <a-timeline-item color='white' v-for="(item,index1) in hitaskDataSource" :key="index1">
                      <div class="bottom">
                        <p>处理人:{{item.assignee_dictText}}</p>
                        <p v-if="index1 !==0">处理时长:{{item.duration}}</p>
                        <p v-if="item.name !== '提交申请'">处理类型:{{item.sequenceFlowName}}</p>
                        <p v-if="item.description != null">处理意见:{{item.description}}</p>
                        <div class="left_qiu"><span>{{item.taskName}}</span></div>
                      </div>
                    </a-timeline-item>
                  </a-timeline>
                </a-card>
              </a-tab-pane>
            </a-tabs>
          </a-spin>
        </a-form>
      </div>
      <div>
        <hr class="shallow-hr">
        <br>
        <b>审批详情</b>
        <br>
        <a-form-model ref="form" :model="approveData" :rules="validatorRules" slot="detail">
          <a-row>
            <a-col ::span='span' v-if="selectShenpiData.taskDefKey ==='task_proofread'" class="btxx">
              <a-form-model-item  label="处理类型" :labelCol="labelCol" :wrapperCol="wrapperCol" prop='status'>
                <j-dict-select-tag  type='list' v-model='assignFileStream.status' dictCode='nc_sq_handle_type_jd' placeholder="请选择处理类型"  />
              </a-form-model-item >
            </a-col>
            <a-col ::span='span' v-if="selectShenpiData.taskDefKey ==='task_approve' || selectShenpiData.taskDefKey ==='task_cut' || selectShenpiData.taskDefKey ==='task_finalize'" class="btxx">
              <a-form-model-item  label="处理类型" :labelCol="labelCol" :wrapperCol="wrapperCol" prop='status'>
                <j-dict-select-tag  type='list' v-model='assignFileStream.status' dictCode='nc_sq_handle_type' placeholder="请选择处理类型"  />
              </a-form-model-item >
            </a-col>
            <a-col :span="24" class="btxx">
              <a-form-model-item  label="处理意见" :labelCol="labelCol" :wrapperCol="wrapperCol">
                <a-textarea v-model="assignFileStream.approveContent" rows="4" placeholder="请输入处理意见"/>
              </a-form-model-item >
            </a-col>
          </a-row>
          <div class="table-operator" style="text-align: right;">
            <a-button  @click="handleQueXiaoTask" type="primary" icon="close">取消</a-button>
            <a-button @click="submitForm">提 äº¤</a-button>
          </div>
        </a-form-model>
      </div>
    </a-card>
  </a-modal>
</template>
<script>
import '@assets/less/TableExpand.less'
import { mixinDevice } from '@/utils/mixin'
import { getAction, deleteAction, postAction, downFile, httpAction } from '@api/manage'
export default {
  name: 'FlowShenPi',
  mixins: [mixinDevice],
  props: {
    selectShenpiData: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      form: this.$form.createForm(this),
      span: 12,
      span1: 8,
      coldisabled: true,
      spinning: false,
      tableRowRecord: {},
      assignFileStream:{},
      tableDataSource: [],
      usageDataSource: [],
      hitaskDataSource:[],
      bomForm: {},
      approveContent:"",
      imageSrc: null,
      drawerVisible: true,
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 }
      },
      wrapperCol: {
        xs: { span: 30 },
        sm: { span: 16 }
      },
      validatorRules: {
        status: {
          rules: [
            { required: true, message: '请选择审批状态!'},
          ]
        },
      },
      approveData: {},
      flowData: {},
      title: '详情页面',
      width: 1000,
      visible: false,
      // è¡¨å¤´
      url: {
        queryBomDataById: '/dncFlow/dispatchFile/selectVoById',
        diagramView: '/assign/flow/diagramView',
        queryHisTaskList:'/dncFlow/dispatchFile/queryHisTaskList',
        approve:"/dncFlow/dispatchFile/approval",
        saveDispatchFile:"/dncFlow/dispatchFile/saveDispatchFile"
      },
      dictOptions: {},
      superFieldList: [],
      workflowSource: []
    }
  },
  created() {
  },
  computed: {},
  methods: {
    callback() {
    },
    handCancel() {
      this.visible = false
    },
    clearTableSource() {
      this.tableDataSource = []
      this.usageDataSource = []
    },
    fetchAndShowBmp() {
      console.log('flowData----->', this.flowData)
      try {
        let parm = {
          processDefinitionId: this.flowData.processDefinitionId,
          processInstanceId:this.flowData.processInstanceId,
          TaskDefinitionKey:this.flowData.processDefinitionKey
        }
        downFile(this.url.diagramView,parm,'get').then((res=>{
          console.log('Pica------>',res)
          const urlObject = window.URL.createObjectURL(new Blob([res]))
          this.imageSrc = urlObject
        }))
      } catch (error) {
        console.error('Error fetching image blob:', error)
        alert('无法加载图片,请稍后再试。')
      }
    },
    handleQueXiaoTask(){
      this.visible = false
      this.routeReload()
    },
    submitForm () {
      const that = this;
      if (that.selectShenpiData.taskDefKey ==='task_prepare'){
        // è§¦å‘表单验证-重新启动
        this.form.validateFields((err, values) => {
          if (!err) {
            that.confirmLoading = true;
            let url=this.url.saveDispatchFile;
            let method = 'post';
            let flowTaskVo = {}
            flowTaskVo.comment =that.assignFileStream.approveContent;
            flowTaskVo.dataId = this.selectShenpiData.dataId
            flowTaskVo.instanceId = this.selectShenpiData.procInstId
            flowTaskVo.taskId = this.selectShenpiData.id
            console.log("表单提交数据",flowTaskVo)
            httpAction(url,flowTaskVo,method).then((res)=>{
              if(res.success){
                that.$message.success(res.message);
                that.visible = false
                //刷新表格
                that.$emit('searchReset')
              }else{
                that.$message.warning(res.message);
              }
            }).finally(() => {
              that.confirmLoading = false;
            })
          }
        })
        //跳出方法
        return false;
      }else {
        if (!that.assignFileStream.status==null || that.assignFileStream.status===undefined){
          this.$message.warning('请选择处理类型!')
          return false;
        }
      }
      if (!that.assignFileStream.approveContent==null || that.assignFileStream.approveContent===undefined) {
        this.$message.warning('请输入处理意见!')
        return false;
      }
      // è§¦å‘表单验证
      this.form.validateFields((err, values) => {
        if (!err) {
          that.confirmLoading = true;
          let url=this.url.approve
          let method = 'post';
          let handle =that.assignFileStream.status === '1';
          let flowTaskVo = {}
          switch (that.selectShenpiData.taskDefKey){
            case "task_approve":
              flowTaskVo.ratify=handle;
              break;
            case "task_cut":
              flowTaskVo.cut=handle;
              break;
            case "task_finalize":
              flowTaskVo.stereotype=handle;
              break;
          }
          if (that.selectShenpiData.taskDefKey ==='task_proofread'){
            flowTaskVo.proofreadStatus =that.assignFileStream.status;
          }
          flowTaskVo.comment =that.assignFileStream.approveContent;
          flowTaskVo.dataId = this.selectShenpiData.dataId
          flowTaskVo.taskId = this.selectShenpiData.id
          flowTaskVo.userId = this.selectShenpiData.assignee
          flowTaskVo.instanceId = this.selectShenpiData.procInstId
          flowTaskVo.values = this.selectShenpiData.variables
          console.log("表单提交数据",flowTaskVo)
          httpAction(url,flowTaskVo,method).then((res)=>{
            if(res.success){
              that.$message.success(res.message);
              that.visible = false
              //刷新表格
              that.$emit('searchReset')
            }else{
              that.$message.warning(res.message);
            }
          }).finally(() => {
            that.confirmLoading = false;
          })
        }
      })
    },
    getAllApproveData(item) {
      console.log('selectShenpiData----->', this.selectShenpiData)
      this.flowData = item
      let param = {
        'id': item.dataId
      }
      let parmhis={
        'procInstId': item.procInstId
      }
      getAction(this.url.queryHisTaskList,parmhis).then(res=>{
        this.hitaskDataSource=res.result
        getAction(this.url.queryBomDataById, param).then((res => {
          if (res.success) {
            this.tableRowRecord = res.result[0]
            console.log('this.tableRowRecord----->', this.tableRowRecord[0])
          }
        }))
      }).finally(
        this.visible = true,
        console.log('this.approveData---->', this.approveData)
      )
    }
  }
}
</script>
<style scoped>
.shallow-hr {
  border: 0;
  height: 1px; /* åˆ†ç•Œçº¿çš„高度 */
  background-color: rgba(0, 0, 0, 0.1); /* ä½¿ç”¨ RGBA é¢œè‰²ï¼Œå¹¶è®¾ç½®è¾ƒä½Žçš„透明度 */
  margin: 20px 0; /* åˆ†ç•Œçº¿ä¸Šä¸‹çš„外边距 */
}
.btn-custom {
  background-color: #4CAF50; /* ç»¿è‰²èƒŒæ™¯ */
  color: white; /* ç™½è‰²æ–‡å­— */
  border: none; /* æ— è¾¹æ¡† */
  padding: 5px 15px; /* å†…边距 */
  text-align: center; /* æ–‡å­—居中 */
  text-decoration: none; /* æ— ä¸‹åˆ’线 */
  display: inline-block; /* è¡Œå†…块元素 */
  font-size: 12px; /* å­—体大小 */
  margin: 4px 2px; /* å¤–边距 */
  cursor: pointer; /* é¼ æ ‡æ‚¬åœæ—¶æ˜¾ç¤ºæ‰‹åž‹ */
  border-radius: 4px; /* åœ†è§’边框 */
}
.bold-large-label {
  font-weight: bold;
  font-size: 20px; /* æˆ–你需要的任何大小 */
}
.left_qiu{
  position: absolute;
  left: -74px;
  top: 0;
  width:54px;
  border-radius: 50%;
  height:54px;
  font-size: 13px;
  margin: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  background: #0099ff;
  transform: translate(0, 0);
}
/deep/ .ant-timeline-item-tail{
  left: -29px !important;
}
.left_qiu span{
  width: 3em;
  display: block;
  color: #fff;
  text-align: center;
}
.img{
  width: 75%;
}
.wrap{
  clear: both;
  width: 100%;
  display: flex;
  height: 50px;
  border: 1px solid #ccc;
  /* background-color: aqua; */
}
.box{
  width:21%;
  height:50px;
  border-right: 1px solid #ccc;
  line-height: 50px;
  /* background: red; */
  text-align:center;
  margin: auto;
}
@import '~@assets/less/common.less';
</style>
src/views/flowable/workflow/dispatchFile/DispatchFileXq.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,364 @@
<!--
 Description: å·¥ä½œæµ-NC审签详情页面 List
 Author: ä½œè€… liuyh
 Date:   2025-02-27
-->
<template>
  <a-modal
    :title="title"
    :width="width"
    :visible="visible"
    :footer="null"
    @cancel="handCancel"
  >
    <a-card :bordered="false">
      <div>
        <b>{{ selectShenpiData.description }}</b>
        <br>
        <br>
        <a-tag color="blue">
          å½“前处理人 {{ selectShenpiData.assignee_dictText }}
        </a-tag>
        <a-tag color="blue">
          å½“前任务创建时间 {{ selectShenpiData.createTime }}
        </a-tag>
        <br>
        <br>
        <button @click="fetchAndShowBmp" class="btn-custom">打开流程图</button>
        <div v-if="imageSrc">
          <img :src="imageSrc" alt="Fetched Image" />
        </div>
        <hr class="shallow-hr">
      </div>
      <div>
        <b>审签详情</b>
        <br>
        <a-form :form='form'>
          <a-spin :spinning="spinning">
            <a-tabs default-active-key='1' @change='callback'>
              <a-tab-pane key='1' tab='基本信息'>
                <a-form-model ref='form' :model='tableRowRecord' :rules='validatorRules'>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='文档名称' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='docName'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.docName'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='文档版本' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='publishVersion'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.publishVersion'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='文档后缀' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='docSuffix'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.docSuffix'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='系统指定版本' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='componentId'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.componentName'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                  <a-row>
                    <a-col :span='span'>
                      <a-form-model-item label='出库状态' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='pullStatus_dictText'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.pullStatus_dictText'></a-input>
                      </a-form-model-item>
                    </a-col>
                    <a-col :span='span'>
                      <a-form-model-item label='出库人' :labelCol='labelCol' :wrapperCol='wrapperCol' prop='pullUser_dictText'>
                        <a-input :disabled='coldisabled' v-model='tableRowRecord.pullUser_dictText'></a-input>
                      </a-form-model-item>
                    </a-col>
                  </a-row>
                </a-form-model>
              </a-tab-pane>
              <a-tab-pane key='2' tab='流程节点'>
                <a-card>
                  <a-timeline style="padding:0 1% 0 12%" >
                    <a-timeline-item color='white' v-for="(item,index1) in hitaskDataSource" :key="index1">
                      <div class="bottom">
                        <p>处理人:{{item.assignee_dictText}}</p>
                        <p v-if="index1 !==0">处理时长:{{item.duration}}</p>
                        <p v-if="item.name !== '提交申请'">处理类型:{{item.sequenceFlowName}}</p>
                        <p v-if="item.description != null">处理意见:{{item.description}}</p>
                        <div class="left_qiu"><span>{{item.taskName}}</span></div>
                      </div>
                    </a-timeline-item>
                  </a-timeline>
                </a-card>
              </a-tab-pane>
            </a-tabs>
          </a-spin>
        </a-form>
      </div>
    </a-card>
  </a-modal>
</template>
<script>
import '@assets/less/TableExpand.less'
import { mixinDevice } from '@/utils/mixin'
import { getAction, deleteAction, postAction, downFile, httpAction } from '@api/manage'
export default {
  name: 'FlowShenPi',
  mixins: [mixinDevice],
  props: {
    selectShenpiData: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      form: this.$form.createForm(this),
      span: 12,
      span1: 8,
      coldisabled: true,
      spinning: false,
      tableRowRecord: {},
      assignFileStream:{},
      tableDataSource: [],
      usageDataSource: [],
      hitaskDataSource:[],
      bomForm: {},
      approveContent:"",
      imageSrc: null,
      drawerVisible: true,
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 }
      },
      wrapperCol: {
        xs: { span: 30 },
        sm: { span: 16 }
      },
      validatorRules: {
        version: {
          rules: [
            { required: true, message: '请输入文档版本!'},
          ]
        },
        applyUser: {
          rules: [
            { required: true, message: '请选择申请人!'},
          ]
        },
        approveContent: {
          rules: [
            { required: true, message: '请输入审批意见!'},
          ]
        },
        docName: {
          rules: [
            { required: true, message: '请输入文档名称!'},
          ]
        },
        status: {
          rules: [
            { required: true, message: '请选择审批状态!'},
          ]
        },
      },
      approveData: {},
      flowData: {},
      title: '详情页面',
      width: 1000,
      visible: false,
      // è¡¨å¤´
      url: {
        queryBomDataById: '/dncFlow/dispatchFile/selectVoById',
        diagramView: '/assign/flow/diagramView',
        queryHisTaskList:'/dncFlow/dispatchFile/queryHisTaskList',
        approve:"/activit/assign/file/approve",
      },
      dictOptions: {},
      superFieldList: [],
      workflowSource: []
    }
  },
  created() {
  },
  computed: {},
  methods: {
    callback() {
    },
    handCancel() {
      this.visible = false
    },
    clearTableSource() {
      this.tableDataSource = []
      this.usageDataSource = []
    },
    fetchAndShowBmp() {
      console.log('flowData----->', this.flowData)
      try {
        let parm = {
          processDefinitionId: this.flowData.processDefinitionId,
          processInstanceId:this.flowData.processInstanceId,
          TaskDefinitionKey:this.flowData.processDefinitionKey
        }
        downFile(this.url.diagramView,parm,'get').then((res=>{
          console.log('Pica------>',res)
          const urlObject = window.URL.createObjectURL(new Blob([res]))
          this.imageSrc = urlObject
        }))
      } catch (error) {
        console.error('Error fetching image blob:', error)
        alert('无法加载图片,请稍后再试。')
      }
    },
    handleQueXiaoTask(){
      this.visible = false
      this.routeReload()
    },
    submitForm () {
      const that = this;
      if (!that.assignFileStream.status==null || that.assignFileStream.status===undefined){
        this.$message.warning('请选择审批状态!')
        return false;
      }
      if (!that.assignFileStream.approveContent==null || that.assignFileStream.approveContent===undefined) {
        this.$message.warning('请输入审批意见!')
        return false;
      }
      // è§¦å‘表单验证
      this.form.validateFields((err, values) => {
        if (!err) {
          that.confirmLoading = true;
          let url=this.url.approve
          let method = 'post';
          let flowTaskVo = {}
          flowTaskVo.status=that.assignFileStream.status;
          flowTaskVo.approveContent =that.assignFileStream.approveContent;
          flowTaskVo.comment =that.assignFileStream.approveContent;
          flowTaskVo.secretLevel = that.assignFileStream.secretLevel;
          flowTaskVo.dataId = this.selectShenpiData.dataId
          flowTaskVo.taskId = this.selectShenpiData.id
          flowTaskVo.userId = this.selectShenpiData.assignee
          flowTaskVo.instanceId = this.selectShenpiData.procInstId
          flowTaskVo.targetKey = this.selectShenpiData.taskDefKey
          flowTaskVo.values = this.selectShenpiData.variables
          flowTaskVo.assignee = this.selectShenpiData.assignee
          flowTaskVo.secretLevel = that.assignFileStream.secretLevel;
          console.log("表单提交数据",flowTaskVo)
          httpAction(url,flowTaskVo,method).then((res)=>{
            if(res.success){
              that.$message.success(res.message);
              that.$emit('ok');
            }else{
              that.$message.warning(res.message);
            }
          }).finally(() => {
            that.confirmLoading = false;
          })
        }
      })
    },
    getAllApproveData(item) {
      console.log('selectShenpiData----->', this.selectShenpiData)
      this.flowData = item
      let param = {
        'id': item.dataId
      }
      let parmhis={
        'procInstId': item.procInstId
      }
      getAction(this.url.queryHisTaskList,parmhis).then(res=>{
        this.hitaskDataSource=res.result
        getAction(this.url.queryBomDataById, param).then((res => {
          if (res.success) {
            this.tableRowRecord = res.result[0]
            console.log('this.tableRowRecord----->', this.tableRowRecord[0])
          }
        }))
      }).finally(
        this.visible = true,
        console.log('this.approveData---->', this.approveData)
      )
    }
  }
}
</script>
<style scoped>
.shallow-hr {
  border: 0;
  height: 1px; /* åˆ†ç•Œçº¿çš„高度 */
  background-color: rgba(0, 0, 0, 0.1); /* ä½¿ç”¨ RGBA é¢œè‰²ï¼Œå¹¶è®¾ç½®è¾ƒä½Žçš„透明度 */
  margin: 20px 0; /* åˆ†ç•Œçº¿ä¸Šä¸‹çš„外边距 */
}
.btn-custom {
  background-color: #4CAF50; /* ç»¿è‰²èƒŒæ™¯ */
  color: white; /* ç™½è‰²æ–‡å­— */
  border: none; /* æ— è¾¹æ¡† */
  padding: 5px 15px; /* å†…边距 */
  text-align: center; /* æ–‡å­—居中 */
  text-decoration: none; /* æ— ä¸‹åˆ’线 */
  display: inline-block; /* è¡Œå†…块元素 */
  font-size: 12px; /* å­—体大小 */
  margin: 4px 2px; /* å¤–边距 */
  cursor: pointer; /* é¼ æ ‡æ‚¬åœæ—¶æ˜¾ç¤ºæ‰‹åž‹ */
  border-radius: 4px; /* åœ†è§’边框 */
}
.bold-large-label {
  font-weight: bold;
  font-size: 20px; /* æˆ–你需要的任何大小 */
}
.left_qiu{
  position: absolute;
  left: -74px;
  top: 0;
  width:54px;
  border-radius: 50%;
  height:54px;
  font-size: 13px;
  margin: auto;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  background: #0099ff;
  transform: translate(0, 0);
}
/deep/ .ant-timeline-item-tail{
  left: -29px !important;
}
.left_qiu span{
  width: 3em;
  display: block;
  color: #fff;
  text-align: center;
}
.img{
  width: 75%;
}
.wrap{
  clear: both;
  width: 100%;
  display: flex;
  height: 50px;
  border: 1px solid #ccc;
  /* background-color: aqua; */
}
.box{
  width:21%;
  height:50px;
  border-right: 1px solid #ccc;
  line-height: 50px;
  /* background: red; */
  text-align:center;
  margin: auto;
}
@import '~@assets/less/common.less';
</style>
src/views/system/SysBusinessCodeRuleList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,177 @@
<template>
  <a-card :bordered="false">
    <!-- æŸ¥è¯¢åŒºåŸŸ -->
    <div class="table-page-search-wrapper">
      <a-form layout="inline" @keyup.enter.native="searchQuery">
        <a-row :gutter="24">
          <a-col :xl="6" :lg="7" :md="8" :sm="24">
            <a-form-item label="业务名称">
              <j-input placeholder="请输入业务名称" v-model="queryParam.businessName"></j-input>
            </a-form-item>
          </a-col>
          <a-col :xl="6" :lg="7" :md="8" :sm="24">
            <a-form-item label="业务编码">
              <j-input placeholder="请输入业务编码" v-model="queryParam.businessCode"></j-input>
            </a-form-item>
          </a-col>
          <a-col :xl="6" :lg="7" :md="8" :sm="24">
            <a-form-item label="编码前缀">
              <j-input placeholder="请输入编码前缀" v-model="queryParam.prefix"></j-input>
            </a-form-item>
          </a-col>
          <a-col :xl="6" :lg="7" :md="8" :sm="24">
            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
              <a-button type="info" @click="searchReset" icon="reload" style="margin-left: 8px">重置</a-button>
            </span>
          </a-col>
        </a-row>
      </a-form>
    </div>
    <!-- æ“ä½œæŒ‰é’®åŒºåŸŸ -->
    <div class="table-operator">
      <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
      <a-dropdown v-if="selectedRowKeys.length > 0">
        <a-menu slot="overlay">
          <a-menu-item key="1" @click="batchDel">
            <a-icon type="delete" />
            åˆ é™¤
          </a-menu-item>
        </a-menu>
        <a-button style="margin-left: 8px"> æ‰¹é‡æ“ä½œ
          <a-icon type="down" />
        </a-button>
      </a-dropdown>
    </div>
    <!-- table区域-begin -->
    <div>
      <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
        <i class="anticon anticon-info-circle ant-alert-icon"></i> å·²é€‰æ‹© <a
        style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
      </div>
      <a-table
        ref="table"
        size="middle"
        bordered
        rowKey="id"
        :columns="columns"
        :dataSource="dataSource"
        :pagination="ipagination"
        :loading="loading"
        class="j-table-force-nowrap"
        :rowSelection="{selectedRowKeys: selectedRowKeys, onChange: onSelectChange}"
        @change="handleTableChange">
        <span slot="action" slot-scope="text, record">
          <a @click="handleEdit(record)">编辑</a>
          <a-divider type="vertical" />
          <a-dropdown>
            <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
            <a-menu slot="overlay">
              <a-menu-item>
                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
                  <a>删除</a>
                </a-popconfirm>
              </a-menu-item>
            </a-menu>
          </a-dropdown>
        </span>
      </a-table>
    </div>
    <!-- table区域-end -->
    <!-- è¡¨å•区域 -->
    <sysBusinessCodeRule-modal ref="modalForm" @ok="modalFormOk"></sysBusinessCodeRule-modal>
  </a-card>
</template>
<script>
import '@/assets/less/TableExpand.less'
import SysBusinessCodeRuleModal from './modules/SysBusinessCodeRuleModal'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
export default {
  name: 'SysBusinessCodeRuleList',
  mixins: [JeecgListMixin],
  components: {
    SysBusinessCodeRuleModal
  },
  data() {
    return {
      description: '业务编码规则管理页面',
      // è¡¨å¤´
      columns: [
        {
          title: '#',
          dataIndex: '',
          key: 'rowIndex',
          width: 60,
          align: 'center',
          customRender: function(t, r, index) {
            return parseInt(index) + 1
          }
        },
        {
          title: '业务名称',
          align: 'center',
          dataIndex: 'businessName'
        },
        {
          title: '业务编码',
          align: 'center',
          dataIndex: 'businessCode'
        },
        {
          title: '编码前缀',
          align: 'center',
          dataIndex: 'prefix'
        },
        {
          title: '年份编码格式',
          align: 'center',
          dataIndex: 'yearFormat'
        },
        {
          title: '月份编码格式',
          align: 'center',
          dataIndex: 'monthFormat'
        },
        {
          title: '天编码格式',
          align: 'center',
          dataIndex: 'dayFormat'
        },
        {
          title: '序号长度',
          align: 'center',
          dataIndex: 'seqLength'
        },
        {
          title: '操作',
          dataIndex: 'action',
          align: 'center',
          scopedSlots: { customRender: 'action' }
        }
      ],
      url: {
        list: '/sys/sysBusinessCodeRule/list',
        delete: '/sys/sysBusinessCodeRule/delete',
        deleteBatch: '/sys/sysBusinessCodeRule/deleteBatch',
      }
    }
  },
  computed: {
  },
  methods: {}
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
src/views/system/SysParamsList.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,214 @@
<template>
  <a-card :bordered="false">
    <!-- æŸ¥è¯¢åŒºåŸŸ -->
    <div class="table-page-search-wrapper">
      <a-form layout="inline" @keyup.enter.native="searchQuery">
        <a-row :gutter="24">
          <a-col :xl="6" :lg="7" :md="8" :sm="24">
            <a-form-item label="参数名称">
              <a-input placeholder="请输入参数名称" v-model="queryParam.settingName"/>
            </a-form-item>
          </a-col>
          <a-col :xl="6" :lg="7" :md="8" :sm="24">
            <span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
              <a-button type="primary" @click="searchQuery" icon="search">查询</a-button>
            </span>
          </a-col>
        </a-row>
      </a-form>
    </div>
    <!-- æŸ¥è¯¢åŒºåŸŸ-END -->
    <!-- æ“ä½œæŒ‰é’®åŒºåŸŸ -->
    <!-- <div class="table-operator">
      <a-button @click="handleAdd" type="primary" icon="plus">新增</a-button>
      <a-button type="primary" icon="download" @click="handleExportXls('系统参数表')">导出</a-button>
      <a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader" :action="importExcelUrl" @change="handleImportExcel">
        <a-button type="primary" icon="import">导入</a-button>
      </a-upload>
      <a-dropdown v-if="selectedRowKeys.length > 0">
        <a-menu slot="overlay">
          <a-menu-item key="1" @click="batchDel"><a-icon type="delete"/>删除</a-menu-item>
        </a-menu>
        <a-button style="margin-left: 8px"> æ‰¹é‡æ“ä½œ <a-icon type="down" /></a-button>
      </a-dropdown>
    </div> -->
    <!-- table区域-begin -->
    <div>
      <!-- <div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
        <i class="anticon anticon-info-circle ant-alert-icon"></i> å·²é€‰æ‹© <a style="font-weight: 600">{{ selectedRowKeys.length }}</a>项
        <a style="margin-left: 24px" @click="onClearSelected">清空</a>
      </div> -->
      <a-table
        ref="table"
        size="middle"
        bordered
        rowKey="id"
        :columns="columns"
        :dataSource="dataSource"
        :pagination="ipagination"
        :loading="loading"
        class="j-table-force-nowrap"
        @change="handleTableChange">
        <span slot="rowIndex" slot-scope="text, record, index">
          {{(ipagination.current-1)*ipagination.pageSize+index+1}}
        </span>
        <template slot="htmlSlot" slot-scope="text">
          <div v-html="text"></div>
        </template>
        <template slot="imgSlot" slot-scope="text">
          <span v-if="!text" style="font-size: 12px;font-style: italic;">无图片</span>
          <img v-else :src="getImgView(text)" height="25px" alt="" style="max-width:80px;font-size: 12px;font-style: italic;"/>
        </template>
        <template slot="fileSlot" slot-scope="text">
          <span v-if="!text" style="font-size: 12px;font-style: italic;">无文件</span>
          <a-button
            v-else
            :ghost="true"
            type="primary"
            icon="download"
            size="small"
            @click="uploadFile(text)">
            ä¸‹è½½
          </a-button>
        </template>
        <span slot="action" slot-scope="text, record">
         <a @click="handleEdit(record)">编辑</a>
         <!--   <a-divider type="vertical" />
          <a-dropdown>
            <a class="ant-dropdown-link">更多 <a-icon type="down" /></a>
            <a-menu slot="overlay">
              <a-menu-item>
                <a-popconfirm title="确定删除吗?" @confirm="() => handleDelete(record.id)">
                  <a>删除</a>
                </a-popconfirm>
              </a-menu-item>
            </a-menu>
          </a-dropdown> -->
          <template>
        <!-- <div v-if="record.settingValue=='OPEN'">
          <a-switch @click="edit(record)" checked-children="开" un-checked-children="关" default-checked />
        </div>
        <div v-else>
          <a-switch @click="edit(record)" checked-children="开" un-checked-children="关"  />
        </div> -->
      </template>
        </span>
        <!-- å­—符串超长截取省略号显示-->
        <span slot="settingValue" slot-scope="text">
          <j-ellipsis :value="text"/>
        </span>
      </a-table>
    </div>
    <sysParams-modal ref="modalForm" @ok="modalFormOk"></sysParams-modal>
  </a-card>
</template>
<script>
  import { httpAction } from '@/api/manage'
  import '@/assets/less/TableExpand.less'
  import { mixinDevice } from '@/utils/mixin'
  import { JeecgListMixin } from '@/mixins/JeecgListMixin'
  import SysParamsModal from './modules/SysParamsModal'
  import JDictSelectTag from '../../components/dict/JDictSelectTag.vue'
  export default {
    name: "SysParamsList",
    mixins:[JeecgListMixin, mixinDevice],
    components: {
      JDictSelectTag,
      SysParamsModal,
    },
    data () {
      return {
        description: '系统参数表管理页面',
        // è¡¨å¤´
        columns: [
          {
            title: '#',
            dataIndex: '',
            key:'rowIndex',
            width:60,
            align:"center",
            scopedSlots: { customRender: 'rowIndex' }
          },
          {
            title:'参数名称',
            align:"center",
            dataIndex: 'settingName'
          },
          {
            title:'参数键',
            align:"center",
            dataIndex: 'settingKey'
          },
          {
            title:'参数值',
            align:"center",
            dataIndex: 'settingValue',
            key: 'settingValue',
            scopedSlots: { customRender: 'settingValue' }
          },
          {
            title:'备注',
            align:"center",
            dataIndex: 'remark'
          },
          {
            title: '操作',
            dataIndex: 'action',
            align:"center",
            // fixed:"right",
            width:147,
            scopedSlots: { customRender: 'action' }
          }
        ],
        url: {
          list: "/system/sysParams/list",
          delete: "/system/sysParams/delete",
          deleteBatch: "/system/sysParams/deleteBatch",
          exportXlsUrl: "/system/sysParams/exportXls",
          importExcelUrl: "system/sysParams/importExcel",
          edit: "/system/sysParams/edit",
        },
        dictOptions:{},
      }
    },
    computed: {
      importExcelUrl: function(){
        return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`;
      },
    },
    methods: {
      initDictConfig(){
      },
      edit(sysParams) {
        if(sysParams.settingValue == "CLOSE"){
          sysParams.settingValue = "OPEN";
        }else{
          sysParams.settingValue = "CLOSE";
        }
      const that = this;
        httpAction("/system/sysParams/edit",sysParams,'put').then((res)=>{
        if(res.success){
        }else{
          that.$message.warning(res.message);
        }
      }).finally(() => {
        that.confirmLoading = false;
      })
    },
    }
  }
</script>
<style scoped>
  @import '~@assets/less/common.less';
</style>
src/views/system/modules/SysBusinessCodeRuleModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,138 @@
<template>
  <j-modal
    :title="title"
    :width="800"
    :visible="visible"
    :confirmLoading="confirmLoading"
    switchFullscreen
    @ok="handleOk"
    @cancel="handleCancel"
    cancelText="关闭">
    <a-spin :spinning="confirmLoading">
      <a-form-model ref="form" :model="model" :rules="validatorRules">
        <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="businessName" label="业务名称">
          <a-input placeholder="请输入业务名称" v-model="model.businessName" />
        </a-form-model-item>
        <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="businessCode" label="业务编码">
          <a-input placeholder="请输入业务编码" v-model="model.businessCode" :disabled="editable" />
        </a-form-model-item>
        <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="prefix" label="编码前缀">
          <a-input placeholder="请输入编码前缀" v-model="model.prefix" />
        </a-form-model-item>
        <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="yearFormat" label="年份编码格式">
          <a-input placeholder="参考日期年份编码格式" v-model="model.yearFormat" />
        </a-form-model-item>
        <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="monthFormat" label="月份编码格式">
          <a-input placeholder="参考日期月份编码格式" v-model="model.monthFormat" />
        </a-form-model-item>
        <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="dayFormat" label="天编码格式">
          <a-input placeholder="参考日期天的编码格式" v-model="model.dayFormat" />
        </a-form-model-item>
        <a-form-model-item :labelCol="labelCol" :wrapperCol="wrapperCol" prop="seqLength" label="序号长度">
          <a-input-number v-model="model.seqLength" :min="1" :max="10" :precision="0" />
        </a-form-model-item>
      </a-form-model>
    </a-spin>
  </j-modal>
</template>
<script>
import { httpAction } from '@/api/manage'
import { validateDuplicateValue } from '@/utils/util'
export default {
  name: 'SysBusinessCodeRuleModal',
  data() {
    return {
      title: '操作',
      visible: false,
      editable: false,
      model: {},
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 16 }
      },
      confirmLoading: false,
      validatorRules: {
        businessName: [
          { required: true, message: '请输入业务名称!' }
        ],
        businessCode: [
          { required: true, message: '请输入业务编码!' },
          { validator: (rule, value, callback) => validateDuplicateValue('sys_business_code_rule', 'business_code', value, this.model.id, callback) }
        ],
        seqLength: [
          { required: true, message: '请输入序号长度!' }
        ]
      },
      url: {
        add: '/sys/sysBusinessCodeRule/add',
        edit: '/sys/sysBusinessCodeRule/edit'
      }
    }
  },
  created() {
  },
  methods: {
    add() {
      this.model = {};
      this.model.seqLength = 4;
      this.editable = false;
      this.visible = true
    },
    edit(record) {
      this.editable = true;
      this.model = Object.assign({}, record)
      this.visible = true
    },
    close() {
      this.$emit('close')
      this.visible = false
      this.$refs.form.clearValidate()
    },
    handleOk() {
      const that = this
      // è§¦å‘表单验证
      this.$refs.form.validate(valid => {
        if (valid) {
          that.confirmLoading = true
          let httpurl = ''
          let method = ''
          if (!this.model.id) {
            httpurl += this.url.add
            method = 'post'
          } else {
            httpurl += this.url.edit
            method = 'put'
          }
          httpAction(httpurl, this.model, method).then((res) => {
            if (res.success) {
              that.$message.success(res.message)
              that.$emit('ok')
            } else {
              that.$message.warning(res.message)
            }
          }).finally(() => {
            that.confirmLoading = false
            that.close()
          })
        } else {
          return false
        }
      })
    },
    handleCancel() {
      this.close()
    }
  }
}
</script>
<style lang="less" scoped>
</style>
src/views/system/modules/SysParamsModal.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,124 @@
<template>
  <j-modal
    :title="title"
    :width="width"
    :visible="visible"
    :confirmLoading="confirmLoading"
    switchFullscreen
    @ok="handleOk"
    @cancel="handleCancel"
    cancelText="关闭">
    <a-spin :spinning="confirmLoading">
      <a-form :form="form">
        <a-form-item label="参数键" :labelCol="labelCol" :wrapperCol="wrapperCol">
          <a-input disabled v-decorator="['settingKey']" placeholder="请输入参数键"></a-input>
        </a-form-item>
        <a-form-item label="参数值" :labelCol="labelCol" :wrapperCol="wrapperCol">
          <a-input v-decorator="['settingValue']" placeholder="请输入参数值"></a-input>
        </a-form-item>
        <a-form-item label="备注" :labelCol="labelCol" :wrapperCol="wrapperCol">
          <a-textarea disabled v-decorator="['remark']" rows="4" placeholder="请输入备注"/>
        </a-form-item>
      </a-form>
    </a-spin>
  </j-modal>
</template>
<script>
  import { httpAction } from '@/api/manage'
  import pick from 'lodash.pick'
  import { validateDuplicateValue } from '@/utils/util'
  export default {
    name: "SysParamsModal",
    components: {
    },
    data () {
      return {
        form: this.$form.createForm(this),
        title:"操作",
        width:800,
        visible: false,
        model: {},
        labelCol: {
          xs: { span: 24 },
          sm: { span: 5 },
        },
        wrapperCol: {
          xs: { span: 24 },
          sm: { span: 16 },
        },
        confirmLoading: false,
        validatorRules: {
        },
        url: {
          add: "/system/sysParams/add",
          edit: "/system/sysParams/edit",
        }
      }
    },
    created () {
    },
    methods: {
      add () {
        this.edit({});
      },
      edit (record) {
        this.form.resetFields();
        this.model = Object.assign({}, record);
        this.visible = true;
        this.$nextTick(() => {
          this.form.setFieldsValue(pick(this.model,'settingKey','settingValue','remark'))
        })
      },
      close () {
        this.$emit('close');
        this.visible = false;
      },
      handleOk () {
        const that = this;
        // è§¦å‘表单验证
        this.form.validateFields((err, values) => {
          if (!err) {
            that.confirmLoading = true;
            let httpurl = '';
            let method = '';
            if(!this.model.id){
              httpurl+=this.url.add;
              method = 'post';
            }else{
              httpurl+=this.url.edit;
               method = 'put';
            }
            let formData = Object.assign(this.model, values);
            console.log("表单提交数据",formData)
            httpAction(httpurl,formData,method).then((res)=>{
              if(res.success){
                that.$message.success(res.message);
                that.$emit('ok');
              }else{
                that.$message.warning(res.message);
              }
            }).finally(() => {
              that.confirmLoading = false;
              that.close();
            })
          }
        })
      },
      handleCancel () {
        this.close()
      },
      popupCallback(row){
        this.form.setFieldsValue(pick(row,'settingKey','settingValue','remark'))
      },
    }
  }
</script>
vue.config.js
@@ -107,13 +107,13 @@
       },*/
      /* æ³¨æ„ï¼šjeecgboot前端做了改造,此处不需要配置跨域和后台接口(只需要改.env相关配置文件即可)
          issues/3462 å¾ˆå¤šäººæ­¤å¤„做了配置,导致刷新前端404问题,请一定注意*/
      '/api': {
        target: 'http://192.168.124.118:9989',
      '/jeecg-boot': {
        target: 'http://localhost:9989',
        ws: false,
        changeOrigin: true,
        pathRewrite: {
          '^/api': ''
        }
        changeOrigin: true
        // pathRewrite: {
        //   '^/api': ''
        // }
      }
    }
  },