From 5e440a7dc434c43eb828fa62cf9c12b0078b8565 Mon Sep 17 00:00:00 2001 From: 疯狂的狮子Li <15040126243@163.com> Date: 星期一, 20 一月 2025 11:36:18 +0800 Subject: [PATCH] !173 发布 5.3.0-BETA 公测版本 Merge pull request !173 from 疯狂的狮子Li/dev --- src/store/modules/dict.ts | 55 src/api/system/dept/index.ts | 15 src/layout/index.vue | 2 src/views/system/tenant/index.vue | 28 src/views/system/user/authRole.vue | 4 src/views/monitor/logininfor/index.vue | 4 src/views/monitor/operlog/index.vue | 61 src/views/monitor/operlog/oper-info-dialog.vue | 111 + src/store/modules/permission.ts | 5 src/views/workflow/leave/leaveEdit.vue | 70 src/components/Process/approvalRecord.vue | 224 ++ src/layout/components/TopBar/search.vue | 2 src/views/system/tenantPackage/index.vue | 2 src/views/workflow/processDefinition/index.vue | 600 +++--- src/components/ImageUpload/index.vue | 4 src/views/workflow/leave/index.vue | 68 src/views/workflow/task/myDocument.vue | 140 src/api/system/dept/types.ts | 12 src/views/system/oss/index.vue | 4 src/components/Breadcrumb/index.vue | 40 .env.development | 2 src/lang/zh_CN.ts | 62 src/directive/permission/index.ts | 2 src/views/tool/gen/index.vue | 24 src/utils/validate.ts | 12 src/components/TopNav/index.vue | 2 src/components/Process/submitVerify.vue | 226 +- src/views/system/role/index.vue | 7 src/views/system/oss/config.vue | 6 src/assets/styles/variables.module.scss | 54 src/lang/en_US.ts | 59 src/api/workflow/task/index.ts | 140 - src/views/system/menu/index.vue | 2 src/views/workflow/task/allTaskWaiting.vue | 273 +-- vite.config.ts | 10 src/components/Process/processMeddle.vue | 207 ++ src/views/system/dict/data.vue | 4 src/views/system/user/profile/onlineDevice.vue | 2 src/views/tool/gen/importTable.vue | 25 vite/plugins/index.ts | 2 src/views/system/dept/index.vue | 4 src/store/modules/tagsView.ts | 18 src/api/login.ts | 14 src/assets/styles/element-ui.scss | 1 src/layout/components/TagsView/index.vue | 8 src/components/UserSelect/index.vue | 10 src/permission.ts | 14 src/views/system/user/profile/resetPwd.vue | 2 src/layout/components/AppMain.vue | 15 src/utils/sse.ts | 7 src/views/index.vue | 2 src/api/workflow/definition/index.ts | 170 ++ src/views/workflow/category/index.vue | 194 +- src/api/workflow/workflowCommon/index.ts | 32 src/api/workflow/definition/types.ts | 31 src/api/workflow/instance/index.ts | 101 + src/views/register.vue | 81 src/views/workflow/processInstance/index.vue | 359 ++- src/views/system/role/authUser.vue | 2 src/plugins/tab.ts | 2 src/router/index.ts | 25 src/views/system/post/index.vue | 4 src/utils/request.ts | 2 src/api/workflow/task/types.ts | 67 src/api/workflow/workflowCommon/types.ts | 15 src/api/workflow/instance/types.ts | 26 README.md | 1 src/lang/index.ts | 10 tsconfig.json | 2 src/plugins/cache.ts | 2 src/views/system/notice/index.vue | 4 src/views/workflow/processDefinition/design.vue | 46 src/components/FileUpload/index.vue | 5 src/views/system/dict/index.vue | 17 src/views/system/config/index.vue | 6 src/api/workflow/category/types.ts | 71 src/layout/components/Navbar.vue | 43 src/api/monitor/online/index.ts | 4 src/views/workflow/task/taskFinish.vue | 99 src/api/workflow/category/index.ts | 27 eslint.config.js | 86 + src/utils/websocket.ts | 8 src/views/system/role/selectUser.vue | 2 src/layout/components/Sidebar/SidebarItem.vue | 6 src/views/system/client/index.vue | 2 src/views/demo/tree/index.vue | 2 src/views/monitor/online/index.vue | 2 src/views/workflow/task/taskCopyList.vue | 59 src/api/system/user/index.ts | 4 src/types/module.d.ts | 22 /dev/null | 6 src/views/system/user/index.vue | 60 src/views/workflow/task/taskWaiting.vue | 97 src/views/login.vue | 78 src/components/RoleSelect/index.vue | 2 src/views/demo/demo/index.vue | 2 package.json | 58 src/api/system/tenant/index.ts | 2 98 files changed, 2,935 insertions(+), 1,678 deletions(-) diff --git a/.env.development b/.env.development index 14e1335..fa845e7 100644 --- a/.env.development +++ b/.env.development @@ -11,7 +11,7 @@ VITE_APP_CONTEXT_PATH = '/' # 鐩戞帶鍦板潃 -VITE_APP_MONITOR_ADMIN = 'http://localhost:9090/admin/applications' +VITE_APP_MONITOR_ADMIN = 'http://localhost:9090/applications' # SnailJob 鎺у埗鍙板湴鍧� VITE_APP_SNAILJOB_ADMIN = 'http://localhost:8800/snail-job' diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index e74db40..0000000 --- a/.eslintignore +++ /dev/null @@ -1,17 +0,0 @@ -*.sh -node_modules -*.md -*.woff -*.ttf -.vscode -.idea -dist -/public -/docs -.husky -.local -/bin -.eslintrc.cjs -prettier.config.js -src/assets -tailwind.config.js diff --git a/.eslintrc.cjs b/.eslintrc.cjs deleted file mode 100644 index 6042c39..0000000 --- a/.eslintrc.cjs +++ /dev/null @@ -1,51 +0,0 @@ -module.exports = { - env: { - browser: true, - node: true, - es6: true - }, - parser: 'vue-eslint-parser', - extends: [ - 'plugin:vue/vue3-recommended', - './.eslintrc-auto-import.json', - 'plugin:@typescript-eslint/recommended', - 'prettier', - 'plugin:prettier/recommended' - ], - parserOptions: { - ecmaVersion: '2020', - sourceType: 'module', - project: './tsconfig.*?.json', - parser: '@typescript-eslint/parser' - }, - plugins: ['vue', '@typescript-eslint', 'import', 'promise', 'node', 'prettier'], - rules: { - '@typescript-eslint/no-empty-function': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-unused-vars': 'off', - '@typescript-eslint/no-this-alias': 'off', - - // vue - 'vue/multi-word-component-names': 'off', - 'vue/valid-define-props': 'off', - 'vue/no-v-model-argument': 'off', - 'prefer-rest-params': 'off', - // prettier - 'prettier/prettier': 'error', - '@typescript-eslint/ban-types': [ - 'error', - { - // 鍏抽棴绌虹被鍨嬫鏌� {} - extendDefaults: true, - types: { - '{}': false, - Function: false - } - } - ] - }, - globals: { - DialogOption: 'readonly', - OptionType: 'readonly' - } -}; diff --git a/README.md b/README.md index 010adb9..531f64b 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ - 鏈粨搴撲负鍓嶇鎶�鏈爤 [Vue3](https://v3.cn.vuejs.org) + [TS](https://www.typescriptlang.org/) + [Element Plus](https://element-plus.org/zh-CN) + [Vite](https://cn.vitejs.dev) 鐗堟湰銆� - 鎴愬憳椤圭洰: 鍩轰簬 vben(ant-design-vue) 鐨勫墠绔」鐩� [ruoyi-plus-vben](https://gitee.com/dapppp/ruoyi-plus-vben) +- 鎴愬憳椤圭洰: 鍩轰簬 vben5(ant-design-vue) 鐨勫墠绔」鐩� [ruoyi-plus-vben5](https://gitee.com/dapppp/ruoyi-plus-vben5) - 閰嶅鍚庣浠g爜浠撳簱鍦板潃 - [RuoYi-Vue-Plus 5.X(娉ㄦ剰鐗堟湰鍙�)](https://gitee.com/dromara/RuoYi-Vue-Plus) - [RuoYi-Cloud-Plus 2.X(娉ㄦ剰鐗堟湰鍙�)](https://gitee.com/dromara/RuoYi-Cloud-Plus) diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..8b67e9e --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,86 @@ +import globals from 'globals'; +import pluginJs from '@eslint/js'; +import tseslint from 'typescript-eslint'; +import pluginVue from 'eslint-plugin-vue'; +import { readFile } from 'node:fs/promises'; +import prettier from 'eslint-plugin-prettier'; + +/** + * https://blog.csdn.net/sayUonly/article/details/123482912 + * 鑷姩瀵煎叆鐨勯厤缃� + */ +const autoImportFile = new URL('./.eslintrc-auto-import.json', import.meta.url); +const autoImportGlobals = JSON.parse(await readFile(autoImportFile, 'utf8')); + +/** @type {import('eslint').Linter.Config[]} */ +export default [ + { + /** + * 涓嶉渶瑕�.eslintignore鏂囦欢 鑰屾槸鍦ㄨ繖閲岄厤缃� + */ + ignores: [ + '*.sh', + 'node_modules', + '*.md', + '*.woff', + '*.ttf', + '.vscode', + '.idea', + 'dist', + '/public', + '/docs', + '.husky', + '.local', + '/bin', + '.eslintrc.cjs', + 'prettier.config.js', + 'src/assets', + 'tailwind.config.js' + ] + }, + { files: ['**/*.{js,mjs,cjs,ts,vue}'] }, + { + languageOptions: { + globals: globals.browser + } + }, + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + ...pluginVue.configs['flat/essential'], + { + files: ['**/*.vue'], + languageOptions: { + parserOptions: { + parser: tseslint.parser + } + } + }, + { + languageOptions: { + globals: { + // 鑷姩瀵煎叆鐨勯厤缃� undef + ...autoImportGlobals.globals, + DialogOption: 'readonly', + LayoutSetting: 'readonly' + } + }, + plugins: { prettier }, + rules: { + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/no-this-alias': 'off', + + // vue + 'vue/multi-word-component-names': 'off', + 'vue/valid-define-props': 'off', + 'vue/no-v-model-argument': 'off', + 'prefer-rest-params': 'off', + // prettier + 'prettier/prettier': 'error', + // 鍏佽浣跨敤绌篛bject绫诲瀷 {} + '@typescript-eslint/no-empty-object-type': 'off', + '@typescript-eslint/no-unused-expressions': 'off' + } + } +]; diff --git a/package.json b/package.json index e67d60f..caac7c0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { + "$schema": "https://json.schemastore.org/tsconfig", "name": "ruoyi-vue-plus", - "version": "5.2.3", + "version": "5.3.0-BETA", "description": "RuoYi-Vue-Plus澶氱鎴风鐞嗙郴缁�", "author": "LionLi", "license": "MIT", @@ -10,7 +11,8 @@ "build:prod": "vite build --mode production", "build:dev": "vite build --mode development", "preview": "vite preview", - "lint:eslint": "eslint --fix --ext .ts,.js,.vue ./src ", + "lint:eslint": "eslint", + "lint:eslint:fix": "eslint --fix", "prettier": "prettier --write ." }, "repository": { @@ -21,71 +23,65 @@ "@element-plus/icons-vue": "2.3.1", "@highlightjs/vue-plugin": "2.1.0", "@vueup/vue-quill": "1.2.0", - "@vueuse/core": "10.9.0", + "@vueuse/core": "11.3.0", "animate.css": "4.1.1", "await-to-js": "3.0.0", - "axios": "1.6.8", - "bpmn-js": "16.4.0", + "axios": "1.7.8", "crypto-js": "4.2.0", "diagram-js": "12.3.0", "didi": "9.0.2", "echarts": "5.5.0", - "element-plus": "2.7.8", + "element-plus": "2.8.8", "file-saver": "2.0.5", "fuse.js": "7.0.0", "highlight.js": "11.9.0", - "image-conversion": "^2.1.1", + "image-conversion": "2.1.1", "js-cookie": "3.0.5", "jsencrypt": "3.3.2", "nprogress": "0.2.0", - "pinia": "2.1.7", + "pinia": "2.2.6", "screenfull": "6.0.2", - "vue": "3.4.34", + "vue": "3.5.13", "vue-cropper": "1.1.1", - "vue-i18n": "9.10.2", - "vue-router": "4.3.2", - "vue-types": "5.1.1", + "vue-i18n": "10.0.5", + "vue-json-pretty": "2.4.0", + "vue-router": "4.4.5", + "vue-types": "5.1.3", "vxe-table": "4.5.22" }, "devDependencies": { - "@iconify/json": "2.2.201", - "@intlify/unplugin-vue-i18n": "3.0.1", + "@eslint/js": "9.15.0", + "@iconify/json": "2.2.276", "@types/crypto-js": "4.2.2", "@types/file-saver": "2.0.7", "@types/js-cookie": "3.0.6", "@types/node": "18.18.2", "@types/nprogress": "0.2.3", - "@typescript-eslint/eslint-plugin": "7.3.1", - "@typescript-eslint/parser": "7.3.1", - "@unocss/preset-attributify": "0.58.6", - "@unocss/preset-icons": "0.58.6", - "@unocss/preset-uno": "0.58.6", + "@unocss/preset-attributify": "0.64.1", + "@unocss/preset-icons": "0.64.1", + "@unocss/preset-uno": "0.64.1", "@vitejs/plugin-vue": "5.0.4", "@vue/compiler-sfc": "3.4.23", "autoprefixer": "10.4.18", - "eslint": "8.57.0", - "eslint-config-prettier": "9.1.0", - "eslint-define-config": "2.1.0", - "eslint-plugin-prettier": "5.1.3", - "eslint-plugin-promise": "6.1.1", - "eslint-plugin-node": "11.1.0", - "eslint-plugin-import": "2.29.1", - "eslint-plugin-vue": "9.23.0", + "eslint": "9.15.0", + "eslint-plugin-prettier": "^5.2.1", + "eslint-plugin-vue": "9.31.0", "fast-glob": "3.3.2", + "globals": "15.12.0", "postcss": "8.4.36", "prettier": "3.2.5", "sass": "1.72.0", - "typescript": "5.4.5", - "unocss": "0.58.6", + "typescript": "5.7.2", + "typescript-eslint": "8.16.0", + "unocss": "0.64.1", "unplugin-auto-import": "0.17.5", "unplugin-icons": "0.18.5", "unplugin-vue-components": "0.26.0", "unplugin-vue-setup-extend-plus": "1.0.1", - "vite": "5.2.12", + "vite": "5.4.11", "vite-plugin-compression": "0.5.1", "vite-plugin-svg-icons": "2.0.1", "vitest": "1.5.0", - "vue-eslint-parser": "9.4.2", "vue-tsc": "2.0.13" } } diff --git a/src/api/login.ts b/src/api/login.ts index c7c291e..35e6a4e 100644 --- a/src/api/login.ts +++ b/src/api/login.ts @@ -51,10 +51,12 @@ * 娉ㄩ攢 */ export function logout() { - request({ - url: '/resource/sse/close', - method: 'get' - }); + if (import.meta.env.VITE_APP_SSE === 'true') { + request({ + url: '/resource/sse/close', + method: 'get' + }); + } return request({ url: '/auth/logout', method: 'post' @@ -100,11 +102,11 @@ } // 鑾峰彇绉熸埛鍒楄〃 -export function getTenantList(): AxiosPromise<TenantInfo> { +export function getTenantList(isToken: boolean): AxiosPromise<TenantInfo> { return request({ url: '/auth/tenant/list', headers: { - isToken: false + isToken: isToken }, method: 'get' }); diff --git a/src/api/monitor/online/index.ts b/src/api/monitor/online/index.ts index 7484702..5b3221c 100644 --- a/src/api/monitor/online/index.ts +++ b/src/api/monitor/online/index.ts @@ -30,7 +30,7 @@ // 鍒犻櫎褰撳墠鍦ㄧ嚎璁惧 export function delOnline(tokenId: string) { return request({ - url: '/monitor/online/' + tokenId, - method: 'post' + url: '/monitor/online/myself/' + tokenId, + method: 'delete' }); } diff --git a/src/api/system/dept/index.ts b/src/api/system/dept/index.ts index 7e097fd..f16cb2c 100644 --- a/src/api/system/dept/index.ts +++ b/src/api/system/dept/index.ts @@ -1,6 +1,6 @@ import request from '@/utils/request'; import { AxiosPromise } from 'axios'; -import { DeptForm, DeptQuery, DeptVO } from './types'; +import {DeptForm, DeptQuery, DeptTreeVO, DeptVO} from './types'; // 鏌ヨ閮ㄩ棬鍒楄〃 export const listDept = (query?: DeptQuery) => { @@ -8,6 +8,17 @@ url: '/system/dept/list', method: 'get', params: query + }); +}; + +/** + * 閫氳繃deptIds鏌ヨ閮ㄩ棬 + * @param deptIds + */ +export const optionSelect = (deptIds: (number | string)[]): AxiosPromise<DeptVO[]> => { + return request({ + url: '/system/dept/optionselect?deptIds=' + deptIds, + method: 'get' }); }; @@ -28,7 +39,7 @@ }; // 鏌ヨ閮ㄩ棬涓嬫媺鏍戠粨鏋� -export const treeselect = (): AxiosPromise<DeptVO[]> => { +export const treeselect = (): AxiosPromise<DeptTreeVO[]> => { return request({ url: '/system/dept/treeselect', method: 'get' diff --git a/src/api/system/dept/types.ts b/src/api/system/dept/types.ts index 494745c..adaefd2 100644 --- a/src/api/system/dept/types.ts +++ b/src/api/system/dept/types.ts @@ -29,6 +29,18 @@ } /** + * 閮ㄩ棬绫诲瀷 + */ +export interface DeptTreeVO extends BaseEntity { + id: number | string; + label: string; + parentId: number | string; + weight: number; + children: DeptTreeVO[]; + disabled: boolean; +} + +/** * 閮ㄩ棬琛ㄥ崟绫诲瀷 */ export interface DeptForm { diff --git a/src/api/system/tenant/index.ts b/src/api/system/tenant/index.ts index 7b7b93f..d1d8ff8 100644 --- a/src/api/system/tenant/index.ts +++ b/src/api/system/tenant/index.ts @@ -96,6 +96,6 @@ export function syncTenantDict() { return request({ url: '/system/tenant/syncTenantDict', - method: 'get', + method: 'get' }); } diff --git a/src/api/system/user/index.ts b/src/api/system/user/index.ts index 25c7884..0867c48 100644 --- a/src/api/system/user/index.ts +++ b/src/api/system/user/index.ts @@ -1,4 +1,4 @@ -import { DeptVO } from './../dept/types'; +import {DeptTreeVO, DeptVO} from './../dept/types'; import { RoleVO } from '@/api/system/role/types'; import request from '@/utils/request'; import { AxiosPromise } from 'axios'; @@ -202,7 +202,7 @@ /** * 鏌ヨ閮ㄩ棬涓嬫媺鏍戠粨鏋� */ -export const deptTreeSelect = (): AxiosPromise<DeptVO[]> => { +export const deptTreeSelect = (): AxiosPromise<DeptTreeVO[]> => { return request({ url: '/system/user/deptTree', method: 'get' diff --git a/src/api/workflow/category/index.ts b/src/api/workflow/category/index.ts index e9723b0..b6a83ea 100644 --- a/src/api/workflow/category/index.ts +++ b/src/api/workflow/category/index.ts @@ -1,6 +1,6 @@ import request from '@/utils/request'; import { AxiosPromise } from 'axios'; -import { CategoryVO, CategoryForm, CategoryQuery } from '@/api/workflow/category/types'; +import { CategoryVO, CategoryForm, CategoryQuery, CategoryTreeVO } from '@/api/workflow/category/types'; /** * 鏌ヨ娴佺▼鍒嗙被鍒楄〃 @@ -18,11 +18,11 @@ /** * 鏌ヨ娴佺▼鍒嗙被璇︾粏 - * @param id + * @param categoryId */ -export const getCategory = (id: string | number): AxiosPromise<CategoryVO> => { +export const getCategory = (categoryId: string | number): AxiosPromise<CategoryVO> => { return request({ - url: '/workflow/category/' + id, + url: '/workflow/category/' + categoryId, method: 'get' }); }; @@ -53,11 +53,24 @@ /** * 鍒犻櫎娴佺▼鍒嗙被 - * @param id + * @param categoryId */ -export const delCategory = (id: string | number | Array<string | number>) => { +export const delCategory = (categoryId: string | number | Array<string | number>) => { return request({ - url: '/workflow/category/' + id, + url: '/workflow/category/' + categoryId, method: 'delete' }); }; + +/** + * 鑾峰彇娴佺▼鍒嗙被鏍戝垪琛� + * @param query 娴佺▼瀹炰緥id + * @returns + */ +export const categoryTree = (query?: CategoryForm): AxiosPromise<CategoryTreeVO[]> => { + return request({ + url: `/workflow/category/categoryTree`, + method: 'get', + params: query + }); +}; diff --git a/src/api/workflow/category/types.ts b/src/api/workflow/category/types.ts index 414fa55..a093073 100644 --- a/src/api/workflow/category/types.ts +++ b/src/api/workflow/category/types.ts @@ -1,18 +1,16 @@ +export interface CategoryTreeVO { + id: number | string; + label: string; + parentId: number | string; + weight: number; + children: CategoryTreeVO[]; +} export interface CategoryVO { - /** - * 涓婚敭 - */ - id: string; /** - * 鍒嗙被鍚嶇О + * 娴佺▼鍒嗙被ID */ - categoryName: string; - - /** - * 鍒嗙被缂栫爜 - */ - categoryCode: string; + categoryId: string | number; /** * 鐖剁骇id @@ -20,48 +18,55 @@ parentId: string | number; /** - * 鎺掑簭 + * 娴佺▼鍒嗙被鍚嶇О */ - sortNum: number; + categoryName: string; - children?: CategoryVO[]; + /** + * 鏄剧ず椤哄簭 + */ + orderNum: number; + + /** + * 鍒涘缓鏃堕棿 + */ + createTime: string; + + /** + * 瀛愬璞� + */ + children: CategoryVO[]; } export interface CategoryForm extends BaseEntity { - /** - * 涓婚敭 - */ - id?: string | number; /** - * 鍒嗙被鍚嶇О + * 娴佺▼鍒嗙被ID + */ + categoryId?: string | number; + + /** + * 娴佺▼鍒嗙被鍚嶇О */ categoryName?: string; /** - * 鍒嗙被缂栫爜 - */ - categoryCode?: string; - - /** - * 鐖剁骇id + * 鐖舵祦绋嬪垎绫籭d */ parentId?: string | number; /** - * 鎺掑簭 + * 鏄剧ず椤哄簭 */ - sortNum?: number; + orderNum?: number; + } -export interface CategoryQuery extends PageQuery { +export interface CategoryQuery { + /** - * 鍒嗙被鍚嶇О + * 娴佺▼鍒嗙被鍚嶇О */ categoryName?: string; - /** - * 鍒嗙被缂栫爜 - */ - categoryCode?: string; } diff --git a/src/api/workflow/definition/index.ts b/src/api/workflow/definition/index.ts new file mode 100644 index 0000000..49e6ee8 --- /dev/null +++ b/src/api/workflow/definition/index.ts @@ -0,0 +1,170 @@ +import request from '@/utils/request'; +import { FlowDefinitionQuery, definitionXmlVO, FlowDefinitionForm, FlowDefinitionVo } from '@/api/workflow/definition/types'; +import { AxiosPromise } from 'axios'; + +/** + * 鑾峰彇娴佺▼瀹氫箟鍒楄〃 + * @param query 娴佺▼瀹炰緥id + * @returns + */ +export const listDefinition = (query: FlowDefinitionQuery): AxiosPromise<FlowDefinitionVo[]> => { + return request({ + url: `/workflow/definition/list`, + method: 'get', + params: query + }); +}; + +/** + * 鏌ヨ鏈彂甯冪殑娴佺▼瀹氫箟鍒楄〃 + * @param query 娴佺▼瀹炰緥id + * @returns + */ +export const unPublishList = (query: FlowDefinitionQuery): AxiosPromise<FlowDefinitionVo[]> => { + return request({ + url: `/workflow/definition/unPublishList`, + method: 'get', + params: query + }); +}; + +/** + * 閫氳繃娴佺▼瀹氫箟id鑾峰彇xml + * @param definitionId 娴佺▼瀹氫箟id + * @returns + */ +export const definitionXml = (definitionId: string): AxiosPromise<definitionXmlVO> => { + return request({ + url: `/workflow/definition/definitionXml/${definitionId}`, + method: 'get' + }); +}; + +/** + * 鍒犻櫎娴佺▼瀹氫箟 + * @param id 娴佺▼瀹氫箟id + * @returns + */ +export const deleteDefinition = (id: string | string[]) => { + return request({ + url: `/workflow/definition/${id}`, + method: 'delete' + }); +}; + +/** + * 鎸傝捣/婵�娲� + * @param definitionId 娴佺▼瀹氫箟id + * @param activityStatus 鐘舵�� + * @returns + */ +export const active = (definitionId: string, activityStatus: boolean) => { + return request({ + url: `/workflow/definition/active/${definitionId}`, + method: 'put', + params: { + active: activityStatus + } + }); +}; + +/** + * 閫氳繃zip鎴杧ml閮ㄧ讲娴佺▼瀹氫箟 + * @returns + */ +export function importDef(data: any) { + return request({ + url: '/workflow/definition/importDef', + method: 'post', + data: data, + headers: { + repeatSubmit: false + } + }); +} + +/** + * 鍙戝竷娴佺▼瀹氫箟 + * @param id 娴佺▼瀹氫箟id + * @returns + */ +export const publish = (id: string) => { + return request({ + url: `/workflow/definition/publish/${id}`, + method: 'put' + }); +}; + +/** + * 鍙栨秷鍙戝竷娴佺▼瀹氫箟 + * @param id 娴佺▼瀹氫箟id + * @returns + */ +export const unPublish = (id: string) => { + return request({ + url: `/workflow/definition/unPublish/${id}`, + method: 'put' + }); +}; + +/** + * 鑾峰彇娴佺▼瀹氫箟xml瀛楃涓� + * @param id 娴佺▼瀹氫箟id + * @returns + */ +export const xmlString = (id: string) => { + return request({ + url: `/workflow/definition/xmlString/${id}`, + method: 'get' + }); +}; + +/** + * 鏂板 + * @param data 鍙傛暟 + * @returns + */ +export const add = (data: FlowDefinitionForm) => { + return request({ + url: `/workflow/definition`, + method: 'post', + data: data + }); +}; + +/** + * 淇敼 + * @param data 鍙傛暟 + * @returns + */ +export const edit = (data: FlowDefinitionForm) => { + return request({ + url: `/workflow/definition`, + method: 'put', + data: data + }); +}; + +/** + * 鏌ヨ璇︽儏 + * @param id 鍙傛暟 + * @returns + */ +export const getInfo = (id: number | string) => { + return request({ + url: `/workflow/definition/${id}`, + method: 'get' + }); +}; + +/** + * 澶嶅埗娴佺▼瀹氫箟 + * @param id 娴佺▼瀹氫箟id + * @returns + */ +export const copy = (id: string) => { + return request({ + url: `/workflow/definition/copy/${id}`, + method: 'post' + }); +}; diff --git a/src/api/workflow/definition/types.ts b/src/api/workflow/definition/types.ts new file mode 100644 index 0000000..5de7f77 --- /dev/null +++ b/src/api/workflow/definition/types.ts @@ -0,0 +1,31 @@ +export interface FlowDefinitionQuery extends PageQuery { + flowCode?: string; + flowName?: string; + category: string | number; + isPublish?: number; +} + +export interface FlowDefinitionVo { + id: string; + flowName: string; + flowCode: string; + formPath: string; + version: string; + isPublish: number; + activityStatus: number; + createTime: Date; + updateTime: Date; +} + +export interface FlowDefinitionForm { + id: string; + flowName: string; + flowCode: string; + category: string; + formPath: string; +} + +export interface definitionXmlVO { + xml: string[]; + xmlStr: string; +} diff --git a/src/api/workflow/definitionConfig/index.ts b/src/api/workflow/definitionConfig/index.ts deleted file mode 100644 index d34bf05..0000000 --- a/src/api/workflow/definitionConfig/index.ts +++ /dev/null @@ -1,49 +0,0 @@ -import request from '@/utils/request'; -import { AxiosPromise } from 'axios'; -import { DefinitionConfigVO, DefinitionConfigForm } from '@/api/workflow/definitionConfig/types'; - -/** - * 鏌ヨ琛ㄥ崟閰嶇疆璇︾粏 - * @param definitionId - */ -export const getByDefId = (definitionId: string | number): AxiosPromise<DefinitionConfigVO> => { - return request({ - url: '/workflow/definitionConfig/getByDefId/' + definitionId, - method: 'get' - }); -}; - -/** - * 鏂板琛ㄥ崟閰嶇疆 - * @param data - */ -export const saveOrUpdate = (data: DefinitionConfigForm) => { - return request({ - url: '/workflow/definitionConfig/saveOrUpdate', - method: 'post', - data: data - }); -}; - -/** - * 鍒犻櫎琛ㄥ崟閰嶇疆 - * @param id - */ -export const deldefinitionConfig = (id: string | number | Array<string | number>) => { - return request({ - url: '/workflow/definitionConfig/' + id, - method: 'delete' - }); -}; - -/** - * 鏌ヨ娴佺▼瀹氫箟閰嶇疆鎺掗櫎褰撳墠鏌ヨ鐨勬祦绋嬪畾涔� - * @param tableName - * @param definitionId - */ -export const getByTableNameNotDefId = (tableName: string, definitionId: string | number) => { - return request({ - url: `/workflow/definitionConfig/getByTableNameNotDefId/${tableName}/${definitionId}`, - method: 'get' - }); -}; diff --git a/src/api/workflow/definitionConfig/types.ts b/src/api/workflow/definitionConfig/types.ts deleted file mode 100644 index 7627403..0000000 --- a/src/api/workflow/definitionConfig/types.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { FormManageVO } from '@/api/workflow/formManage/types'; - -export interface DefinitionConfigVO { - /** - * 涓婚敭 - */ - id: string | number; - - /** - * 琛ㄥ悕 - */ - tableName?: string; - - /** - * 娴佺▼瀹氫箟ID - */ - definitionId: string | number; - - /** - * 娴佺▼KEY - */ - processKey: string; - - /** - * 娴佺▼鐗堟湰 - */ - version?: string | number; - - /** - * 澶囨敞 - */ - remark: string; - - /** - * 琛ㄥ崟绠$悊 - */ - wfFormManageVo: FormManageVO; -} - -export interface DefinitionConfigForm extends BaseEntity { - /** - * 涓婚敭 - */ - id?: string | number; - - /** - * 琛ㄥ悕 - */ - tableName?: string; - - /** - * 娴佺▼瀹氫箟ID - */ - definitionId?: string | number; - - /** - * 娴佺▼KEY - */ - processKey?: string; - - /** - * 娴佺▼鐗堟湰 - */ - version?: string | number; - - /** - * 澶囨敞 - */ - remark?: string; - - /** - * 琛ㄥ崟绠$悊 - */ - wfFormManageVo?: FormManageVO; -} - -export interface DefinitionConfigQuery extends PageQuery { - /** - * 琛ㄥ悕 - */ - tableName?: string; - - /** - * 娴佺▼瀹氫箟ID - */ - definitionId?: string | number; - - /** - * 娴佺▼KEY - */ - processKey?: string; - - /** - * 娴佺▼鐗堟湰 - */ - version?: string | number; - - /** - * 琛ㄥ崟绠$悊 - */ - wfFormManageVo: FormManageVO; -} diff --git a/src/api/workflow/formManage/index.ts b/src/api/workflow/formManage/index.ts deleted file mode 100644 index 6c5ec60..0000000 --- a/src/api/workflow/formManage/index.ts +++ /dev/null @@ -1,76 +0,0 @@ -import request from '@/utils/request'; -import { AxiosPromise } from 'axios'; -import { FormManageVO, FormManageForm, FormManageQuery } from '@/api/workflow/formManage/types'; - -/** - * 鏌ヨ琛ㄥ崟绠$悊鍒楄〃 - * @param query - * @returns {*} - */ - -export const listFormManage = (query?: FormManageQuery): AxiosPromise<FormManageVO[]> => { - return request({ - url: '/workflow/formManage/list', - method: 'get', - params: query - }); -}; - -/** - * 鏌ヨ琛ㄥ崟绠$悊鍒楄〃 - * @param query - * @returns {*} - */ - -export const selectListFormManage = (): AxiosPromise<FormManageVO[]> => { - return request({ - url: '/workflow/formManage/list/selectList', - method: 'get' - }); -}; - -/** - * 鏌ヨ琛ㄥ崟绠$悊璇︾粏 - * @param id - */ -export const getFormManage = (id: string | number): AxiosPromise<FormManageVO> => { - return request({ - url: '/workflow/formManage/' + id, - method: 'get' - }); -}; - -/** - * 鏂板琛ㄥ崟绠$悊 - * @param data - */ -export const addFormManage = (data: FormManageForm) => { - return request({ - url: '/workflow/formManage', - method: 'post', - data: data - }); -}; - -/** - * 淇敼琛ㄥ崟绠$悊 - * @param data - */ -export const updateFormManage = (data: FormManageForm) => { - return request({ - url: '/workflow/formManage', - method: 'put', - data: data - }); -}; - -/** - * 鍒犻櫎琛ㄥ崟绠$悊 - * @param id - */ -export const delFormManage = (id: string | number | Array<string | number>) => { - return request({ - url: '/workflow/formManage/' + id, - method: 'delete' - }); -}; diff --git a/src/api/workflow/formManage/types.ts b/src/api/workflow/formManage/types.ts deleted file mode 100644 index b9dc1d8..0000000 --- a/src/api/workflow/formManage/types.ts +++ /dev/null @@ -1,69 +0,0 @@ -export interface FormManageVO { - /** - * 涓婚敭 - */ - id: string | number; - - /** - * 琛ㄥ崟鍚嶇О - */ - formName: string; - - /** - * 琛ㄥ崟绫诲瀷 - */ - formType: string; - /** - * 琛ㄥ崟绫诲瀷鍚嶇О - */ - formTypeName: string; - - /** - * 璺敱鍦板潃/琛ㄥ崟ID - */ - router: string; - - /** - * 澶囨敞 - */ - remark: string; -} - -export interface FormManageForm extends BaseEntity { - /** - * 涓婚敭 - */ - id?: string | number; - - /** - * 琛ㄥ崟鍚嶇О - */ - formName?: string; - - /** - * 琛ㄥ崟绫诲瀷 - */ - formType?: string; - - /** - * 璺敱鍦板潃/琛ㄥ崟ID - */ - router?: string; - - /** - * 澶囨敞 - */ - remark?: string; -} - -export interface FormManageQuery extends PageQuery { - /** - * 琛ㄥ崟鍚嶇О - */ - formName?: string; - - /** - * 琛ㄥ崟绫诲瀷 - */ - formType?: string; -} diff --git a/src/api/workflow/instance/index.ts b/src/api/workflow/instance/index.ts new file mode 100644 index 0000000..42d748d --- /dev/null +++ b/src/api/workflow/instance/index.ts @@ -0,0 +1,101 @@ +import request from '@/utils/request'; +import { FlowInstanceQuery, FlowInstanceVO } from '@/api/workflow/instance/types'; +import { AxiosPromise } from 'axios'; + +/** + * 鏌ヨ杩愯涓疄渚嬪垪琛� + * @param query + * @returns {*} + */ +export const pageByRunning = (query: FlowInstanceQuery): AxiosPromise<FlowInstanceVO[]> => { + return request({ + url: '/workflow/instance/pageByRunning', + method: 'get', + params: query + }); +}; + +/** + * 鏌ヨ宸插畬鎴愬疄渚嬪垪琛� + * @param query + * @returns {*} + */ +export const pageByFinish = (query: FlowInstanceQuery): AxiosPromise<FlowInstanceVO[]> => { + return request({ + url: '/workflow/instance/pageByFinish', + method: 'get', + params: query + }); +}; + +/** + * 閫氳繃涓氬姟id鑾峰彇鍘嗗彶娴佺▼鍥� + */ +export const flowImage = (businessId: string | number) => { + return request({ + url: `/workflow/instance/flowImage/${businessId}` + '?t' + Math.random(), + method: 'get' + }); +}; + +/** + * 鍒嗛〉鏌ヨ褰撳墠鐧诲綍浜哄崟鎹� + * @param query + * @returns {*} + */ +export const pageByCurrent = (query: FlowInstanceQuery): AxiosPromise<FlowInstanceVO[]> => { + return request({ + url: '/workflow/instance/pageByCurrent', + method: 'get', + params: query + }); +}; + +/** + * 鎾ら攢娴佺▼ + * @param data 鍙傛暟 + * @returns + */ +export const cancelProcessApply = (data: any) => { + return request({ + url: `/workflow/instance/cancelProcessApply`, + method: 'put', + data: data + }); +}; + +/** + * 鑾峰彇娴佺▼鍙橀噺 + * @param instanceId 瀹炰緥id + * @returns + */ +export const instanceVariable = (instanceId: string | number) => { + return request({ + url: `/workflow/instance/instanceVariable/${instanceId}`, + method: 'get' + }); +}; + +/** + * 鍒犻櫎 + * @param instanceIds 娴佺▼瀹炰緥id + * @returns + */ +export const deleteByInstanceIds = (instanceIds: Array<string | number> | string | number) => { + return request({ + url: `/workflow/instance/deleteByInstanceIds/${instanceIds}`, + method: 'delete' + }); +}; +/** + * 浣滃簾娴佺▼ + * @param data 鍙傛暟 + * @returns + */ +export const invalid = (data: any) => { + return request({ + url: `/workflow/instance/invalid`, + method: 'post', + data: data + }); +}; diff --git a/src/api/workflow/instance/types.ts b/src/api/workflow/instance/types.ts new file mode 100644 index 0000000..a12dab3 --- /dev/null +++ b/src/api/workflow/instance/types.ts @@ -0,0 +1,26 @@ +import { FlowTaskVO } from '@/api/workflow/task/types'; + +export interface FlowInstanceQuery extends PageQuery { + category?: string | number; + nodeName?: string; + flowCode?: string; + flowName?: string; + createByIds?: string[] | number[]; + businessId?: string; +} + +export interface FlowInstanceVO extends BaseEntity { + id: string | number; + definitionId: string; + flowName: string; + flowCode: string; + version: string; + businessId: string; + activityStatus: number; + tenantId: string; + createTime: string; + createBy: string; + flowStatus: string; + flowStatusName: string; + flowTaskList: FlowTaskVO[]; +} diff --git a/src/api/workflow/model/index.ts b/src/api/workflow/model/index.ts deleted file mode 100644 index 1ca8b19..0000000 --- a/src/api/workflow/model/index.ts +++ /dev/null @@ -1,104 +0,0 @@ -import request from '@/utils/request'; -import { AxiosPromise } from 'axios'; -import { ModelForm, ModelQuery, ModelVO } from '@/api/workflow/model/types'; - -/** - * 鏌ヨ妯″瀷鍒楄〃 - * @param query - * @returns {*} - */ -export const listModel = (query: ModelQuery): AxiosPromise<ModelVO[]> => { - return request({ - url: '/workflow/model/list', - method: 'get', - params: query - }); -}; - -/** - * 鏌ヨ妯″瀷淇℃伅 - * @param query - * @returns {*} - */ -export const getInfo = (id: string): AxiosPromise<ModelForm> => { - return request({ - url: '/workflow/model/getInfo/' + id, - method: 'get' - }); -}; - -/** - * 鏂板妯″瀷 - * @param data - * @returns {*} - */ -export const addModel = (data: ModelForm): AxiosPromise<void> => { - return request({ - url: '/workflow/model/save', - method: 'post', - data: data - }); -}; - -/** - * 淇敼妯″瀷淇℃伅 - * @param data - * @returns {*} - */ -export function update(data: ModelForm): AxiosPromise<void> { - return request({ - url: '/workflow/model/update', - method: 'put', - data: data - }); -} - -/** - * 淇敼妯″瀷淇℃伅 - * @param data - * @returns {*} - */ -export function editModelXml(data: ModelForm): AxiosPromise<void> { - return request({ - url: '/workflow/model/editModelXml', - method: 'put', - data: data - }); -} - -/** - * 鎸塱d鍒犻櫎妯″瀷 - * @returns {*} - * @param id 妯″瀷id - */ -export function delModel(id: string | string[]): AxiosPromise<void> { - return request({ - url: '/workflow/model/' + id, - method: 'delete' - }); -} - -/** - * 妯″瀷閮ㄧ讲 - * @returns {*} - * @param id 妯″瀷id - */ -export const modelDeploy = (id: string): AxiosPromise<void> => { - return request({ - url: `/workflow/model/modelDeploy/${id}`, - method: 'post' - }); -}; - -/** - * 澶嶅埗妯″瀷 - * @param data - * @returns {*} - */ -export const copyModel = (data: ModelForm): AxiosPromise<void> => { - return request({ - url: '/workflow/model/copyModel', - method: 'post', - data: data - }); -}; diff --git a/src/api/workflow/model/types.ts b/src/api/workflow/model/types.ts deleted file mode 100644 index 77f947d..0000000 --- a/src/api/workflow/model/types.ts +++ /dev/null @@ -1,66 +0,0 @@ -export interface ModelForm { - id: string; - name: string; - key: string; - categoryCode: string; - xml: string; - svg: string; - description: string; -} - -export interface ModelQuery extends PageQuery { - name?: string; - key?: string; - categoryCode?: string; -} - -export interface OriginalPersistentState { - metaInfo: string; - editorSourceValueId: string; - createTime: string; - deploymentId?: string; - name: string; - tenantId: string; - category?: string; - version: number; - editorSourceExtraValueId?: string; - key: string; - lastUpdateTime: string; -} - -export interface PersistentState { - metaInfo: string; - editorSourceValueId: string; - createTime: string; - deploymentId?: string; - name: string; - tenantId: string; - category?: string; - version: number; - editorSourceExtraValueId?: string; - key: string; - lastUpdateTime: string; -} - -export interface ModelVO { - id: string; - revision: number; - originalPersistentState: OriginalPersistentState; - name: string; - key: string; - category?: string; - createTime: string; - lastUpdateTime: string; - version: number; - metaInfo: string; - deploymentId?: string; - editorSourceValueId: string; - editorSourceExtraValueId?: string; - tenantId: string; - persistentState: PersistentState; - revisionNext: number; - idPrefix: string; - inserted: boolean; - updated: boolean; - deleted: boolean; -} diff --git a/src/api/workflow/nodeConfig/types.ts b/src/api/workflow/nodeConfig/types.ts deleted file mode 100644 index a55fc91..0000000 --- a/src/api/workflow/nodeConfig/types.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { FormManageVO } from '@/api/workflow/formManage/types'; - -export interface NodeConfigVO { - /** - * 涓婚敭 - */ - id: string | number; - - /** - * 琛ㄥ崟id - */ - formId: string | number; - - /** - * 琛ㄥ崟绫诲瀷 - */ - formType: string; - - /** - * 鑺傜偣鍚嶇О - */ - nodeName: string; - - /** - * 鑺傜偣id - */ - nodeId: string | number; - - /** - * 娴佺▼瀹氫箟id - */ - definitionId: string | number; - - /** - * 琛ㄥ崟绠$悊 - */ - wfFormManageVo: FormManageVO; -} diff --git a/src/api/workflow/processDefinition/index.ts b/src/api/workflow/processDefinition/index.ts deleted file mode 100644 index c063120..0000000 --- a/src/api/workflow/processDefinition/index.ts +++ /dev/null @@ -1,114 +0,0 @@ -import request from '@/utils/request'; -import { ProcessDefinitionQuery, ProcessDefinitionVO, definitionXmlVO } from '@/api/workflow/processDefinition/types'; -import { AxiosPromise } from 'axios'; - -/** - * 鑾峰彇娴佺▼瀹氫箟鍒楄〃 - * @param query 娴佺▼瀹炰緥id - * @returns - */ -export const listProcessDefinition = (query: ProcessDefinitionQuery): AxiosPromise<ProcessDefinitionVO[]> => { - return request({ - url: `/workflow/processDefinition/list`, - method: 'get', - params: query - }); -}; -/** - * 鎸夌収娴佺▼瀹氫箟key鑾峰彇娴佺▼瀹氫箟 - * @param processInstanceId 娴佺▼瀹炰緥id - * @returns - */ -export const getListByKey = (key: string) => { - return request({ - url: `/workflow/processDefinition/getListByKey/${key}`, - method: 'get' - }); -}; - -/** - * 閫氳繃娴佺▼瀹氫箟id鑾峰彇娴佺▼鍥� - */ -export const definitionImage = (processDefinitionId: string): AxiosPromise<any> => { - return request({ - url: `/workflow/processDefinition/definitionImage/${processDefinitionId}` + '?t' + Math.random(), - method: 'get' - }); -}; - -/** - * 閫氳繃娴佺▼瀹氫箟id鑾峰彇xml - * @param processDefinitionId 娴佺▼瀹氫箟id - * @returns - */ -export const definitionXml = (processDefinitionId: string): AxiosPromise<definitionXmlVO> => { - return request({ - url: `/workflow/processDefinition/definitionXml/${processDefinitionId}`, - method: 'get' - }); -}; - -/** - * 鍒犻櫎娴佺▼瀹氫箟 - * @param deploymentId 閮ㄧ讲id - * @param processDefinitionId 娴佺▼瀹氫箟id - * @returns - */ -export const deleteProcessDefinition = (deploymentId: string | string[], processDefinitionId: string | string[]) => { - return request({ - url: `/workflow/processDefinition/${deploymentId}/${processDefinitionId}`, - method: 'delete' - }); -}; - -/** - * 鎸傝捣/婵�娲� - * @param processDefinitionId 娴佺▼瀹氫箟id - * @returns - */ -export const updateDefinitionState = (processDefinitionId: string) => { - return request({ - url: `/workflow/processDefinition/updateDefinitionState/${processDefinitionId}`, - method: 'put' - }); -}; - -/** - * 娴佺▼瀹氫箟杞崲涓烘ā鍨� - * @param processDefinitionId 娴佺▼瀹氫箟id - * @returns - */ -export const convertToModel = (processDefinitionId: string) => { - return request({ - url: `/workflow/processDefinition/convertToModel/${processDefinitionId}`, - method: 'put' - }); -}; - -/** - * 閫氳繃zip鎴杧ml閮ㄧ讲娴佺▼瀹氫箟 - * @returns - */ -export function deployProcessFile(data: any) { - return request({ - url: '/workflow/processDefinition/deployByFile', - method: 'post', - data: data, - headers: { - repeatSubmit: false - } - }); -} - -/** - * 杩佺Щ娴佺▼ - * @param currentProcessDefinitionId - * @param fromProcessDefinitionId - * @returns - */ -export const migrationDefinition = (currentProcessDefinitionId: string, fromProcessDefinitionId: string) => { - return request({ - url: `/workflow/processDefinition/migrationDefinition/${currentProcessDefinitionId}/${fromProcessDefinitionId}`, - method: 'put' - }); -}; diff --git a/src/api/workflow/processDefinition/types.ts b/src/api/workflow/processDefinition/types.ts deleted file mode 100644 index 979ec25..0000000 --- a/src/api/workflow/processDefinition/types.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { DefinitionConfigVO } from '@/api/workflow/definitionConfig/types'; -export interface ProcessDefinitionQuery extends PageQuery { - key?: string; - name?: string; - categoryCode?: string; -} - -export interface ProcessDefinitionVO extends BaseEntity { - id: string; - name: string; - key: string; - version: number; - suspensionState: number; - resourceName: string; - diagramResourceName: string; - deploymentId: string; - deploymentTime: string; - wfDefinitionConfigVo: DefinitionConfigVO; -} - -export interface definitionXmlVO { - xml: string[]; - xmlStr: string; -} diff --git a/src/api/workflow/processInstance/index.ts b/src/api/workflow/processInstance/index.ts deleted file mode 100644 index 6d5e53b..0000000 --- a/src/api/workflow/processInstance/index.ts +++ /dev/null @@ -1,136 +0,0 @@ -import request from '@/utils/request'; -import { ProcessInstanceQuery, ProcessInstanceVO } from '@/api/workflow/processInstance/types'; -import { AxiosPromise } from 'axios'; - -/** - * 鏌ヨ杩愯涓疄渚嬪垪琛� - * @param query - * @returns {*} - */ -export const getPageByRunning = (query: ProcessInstanceQuery): AxiosPromise<ProcessInstanceVO[]> => { - return request({ - url: '/workflow/processInstance/getPageByRunning', - method: 'get', - params: query - }); -}; - -/** - * 鏌ヨ宸插畬鎴愬疄渚嬪垪琛� - * @param query - * @returns {*} - */ -export const getPageByFinish = (query: ProcessInstanceQuery): AxiosPromise<ProcessInstanceVO[]> => { - return request({ - url: '/workflow/processInstance/getPageByFinish', - method: 'get', - params: query - }); -}; - -/** - * 閫氳繃涓氬姟id鑾峰彇鍘嗗彶娴佺▼鍥� - */ -export const getHistoryImage = (businessKey: string) => { - return request({ - url: `/workflow/processInstance/getHistoryImage/${businessKey}` + '?t' + Math.random(), - method: 'get' - }); -}; - -/** - * 閫氳繃涓氬姟id鑾峰彇鍘嗗彶娴佺▼鍥捐繍琛屼腑锛屽巻鍙茬瓑鑺傜偣 - */ -export const getHistoryList = (businessKey: string): AxiosPromise<Record<string, any>> => { - return request({ - url: `/workflow/processInstance/getHistoryList/${businessKey}` + '?t' + Math.random(), - method: 'get' - }); -}; - -/** - * 鑾峰彇瀹℃壒璁板綍 - * @param businessKey 涓氬姟id - * @returns - */ -export const getHistoryRecord = (businessKey: string | number) => { - return request({ - url: `/workflow/processInstance/getHistoryRecord/${businessKey}`, - method: 'get' - }); -}; - -/** - * 浣滃簾 - * @param data 鍙傛暟 - * @returns - */ -export const deleteRunInstance = (data: object) => { - return request({ - url: `/workflow/processInstance/deleteRunInstance`, - method: 'post', - data: data - }); -}; - -/** - * 杩愯涓殑瀹炰緥 鍒犻櫎绋嬪疄渚嬶紝鍒犻櫎鍘嗗彶璁板綍锛屽垹闄や笟鍔′笌娴佺▼鍏宠仈淇℃伅 - * @param businessKey 涓氬姟id - * @returns - */ -export const deleteRunAndHisInstance = (businessKey: string | string[]) => { - return request({ - url: `/workflow/processInstance/deleteRunAndHisInstance/${businessKey}`, - method: 'delete' - }); -}; - -/** - * 宸插畬鎴愮殑瀹炰緥 鍒犻櫎绋嬪疄渚嬶紝鍒犻櫎鍘嗗彶璁板綍锛屽垹闄や笟鍔′笌娴佺▼鍏宠仈淇℃伅 - * @param businessKey 涓氬姟id - * @returns - */ -export const deleteFinishAndHisInstance = (businessKey: string | string[]) => { - return request({ - url: `/workflow/processInstance/deleteFinishAndHisInstance/${businessKey}`, - method: 'delete' - }); -}; - -/** - * 鍒嗛〉鏌ヨ褰撳墠鐧诲綍浜哄崟鎹� - * @param query - * @returns {*} - */ -export const getPageByCurrent = (query: ProcessInstanceQuery): AxiosPromise<ProcessInstanceVO[]> => { - return request({ - url: '/workflow/processInstance/getPageByCurrent', - method: 'get', - params: query - }); -}; - -/** - * 鎾ら攢娴佺▼ - * @param businessKey 涓氬姟id - * @returns - */ -export const cancelProcessApply = (businessKey: string) => { - return request({ - url: `/workflow/processInstance/cancelProcessApply/${businessKey}`, - method: 'post' - }); -}; - -export default { - getPageByRunning, - getPageByFinish, - getHistoryImage, - getHistoryList, - getHistoryRecord, - deleteRunInstance, - deleteRunAndHisInstance, - deleteFinishAndHisInstance, - getPageByCurrent, - cancelProcessApply -}; diff --git a/src/api/workflow/processInstance/types.ts b/src/api/workflow/processInstance/types.ts deleted file mode 100644 index 99d0511..0000000 --- a/src/api/workflow/processInstance/types.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { TaskVO } from '@/api/workflow/task/types'; - -export interface ProcessInstanceQuery extends PageQuery { - categoryCode?: string; - name?: string; - key?: string; - startUserId?: string; - businessKey?: string; -} - -export interface ProcessInstanceVO extends BaseEntity { - id: string; - processDefinitionId: string; - processDefinitionName: string; - processDefinitionKey: string; - processDefinitionVersion: string; - deploymentId: string; - businessKey: string; - isSuspended?: any; - tenantId: string; - startTime: string; - endTime?: string; - startUserId: string; - businessStatus: string; - businessStatusName: string; - taskVoList: TaskVO[]; -} diff --git a/src/api/workflow/task/index.ts b/src/api/workflow/task/index.ts index d29de30..55ede45 100644 --- a/src/api/workflow/task/index.ts +++ b/src/api/workflow/task/index.ts @@ -1,15 +1,15 @@ import request from '@/utils/request'; import { AxiosPromise } from 'axios'; -import { TaskQuery, TaskVO } from '@/api/workflow/task/types'; +import { TaskQuery, FlowTaskVO, TaskOperationBo } from '@/api/workflow/task/types'; /** * 鏌ヨ寰呭姙鍒楄〃 * @param query * @returns {*} */ -export const getPageByTaskWait = (query: TaskQuery): AxiosPromise<TaskVO[]> => { +export const pageByTaskWait = (query: TaskQuery): AxiosPromise<FlowTaskVO[]> => { return request({ - url: '/workflow/task/getPageByTaskWait', + url: '/workflow/task/pageByTaskWait', method: 'get', params: query }); @@ -20,9 +20,9 @@ * @param query * @returns {*} */ -export const getPageByTaskFinish = (query: TaskQuery): AxiosPromise<TaskVO[]> => { +export const pageByTaskFinish = (query: TaskQuery): AxiosPromise<FlowTaskVO[]> => { return request({ - url: '/workflow/task/getPageByTaskFinish', + url: '/workflow/task/pageByTaskFinish', method: 'get', params: query }); @@ -33,9 +33,9 @@ * @param query * @returns {*} */ -export const getPageByTaskCopy = (query: TaskQuery): AxiosPromise<TaskVO[]> => { +export const pageByTaskCopy = (query: TaskQuery): AxiosPromise<FlowTaskVO[]> => { return request({ - url: '/workflow/task/getPageByTaskCopy', + url: '/workflow/task/pageByTaskCopy', method: 'get', params: query }); @@ -46,9 +46,9 @@ * @param query * @returns {*} */ -export const getPageByAllTaskWait = (query: TaskQuery): AxiosPromise<TaskVO[]> => { +export const pageByAllTaskWait = (query: TaskQuery): AxiosPromise<FlowTaskVO[]> => { return request({ - url: '/workflow/task/getPageByAllTaskWait', + url: '/workflow/task/pageByAllTaskWait', method: 'get', params: query }); @@ -59,9 +59,9 @@ * @param query * @returns {*} */ -export const getPageByAllTaskFinish = (query: TaskQuery): AxiosPromise<TaskVO[]> => { +export const pageByAllTaskFinish = (query: TaskQuery): AxiosPromise<FlowTaskVO[]> => { return request({ - url: '/workflow/task/getPageByAllTaskFinish', + url: '/workflow/task/pageByAllTaskFinish', method: 'get', params: query }); @@ -94,30 +94,6 @@ }; /** - * 璁ら浠诲姟 - * @param taskId - * @returns {*} - */ -export const claim = (taskId: string): any => { - return request({ - url: '/workflow/task/claim/' + taskId, - method: 'post' - }); -}; - -/** - * 褰掕繕浠诲姟 - * @param taskId - * @returns {*} - */ -export const returnTask = (taskId: string): any => { - return request({ - url: '/workflow/task/returnTask/' + taskId, - method: 'post' - }); -}; - -/** * 浠诲姟椹冲洖 * @param data * @returns {*} @@ -135,61 +111,24 @@ * @param taskId * @returns */ -export const getTaskById = (taskId: string) => { +export const getTask = (taskId: string) => { return request({ - url: '/workflow/task/getTaskById/' + taskId, + url: '/workflow/task/getTask/' + taskId, method: 'get' }); }; /** - * 鍔犵 - * @param data - * @returns - */ -export const addMultiInstanceExecution = (data: any) => { - return request({ - url: '/workflow/task/addMultiInstanceExecution', - method: 'post', - data: data - }); -}; - -/** - * 鍑忕 - * @param data - * @returns - */ -export const deleteMultiInstanceExecution = (data: any) => { - return request({ - url: '/workflow/task/deleteMultiInstanceExecution', - method: 'post', - data: data - }); -}; - -/** * 淇敼浠诲姟鍔炵悊浜� - * @param taskIds + * @param taskIdList * @param userId * @returns */ -export const updateAssignee = (taskIds: Array<string>, userId: string) => { +export const updateAssignee = (taskIdList: Array<string>, userId: string) => { return request({ - url: `/workflow/task/updateAssignee/${taskIds}/${userId}`, - method: 'put' - }); -}; - -/** - * 杞姙浠诲姟 - * @returns - */ -export const transferTask = (data: any) => { - return request({ - url: `/workflow/task/transferTask`, - method: 'post', - data: data + url: `/workflow/task/updateAssignee/${userId}`, + method: 'put', + data: taskIdList }); }; @@ -206,59 +145,36 @@ }; /** - * 鏌ヨ娴佺▼鍙橀噺 - * @returns - */ -export const getInstanceVariable = (taskId: string) => { - return request({ - url: `/workflow/task/getInstanceVariable/${taskId}`, - method: 'get' - }); -}; - -/** * 鑾峰彇鍙┏鍥炲緱浠诲姟鑺傜偣 * @returns */ -export const getTaskNodeList = (processInstanceId: string) => { +export const getBackTaskNode = (definitionId: string, nodeCode: string) => { return request({ - url: `/workflow/task/getTaskNodeList/${processInstanceId}`, + url: `/workflow/task/getBackTaskNode/${definitionId}/${nodeCode}`, method: 'get' }); }; /** - * 濮旀墭浠诲姟 + * 浠诲姟鎿嶄綔 鎿嶄綔绫诲瀷锛屽娲� delegateTask銆佽浆鍔� transferTask銆佸姞绛� addSignature銆佸噺绛� reductionSignature * @returns */ -export const delegateTask = (data: any) => { +export const taskOperation = (data: TaskOperationBo, operation: string) => { return request({ - url: `/workflow/task/delegateTask`, + url: `/workflow/task/taskOperation/${operation}`, method: 'post', data: data }); }; /** - * 鏌ヨ宸ヤ綔娴佷换鍔$敤鎴烽�夋嫨鍔犵浜哄憳 - * @param taskId - * @returns {*} + * 鑾峰彇褰撳墠浠诲姟鍔炵悊浜� + * @param taskId 浠诲姟id + * @returns */ -export const getTaskUserIdsByAddMultiInstance = (taskId: string) => { +export const currentTaskAllUser = (taskId: string | number) => { return request({ - url: '/workflow/task/getTaskUserIdsByAddMultiInstance/' + taskId, - method: 'get' - }); -}; - -/** - * 鏌ヨ宸ヤ綔娴侀�夋嫨鍑忕浜哄憳 - * @param taskId - * @returns {*} - */ -export const getListByDeleteMultiInstance = (taskId: string) => { - return request({ - url: '/workflow/task/getListByDeleteMultiInstance/' + taskId, + url: `/workflow/task/currentTaskAllUser/${taskId}`, method: 'get' }); }; diff --git a/src/api/workflow/task/types.ts b/src/api/workflow/task/types.ts index 0425a1a..8ea803b 100644 --- a/src/api/workflow/task/types.ts +++ b/src/api/workflow/task/types.ts @@ -1,9 +1,8 @@ -import { NodeConfigVO } from '@/api/workflow/nodeConfig/types'; -import { DefinitionConfigVO } from '@/api/workflow/definitionConfig/types'; export interface TaskQuery extends PageQuery { - name?: string; - processDefinitionKey?: string; - processDefinitionName?: string; + nodeName?: string; + flowCode?: string; + flowName?: string; + createByIds?: string[] | number[]; } export interface ParticipantVo { @@ -12,38 +11,38 @@ candidateName: string[]; claim: boolean; } - -export interface TaskVO extends BaseEntity { - id: string; - name: string; - description?: string; - priority: number; - owner?: string; - assignee?: string | number; - assigneeName?: string; - processInstanceId: string; - executionId: string; - taskDefinitionId?: any; - processDefinitionId: string; - endTime?: string; - taskDefinitionKey: string; - dueDate?: string; - category?: any; - parentTaskId?: any; - tenantId: string; - claimTime?: string; - businessStatus?: string; - businessStatusName?: string; - processDefinitionName?: string; - processDefinitionKey?: string; - participantVo?: ParticipantVo; - multiInstance?: boolean; - businessKey?: string; - wfNodeConfigVo?: NodeConfigVO; - wfDefinitionConfigVo?: DefinitionConfigVO; +export interface FlowTaskVO { + id: string | number; + createTime?: Date; + updateTime?: Date; + tenantId?: string; + definitionId?: string; + instanceId: string; + flowName: string; + businessId: string; + nodeCode: string; + nodeName: string; + flowCode: string; + flowStatus: string; + formCustom: string; + formPath: string; + nodeType: number; + nodeRatio: string | number; + version?: string; } export interface VariableVo { key: string; value: string; } + +export interface TaskOperationBo { + //濮旀淳/杞姙浜虹殑鐢ㄦ埛ID锛堝繀濉紝鍑嗗濮旀淳/杞姙浜烘搷浣滐級 + userId?: string; + //鍔犵/鍑忕浜虹殑鐢ㄦ埛ID鍒楄〃锛堝繀濉紝閽堝鍔犵/鍑忕鎿嶄綔锛� + userIds?: string[]; + //浠诲姟ID锛堝繀濉級 + taskId: string | number; + //鎰忚鎴栧娉ㄤ俊鎭紙鍙�夛級 + message?: string; +} diff --git a/src/api/workflow/workflowCommon/index.ts b/src/api/workflow/workflowCommon/index.ts index 63ce318..0f5ce1b 100644 --- a/src/api/workflow/workflowCommon/index.ts +++ b/src/api/workflow/workflowCommon/index.ts @@ -2,28 +2,14 @@ export default { routerJump(routerJumpVo: RouterJumpVo, proxy) { - if (routerJumpVo.wfNodeConfigVo && routerJumpVo.wfNodeConfigVo.formType === 'static' && routerJumpVo.wfNodeConfigVo.wfFormManageVo) { - proxy.$tab.closePage(proxy.$route); - proxy.$router.push({ - path: `${routerJumpVo.wfNodeConfigVo.wfFormManageVo.router}`, - query: { - id: routerJumpVo.businessKey, - type: routerJumpVo.type, - taskId: routerJumpVo.taskId - } - }); - } else if (routerJumpVo.wfNodeConfigVo && routerJumpVo.wfNodeConfigVo.formType === 'dynamic' && routerJumpVo.wfNodeConfigVo.wfFormManageVo) { - proxy.$tab.closePage(proxy.$route); - proxy.$router.push({ - path: `${routerJumpVo.wfNodeConfigVo.wfFormManageVo.router}`, - query: { - id: routerJumpVo.businessKey, - type: routerJumpVo.type, - taskId: routerJumpVo.taskId - } - }); - } else { - proxy?.$modal.msgError('璇峰埌妯″瀷閰嶇疆鑿滃崟锛�'); - } + proxy.$tab.closePage(proxy.$route); + proxy.$router.push({ + path: routerJumpVo.formPath, + query: { + id: routerJumpVo.businessId, + type: routerJumpVo.type, + taskId: routerJumpVo.taskId + } + }); } }; diff --git a/src/api/workflow/workflowCommon/types.ts b/src/api/workflow/workflowCommon/types.ts index 0f1ef1f..3e7a71d 100644 --- a/src/api/workflow/workflowCommon/types.ts +++ b/src/api/workflow/workflowCommon/types.ts @@ -1,16 +1,13 @@ -import { NodeConfigVO } from '@/api/workflow/nodeConfig/types'; -import { DefinitionConfigVO } from '@/api/workflow/definitionConfig/types'; - export interface RouterJumpVo { - wfNodeConfigVo: NodeConfigVO; - wfDefinitionConfigVo: DefinitionConfigVO; - businessKey: string; - taskId: string; + businessId: string; + taskId: string | number; type: string; + formCustom: string; + formPath: string; } export interface StartProcessBo { - businessKey: string | number; - tableName: string; + businessId: string | number; + flowCode: string; variables: any; } diff --git a/src/assets/styles/element-ui.scss b/src/assets/styles/element-ui.scss index 220e4ac..5dd573d 100644 --- a/src/assets/styles/element-ui.scss +++ b/src/assets/styles/element-ui.scss @@ -1,4 +1,3 @@ - .el-collapse { .collapse__title { font-weight: 600; diff --git a/src/assets/styles/variables.module.scss b/src/assets/styles/variables.module.scss index 92fc34d..3aa871b 100644 --- a/src/assets/styles/variables.module.scss +++ b/src/assets/styles/variables.module.scss @@ -14,14 +14,14 @@ --tableHeaderBg: #f8f8f9; --tableHeaderTextColor: #515a6e; - // 宸ヤ綔娴� - --bpmn-panel-border: #eeeeee; - --bpmn-panel-box-shadow: #cccccc; - --bpmn-panel-bar-background-color: #f5f7fa; - // ele - --brder-color: #e8e8e8 + --brder-color: #e8e8e8; + + // 娣诲姞 tag 鐩稿叧鍙橀噺 + --tags-view-active-bg: var(--el-color-primary); + --tags-view-active-border-color: var(--el-color-primary); } + html.dark { --menuBg: #1d1e1f; --menuColor: #bfcbd9; @@ -41,26 +41,40 @@ .el-tree-node__content { --el-color-primary-light-9: #262727; } + + .el-button--primary { + --el-button-bg-color: var(--el-color-primary-dark-6); + --el-button-border-color: var(--el-color-primary-light-2); + } + + .el-switch { + --el-switch-on-color: var(--el-color-primary-dark-6); + --el-switch-border-color: var(--el-color-primary-light-2); + } + + .el-tag--primary { + --el-tag-bg-color: var(--el-color-primary-dark-6); + --el-tag-border-color: var(--el-color-primary-light-2); + } + + // 鍦ㄦ繁鑹叉ā寮忎笅浣跨敤鏇存繁鐨勯鑹� + --tags-view-active-bg: var(--el-color-primary-dark-6); + --tags-view-active-border-color: var(--el-color-primary-light-2); // vxe-table 涓婚 - --vxe-font-color: #98989E; - --vxe-primary-color: #2C7ECF; - --vxe-icon-background-color: #98989E; - --vxe-table-font-color: #98989E; + --vxe-font-color: #98989e; + --vxe-primary-color: #2c7ecf; + --vxe-icon-background-color: #98989e; + --vxe-table-font-color: #98989e; --vxe-table-resizable-color: #95969a; - --vxe-table-header-background-color: #28282A; + --vxe-table-header-background-color: #28282a; --vxe-table-body-background-color: #151518; --vxe-table-background-color: #4a5663; --vxe-table-border-width: 1px; - --vxe-table-border-color: #37373A; - --vxe-toolbar-background-color: #37373A; - - // 宸ヤ綔娴� - --bpmn-panel-border: #37373A; - --bpmn-panel-box-shadow: #37373A; - --bpmn-panel-bar-background-color: #37373A; + --vxe-table-border-color: #37373a; + --vxe-toolbar-background-color: #37373a; // ele - --brder-color: #37373A + --brder-color: #37373a; } // base color @@ -118,4 +132,4 @@ dangerColor: $--color-danger; infoColor: $--color-info; warningColor: $--color-warning; -} +} \ No newline at end of file diff --git a/src/bpmn/assets/defaultXML.ts b/src/bpmn/assets/defaultXML.ts deleted file mode 100644 index dff0349..0000000 --- a/src/bpmn/assets/defaultXML.ts +++ /dev/null @@ -1,23 +0,0 @@ -function generateRandomValue() { - // 鐢熸垚涓�涓殢鏈烘暟 - const randomValue = Math.random().toString(36).slice(2, 12); - return `Process_${randomValue}`; -} - -const cartage: string = 'default'; -export default `<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:bioc="http://bpmn.io/schema/bpmn/biocolor/1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" targetNamespace="http://www.flowable.org/processdef"> - <process id="process_${generateRandomValue()}" name="name_${generateRandomValue()}"> - <startEvent id="startNode1" name="寮�濮�" /> - </process> - <bpmndi:BPMNDiagram id="BPMNDiagram_flow"> - <bpmndi:BPMNPlane id="BPMNPlane_flow" bpmnElement="T-2d89e7a3-ba79-4abd-9f64-ea59621c258c"> - <bpmndi:BPMNShape id="BPMNShape_startNode1" bpmnElement="startNode1" bioc:stroke=""> - <omgdc:Bounds x="240" y="200" width="30" height="30" /> - <bpmndi:BPMNLabel> - <omgdc:Bounds x="242" y="237" width="23" height="14" /> - </bpmndi:BPMNLabel> - </bpmndi:BPMNShape> - </bpmndi:BPMNPlane> - </bpmndi:BPMNDiagram> -</definitions>`; diff --git a/src/bpmn/assets/lang/zh.ts b/src/bpmn/assets/lang/zh.ts deleted file mode 100644 index ee0c5de..0000000 --- a/src/bpmn/assets/lang/zh.ts +++ /dev/null @@ -1,126 +0,0 @@ -export const NodeName = { - 'bpmn:Process': '娴佺▼', - 'bpmn:StartEvent': '寮�濮嬩簨浠�', - 'bpmn:IntermediateThrowEvent': '涓棿浜嬩欢', - 'bpmn:Task': '浠诲姟', - 'bpmn:SendTask': '鍙戦�佷换鍔�', - 'bpmn:ReceiveTask': '鎺ユ敹浠诲姟', - 'bpmn:UserTask': '鐢ㄦ埛浠诲姟', - 'bpmn:ManualTask': '鎵嬪伐浠诲姟', - 'bpmn:BusinessRuleTask': '涓氬姟瑙勫垯浠诲姟', - 'bpmn:ServiceTask': '鏈嶅姟浠诲姟', - 'bpmn:ScriptTask': '鑴氭湰浠诲姟', - 'bpmn:EndEvent': '缁撴潫浜嬩欢', - 'bpmn:SequenceFlow': '娴佺▼绾�', - 'bpmn:ExclusiveGateway': '浜掓枼缃戝叧', - 'bpmn:ParallelGateway': '骞惰缃戝叧', - 'bpmn:InclusiveGateway': '鐩稿缃戝叧', - 'bpmn:ComplexGateway': '澶嶆潅缃戝叧', - 'bpmn:EventBasedGateway': '浜嬩欢缃戝叧', - 'bpmn:Participant': '姹�/鍙備笌鑰�', - 'bpmn:SubProcess': '瀛愭祦绋�', - 'bpmn:DataObjectReference': '鏁版嵁瀵硅薄寮曠敤', - 'bpmn:DataStoreReference': '鏁版嵁瀛樺偍寮曠敤', - 'bpmn:Group': '缁�' -}; - -export default { - 'Activate hand tool': '鍚姩鎵嬪姩宸ュ叿', - 'Activate lasso tool': '鍚姩 Lasso 宸ュ叿', - 'Activate create/remove space tool': '鍚姩鍒涘缓/鍒犻櫎绌洪棿宸ュ叿', - 'Activate global connect tool': '鍚姩鍏ㄥ眬杩炴帴宸ュ叿', - 'Ad-hoc': 'Ad-hoc', - 'Add lane above': '鍦ㄤ笂鏂规坊鍔犳吵閬�', - 'Add lane below': '鍦ㄤ笅鏂规坊鍔犳吵閬�', - 'Business rule task': '瑙勫垯浠诲姟', - 'Call activity': '寮曠敤娴佺▼', - 'Compensation end event': '缁撴潫琛ュ伩浜嬩欢', - 'Compensation intermediate throw event': '涓棿琛ュ伩鎶涘嚭浜嬩欢', - 'Complex gateway': '澶嶆潅缃戝叧', - 'Conditional intermediate catch event': '涓棿鏉′欢鎹曡幏浜嬩欢', - 'Conditional start event (non-interrupting)': '鏉′欢鍚姩浜嬩欢 (闈炰腑鏂�)', - 'Conditional start event': '鏉′欢鍚姩浜嬩欢', - 'Connect using association': '鏂囨湰鍏宠仈', - 'Connect using sequence/message flow or association': '娑堟伅鍏宠仈', - 'Change element': '鏇存敼鍏冪礌', - 'Change type': '鏇存敼绫诲瀷', - 'Create data object reference': '鍒涘缓鏁版嵁瀵硅薄寮曠敤', - 'Create data store reference': '鍒涘缓鏁版嵁瀛樺偍寮曠敤', - 'Create expanded sub-process': '鍒涘缓鍙姌鍙犲瓙娴佺▼', - 'Create pool/participant': '鍒涘缓姹�/鍙備笌鑰�', - 'Collection': '闆嗗悎', - 'Connect using data input association': '鏁版嵁杈撳叆鍏宠仈', - 'Data store reference': '鏁版嵁瀛樺偍寮曠敤', - 'Data object reference': '鏁版嵁瀵硅薄寮曠敤', - 'Divide into two lanes': '鍒嗘垚涓や釜娉抽亾', - 'Divide into three lanes': '鍒嗘垚涓変釜娉抽亾', - 'End event': '缁撴潫浜嬩欢', - 'Error end event': '缁撴潫閿欒浜嬩欢', - 'Escalation end event': '缁撴潫鍗囩骇浜嬩欢', - 'Escalation intermediate throw event': '涓棿鍗囩骇鎶涘嚭浜嬩欢', - 'Event sub-process': '浜嬩欢瀛愭祦绋�', - 'Event-based gateway': '浜嬩欢缃戝叧', - 'Exclusive gateway': '浜掓枼缃戝叧', - 'Empty pool/participant (removes content)': '娓呯┖姹�/鍙備笌鑰� (鍒犻櫎鍐呭)', - 'Empty pool/participant': '娓呯┖姹�/鍙備笌鑰�', - 'Expanded pool/participant': '灞曞紑姹�/鍙備笌鑰�', - 'Inclusive gateway': '鐩稿缃戝叧', - 'Intermediate throw event': '涓棿鎶涘嚭浜嬩欢', - 'Loop': '寰幆', - 'Link intermediate catch event': '涓棿閾炬帴鎹曡幏浜嬩欢', - 'Link intermediate throw event': '涓棿閾炬帴鎶涘嚭浜嬩欢', - 'Manual task': '鎵嬪姩浠诲姟', - 'Message end event': '缁撴潫娑堟伅浜嬩欢', - 'Message intermediate catch event': '涓棿娑堟伅鎹曡幏浜嬩欢', - 'Message intermediate throw event': '涓棿娑堟伅鎶涘嚭浜嬩欢', - 'Message start event': '娑堟伅鍚姩浜嬩欢', - 'Parallel gateway': '骞惰缃戝叧', - 'Parallel multi-instance': '骞惰澶氬疄渚�', - 'Participant multiplicity': '鍙備笌鑰呭閲嶆��', - 'Receive task': '鎺ュ彈浠诲姟', - 'Remove': '绉婚櫎', - 'Script task': '鑴氭湰浠诲姟', - 'Send task': '鍙戦�佷换鍔�', - 'Sequential multi-instance': '涓茶澶氬疄渚�', - 'Service task': '鏈嶅姟浠诲姟', - 'Signal end event': '缁撴潫淇″彿浜嬩欢', - 'Signal intermediate catch event': '涓棿淇″彿鎹曡幏浜嬩欢', - 'Signal intermediate throw event': '涓棿淇″彿鎶涘嚭浜嬩欢', - 'Signal start event (non-interrupting)': '淇″彿鍚姩浜嬩欢 (闈炰腑鏂�)', - 'Signal start event': '淇″彿鍚姩浜嬩欢', - 'Start event': '寮�濮嬩簨浠�', - 'Sub-process (collapsed)': '鍙姌鍙犲瓙娴佺▼', - 'Sub-process (expanded)': '鍙睍寮�瀛愭祦绋�', - 'Sub rocess': '瀛愭祦绋�', - 'Task': '浠诲姟', - 'Transaction': '浜嬪姟', - 'Terminate end event': '缁堟杈圭晫浜嬩欢', - 'Timer intermediate catch event': '涓棿瀹氭椂鎹曡幏浜嬩欢', - 'Timer start event (non-interrupting)': '瀹氭椂鍚姩浜嬩欢 (闈炰腑鏂�)', - 'Timer start event': '瀹氭椂鍚姩浜嬩欢', - 'User task': '鐢ㄦ埛浠诲姟', - 'Create start event': '鍒涘缓寮�濮嬩簨浠�', - 'Create gateway': '鍒涘缓缃戝叧', - 'Create intermediate/boundary event': '鍒涘缓涓棿/杈圭晫浜嬩欢', - 'Create end event': '鍒涘缓缁撴潫浜嬩欢', - 'Create group': '鍒涘缓缁�', - 'Create startEvent': '寮�濮嬭妭鐐�', - 'Create endEvent': '缁撴潫鑺傜偣', - 'Create exclusiveGateway': '浜掓枼缃戝叧', - 'Create parallelGateway': '骞惰缃戝叧', - 'Create task': '浠诲姟鑺傜偣', - 'Create userTask': '鐢ㄦ埛浠诲姟鑺傜偣', - 'Condition type': '鏉′欢绫诲瀷', - 'Append end event': '杩藉姞缁撴潫浜嬩欢鑺傜偣', - 'Append gateway': '杩藉姞缃戝叧鑺傜偣', - 'Append task': '杩藉姞浠诲姟', - 'Append user task': '杩藉姞鐢ㄦ埛浠诲姟鑺傜偣', - 'Append text annotation': '杩藉姞鏂囨湰娉ㄩ噴', - 'Append intermediate/boundary event': '杩藉姞涓棿鎴栬竟鐣屼簨浠�', - 'Append receive task': '杩藉姞鎺ユ敹浠诲姟鑺傜偣', - 'Append message intermediate catch event': '杩藉姞涓棿娑堟伅鎹曡幏浜嬩欢', - 'Append timer intermediate catch event': '杩藉姞涓棿瀹氭椂鎹曡幏浜嬩欢', - 'Append conditional intermediate catch event': '杩藉姞涓棿鏉′欢鎹曡幏浜嬩欢', - 'Append signal intermediate catch event': '杩藉姞涓棿淇″彿鎹曡幏浜嬩欢', - 'flow elements must be children of pools/participants': '娴佺▼鍏冪礌蹇呴』鏄睜/鍙備笌鑰呯殑瀛愬厓绱�' -}; diff --git a/src/bpmn/assets/moddle/flowable.ts b/src/bpmn/assets/moddle/flowable.ts deleted file mode 100644 index de959a6..0000000 --- a/src/bpmn/assets/moddle/flowable.ts +++ /dev/null @@ -1,1250 +0,0 @@ -export default { - 'name': 'Flowable', - 'uri': 'http://flowable.org/bpmn', - 'prefix': 'flowable', - 'xml': { - 'tagAlias': 'lowerCase' - }, - 'associations': [], - 'types': [ - { - 'name': 'flowable:extCandidateUsers', - 'isAbstract': true, - 'extends': [], - 'superClass': ['Element'], - 'meta': { - 'allowedIn': ['*'] - }, - 'properties': [ - { - 'name': 'body', - 'type': 'String', - 'isBody': true - } - ] - }, - { - 'name': 'flowable:extAssignee', - 'isAbstract': true, - 'extends': [], - 'superClass': ['Element'], - 'meta': { - 'allowedIn': ['*'] - }, - 'properties': [ - { - 'name': 'body', - 'type': 'String', - 'isBody': true - } - ] - }, - { - 'name': 'flowable:property', - 'superClass': ['Element'], - 'properties': [ - { - 'name': 'id', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'name', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'value', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'flowable:properties', - 'isAbstract': true, - 'extends': [], - 'superClass': ['Element'], - 'meta': { - 'allowedIn': ['*'] - }, - 'properties': [ - { - 'name': 'values', - 'type': 'flowable:property', - 'isMany': true - } - ] - }, - { - 'name': 'InOutBinding', - 'superClass': ['Element'], - 'isAbstract': true, - 'properties': [ - { - 'name': 'source', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'sourceExpression', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'target', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'businessKey', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'local', - 'isAttr': true, - 'type': 'Boolean', - 'default': false - }, - { - 'name': 'variables', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'In', - 'superClass': ['InOutBinding'], - 'meta': { - 'allowedIn': ['bpmn:CallActivity'] - } - }, - { - 'name': 'Out', - 'superClass': ['InOutBinding'], - 'meta': { - 'allowedIn': ['bpmn:CallActivity'] - } - }, - { - 'name': 'AsyncCapable', - 'isAbstract': true, - 'extends': ['bpmn:Activity', 'bpmn:Gateway', 'bpmn:Event'], - 'properties': [ - { - 'name': 'async', - 'isAttr': true, - 'type': 'Boolean', - 'default': false - }, - { - 'name': 'asyncBefore', - 'isAttr': true, - 'type': 'Boolean', - 'default': false - }, - { - 'name': 'asyncAfter', - 'isAttr': true, - 'type': 'Boolean', - 'default': false - }, - { - 'name': 'exclusive', - 'isAttr': true, - 'type': 'Boolean', - 'default': true - } - ] - }, - { - 'name': 'flowable:in', - 'superClass': ['Element'], - 'properties': [ - { - 'name': 'source', - 'type': 'string', - 'isAttr': true - }, - { - 'name': 'target', - 'type': 'string', - 'isAttr': true - } - ] - }, - { - 'name': 'flowable:out', - 'superClass': ['Element'], - 'properties': [ - { - 'name': 'source', - 'type': 'string', - 'isAttr': true - }, - { - 'name': 'target', - 'type': 'string', - 'isAttr': true - } - ] - }, - { - 'name': 'BoundaryEvent', - 'superClass': ['CatchEvent'], - 'properties': [ - { - 'name': 'cancelActivity', - 'default': true, - 'isAttr': true, - 'type': 'Boolean' - }, - { - 'name': 'attachedToRef', - 'type': 'Activity', - 'isAttr': true, - 'isReference': true - } - ] - }, - { - 'name': 'JobPriorized', - 'isAbstract': true, - 'extends': ['bpmn:Process', 'flowable:AsyncCapable'], - 'properties': [ - { - 'name': 'jobPriority', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'SignalEventDefinition', - 'isAbstract': true, - 'extends': ['bpmn:SignalEventDefinition'], - 'properties': [ - { - 'name': 'async', - 'isAttr': true, - 'type': 'Boolean', - 'default': false - } - ] - }, - { - 'name': 'ErrorEventDefinition', - 'isAbstract': true, - 'extends': ['bpmn:ErrorEventDefinition'], - 'properties': [ - { - 'name': 'errorCodeVariable', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'errorMessageVariable', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'Error', - 'isAbstract': true, - 'extends': ['bpmn:Error'], - 'properties': [ - { - 'name': 'flowable:errorMessage', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'PotentialStarter', - 'superClass': ['Element'], - 'properties': [ - { - 'name': 'resourceAssignmentExpression', - 'type': 'bpmn:ResourceAssignmentExpression' - } - ] - }, - { - 'name': 'UserTask', - 'isAbstract': true, - 'extends': ['bpmn:UserTask'], - 'properties': [ - { - 'name': 'timerEventDefinition', - 'type': 'Expression' - }, - { - 'name': 'multiInstanceLoopCharacteristics', - 'type': 'MultiInstanceLoopCharacteristics' - } - ] - }, - { - 'name': 'StartEvent', - 'isAbstract': true, - 'extends': ['bpmn:StartEvent'], - 'properties': [ - { - 'name': 'timerEventDefinition', - 'type': 'Expression' - } - ] - }, - { - 'name': 'FormSupported', - 'isAbstract': true, - 'extends': ['bpmn:StartEvent', 'bpmn:UserTask'], - 'properties': [ - { - 'name': 'formHandlerClass', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'formKey', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'TemplateSupported', - 'isAbstract': true, - 'extends': ['bpmn:Process', 'bpmn:FlowElement'], - 'properties': [ - { - 'name': 'modelerTemplate', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'Initiator', - 'isAbstract': true, - 'extends': ['bpmn:StartEvent'], - 'properties': [ - { - 'name': 'initiator', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'ScriptTask', - 'isAbstract': true, - 'extends': ['bpmn:ScriptTask'], - 'properties': [ - { - 'name': 'resultVariable', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'resource', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'Process', - 'isAbstract': true, - 'extends': ['bpmn:Process'], - 'properties': [ - { - 'name': 'candidateStarterGroups', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'candidateStarterUsers', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'versionTag', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'historyTimeToLive', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'isStartableInTasklist', - 'isAttr': true, - 'type': 'Boolean', - 'default': true - } - ] - }, - { - 'name': 'EscalationEventDefinition', - 'isAbstract': true, - 'extends': ['bpmn:EscalationEventDefinition'], - 'properties': [ - { - 'name': 'escalationCodeVariable', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'FormalExpression', - 'isAbstract': true, - 'extends': ['bpmn:FormalExpression'], - 'properties': [ - { - 'name': 'resource', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'Assignable', - 'extends': ['bpmn:UserTask'], - 'properties': [ - { - 'name': 'candidateGroups', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'dueDate', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'followUpDate', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'priority', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'CallActivity', - 'extends': ['bpmn:CallActivity'], - 'properties': [ - { - 'name': 'calledElementBinding', - 'isAttr': true, - 'type': 'String', - 'default': 'latest' - }, - { - 'name': 'calledElementVersion', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'calledElementVersionTag', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'calledElementTenantId', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'caseRef', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'caseBinding', - 'isAttr': true, - 'type': 'String', - 'default': 'latest' - }, - { - 'name': 'caseVersion', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'caseTenantId', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'variableMappingClass', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'variableMappingDelegateExpression', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'ServiceTaskLike', - 'extends': ['bpmn:ServiceTask', 'bpmn:BusinessRuleTask', 'bpmn:SendTask', 'bpmn:MessageEventDefinition'], - 'properties': [ - { - 'name': 'expression', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'class', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'delegateExpression', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'resultVariable', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'ExclusiveGateway', - 'isAbstract': true, - 'extends': ['bpmn:ExclusiveGateway'], - 'properties': [ - { - 'name': 'serviceClass', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'DmnCapable', - 'extends': ['bpmn:BusinessRuleTask'], - 'properties': [ - { - 'name': 'decisionRef', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'decisionRefBinding', - 'isAttr': true, - 'type': 'String', - 'default': 'latest' - }, - { - 'name': 'decisionRefVersion', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'mapDecisionResult', - 'isAttr': true, - 'type': 'String', - 'default': 'resultList' - }, - { - 'name': 'decisionRefTenantId', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'ExternalCapable', - 'extends': ['flowable:ServiceTaskLike'], - 'properties': [ - { - 'name': 'type', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'topic', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'TaskPriorized', - 'extends': ['bpmn:Process', 'flowable:ExternalCapable'], - 'properties': [ - { - 'name': 'taskPriority', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'Properties', - 'superClass': ['Element'], - 'meta': { - 'allowedIn': ['*'] - }, - 'properties': [ - { - 'name': 'values', - 'type': 'Property', - 'isMany': true - } - ] - }, - { - 'name': 'Property', - 'superClass': ['Element'], - 'properties': [ - { - 'name': 'id', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'name', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'value', - 'type': 'String', - 'isAttr': true - } - ] - }, - { - 'name': 'Connector', - 'superClass': ['Element'], - 'meta': { - 'allowedIn': ['flowable:ServiceTaskLike'] - }, - 'properties': [ - { - 'name': 'inputOutput', - 'type': 'InputOutput' - }, - { - 'name': 'connectorId', - 'type': 'String' - } - ] - }, - { - 'name': 'InputOutput', - 'superClass': ['Element'], - 'meta': { - 'allowedIn': ['bpmn:FlowNode', 'flowable:Connector'] - }, - 'properties': [ - { - 'name': 'inputOutput', - 'type': 'InputOutput' - }, - { - 'name': 'connectorId', - 'type': 'String' - }, - { - 'name': 'inputParameters', - 'isMany': true, - 'type': 'InputParameter' - }, - { - 'name': 'outputParameters', - 'isMany': true, - 'type': 'OutputParameter' - } - ] - }, - { - 'name': 'InputOutputParameter', - 'properties': [ - { - 'name': 'name', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'value', - 'isBody': true, - 'type': 'String' - }, - { - 'name': 'definition', - 'type': 'InputOutputParameterDefinition' - } - ] - }, - { - 'name': 'InputOutputParameterDefinition', - 'isAbstract': true - }, - { - 'name': 'List', - 'superClass': ['InputOutputParameterDefinition'], - 'properties': [ - { - 'name': 'items', - 'isMany': true, - 'type': 'InputOutputParameterDefinition' - } - ] - }, - { - 'name': 'Map', - 'superClass': ['InputOutputParameterDefinition'], - 'properties': [ - { - 'name': 'entries', - 'isMany': true, - 'type': 'Entry' - } - ] - }, - { - 'name': 'Entry', - 'properties': [ - { - 'name': 'key', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'value', - 'isBody': true, - 'type': 'String' - }, - { - 'name': 'definition', - 'type': 'InputOutputParameterDefinition' - } - ] - }, - { - 'name': 'Value', - 'superClass': ['InputOutputParameterDefinition'], - 'properties': [ - { - 'name': 'id', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'name', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'value', - 'isBody': true, - 'type': 'String' - } - ] - }, - { - 'name': 'Script', - 'superClass': ['InputOutputParameterDefinition'], - 'properties': [ - { - 'name': 'scriptFormat', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'resource', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'value', - 'isBody': true, - 'type': 'String' - } - ] - }, - { - 'name': 'Field', - 'superClass': ['Element'], - 'meta': { - 'allowedIn': ['flowable:ServiceTaskLike', 'flowable:ExecutionListener', 'flowable:TaskListener'] - }, - 'properties': [ - { - 'name': 'name', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'expression', - 'isAttr': true, - 'type': 'expression' - }, - { - 'name': 'string', - 'type': 'string' - }, - { - 'name': 'stringValue', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'string', - 'superClass': ['Element'], - 'meta': { - 'allowedIn': ['flowable:Field'] - }, - 'properties': [ - { - 'name': 'body', - 'isBody': true, - 'type': 'String' - } - ] - }, - { - 'name': 'expression', - 'superClass': ['Element'], - 'meta': { - 'allowedIn': ['flowable:Field'] - }, - 'properties': [ - { - 'name': 'body', - 'isBody': true, - 'type': 'String' - } - ] - }, - { - 'name': 'InputParameter', - 'superClass': ['InputOutputParameter'] - }, - { - 'name': 'OutputParameter', - 'superClass': ['InputOutputParameter'] - }, - { - 'name': 'Collectable', - 'isAbstract': true, - 'extends': ['bpmn:MultiInstanceLoopCharacteristics'], - 'superClass': ['flowable:AsyncCapable'], - 'properties': [ - { - 'name': 'collection', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'elementVariable', - 'isAttr': true, - 'type': 'String' - } - ] - }, - { - 'name': 'SequenceFlow', - 'superClass': ['FlowElement'], - 'properties': [ - { - 'name': 'isImmediate', - 'isAttr': true, - 'type': 'Boolean' - }, - { - 'name': 'conditionExpression', - 'type': 'Expression' - }, - { - 'name': 'sourceRef', - 'type': 'FlowNode', - 'isAttr': true, - 'isReference': true - }, - { - 'name': 'targetRef', - 'type': 'FlowNode', - 'isAttr': true, - 'isReference': true - } - ] - }, - { - 'name': 'MultiInstanceLoopCharacteristics', - 'superClass': ['LoopCharacteristics'], - 'properties': [ - { - 'name': 'isSequential', - 'default': false, - 'isAttr': true, - 'type': 'Boolean' - }, - { - 'name': 'behavior', - 'type': 'MultiInstanceBehavior', - 'default': 'All', - 'isAttr': true - }, - { - 'name': 'loopCardinality', - 'type': 'Expression', - 'xml': { - 'serialize': 'xsi:type' - } - }, - { - 'name': 'loopDataInputRef', - 'type': 'ItemAwareElement', - 'isReference': true - }, - { - 'name': 'loopDataOutputRef', - 'type': 'ItemAwareElement', - 'isReference': true - }, - { - 'name': 'inputDataItem', - 'type': 'DataInput', - 'xml': { - 'serialize': 'property' - } - }, - { - 'name': 'outputDataItem', - 'type': 'DataOutput', - 'xml': { - 'serialize': 'property' - } - }, - { - 'name': 'complexBehaviorDefinition', - 'type': 'ComplexBehaviorDefinition', - 'isMany': true - }, - { - 'name': 'completionCondition', - 'type': 'Expression', - 'xml': { - 'serialize': 'xsi:type' - } - }, - { - 'name': 'oneBehaviorEventRef', - 'type': 'EventDefinition', - 'isAttr': true, - 'isReference': true - }, - { - 'name': 'noneBehaviorEventRef', - 'type': 'EventDefinition', - 'isAttr': true, - 'isReference': true - } - ] - }, - { - 'name': 'FailedJobRetryTimeCycle', - 'superClass': ['Element'], - 'meta': { - 'allowedIn': ['flowable:AsyncCapable', 'bpmn:MultiInstanceLoopCharacteristics'] - }, - 'properties': [ - { - 'name': 'body', - 'isBody': true, - 'type': 'String' - } - ] - }, - { - 'name': 'ExecutionListener', - 'superClass': ['Element'], - 'meta': { - 'allowedIn': [ - 'bpmn:Task', - 'bpmn:ServiceTask', - 'bpmn:UserTask', - 'bpmn:BusinessRuleTask', - 'bpmn:ScriptTask', - 'bpmn:ReceiveTask', - 'bpmn:ManualTask', - 'bpmn:ExclusiveGateway', - 'bpmn:SequenceFlow', - 'bpmn:ParallelGateway', - 'bpmn:InclusiveGateway', - 'bpmn:EventBasedGateway', - 'bpmn:StartEvent', - 'bpmn:IntermediateCatchEvent', - 'bpmn:IntermediateThrowEvent', - 'bpmn:EndEvent', - 'bpmn:BoundaryEvent', - 'bpmn:CallActivity', - 'bpmn:SubProcess', - 'bpmn:Process' - ] - }, - 'properties': [ - { - 'name': 'expression', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'class', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'delegateExpression', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'event', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'script', - 'type': 'Script' - }, - { - 'name': 'fields', - 'type': 'Field', - 'isMany': true - } - ] - }, - { - 'name': 'TaskListener', - 'superClass': ['Element'], - 'meta': { - 'allowedIn': ['bpmn:UserTask'] - }, - 'properties': [ - { - 'name': 'expression', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'class', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'delegateExpression', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'event', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'script', - 'type': 'Script' - }, - { - 'name': 'fields', - 'type': 'Field', - 'isMany': true - } - ] - }, - { - 'name': 'FormProperty', - 'superClass': ['Element'], - 'meta': { - 'allowedIn': ['bpmn:StartEvent', 'bpmn:UserTask'] - }, - 'properties': [ - { - 'name': 'id', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'name', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'type', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'required', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'readable', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'writable', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'variable', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'expression', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'datePattern', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'default', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'values', - 'type': 'Value', - 'isMany': true - } - ] - }, - { - 'name': 'FormData', - 'superClass': ['Element'], - 'meta': { - 'allowedIn': ['bpmn:StartEvent', 'bpmn:UserTask'] - }, - 'properties': [ - { - 'name': 'fields', - 'type': 'FormField', - 'isMany': true - }, - { - 'name': 'businessKey', - 'type': 'String', - 'isAttr': true - } - ] - }, - { - 'name': 'FormField', - 'superClass': ['Element'], - 'properties': [ - { - 'name': 'id', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'label', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'type', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'datePattern', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'defaultValue', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'properties', - 'type': 'Properties' - }, - { - 'name': 'validation', - 'type': 'Validation' - }, - { - 'name': 'values', - 'type': 'Value', - 'isMany': true - } - ] - }, - { - 'name': 'Validation', - 'superClass': ['Element'], - 'properties': [ - { - 'name': 'constraints', - 'type': 'Constraint', - 'isMany': true - } - ] - }, - { - 'name': 'Constraint', - 'superClass': ['Element'], - 'properties': [ - { - 'name': 'name', - 'type': 'String', - 'isAttr': true - }, - { - 'name': 'config', - 'type': 'String', - 'isAttr': true - } - ] - }, - { - 'name': 'ConditionalEventDefinition', - 'isAbstract': true, - 'extends': ['bpmn:ConditionalEventDefinition'], - 'properties': [ - { - 'name': 'variableName', - 'isAttr': true, - 'type': 'String' - }, - { - 'name': 'variableEvent', - 'isAttr': true, - 'type': 'String' - } - ] - } - ], - 'emumerations': [] -}; diff --git a/src/bpmn/assets/module/ContextPad/CustomContextPadProvider.ts b/src/bpmn/assets/module/ContextPad/CustomContextPadProvider.ts deleted file mode 100644 index 13ccf50..0000000 --- a/src/bpmn/assets/module/ContextPad/CustomContextPadProvider.ts +++ /dev/null @@ -1,138 +0,0 @@ -import ContextPadProvider from 'bpmn-js/lib/features/context-pad/ContextPadProvider'; -import { Injector } from 'didi'; -import EventBus from 'diagram-js/lib/core/EventBus'; -import ContextPad from 'diagram-js/lib/features/context-pad/ContextPad'; -import Modeling from 'bpmn-js/lib/features/modeling/Modeling.js'; -import ElementFactory from 'bpmn-js/lib/features/modeling/ElementFactory'; -import Connect from 'diagram-js/lib/features/connect/Connect'; -import Create from 'diagram-js/lib/features/create/Create'; -import PopupMenu from 'diagram-js/lib/features/popup-menu/PopupMenu'; -import Canvas from 'diagram-js/lib/core/Canvas'; -import Rules from 'diagram-js/lib/features/rules/Rules'; -import { Element, Shape } from 'diagram-js/lib/model/Types'; -import BpmnFactory from 'bpmn-js/lib/features/modeling/BpmnFactory'; -import modeler from '@/store/modules/modeler'; - -// @Description: 澧炲己鍏冪礌杩炵嚎浜嬩欢 - -class CustomContextPadProvider extends ContextPadProvider { - private _contextPad: ContextPad; - private _modeling: Modeling; - private _elementFactory: ElementFactory; - private _autoPlace: any; - private _connect: Connect; - private _create: Create; - private _popupMenu: PopupMenu; - private _canvas: Canvas; - private _rules: Rules; - - constructor( - config: any, - injector: Injector, - eventBus: EventBus, - contextPad: ContextPad, - modeling: Modeling, - elementFactory: ElementFactory, - connect: Connect, - create: Create, - popupMenu: PopupMenu, - canvas: Canvas, - rules: Rules, - translate - ) { - // @ts-expect-error 蹇界暐寮傚父 - super(config, injector, eventBus, contextPad, modeling, elementFactory, connect, create, popupMenu, canvas, rules, translate); - - this._contextPad = contextPad; - this._modeling = modeling; - this._elementFactory = elementFactory; - this._connect = connect; - this._create = create; - this._popupMenu = popupMenu; - this._canvas = canvas; - this._rules = rules; - - this._autoPlace = injector.get('autoPlace', false); - } - - getContextPadEntries(element: Element) { - const actions: Record<string, any> = {}; - - const appendUserTask = (event: Event, element: Shape) => { - const shape = this._elementFactory.createShape({ type: 'bpmn:UserTask' }); - this._create.start(event, shape, { - source: element - }); - }; - - const appendMultiInstanceUserTask = (event: Event, element: Shape) => { - const store = modeler(); - const bpmnFactory = store.getModeler().get('bpmnFactory') as BpmnFactory; - const businessObject = bpmnFactory.create('bpmn:UserTask', { - // name: '澶氬疄渚嬬敤鎴蜂换鍔�', - isForCompensation: false - }); - businessObject.loopCharacteristics = bpmnFactory.create('bpmn:MultiInstanceLoopCharacteristics'); - // 鍒涘缓 Shape - const shape = this._elementFactory.createShape({ - type: 'bpmn:UserTask', - businessObject: businessObject - }); - this._create.start(event, shape, { source: element }); - }; - - const appendTask = this._autoPlace - ? (event, element) => { - const bpmnFactory: BpmnFactory | undefined = modeler().getModeler().get('bpmnFactory'); - const businessObject = bpmnFactory.create('bpmn:UserTask', { - // name: '澶氬疄渚嬬敤鎴蜂换鍔�',// 鍙抽敭鍒涘缓鏄剧ず - isForCompensation: false - }); - - // 鍒涘缓澶氬疄渚嬪睘鎬у苟鍒嗛厤缁欑敤鎴蜂换鍔$殑 loopCharacteristics - businessObject.loopCharacteristics = bpmnFactory.create('bpmn:MultiInstanceLoopCharacteristics'); - - // 鍒涘缓 Shape - const shape = this._elementFactory.createShape({ - type: 'bpmn:UserTask', - businessObject: businessObject - }); - - this._autoPlace.append(element, shape); - } - : appendMultiInstanceUserTask; - - const append = this._autoPlace - ? (event: Event, element: Shape) => { - const shape = this._elementFactory.createShape({ type: 'bpmn:UserTask' }); - this._autoPlace.append(element, shape); - } - : appendUserTask; - - // // 娣诲姞鍒涘缓鐢ㄦ埛浠诲姟鎸夐挳 - actions['append.append-user-task'] = { - group: 'model', - className: 'bpmn-icon-user-task', - title: '鐢ㄦ埛浠诲姟', - action: { - dragstart: appendUserTask, - click: append - } - }; - - // 娣诲姞鍒涘缓澶氬疄渚嬬敤鎴蜂换鍔℃寜閽� - actions['append.append-multi-instance-user-task'] = { - group: 'model', - className: 'bpmn-icon-user', // 浣犲彲浠ヤ娇鐢ㄥ瀹炰緥鐢ㄦ埛浠诲姟鐨勫浘鏍� bpmn-icon-user bpmn-icon-user-task - title: '澶氬疄渚嬬敤鎴蜂换鍔�', - action: { - dragstart: appendMultiInstanceUserTask, - click: appendTask - } - }; - - return actions; - } -} - -export default CustomContextPadProvider; diff --git a/src/bpmn/assets/module/Palette/CustomPaletteProvider.ts b/src/bpmn/assets/module/Palette/CustomPaletteProvider.ts deleted file mode 100644 index 8556d9b..0000000 --- a/src/bpmn/assets/module/Palette/CustomPaletteProvider.ts +++ /dev/null @@ -1,109 +0,0 @@ -import { assign } from 'min-dash'; -import PaletteProvider from 'bpmn-js/lib/features/palette/PaletteProvider'; -import ElementFactory from 'bpmn-js/lib/features/modeling/ElementFactory'; -import Create from 'diagram-js/lib/features/create/Create'; -import SpaceTool from 'diagram-js/lib/features/space-tool/SpaceTool'; -import LassoTool from 'diagram-js/lib/features/lasso-tool/LassoTool'; -import HandTool from 'diagram-js/lib/features/hand-tool/HandTool'; -import GlobalConnect from 'diagram-js/lib/features/global-connect/GlobalConnect'; -import Palette from 'diagram-js/lib/features/palette/Palette'; -import modeler from '@/store/modules/modeler'; -import BpmnFactory from 'bpmn-js/lib/features/modeling/BpmnFactory'; - -// @Description: 澧炲己宸︿晶闈㈡澘 -class CustomPaletteProvider extends PaletteProvider { - private readonly _palette: Palette; - private readonly _create: Create; - private readonly _elementFactory: ElementFactory; - private readonly _spaceTool: SpaceTool; - private readonly _lassoTool: LassoTool; - private readonly _handTool: HandTool; - private readonly _globalConnect: GlobalConnect; - private readonly _translate: any; - - constructor(palette, create, elementFactory, spaceTool, lassoTool, handTool, globalConnect, translate) { - super(palette, create, elementFactory, spaceTool, lassoTool, handTool, globalConnect, translate); - this._palette = palette; - this._create = create; - this._elementFactory = elementFactory; - this._spaceTool = spaceTool; - this._lassoTool = lassoTool; - this._handTool = handTool; - this._globalConnect = globalConnect; - this._translate = translate; - } - - getPaletteEntries() { - const actions = {}, - create = this._create, - elementFactory = this._elementFactory, - translate = this._translate; - - function createAction(type: string, group: string, className: string, title: string, options?: object) { - function createListener(event) { - const shape = elementFactory.createShape(assign({ type: type }, options)); - if (options) { - !shape.businessObject.di && (shape.businessObject.di = {}); - shape.businessObject.di.isExpanded = (options as { [key: string]: any }).isExpanded; - } - create.start(event, shape, null); - } - const shortType = type.replace(/^bpmn:/, ''); - return { - group: group, - className: className, - title: title || translate('Create {type}', { type: shortType }), - action: { - dragstart: createListener, - click: createListener - } - }; - } - - function createMultiInstanceUserTask(event) { - const bpmnFactory: BpmnFactory | undefined = modeler().getBpmnFactory(); - // 鍒涘缓涓�涓� bpmn:UserTask - const userTask = bpmnFactory.create('bpmn:UserTask', { - // name: '澶氬疄渚嬬敤鎴蜂换鍔�', // 鍦ㄧ敾鏉夸腑鏄剧ず瀛楁 - isForCompensation: false - }); - // 灏嗗瀹炰緥灞炴�у垎閰嶇粰 bpmn:UserTask 鐨� loopCharacteristics - userTask.loopCharacteristics = bpmnFactory.create('bpmn:MultiInstanceLoopCharacteristics'); - const customUserTask = elementFactory.createShape({ - type: 'bpmn:UserTask', - businessObject: userTask // 鍒嗛厤鍒涘缓鐨� userTask 鍒� businessObject - }); - create.start(event, customUserTask, {}); - } - - assign(actions, { - 'create.parallel-gateway': createAction('bpmn:ParallelGateway', 'gateway', 'bpmn-icon-gateway-parallel', '骞惰缃戝叧'), - 'create.event-base-gateway': createAction('bpmn:EventBasedGateway', 'gateway', 'bpmn-icon-gateway-eventbased', '浜嬩欢缃戝叧'), - // 鍒嗙粍绾� - 'gateway-separator': { - group: 'gateway', - separator: true - }, - 'create.user-task': createAction('bpmn:UserTask', 'activity', 'bpmn-icon-user-task', '鍒涘缓鐢ㄦ埛浠诲姟'), - 'create.multi-instance-user-task': { - group: 'activity', - type: 'bpmn:UserTask', - className: 'bpmn-icon-user task-multi-instance', - title: '鍒涘缓澶氬疄渚嬬敤鎴蜂换鍔�', - action: { - click: createMultiInstanceUserTask, - dragstart: createMultiInstanceUserTask - } - }, - 'task-separator': { - group: 'activity', - separator: true - } - }); - return actions; - } -} - -CustomPaletteProvider['$inject'] = ['palette', 'create', 'elementFactory', 'spaceTool', 'lassoTool', 'handTool', 'globalConnect', 'translate']; - -export default CustomPaletteProvider; diff --git a/src/bpmn/assets/module/Renderer/CustomRenderer.ts b/src/bpmn/assets/module/Renderer/CustomRenderer.ts deleted file mode 100644 index 6a4eb1a..0000000 --- a/src/bpmn/assets/module/Renderer/CustomRenderer.ts +++ /dev/null @@ -1,56 +0,0 @@ -import BaseRenderer from 'diagram-js/lib/draw/BaseRenderer'; -import { - append as svgAppend, - attr as svgAttr, - create as svgCreate, - select as svgSelect, - selectAll as svgSelectAll, - clone as svgClone, - clear as svgClear, - remove as svgRemove -} from 'tiny-svg'; - -const HIGH_PRIORITY = 1500; -export default class CustomRenderer extends BaseRenderer { - bpmnRenderer: BaseRenderer; - modeling: any; - constructor(eventBus, bpmnRenderer, modeling) { - super(eventBus, HIGH_PRIORITY); - this.bpmnRenderer = bpmnRenderer; - this.modeling = modeling; - } - canRender(element) { - // ignore labels - return !element.labelTarget; - } - - /** - * 鑷畾涔夎妭鐐瑰浘褰� - * @param {*} parentNode 褰撳墠鍏冪礌鐨剆vgNode - * @param {*} element - * @returns - */ - drawShape(parentNode, element) { - const shape = this.bpmnRenderer.drawShape(parentNode, element); - const { type, width, height } = element; - // 寮�濮� 濉厖缁胯壊 - if (type === 'bpmn:StartEvent') { - svgAttr(shape, { fill: '#77DF6D' }); - return shape; - } - if (type === 'bpmn:EndEvent') { - svgAttr(shape, { fill: '#EE7B77' }); - return shape; - } - if (type === 'bpmn:UserTask') { - svgAttr(shape, { fill: '#A9C4F8' }); - return shape; - } - return shape; - } - - getShapePath(shape) { - return this.bpmnRenderer.getShapePath(shape); - } -} -CustomRenderer['$inject'] = ['eventBus', 'bpmnRenderer']; diff --git a/src/bpmn/assets/module/Translate/index.ts b/src/bpmn/assets/module/Translate/index.ts deleted file mode 100644 index 6b52dae..0000000 --- a/src/bpmn/assets/module/Translate/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -import zh from '../../lang/zh'; - -const customTranslate = (template: any, replacements: any) => { - replacements = replacements || {}; - template = zh[template] || template; - return template.replace(/{([^}]+)}/g, function (_: any, key: any) { - return replacements[key] || '{' + key + '}'; - }); -}; - -export const translateModule = { - translate: ['value', customTranslate] -}; - -export default translateModule; diff --git a/src/bpmn/assets/module/index.ts b/src/bpmn/assets/module/index.ts deleted file mode 100644 index 55f6b9f..0000000 --- a/src/bpmn/assets/module/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -// 缈昏瘧妯″潡 -import TranslationModule from './Translate'; -import { ModuleDeclaration } from 'didi'; -import CustomPaletteProvider from './Palette/CustomPaletteProvider'; -import CustomRenderer from './Renderer/CustomRenderer'; -import CustomContextPadProvider from './ContextPad/CustomContextPadProvider'; - -const Module: ModuleDeclaration[] = [ - { - __init__: ['customPaletteProvider', 'customContextPadProvider', 'customRenderer'], - customPaletteProvider: ['type', CustomPaletteProvider], - customRenderer: ['type', CustomRenderer], - customContextPadProvider: ['type', CustomContextPadProvider] - }, - TranslationModule -]; -export default Module; diff --git a/src/bpmn/assets/showConfig.ts b/src/bpmn/assets/showConfig.ts deleted file mode 100644 index 853eb35..0000000 --- a/src/bpmn/assets/showConfig.ts +++ /dev/null @@ -1,50 +0,0 @@ -export default { - 'bpmn:EndEvent': {}, - 'bpmn:StartEvent': { - initiator: true, - formKey: true - }, - 'bpmn:UserTask': { - allocationType: true, - specifyDesc: true, - multipleUserAuditType: true, - async: true, - priority: true, - skipExpression: true, - dueDate: true, - taskListener: true, - executionListener: true - }, - 'bpmn:ServiceTask': { - async: true, - skipExpression: true, - isForCompensation: true, - triggerable: true, - class: true - }, - 'bpmn:ScriptTask': { - async: true, - isForCompensation: true, - autoStoreVariables: true - }, - 'bpmn:ManualTask': { - async: true, - isForCompensation: true - }, - 'bpmn:ReceiveTask': { - async: true, - isForCompensation: true - }, - 'bpmn:SendTask': { - async: true, - isForCompensation: true - }, - 'bpmn:BusinessRuleTask': { - async: true, - isForCompensation: true, - ruleVariablesInput: true, - rules: true, - resultVariable: true, - exclude: true - } -}; diff --git a/src/bpmn/assets/style/index.scss b/src/bpmn/assets/style/index.scss deleted file mode 100644 index 3c92792..0000000 --- a/src/bpmn/assets/style/index.scss +++ /dev/null @@ -1,284 +0,0 @@ -.djs-palette { - width: 300px; - - .bpmn-icon-hand-tool:hover { - &:after { - content: '鍚姩鎵嬪姩宸ュ叿'; - position: absolute; - left: 45px; - width: 120px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-lasso-tool:hover { - &:after { - content: '鍚姩濂楃储宸ュ叿'; - position: absolute; - left: 100px; - width: 120px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-space-tool:hover { - &:after { - content: '鍚姩鍒涘缓/鍒犻櫎绌洪棿宸ュ叿'; - position: absolute; - left: 45px; - width: 170px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-connection-multi:hover { - &:after { - content: '鍚姩鍏ㄥ眬杩炴帴宸ュ叿'; - position: absolute; - left: 100px; - width: 140px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-start-event-none:hover { - &:after { - content: '鍒涘缓寮�濮嬩簨浠�'; - position: absolute; - left: 45px; - width: 120px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-intermediate-event-none:hover { - &:after { - content: '鍒涘缓涓棿/杈圭晫浜嬩欢'; - position: absolute; - left: 100px; - width: 140px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-end-event-none:hover { - &:after { - content: '鍒涘缓缁撴潫浜嬩欢'; - position: absolute; - left: 45px; - width: 120px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-gateway-none:hover { - &:after { - content: '鍒涘缓缃戝叧'; - position: absolute; - left: 100px; - width: 90px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-gateway-parallel:hover { - &:after { - content: '鍒涘缓骞惰缃戝叧'; - position: absolute; - left: 45px; - width: 120px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-gateway-eventbased:hover { - &:after { - content: '鍒涘缓浜嬩欢缃戝叧'; - position: absolute; - left: 100px; - width: 120px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-task:hover { - &:after { - content: '鍒涘缓浠诲姟'; - position: absolute; - left: 45px; - width: 80px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-subprocess-expanded:hover { - &:after { - content: '鍒涘缓鍙姌鍙犲瓙娴佺▼'; - position: absolute; - left: 100px; - width: 140px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-user-task:hover { - &:after { - content: '鍒涘缓鐢ㄦ埛浠诲姟'; - position: absolute; - left: 45px; - width: 120px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - - .task-multi-instance:hover { - &:after { - content: '鍒涘缓澶氬疄渚嬬敤鎴蜂换鍔�'; - position: absolute; - left: 100px; - width: 160px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-participant:hover { - &:after { - content: '鍒涘缓娉虫睜/娉抽亾'; - position: absolute; - left: 45px; - width: 120px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - .bpmn-icon-data-object { - display: none; - &:hover { - &:after { - content: '鍒涘缓鏁版嵁瀵硅薄'; - position: absolute; - left: 45px; - width: 120px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - } - .bpmn-icon-data-store { - display: none; - &:hover { - &:after { - content: '鍒涘缓鏁版嵁瀛樺偍'; - position: absolute; - left: 100px; - width: 120px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - } - .bpmn-icon-group { - display: none; - &:hover { - &:after { - content: '鍒涘缓鍒嗙粍'; - position: absolute; - left: 100px; - width: 100px; - font-size: 15px; - font-weight: bold; - color: #3a84de; - border-radius: 2px; - border: 1px solid #cccccc; - background-color: #fafafa; - opacity: 0.8; - } - } - } -} diff --git a/src/bpmn/hooks/usePanel.ts b/src/bpmn/hooks/usePanel.ts deleted file mode 100644 index ace579b..0000000 --- a/src/bpmn/hooks/usePanel.ts +++ /dev/null @@ -1,145 +0,0 @@ -import showConfig from '../assets/showConfig'; -import type { ModdleElement } from 'bpmn'; -import useModelerStore from '@/store/modules/modeler'; -import { MultiInstanceTypeEnum } from '@/enums/bpmn/IndexEnums'; -interface Options { - element: ModdleElement; -} - -export default (ops: Options) => { - const { element } = ops; - const { getModeling, getModdle } = useModelerStore(); - const modeling = getModeling(); - const moddle = getModdle(); - - /** - * 褰撳墠鑺傜偣绫诲瀷 - */ - const elementType = computed(() => { - const bizObj = element.businessObject; - return bizObj.eventDefinitions ? bizObj.eventDefinitions[0].$type : bizObj.$type; - }); - - /** - * 鐢ㄤ簬鎺у埗闈㈡澘瀛楁鏄剧ず涓庨殣钘忕殑閰嶇疆 - */ - const config = computed(() => showConfig[elementType.value] || {}); - - /** - * 鍒涘缓涓�涓妭鐐� - * @param elementType 鑺傜偣绫诲瀷 - * @param properties 灞炴�� - * @param parent 鐖惰妭鐐� - */ - const createModdleElement = (elementType: string, properties: any, parent: ModdleElement) => { - const element = moddle.create(elementType, properties); - parent && (element.$parent = parent); - return element; - }; - - /** - * 鑾峰彇鎵╁睍灞炴�э紝濡傛灉涓嶅瓨鍦ㄤ細鑷姩鍒涘缓 - */ - const getExtensionElements = (create = true) => { - let extensionElements = element.businessObject.get<ModdleElement>('extensionElements'); - if (!extensionElements && create) { - extensionElements = createModdleElement('bpmn:ExtensionElements', { values: [] }, element.businessObject); - modeling.updateModdleProperties(element, element.businessObject, { extensionElements }); - } - return extensionElements; - }; - - /** - * 鑾峰彇extensionElements涓嬬殑properties - * @param extensionElements 鍙�夊弬鏁帮紝榛樿鑾峰彇褰撳墠Element涓嬬殑extensionElements涓嬬殑Properties - */ - const getPropertiesElements = (extensionElements?: ModdleElement) => { - if (!extensionElements) { - extensionElements = getExtensionElements(); - } - let propertiesElements = extensionElements.values.find((item) => item.$type === 'flowable:properties'); - if (!propertiesElements) { - propertiesElements = createModdleElement('flowable:properties', { values: [] }, extensionElements); - modeling.updateModdleProperties(element, extensionElements, { - values: [...extensionElements.get<[]>('values'), propertiesElements] - }); - } - return propertiesElements; - }; - - /** - * 鏇存柊鑺傜偣灞炴�� - * @param properties 灞炴�у�� - */ - const updateProperties = (properties: any) => { - modeling.updateProperties(element, properties); - }; - - /** - * 鏇存柊鑺傜偣淇℃伅 - * @param updateElement 闇�瑕佹洿鏂扮殑鑺傜偣 - * @param properties 灞炴�� - */ - const updateModdleProperties = (updateElement, properties: any) => { - modeling.updateModdleProperties(element, updateElement, properties); - }; - - /** - * 鏇存柊Property灞炴�� - * @param name key鍊� - * @param value 鍊� - */ - const updateProperty = (name: string, value: string) => { - const propertiesElements = getPropertiesElements(); - - let propertyElements = propertiesElements.values.find((item) => item.name === name); - if (!propertyElements) { - propertyElements = createModdleElement('flowable:property', { name: name, value: value }, propertiesElements); - modeling.updateModdleProperties(element, propertiesElements, { - values: [...propertiesElements.get('values'), propertyElements] - }); - } else { - propertyElements.name = name; - propertyElements.value = value; - } - return propertyElements; - }; - - const idChange = (newVal: string) => { - if (newVal) { - updateProperties({ id: newVal }); - } - }; - const nameChange = (newVal: string) => { - if (newVal) { - updateProperties({ name: newVal }); - } - }; - const formKeyChange = (newVal: string) => { - updateProperties({ formKey: newVal }); - }; - const constant = { - MultiInstanceType: [ - { id: '373d4b81-a0d1-4eb8-8685-0d2fb1b468e2', label: '鏃�', value: MultiInstanceTypeEnum.NONE }, - { id: 'b5acea7c-b7e5-46b0-8778-390db091bdab', label: '涓茶', value: MultiInstanceTypeEnum.SERIAL }, - { id: 'b4f0c683-1ccc-43c4-8380-e1b998986caf', label: '骞惰', value: MultiInstanceTypeEnum.PARALLEL } - ] - }; - - return { - elementType, - constant, - showConfig: config, - - updateProperties, - updateProperty, - updateModdleProperties, - - createModdleElement, - idChange, - nameChange, - formKeyChange, - getExtensionElements, - getPropertiesElements - }; -}; diff --git a/src/bpmn/hooks/useParseElement.ts b/src/bpmn/hooks/useParseElement.ts deleted file mode 100644 index e1a6054..0000000 --- a/src/bpmn/hooks/useParseElement.ts +++ /dev/null @@ -1,34 +0,0 @@ -import type { ModdleElement } from 'bpmn'; - -interface Options { - element: ModdleElement; -} - -interface Data { - id: string; -} - -export default (ops: Options) => { - const { element } = ops; - - const parseData = <T>(): T => { - const result = { - ...element.businessObject, - ...element.businessObject.$attrs - }; - - // 绉婚櫎flowable鍓嶇紑锛屾牸寮忓寲鏁扮粍 - for (const key in result) { - if (key.indexOf('flowable:') === 0) { - const newKey = key.replace('flowable:', ''); - result[newKey] = result[key]; - delete result[key]; - } - } - return { ...result } as T; - }; - - return { - parseData - }; -}; diff --git a/src/bpmn/index.vue b/src/bpmn/index.vue deleted file mode 100644 index 15437c8..0000000 --- a/src/bpmn/index.vue +++ /dev/null @@ -1,496 +0,0 @@ -<template> - <div class="containers-bpmn"> - <!-- dark妯″紡涓� 杩炴帴绾跨殑绠ご鏍峰紡 --> - <svg width="0" height="0" style="position: absolute"> - <defs> - <marker id="markerArrow-dark-mode" viewBox="0 0 20 20" refX="11" refY="10" markerWidth="10" markerHeight="10" orient="auto"> - <path d="M 1 5 L 11 10 L 1 15 Z" class="arrow-dark" /> - </marker> - </defs> - </svg> - <div v-loading="loading" class="app-containers-bpmn"> - <el-container class="h-full"> - <el-container style="align-items: stretch"> - <el-header> - <div class="process-toolbar"> - <el-space wrap :size="10"> - <el-tooltip effect="dark" content="鑷�傚簲灞忓箷" placement="bottom"> - <el-button size="small" icon="Rank" @click="fitViewport" /> - </el-tooltip> - <el-tooltip effect="dark" content="鏀惧ぇ" placement="bottom"> - <el-button size="small" icon="ZoomIn" @click="zoomViewport(true)" /> - </el-tooltip> - <el-tooltip effect="dark" content="缂╁皬" placement="bottom"> - <el-button size="small" icon="ZoomOut" @click="zoomViewport(false)" /> - </el-tooltip> - <el-tooltip effect="dark" content="鍚庨��" placement="bottom"> - <el-button size="small" icon="Back" @click="bpmnModeler.get('commandStack').undo()" /> - </el-tooltip> - <el-tooltip effect="dark" content="鍓嶈繘" placement="bottom"> - <el-button size="small" icon="Right" @click="bpmnModeler.get('commandStack').redo()" /> - </el-tooltip> - </el-space> - <el-space wrap :size="10" style="float: right; padding-right: 10px"> - <el-button size="small" type="primary" @click="saveXml">淇� 瀛�</el-button> - <el-dropdown size="small"> - <el-button size="small" type="primary"> 棰� 瑙� </el-button> - <template #dropdown> - <el-dropdown-menu> - <el-dropdown-item icon="Document" @click="previewXML">XML棰勮</el-dropdown-item> - <el-dropdown-item icon="View" @click="previewSVG"> SVG棰勮</el-dropdown-item> - </el-dropdown-menu> - </template> - </el-dropdown> - <el-dropdown size="small"> - <el-button size="small" type="primary"> 涓� 杞� </el-button> - <template #dropdown> - <el-dropdown-menu> - <el-dropdown-item icon="Download" @click="downloadXML">涓嬭浇XML</el-dropdown-item> - <el-dropdown-item icon="Download" @click="downloadSVG"> 涓嬭浇SVG</el-dropdown-item> - </el-dropdown-menu> - </template> - </el-dropdown> - </el-space> - </div> - </el-header> - <div ref="canvas" class="canvas" /> - </el-container> - <div :class="{ 'process-panel': true, 'hide': panelFlag }"> - <div class="process-panel-bar" @click="panelBarClick"> - <div class="open-bar"> - <el-link type="default" :underline="false"> - <svg-icon class-name="open-bar" :icon-class="panelFlag ? 'caret-back' : 'caret-forward'"></svg-icon> - </el-link> - </div> - </div> - <transition enter-active-class="animate__animated animate__fadeIn"> - <div v-show="showPanel" v-if="bpmnModeler" class="panel-content"> - <PropertyPanel :modeler="bpmnModeler" /> - </div> - </transition> - </div> - </el-container> - </div> - </div> - <div> - <el-dialog v-model="perviewXMLShow" title="XML棰勮" width="80%" append-to-body> - <highlightjs :code="xmlStr" language="XML" /> - </el-dialog> - </div> - <div> - <el-dialog v-model="perviewSVGShow" title="SVG棰勮" width="80%" append-to-body> - <div style="text-align: center" v-html="svgData" /> - </el-dialog> - </div> -</template> - -<script lang="ts" setup name="BpmnDesign"> -import 'bpmn-js/dist/assets/diagram-js.css'; -import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'; -import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'; -import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'; -import './assets/style/index.scss'; -import type { Canvas, Modeler } from 'bpmn'; -import PropertyPanel from './panel/index.vue'; -import BpmnModeler from 'bpmn-js/lib/Modeler.js'; -import defaultXML from './assets/defaultXML'; -import flowableModdle from './assets/moddle/flowable'; -import Modules from './assets/module/index'; -import useModelerStore from '@/store/modules/modeler'; -import useDialog from '@/hooks/useDialog'; - -const emit = defineEmits(['closeCallBack', 'saveCallBack']); - -const { visible, title, openDialog, closeDialog } = useDialog({ - title: '缂栬緫娴佺▼' -}); -const modelerStore = useModelerStore(); - -const { proxy } = getCurrentInstance() as ComponentInternalInstance; - -const panelFlag = ref(false); -const showPanel = ref(true); -const canvas = ref<HTMLDivElement>(); -const panel = ref<HTMLDivElement>(); -const bpmnModeler = ref<Modeler>(); -const zoom = ref(1); -const perviewXMLShow = ref(false); -const perviewSVGShow = ref(false); -const xmlStr = ref(''); -const svgData = ref(''); -const loading = ref(false); - -const panelBarClick = () => { - // 寤惰繜鎵ц锛屽惁鍒欎細瀵艰嚧闈㈡澘鏀惰捣鏃讹紝灞炴�ч潰鏉夸笉鏄剧ず - panelFlag.value = !panelFlag.value; - setTimeout(() => { - showPanel.value = !panelFlag.value; - }, 100); -}; - -/** - * 鍒濆鍖朇anvas - */ -const initCanvas = () => { - bpmnModeler.value = new BpmnModeler({ - container: canvas.value, - // 閿洏 - keyboard: { - bindTo: window // 鎴栬�厀indow锛屾敞鎰忎笌澶栭儴琛ㄥ崟鐨勯敭鐩樼洃鍚簨浠舵槸鍚﹀啿绐� - }, - propertiesPanel: { - parent: panel.value - }, - additionalModules: Modules, - moddleExtensions: { - flowable: flowableModdle - } - }); -}; - -/** - * 鍒濆鍖朚odel - */ -const initModel = () => { - if (modelerStore.getModeler()) { - modelerStore.getModeler().destroy(); - modelerStore.setModeler(undefined); - } - modelerStore.setModeler(bpmnModeler.value); -}; - -/** - * 鏂板缓 - */ -const newDiagram = async () => { - await proxy?.$modal.confirm('鏄惁纭鏂板缓'); - initDiagram(); -}; - -/** - * 鍒濆鍖� - */ -const initDiagram = (xml?: string) => { - if (!xml) xml = defaultXML; - bpmnModeler.value.importXML(xml); -}; - -/** - * 鑷�傚簲灞忓箷 - */ -const fitViewport = () => { - zoom.value = bpmnModeler.value.get<Canvas>('canvas').zoom('fit-viewport'); - const bbox = document.querySelector<SVGGElement>('.app-containers-bpmn .viewport').getBBox(); - const currentViewBox = bpmnModeler.value.get<Canvas>('canvas').viewbox(); - const elementMid = { - x: bbox.x + bbox.width / 2 - 65, - y: bbox.y + bbox.height / 2 - }; - bpmnModeler.value.get<Canvas>('canvas').viewbox({ - x: elementMid.x - currentViewBox.width / 2, - y: elementMid.y - currentViewBox.height / 2, - width: currentViewBox.width, - height: currentViewBox.height - }); - zoom.value = (bbox.width / currentViewBox.width) * 1.8; -}; -/** - * 鏀惧ぇ鎴栬�呯缉灏� - * @param zoomIn true 鏀惧ぇ | false 缂╁皬 - */ -const zoomViewport = (zoomIn = true) => { - zoom.value = bpmnModeler.value.get<Canvas>('canvas').zoom(); - zoom.value += zoomIn ? 0.1 : -0.1; - bpmnModeler.value.get<Canvas>('canvas').zoom(zoom.value); -}; - -/** - * 涓嬭浇XML - */ -const downloadXML = async () => { - try { - const { xml } = await bpmnModeler.value.saveXML({ format: true }); - downloadFile(`${getProcessElement().name}.bpmn20.xml`, xml, 'application/xml'); - } catch (e) { - proxy?.$modal.msgError(e); - } -}; - -/** - * 涓嬭浇SVG - */ -const downloadSVG = async () => { - try { - const { svg } = await bpmnModeler.value.saveSVG(); - downloadFile(getProcessElement().name, svg, 'image/svg+xml'); - } catch (e) { - proxy?.$modal.msgError(e); - } -}; - -/** - * XML棰勮 - */ -const previewXML = async () => { - try { - const { xml } = await bpmnModeler.value.saveXML({ format: true }); - xmlStr.value = xml; - perviewXMLShow.value = true; - } catch (e) { - proxy?.$modal.msgError(e); - } -}; - -/** - * SVG棰勮 - */ -const previewSVG = async () => { - try { - const { svg } = await bpmnModeler.value.saveSVG(); - svgData.value = svg; - perviewSVGShow.value = true; - } catch (e) { - proxy?.$modal.msgError(e); - } -}; - -const curNodeInfo = reactive({ - curType: '', // 浠诲姟绫诲瀷 鐢ㄦ埛浠诲姟 - curNode: '', - expValue: '' //澶氱敤鎴峰拰閮ㄩ棬瑙掕壊瀹炵幇 -}); - -const downloadFile = (fileName: string, data: any, type: string) => { - const a = document.createElement('a'); - const url = window.URL.createObjectURL(new Blob([data], { type: type })); - a.href = url; - a.download = fileName; - a.click(); - window.URL.revokeObjectURL(url); -}; - -const getProcessElement = () => { - const rootElements = bpmnModeler.value?.getDefinitions().rootElements; - for (let i = 0; i < rootElements.length; i++) { - if (rootElements[i].$type === 'bpmn:Process') return rootElements[i]; - } -}; - -const getProcess = () => { - const element = getProcessElement(); - return { - id: element.id, - name: element.name - }; -}; - -const saveXml = async () => { - const { xml } = await bpmnModeler.value.saveXML({ format: true }); - const { svg } = await bpmnModeler.value.saveSVG(); - const process = getProcess(); - let data = { - xml: xml, - svg: svg, - key: process.id, - name: process.name, - loading: loading - }; - emit('saveCallBack', data); -}; - -const open = (xml?: string) => { - openDialog(); - nextTick(() => { - initDiagram(xml); - }); -}; -const close = () => { - closeDialog(); -}; - -onMounted(() => { - nextTick(() => { - initCanvas(); - initModel(); - }); -}); - -/** - * 瀵瑰鏆撮湶瀛愮粍浠舵柟娉� - */ -defineExpose({ - initDiagram, - saveXml, - open, - close -}); -</script> - -<style lang="scss"> -/** 澶滈棿妯″紡 绾挎潯鐨勯鑹� */ -$stroke-color-dark: white; -$bpmn-font-size: 12px; -/** 鏃ラ棿妯″紡 瀛椾綋棰滆壊 */ -$bpmn-font-color-dark: white; -/** 澶滈棿妯″紡 瀛椾綋棰滆壊 */ -$bpmn-font-color-light: #222; - -/* 鑳屾櫙缃戞牸 */ -@mixin djs-container { - background-image: linear-gradient(90deg, hsl(0deg 0% 78.4% / 15%) 10%, transparent 0), linear-gradient(hsl(0deg 0% 78.4% / 15%) 10%, transparent 0) !important; - background-size: 10px 10px !important; -} - -html[class='light'] { - /** 浠庡乏渚ф嫋鍔ㄦ椂鐨勮儗鏅浘 */ - svg.new-parent { - @include djs-container; - } - - /** 鍙屽嚮缂栬緫鍏冪礌鏃舵牱寮忎繚鎸佷竴鑷� */ - div.djs-direct-editing-parent { - border-radius: 10px; - background-color: transparent !important; - color: $bpmn-font-color-light; - } - - g.djs-visual { - .djs-label { - fill: $bpmn-font-color-light !important; - font-size: $bpmn-font-size !important; - } - } -} - -html[class='dark'] { - /** dark妯″紡涓� 杩炴帴绾跨殑绠ご鏍峰紡 */ - .arrow-dark { - stroke-width: 1px; - stroke-linecap: round; - stroke: $stroke-color-dark; - fill: $stroke-color-dark; - stroke-linejoin: round; - } - - /** 浠庡乏渚ф嫋鍔ㄦ椂鐨勮儗鏅浘 */ - svg.new-parent { - background-color: black !important; - @include djs-container; - } - - /** 鍙屽嚮缂栬緫鍏冪礌鏃舵牱寮忎繚鎸佷竴鑷� */ - div.djs-direct-editing-parent { - border-radius: 10px; - background-color: transparent !important; - color: $bpmn-font-color-dark; - } - - /** 鍏冪礌鐩稿叧璁剧疆 */ - g.djs-visual { - /** 鍏冪礌杈规 闇�瑕佸幓闄ゆ枃瀛�(.djs-label) */ - & > *:first-child:not(.djs-label) { - stroke: $stroke-color-dark !important; - } - - /** 瀛椾綋棰滆壊 */ - .djs-label { - fill: $bpmn-font-color-dark !important; - font-size: $bpmn-font-size !important; - } - - /* 杩炴帴绾挎牱寮� */ - path[data-corner-radius] { - stroke: $stroke-color-dark !important; - marker-end: url('#markerArrow-dark-mode') !important; - } - } -} - -.containers-bpmn { - height: 100%; - .app-containers-bpmn { - width: 100%; - height: 100%; - .canvas { - width: 100%; - height: 100%; - @include djs-container; - } - .el-header { - height: 35px; - padding: 0; - } - - .process-panel { - transition: width 0.25s ease-in; - .process-panel-bar { - width: 34px; - height: 40px; - .open-bar { - width: 34px; - line-height: 40px; - } - } - // 鏀惰捣闈㈡澘鏍峰紡 - &.hide { - width: 34px; - overflow: hidden; - padding: 0; - .process-panel-bar { - width: 34px; - height: 100%; - box-sizing: border-box; - display: block; - text-align: left; - line-height: 34px; - } - .process-panel-bar:hover { - background-color: var(--bpmn-panel-bar-background-color); - } - } - } - } -} -pre { - margin: 0; - height: 100%; - max-height: calc(80vh - 32px); - overflow-x: hidden; - overflow-y: auto; - .hljs { - word-break: break-word; - white-space: pre-wrap; - padding: 0.5em; - } -} - -.open-bar { - font-size: 20px; - cursor: pointer; - text-align: center; -} -.process-panel { - box-sizing: border-box; - padding: 0 8px 0 8px; - border-left: 1px solid var(--bpmn-panel-border); - box-shadow: var(--bpmn-panel-box-shadow) 0 0 8px; - max-height: 100%; - width: 25%; - height: calc(100vh - 100px); - .el-collapse { - height: calc(100vh - 182px); - overflow: auto; - } -} - -// 浠诲姟鏍� 閫忔槑搴� -//:deep(.djs-palette) { -// opacity: 0.3; -// transition: all 1s; -//} -// -//:deep(.djs-palette:hover) { -// opacity: 1; -// transition: all 1s; -//} -</style> diff --git a/src/bpmn/panel/GatewayPanel.vue b/src/bpmn/panel/GatewayPanel.vue deleted file mode 100644 index 20cc134..0000000 --- a/src/bpmn/panel/GatewayPanel.vue +++ /dev/null @@ -1,68 +0,0 @@ -<template> - <div> - <el-collapse v-model="currentCollapseItem"> - <el-collapse-item name="1"> - <template #title> - <div class="collapse__title"> - <el-icon> - <InfoFilled /> - </el-icon> - 甯歌 - </div> - </template> - <div> - <el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px"> - <el-form-item prop="id" label="鑺傜偣 ID"> - <el-input v-model="formData.id" @change="idChange"> </el-input> - </el-form-item> - <el-form-item prop="name" label="鑺傜偣鍚嶇О"> - <el-input v-model="formData.name" @change="nameChange"> </el-input> - </el-form-item> - </el-form> - </div> - </el-collapse-item> - - <el-collapse-item name="2"> - <template #title> - <div class="collapse__title"> - <el-icon> - <BellFilled /> - </el-icon> - 鎵ц鐩戝惉鍣� - </div> - </template> - <div> - <ExecutionListener :element="element"></ExecutionListener> - </div> - </el-collapse-item> - </el-collapse> - </div> -</template> -<script setup lang="ts"> -import useParseElement from '../hooks/useParseElement'; -import usePanel from '../hooks/usePanel'; -import type { Modeler, ModdleElement } from 'bpmn'; -import type { GatewayPanel } from 'bpmnDesign'; -import ExecutionListener from './property/ExecutionListener.vue'; - -interface PropType { - element: ModdleElement; -} -const props = withDefaults(defineProps<PropType>(), {}); -const { nameChange, idChange } = usePanel({ - element: toRaw(props.element) -}); -const { parseData } = useParseElement({ - element: toRaw(props.element) -}); -const currentCollapseItem = ref(['1', '2']); -const formData = ref(parseData<GatewayPanel>()); - -const formRules = ref<ElFormRules>({ - processCategory: [{ required: true, message: '璇烽�夋嫨', trigger: 'blur' }], - id: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }], - name: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }] -}); -</script> - -<style lang="scss" scoped></style> diff --git a/src/bpmn/panel/ParticipantPanel.vue b/src/bpmn/panel/ParticipantPanel.vue deleted file mode 100644 index b1d42e6..0000000 --- a/src/bpmn/panel/ParticipantPanel.vue +++ /dev/null @@ -1,68 +0,0 @@ -<template> - <div> - <el-collapse v-model="currentCollapseItem"> - <el-collapse-item name="1"> - <template #title> - <div class="collapse__title"> - <el-icon> - <InfoFilled /> - </el-icon> - 甯歌 - </div> - </template> - <div> - <el-form ref="formRef" :model="formData" :rules="formRules" label-width="90px"> - <el-form-item prop="id" label="鑺傜偣 ID"> - <el-input v-model="formData.id" @change="idChange"></el-input> - </el-form-item> - <el-form-item prop="name" label="鑺傜偣鍚嶇О"> - <el-input v-model="formData.name" @change="nameChange"></el-input> - </el-form-item> - </el-form> - </div> - </el-collapse-item> - - <el-collapse-item name="2"> - <template #title> - <div class="collapse__title"> - <el-icon> - <BellFilled /> - </el-icon> - 鎵ц鐩戝惉鍣� - </div> - </template> - <div> - <ExecutionListener :element="element"></ExecutionListener> - </div> - </el-collapse-item> - </el-collapse> - </div> -</template> -<script setup lang="ts"> -import useParseElement from '../hooks/useParseElement'; -import usePanel from '../hooks/usePanel'; -import ExecutionListener from './property/ExecutionListener.vue'; -import type { ModdleElement } from 'bpmn'; -import type { ParticipantPanel } from 'bpmnDesign'; - -interface PropType { - element: ModdleElement; -} - -const props = withDefaults(defineProps<PropType>(), {}); -const { nameChange, idChange } = usePanel({ - element: toRaw(props.element) -}); -const { parseData } = useParseElement({ - element: toRaw(props.element) -}); - -const formData = ref(parseData<ParticipantPanel>()); -const currentCollapseItem = ref(['1', '2']); -const formRules = ref<ElFormRules>({ - id: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }], - name: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }] -}); -</script> - -<style lang="scss" scoped></style> diff --git a/src/bpmn/panel/ProcessPanel.vue b/src/bpmn/panel/ProcessPanel.vue deleted file mode 100644 index 9e118e2..0000000 --- a/src/bpmn/panel/ProcessPanel.vue +++ /dev/null @@ -1,71 +0,0 @@ -<template> - <div> - <el-collapse v-model="currentCollapseItem"> - <el-collapse-item name="1"> - <template #title> - <div class="collapse__title"> - <el-icon> - <InfoFilled /> - </el-icon> - 甯歌 - </div> - </template> - <div> - <el-form ref="formRef" :model="formData" :rules="formRules" label-width="80px"> - <el-form-item label="娴佺▼鏍囪瘑" prop="id"> - <el-input v-model="formData.id" @change="idChange"></el-input> - </el-form-item> - <el-form-item label="娴佺▼鍚嶇О" prop="name"> - <el-input v-model="formData.name" @change="nameChange"></el-input> - </el-form-item> - </el-form> - </div> - </el-collapse-item> - - <el-collapse-item name="2"> - <template #title> - <div class="collapse__title"> - <el-icon> - <BellFilled /> - </el-icon> - 鎵ц鐩戝惉鍣� - </div> - </template> - <div> - <ExecutionListener :element="element"></ExecutionListener> - </div> - </el-collapse-item> - </el-collapse> - </div> -</template> - -<script setup lang="ts"> -import ExecutionListener from './property/ExecutionListener.vue'; -import useParseElement from '../hooks/useParseElement'; -import usePanel from '../hooks/usePanel'; -import type { Modeler, ModdleElement } from 'bpmn'; -import type { ProcessPanel } from 'bpmnDesign'; - -const { proxy } = getCurrentInstance() as ComponentInternalInstance; - -interface PropType { - element: ModdleElement; -} -const props = withDefaults(defineProps<PropType>(), {}); - -const { parseData } = useParseElement({ - element: toRaw(props.element) -}); -const { idChange, nameChange } = usePanel({ - element: toRaw(props.element) -}); -const currentCollapseItem = ref(['1', '2']); -const formData = ref<ProcessPanel>(parseData<ProcessPanel>()); - -const formRules = ref<ElFormRules>({ - id: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }], - name: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }] -}); -</script> - -<style scoped lang="scss"></style> diff --git a/src/bpmn/panel/SequenceFlowPanel.vue b/src/bpmn/panel/SequenceFlowPanel.vue deleted file mode 100644 index eac8227..0000000 --- a/src/bpmn/panel/SequenceFlowPanel.vue +++ /dev/null @@ -1,95 +0,0 @@ -<template> - <div> - <el-collapse v-model="currentCollapseItem"> - <el-collapse-item name="1"> - <template #title> - <div class="collapse__title"> - <el-icon> - <InfoFilled /> - </el-icon> - 甯歌 - </div> - </template> - <div> - <el-form ref="formRef" :model="formData" :rules="formRules" label-width="90px"> - <el-form-item prop="id" label="鑺傜偣 ID"> - <el-input v-model="formData.id" @change="idChange"> </el-input> - </el-form-item> - <el-form-item prop="name" label="鑺傜偣鍚嶇О"> - <el-input v-model="formData.name" @change="nameChange"> </el-input> - </el-form-item> - <el-form-item prop="conditionExpression" label="璺宠浆鏉′欢"> - <el-input v-model="formData.conditionExpressionValue" @change="conditionExpressionChange"> </el-input> - </el-form-item> - <el-form-item prop="skipExpression" label="璺宠繃琛ㄨ揪寮�"> - <el-input v-model="formData.skipExpression" @change="skipExpressionChange"> </el-input> - </el-form-item> - </el-form> - </div> - </el-collapse-item> - - <el-collapse-item name="2"> - <template #title> - <div class="collapse__title"> - <el-icon> - <BellFilled /> - </el-icon> - 鎵ц鐩戝惉鍣� - </div> - </template> - <div> - <ExecutionListener :element="element"></ExecutionListener> - </div> - </el-collapse-item> - </el-collapse> - </div> -</template> -<script setup lang="ts"> -import useParseElement from '../hooks/useParseElement'; -import useModelerStore from '@/store/modules/modeler'; -import usePanel from '../hooks/usePanel'; -import ExecutionListener from './property/ExecutionListener.vue'; -import type { Modeler, ModdleElement } from 'bpmn'; -import type { SequenceFlowPanel } from 'bpmnDesign'; - -interface PropType { - element: ModdleElement; -} -const props = withDefaults(defineProps<PropType>(), {}); -const { nameChange, idChange, updateProperties } = usePanel({ - element: toRaw(props.element) -}); -const { parseData } = useParseElement({ - element: toRaw(props.element) -}); -const moddle = useModelerStore().getModdle(); -const currentCollapseItem = ref(['1', '2']); -const formData = ref(parseData<SequenceFlowPanel>()); - -const formRules = ref<ElFormRules>({ - processCategory: [{ required: true, message: '璇烽�夋嫨', trigger: 'blur' }], - id: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }], - name: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }] -}); - -const conditionExpressionChange = (val: string) => { - if (val) { - const newCondition = moddle.create('bpmn:FormalExpression', { body: val }); - updateProperties({ conditionExpression: newCondition }); - } else { - updateProperties({ conditionExpression: null }); - } -}; - -const skipExpressionChange = (val: string) => { - updateProperties({ 'flowable:skipExpression': val }); -}; - -onBeforeMount(() => { - if (formData.value.conditionExpression) { - formData.value.conditionExpressionValue = formData.value.conditionExpression.body; - } -}); -</script> - -<style lang="scss" scoped></style> diff --git a/src/bpmn/panel/StartEndPanel.vue b/src/bpmn/panel/StartEndPanel.vue deleted file mode 100644 index bde1212..0000000 --- a/src/bpmn/panel/StartEndPanel.vue +++ /dev/null @@ -1,67 +0,0 @@ -<template> - <div> - <el-collapse v-model="currentCollapseItem"> - <el-collapse-item name="1"> - <template #title> - <div class="collapse__title"> - <el-icon> - <InfoFilled /> - </el-icon> - 甯歌 - </div> - </template> - <div> - <el-form ref="formRef" :model="formData" :rules="formRules" label-width="90px"> - <el-form-item prop="id" label="鑺傜偣 ID"> - <el-input v-model="formData.id" @change="idChange"> </el-input> - </el-form-item> - <el-form-item prop="name" label="鑺傜偣鍚嶇О"> - <el-input v-model="formData.name" @change="nameChange"> </el-input> - </el-form-item> - </el-form> - </div> - </el-collapse-item> - - <el-collapse-item name="2"> - <template #title> - <div class="collapse__title"> - <el-icon> - <BellFilled /> - </el-icon> - 鎵ц鐩戝惉鍣� - </div> - </template> - <div> - <ExecutionListener :element="element"></ExecutionListener> - </div> - </el-collapse-item> - </el-collapse> - </div> -</template> -<script setup lang="ts"> -import ExecutionListener from './property/ExecutionListener.vue'; -import useParseElement from '../hooks/useParseElement'; -import usePanel from '../hooks/usePanel'; -import type { Modeler, ModdleElement } from 'bpmn'; -import type { StartEndPanel } from 'bpmnDesign'; - -interface PropType { - element: ModdleElement; -} -const props = withDefaults(defineProps<PropType>(), {}); -const { nameChange, idChange } = usePanel({ - element: toRaw(props.element) -}); -const { parseData } = useParseElement({ - element: toRaw(props.element) -}); - -const formData = ref(parseData<StartEndPanel>()); -const currentCollapseItem = ref(['1', '2']); -const formRules = ref<ElFormRules>({ - id: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }], - name: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }] -}); -</script> - -<style lang="scss" scoped></style> diff --git a/src/bpmn/panel/SubProcessPanel.vue b/src/bpmn/panel/SubProcessPanel.vue deleted file mode 100644 index 3490fff..0000000 --- a/src/bpmn/panel/SubProcessPanel.vue +++ /dev/null @@ -1,193 +0,0 @@ -<template> - <div> - <el-form ref="formRef" :model="formData" :rules="formRules" label-width="90px"> - <el-collapse v-model="currentCollapseItem"> - <el-collapse-item name="1"> - <template #title> - <div class="collapse__title"> - <el-icon> - <InfoFilled /> - </el-icon> - 甯歌 - </div> - </template> - <div> - <el-form-item prop="id" label="鑺傜偣 ID"> - <el-input v-model="formData.id" @change="idChange"> </el-input> - </el-form-item> - <el-form-item prop="name" label="鑺傜偣鍚嶇О"> - <el-input v-model="formData.name" @change="nameChange"> </el-input> - </el-form-item> - </div> - </el-collapse-item> - - <el-collapse-item name="2"> - <template #title> - <div class="collapse__title"> - <el-icon> - <BellFilled /> - </el-icon> - 鎵ц鐩戝惉鍣� - </div> - </template> - <div> - <ExecutionListener :element="element"></ExecutionListener> - </div> - </el-collapse-item> - <el-collapse-item name="3"> - <template #title> - <div class="collapse__title"> - <el-icon> - <HelpFilled /> - </el-icon> - 澶氬疄渚� - </div> - </template> - <div> - <el-form-item label="澶氬疄渚嬬被鍨�"> - <el-select v-model="formData.multiInstanceType" @change="multiInstanceTypeChange"> - <el-option v-for="item in constant.MultiInstanceType" :key="item.id" :value="item.value" :label="item.label"> </el-option> - </el-select> - </el-form-item> - - <div v-if="formData.multiInstanceType !== MultiInstanceTypeEnum.NONE"> - <el-form-item label="闆嗗悎"> - <template #label> - <span> - 闆嗗悎 - <el-tooltip placement="top"> - <el-icon><QuestionFilled /></el-icon> - <template #content> - 灞炴�т細浣滀负琛ㄨ揪寮忚繘琛岃В鏋愩�傚鏋滆〃杈惧紡瑙f瀽涓哄瓧绗︿覆鑰屼笉鏄竴涓泦鍚堬紝<br /> - 涓嶈鏄洜涓烘湰韬厤缃殑灏辨槸闈欐�佸瓧绗︿覆鍊硷紝杩樻槸琛ㄨ揪寮忚绠楃粨鏋滀负瀛楃涓诧紝<br /> - 杩欎釜瀛楃涓查兘浼氳褰撳仛鍙橀噺鍚嶏紝骞朵粠娴佺▼鍙橀噺涓敤浜庤幏鍙栧疄闄呯殑闆嗗悎銆� - </template> - </el-tooltip> - </span> - </template> - <el-input v-model="formData.collection" @change="collectionChange"></el-input> - </el-form-item> - <el-form-item label="鍏冪礌鍙橀噺"> - <template #label> - <span> - 鍏冪礌鍙橀噺 - <el-tooltip placement="top"> - <el-icon><QuestionFilled /></el-icon> - <template #content> - 姣忓垱寤轰竴涓敤鎴蜂换鍔″墠锛屽厛浠ヨ鍏冪礌鍙橀噺涓簂abel锛岄泦鍚堜腑鐨勪竴椤逛负value锛�<br /> - 鍒涘缓锛堝眬閮級娴佺▼鍙橀噺锛岃灞�閮ㄦ祦绋嬪彉閲忚鐢ㄤ簬鎸囨淳鐢ㄦ埛浠诲姟銆�<br /> - 涓�鑸潵璇达紝璇ュ瓧绗︿覆搴斾笌鎸囧畾浜哄憳鍙橀噺鐩稿悓銆� - </template> - </el-tooltip> - </span> - </template> - <el-input v-model="formData.elementVariable" @change="elementVariableChange"> </el-input> - </el-form-item> - <el-form-item label="瀹屾垚鏉′欢"> - <template #label> - <span> - 瀹屾垚鏉′欢 - <el-tooltip placement="top"> - <el-icon><QuestionFilled /></el-icon> - <template #content> - 澶氬疄渚嬫椿鍔ㄥ湪鎵�鏈夊疄渚嬮兘瀹屾垚鏃剁粨鏉燂紝鐒惰�屼篃鍙互鎸囧畾涓�涓〃杈惧紡锛屽湪姣忎釜瀹炰緥<br /> - 缁撴潫鏃惰繘琛岃绠椼�傚綋琛ㄨ揪寮忚绠椾负true鏃讹紝灏嗛攢姣佹墍鏈夊墿浣欑殑瀹炰緥锛屽苟缁撴潫澶氬疄渚�<br /> - 娲诲姩锛岀户缁墽琛屾祦绋嬨�備緥濡� ${nrOfCompletedInstances/nrOfInstances >= 0.6 }锛�<br /> - 琛ㄧず褰撲换鍔″畬鎴�60%鏃讹紝璇ヨ妭鐐瑰氨绠楀畬鎴� - </template> - </el-tooltip> - </span> - </template> - <el-input v-model="formData.completionCondition" @change="completionConditionChange"> </el-input> - </el-form-item> - </div> - </div> - </el-collapse-item> - </el-collapse> - </el-form> - </div> -</template> -<script setup lang="ts"> -import ExecutionListener from './property/ExecutionListener.vue'; -import useParseElement from '../hooks/useParseElement'; -import usePanel from '../hooks/usePanel'; -import type { ModdleElement } from 'bpmn'; -import type { SubProcessPanel } from 'bpmnDesign'; -import { MultiInstanceTypeEnum } from '@/enums/bpmn/IndexEnums'; - -interface PropType { - element: ModdleElement; -} -const props = withDefaults(defineProps<PropType>(), {}); -const { nameChange, idChange, updateProperties, createModdleElement, constant } = usePanel({ - element: toRaw(props.element) -}); -const { parseData } = useParseElement({ - element: toRaw(props.element) -}); - -const formData = ref(parseData<SubProcessPanel>()); -const currentCollapseItem = ref(['1', '2', '3']); - -const multiInstanceTypeChange = (newVal) => { - if (newVal !== MultiInstanceTypeEnum.NONE) { - let loopCharacteristics = props.element.businessObject.get('loopCharacteristics'); - if (!loopCharacteristics) { - loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject); - } - loopCharacteristics.isSequential = newVal === MultiInstanceTypeEnum.SERIAL; - updateProperties({ loopCharacteristics: loopCharacteristics }); - } else { - updateProperties({ loopCharacteristics: undefined }); - } -}; -const collectionChange = (newVal) => { - let loopCharacteristics = props.element.businessObject.get('loopCharacteristics'); - if (!loopCharacteristics) { - loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject); - } - loopCharacteristics.collection = newVal && newVal.length > 0 ? newVal : undefined; - updateProperties({ loopCharacteristics: loopCharacteristics }); -}; -const elementVariableChange = (newVal) => { - let loopCharacteristics = props.element.businessObject.get('loopCharacteristics'); - if (!loopCharacteristics) { - loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject); - } - loopCharacteristics.elementVariable = newVal && newVal.length > 0 ? newVal : undefined; - updateProperties({ loopCharacteristics: loopCharacteristics }); -}; -const completionConditionChange = (newVal) => { - let loopCharacteristics = props.element.businessObject.get<ModdleElement>('loopCharacteristics'); - if (!loopCharacteristics) { - loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject); - } - if (newVal && newVal.length > 0) { - if (!loopCharacteristics.completionCondition) { - loopCharacteristics.completionCondition = createModdleElement('bpmn:Expression', { body: newVal }, loopCharacteristics); - } else { - loopCharacteristics.completionCondition.body = newVal; - } - } else { - loopCharacteristics.completionCondition = undefined; - } - updateProperties({ loopCharacteristics: loopCharacteristics }); -}; - -onBeforeMount(() => { - if (formData.value.loopCharacteristics) { - const loopCharacteristics = formData.value.loopCharacteristics; - formData.value.collection = loopCharacteristics.collection || ''; - formData.value.elementVariable = loopCharacteristics.elementVariable || ''; - formData.value.completionCondition = loopCharacteristics.completionCondition?.body || ''; - formData.value.multiInstanceType = loopCharacteristics.isSequential ? MultiInstanceTypeEnum.SERIAL : MultiInstanceTypeEnum.PARALLEL; - } -}); - -const formRules = ref<ElFormRules>({ - id: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }], - name: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }] -}); -</script> - -<style lang="scss" scoped></style> diff --git a/src/bpmn/panel/TaskPanel.vue b/src/bpmn/panel/TaskPanel.vue deleted file mode 100644 index a42de8a..0000000 --- a/src/bpmn/panel/TaskPanel.vue +++ /dev/null @@ -1,491 +0,0 @@ -<template> - <div> - <el-form ref="formRef" size="default" :model="formData" :rules="formRules" label-width="100px"> - <el-collapse v-model="currentCollapseItem"> - <el-collapse-item name="1"> - <template #title> - <div class="collapse__title"> - <el-icon> - <InfoFilled /> - </el-icon> - 甯歌 - </div> - </template> - <div> - <el-form-item prop="id" label="鑺傜偣 ID"> - <el-input v-model="formData.id" @change="idChange"> </el-input> - </el-form-item> - <el-form-item prop="name" label="鑺傜偣鍚嶇О"> - <el-input v-model="formData.name" @change="nameChange"> </el-input> - </el-form-item> - <el-form-item v-if="showConfig.skipExpression" prop="skipExpression" label="璺宠繃琛ㄨ揪寮�"> - <el-input v-model="formData.skipExpression" @change="skipExpressionChange"> </el-input> - </el-form-item> - <el-form-item v-loading="formManageListLoading" prop="formKey" label="琛ㄥ崟鍦板潃"> - <el-select v-model="formData.formKey" clearable filterable placeholder="璇烽�夋嫨琛ㄥ崟" style="width: 260px" @change="formKeyChange"> - <el-option - v-for="item in formManageList" - :key="item.id" - :label="item.formTypeName + ':' + item.formName" - :value="item.formType + ':' + item.id" - /> - </el-select> - </el-form-item> - </div> - </el-collapse-item> - <el-collapse-item name="2"> - <template #title> - <div class="collapse__title"> - <el-icon> - <Checked /> - </el-icon> - 浠诲姟 - </div> - </template> - <div> - <el-form-item v-if="showConfig.async" prop="sync" label="鏄惁寮傛"> - <el-switch v-model="formData.async" inline-prompt active-text="鏄�" inactive-text="鍚�" @change="syncChange" /> - </el-form-item> - - <el-tabs tab-position="left" class="demo-tabs"> - <el-tab-pane label="韬唤瀛樺偍"> - <el-form-item label="鍒嗛厤浜哄憳"> - <el-input v-model="formData.assignee" @blur="blurAssignee(formData.assignee)"> - <template #append> - <el-button icon="Search" type="primary" @click="openSingleUserSelect" /> - </template> - </el-input> - </el-form-item> - <el-form-item label="鍊欓�変汉鍛�"> - <el-badge :value="selectUserLength" :max="99"> - <el-button size="small" type="primary" @click="openUserSelect">閫夋嫨浜哄憳</el-button> - </el-badge> - </el-form-item> - <el-form-item label="鍊欓�夌粍"> - <el-badge :value="selectRoleLength" :max="99"> - <el-button size="small" type="primary" @click="openRoleSelect">閫夋嫨缁�</el-button> - </el-badge> - </el-form-item> - </el-tab-pane> - - <!-- <el-tab-pane label="鍥哄畾鍊�"> - <el-form-item prop="auditUserType" label="鍒嗛厤绫诲瀷"> - <el-select v-model="formData.allocationType"> - <el-option v-for="item in AllocationTypeSelect" :key="item.id" :value="item.value" :label="item.label"> </el-option> - </el-select> - </el-form-item> - <el-form-item v-if="formData.allocationType === AllocationTypeEnum.USER" label="鍒嗛厤浜哄憳"> - <el-input v-model="formData.assignee"> - <template #append> - <el-button icon="Search" type="primary" @click="openSingleUserSelect" /> - </template> - </el-input> - </el-form-item> - <div v-if="formData.allocationType === AllocationTypeEnum.CANDIDATE"> - <el-form-item label="鍊欓�変汉鍛�"> - <el-badge :value="selectUserLength" :max="99"> - <el-button size="small" type="primary" @click="openUserSelect">閫夋嫨浜哄憳</el-button> - </el-badge> - </el-form-item> - <el-form-item label="鍊欓�夌粍"> - <el-badge :value="selectRoleLength" :max="99"> - <el-button size="small" type="primary" @click="openRoleSelect">閫夋嫨缁�</el-button> - </el-badge> - </el-form-item> - </div> - <el-form-item v-if="formData.allocationType === AllocationTypeEnum.SPECIFY && showConfig.specifyDesc" style=""> - <el-radio-group v-model="formData.specifyDesc" class="ml-4"> - <el-radio v-for="item in SpecifyDesc" :key="item.id" :value="item.value" size="large">{{ item.label }}</el-radio> - </el-radio-group> - </el-form-item> - </el-tab-pane> --> - </el-tabs> - - <el-form-item v-if="showConfig.dueDate" prop="dueDate" label="鍒版湡鏃堕棿"> - <el-input v-model="formData.dueDate" clearable @change="dueDateChange" @click="openDueDate"> - <template #append> - <el-button icon="Search" type="primary" @click="openDueDate" /> - </template> - </el-input> - </el-form-item> - <el-form-item v-if="showConfig.priority" prop="priority" label="浼樺厛绾�"> - <el-input-number v-model="formData.priority" :min="0" @change="priorityChange"> </el-input-number> - </el-form-item> - </div> - </el-collapse-item> - <el-collapse-item name="3"> - <template #title> - <div class="collapse__title"> - <el-icon> - <HelpFilled /> - </el-icon> - 澶氬疄渚� - </div> - </template> - <div> - <el-form-item label="澶氬疄渚嬬被鍨�"> - <el-select v-model="formData.multiInstanceType" @change="multiInstanceTypeChange"> - <el-option v-for="item in constant.MultiInstanceType" :key="item.id" :value="item.value" :label="item.label"> </el-option> - </el-select> - </el-form-item> - - <div v-if="formData.multiInstanceType !== MultiInstanceTypeEnum.NONE"> - <el-form-item label="闆嗗悎"> - <template #label> - <span> - 闆嗗悎 - <el-tooltip placement="top"> - <el-icon><QuestionFilled /></el-icon> - <template #content> - 灞炴�т細浣滀负琛ㄨ揪寮忚繘琛岃В鏋愩�傚鏋滆〃杈惧紡瑙f瀽涓哄瓧绗︿覆鑰屼笉鏄竴涓泦鍚堬紝<br /> - 涓嶈鏄洜涓烘湰韬厤缃殑灏辨槸闈欐�佸瓧绗︿覆鍊硷紝杩樻槸琛ㄨ揪寮忚绠楃粨鏋滀负瀛楃涓诧紝<br /> - 杩欎釜瀛楃涓查兘浼氳褰撳仛鍙橀噺鍚嶏紝骞朵粠娴佺▼鍙橀噺涓敤浜庤幏鍙栧疄闄呯殑闆嗗悎銆� - </template> - </el-tooltip> - </span> - </template> - <el-input v-model="formData.collection" @change="collectionChange"></el-input> - </el-form-item> - <el-form-item label="鍏冪礌鍙橀噺"> - <template #label> - <span> - 鍏冪礌鍙橀噺 - <el-tooltip placement="top"> - <el-icon><QuestionFilled /></el-icon> - <template #content> - 姣忓垱寤轰竴涓敤鎴蜂换鍔″墠锛屽厛浠ヨ鍏冪礌鍙橀噺涓簂abel锛岄泦鍚堜腑鐨勪竴椤逛负value锛�<br /> - 鍒涘缓锛堝眬閮級娴佺▼鍙橀噺锛岃灞�閮ㄦ祦绋嬪彉閲忚鐢ㄤ簬鎸囨淳鐢ㄦ埛浠诲姟銆�<br /> - 涓�鑸潵璇达紝璇ュ瓧绗︿覆搴斾笌鎸囧畾浜哄憳鍙橀噺鐩稿悓銆� - </template> - </el-tooltip> - </span> - </template> - <el-input v-model="formData.elementVariable" @change="elementVariableChange"> </el-input> - </el-form-item> - <el-form-item label="瀹屾垚鏉′欢"> - <template #label> - <span> - 瀹屾垚鏉′欢 - <el-tooltip placement="top"> - <el-icon><QuestionFilled /></el-icon> - <template #content> - 澶氬疄渚嬫椿鍔ㄥ湪鎵�鏈夊疄渚嬮兘瀹屾垚鏃剁粨鏉燂紝鐒惰�屼篃鍙互鎸囧畾涓�涓〃杈惧紡锛屽湪姣忎釜瀹炰緥<br /> - 缁撴潫鏃惰繘琛岃绠椼�傚綋琛ㄨ揪寮忚绠椾负true鏃讹紝灏嗛攢姣佹墍鏈夊墿浣欑殑瀹炰緥锛屽苟缁撴潫澶氬疄渚�<br /> - 娲诲姩锛岀户缁墽琛屾祦绋嬨�備緥濡� ${nrOfCompletedInstances/nrOfInstances >= 0.6 }锛�<br /> - 琛ㄧず褰撲换鍔″畬鎴�60%鏃讹紝璇ヨ妭鐐瑰氨绠楀畬鎴� - </template> - </el-tooltip> - </span> - </template> - <el-input v-model="formData.completionCondition" @change="completionConditionChange"> </el-input> - </el-form-item> - </div> - </div> - </el-collapse-item> - <el-collapse-item v-if="showConfig.taskListener" name="4"> - <template #title> - <div class="collapse__title"> - <el-icon> - <BellFilled /> - </el-icon> - 浠诲姟鐩戝惉鍣� - </div> - </template> - <div> - <TaskListener v-if="showConfig.taskListener" :element="element"></TaskListener> - </div> - </el-collapse-item> - <el-collapse-item v-if="showConfig.executionListener" name="5"> - <template #title> - <div class="collapse__title"> - <el-icon> - <BellFilled /> - </el-icon> - 鎵ц鐩戝惉鍣� - </div> - </template> - <div> - <ExecutionListener v-if="showConfig.executionListener" :element="element"></ExecutionListener> - </div> - </el-collapse-item> - - <el-form-item v-if="showConfig.isForCompensation" prop="isForCompensation" label="鏄惁涓鸿ˉ鍋�"> - <el-switch v-model="formData.isForCompensation" inline-prompt active-text="鏄�" inactive-text="鍚�" /> - </el-form-item> - <el-form-item v-if="showConfig.triggerServiceTask" prop="triggerServiceTask" label="鏈嶅姟浠诲姟鍙Е鍙�"> - <el-switch v-model="formData.triggerServiceTask" inline-prompt active-text="鏄�" inactive-text="鍚�" /> - </el-form-item> - <el-form-item v-if="showConfig.autoStoreVariables" prop="autoStoreVariables" label="鑷姩瀛樺偍鍙橀噺"> - <el-switch v-model="formData.autoStoreVariables" inline-prompt active-text="鏄�" inactive-text="鍚�" /> - </el-form-item> - <el-form-item v-if="showConfig.ruleVariablesInput" prop="skipExpression" label="杈撳叆鍙橀噺"> - <el-input v-model="formData.ruleVariablesInput"> </el-input> - </el-form-item> - <el-form-item v-if="showConfig.exclude" prop="exclude" label="鎺掗櫎"> - <el-switch v-model="formData.exclude" inline-prompt active-text="鏄�" inactive-text="鍚�" /> - </el-form-item> - <el-form-item v-if="showConfig.class" prop="class" label="绫�"> - <el-input v-model="formData.class"> </el-input> - </el-form-item> - </el-collapse> - </el-form> - <UserSelect ref="userSelectRef" :data="formData.candidateUsers" @confirm-call-back="userSelectCallBack"></UserSelect> - <UserSelect ref="singleUserSelectRef" :data="formData.assignee" :multiple="false" @confirm-call-back="singleUserSelectCallBack"></UserSelect> - <RoleSelect ref="roleSelectRef" :data="formData.candidateGroups" @confirm-call-back="roleSelectCallBack"></RoleSelect> - <DueDate ref="dueDateRef" v-model="formData.dueDate" :data="formData.dueDate" @confirm-call-back="dueDateCallBack"></DueDate> - </div> -</template> -<script setup lang="ts"> -import useParseElement from '../hooks/useParseElement'; -import usePanel from '../hooks/usePanel'; -import UserSelect from '@/components/UserSelect'; -import RoleSelect from '@/components/RoleSelect'; -import ExecutionListener from './property/ExecutionListener.vue'; -import TaskListener from './property/TaskListener.vue'; -import DueDate from './property/DueDate.vue'; -import type { ModdleElement } from 'bpmn'; -import type { TaskPanel } from 'bpmnDesign'; -import { AllocationTypeEnum, MultiInstanceTypeEnum, SpecifyDescEnum } from '@/enums/bpmn/IndexEnums'; -import { UserVO } from '@/api/system/user/types'; -import { RoleVO } from '@/api/system/role/types'; -import { selectListFormManage } from '@/api/workflow/formManage'; -import { FormManageVO } from '@/api/workflow/formManage/types'; -const formManageList = ref<FormManageVO[]>([]); -const formManageListLoading = ref(false); -interface PropType { - element: ModdleElement; -} -const props = withDefaults(defineProps<PropType>(), {}); -const { showConfig, nameChange, formKeyChange, idChange, updateProperties, getExtensionElements, createModdleElement, constant } = usePanel({ - element: toRaw(props.element) -}); -const { parseData } = useParseElement({ - element: toRaw(props.element) -}); - -const initFormData = { - id: '', - name: '', - dueDate: '', - multiInstanceType: MultiInstanceTypeEnum.NONE, - allocationType: AllocationTypeEnum.USER, - specifyDesc: SpecifyDescEnum.SPECIFY_SINGLE -}; -const formData = ref({ ...initFormData, ...parseData<TaskPanel>() }); -const assignee = ref<Partial<UserVO>>({ - userName: '' -}); -const currentCollapseItem = ref(['1', '2']); -const userSelectRef = ref<InstanceType<typeof UserSelect>>(); -const singleUserSelectRef = ref<InstanceType<typeof UserSelect>>(); -const roleSelectRef = ref<InstanceType<typeof RoleSelect>>(); -const dueDateRef = ref<InstanceType<typeof DueDate>>(); - -const openUserSelect = () => { - userSelectRef.value.open(); -}; -const openSingleUserSelect = () => { - if (formData.value.assignee?.includes('$')) { - formData.value.assignee = ''; - } - singleUserSelectRef.value.open(); -}; -const openRoleSelect = () => { - roleSelectRef.value.open(); -}; -const openDueDate = (e) => { - dueDateRef.value.openDialog(); -}; -const blurAssignee = (assignee) => { - updateProperties({ 'flowable:assignee': assignee ? assignee : undefined }); -}; -const singleUserSelectCallBack = (data: UserVO[]) => { - const user: UserVO = data.length !== 0 ? data[0] : undefined; - updateProperties({ 'flowable:assignee': user?.userId }); - assignee.value = user ? user : { userName: '' }; - formData.value.assignee = String(user?.userId); - let extensionElements = getExtensionElements(); - extensionElements.values = extensionElements.get('values').filter((item) => item.$type !== 'flowable:extAssignee'); - if (user) { - const extAssigneeElement = createModdleElement('flowable:extAssignee', { body: '' }, extensionElements); - extensionElements.get('values').push(extAssigneeElement); - extAssigneeElement.body = JSON.stringify({ userName: user.userName, userId: user.userId }); - } - if (extensionElements.values.length === 0) { - extensionElements = undefined; - } - updateProperties({ extensionElements: extensionElements }); -}; -const userSelectCallBack = (data: UserVO[]) => { - let extensionElements = getExtensionElements(); - extensionElements.values = extensionElements.values.filter((item) => item.$type !== 'flowable:extCandidateUsers'); - if (data.length === 0) { - formData.value.candidateUsers = undefined; - updateProperties({ 'flowable:candidateUsers': undefined }); - } else { - const userIds = data.map((item) => item.userId).join(','); - formData.value.candidateUsers = userIds; - updateProperties({ 'flowable:candidateUsers': userIds }); - const extCandidateUsersElement = createModdleElement('flowable:extCandidateUsers', { body: '' }, extensionElements); - extensionElements.values.push(extCandidateUsersElement); - const users = data.map((item) => { - return { - userId: item.userId, - userName: item.userName - }; - }); - extCandidateUsersElement.body = JSON.stringify(users); - } - if (extensionElements.values.length === 0) { - extensionElements = undefined; - } - updateProperties({ extensionElements: extensionElements }); -}; -const roleSelectCallBack = (data: RoleVO[]) => { - if (data.length === 0) { - formData.value.candidateGroups = ''; - updateProperties({ 'flowable:candidateGroups': undefined }); - } else { - const roleIds = data.map((item) => item.roleId).join(','); - formData.value.candidateGroups = roleIds; - updateProperties({ 'flowable:candidateGroups': roleIds }); - } -}; -const dueDateCallBack = (data: string) => { - updateProperties({ 'flowable:dueDate': data }); -}; - -const taskTabClick = (e) => { - formData.value.candidateGroups = ''; - formData.value.candidateUsers = ''; - formData.value.assignee = ''; - // formData.value.fixedAssignee = ''; - assignee.value = {}; -}; - -const syncChange = (newVal) => { - updateProperties({ 'flowable:async': newVal }); -}; -const skipExpressionChange = (newVal) => { - updateProperties({ 'flowable:skipExpression': newVal && newVal.length > 0 ? newVal : undefined }); -}; -const priorityChange = (newVal) => { - updateProperties({ 'flowable:priority': newVal }); -}; -const fixedAssigneeChange = (newVal) => { - updateProperties({ 'flowable:assignee': newVal && newVal.length > 0 ? newVal : undefined }); -}; -const multiInstanceTypeChange = (newVal) => { - if (newVal !== MultiInstanceTypeEnum.NONE) { - let loopCharacteristics = props.element.businessObject.get('loopCharacteristics'); - if (!loopCharacteristics) { - loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject); - } - loopCharacteristics.isSequential = newVal === MultiInstanceTypeEnum.SERIAL; - updateProperties({ loopCharacteristics: loopCharacteristics }); - } else { - updateProperties({ loopCharacteristics: undefined }); - } -}; -const collectionChange = (newVal) => { - let loopCharacteristics = props.element.businessObject.get('loopCharacteristics'); - if (!loopCharacteristics) { - loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject); - } - loopCharacteristics.collection = newVal && newVal.length > 0 ? newVal : undefined; - updateProperties({ loopCharacteristics: loopCharacteristics }); -}; -const elementVariableChange = (newVal) => { - let loopCharacteristics = props.element.businessObject.get('loopCharacteristics'); - if (!loopCharacteristics) { - loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject); - } - loopCharacteristics.elementVariable = newVal && newVal.length > 0 ? newVal : undefined; - updateProperties({ loopCharacteristics: loopCharacteristics }); -}; -const completionConditionChange = (newVal) => { - let loopCharacteristics = props.element.businessObject.get<ModdleElement>('loopCharacteristics'); - if (!loopCharacteristics) { - loopCharacteristics = createModdleElement('bpmn:MultiInstanceLoopCharacteristics', {}, props.element.businessObject); - } - if (newVal && newVal.length > 0) { - if (!loopCharacteristics.completionCondition) { - loopCharacteristics.completionCondition = createModdleElement('bpmn:Expression', { body: newVal }, loopCharacteristics); - } else { - loopCharacteristics.completionCondition.body = newVal; - } - } else { - loopCharacteristics.completionCondition = undefined; - } - updateProperties({ loopCharacteristics: loopCharacteristics }); -}; -const dueDateChange = (newVal) => { - updateProperties({ 'flowable:dueDate': newVal && newVal.length > 0 ? newVal : undefined }); -}; -const selectUserLength = computed(() => { - if (formData.value.candidateUsers) { - return formData.value.candidateUsers.split(',').length; - } else { - return 0; - } -}); -const selectRoleLength = computed(() => { - if (formData.value.candidateGroups) { - return formData.value.candidateGroups.split(',').length; - } else { - return 0; - } -}); - -onBeforeMount(() => { - const extensionElements = getExtensionElements(false); - if (extensionElements && extensionElements.get('values')) { - let extAssigneeElement = extensionElements.get('values').find((item) => item.$type === 'flowable:extAssignee'); - if (extAssigneeElement) { - assignee.value = JSON.parse(extAssigneeElement.body); - } - } - - if (formData.value.loopCharacteristics) { - const loopCharacteristics = formData.value.loopCharacteristics; - formData.value.collection = loopCharacteristics.collection || ''; - formData.value.elementVariable = loopCharacteristics.elementVariable || ''; - formData.value.completionCondition = loopCharacteristics.completionCondition?.body || ''; - formData.value.multiInstanceType = loopCharacteristics.isSequential ? MultiInstanceTypeEnum.SERIAL : MultiInstanceTypeEnum.PARALLEL; - } - - if (formData.value.assignee) { - formData.value.fixedAssignee = formData.value.assignee; - } -}); - -const formRules = ref<ElFormRules>({ - id: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }], - name: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }] -}); - -const AllocationTypeSelect = [ - { id: 'b9cdf970-dd91-47c0-819f-42a7010ca2a6', label: '鎸囧畾浜哄憳', value: AllocationTypeEnum.USER }, - { id: '3f7ccbcd-c464-4602-bb9d-e96649d10585', label: '鍊欓�変汉鍛�', value: AllocationTypeEnum.CANDIDATE }, - { id: 'c49065e0-7f2d-4c09-aedb-ab2d47d9a454', label: '鍙戣捣浜鸿嚜宸�', value: AllocationTypeEnum.YOURSELF }, - { id: '6ef40a03-7e9a-4898-89b2-c88fe9064542', label: '鍙戣捣浜烘寚瀹�', value: AllocationTypeEnum.SPECIFY } -]; -const SpecifyDesc = [ - { id: 'fa253b34-4335-458c-b1bc-b039e2a2b7a6', label: '鎸囧畾涓�涓汉', value: 'specifySingle' }, - { id: '7365ff54-2e05-4312-9bfb-0b8edd779c5b', label: '鎸囧畾澶氫釜浜�', value: 'specifyMultiple' } -]; - -const listFormManage = async () => { - formManageListLoading.value = true; - const res = await selectListFormManage(); - formManageList.value = res.data; - formManageListLoading.value = false; -}; -onMounted(() => { - nextTick(() => { - listFormManage(); - }); -}); -</script> - -<style lang="scss" scoped></style> diff --git a/src/bpmn/panel/index.vue b/src/bpmn/panel/index.vue deleted file mode 100644 index 445571a..0000000 --- a/src/bpmn/panel/index.vue +++ /dev/null @@ -1,110 +0,0 @@ -<template> - <div ref="propertyPanel"> - <div v-if="nodeName" class="node-name">{{ nodeName }}</div> - <component :is="component" v-if="element" :element="element" /> - </div> -</template> -<script setup lang="ts" name="PropertyPanel"> -import { NodeName } from '../assets/lang/zh'; -import TaskPanel from './TaskPanel.vue'; -import ProcessPanel from './ProcessPanel.vue'; -import StartEndPanel from './StartEndPanel.vue'; -import GatewayPanel from './GatewayPanel.vue'; -import SequenceFlowPanel from './SequenceFlowPanel.vue'; -import ParticipantPanel from './ParticipantPanel.vue'; -import SubProcessPanel from './SubProcessPanel.vue'; -import type { Modeler, ModdleElement } from 'bpmn'; -const { proxy } = getCurrentInstance() as ComponentInternalInstance; -interface propsType { - modeler: Modeler; -} -const props = withDefaults(defineProps<propsType>(), {}); - -const element = ref<ModdleElement>(); -const processElement = ref<ModdleElement>(); - -const startEndType = ['bpmn:IntermediateThrowEvent', 'bpmn:StartEvent', 'bpmn:EndEvent']; -const taskType = [ - 'bpmn:UserTask', - 'bpmn:Task', - 'bpmn:SendTask', - 'bpmn:ReceiveTask', - 'bpmn:ManualTask', - 'bpmn:BusinessRuleTask', - 'bpmn:ServiceTask', - 'bpmn:ScriptTask' -]; -const sequenceType = ['bpmn:SequenceFlow']; -const gatewayType = ['bpmn:InclusiveGateway', 'bpmn:ExclusiveGateway', 'bpmn:ParallelGateway', 'bpmn:EventBasedGateway', 'bpmn:ComplexGateway']; -const processType = ['bpmn:Process']; - -// 缁勪欢璁$畻 -const component = computed(() => { - if (!element.value) return null; - const type = element.value.type; - if (startEndType.includes(type)) return StartEndPanel; - if (taskType.includes(type)) return TaskPanel; - if (sequenceType.includes(type)) return SequenceFlowPanel; - if (gatewayType.includes(type)) return GatewayPanel; - if (processType.includes(type)) return ProcessPanel; - if (type === 'bpmn:Participant') return ParticipantPanel; - if (type === 'bpmn:SubProcess') return SubProcessPanel; - //return proxy?.$modal.msgWarning('闈㈡澘寮�鍙戜腑....'); - return undefined; -}); - -const nodeName = computed(() => { - if (element.value) { - const bizObj = element.value.businessObject; - const type = bizObj?.eventDefinitions && bizObj?.eventDefinitions.length > 0 ? bizObj.eventDefinitions[0].$type : bizObj.$type; - return NodeName[type] || type; - } - return ''; -}); - -const handleModeler = () => { - props.modeler.on('root.added', (e: any) => { - element.value = null; - if (e.element.type === 'bpmn:Process') { - nextTick(() => { - element.value = e.element; - processElement.value = e.element; - }); - } - }); - props.modeler.on('element.click', (e: any) => { - if (e.element.type === 'bpmn:Process') { - nextTick(() => { - element.value = e.element; - processElement.value = e.element; - }); - } - }); - props.modeler.on('selection.changed', (e: any) => { - // 鍏堢粰null涓轰簡璁﹙ue鍒锋柊 - element.value = null; - const newElement = e.newSelection[0]; - if (newElement) { - nextTick(() => { - element.value = newElement; - }); - } else { - nextTick(() => { - element.value = processElement.value; - }); - } - }); -}; - -onMounted(() => { - handleModeler(); -}); -</script> - -<style scoped lang="scss"> -.node-name { - font-size: 16px; - font-weight: bold; - padding: 10px; -} -</style> diff --git a/src/bpmn/panel/property/DueDate.vue b/src/bpmn/panel/property/DueDate.vue deleted file mode 100644 index 882766b..0000000 --- a/src/bpmn/panel/property/DueDate.vue +++ /dev/null @@ -1,252 +0,0 @@ -<template> - <div> - <el-dialog v-model="visible" :title="title" width="600px" append-to-body> - <el-form label-width="100px"> - <el-form-item label="灏忔椂"> - <el-radio-group v-model="hourValue" @change="hourChange"> - <el-radio-button label="4" value="4" /> - <el-radio-button label="8" value="8" /> - <el-radio-button label="12" value="12" /> - <el-radio-button label="24" value="24" /> - <el-radio-button label="鑷畾涔�" value="鑷畾涔�" /> - <el-input-number v-show="hourValue === '鑷畾涔�'" v-model="customHourValue" :min="1" @change="customHourValueChange"></el-input-number> - </el-radio-group> - </el-form-item> - <el-form-item label="澶�"> - <el-radio-group v-model="dayValue" @change="dayChange"> - <el-radio-button label="1" value="1" /> - <el-radio-button label="2" value="2" /> - <el-radio-button label="3" value="3" /> - <el-radio-button label="4" value="4" /> - <el-radio-button label="鑷畾涔�" value="鑷畾涔�" /> - <el-input-number v-show="dayValue === '鑷畾涔�'" v-model="customDayValue" :min="1" @change="customDayValueChange"></el-input-number> - </el-radio-group> - </el-form-item> - <el-form-item label="鍛�"> - <el-radio-group v-model="weekValue" @change="weekChange"> - <el-radio-button label="1" value="1" /> - <el-radio-button label="2" value="2" /> - <el-radio-button label="3" value="3" /> - <el-radio-button label="4" value="4" /> - <el-radio-button label="鑷畾涔�" value="鑷畾涔�" /> - <el-input-number v-show="weekValue === '鑷畾涔�'" v-model="customWeekValue" :min="1" @change="customWeekValueChange"></el-input-number> - </el-radio-group> - </el-form-item> - <el-form-item label="鏈�"> - <el-radio-group v-model="monthValue" @change="monthChange"> - <el-radio-button label="1" value="1" /> - <el-radio-button label="2" value="2" /> - <el-radio-button label="3" value="3" /> - <el-radio-button label="4" value="4" /> - <el-radio-button label="鑷畾涔�" value="鑷畾涔�" /> - <el-input-number v-show="monthValue === '鑷畾涔�'" v-model="customMonthValue" :min="1" @change="customMonthValueChange"></el-input-number> - </el-radio-group> - </el-form-item> - </el-form> - - <template #footer> - <div> - <el-button @click="closeDialog">鍙栨秷</el-button> - <el-button type="primary" @click="confirm">纭畾</el-button> - </div> - </template> - </el-dialog> - </div> -</template> - -<script setup lang="ts"> -import useDialog from '@/hooks/useDialog'; - -interface PropType { - modelValue?: string; - data?: string; -} -const prop = withDefaults(defineProps<PropType>(), { - modelValue: '', - data: '' -}); -const emit = defineEmits(['update:modelValue', 'confirmCallBack']); - -const { title, visible, openDialog, closeDialog } = useDialog({ - title: '璁剧疆浠诲姟鍒版湡鏃堕棿' -}); -const formValue = ref(); -const valueType = ref(); - -const hourValue = ref(''); -const dayValue = ref(''); -const weekValue = ref(''); -const monthValue = ref(''); - -const customHourValue = ref(1); -const customDayValue = ref(1); -const customWeekValue = ref(1); -const customMonthValue = ref(1); - -const hourValueConst = ['4', '8', '12', '24']; -const dayAndWeekAndMonthValueConst = ['1', '2', '3', '4']; - -const initValue = () => { - formValue.value = prop.data; - if (prop.data) { - const lastStr = prop.data.substring(prop.data.length - 1); - if (lastStr === 'H') { - const hourValueValue = prop.data.substring(2, prop.data.length - 1); - if (hourValueConst.includes(hourValueValue)) { - hourValue.value = hourValueValue; - } else { - hourValue.value = '鑷畾涔�'; - customHourValue.value = Number(hourValueValue); - } - } - const dayAndWeekAndMonthValue = prop.data.substring(1, prop.data.length - 1); - if (lastStr === 'D') { - if (dayAndWeekAndMonthValueConst.includes(dayAndWeekAndMonthValue)) { - dayValue.value = dayAndWeekAndMonthValue; - } else { - dayValue.value = '鑷畾涔�'; - customDayValue.value = Number(dayAndWeekAndMonthValue); - } - } - if (lastStr === 'W') { - if (dayAndWeekAndMonthValueConst.includes(dayAndWeekAndMonthValue)) { - weekValue.value = dayAndWeekAndMonthValue; - } else { - weekValue.value = '鑷畾涔�'; - customWeekValue.value = Number(dayAndWeekAndMonthValue); - } - } - if (lastStr === 'M') { - if (dayAndWeekAndMonthValueConst.includes(dayAndWeekAndMonthValue)) { - monthValue.value = dayAndWeekAndMonthValue; - } else { - monthValue.value = '鑷畾涔�'; - customMonthValue.value = Number(dayAndWeekAndMonthValue); - } - } - } -}; - -const confirm = () => { - emit('update:modelValue', formValue.value); - emit('confirmCallBack', formValue.value); - closeDialog(); -}; - -const customHourValueChange = (customHourValue) => { - formValue.value = `PT${customHourValue}H`; - - dayValue.value = ''; - weekValue.value = ''; - monthValue.value = ''; - customDayValue.value = 1; - customWeekValue.value = 1; - customMonthValue.value = 1; -}; -const customDayValueChange = (customDayValue) => { - formValue.value = `P${customDayValue}D`; - hourValue.value = ''; - weekValue.value = ''; - monthValue.value = ''; - - customHourValue.value = 1; - customWeekValue.value = 1; - customMonthValue.value = 1; -}; - -const customWeekValueChange = (customWeekValue) => { - formValue.value = `P${customWeekValue}W`; - hourValue.value = ''; - dayValue.value = ''; - monthValue.value = ''; - - customHourValue.value = 1; - customDayValue.value = 1; - customMonthValue.value = 1; -}; - -const customMonthValueChange = (customMonthValue) => { - formValue.value = `P${customMonthValue}M`; - hourValue.value = ''; - dayValue.value = ''; - weekValue.value = ''; - - customHourValue.value = 1; - customDayValue.value = 1; - customWeekValue.value = 1; -}; - -const hourChange = (hourValue) => { - if (hourValue === '鑷畾涔�') { - formValue.value = `PT${customHourValue.value}H`; - } else { - formValue.value = `PT${hourValue}H`; - } - - dayValue.value = ''; - weekValue.value = ''; - monthValue.value = ''; - customDayValue.value = 1; - customWeekValue.value = 1; - customMonthValue.value = 1; -}; -const dayChange = (dayValue) => { - if (dayValue === '鑷畾涔�') { - formValue.value = `P${customDayValue.value}D`; - } else { - formValue.value = `P${dayValue}D`; - } - - hourValue.value = ''; - weekValue.value = ''; - monthValue.value = ''; - - customHourValue.value = 1; - customWeekValue.value = 1; - customMonthValue.value = 1; -}; -const weekChange = (weekValue) => { - if (weekValue === '鑷畾涔�') { - formValue.value = `P${customWeekValue.value}W`; - } else { - formValue.value = `P${weekValue}W`; - } - - hourValue.value = ''; - dayValue.value = ''; - monthValue.value = ''; - - customHourValue.value = 1; - customDayValue.value = 1; - customMonthValue.value = 1; -}; -const monthChange = (monthValue) => { - if (monthValue === '鑷畾涔�') { - formValue.value = `P${customMonthValue.value}M`; - } else { - formValue.value = `P${monthValue}M`; - } - - hourValue.value = ''; - dayValue.value = ''; - weekValue.value = ''; - - customHourValue.value = 1; - customDayValue.value = 1; - customWeekValue.value = 1; -}; - -watch( - () => visible.value, - () => { - if (visible.value) { - initValue(); - } - } -); - -defineExpose({ - openDialog, - closeDialog -}); -</script> diff --git a/src/bpmn/panel/property/ExecutionListener.vue b/src/bpmn/panel/property/ExecutionListener.vue deleted file mode 100644 index 3c584cb..0000000 --- a/src/bpmn/panel/property/ExecutionListener.vue +++ /dev/null @@ -1,308 +0,0 @@ -<template> - <div> - <vxe-toolbar> - <template #buttons> - <el-button type="primary" link size="small" @click="insertEvent">鏂板</el-button> - <el-button type="primary" link size="small" @click="removeSelectRowEvent">鍒犻櫎</el-button> - </template> - </vxe-toolbar> - <vxe-table - ref="tableRef" - size="mini" - height="100px" - border - show-overflow - keep-source - :data="tableData" - :menu-config="menuConfig" - @cell-dblclick="cellDBLClickEvent" - @menu-click="contextMenuClickEvent" - > - <vxe-column type="checkbox" width="40"></vxe-column> - <vxe-column type="seq" width="40"></vxe-column> - <vxe-column field="event" title="浜嬩欢" min-width="100px"> - <template #default="slotParams"> - <span>{{ eventSelect.find((e) => e.value === slotParams.row.event)?.label }}</span> - </template> - </vxe-column> - <vxe-column field="type" title="绫诲瀷" min-width="100px"> - <template #default="slotParams"> - <span>{{ typeSelect.find((e) => e.value === slotParams.row.type)?.label }}</span> - </template> - </vxe-column> - <vxe-column field="className" title="Java 绫诲悕" min-width="100px"> </vxe-column> - </vxe-table> - - <el-dialog - v-model="formDialog.visible.value" - :title="formDialog.title.value" - width="600px" - :close-on-click-modal="false" - :close-on-press-escape="false" - :show-close="false" - append-to-body - > - <el-form ref="formRef" :model="formData" :rules="tableRules" label-width="100px"> - <el-form-item label="浜嬩欢" prop="event"> - <el-select v-model="formData.event"> - <el-option v-for="item in eventSelect" :key="item.id" :value="item.value" :label="item.label"></el-option> - </el-select> - </el-form-item> - <el-form-item label="绫诲瀷" prop="type"> - <template #label> - <span> - 绫诲瀷 - <el-tooltip placement="top"> - <el-icon><QuestionFilled /></el-icon> - <template #content> - 绫伙細绀轰緥 com.company.MyCustomListener锛岃嚜瀹氫箟绫诲繀椤诲疄鐜� org.flowable.engine.delegate.TaskListener 鎺ュ彛<br /> - 琛ㄨ揪寮忥細绀轰緥 ${myObject.callMethod(task, task.eventName)}<br /> - 濮旀墭琛ㄨ揪寮忥細绀轰緥 ${myListenerSpringBean} 锛岃 springBean 闇�瑕佸疄鐜� org.flowable.engine.delegate.TaskListener 鎺ュ彛 - </template> - </el-tooltip> - </span> - </template> - <el-select v-model="formData.type"> - <el-option v-for="item in typeSelect" :key="item.id" :value="item.value" :label="item.label"></el-option> - </el-select> - </el-form-item> - <el-form-item - :label="typeSelect.filter((e) => e.value === formData.type)[0] ? typeSelect.filter((e) => e.value === formData.type)[0]?.label : '琛ㄨ揪寮�'" - prop="className" - > - <el-input v-model="formData.className" type="text"></el-input> - </el-form-item> - </el-form> - <el-tabs type="border-card"> - <el-tab-pane label="鍙傛暟"> - <ListenerParam ref="listenerParamRef" :table-data="formData.params" /> - </el-tab-pane> - </el-tabs> - <template #footer> - <div class="dialog-footer"> - <el-button @click="formDialog.closeDialog">鍙� 娑�</el-button> - <el-button type="primary" @click="submitEvent">纭� 瀹�</el-button> - </div> - </template> - </el-dialog> - </div> -</template> -<script setup lang="ts"> -import ListenerParam from './ListenerParam.vue'; -import { VxeTableEvents, VxeTableInstance, VxeTablePropTypes } from 'vxe-table'; -import type { ExecutionListenerVO } from 'bpmnDesign'; -import type { Moddle, Modeler, ModdleElement } from 'bpmn'; - -import usePanel from '../../hooks/usePanel'; -import useDialog from '@/hooks/useDialog'; -import useModelerStore from '@/store/modules/modeler'; - -const emit = defineEmits(['close']); -interface PropType { - element: ModdleElement; -} -const props = withDefaults(defineProps<PropType>(), {}); - -const { proxy } = getCurrentInstance() as ComponentInternalInstance; - -const selectRow = ref<ExecutionListenerVO | null>(); -const formDialog = useDialog({ - title: selectRow.value ? '缂栬緫&淇濆瓨' : '鏂板&淇濆瓨' -}); - -const { showConfig, elementType, updateProperties } = usePanel({ - element: toRaw(props.element) -}); -const { getModdle } = useModelerStore(); -const moddle = getModdle(); - -const listenerParamRef = ref<InstanceType<typeof ListenerParam>>(); -const tableRef = ref<VxeTableInstance<ExecutionListenerVO>>(); -const formRef = ref<ElFormInstance>(); - -const initData: ExecutionListenerVO = { - event: '', - type: '', - className: '', - params: [] -}; -const formData = ref<ExecutionListenerVO>({ ...initData }); -const tableData = ref<ExecutionListenerVO[]>([]); -const tableRules = ref<ElFormRules>({ - event: [{ required: true, message: '璇烽�夋嫨', trigger: 'blur' }], - type: [{ required: true, message: '璇烽�夋嫨', trigger: 'blur' }], - className: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }] -}); - -const submitEvent = async () => { - const error = await listenerParamRef.value.validate(); - await formRef.value.validate((validate) => { - if (validate && !error) { - const $table = tableRef.value; - if ($table) { - formData.value.params = listenerParamRef.value.getTableData(); - if (selectRow.value) { - Object.assign(selectRow.value, formData.value); - } else { - $table.insertAt({ ...formData.value }, -1); - } - updateElement(); - formDialog.closeDialog(); - } - } - }); -}; - -const removeSelectRowEvent = async () => { - const $table = tableRef.value; - if ($table) { - const selectCount = $table.getCheckboxRecords().length; - if (selectCount === 0) { - proxy?.$modal.msgWarning('璇烽�夋嫨琛�'); - } else { - await $table.removeCheckboxRow(); - updateElement(); - } - } -}; -const insertEvent = async () => { - Object.assign(formData.value, initData); - selectRow.value = null; - formDialog.openDialog(); -}; - -const editEvent = (row: ExecutionListenerVO) => { - Object.assign(formData.value, row); - selectRow.value = row; - formDialog.openDialog(); -}; - -const removeEvent = async (row: ExecutionListenerVO) => { - await proxy?.$modal.confirm('鎮ㄧ‘瀹氳鍒犻櫎璇ユ暟鎹�?'); - const $table = tableRef.value; - if ($table) { - await $table.remove(row); - updateElement(); - } -}; -const updateElement = () => { - const $table = tableRef.value; - const data = $table.getTableData().fullData; - if (data.length) { - let extensionElements = props.element.businessObject.get('extensionElements'); - if (!extensionElements) { - extensionElements = moddle.create('bpmn:ExtensionElements'); - } - // 娓呴櫎鏃у�� - extensionElements.values = extensionElements.values?.filter((item) => item.$type !== 'flowable:ExecutionListener') ?? []; - data.forEach((item) => { - const executionListener = moddle.create('flowable:ExecutionListener'); - executionListener['event'] = item.event; - executionListener[item.type] = item.className; - if (item.params && item.params.length) { - item.params.forEach((field) => { - const fieldElement = moddle.create('flowable:Field'); - fieldElement['name'] = field.name; - fieldElement[field.type] = field.value; - executionListener.get('fields').push(fieldElement); - }); - } - extensionElements.get('values').push(executionListener); - }); - updateProperties({ extensionElements: extensionElements }); - } else { - const extensionElements = props.element.businessObject[`extensionElements`]; - if (extensionElements) { - extensionElements.values = extensionElements.values?.filter((item) => item.$type !== 'flowable:ExecutionListener') ?? []; - } - } -}; - -const cellDBLClickEvent: VxeTableEvents.CellDblclick<ExecutionListenerVO> = ({ row }) => { - editEvent(row); -}; - -const menuConfig = reactive<VxeTablePropTypes.MenuConfig<ExecutionListenerVO>>({ - body: { - options: [ - [ - { code: 'edit', name: '缂栬緫', prefixIcon: 'vxe-icon-edit', disabled: false }, - { code: 'remove', name: '鍒犻櫎', prefixIcon: 'vxe-icon-delete', disabled: false } - ] - ] - }, - visibleMethod({ options, column }) { - const isDisabled = !column; - options.forEach((list) => { - list.forEach((item) => { - item.disabled = isDisabled; - }); - }); - return true; - } -}); -const contextMenuClickEvent: VxeTableEvents.MenuClick<ExecutionListenerVO> = ({ menu, row, column }) => { - const $table = tableRef.value; - if ($table) { - switch (menu.code) { - case 'edit': - editEvent(row); - break; - case 'remove': - removeEvent(row); - break; - } - } -}; - -const initTableData = () => { - tableData.value = - props.element.businessObject.extensionElements?.values - .filter((item) => item.$type === 'flowable:ExecutionListener') - .map((item) => { - let type; - if ('class' in item) type = 'class'; - if ('expression' in item) type = 'expression'; - if ('delegateExpression' in item) type = 'delegateExpression'; - return { - event: item.event, - type: type, - className: item[type], - params: - item.fields?.map((field) => { - let fieldType; - if ('stringValue' in field) fieldType = 'stringValue'; - if ('expression' in field) fieldType = 'expression'; - return { - name: field.name, - type: fieldType, - value: field[fieldType] - }; - }) ?? [] - }; - }) ?? []; -}; - -onMounted(() => { - initTableData(); -}); - -const typeSelect = [ - { id: '742fdeb7-23b4-416b-ac66-cd4ec8b901b7', label: '绫�', value: 'class' }, - { id: '660c9c46-8fae-4bae-91a0-0335420019dc', label: '琛ㄨ揪寮�', value: 'expression' }, - { id: '4b8135ab-6bc3-4a0f-80be-22f58bc6c5fd', label: '濮旀墭琛ㄨ揪寮�', value: 'delegateExpression' } -]; -const eventSelect = [ - { id: 'e6e0a51a-2d5d-4dc4-b847-b5c14f43a6ab', label: '寮�濮�', value: 'start' }, - { id: '6da97c1e-15fc-4445-8943-75d09f49778e', label: '缁撴潫', value: 'end' }, - { id: '6a2cbcec-e026-4f11-bef7-fff0b5c871e2', label: '鍚敤', value: 'take' } -]; -</script> - -<style scoped lang="scss"> -.el-badge { - :deep(.el-badge__content) { - top: 10px; - } -} -</style> diff --git a/src/bpmn/panel/property/ListenerParam.vue b/src/bpmn/panel/property/ListenerParam.vue deleted file mode 100644 index 21c6de1..0000000 --- a/src/bpmn/panel/property/ListenerParam.vue +++ /dev/null @@ -1,121 +0,0 @@ -<template> - <vxe-toolbar> - <template #buttons> - <el-button icon="Plus" @click="insertRow">鏂板</el-button> - </template> - </vxe-toolbar> - <vxe-table - ref="tableRef" - :height="height" - border - show-overflow - keep-source - :data="tableData" - :edit-rules="tableRules" - :edit-config="{ trigger: 'click', mode: 'row', showStatus: true }" - > - <vxe-column type="seq" width="40"></vxe-column> - <vxe-column field="type" title="绫诲瀷" :edit-render="{}"> - <template #default="slotParams"> - <span>{{ typeSelect.find((e) => e.value === slotParams.row.type)?.label }}</span> - </template> - <template #edit="slotParams"> - <vxe-select v-model="slotParams.row.type"> - <vxe-option v-for="item in typeSelect" :key="item.id" :value="item.value" :label="item.label"></vxe-option> - </vxe-select> - </template> - </vxe-column> - <vxe-column field="name" title="鍚嶇О" :edit-render="{}"> - <template #edit="slotParams"> - <vxe-input v-model="slotParams.row.name" type="text"></vxe-input> - </template> - </vxe-column> - <vxe-column field="value" title="鍊�" :edit-render="{}"> - <template #edit="slotParams"> - <vxe-input v-model="slotParams.row.value" type="text"></vxe-input> - </template> - </vxe-column> - <vxe-column title="鎿嶄綔" width="100" show-overflow align="center"> - <template #default="slotParams"> - <el-tooltip content="鍒犻櫎" placement="top"> - <el-button link type="danger" icon="Delete" @click="removeRow(slotParams.row)"></el-button> - </el-tooltip> - </template> - </vxe-column> - </vxe-table> -</template> - -<script setup lang="ts"> -import { VXETable, VxeTableInstance, VxeTablePropTypes } from 'vxe-table'; -import type { ParamVO } from 'bpmnDesign'; -import useDialog from '@/hooks/useDialog'; - -interface PropType { - height?: string; - tableData?: ParamVO[]; -} - -const { proxy } = getCurrentInstance() as ComponentInternalInstance; - -const props = withDefaults(defineProps<PropType>(), { - height: '200px', - tableData: () => [] -}); - -const tableRules = ref<VxeTablePropTypes.EditRules>({ - type: [{ required: true, message: '璇烽�夋嫨', trigger: 'blur' }], - name: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }], - value: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }] -}); - -const { title, visible, openDialog, closeDialog } = useDialog({ - title: '鐩戝惉鍣ㄥ弬鏁�' -}); -const typeSelect = [ - { id: '742fdeb7-23b4-416b-ac66-cd4ec8b901b7', label: '瀛楃涓�', value: 'stringValue' }, - { id: '660c9c46-8fae-4bae-91a0-0335420019dc', label: '琛ㄨ揪寮�', value: 'expression' } -]; - -const tableRef = ref<VxeTableInstance<ParamVO>>(); - -const getTableData = () => { - const $table = tableRef.value; - if ($table) { - return $table.getTableData().fullData; - } - return []; -}; - -const insertRow = async () => { - const $table = tableRef.value; - if ($table) { - const { row: newRow } = await $table.insertAt({}, -1); - // 鎻掑叆涓�鏉℃暟鎹苟瑙﹀彂鏍¢獙 - await $table.validate(newRow); - } -}; - -const removeRow = async (row: ParamVO) => { - await proxy?.$modal.confirm('鎮ㄧ‘瀹氳鍒犻櫎璇ユ暟鎹�?'); - const $table = tableRef.value; - if ($table) { - await $table.remove(row); - } -}; - -const validate = async () => { - const $table = tableRef.value; - if ($table) { - return await $table.validate(true); - } -}; - -defineExpose({ - closeDialog, - openDialog, - validate, - getTableData -}); -</script> - -<style scoped lang="scss"></style> diff --git a/src/bpmn/panel/property/TaskListener.vue b/src/bpmn/panel/property/TaskListener.vue deleted file mode 100644 index 9a32c47..0000000 --- a/src/bpmn/panel/property/TaskListener.vue +++ /dev/null @@ -1,310 +0,0 @@ -<template> - <div> - <vxe-toolbar> - <template #buttons> - <el-button type="primary" link size="small" @click="insertEvent">鏂板</el-button> - <el-button type="primary" link size="small" @click="removeSelectRowEvent">鍒犻櫎</el-button> - </template> - </vxe-toolbar> - <vxe-table - ref="tableRef" - size="mini" - height="100px" - border - show-overflow - keep-source - :data="tableData" - :menu-config="menuConfig" - @cell-dblclick="cellDBLClickEvent" - @menu-click="contextMenuClickEvent" - > - <vxe-column type="checkbox" width="40"></vxe-column> - <vxe-column type="seq" width="40"></vxe-column> - <vxe-column field="event" title="浜嬩欢" min-width="100px"> - <template #default="slotParams"> - <span>{{ eventSelect.find((e) => e.value === slotParams.row.event)?.label }}</span> - </template> - </vxe-column> - <vxe-column field="type" title="绫诲瀷" min-width="100px"> - <template #default="slotParams"> - <span>{{ typeSelect.find((e) => e.value === slotParams.row.type)?.label }}</span> - </template> - </vxe-column> - <vxe-column field="className" title="Java 绫诲悕" min-width="100px"> </vxe-column> - </vxe-table> - - <el-dialog - v-model="formDialog.visible.value" - :title="formDialog.title.value" - width="600px" - :close-on-click-modal="false" - :close-on-press-escape="false" - :show-close="false" - append-to-body - > - <el-form ref="formRef" :model="formData" :rules="tableRules" label-width="100px"> - <el-form-item label="浜嬩欢" prop="event"> - <template #label> - <span> - 浜嬩欢 - <el-tooltip placement="top"> - <el-icon><QuestionFilled /></el-icon> - <template #content> - create锛堝垱寤猴級锛氬綋浠诲姟宸茬粡鍒涘缓锛屽苟涓旀墍鏈変换鍔″弬鏁伴兘宸茬粡璁剧疆鏃惰Е鍙戙��<br /> - assignment锛堟寚娲撅級锛氬綋浠诲姟宸茬粡鎸囨淳缁欐煇浜烘椂瑙﹀彂銆傝娉ㄦ剰锛氬綋娴佺▼鎵ц鍒拌揪鐢ㄦ埛浠诲姟鏃讹紝鍦ㄨЕ鍙慶reate浜嬩欢涔嬪墠锛屼細棣栧厛瑙﹀彂assignment浜嬩欢銆�<br /> - complete锛堝畬鎴愶級锛氬綋浠诲姟宸茬粡瀹屾垚锛屼粠杩愯鏃舵暟鎹腑鍒犻櫎鍓嶈Е鍙戙��<br /> - delete锛堝垹闄わ級锛氬湪浠诲姟鍗冲皢琚垹闄ゅ墠瑙﹀彂銆傝娉ㄦ剰浠诲姟鐢眂ompleteTask姝e父瀹屾垚鏃朵篃浼氳Е鍙戙�� - </template> - </el-tooltip> - </span> - </template> - <el-select v-model="formData.event"> - <el-option v-for="item in eventSelect" :key="item.id" :value="item.value" :label="item.label"></el-option> - </el-select> - </el-form-item> - <el-form-item label="绫诲瀷" prop="type"> - <el-select v-model="formData.type"> - <el-option v-for="item in typeSelect" :key="item.id" :value="item.value" :label="item.label"></el-option> - </el-select> - </el-form-item> - <el-form-item - :label="typeSelect.filter((e) => e.value === formData.type)[0] ? typeSelect.filter((e) => e.value === formData.type)[0]?.label : '琛ㄨ揪寮�'" - prop="className" - > - <el-input v-model="formData.className" type="text"></el-input> - </el-form-item> - </el-form> - <el-tabs type="border-card"> - <el-tab-pane label="鍙傛暟"> - <ListenerParam ref="listenerParamRef" :table-data="formData.params" /> - </el-tab-pane> - </el-tabs> - <template #footer> - <div class="dialog-footer"> - <el-button @click="formDialog.closeDialog">鍙� 娑�</el-button> - <el-button type="primary" @click="submitEvent">纭� 瀹�</el-button> - </div> - </template> - </el-dialog> - </div> -</template> -<script setup lang="ts"> -import ListenerParam from './ListenerParam.vue'; -import { VxeTableEvents, VxeTableInstance, VxeTablePropTypes } from 'vxe-table'; -import type { TaskListenerVO } from 'bpmnDesign'; -import type { ModdleElement } from 'bpmn'; - -import usePanel from '../../hooks/usePanel'; -import useDialog from '@/hooks/useDialog'; -import useModelerStore from '@/store/modules/modeler'; - -const { proxy } = getCurrentInstance() as ComponentInternalInstance; - -interface PropType { - element: ModdleElement; -} -const props = withDefaults(defineProps<PropType>(), {}); - -const selectRow = ref<TaskListenerVO | null>(); -const formDialog = useDialog({ - title: selectRow.value ? '缂栬緫&淇濆瓨' : '鏂板&淇濆瓨' -}); -const { showConfig, elementType, updateProperties } = usePanel({ - element: toRaw(props.element) -}); -const { getModdle } = useModelerStore(); -const moddle = getModdle(); - -const listenerParamRef = ref<InstanceType<typeof ListenerParam>>(); -const tableRef = ref<VxeTableInstance<TaskListenerVO>>(); -const formRef = ref<ElFormInstance>(); - -const initData: TaskListenerVO = { - event: '', - type: '', - className: '', - name: '', - params: [] -}; -const formData = ref<TaskListenerVO>({ ...initData }); -const currentIndex = ref(0); -const tableData = ref<TaskListenerVO[]>([]); -const tableRules = ref<VxeTablePropTypes.EditRules>({ - event: [{ required: true, message: '璇烽�夋嫨', trigger: 'blur' }], - type: [{ required: true, message: '璇烽�夋嫨', trigger: 'blur' }], - name: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }], - className: [{ required: true, message: '璇疯緭鍏�', trigger: 'blur' }] -}); - -const submitEvent = async () => { - const error = await listenerParamRef.value.validate(); - await formRef.value.validate((validate) => { - if (validate && !error) { - const $table = tableRef.value; - if ($table) { - formData.value.params = listenerParamRef.value.getTableData(); - if (selectRow.value) { - Object.assign(selectRow.value, formData.value); - } else { - $table.insertAt({ ...formData.value }, -1); - } - updateElement(); - formDialog.closeDialog(); - } - } - }); -}; - -const insertEvent = async () => { - Object.assign(formData.value, initData); - selectRow.value = null; - formDialog.openDialog(); -}; - -const editEvent = (row: TaskListenerVO) => { - Object.assign(formData.value, row); - selectRow.value = row; - formDialog.openDialog(); -}; -const removeEvent = async (row: TaskListenerVO) => { - await proxy?.$modal.confirm('鎮ㄧ‘瀹氳鍒犻櫎璇ユ暟鎹�?'); - const $table = tableRef.value; - if ($table) { - await $table.remove(row); - updateElement(); - } -}; - -const removeSelectRowEvent = async () => { - const $table = tableRef.value; - if ($table) { - const selectCount = $table.getCheckboxRecords().length; - if (selectCount === 0) { - proxy?.$modal.msgWarning('璇烽�夋嫨琛�'); - } else { - await $table.removeCheckboxRow(); - updateElement(); - } - } -}; -const updateElement = () => { - const $table = tableRef.value; - const data = $table.getTableData().fullData; - if (data.length) { - let extensionElements = props.element.businessObject.get('extensionElements'); - if (!extensionElements) { - extensionElements = moddle.create('bpmn:ExtensionElements'); - } - // 娓呴櫎鏃у�� - extensionElements.values = extensionElements.values?.filter((item) => item.$type !== 'flowable:TaskListener') ?? []; - data.forEach((item) => { - const taskListener = moddle.create('flowable:TaskListener'); - taskListener['event'] = item.event; - taskListener[item.type] = item.className; - if (item.params && item.params.length) { - item.params.forEach((field) => { - const fieldElement = moddle.create('flowable:Field'); - fieldElement['name'] = field.name; - fieldElement[field.type] = field.value; - taskListener.get('fields').push(fieldElement); - }); - } - extensionElements.get('values').push(taskListener); - }); - updateProperties({ extensionElements: extensionElements }); - } else { - const extensionElements = props.element.businessObject[`extensionElements`]; - if (extensionElements) { - extensionElements.values = extensionElements.values?.filter((item) => item.$type !== 'flowable:TaskListener') ?? []; - } - } -}; - -const cellDBLClickEvent: VxeTableEvents.CellDblclick<TaskListenerVO> = ({ row }) => { - editEvent(row); -}; - -const menuConfig = reactive<VxeTablePropTypes.MenuConfig<TaskListenerVO>>({ - body: { - options: [ - [ - { code: 'edit', name: '缂栬緫', prefixIcon: 'vxe-icon-edit', disabled: false }, - { code: 'remove', name: '鍒犻櫎', prefixIcon: 'vxe-icon-delete', disabled: false } - ] - ] - }, - visibleMethod({ options, column }) { - const isDisabled = !column; - options.forEach((list) => { - list.forEach((item) => { - item.disabled = isDisabled; - }); - }); - return true; - } -}); -const contextMenuClickEvent: VxeTableEvents.MenuClick<TaskListenerVO> = ({ menu, row, column }) => { - const $table = tableRef.value; - if ($table) { - switch (menu.code) { - case 'edit': - editEvent(row); - break; - case 'remove': - removeEvent(row); - break; - } - } -}; -const initTableData = () => { - tableData.value = - props.element.businessObject.extensionElements?.values - .filter((item) => item.$type === 'flowable:TaskListener') - .map((item) => { - let type; - if ('class' in item) type = 'class'; - if ('expression' in item) type = 'expression'; - if ('delegateExpression' in item) type = 'delegateExpression'; - return { - event: item.event, - type: type, - className: item[type], - params: - item.fields?.map((field) => { - let fieldType; - if ('stringValue' in field) fieldType = 'stringValue'; - if ('expression' in field) fieldType = 'expression'; - return { - name: field.name, - type: fieldType, - value: field[fieldType] - }; - }) ?? [] - }; - }) ?? []; -}; - -onMounted(() => { - initTableData(); -}); - -const typeSelect = [ - { id: '742fdeb7-23b4-416b-ac66-cd4ec8b901b7', label: '绫�', value: 'class' }, - { id: '660c9c46-8fae-4bae-91a0-0335420019dc', label: '琛ㄨ揪寮�', value: 'expression' }, - { id: '4b8135ab-6bc3-4a0f-80be-22f58bc6c5fd', label: '濮旀墭琛ㄨ揪寮�', value: 'delegateExpression' } -]; -const eventSelect = [ - { id: 'e6e0a51a-2d5d-4dc4-b847-b5c14f43a6ab', label: '鍒涘缓', value: 'create' }, - { id: '6da97c1e-15fc-4445-8943-75d09f49778e', label: '鎸囨淳', value: 'assignment' }, - { id: '6a2cbcec-e026-4f11-bef7-fff0b5c871e2', label: '瀹屾垚', value: 'complete' }, - { id: '68801972-85f1-482f-bd86-1fad015c26ed', label: '鍒犻櫎', value: 'delete' } -]; -</script> - -<style scoped lang="scss"> -.el-badge { - :deep(.el-badge__content) { - top: 10px; - } -} -</style> diff --git a/src/components/BpmnDesign/index.vue b/src/components/BpmnDesign/index.vue deleted file mode 100644 index 1f84516..0000000 --- a/src/components/BpmnDesign/index.vue +++ /dev/null @@ -1,71 +0,0 @@ -<template> - <div class="design"> - <el-dialog v-model="visible" width="100%" fullscreen :title="title"> - <div class="modeler"> - <bpmn-design ref="bpmnDesignRef" @save-call-back="saveCallBack"></bpmn-design> - </div> - </el-dialog> - </div> -</template> - -<script lang="ts" setup name="Design"> -import { getInfo, editModelXml } from '@/api/workflow/model'; - -const { proxy } = getCurrentInstance() as ComponentInternalInstance; - -import { ModelForm } from '@/api/workflow/model/types'; -import BpmnDesign from '@/bpmn/index.vue'; -import useDialog from '@/hooks/useDialog'; -const bpmnDesignRef = ref<InstanceType<typeof BpmnDesign>>(); -const modelForm = ref<ModelForm>(); -const emit = defineEmits(['closeCallBack']); -const { visible, title } = useDialog({ - title: '缂栬緫娴佺▼' -}); -const modelId = ref(''); -const open = async (id) => { - visible.value = true; - modelId.value = id; - const { data } = await getInfo(id); - modelForm.value = data; - bpmnDesignRef.value.initDiagram(modelForm.value.xml); -}; -//淇濆瓨妯″瀷 -const saveCallBack = async (data) => { - await proxy?.$modal.confirm('鏄惁纭淇濆瓨锛�'); - data.loading.value = true; - modelForm.value.id = modelId.value; - modelForm.value.xml = data.xml; - modelForm.value.svg = data.svg; - modelForm.value.key = data.key; - modelForm.value.name = data.name; - editModelXml(modelForm.value).then((res) => { - if (res.code === 200) { - visible.value = false; - proxy?.$modal.msgSuccess('淇濆瓨鎴愬姛'); - emit('closeCallBack', data); - } - }); - data.loading.value = false; -}; - -/** - * 瀵瑰鏆撮湶瀛愮粍浠舵柟娉� - */ -defineExpose({ - open -}); -</script> - -<style lang="scss" scoped> -.design { - :deep(.el-dialog .el-dialog__body) { - max-height: 100% !important; - min-height: calc(100vh - 80px); - padding: 10px 0 10px 0 !important; - } - :deep(.el-dialog__header) { - padding: 0 0 5px 0 !important; - } -} -</style> diff --git a/src/components/BpmnView/index.vue b/src/components/BpmnView/index.vue deleted file mode 100644 index c5e0c7b..0000000 --- a/src/components/BpmnView/index.vue +++ /dev/null @@ -1,411 +0,0 @@ -<template> - <div v-loading="loading" class="bpmnDialogContainers"> - <el-header style="border-bottom: 1px solid rgb(218 218 218); height: auto"> - <div class="header-div"> - <div> - <el-tooltip effect="dark" content="鑷�傚簲灞忓箷" placement="bottom"> - <el-button size="small" icon="Rank" @click="fitViewport" /> - </el-tooltip> - <el-tooltip effect="dark" content="鏀惧ぇ" placement="bottom"> - <el-button size="small" icon="ZoomIn" @click="zoomViewport(true)" /> - </el-tooltip> - <el-tooltip effect="dark" content="缂╁皬" placement="bottom"> - <el-button size="small" icon="ZoomOut" @click="zoomViewport(false)" /> - </el-tooltip> - </div> - <div> - <div class="tips-label"> - <div class="un-complete">鏈畬鎴�</div> - <div class="in-progress">杩涜涓�</div> - <div class="complete">宸插畬鎴�</div> - </div> - </div> - </div> - </el-header> - <div class="flow-containers"> - <el-container class="bpmn-el-container" style="align-items: stretch"> - <el-main style="padding: 0"> - <div ref="canvas" class="canvas" /> - </el-main> - </el-container> - </div> - </div> -</template> - -<script lang="ts" setup> -import BpmnViewer from 'bpmn-js/lib/Viewer'; -import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas'; -import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll'; -import { ModuleDeclaration } from 'didi'; -import type { Canvas, ModdleElement } from 'bpmn'; -import EventBus from 'diagram-js/lib/core/EventBus'; -import Overlays from 'diagram-js/lib/features/overlays/Overlays'; -import processApi from '@/api/workflow/processInstance/index'; - -const canvas = ref<HTMLElement>(); -const modeler = ref<BpmnViewer>(); -const taskList = ref([]); -const zoom = ref(1); -const xml = ref(''); -const loading = ref(false); -const bpmnVisible = ref(true); -const historyList = ref([]); - -const init = (businessKey) => { - loading.value = true; - bpmnVisible.value = true; - nextTick(async () => { - if (modeler.value) modeler.value.destroy(); - modeler.value = new BpmnViewer({ - container: canvas.value, - additionalModules: [ - { - //绂佹婊氳疆婊氬姩 - zoomScroll: ['value', ''] - }, - ZoomScrollModule, - MoveCanvasModule - ] as ModuleDeclaration[] - }); - const resp = await processApi.getHistoryList(businessKey); - xml.value = resp.data.xml; - taskList.value = resp.data.taskList; - historyList.value = resp.data.historyList; - await createDiagram(xml.value); - loading.value = false; - }); -}; - -const initXml = (xmlStr: string) => { - loading.value = true; - bpmnVisible.value = true; - nextTick(async () => { - if (modeler.value) modeler.value.destroy(); - modeler.value = new BpmnViewer({ - container: canvas.value, - additionalModules: [ - { - //绂佹婊氳疆婊氬姩 - zoomScroll: ['value', ''] - }, - ZoomScrollModule, - MoveCanvasModule - ] as ModuleDeclaration[] - }); - xml.value = xmlStr; - await createDiagram(xml.value); - loading.value = false; - }); -}; - -const createDiagram = async (data) => { - try { - await modeler.value.importXML(data); - fitViewport(); - fillColor(); - loading.value = false; - addEventBusListener(); - } catch (err) { - console.log(err); - } -}; -const addEventBusListener = () => { - const eventBus = modeler.value.get<EventBus>('eventBus'); - const overlays = modeler.value.get<Overlays>('overlays'); - eventBus.on<ModdleElement>('element.hover', (e) => { - let data = historyList.value.find((t) => t.taskDefinitionKey === e.element.id); - if (e.element.type === 'bpmn:UserTask' && data) { - setTimeout(() => { - genNodeDetailBox(e, overlays, data); - }, 10); - } - }); - eventBus.on('element.out', (e) => { - overlays.clear(); - }); -}; -const genNodeDetailBox = (e, overlays, data) => { - overlays.add(e.element.id, { - position: { top: e.element.height, left: 0 }, - html: `<div class="verlays"> - <p>瀹℃壒浜哄憳: ${data.nickName || ''}<p/> - <p>鑺傜偣鐘舵�侊細${data.status || ''}</p> - <p>寮�濮嬫椂闂达細${data.startTime || ''}</p> - <p>缁撴潫鏃堕棿锛�${data.endTime || ''}</p> - <p>瀹℃壒鑰楁椂锛�${data.runDuration || ''}</p> - <p>娴佺▼鐗堟湰锛歷${data.version || ''}</p> - </div>` - }); -}; -// 璁╁浘鑳借嚜閫傚簲灞忓箷 -const fitViewport = () => { - zoom.value = modeler.value.get<Canvas>('canvas').zoom('fit-viewport'); - const bbox = document.querySelector<SVGGElement>('.flow-containers .viewport').getBBox(); - const currentViewBox = modeler.value.get('canvas').viewbox(); - const elementMid = { - x: bbox.x + bbox.width / 2 - 65, - y: bbox.y + bbox.height / 2 - }; - modeler.value.get<Canvas>('canvas').viewbox({ - x: elementMid.x - currentViewBox.width / 2, - y: elementMid.y - currentViewBox.height / 2, - width: currentViewBox.width, - height: currentViewBox.height - }); - zoom.value = (bbox.width / currentViewBox.width) * 1.8; -}; -// 鏀惧ぇ缂╁皬 -const zoomViewport = (zoomIn = true) => { - zoom.value = modeler.value.get<Canvas>('canvas').zoom(); - zoom.value += zoomIn ? 0.1 : -0.1; - modeler.value.get<Canvas>('canvas').zoom(zoom.value); -}; -//涓婅壊 -const fillColor = () => { - const canvas = modeler.value.get<Canvas>('canvas'); - bpmnNodeList(modeler.value._definitions.rootElements[0].flowElements, canvas); -}; -//閫掑綊涓婅壊 -const bpmnNodeList = (flowElements, canvas) => { - flowElements.forEach((n) => { - if (n.$type === 'bpmn:UserTask') { - const completeTask = taskList.value.find((m) => m.key === n.id); - if (completeTask) { - canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo'); - n.outgoing?.forEach((nn) => { - const targetTask = taskList.value.find((m) => m.key === nn.targetRef.id); - if (targetTask) { - canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo'); - } else if (nn.targetRef.$type === 'bpmn:ExclusiveGateway') { - canvas.addMarker(nn.id, completeTask.completed ? 'highlight' : 'highlight-todo'); - canvas.addMarker(nn.targetRef.id, completeTask.completed ? 'highlight' : 'highlight-todo'); - nn.targetRef.outgoing.forEach((e) => { - gateway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed); - }); - } else if (nn.targetRef.$type === 'bpmn:ParallelGateway') { - canvas.addMarker(nn.id, completeTask.completed ? 'highlight' : 'highlight-todo'); - canvas.addMarker(nn.targetRef.id, completeTask.completed ? 'highlight' : 'highlight-todo'); - nn.targetRef.outgoing.forEach((e) => { - gateway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed); - }); - } else if (nn.targetRef.$type === 'bpmn:InclusiveGateway') { - canvas.addMarker(nn.id, completeTask.completed ? 'highlight' : 'highlight-todo'); - canvas.addMarker(nn.targetRef.id, completeTask.completed ? 'highlight' : 'highlight-todo'); - nn.targetRef.outgoing.forEach((e) => { - gateway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed); - }); - } - }); - } - } else if (n.$type === 'bpmn:ExclusiveGateway') { - n.outgoing.forEach((nn) => { - const targetTask = taskList.value.find((m) => m.key === nn.targetRef.id); - if (targetTask) { - canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo'); - } - }); - } else if (n.$type === 'bpmn:ParallelGateway') { - n.outgoing.forEach((nn) => { - const targetTask = taskList.value.find((m) => m.key === nn.targetRef.id); - if (targetTask) { - canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo'); - } - }); - } else if (n.$type === 'bpmn:InclusiveGateway') { - n.outgoing.forEach((nn) => { - const targetTask = taskList.value.find((m) => m.key === nn.targetRef.id); - if (targetTask) { - canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo'); - } - }); - } else if (n.$type === 'bpmn:SubProcess') { - const completeTask = taskList.value.find((m) => m.key === n.id); - if (completeTask) { - canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo'); - } - bpmnNodeList(n.flowElements, canvas); - } else if (n.$type === 'bpmn:StartEvent') { - canvas.addMarker(n.id, 'startEvent'); - if (n.outgoing) { - n.outgoing.forEach((nn) => { - const completeTask = taskList.value.find((m) => m.key === nn.targetRef.id); - if (completeTask) { - canvas.addMarker(nn.id, 'highlight'); - canvas.addMarker(n.id, 'highlight'); - } - }); - } - } else if (n.$type === 'bpmn:EndEvent') { - canvas.addMarker(n.id, 'endEvent'); - const completeTask = taskList.value.find((m) => m.key === n.id); - if (completeTask) { - canvas.addMarker(completeTask.key, 'highlight'); - canvas.addMarker(n.id, 'highlight'); - return; - } - } - }); -}; -const gateway = (id, targetRefType, targetRefId, canvas, completed) => { - if (targetRefType === 'bpmn:ExclusiveGateway') { - canvas.addMarker(id, completed ? 'highlight' : 'highlight-todo'); - canvas.addMarker(targetRefId, completed ? 'highlight' : 'highlight-todo'); - } - if (targetRefType === 'bpmn:ParallelGateway') { - canvas.addMarker(id, completed ? 'highlight' : 'highlight-todo'); - canvas.addMarker(targetRefId, completed ? 'highlight' : 'highlight-todo'); - } - if (targetRefType === 'bpmn:InclusiveGateway') { - canvas.addMarker(id, completed ? 'highlight' : 'highlight-todo'); - canvas.addMarker(targetRefId, completed ? 'highlight' : 'highlight-todo'); - } -}; -defineExpose({ - init, - initXml -}); -</script> - -<style lang="scss" scoped> -.canvas { - width: 100%; - height: 100%; -} - -.header-div { - display: flex; - padding: 10px 0; - justify-content: space-between; - - .tips-label { - display: flex; - div { - margin-right: 10px; - padding: 5px; - font-size: 12px; - } - .un-complete { - border: 1px solid #000; - } - .in-progress { - background-color: rgb(255, 237, 204); - border: 1px dashed orange; - } - .complete { - background-color: rgb(204, 230, 204); - border: 1px solid green; - } - } -} - -.view-mode { - .el-header, - .el-aside, - .djs-palette, - .bjs-powered-by { - display: none; - } - .el-loading-mask { - background-color: initial; - } - .el-loading-spinner { - display: none; - } -} -.bpmn-el-container { - height: calc(100vh - 350px); -} -.flow-containers { - width: 100%; - height: 100%; - overflow-y: auto; - .canvas { - width: 100%; - height: 100%; - } - .load { - margin-right: 10px; - } - :deep(.el-form-item__label) { - font-size: 13px; - } - - :deep(.djs-palette) { - left: 0 !important; - top: 0; - border-top: none; - } - - :deep(.djs-container svg) { - min-height: 650px; - } - - :deep(.startEvent.djs-shape .djs-visual > :nth-child(1)) { - fill: #77df6d !important; - } - :deep(.endEvent.djs-shape .djs-visual > :nth-child(1)) { - fill: #ee7b77 !important; - } - :deep(.highlight.djs-shape .djs-visual > :nth-child(1)) { - fill: green !important; - stroke: green !important; - fill-opacity: 0.2 !important; - } - :deep(.highlight.djs-shape .djs-visual > :nth-child(2)) { - fill: green !important; - } - :deep(.highlight.djs-shape .djs-visual > path) { - fill: green !important; - fill-opacity: 0.2 !important; - stroke: green !important; - } - :deep(.highlight.djs-connection > .djs-visual > path) { - stroke: green !important; - } - - // 杈规婊氬姩鍔ㄧ敾 - @keyframes path-animation { - from { - stroke-dashoffset: 100%; - } - - to { - stroke-dashoffset: 0%; - } - } - - :deep(.highlight-todo.djs-connection > .djs-visual > path) { - animation: path-animation 60s; - animation-timing-function: linear; - animation-iteration-count: infinite; - stroke-dasharray: 4px !important; - stroke: orange !important; - fill-opacity: 0.2 !important; - marker-end: url('#sequenceflow-end-_E7DFDF-_E7DFDF-803g1kf6zwzmcig1y2ulm5egr'); - } - - :deep(.highlight-todo.djs-shape .djs-visual > :nth-child(1)) { - animation: path-animation 60s; - animation-timing-function: linear; - animation-iteration-count: infinite; - stroke-dasharray: 4px !important; - stroke: orange !important; - fill: orange !important; - fill-opacity: 0.2 !important; - } -} -:deep(.verlays) { - width: 250px; - background: rgb(102, 102, 102); - border-radius: 4px; - border: 1px solid #ebeef5; - color: #fff; - padding: 15px 10px; - p { - line-height: 28px; - margin: 0; - padding: 0; - } - cursor: pointer; -} -</style> diff --git a/src/components/Breadcrumb/index.vue b/src/components/Breadcrumb/index.vue index 9502e60..a8b2f68 100644 --- a/src/components/Breadcrumb/index.vue +++ b/src/components/Breadcrumb/index.vue @@ -11,21 +11,53 @@ <script setup lang="ts"> import { RouteLocationMatched } from 'vue-router'; +import usePermissionStore from '@/store/modules/permission'; const route = useRoute(); const router = useRouter(); +const permissionStore = usePermissionStore(); const levelList = ref<RouteLocationMatched[]>([]); const getBreadcrumb = () => { // only show routes with meta.title - let matched = route.matched.filter((item) => item.meta && item.meta.title); - const first = matched[0]; + let matched = []; + const pathNum = findPathNum(route.path); + // multi-level menu + if (pathNum > 2) { + const reg = /\/\w+/gi; + const pathList = route.path.match(reg).map((item, index) => { + if (index !== 0) item = item.slice(1); + return item; + }); + getMatched(pathList, permissionStore.defaultRoutes, matched); + } else { + matched = route.matched.filter((item) => item.meta && item.meta.title); + } // 鍒ゆ柇鏄惁涓洪椤� - if (!isDashboard(first)) { - matched = ([{ path: '/index', meta: { title: '棣栭〉' } }] as any).concat(matched); + if (!isDashboard(matched[0])) { + matched = [{ path: '/index', meta: { title: '棣栭〉' } }].concat(matched); } levelList.value = matched.filter((item) => item.meta && item.meta.title && item.meta.breadcrumb !== false); }; +const findPathNum = (str, char = '/') => { + let index = str.indexOf(char); + let num = 0; + while (index !== -1) { + num++; + index = str.indexOf(char, index + 1); + } + return num; +}; +const getMatched = (pathList, routeList, matched) => { + let data = routeList.find((item) => item.path == pathList[0] || (item.name += '').toLowerCase() == pathList[0]); + if (data) { + matched.push(data); + if (data.children && pathList.length) { + pathList.shift(); + getMatched(pathList, data.children, matched); + } + } +}; const isDashboard = (route: RouteLocationMatched) => { const name = route && (route.name as string); if (!name) { diff --git a/src/components/FileUpload/index.vue b/src/components/FileUpload/index.vue index aaaa45c..b22d09a 100644 --- a/src/components/FileUpload/index.vue +++ b/src/components/FileUpload/index.vue @@ -121,6 +121,11 @@ return false; } } + // 鏍℃鏂囦欢鍚嶆槸鍚﹀寘鍚壒娈婂瓧绗� + if (file.name.includes(',')) { + proxy?.$modal.msgError('鏂囦欢鍚嶄笉姝g‘锛屼笉鑳藉寘鍚嫳鏂囬�楀彿!'); + return false; + } // 鏍℃鏂囦欢澶у皬 if (props.fileSize) { const isLt = file.size / 1024 / 1024 < props.fileSize; diff --git a/src/components/ImageUpload/index.vue b/src/components/ImageUpload/index.vue index 1c6dcd1..0778121 100644 --- a/src/components/ImageUpload/index.vue +++ b/src/components/ImageUpload/index.vue @@ -139,6 +139,10 @@ proxy?.$modal.msgError(`鏂囦欢鏍煎紡涓嶆纭�, 璇蜂笂浼�${props.fileType.join('/')}鍥剧墖鏍煎紡鏂囦欢!`); return false; } + if (file.name.includes(',')) { + proxy?.$modal.msgError('鏂囦欢鍚嶄笉姝g‘锛屼笉鑳藉寘鍚嫳鏂囬�楀彿!'); + return false; + } if (props.fileSize) { const isLt = file.size / 1024 / 1024 < props.fileSize; if (!isLt) { diff --git a/src/components/Process/approvalRecord.vue b/src/components/Process/approvalRecord.vue index bb4ed91..5c46a58 100644 --- a/src/components/Process/approvalRecord.vue +++ b/src/components/Process/approvalRecord.vue @@ -2,39 +2,63 @@ <div class="container"> <el-dialog v-model="visible" draggable title="瀹℃壒璁板綍" :width="props.width" :height="props.height" :close-on-click-modal="false"> <el-tabs v-model="tabActiveName" class="demo-tabs"> - <el-tab-pane label="娴佺▼鍥�" name="bpmn"> - <BpmnView ref="bpmnViewRef"></BpmnView> + <el-tab-pane v-loading="loading" label="娴佺▼鍥�" name="image" style="height: 68vh"> + <div + ref="imageWrapperRef" + class="image-wrapper" + @wheel="handleMouseWheel" + @mousedown="handleMouseDown" + @mousemove="handleMouseMove" + @mouseup="handleMouseUp" + @mouseleave="handleMouseLeave" + @dblclick="resetTransform" + :style="transformStyle" + > + <el-card class="box-card"> + <el-image :src="imgUrl" class="scalable-image" /> + </el-card> + </div> </el-tab-pane> <el-tab-pane v-loading="loading" label="瀹℃壒淇℃伅" name="info"> <div> <el-table :data="historyList" style="width: 100%" border fit> <el-table-column type="index" label="搴忓彿" align="center" width="60"></el-table-column> - <el-table-column prop="name" label="浠诲姟鍚嶇О" sortable align="center"></el-table-column> - <el-table-column prop="nickName" :show-overflow-tooltip="true" label="鍔炵悊浜�" sortable align="center"> + <el-table-column prop="nodeName" label="浠诲姟鍚嶇О" sortable align="center"></el-table-column> + <el-table-column prop="approveName" :show-overflow-tooltip="true" label="鍔炵悊浜�" sortable align="center"> <template #default="scope"> - <el-tag type="success">{{ scope.row.nickName || '鏃�' }}</el-tag> + <template v-if="scope.row.approveName"> + <el-tag v-for="(item, index) in scope.row.approveName.split(',')" :key="index" type="success">{{ item }}</el-tag> + </template> + <template v-else> <el-tag type="success">鏃�</el-tag></template> </template> </el-table-column> - <el-table-column label="鐘舵��" sortable align="center"> + <el-table-column prop="flowStatus" label="鐘舵��" width="80" sortable align="center"> <template #default="scope"> - <el-tag type="success">{{ scope.row.statusName }}</el-tag> + <dict-tag :options="wf_task_status" :value="scope.row.flowStatus"></dict-tag> </template> </el-table-column> - <el-table-column prop="comment" label="瀹℃壒鎰忚" sortable align="center"></el-table-column> - <el-table-column prop="startTime" label="寮�濮嬫椂闂�" sortable align="center"></el-table-column> - <el-table-column prop="endTime" label="缁撴潫鏃堕棿" sortable align="center"></el-table-column> - <el-table-column prop="runDuration" label="杩愯鏃堕暱" sortable align="center"></el-table-column> - <el-table-column prop="attachmentList" label="闄勪欢" sortable align="center"> + <el-table-column prop="message" label="瀹℃壒鎰忚" :show-overflow-tooltip="true" sortable align="center"></el-table-column> + <el-table-column prop="createTime" label="寮�濮嬫椂闂�" width="160" :show-overflow-tooltip="true" sortable align="center"></el-table-column> + <el-table-column prop="updateTime" label="缁撴潫鏃堕棿" width="160" :show-overflow-tooltip="true" sortable align="center"></el-table-column> + <el-table-column + prop="runDuration" + label="杩愯鏃跺父" + width="140" + :show-overflow-tooltip="true" + sortable + align="center" + ></el-table-column> + <el-table-column prop="attachmentList" width="120" label="闄勪欢" align="center"> <template #default="scope"> <el-popover v-if="scope.row.attachmentList && scope.row.attachmentList.length > 0" placement="right" :width="310" trigger="click"> <template #reference> - <el-button style="margin-right: 16px">闄勪欢</el-button> + <el-button type="primary" style="margin-right: 16px">闄勪欢</el-button> </template> <el-table border :data="scope.row.attachmentList"> - <el-table-column prop="name" width="202" :show-overflow-tooltip="true" label="闄勪欢鍚嶇О"></el-table-column> + <el-table-column prop="originalName" width="202" :show-overflow-tooltip="true" label="闄勪欢鍚嶇О"></el-table-column> <el-table-column prop="name" width="80" align="center" :show-overflow-tooltip="true" label="鎿嶄綔"> <template #default="tool"> - <el-button type="text" @click="handleDownload(tool.row.contentId)">涓嬭浇</el-button> + <el-button type="text" @click="handleDownload(tool.row.ossId)">涓嬭浇</el-button> </template> </el-table-column> </el-table> @@ -49,42 +73,160 @@ </div> </template> <script lang="ts" setup> -import BpmnView from '@/components/BpmnView/index.vue'; -import processApi from '@/api/workflow/processInstance'; +import { flowImage } from '@/api/workflow/instance'; import { propTypes } from '@/utils/propTypes'; +import { listByIds } from '@/api/system/oss'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; - +const { wf_task_status } = toRefs<any>(proxy?.useDict('wf_task_status')); const props = defineProps({ - width: propTypes.string.def('70%'), + width: propTypes.string.def('80%'), height: propTypes.string.def('100%') }); const loading = ref(false); const visible = ref(false); const historyList = ref<Array<any>>([]); -const tabActiveName = ref('bpmn'); - -const bpmnViewRef = ref<BpmnView>(); +const tabActiveName = ref('image'); +const imgUrl = ref(''); //鍒濆鍖栨煡璇㈠鎵硅褰� -const init = async (businessKey: string | number) => { +const init = async (businessId: string | number) => { visible.value = true; loading.value = true; - tabActiveName.value = 'bpmn'; + tabActiveName.value = 'image'; historyList.value = []; - processApi.getHistoryRecord(businessKey).then((resp) => { - historyList.value = resp.data; - loading.value = false; + flowImage(businessId).then((resp) => { + if (resp.data) { + historyList.value = resp.data.list; + imgUrl.value = 'data:image/gif;base64,' + resp.data.image; + if (historyList.value.length > 0) { + historyList.value.forEach((item) => { + if (item.ext) { + getIds(item.ext).then((res) => { + item.attachmentList = res.data; + }); + } else { + item.attachmentList = []; + } + }); + } + loading.value = false; + } }); - await nextTick(() => { - bpmnViewRef.value.init(businessKey); - }); +}; +const getIds = async (ids: string | number) => { + const res = await listByIds(ids); + return res; }; /** 涓嬭浇鎸夐挳鎿嶄綔 */ const handleDownload = (ossId: string) => { proxy?.$download.oss(ossId); }; + +const imageWrapperRef = ref<HTMLElement | null>(null); +const scale = ref(1); // 鍒濆缂╂斁姣斾緥 +const maxScale = 3; // 鏈�澶х缉鏀炬瘮渚� +const minScale = 0.5; // 鏈�灏忕缉鏀炬瘮渚� + +let isDragging = false; +let startX = 0; +let startY = 0; +let currentTranslateX = 0; +let currentTranslateY = 0; + +const handleMouseWheel = (event: WheelEvent) => { + event.preventDefault(); + let newScale = scale.value - event.deltaY / 1000; + newScale = Math.max(minScale, Math.min(newScale, maxScale)); + if (newScale !== scale.value) { + scale.value = newScale; + resetDragPosition(); // 閲嶇疆鎷栨嫿浣嶇疆锛屼娇鍥剧墖灞呬腑 + } +}; + +const handleMouseDown = (event: MouseEvent) => { + if (scale.value > 1) { + event.preventDefault(); // 闃绘榛樿琛屼负锛岄槻姝㈡嫋鎷� + isDragging = true; + startX = event.clientX; + startY = event.clientY; + } +}; + +const handleMouseMove = (event: MouseEvent) => { + if (!isDragging || !imageWrapperRef.value) return; + + const deltaX = event.clientX - startX; + const deltaY = event.clientY - startY; + startX = event.clientX; + startY = event.clientY; + + currentTranslateX += deltaX; + currentTranslateY += deltaY; + + // 杈圭晫妫�娴嬶紝闃叉鍥剧墖琚嫋鍑哄鍣� + const bounds = getBounds(); + if (currentTranslateX > bounds.maxTranslateX) { + currentTranslateX = bounds.maxTranslateX; + } else if (currentTranslateX < bounds.minTranslateX) { + currentTranslateX = bounds.minTranslateX; + } + + if (currentTranslateY > bounds.maxTranslateY) { + currentTranslateY = bounds.maxTranslateY; + } else if (currentTranslateY < bounds.minTranslateY) { + currentTranslateY = bounds.minTranslateY; + } + + applyTransform(); +}; + +const handleMouseUp = () => { + isDragging = false; +}; + +const handleMouseLeave = () => { + isDragging = false; +}; + +const resetTransform = () => { + scale.value = 1; + currentTranslateX = 0; + currentTranslateY = 0; + applyTransform(); +}; + +const resetDragPosition = () => { + currentTranslateX = 0; + currentTranslateY = 0; + applyTransform(); +}; + +const applyTransform = () => { + if (imageWrapperRef.value) { + imageWrapperRef.value.style.transform = `translate(${currentTranslateX}px, ${currentTranslateY}px) scale(${scale.value})`; + } +}; + +const getBounds = () => { + if (!imageWrapperRef.value) return { minTranslateX: 0, maxTranslateX: 0, minTranslateY: 0, maxTranslateY: 0 }; + + const imgRect = imageWrapperRef.value.getBoundingClientRect(); + const containerRect = imageWrapperRef.value.parentElement?.getBoundingClientRect() ?? imgRect; + + const minTranslateX = (containerRect.width - imgRect.width * scale.value) / 2; + const maxTranslateX = -(containerRect.width - imgRect.width * scale.value) / 2; + const minTranslateY = (containerRect.height - imgRect.height * scale.value) / 2; + const maxTranslateY = -(containerRect.height - imgRect.height * scale.value) / 2; + + return { minTranslateX, maxTranslateX, minTranslateY, maxTranslateY }; +}; + +const transformStyle = computed(() => ({ + transition: isDragging ? 'none' : 'transform 0.2s ease' +})); + /** * 瀵瑰鏆撮湶瀛愮粍浠舵柟娉� */ @@ -113,4 +255,26 @@ min-height: calc(100vh - 170px) !important; } } + +.image-wrapper { + width: 100%; + overflow: hidden; + position: relative; + margin: 0 auto; + display: flex; + justify-content: center; + align-items: center; + user-select: none; /* 绂佺敤鏂囨湰閫夋嫨 */ + cursor: grab; /* 璁剧疆鍒濆榧犳爣鎸囬拡涓哄彲鎷栧姩 */ +} + +.image-wrapper:active { + cursor: grabbing; /* 褰撴鍦ㄦ嫋鍔ㄦ椂鏀瑰彉榧犳爣鎸囬拡 */ +} + +.scalable-image { + object-fit: contain; + width: 100%; + padding: 15px; +} </style> diff --git a/src/components/Process/multiInstanceUser.vue b/src/components/Process/multiInstanceUser.vue deleted file mode 100644 index d19fb5f..0000000 --- a/src/components/Process/multiInstanceUser.vue +++ /dev/null @@ -1,378 +0,0 @@ -<template> - <el-dialog v-model="visible" draggable :title="title" :width="width" :height="height" append-to-body :close-on-click-modal="false"> - <div v-if="multiInstance === 'add'" class="p-2"> - <el-row :gutter="20"> - <!-- 閮ㄩ棬鏍� --> - <el-col :lg="4" :xs="24" style=""> - <el-card shadow="hover"> - <el-input v-model="deptName" placeholder="璇疯緭鍏ラ儴闂ㄥ悕绉�" prefix-icon="Search" clearable /> - <el-tree - ref="deptTreeRef" - class="mt-2" - node-key="id" - :data="deptOptions" - :props="{ label: 'label', children: 'children' }" - :expand-on-click-node="false" - :filter-node-method="filterNode" - highlight-current - default-expand-all - @node-click="handleNodeClick" - ></el-tree> - </el-card> - </el-col> - <el-col :lg="20" :xs="24"> - <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> - <div v-show="showSearch" class="search"> - <el-form ref="queryFormRef" :model="queryParams" :inline="true"> - <el-form-item label="鐢ㄦ埛鍚嶇О" prop="userName"> - <el-input v-model="queryParams.userName" placeholder="璇疯緭鍏ョ敤鎴峰悕绉�" clearable @keyup.enter="handleQuery" /> - </el-form-item> - <el-form-item label="鎵嬫満鍙风爜" prop="phonenumber"> - <el-input v-model="queryParams.phonenumber" placeholder="璇疯緭鍏ユ墜鏈哄彿鐮�" clearable @keyup.enter="handleQuery" /> - </el-form-item> - <el-form-item> - <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button> - <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button> - </el-form-item> - </el-form> - </div> - </transition> - - <el-card shadow="hover"> - <template #header> - <el-row :gutter="10"> - <right-toolbar v-model:showSearch="showSearch" :search="true" @query-table="handleQuery"></right-toolbar> - </el-row> - </template> - - <el-table ref="multipleTableRef" v-loading="loading" :data="userList" row-key="userId" @selection-change="handleSelectionChange"> - <el-table-column type="selection" width="50" align="center" /> - <el-table-column key="userId" label="鐢ㄦ埛缂栧彿" align="center" prop="userId" /> - <el-table-column key="userName" label="鐢ㄦ埛鍚嶇О" align="center" prop="userName" :show-overflow-tooltip="true" /> - <el-table-column key="nickName" label="鐢ㄦ埛鏄电О" align="center" prop="nickName" :show-overflow-tooltip="true" /> - <el-table-column key="phonenumber" label="鎵嬫満鍙风爜" align="center" prop="phonenumber" width="120" /> - <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="160"> - <template #default="scope"> - <span>{{ scope.row.createTime }}</span> - </template> - </el-table-column> - </el-table> - - <pagination - v-show="total > 0" - v-model:page="queryParams.pageNum" - v-model:limit="queryParams.pageSize" - :total="total" - @pagination="handleQuery" - /> - </el-card> - <el-card shadow="hover"> - <el-tag v-for="(user, index) in chooseUserList" :key="user.userId" style="margin: 2px" closable @close="handleCloseTag(user, index)" - >{{ user.userName }} - </el-tag> - </el-card> - </el-col> - </el-row> - </div> - <div v-if="multiInstance === 'delete'" class="p-2"> - <el-table v-loading="loading" :data="taskList" @selection-change="handleTaskSelection"> - <el-table-column type="selection" width="55" /> - <el-table-column prop="name" label="浠诲姟鍚嶇О" /> - <el-table-column prop="assigneeName" label="鍔炵悊浜�" /> - </el-table> - </div> - <template #footer> - <div class="dialog-footer"> - <el-button type="primary" @click="submitFileForm">纭� 瀹�</el-button> - <el-button @click="visible = false">鍙� 娑�</el-button> - </div> - </template> - </el-dialog> -</template> - -<script setup name="User" lang="ts"> -import { deptTreeSelect, listUser, optionSelect } from '@/api/system/user'; -import { - addMultiInstanceExecution, - deleteMultiInstanceExecution, - getTaskUserIdsByAddMultiInstance, - getListByDeleteMultiInstance -} from '@/api/workflow/task'; -import { UserVO } from '@/api/system/user/types'; -import { DeptVO } from '@/api/system/dept/types'; -import { ComponentInternalInstance } from 'vue'; -import { ElTree, ElTable } from 'element-plus'; -const { proxy } = getCurrentInstance() as ComponentInternalInstance; - -const props = defineProps({ - // 瀹� - width: { - type: String, - default: '70%' - }, - // 楂� - height: { - type: String, - default: '100%' - }, - // 鏍囬 - title: { - type: String, - default: '鍔犵浜哄憳' - }, - //鏄惁澶氶�� - multiple: { - type: Boolean, - default: true - }, - //鍥炴樉鐢ㄦ埛id - userIdList: { - type: Array, - default: () => [] - } -}); -const deptTreeRef = ref(ElTree); -const multipleTableRef = ref(ElTable); - -const userList = ref<UserVO[]>(); -const taskList = ref<Array<any>[]>(); -const loading = ref(true); -const showSearch = ref(true); -const selectionTask = ref<Array<any>[]>(); -const visible = ref(false); -const total = ref(0); -const deptName = ref(''); -const deptOptions = ref<DeptVO[]>([]); -const chooseUserList = ref(ref<UserVO[]>()); -const userIds = ref<Array<number | string>>([]); -//鍔犵鎴栬�呭噺绛� -const multiInstance = ref(''); -const queryParams = ref<Record<string, any>>({ - pageNum: 1, - pageSize: 10, - userName: '', - nickName: '', - taskId: '' -}); -/** 鏌ヨ鐢ㄦ埛鍒楄〃 */ -const getAddMultiInstanceList = async (taskId: string, userIdList: Array<number | string>) => { - deptOptions.value = []; - getTreeSelect(); - multiInstance.value = 'add'; - userIds.value = userIdList; - visible.value = true; - queryParams.value.taskId = taskId; - loading.value = true; - const res1 = await getTaskUserIdsByAddMultiInstance(taskId); - queryParams.value.excludeUserIds = res1.data; - const res = await listUser(queryParams.value); - loading.value = false; - userList.value = res.rows; - total.value = res.total; - if (userList.value && userIds.value.length > 0) { - const data = await optionSelect(userIds.value); - if (data.data && data.data.length > 0) { - chooseUserList.value = data.data; - data.data.forEach((user: UserVO) => { - multipleTableRef.value!.toggleRowSelection( - userList.value.find((item) => { - return item.userId == user.userId; - }), - true - ); - }); - } - } -}; - -const getList = async () => { - loading.value = true; - const res1 = await getTaskUserIdsByAddMultiInstance(queryParams.value.taskId); - queryParams.value.excludeUserIds = res1.data; - const res = await listUser(queryParams.value); - loading.value = false; - userList.value = res.rows; - total.value = res.total; - if (userList.value && userIds.value.length > 0) { - const data = await optionSelect(userIds.value); - if (data.data && data.data.length > 0) { - chooseUserList.value = data.data; - data.data.forEach((user: UserVO) => { - multipleTableRef.value!.toggleRowSelection( - userList.value.find((item) => { - return item.userId == user.userId; - }), - true - ); - }); - } - } -}; - -const getDeleteMultiInstanceList = async (taskId: string) => { - deptOptions.value = []; - loading.value = true; - queryParams.value.taskId = taskId; - multiInstance.value = 'delete'; - visible.value = true; - const res = await getListByDeleteMultiInstance(taskId); - taskList.value = res.data; - loading.value = false; -}; -/** 鎼滅储鎸夐挳鎿嶄綔 */ -const handleQuery = () => { - queryParams.value.pageNum = 1; - getAddMultiInstanceList(queryParams.value.taskId, userIds.value); -}; - -/** 閲嶇疆鎸夐挳鎿嶄綔 */ -const resetQuery = () => { - queryParams.value.pageNum = 1; - queryParams.value.deptId = undefined; - queryParams.value.userName = undefined; - queryParams.value.nickName = undefined; - deptTreeRef.value.setCurrentKey(null); - handleQuery(); -}; - -/** 閫夋嫨鏉℃暟 */ -const handleSelectionChange = (selection: UserVO[]) => { - if (props.multiple) { - chooseUserList.value = selection.filter((element, index, self) => { - return self.findIndex((x) => x.userId === element.userId) === index; - }); - selection.forEach((u) => { - if (chooseUserList.value && !chooseUserList.value.includes(u)) { - multipleTableRef.value!.toggleRowSelection(u, undefined); - } - }); - userIds.value = chooseUserList.value.map((item) => { - return item.userId; - }); - } else { - chooseUserList.value = selection; - if (selection.length > 1) { - let delRow = selection.shift(); - multipleTableRef.value!.toggleRowSelection(delRow, undefined); - } - if (selection.length === 0) { - chooseUserList.value = []; - } - } -}; -/** 閫夋嫨鏉℃暟 */ -const handleTaskSelection = (selection: any) => { - selectionTask.value = selection; -}; - -/** 鏌ヨ閮ㄩ棬涓嬫媺鏍戠粨鏋� */ -const getTreeSelect = async () => { - const res = await deptTreeSelect(); - deptOptions.value = res.data; -}; - -/** 閫氳繃鏉′欢杩囨护鑺傜偣 */ -const filterNode = (value: string, data: any) => { - if (!value) return true; - return data.label.indexOf(value) !== -1; -}; -/** 鏍规嵁鍚嶇О绛涢�夐儴闂ㄦ爲 */ -watchEffect( - () => { - if (visible.value && deptOptions.value && deptOptions.value.length > 0) { - deptTreeRef.value.filter(deptName.value); - } - }, - { - flush: 'post' // watchEffect浼氬湪DOM鎸傝浇鎴栬�呮洿鏂颁箣鍓嶅氨浼氳Е鍙戯紝姝ゅ睘鎬ф帶鍒跺湪DOM鍏冪礌鏇存柊鍚庤繍琛� - } -); -/** 鑺傜偣鍗曞嚮浜嬩欢 */ -const handleNodeClick = (data: DeptVO) => { - queryParams.value.deptId = data.id; - getList(); -}; -//鍒犻櫎tag -const handleCloseTag = (user: UserVO, index: any) => { - if (multipleTableRef.value.selection && multipleTableRef.value.selection.length > 0) { - multipleTableRef.value.selection.forEach((u: UserVO, i: number) => { - if (user.userId === u.userId) { - multipleTableRef.value.selection.splice(i, 1); - } - }); - } - if (chooseUserList.value && chooseUserList.value.length > 0) { - chooseUserList.value.splice(index, 1); - } - multipleTableRef.value.toggleRowSelection(user, undefined); - - if (userIds.value && userIds.value.length > 0) { - userIds.value.forEach((userId, i) => { - if (userId === user.userId) { - userIds.value.splice(i, 1); - } - }); - } -}; -const submitFileForm = async () => { - if (multiInstance.value === 'add') { - if (chooseUserList.value && chooseUserList.value.length > 0) { - loading.value = true; - let userIds = chooseUserList.value.map((item) => { - return item.userId; - }); - let nickNames = chooseUserList.value.map((item) => { - return item.nickName; - }); - let params = { - taskId: queryParams.value.taskId, - assignees: userIds, - assigneeNames: nickNames - }; - await addMultiInstanceExecution(params); - emits('submitCallback'); - loading.value = false; - proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); - visible.value = false; - } - } else { - if (selectionTask.value && selectionTask.value.length > 0) { - loading.value = true; - let taskIds = selectionTask.value.map((item: any) => { - return item.id; - }); - let executionIds = selectionTask.value.map((item: any) => { - return item.executionId; - }); - let assigneeIds = selectionTask.value.map((item: any) => { - return item.assignee; - }); - let assigneeNames = selectionTask.value.map((item: any) => { - return item.assigneeName; - }); - let params = { - taskId: queryParams.value.taskId, - taskIds: taskIds, - executionIds: executionIds, - assigneeIds: assigneeIds, - assigneeNames: assigneeNames - }; - await deleteMultiInstanceExecution(params); - emits('submitCallback'); - loading.value = false; - proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); - visible.value = false; - } - } -}; -//浜嬩欢 -const emits = defineEmits(['submitCallback']); - -/** - * 瀵瑰鏆撮湶瀛愮粍浠舵柟娉� - */ -defineExpose({ - getAddMultiInstanceList, - getDeleteMultiInstanceList -}); -</script> diff --git a/src/components/Process/processMeddle.vue b/src/components/Process/processMeddle.vue new file mode 100644 index 0000000..7224755 --- /dev/null +++ b/src/components/Process/processMeddle.vue @@ -0,0 +1,207 @@ +<template> + <el-dialog v-model="visible" draggable title="娴佺▼骞查" :width="props.width" :height="props.height" :close-on-click-modal="false"> + <el-descriptions v-loading="loading" class="margin-top" :title="`${task.flowName}(${task.flowCode})`" :column="2" border> + <el-descriptions-item label="浠诲姟鍚嶇О">{{ task.nodeName }}</el-descriptions-item> + <el-descriptions-item label="鑺傜偣缂栫爜">{{ task.nodeCode }}</el-descriptions-item> + <el-descriptions-item label="寮�濮嬫椂闂�">{{ task.createTime }}</el-descriptions-item> + <el-descriptions-item label="娴佺▼瀹炰緥ID">{{ task.instanceId }}</el-descriptions-item> + <el-descriptions-item label="鐗堟湰鍙�">{{ task.version }}.0</el-descriptions-item> + <el-descriptions-item label="涓氬姟ID">{{ task.businessId }}</el-descriptions-item> + </el-descriptions> + <template #footer> + <span class="dialog-footer"> + <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openTransferTask"> 杞姙 </el-button> + <el-button + v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0" + :disabled="buttonDisabled" + type="primary" + @click="openMultiInstanceUser" + > + 鍔犵 + </el-button> + <el-button + v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0" + :disabled="buttonDisabled" + type="primary" + @click="handleTaskUser" + > + 鍑忕 + </el-button> + <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleTerminationTask"> 缁堟 </el-button> + </span> + </template> + <!-- 杞姙 --> + <UserSelect ref="transferTaskRef" :multiple="false" @confirm-call-back="handleTransferTask"></UserSelect> + <!-- 鍔犵缁勪欢 --> + <UserSelect ref="multiInstanceUserRef" :multiple="true" @confirm-call-back="addMultiInstanceUser"></UserSelect> + <el-dialog v-model="deleteSignatureVisible" draggable title="鍑忕浜哄憳" width="700px" height="400px" append-to-body :close-on-click-modal="false" + ><div> + <el-table :data="deleteUserList" border> + <el-table-column prop="nodeName" label="浠诲姟鍚嶇О" /> + <el-table-column prop="nickName" label="鍔炵悊浜�" /> + <el-table-column label="鎿嶄綔" align="center" width="160"> + <template #default="scope"> + <el-button type="danger" size="small" icon="Delete" @click="deleteMultiInstanceUser(scope.row)">鍒犻櫎</el-button> + </template> + </el-table-column> + </el-table> + </div> + </el-dialog> + </el-dialog> +</template> +<script lang="ts" setup> +import { propTypes } from '@/utils/propTypes'; +import { FlowTaskVO, TaskOperationBo } from '@/api/workflow/task/types'; +import UserSelect from '@/components/UserSelect'; +const { proxy } = getCurrentInstance() as ComponentInternalInstance; +import { getTask, taskOperation, currentTaskAllUser, terminationTask } from '@/api/workflow/task'; +const props = defineProps({ + width: propTypes.string.def('50%'), + height: propTypes.string.def('100%') +}); +const emits = defineEmits(['submitCallback']); +const transferTaskRef = ref<InstanceType<typeof UserSelect>>(); +const multiInstanceUserRef = ref<InstanceType<typeof UserSelect>>(); +//閬僵灞� +const loading = ref(true); +//鎸夐挳 +const buttonDisabled = ref(true); +const visible = ref(false); +//鍑忕寮圭獥 +const deleteSignatureVisible = ref(false); +//鍙噺绛剧殑浜哄憳 +const deleteUserList = ref<any>([]); +//浠诲姟 +const task = ref<FlowTaskVO>({ + id: undefined, + createTime: undefined, + updateTime: undefined, + tenantId: undefined, + definitionId: undefined, + instanceId: undefined, + flowName: undefined, + businessId: undefined, + nodeCode: undefined, + nodeName: undefined, + flowCode: undefined, + flowStatus: undefined, + nodeType: undefined, + nodeRatio: undefined, + version: undefined +}); + +const open = (taskId: string) => { + visible.value = true; + getTask(taskId).then((response) => { + loading.value = false; + buttonDisabled.value = false; + task.value = response.data; + }); +}; + +//鎵撳紑杞姙 +const openTransferTask = () => { + transferTaskRef.value.open(); +}; +//杞姙 +const handleTransferTask = async (data) => { + if (data && data.length > 0) { + const taskOperationBo = reactive<TaskOperationBo>({ + userId: data[0].userId, + taskId: task.value.id, + message: '' + }); + await proxy?.$modal.confirm('鏄惁纭鎻愪氦锛�'); + loading.value = true; + buttonDisabled.value = true; + await taskOperation(taskOperationBo, 'transferTask').finally(() => { + loading.value = false; + buttonDisabled.value = false; + }); + visible.value = false; + emits('submitCallback'); + proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); + } else { + proxy?.$modal.msgWarning('璇烽�夋嫨鐢ㄦ埛锛�'); + } +}; +//鍔犵 +const openMultiInstanceUser = async () => { + multiInstanceUserRef.value.open(); +}; +//鍔犵 +const addMultiInstanceUser = async (data) => { + if (data && data.length > 0) { + const taskOperationBo = reactive<TaskOperationBo>({ + userIds: data.map((e) => e.userId), + taskId: task.value.id, + message: '' + }); + await proxy?.$modal.confirm('鏄惁纭鎻愪氦锛�'); + loading.value = true; + buttonDisabled.value = true; + await taskOperation(taskOperationBo, 'addSignature').finally(() => { + loading.value = false; + buttonDisabled.value = false; + }); + visible.value = false; + emits('submitCallback'); + proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); + } else { + proxy?.$modal.msgWarning('璇烽�夋嫨鐢ㄦ埛锛�'); + } +}; +//鍑忕 +const deleteMultiInstanceUser = async (row) => { + await proxy?.$modal.confirm('鏄惁纭鎻愪氦锛�'); + loading.value = true; + buttonDisabled.value = true; + const taskOperationBo = reactive<TaskOperationBo>({ + userIds: [row.userId], + taskId: task.value.id, + message: '' + }); + await taskOperation(taskOperationBo, 'reductionSignature').finally(() => { + loading.value = false; + buttonDisabled.value = false; + }); + visible.value = false; + emits('submitCallback'); + proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); +}; +//鑾峰彇鍔炵悊浜� +const handleTaskUser = async () => { + let data = await currentTaskAllUser(task.value.id); + deleteUserList.value = data.data; + if (deleteUserList.value && deleteUserList.value.length > 0) { + deleteUserList.value.forEach((e) => { + e.nodeName = task.value.nodeName; + }); + } + deleteSignatureVisible.value = true; +}; + +//缁堟浠诲姟 +const handleTerminationTask = async () => { + let params = { + taskId: task.value.id, + comment: '' + }; + await proxy?.$modal.confirm('鏄惁纭缁堟锛�'); + loading.value = true; + buttonDisabled.value = true; + await terminationTask(params).finally(() => { + loading.value = false; + buttonDisabled.value = false; + }); + visible.value = false; + emits('submitCallback'); + proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); +}; +/** + * 瀵瑰鏆撮湶瀛愮粍浠舵柟娉� + */ +defineExpose({ + open +}); +</script> diff --git a/src/components/Process/submitVerify.vue b/src/components/Process/submitVerify.vue index 09fc82e..4c2ea88 100644 --- a/src/components/Process/submitVerify.vue +++ b/src/components/Process/submitVerify.vue @@ -3,47 +3,47 @@ <el-form v-loading="loading" :model="form" label-width="120px"> <el-form-item label="娑堟伅鎻愰啋"> <el-checkbox-group v-model="form.messageType"> - <el-checkbox label="1" name="type" disabled>绔欏唴淇�</el-checkbox> - <el-checkbox label="2" name="type">閭欢</el-checkbox> - <el-checkbox label="3" name="type">鐭俊</el-checkbox> + <el-checkbox value="1" name="type" disabled>绔欏唴淇�</el-checkbox> + <el-checkbox value="2" name="type">閭欢</el-checkbox> + <el-checkbox value="3" name="type">鐭俊</el-checkbox> </el-checkbox-group> </el-form-item> - <el-form-item v-if="task.businessStatus === 'waiting'" label="闄勪欢"> - <fileUpload v-model="form.fileId" :file-type="['doc', 'xls', 'ppt', 'txt', 'pdf', 'xlsx', 'docx', 'zip']" :file-size="'20'" /> + <el-form-item v-if="task.flowStatus === 'waiting'" label="闄勪欢"> + <fileUpload v-model="form.fileId" :file-type="['png', 'jpg', 'jpeg', 'doc', 'docx', 'xlsx', 'xls', 'ppt', 'txt', 'pdf']" :file-size="20" /> </el-form-item> <el-form-item label="鎶勯��"> <el-button type="primary" icon="Plus" circle @click="openUserSelectCopy" /> <el-tag v-for="user in selectCopyUserList" :key="user.userId" closable style="margin: 2px" @close="handleCopyCloseTag(user)"> - {{ user.userName }} + {{ user.nickName }} </el-tag> </el-form-item> - <el-form-item v-if="task.businessStatus === 'waiting'" label="瀹℃壒鎰忚"> + <el-form-item v-if="task.flowStatus === 'waiting'" label="瀹℃壒鎰忚"> <el-input v-model="form.message" type="textarea" resize="none" /> </el-form-item> </el-form> <template #footer> <span class="dialog-footer"> <el-button :disabled="buttonDisabled" type="primary" @click="handleCompleteTask"> 鎻愪氦 </el-button> - <el-button v-if="task.businessStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openDelegateTask"> 濮旀墭 </el-button> - <el-button v-if="task.businessStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openTransferTask"> 杞姙 </el-button> + <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openDelegateTask"> 濮旀墭 </el-button> + <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openTransferTask"> 杞姙 </el-button> <el-button - v-if="task.businessStatus === 'waiting' && task.multiInstance" + v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0" :disabled="buttonDisabled" type="primary" - @click="addMultiInstanceUser" + @click="openMultiInstanceUser" > 鍔犵 </el-button> <el-button - v-if="task.businessStatus === 'waiting' && task.multiInstance" + v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0" :disabled="buttonDisabled" type="primary" - @click="deleteMultiInstanceUser" + @click="handleTaskUser" > 鍑忕 </el-button> - <el-button v-if="task.businessStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleTerminationTask"> 缁堟 </el-button> - <el-button v-if="task.businessStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleBackProcessOpen"> 閫�鍥� </el-button> + <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleTerminationTask"> 缁堟 </el-button> + <el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleBackProcessOpen"> 閫�鍥� </el-button> <el-button :disabled="buttonDisabled" @click="cancel">鍙栨秷</el-button> </span> </template> @@ -54,14 +54,14 @@ <!-- 濮旀墭 --> <UserSelect ref="delegateTaskRef" :multiple="false" @confirm-call-back="handleDelegateTask"></UserSelect> <!-- 鍔犵缁勪欢 --> - <multiInstanceUser ref="multiInstanceUserRef" :title="title" @submit-callback="closeDialog" /> + <UserSelect ref="multiInstanceUserRef" :multiple="true" @confirm-call-back="addMultiInstanceUser"></UserSelect> <!-- 椹冲洖寮�濮� --> <el-dialog v-model="backVisible" draggable title="椹冲洖" width="40%" :close-on-click-modal="false"> - <el-form v-if="task.businessStatus === 'waiting'" v-loading="backLoading" :model="backForm" label-width="120px"> + <el-form v-if="task.flowStatus === 'waiting'" v-loading="backLoading" :model="backForm" label-width="120px"> <el-form-item label="椹冲洖鑺傜偣"> - <el-select v-model="backForm.targetActivityId" clearable placeholder="璇烽�夋嫨" style="width: 300px"> - <el-option v-for="item in taskNodeList" :key="item.nodeId" :label="item.nodeName" :value="item.nodeId" /> + <el-select v-model="backForm.nodeCode" clearable placeholder="璇烽�夋嫨" style="width: 300px"> + <el-option v-for="item in taskNodeList" :key="item.nodeCode" :label="item.nodeName" :value="item.nodeCode" /> </el-select> </el-form-item> <el-form-item label="娑堟伅鎻愰啋"> @@ -83,6 +83,19 @@ </template> </el-dialog> <!-- 椹冲洖缁撴潫 --> + <el-dialog v-model="deleteSignatureVisible" draggable title="鍑忕浜哄憳" width="700px" height="400px" append-to-body :close-on-click-modal="false"> + <div> + <el-table :data="deleteUserList" border> + <el-table-column prop="nodeName" label="浠诲姟鍚嶇О" /> + <el-table-column prop="nickName" label="鍔炵悊浜�" /> + <el-table-column label="鎿嶄綔" align="center" width="160"> + <template #default="scope"> + <el-button type="danger" size="small" icon="Delete" @click="deleteMultiInstanceUser(scope.row)">鍒犻櫎 </el-button> + </template> + </el-table-column> + </el-table> + </div> + </el-dialog> </el-dialog> </template> @@ -90,18 +103,17 @@ import { ref } from 'vue'; import { ComponentInternalInstance } from 'vue'; import { ElForm } from 'element-plus'; -import { completeTask, backProcess, getTaskById, transferTask, terminationTask, getTaskNodeList, delegateTask } from '@/api/workflow/task'; +import { completeTask, backProcess, getTask, taskOperation, terminationTask, getBackTaskNode, currentTaskAllUser } from '@/api/workflow/task'; import UserSelect from '@/components/UserSelect'; -import MultiInstanceUser from '@/components/Process/multiInstanceUser.vue'; + const { proxy } = getCurrentInstance() as ComponentInternalInstance; import { UserVO } from '@/api/system/user/types'; -import { TaskVO } from '@/api/workflow/task/types'; +import { FlowTaskVO, TaskOperationBo } from '@/api/workflow/task/types'; + const userSelectCopyRef = ref<InstanceType<typeof UserSelect>>(); const transferTaskRef = ref<InstanceType<typeof UserSelect>>(); const delegateTaskRef = ref<InstanceType<typeof UserSelect>>(); - -//鍔犵缁勪欢 -const multiInstanceUserRef = ref<InstanceType<typeof MultiInstanceUser>>(); +const multiInstanceUserRef = ref<InstanceType<typeof UserSelect>>(); const props = defineProps({ taskVariables: { @@ -119,65 +131,53 @@ const selectCopyUserList = ref<UserVO[]>([]); //鎶勯�佷汉id const selectCopyUserIds = ref<string>(undefined); -// 椹冲洖鏄惁鏄剧ず +//鍙噺绛剧殑浜哄憳 +const deleteUserList = ref<any>([]); +//椹冲洖鏄惁鏄剧ず const backVisible = ref(false); const backLoading = ref(true); const backButtonDisabled = ref(true); // 鍙┏鍥炲緱浠诲姟鑺傜偣 const taskNodeList = ref([]); //浠诲姟 -const task = ref<TaskVO>({ +const task = ref<FlowTaskVO>({ id: undefined, - name: undefined, - description: undefined, - priority: undefined, - owner: undefined, - assignee: undefined, - assigneeName: undefined, - processInstanceId: undefined, - executionId: undefined, - taskDefinitionId: undefined, - processDefinitionId: undefined, - endTime: undefined, - taskDefinitionKey: undefined, - dueDate: undefined, - category: undefined, - parentTaskId: undefined, + createTime: undefined, + updateTime: undefined, tenantId: undefined, - claimTime: undefined, - businessStatus: undefined, - businessStatusName: undefined, - processDefinitionName: undefined, - processDefinitionKey: undefined, - participantVo: undefined, - multiInstance: undefined, - businessKey: undefined, - wfNodeConfigVo: undefined + definitionId: undefined, + instanceId: undefined, + flowName: undefined, + businessId: undefined, + nodeCode: undefined, + nodeName: undefined, + flowCode: undefined, + flowStatus: undefined, + formCustom: undefined, + formPath: undefined, + nodeType: undefined, + nodeRatio: undefined }); -//鍔犵 鍑忕鏍囬 -const title = ref(''); const dialog = reactive<DialogOption>({ visible: false, title: '鎻愮ず' }); - +//鍑忕寮圭獥 +const deleteSignatureVisible = ref(false); const form = ref<Record<string, any>>({ taskId: undefined, message: undefined, variables: {}, messageType: ['1'], - wfCopyList: [] + flowCopyList: [] }); const backForm = ref<Record<string, any>>({ taskId: undefined, - targetActivityId: undefined, + nodeCode: undefined, message: undefined, variables: {}, messageType: ['1'] }); -const closeDialog = () => { - dialog.visible = false; -}; //鎵撳紑寮圭獥 const openDialog = (id?: string) => { selectCopyUserIds.value = undefined; @@ -189,7 +189,7 @@ loading.value = true; buttonDisabled.value = true; nextTick(() => { - getTaskById(taskId.value).then((response) => { + getTask(taskId.value).then((response) => { task.value = response.data; loading.value = false; buttonDisabled.value = false; @@ -205,15 +205,15 @@ form.value.taskId = taskId.value; form.value.taskVariables = props.taskVariables; if (selectCopyUserList.value && selectCopyUserList.value.length > 0) { - let wfCopyList = []; + let flowCopyList = []; selectCopyUserList.value.forEach((e) => { let copyUser = { userId: e.userId, userName: e.nickName }; - wfCopyList.push(copyUser); + flowCopyList.push(copyUser); }); - form.value.wfCopyList = wfCopyList; + form.value.flowCopyList = flowCopyList; } await proxy?.$modal.confirm('鏄惁纭鎻愪氦锛�'); loading.value = true; @@ -236,11 +236,11 @@ backVisible.value = true; backLoading.value = true; backButtonDisabled.value = true; - let data = await getTaskNodeList(task.value.processInstanceId); + let data = await getBackTaskNode(task.value.definitionId, task.value.nodeCode); taskNodeList.value = data.data; backLoading.value = false; backButtonDisabled.value = false; - backForm.value.targetActivityId = taskNodeList.value[0].nodeId; + backForm.value.nodeCode = taskNodeList.value[0].nodeCode; }; /** 椹冲洖娴佺▼ */ const handleBackProcess = async () => { @@ -249,7 +249,10 @@ loading.value = true; backLoading.value = true; backButtonDisabled.value = true; - await backProcess(backForm.value).finally(() => (loading.value = false)); + await backProcess(backForm.value).finally(() => { + loading.value = false; + buttonDisabled.value = false; + }); dialog.visible = false; backLoading.value = false; backButtonDisabled.value = false; @@ -282,18 +285,48 @@ selectCopyUserIds.value = selectCopyUserList.value.map((item) => item.userId).join(','); }; //鍔犵 -const addMultiInstanceUser = () => { - if (multiInstanceUserRef.value) { - title.value = '鍔犵浜哄憳'; - multiInstanceUserRef.value.getAddMultiInstanceList(taskId.value, []); +const openMultiInstanceUser = async () => { + multiInstanceUserRef.value.open(); +}; +//鍔犵 +const addMultiInstanceUser = async (data) => { + if (data && data.length > 0) { + const taskOperationBo = reactive<TaskOperationBo>({ + userIds: data.map((e) => e.userId), + taskId: taskId.value, + message: form.value.message + }); + await proxy?.$modal.confirm('鏄惁纭鎻愪氦锛�'); + loading.value = true; + buttonDisabled.value = true; + await taskOperation(taskOperationBo, 'addSignature').finally(() => { + loading.value = false; + buttonDisabled.value = false; + }); + dialog.visible = false; + emits('submitCallback'); + proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); + } else { + proxy?.$modal.msgWarning('璇烽�夋嫨鐢ㄦ埛锛�'); } }; //鍑忕 -const deleteMultiInstanceUser = () => { - if (multiInstanceUserRef.value) { - title.value = '鍑忕浜哄憳'; - multiInstanceUserRef.value.getDeleteMultiInstanceList(taskId.value); - } +const deleteMultiInstanceUser = async (row) => { + await proxy?.$modal.confirm('鏄惁纭鎻愪氦锛�'); + loading.value = true; + buttonDisabled.value = true; + const taskOperationBo = reactive<TaskOperationBo>({ + userIds: [row.userId], + taskId: taskId.value, + message: form.value.message + }); + await taskOperation(taskOperationBo, 'reductionSignature').finally(() => { + loading.value = false; + buttonDisabled.value = false; + }); + dialog.visible = false; + emits('submitCallback'); + proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); }; //鎵撳紑杞姙 const openTransferTask = () => { @@ -302,15 +335,18 @@ //杞姙 const handleTransferTask = async (data) => { if (data && data.length > 0) { - let params = { - taskId: taskId.value, + const taskOperationBo = reactive<TaskOperationBo>({ userId: data[0].userId, - comment: form.value.message - }; + taskId: taskId.value, + message: form.value.message + }); await proxy?.$modal.confirm('鏄惁纭鎻愪氦锛�'); loading.value = true; buttonDisabled.value = true; - await transferTask(params).finally(() => (loading.value = false)); + await taskOperation(taskOperationBo, 'transferTask').finally(() => { + loading.value = false; + buttonDisabled.value = false; + }); dialog.visible = false; emits('submitCallback'); proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); @@ -326,15 +362,18 @@ //濮旀墭 const handleDelegateTask = async (data) => { if (data && data.length > 0) { - let params = { - taskId: taskId.value, + const taskOperationBo = reactive<TaskOperationBo>({ userId: data[0].userId, - nickName: data[0].nickName - }; + taskId: taskId.value, + message: form.value.message + }); await proxy?.$modal.confirm('鏄惁纭鎻愪氦锛�'); loading.value = true; buttonDisabled.value = true; - await delegateTask(params).finally(() => (loading.value = false)); + await taskOperation(taskOperationBo, 'delegateTask').finally(() => { + loading.value = false; + buttonDisabled.value = false; + }); dialog.visible = false; emits('submitCallback'); proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); @@ -343,7 +382,7 @@ } }; //缁堟浠诲姟 -const handleTerminationTask = async (data) => { +const handleTerminationTask = async () => { let params = { taskId: taskId.value, comment: form.value.message @@ -351,11 +390,24 @@ await proxy?.$modal.confirm('鏄惁纭缁堟锛�'); loading.value = true; buttonDisabled.value = true; - await terminationTask(params).finally(() => (loading.value = false)); + await terminationTask(params).finally(() => { + loading.value = false; + buttonDisabled.value = false; + }); dialog.visible = false; emits('submitCallback'); proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); }; +const handleTaskUser = async () => { + let data = await currentTaskAllUser(taskId.value); + deleteUserList.value = data.data; + if (deleteUserList.value && deleteUserList.value.length > 0) { + deleteUserList.value.forEach((e) => { + e.nodeName = task.value.nodeName; + }); + } + deleteSignatureVisible.value = true; +}; /** * 瀵瑰鏆撮湶瀛愮粍浠舵柟娉� diff --git a/src/components/RoleSelect/index.vue b/src/components/RoleSelect/index.vue index 6ba2076..56a784b 100644 --- a/src/components/RoleSelect/index.vue +++ b/src/components/RoleSelect/index.vue @@ -53,7 +53,7 @@ </vxe-column> <vxe-column field="createTime" title="鍒涘缓鏃堕棿" align="center"> <template #default="scope"> - <span>{{ parseTime(scope.row.createTime) }}</span> + <span>{{ proxy.parseTime(scope.row.createTime) }}</span> </template> </vxe-column> </vxe-table> diff --git a/src/components/TopNav/index.vue b/src/components/TopNav/index.vue index e93e005..cfe2cd7 100644 --- a/src/components/TopNav/index.vue +++ b/src/components/TopNav/index.vue @@ -91,8 +91,8 @@ let activePath = path; if (path !== undefined && path.lastIndexOf('/') > 0 && hideList.indexOf(path) === -1) { const tmpPath = path.substring(1, path.length); - activePath = '/' + tmpPath.substring(0, tmpPath.indexOf('/')); if (!route.meta.link) { + activePath = '/' + tmpPath.substring(0, tmpPath.indexOf('/')); appStore.toggleSideBarHide(false); } } else if (!route.children) { diff --git a/src/components/UserSelect/index.vue b/src/components/UserSelect/index.vue index e9865e5..937a395 100644 --- a/src/components/UserSelect/index.vue +++ b/src/components/UserSelect/index.vue @@ -43,7 +43,7 @@ <el-card shadow="hover"> <template v-if="prop.multiple" #header> <el-tag v-for="user in selectUserList" :key="user.userId" closable style="margin: 2px" @close="handleCloseTag(user)"> - {{ user.userName }} + {{ user.nickName }} </el-tag> </template> @@ -100,14 +100,14 @@ <script setup lang="ts"> import api from '@/api/system/user'; import { UserQuery, UserVO } from '@/api/system/user/types'; -import { DeptVO } from '@/api/system/dept/types'; +import { DeptTreeVO, DeptVO } from '@/api/system/dept/types'; import { VxeTableInstance } from 'vxe-table'; import useDialog from '@/hooks/useDialog'; interface PropType { modelValue?: UserVO[] | UserVO | undefined; multiple?: boolean; - data?: string | number | (string | number)[]; + data?: string | number | (string | number)[] | undefined; } const prop = withDefaults(defineProps<PropType>(), { multiple: true, @@ -125,7 +125,7 @@ const total = ref(0); const dateRange = ref<[DateModelType, DateModelType]>(['', '']); const deptName = ref(''); -const deptOptions = ref<DeptVO[]>([]); +const deptOptions = ref<DeptTreeVO[]>([]); const selectUserList = ref<UserVO[]>([]); const deptTreeRef = ref<ElTreeInstance>(); @@ -166,7 +166,7 @@ const computedIds = (data) => { if (data instanceof Array) { - return [...data]; + return data.map(item => String(item)); } else if (typeof data === 'string') { return data.split(','); } else if (typeof data === 'number') { diff --git a/src/directive/permission/index.ts b/src/directive/permission/index.ts index afde332..eb2dccc 100644 --- a/src/directive/permission/index.ts +++ b/src/directive/permission/index.ts @@ -31,7 +31,7 @@ const { roles } = useUserStore(); if (value && value instanceof Array && value.length > 0) { const hasRole = roles.some((role: string) => { - return role === 'admin' || value.includes(role); + return role === 'superadmin' || role === 'admin' || value.includes(role); }); if (!hasRole) { el.parentNode && el.parentNode.removeChild(el); diff --git a/src/enums/SettingTypeEnum.ts b/src/enums/SettingTypeEnum.ts deleted file mode 100644 index bf4ec43..0000000 --- a/src/enums/SettingTypeEnum.ts +++ /dev/null @@ -1,16 +0,0 @@ -export enum SettingTypeEnum { - TITLE = 'title', - THEME = 'theme', - SIDE_THEME = 'sideTheme', - SHOW_SETTINGS = 'showSettings', - TOP_NAV = 'topNav', - TAGS_VIEW = 'tagsView', - FIXED_HEADER = 'fixedHeader', - SIDEBAR_LOGO = 'sidebarLogo', - DYNAMIC_TITLE = 'dynamicTitle', - ANIMATION_ENABLE = 'animationEnable', - LAYOUT = 'layout', - DARK = 'dark', - - LAYOUT_SETTING = 'layout-setting' -} diff --git a/src/enums/bpmn/IndexEnums.ts b/src/enums/bpmn/IndexEnums.ts deleted file mode 100644 index 8c39823..0000000 --- a/src/enums/bpmn/IndexEnums.ts +++ /dev/null @@ -1,17 +0,0 @@ -export enum AllocationTypeEnum { - USER = 'user', - CANDIDATE = 'candidate', - YOURSELF = 'yourself', - SPECIFY = 'specify' -} - -export enum SpecifyDescEnum { - SPECIFY_MULTIPLE = 'specifyMultiple', - SPECIFY_SINGLE = 'specifySingle' -} - -export enum MultiInstanceTypeEnum { - SERIAL = 'serial', - PARALLEL = 'parallel', - NONE = 'none' -} diff --git a/src/enums/layout/LayoutEnum.ts b/src/enums/layout/LayoutEnum.ts deleted file mode 100644 index 0aa601b..0000000 --- a/src/enums/layout/LayoutEnum.ts +++ /dev/null @@ -1,4 +0,0 @@ -export enum ThemeEnum { - DARK = 'theme-dark', - LIGHT = 'theme-light' -} diff --git a/src/lang/en_US.json b/src/lang/en_US.json deleted file mode 100644 index 17b472e..0000000 --- a/src/lang/en_US.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "route": { - "dashboard": "Dashboard", - "document": "Document" - }, - "login": { - "username": "Username", - "password": "Password", - "login": "Login", - "code": "Verification Code", - "copyright": "" - }, - "navbar": { - "full": "Full Screen", - "language": "Language", - "dashboard": "Dashboard", - "document": "Document", - "message": "Message", - "layoutSize": "Layout Size", - "selectTenant": "Select Tenant", - "layoutSetting": "Layout Setting", - "personalCenter": "Personal Center", - "logout": "Logout" - } -} diff --git a/src/lang/en_US.ts b/src/lang/en_US.ts index 034ea91..b090d3e 100644 --- a/src/lang/en_US.ts +++ b/src/lang/en_US.ts @@ -6,11 +6,68 @@ }, // 鐧诲綍椤甸潰鍥介檯鍖� login: { + selectPlaceholder: 'Please select/enter a company name', username: 'Username', password: 'Password', login: 'Login', + logging: 'Logging...', code: 'Verification Code', - copyright: '' + rememberPassword: 'Remember me', + switchRegisterPage: 'Sign up now', + rule: { + tenantId: { + required: 'Please enter your tenant id' + }, + username: { + required: 'Please enter your account' + }, + password: { + required: 'Please enter your password' + }, + code: { + required: 'Please enter a verification code' + } + }, + social: { + wechat: 'Wechat Login', + maxkey: 'MaxKey Login', + topiam: 'TopIam Login', + gitee: 'Gitee Login', + github: 'Github Login' + } + }, + // 娉ㄥ唽椤甸潰鍥介檯鍖� + register: { + selectPlaceholder: 'Please select/enter a company name', + username: 'Username', + password: 'Password', + confirmPassword: 'Confirm Password', + register: 'Register', + registering: 'Registering...', + registerSuccess: 'Congratulations, your {username} account has been registered!', + code: 'Verification Code', + switchLoginPage: 'Log in with an existing account', + rule: { + tenantId: { + required: 'Please enter your tenant id' + }, + username: { + required: 'Please enter your account', + length: 'The length of the user account must be between {min} and {max}' + }, + password: { + required: 'Please enter your password', + length: 'The user password must be between {min} and {max} in length', + pattern: "Can't contain illegal characters: {strings}" + }, + code: { + required: 'Please enter a verification code' + }, + confirmPassword: { + required: 'Please enter your password again', + equalToPassword: 'The password entered twice is inconsistent' + } + } }, // 瀵艰埅鏍忓浗闄呭寲 navbar: { diff --git a/src/lang/index.ts b/src/lang/index.ts index e4e1d25..4f8e74c 100644 --- a/src/lang/index.ts +++ b/src/lang/index.ts @@ -2,7 +2,8 @@ import { createI18n } from 'vue-i18n'; import { LanguageEnum } from '@/enums/LanguageEnum'; -import messages from '@intlify/unplugin-vue-i18n/messages'; +import zh_CN from '@/lang/zh_CN'; +import en_US from '@/lang/en_US'; /** * 鑾峰彇褰撳墠璇█ @@ -21,7 +22,12 @@ allowComposition: true, legacy: false, locale: getLanguage(), - messages + messages: { + zh_CN: zh_CN, + en_US: en_US + } }); export default i18n; + +export type LanguageType = typeof zh_CN; diff --git a/src/lang/zh_CN.json b/src/lang/zh_CN.json deleted file mode 100644 index 071598d..0000000 --- a/src/lang/zh_CN.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "route": { - "dashboard": "棣栭〉", - "document": "椤圭洰鏂囨。" - }, - "login": { - "username": "鐢ㄦ埛鍚�", - "password": "瀵嗙爜", - "login": "鐧� 褰�", - "code": "璇疯緭鍏ラ獙璇佺爜", - "copyright": "" - }, - "navbar": { - "full": "鍏ㄥ睆", - "language": "璇█", - "dashboard": "棣栭〉", - "document": "椤圭洰鏂囨。", - "message": "娑堟伅", - "layoutSize": "甯冨眬澶у皬", - "selectTenant": "閫夋嫨绉熸埛", - "layoutSetting": "甯冨眬璁剧疆", - "personalCenter": "涓汉涓績", - "logout": "閫�鍑虹櫥褰�" - } -} diff --git a/src/lang/zh_CN.ts b/src/lang/zh_CN.ts index 666a400..3cc9872 100644 --- a/src/lang/zh_CN.ts +++ b/src/lang/zh_CN.ts @@ -6,12 +6,70 @@ }, // 鐧诲綍椤甸潰鍥介檯鍖� login: { + selectPlaceholder: '璇烽�夋嫨/杈撳叆鍏徃鍚嶇О', username: '鐢ㄦ埛鍚�', password: '瀵嗙爜', login: '鐧� 褰�', - code: '璇疯緭鍏ラ獙璇佺爜', - copyright: '' + logging: '鐧� 褰� 涓�...', + code: '楠岃瘉鐮�', + rememberPassword: '璁颁綇鎴�', + switchRegisterPage: '绔嬪嵆娉ㄥ唽', + rule: { + tenantId: { + required: '璇疯緭鍏ユ偍鐨勭鎴风紪鍙�' + }, + username: { + required: '璇疯緭鍏ユ偍鐨勮处鍙�' + }, + password: { + required: '璇疯緭鍏ユ偍鐨勫瘑鐮�' + }, + code: { + required: '璇疯緭鍏ラ獙璇佺爜' + } + }, + social: { + wechat: '寰俊鐧诲綍', + maxkey: 'MaxKey鐧诲綍', + topiam: 'TopIam鐧诲綍', + gitee: 'Gitee鐧诲綍', + github: 'Github鐧诲綍' + } }, + // 娉ㄥ唽椤甸潰鍥介檯鍖� + register: { + selectPlaceholder: '璇烽�夋嫨/杈撳叆鍏徃鍚嶇О', + username: '鐢ㄦ埛鍚�', + password: '瀵嗙爜', + confirmPassword: '纭瀵嗙爜', + register: '娉� 鍐�', + registering: '娉� 鍐� 涓�...', + registerSuccess: '鎭枩浣狅紝鎮ㄧ殑璐﹀彿 {username} 娉ㄥ唽鎴愬姛锛�', + code: '楠岃瘉鐮�', + switchLoginPage: '浣跨敤宸叉湁璐︽埛鐧诲綍', + rule: { + tenantId: { + required: '璇疯緭鍏ユ偍鐨勭鎴风紪鍙�' + }, + username: { + required: '璇疯緭鍏ユ偍鐨勮处鍙�', + length: '鐢ㄦ埛璐﹀彿闀垮害蹇呴』浠嬩簬 {min} 鍜� {max} 涔嬮棿' + }, + password: { + required: '璇疯緭鍏ユ偍鐨勫瘑鐮�', + length: '鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 {min} 鍜� {max} 涔嬮棿', + pattern: '涓嶈兘鍖呭惈闈炴硶瀛楃锛歿strings}' + }, + code: { + required: '璇疯緭鍏ラ獙璇佺爜' + }, + confirmPassword: { + required: '璇峰啀娆¤緭鍏ユ偍鐨勫瘑鐮�', + equalToPassword: '涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�' + } + } + }, + // 瀵艰埅鏍忓浗闄呭寲 navbar: { full: '鍏ㄥ睆', language: '璇█', diff --git a/src/layout/components/AppMain.vue b/src/layout/components/AppMain.vue index 7f86ef4..0d402f2 100644 --- a/src/layout/components/AppMain.vue +++ b/src/layout/components/AppMain.vue @@ -20,6 +20,7 @@ import IframeToggle from './IframeToggle/index.vue'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; +const route = useRoute(); const tagsViewStore = useTagsViewStore(); // 闅忔満鍔ㄧ敾闆嗗悎 @@ -37,6 +38,20 @@ }, { immediate: true } ); + +onMounted(() => { + addIframe() +}) + +watchEffect((route) => { + addIframe() +}) + +function addIframe() { + if (route.meta.link) { + useTagsViewStore().addIframeView(route) + } +} </script> <style lang="scss" scoped> diff --git a/src/layout/components/Navbar.vue b/src/layout/components/Navbar.vue index c2ed0b6..01cc22e 100644 --- a/src/layout/components/Navbar.vue +++ b/src/layout/components/Navbar.vue @@ -13,7 +13,7 @@ clearable filterable reserve-keyword - :placeholder="$t('navbar.selectTenant')" + :placeholder="proxy.$t('navbar.selectTenant')" @change="dynamicTenantEvent" @clear="dynamicClearEvent" > @@ -29,7 +29,7 @@ </div> </el-tooltip> <!-- 娑堟伅 --> - <el-tooltip :content="$t('navbar.message')" effect="dark" placement="bottom"> + <el-tooltip :content="proxy.$t('navbar.message')" effect="dark" placement="bottom"> <div> <el-popover placement="bottom" trigger="click" transition="el-zoom-in-top" :width="300" :persistent="false"> <template #reference> @@ -47,19 +47,19 @@ <ruo-yi-git id="ruoyi-git" class="right-menu-item hover-effect" /> </el-tooltip> - <el-tooltip :content="$t('navbar.document')" effect="dark" placement="bottom"> + <el-tooltip :content="proxy.$t('navbar.document')" effect="dark" placement="bottom"> <ruo-yi-doc id="ruoyi-doc" class="right-menu-item hover-effect" /> </el-tooltip> - <el-tooltip :content="$t('navbar.full')" effect="dark" placement="bottom"> + <el-tooltip :content="proxy.$t('navbar.full')" effect="dark" placement="bottom"> <screenfull id="screenfull" class="right-menu-item hover-effect" /> </el-tooltip> - <el-tooltip :content="$t('navbar.language')" effect="dark" placement="bottom"> + <el-tooltip :content="proxy.$t('navbar.language')" effect="dark" placement="bottom"> <lang-select id="lang-select" class="right-menu-item hover-effect" /> </el-tooltip> - <el-tooltip :content="$t('navbar.layoutSize')" effect="dark" placement="bottom"> + <el-tooltip :content="proxy.$t('navbar.layoutSize')" effect="dark" placement="bottom"> <size-select id="size-select" class="right-menu-item hover-effect" /> </el-tooltip> </template> @@ -72,13 +72,13 @@ <template #dropdown> <el-dropdown-menu> <router-link v-if="!dynamic" to="/user/profile"> - <el-dropdown-item>{{ $t('navbar.personalCenter') }}</el-dropdown-item> + <el-dropdown-item>{{ proxy.$t('navbar.personalCenter') }}</el-dropdown-item> </router-link> <el-dropdown-item v-if="settingsStore.showSettings" command="setLayout"> - <span>{{ $t('navbar.layoutSetting') }}</span> + <span>{{ proxy.$t('navbar.layoutSetting') }}</span> </el-dropdown-item> <el-dropdown-item divided command="logout"> - <span>{{ $t('navbar.logout') }}</span> + <span>{{ proxy.$t('navbar.logout') }}</span> </el-dropdown-item> </el-dropdown-menu> </template> @@ -98,6 +98,7 @@ import { dynamicClear, dynamicTenant } from '@/api/system/tenant'; import { TenantVO } from '@/api/types'; import notice from './notice/index.vue'; +import router from '@/router'; const appStore = useAppStore(); const userStore = useUserStore(); @@ -126,23 +127,23 @@ if (companyName.value != null && companyName.value !== '') { await dynamicTenant(tenantId); dynamic.value = true; - proxy?.$tab.closeAllPage(); - proxy?.$router.push('/'); - proxy?.$tab.refreshPage(); + await proxy?.$router.push('/'); + await proxy?.proxy.$tab.closeAllPage(); + await proxy?.proxy.$tab.refreshPage(); } }; const dynamicClearEvent = async () => { await dynamicClear(); dynamic.value = false; - proxy?.$tab.closeAllPage(); - proxy?.$router.push('/'); - proxy?.$tab.refreshPage(); + await proxy?.$router.push('/'); + await proxy?.proxy.$tab.closeAllPage(); + await proxy?.proxy.$tab.refreshPage(); }; /** 绉熸埛鍒楄〃 */ const initTenantList = async () => { - const { data } = await getTenantList(); + const { data } = await getTenantList(true); tenantEnabled.value = data.tenantEnabled === undefined ? true : data.tenantEnabled; if (tenantEnabled.value) { tenantList.value = data.voList; @@ -163,8 +164,14 @@ cancelButtonText: '鍙栨秷', type: 'warning' }); - await userStore.logout(); - location.href = import.meta.env.VITE_APP_CONTEXT_PATH + 'index'; + userStore.logout().then(() => { + router.replace({ + path: '/login', + query: { + redirect: encodeURIComponent(router.currentRoute.value.fullPath || '/') + } + }); + }); }; const emits = defineEmits(['setLayout']); diff --git a/src/layout/components/Sidebar/SidebarItem.vue b/src/layout/components/Sidebar/SidebarItem.vue index 3720062..5e82ea3 100644 --- a/src/layout/components/Sidebar/SidebarItem.vue +++ b/src/layout/components/Sidebar/SidebarItem.vue @@ -59,11 +59,9 @@ const showingChildren = children.filter((item) => { if (item.hidden) { return false; - } else { - // Temp set(will be used if only has one showing child) - onlyOneChild.value = item; - return true; } + onlyOneChild.value = item; + return true; }); // When there is only one child router, the child router is displayed by default diff --git a/src/layout/components/TagsView/index.vue b/src/layout/components/TagsView/index.vue index 1e12ca4..9bcf285 100644 --- a/src/layout/components/TagsView/index.vue +++ b/src/layout/components/TagsView/index.vue @@ -70,8 +70,8 @@ const activeStyle = (tag: RouteLocationNormalized) => { if (!isActive(tag)) return {}; return { - 'background-color': theme.value, - 'border-color': theme.value + 'background-color': 'var(--tags-view-active-bg)', + 'border-color': 'var(--tags-view-active-border-color)' }; }; const isAffix = (tag: RouteLocationNormalized) => { @@ -135,11 +135,7 @@ } if (name) { useTagsViewStore().addView(route as any); - if (route.meta.link) { - useTagsViewStore().addIframeView(route as any); - } } - return false; }; const moveToCurrentTag = () => { nextTick(() => { diff --git a/src/layout/components/TopBar/search.vue b/src/layout/components/TopBar/search.vue index cf4b024..182e84a 100644 --- a/src/layout/components/TopBar/search.vue +++ b/src/layout/components/TopBar/search.vue @@ -66,7 +66,7 @@ state.isShowSearch = false; }; // 鑿滃崟鎼滅储鏁版嵁杩囨护 -const menuSearch = (queryString: string, cb: Function) => { +const menuSearch = (queryString: string, cb: (options: any[]) => void) => { let options = state.menuList.filter((item) => { return item.title.indexOf(queryString) > -1; }); diff --git a/src/layout/index.vue b/src/layout/index.vue index ce47a30..207a470 100644 --- a/src/layout/index.vue +++ b/src/layout/index.vue @@ -27,7 +27,7 @@ import useAppStore from '@/store/modules/app'; import useSettingsStore from '@/store/modules/settings'; import { initWebSocket } from '@/utils/websocket'; -import { initSSE } from "@/utils/sse"; +import { initSSE } from '@/utils/sse'; const settingsStore = useSettingsStore(); const theme = computed(() => settingsStore.theme); diff --git a/src/permission.ts b/src/permission.ts index 125438b..b05f8c3 100644 --- a/src/permission.ts +++ b/src/permission.ts @@ -3,14 +3,18 @@ import NProgress from 'nprogress'; import 'nprogress/nprogress.css'; import { getToken } from '@/utils/auth'; -import { isHttp } from '@/utils/validate'; +import { isHttp, isPathMatch } from '@/utils/validate'; import { isRelogin } from '@/utils/request'; import useUserStore from '@/store/modules/user'; import useSettingsStore from '@/store/modules/settings'; import usePermissionStore from '@/store/modules/permission'; NProgress.configure({ showSpinner: false }); -const whiteList = ['/login', '/register', '/social-callback']; +const whiteList = ['/login', '/register', '/social-callback', '/register*', '/register/*']; + +const isWhiteList = (path: string) => { + return whiteList.some(pattern => isPathMatch(pattern, path)) +} router.beforeEach(async (to, from, next) => { NProgress.start(); @@ -20,7 +24,7 @@ if (to.path === '/login') { next({ path: '/' }); NProgress.done(); - } else if (whiteList.indexOf(to.path as string) !== -1) { + } else if (isWhiteList(to.path)) { next(); } else { if (useUserStore().roles.length === 0) { @@ -40,7 +44,7 @@ router.addRoute(route); // 鍔ㄦ�佹坊鍔犲彲璁块棶璺敱琛� } }); - // @ts-ignore + // @ts-expect-error hack鏂规硶 纭繚addRoutes宸插畬鎴� next({ path: to.path, replace: true, params: to.params, query: to.query, hash: to.hash, name: to.name as string }); // hack鏂规硶 纭繚addRoutes宸插畬鎴� } } else { @@ -49,7 +53,7 @@ } } else { // 娌℃湁token - if (whiteList.indexOf(to.path as string) !== -1) { + if (isWhiteList(to.path)) { // 鍦ㄥ厤鐧诲綍鐧藉悕鍗曪紝鐩存帴杩涘叆 next(); } else { diff --git a/src/plugins/cache.ts b/src/plugins/cache.ts index cf43680..e5ceead 100644 --- a/src/plugins/cache.ts +++ b/src/plugins/cache.ts @@ -26,6 +26,7 @@ if (value != null) { return JSON.parse(value); } + return null; }, remove(key: string) { sessionStorage.removeItem(key); @@ -59,6 +60,7 @@ if (value != null) { return JSON.parse(value); } + return null; }, remove(key: string) { localStorage.removeItem(key); diff --git a/src/plugins/tab.ts b/src/plugins/tab.ts index 86421a8..4b44dc6 100644 --- a/src/plugins/tab.ts +++ b/src/plugins/tab.ts @@ -1,5 +1,5 @@ import router from '@/router'; -import {RouteLocationMatched, RouteLocationNormalized, RouteLocationRaw} from 'vue-router'; +import { RouteLocationMatched, RouteLocationNormalized, RouteLocationRaw } from 'vue-router'; import useTagsViewStore from '@/store/modules/tagsView'; export default { diff --git a/src/router/index.ts b/src/router/index.ts index 86e0092..2ab09dd 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -103,7 +103,7 @@ path: 'role/:userId(\\d+)', component: () => import('@/views/system/user/authRole.vue'), name: 'AuthRole', - meta: { title: '鍒嗛厤瑙掕壊', activeMenu: '/system/user', icon: '' } + meta: { title: '鍒嗛厤瑙掕壊', activeMenu: '/system/user', icon: '', noCache: true } } ] }, @@ -117,7 +117,7 @@ path: 'user/:roleId(\\d+)', component: () => import('@/views/system/role/authUser.vue'), name: 'AuthUser', - meta: { title: '鍒嗛厤鐢ㄦ埛', activeMenu: '/system/role', icon: '' } + meta: { title: '鍒嗛厤鐢ㄦ埛', activeMenu: '/system/role', icon: '', noCache: true } } ] }, @@ -131,7 +131,7 @@ path: 'index/:dictId(\\d+)', component: () => import('@/views/system/dict/data.vue'), name: 'Data', - meta: { title: '瀛楀吀鏁版嵁', activeMenu: '/system/dict', icon: '' } + meta: { title: '瀛楀吀鏁版嵁', activeMenu: '/system/dict', icon: '', noCache: true } } ] }, @@ -145,7 +145,7 @@ path: 'index', component: () => import('@/views/system/oss/config.vue'), name: 'OssConfig', - meta: { title: '閰嶇疆绠$悊', activeMenu: '/system/oss', icon: '' } + meta: { title: '閰嶇疆绠$悊', activeMenu: '/system/oss', icon: '', noCache: true } } ] }, @@ -176,6 +176,20 @@ meta: { title: '璇峰亣鐢宠', activeMenu: '/workflow/leave', noCache: true } } ] + }, + { + path: '/workflow/design', + component: Layout, + hidden: true, + permissions: ['workflow:leave:edit'], + children: [ + { + path: 'index', + component: () => import('@/views/workflow/processDefinition/design.vue'), + name: 'design', + meta: { title: '娴佺▼璁捐', activeMenu: '/workflow/processDefinition', noCache: true } + } + ] } ]; @@ -189,9 +203,8 @@ scrollBehavior(to, from, savedPosition) { if (savedPosition) { return savedPosition; - } else { - return { top: 0 }; } + return { top: 0 }; } }); diff --git a/src/store/modules/dict.ts b/src/store/modules/dict.ts index 2f937b9..cd1a41d 100644 --- a/src/store/modules/dict.ts +++ b/src/store/modules/dict.ts @@ -1,29 +1,15 @@ export const useDictStore = defineStore('dict', () => { - const dict = ref< - Array<{ - key: string; - value: DictDataOption[]; - }> - >([]); + const dict = ref<Map<string, DictDataOption[]>>(new Map()); /** * 鑾峰彇瀛楀吀 * @param _key 瀛楀吀key */ const getDict = (_key: string): DictDataOption[] | null => { - if (_key == null && _key == '') { + if (!_key) { return null; } - try { - for (let i = 0; i < dict.value.length; i++) { - if (dict.value[i].key == _key) { - return dict.value[i].value; - } - } - } catch (e) { - return null; - } - return null; + return dict.value.get(_key) || null; }; /** @@ -32,11 +18,15 @@ * @param _value 瀛楀吀value */ const setDict = (_key: string, _value: DictDataOption[]) => { - if (_key !== null && _key !== '') { - dict.value.push({ - key: _key, - value: _value - }); + if (!_key) { + return false; + } + try { + dict.value.set(_key, _value); + return true; + } catch (e) { + console.error('Error in setDict:', e); + return false; } }; @@ -45,25 +35,22 @@ * @param _key */ const removeDict = (_key: string): boolean => { - let bln = false; - try { - for (let i = 0; i < dict.value.length; i++) { - if (dict.value[i].key == _key) { - dict.value.splice(i, 1); - return true; - } - } - } catch (e) { - bln = false; + if (!_key) { + return false; } - return bln; + try { + return dict.value.delete(_key); + } catch (e) { + console.error('Error in removeDict:', e); + return false; + } }; /** * 娓呯┖瀛楀吀 */ const cleanDict = (): void => { - dict.value = []; + dict.value.clear(); }; return { diff --git a/src/store/modules/modeler.ts b/src/store/modules/modeler.ts deleted file mode 100644 index 204f450..0000000 --- a/src/store/modules/modeler.ts +++ /dev/null @@ -1,76 +0,0 @@ -import type { Modeler, Modeling, Canvas, ElementRegistry, Moddle, BpmnFactory } from 'bpmn'; - -type ModelerStore = { - modeler: Modeler | undefined; - moddle: Moddle | undefined; - modeling: Modeling | undefined; - canvas: Canvas | undefined; - elementRegistry: ElementRegistry | undefined; - bpmnFactory: BpmnFactory | undefined; - // 娴佺▼瀹氫箟鏍硅妭鐐逛俊鎭� - procDefId: string | undefined; - procDefName: string | undefined; -}; - -const defaultState: ModelerStore = { - modeler: undefined, - moddle: undefined, - modeling: undefined, - canvas: undefined, - elementRegistry: undefined, - bpmnFactory: undefined, - procDefId: undefined, - procDefName: undefined -}; -export const useModelerStore = defineStore('modeler', () => { - let modeler = defaultState.modeler; - let moddle = defaultState.moddle; - let modeling = defaultState.modeling; - let canvas = defaultState.canvas; - let elementRegistry = defaultState.elementRegistry; - let bpmnFactory = defaultState.bpmnFactory; - const procDefId = ref(defaultState.procDefId); - const procDefName = ref(defaultState.procDefName); - - const getModeler = () => modeler; - const getModdle = () => moddle; - const getModeling = (): Modeling | undefined => modeling; - const getCanvas = (): Canvas | undefined => canvas; - const getElRegistry = (): ElementRegistry | undefined => elementRegistry; - const getBpmnFactory = (): BpmnFactory | undefined => bpmnFactory; - const getProcDefId = (): string | undefined => procDefId.value; - const getProcDefName = (): string | undefined => procDefName.value; - - // 璁剧疆鏍硅妭鐐� - const setModeler = (modelers: Modeler | undefined) => { - if (modelers) { - modeler = modelers; - modeling = modelers.get<Modeling>('modeling'); - moddle = modelers.get<Moddle>('moddle'); - canvas = modelers.get<Canvas>('canvas'); - bpmnFactory = modelers.get<BpmnFactory>('bpmnFactory'); - elementRegistry = modelers.get<ElementRegistry>('elementRegistry'); - } else { - modeling = moddle = canvas = elementRegistry = bpmnFactory = undefined; - } - }; - // 璁剧疆娴佺▼瀹氫箟鏍硅妭鐐逛俊鎭� - const setProcDef = (modeler: Modeler | undefined) => { - procDefId.value = modeler.get<Canvas>('canvas').getRootElement().businessObject.get('id'); - procDefName.value = modeler.get<Canvas>('canvas').getRootElement().businessObject.get('name'); - }; - - return { - getModeler, - getModdle, - getModeling, - getCanvas, - getElRegistry, - getBpmnFactory, - getProcDefId, - getProcDefName, - setModeler, - setProcDef - }; -}); -export default useModelerStore; diff --git a/src/store/modules/permission.ts b/src/store/modules/permission.ts index e90df4c..43fcef8 100644 --- a/src/store/modules/permission.ts +++ b/src/store/modules/permission.ts @@ -158,9 +158,12 @@ export const loadView = (view: any, name: string) => { let res; for (const path in modules) { - const dir = path.split('views/')[1].split('.vue')[0]; + const viewsIndex = path.indexOf('/views/'); + let dir = path.substring(viewsIndex + 7); + dir = dir.substring(0, dir.lastIndexOf('.vue')); if (dir === view) { res = createCustomNameComponent(modules[path], { name }); + return res; } } return res; diff --git a/src/store/modules/tagsView.ts b/src/store/modules/tagsView.ts index 9756ac2..b6cf434 100644 --- a/src/store/modules/tagsView.ts +++ b/src/store/modules/tagsView.ts @@ -31,7 +31,7 @@ const delIframeView = (view: RouteLocationNormalized): Promise<RouteLocationNormalized[]> => { return new Promise((resolve) => { iframeViews.value = iframeViews.value.filter((item: RouteLocationNormalized) => item.path !== view.path); - resolve([...iframeViews.value as RouteLocationNormalized[]]); + resolve([...(iframeViews.value as RouteLocationNormalized[])]); }); }; const addVisitedView = (view: RouteLocationNormalized): void => { @@ -54,7 +54,7 @@ delCachedView(view); } resolve({ - visitedViews: [...visitedViews.value as RouteLocationNormalized[]], + visitedViews: [...(visitedViews.value as RouteLocationNormalized[])], cachedViews: [...cachedViews.value] }); }); @@ -68,7 +68,7 @@ break; } } - resolve([...visitedViews.value as RouteLocationNormalized[]]); + resolve([...(visitedViews.value as RouteLocationNormalized[])]); }); }; const delCachedView = (view?: RouteLocationNormalized): Promise<string[]> => { @@ -92,7 +92,7 @@ delOthersVisitedViews(view); delOthersCachedViews(view); resolve({ - visitedViews: [...visitedViews.value as RouteLocationNormalized[]], + visitedViews: [...(visitedViews.value as RouteLocationNormalized[])], cachedViews: [...cachedViews.value] }); }); @@ -103,7 +103,7 @@ visitedViews.value = visitedViews.value.filter((v: RouteLocationNormalized) => { return v.meta?.affix || v.path === view.path; }); - resolve([...visitedViews.value as RouteLocationNormalized[]]); + resolve([...(visitedViews.value as RouteLocationNormalized[])]); }); }; const delOthersCachedViews = (view: RouteLocationNormalized): Promise<string[]> => { @@ -124,7 +124,7 @@ delAllVisitedViews(); delAllCachedViews(); resolve({ - visitedViews: [...visitedViews.value as RouteLocationNormalized[]], + visitedViews: [...(visitedViews.value as RouteLocationNormalized[])], cachedViews: [...cachedViews.value] }); }); @@ -132,7 +132,7 @@ const delAllVisitedViews = (): Promise<RouteLocationNormalized[]> => { return new Promise((resolve) => { visitedViews.value = visitedViews.value.filter((tag: RouteLocationNormalized) => tag.meta?.affix); - resolve([...visitedViews.value as RouteLocationNormalized[]]); + resolve([...(visitedViews.value as RouteLocationNormalized[])]); }); }; @@ -167,7 +167,7 @@ } return false; }); - resolve([...visitedViews.value as RouteLocationNormalized[]]); + resolve([...(visitedViews.value as RouteLocationNormalized[])]); }); }; const delLeftTags = (view: RouteLocationNormalized): Promise<RouteLocationNormalized[]> => { @@ -186,7 +186,7 @@ } return false; }); - resolve([...visitedViews.value as RouteLocationNormalized[]]); + resolve([...(visitedViews.value as RouteLocationNormalized[])]); }); }; diff --git a/src/types/bpmn/editor/global.d.ts b/src/types/bpmn/editor/global.d.ts deleted file mode 100644 index 1b9a634..0000000 --- a/src/types/bpmn/editor/global.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { MessageApiInjection } from 'naive-ui/lib/message/src/MessageProvider'; - -declare global { - interface Window { - bpmnInstances: any; - __messageBox: MessageApiInjection; - URL: any; - } -} - -declare interface Window { - bpmnInstances: any; -} diff --git a/src/types/bpmn/index.d.ts b/src/types/bpmn/index.d.ts deleted file mode 100644 index f8e8d15..0000000 --- a/src/types/bpmn/index.d.ts +++ /dev/null @@ -1,15 +0,0 @@ -declare module 'bpmn' { - import type modeler from 'bpmn-js/lib/Modeler'; - import type modeling from 'bpmn-js/lib/features/modeling/Modeling'; - import type canvas from 'diagram-js/lib/core/Canvas'; - import type elementRegistry from 'diagram-js/lib/core/ElementRegistry'; - import type bpmnFactory from 'bpmn-js/lib/features/modeling/BpmnFactory'; - - export type Modeler = modeler; - export type Modeling = modeling; - export type Canvas = canvas; - export type ElementRegistry = elementRegistry; - export type Moddle = import('moddle').Moddle; - export type ModdleElement = import('moddle').ModdleElement; - export type BpmnFactory = bpmnFactory; -} diff --git a/src/types/bpmn/moddle.d.ts b/src/types/bpmn/moddle.d.ts deleted file mode 100644 index 1ed7933..0000000 --- a/src/types/bpmn/moddle.d.ts +++ /dev/null @@ -1,37 +0,0 @@ -declare module 'moddle' { - import type { Element as element } from 'bpmn-js/lib/model/Types'; - - export type Element = { - get<T>(name: string): T; - - set(name: string, value: any): void; - } & element; - - export interface ModdleElement extends Element { - $model: Moddle; - readonly $type: string; - $attrs: object | {}; - $parent: any; - businessObject: ModdleElement; - type: string; - - [field: string]: any; - - hasType(element: ModdleElement, type?: string): boolean; - } - - export interface Package { - name: string; - prefix: string; - } - - export interface Moddle { - typeCache: Record<string, ModdleElement>; - - getPackage: typeof Registry.prototype.getPackage; - - getPackages: typeof Registry.prototype.getPackages; - - create(type: string, attrs?: any): ModdleElement; - } -} diff --git a/src/types/bpmn/panel.d.ts b/src/types/bpmn/panel.d.ts deleted file mode 100644 index 3179261..0000000 --- a/src/types/bpmn/panel.d.ts +++ /dev/null @@ -1,92 +0,0 @@ -declare module 'bpmnDesign' { - import { AllocationTypeEnum, SpecifyDescEnum, MultiInstanceTypeEnum } from '@/enums/bpmn/IndexEnums'; - - export interface ParamVO { - type: string; - name: string; - value: string; - } - - export interface TaskListenerVO { - event: string; - type: string; - name: string; - className: string; - params: ParamVO[]; - } - - export interface ExecutionListenerVO { - event: string; - type: string; - className: string; - params: ParamVO[]; - } - - interface BasePanel { - id: string; - name: string; - } - export interface ProcessPanel extends BasePanel {} - - export interface TaskPanel extends BasePanel { - allocationType: AllocationTypeEnum; - specifyDesc: SpecifyDescEnum; - multiInstanceType: MultiInstanceTypeEnum; - async?: boolean; - priority?: number; - formKey?: string; - skipExpression?: string; - isForCompensation?: boolean; - triggerServiceTask?: boolean; - autoStoreVariables?: boolean; - ruleVariablesInput?: string; - excludeTaskListener?: boolean; - exclude?: boolean; - class?: string; - dueDate?: string; - fixedAssignee?: string; - - candidateUsers?: string; - assignee?: string; - candidateGroups?: string; - collection?: string; - elementVariable?: string; - completionCondition?: string; - isSequential?: boolean; - - loopCharacteristics?: { - collection: string; - elementVariable: string; - isSequential: boolean; - completionCondition: { - body: string; - }; - }; - } - - export interface StartEndPanel extends BasePanel {} - export interface GatewayPanel extends BasePanel {} - export interface SequenceFlowPanel extends BasePanel { - conditionExpression: { - body: string; - }; - conditionExpressionValue: string; - skipExpression: string; - } - - export interface ParticipantPanel extends BasePanel {} - export interface SubProcessPanel extends BasePanel { - multiInstanceType: MultiInstanceTypeEnum; - collection?: string; - elementVariable?: string; - completionCondition?: string; - loopCharacteristics?: { - collection: string; - elementVariable: string; - isSequential: boolean; - completionCondition: { - body: string; - }; - }; - } -} diff --git a/src/types/module.d.ts b/src/types/module.d.ts index 984df9f..2fc273a 100644 --- a/src/types/module.d.ts +++ b/src/types/module.d.ts @@ -8,10 +8,11 @@ import { handleTree, addDateRange, selectDictLabel, selectDictLabels, parseTime } from '@/utils/ruoyi'; import { getConfigKey, updateConfigByKey } from '@/api/system/config'; import { download as rd } from '@/utils/request'; +import type { LanguageType } from '@/lang'; export {}; -declare module 'vue' { +declare module '@vue/runtime-core' { interface ComponentCustomProperties { // 鍏ㄥ眬鏂规硶澹版槑 $modal: typeof modal; @@ -20,6 +21,11 @@ $auth: typeof auth; $cache: typeof cache; animate: typeof animate; + /** + * i18n $t鏂规硶鏀寔ts绫诲瀷鎻愮ず + * @param key i18n key + */ + $t(key: ObjKeysToUnion<LanguageType>): string; useDict: typeof useDict; addDateRange: typeof addDateRange; @@ -33,7 +39,13 @@ } } -declare module 'vform3-builds' { - const content: any; - export = content; -} +/** + * { a: 1, b: { ba: { baa: 1, bab: 2 }, bb: 2} } ---> a | b.ba.baa | b.ba.bab | b.bb + * https://juejin.cn/post/7280062870670606397 + */ +export type ObjKeysToUnion<T, P extends string = ''> = T extends object + ? { + [K in keyof T]: ObjKeysToUnion<T[K], P extends '' ? `${K & string}` : `${P}.${K & string}`>; + }[keyof T] + : P; + diff --git a/src/utils/request.ts b/src/utils/request.ts index f8f1f53..9682b81 100644 --- a/src/utils/request.ts +++ b/src/utils/request.ts @@ -10,7 +10,7 @@ import { getLanguage } from '@/lang'; import { encryptBase64, encryptWithAes, generateAesKey, decryptWithAes, decryptBase64 } from '@/utils/crypto'; import { encrypt, decrypt } from '@/utils/jsencrypt'; -import router from "@/router"; +import router from '@/router'; const encryptHeader = 'encrypt-key'; let downloadLoadingInstance: LoadingInstance; diff --git a/src/utils/sse.ts b/src/utils/sse.ts index 9174f0d..69447ad 100644 --- a/src/utils/sse.ts +++ b/src/utils/sse.ts @@ -8,11 +8,8 @@ return; } - url = url + '?Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID - const { - data, - error - } = useEventSource(url, [], { + url = url + '?Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID; + const { data, error } = useEventSource(url, [], { autoReconnect: { retries: 10, delay: 3000, diff --git a/src/utils/validate.ts b/src/utils/validate.ts index 4d57894..788095c 100644 --- a/src/utils/validate.ts +++ b/src/utils/validate.ts @@ -1,4 +1,16 @@ /** + * 璺緞鍖归厤鍣� + * @param {string} pattern + * @param {string} path + * @returns {Boolean} + */ +export function isPathMatch(pattern: string, path: string) { + const regexPattern = pattern.replace(/\//g, '\\/').replace(/\*\*/g, '.*').replace(/\*/g, '[^\\/]*') + const regex = new RegExp(`^${regexPattern}$`) + return regex.test(path) +} + +/** * 鍒ゆ柇url鏄惁鏄痟ttp鎴杊ttps * @returns {Boolean} * @param url diff --git a/src/utils/websocket.ts b/src/utils/websocket.ts index ade13ef..c9b394c 100644 --- a/src/utils/websocket.ts +++ b/src/utils/websocket.ts @@ -7,7 +7,7 @@ if (import.meta.env.VITE_APP_WEBSOCKET === 'false') { return; } - url = url + '?Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID + url = url + '?Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID; useWebSocket(url, { autoReconnect: { // 閲嶈繛鏈�澶ф鏁� @@ -16,14 +16,14 @@ delay: 1000, onFailed() { console.log('websocket閲嶈繛澶辫触'); - }, + } }, heartbeat: { - message: JSON.stringify({type: 'ping'}), + message: JSON.stringify({ type: 'ping' }), // 鍙戦�佸績璺崇殑闂撮殧 interval: 10000, // 鎺ユ敹鍒板績璺硆esponse鐨勮秴鏃舵椂闂� - pongTimeout: 2000, + pongTimeout: 2000 }, onConnected() { console.log('websocket宸茬粡杩炴帴'); diff --git a/src/views/demo/demo/index.vue b/src/views/demo/demo/index.vue index 523deff..da1bc16 100644 --- a/src/views/demo/demo/index.vue +++ b/src/views/demo/demo/index.vue @@ -45,7 +45,7 @@ <el-col :span="1.5"> <el-button v-hasPermi="['demo:demo:export']" type="warning" plain icon="Download" @click="handleExport">瀵煎嚭</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> diff --git a/src/views/demo/tree/index.vue b/src/views/demo/tree/index.vue index 921ddd9..566d071 100644 --- a/src/views/demo/tree/index.vue +++ b/src/views/demo/tree/index.vue @@ -25,7 +25,7 @@ <el-col :span="1.5"> <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">灞曞紑/鎶樺彔</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> <el-table diff --git a/src/views/index.vue b/src/views/index.vue index b67eb07..8e6b23d 100644 --- a/src/views/index.vue +++ b/src/views/index.vue @@ -33,7 +33,7 @@ * 閮ㄧ讲鏂瑰紡 Docker 瀹瑰櫒缂栨帓 涓�閿儴缃蹭笟鍔¢泦缇�<br /> * 鍥介檯鍖� SpringMessage Spring鏍囧噯鍥介檯鍖栨柟妗�<br /> </p> - <p><b>褰撳墠鐗堟湰:</b> <span>v5.2.3</span></p> + <p><b>褰撳墠鐗堟湰:</b> <span>v5.3.0-BETA</span></p> <p> <el-tag type="danger">¥鍏嶈垂寮�婧�</el-tag> </p> diff --git a/src/views/login.vue b/src/views/login.vue index db1fca6..cbc980c 100644 --- a/src/views/login.vue +++ b/src/views/login.vue @@ -1,56 +1,73 @@ <template> <div class="login"> <el-form ref="loginRef" :model="loginForm" :rules="loginRules" class="login-form"> - <h3 class="title">RuoYi-Vue-Plus澶氱鎴风鐞嗙郴缁�</h3> + <div class="title-box"> + <h3 class="title">RuoYi-Vue-Plus澶氱鎴风鐞嗙郴缁�</h3> + <lang-select /> + </div> <el-form-item v-if="tenantEnabled" prop="tenantId"> - <el-select v-model="loginForm.tenantId" filterable placeholder="璇烽�夋嫨/杈撳叆鍏徃鍚嶇О" style="width: 100%"> + <el-select v-model="loginForm.tenantId" filterable :placeholder="proxy.$t('login.selectPlaceholder')" style="width: 100%"> <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"></el-option> <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template> </el-select> </el-form-item> <el-form-item prop="username"> - <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" placeholder="璐﹀彿"> + <el-input v-model="loginForm.username" type="text" size="large" auto-complete="off" :placeholder="proxy.$t('login.username')"> <template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template> </el-input> </el-form-item> <el-form-item prop="password"> - <el-input v-model="loginForm.password" type="password" size="large" auto-complete="off" placeholder="瀵嗙爜" @keyup.enter="handleLogin"> + <el-input + v-model="loginForm.password" + type="password" + size="large" + auto-complete="off" + :placeholder="proxy.$t('login.password')" + @keyup.enter="handleLogin" + > <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template> </el-input> </el-form-item> <el-form-item v-if="captchaEnabled" prop="code"> - <el-input v-model="loginForm.code" size="large" auto-complete="off" placeholder="楠岃瘉鐮�" style="width: 63%" @keyup.enter="handleLogin"> + <el-input + v-model="loginForm.code" + size="large" + auto-complete="off" + :placeholder="proxy.$t('login.code')" + style="width: 63%" + @keyup.enter="handleLogin" + > <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template> </el-input> <div class="login-code"> <img :src="codeUrl" class="login-code-img" @click="getCode" /> </div> </el-form-item> - <el-checkbox v-model="loginForm.rememberMe" style="margin: 0 0 25px 0">璁颁綇瀵嗙爜</el-checkbox> + <el-checkbox v-model="loginForm.rememberMe" style="margin: 0 0 25px 0">{{ proxy.$t('login.rememberPassword') }}</el-checkbox> <el-form-item style="float: right"> - <el-button circle title="寰俊鐧诲綍" @click="doSocialLogin('wechat')"> + <el-button circle :title="proxy.$t('login.social.wechat')" @click="doSocialLogin('wechat')"> <svg-icon icon-class="wechat" /> </el-button> - <el-button circle title="MaxKey鐧诲綍" @click="doSocialLogin('maxkey')"> + <el-button circle :title="proxy.$t('login.social.maxkey')" @click="doSocialLogin('maxkey')"> <svg-icon icon-class="maxkey" /> </el-button> - <el-button circle title="TopIam鐧诲綍" @click="doSocialLogin('topiam')"> + <el-button circle :title="proxy.$t('login.social.topiam')" @click="doSocialLogin('topiam')"> <svg-icon icon-class="topiam" /> </el-button> - <el-button circle title="Gitee鐧诲綍" @click="doSocialLogin('gitee')"> + <el-button circle :title="proxy.$t('login.social.gitee')" @click="doSocialLogin('gitee')"> <svg-icon icon-class="gitee" /> </el-button> - <el-button circle title="Github鐧诲綍" @click="doSocialLogin('github')"> + <el-button circle :title="proxy.$t('login.social.github')" @click="doSocialLogin('github')"> <svg-icon icon-class="github" /> </el-button> </el-form-item> <el-form-item style="width: 100%"> <el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleLogin"> - <span v-if="!loading">鐧� 褰�</span> - <span v-else>鐧� 褰� 涓�...</span> + <span v-if="!loading">{{ proxy.$t('login.login') }}</span> + <span v-else>{{ proxy.$t('login.logging') }}</span> </el-button> <div v-if="register" style="float: right"> - <router-link class="link-type" :to="'/register'">绔嬪嵆娉ㄥ唽</router-link> + <router-link class="link-type" :to="'/register'">{{ proxy.$t('login.switchRegisterPage') }}</router-link> </div> </el-form-item> </el-form> @@ -68,9 +85,13 @@ import { LoginData, TenantVO } from '@/api/types'; import { to } from 'await-to-js'; import { HttpStatus } from '@/enums/RespEnum'; +import { useI18n } from 'vue-i18n'; + +const { proxy } = getCurrentInstance() as ComponentInternalInstance; const userStore = useUserStore(); const router = useRouter(); +const { t } = useI18n(); const loginForm = ref<LoginData>({ tenantId: '000000', @@ -82,10 +103,10 @@ } as LoginData); const loginRules: ElFormRules = { - tenantId: [{ required: true, trigger: 'blur', message: '璇疯緭鍏ユ偍鐨勭鎴风紪鍙�' }], - username: [{ required: true, trigger: 'blur', message: '璇疯緭鍏ユ偍鐨勮处鍙�' }], - password: [{ required: true, trigger: 'blur', message: '璇疯緭鍏ユ偍鐨勫瘑鐮�' }], - code: [{ required: true, trigger: 'change', message: '璇疯緭鍏ラ獙璇佺爜' }] + tenantId: [{ required: true, trigger: 'blur', message: t('login.rule.tenantId.required') }], + username: [{ required: true, trigger: 'blur', message: t('login.rule.username.required') }], + password: [{ required: true, trigger: 'blur', message: t('login.rule.password.required') }], + code: [{ required: true, trigger: 'change', message: t('login.rule.code.required') }] }; const codeUrl = ref(''); @@ -105,7 +126,7 @@ watch( () => router.currentRoute.value, (newRoute: any) => { - redirect.value = newRoute.query && decodeURIComponent(newRoute.query.redirect); + redirect.value = newRoute.query && newRoute.query.redirect && decodeURIComponent(newRoute.query.redirect); }, { immediate: true } ); @@ -176,7 +197,7 @@ * 鑾峰彇绉熸埛鍒楄〃 */ const initTenantList = async () => { - const { data } = await getTenantList(); + const { data } = await getTenantList(false); tenantEnabled.value = data.tenantEnabled === undefined ? true : data.tenantEnabled; if (tenantEnabled.value) { tenantList.value = data.voList; @@ -218,10 +239,19 @@ background-size: cover; } -.title { - margin: 0px auto 30px auto; - text-align: center; - color: #707070; +.title-box { + display: flex; + + .title { + margin: 0px auto 30px auto; + text-align: center; + color: #707070; + } + + :deep(.lang-select--style) { + line-height: 0; + color: #7483a3; + } } .login-form { diff --git a/src/views/monitor/logininfor/index.vue b/src/views/monitor/logininfor/index.vue index 4cc890d..d914544 100644 --- a/src/views/monitor/logininfor/index.vue +++ b/src/views/monitor/logininfor/index.vue @@ -54,7 +54,7 @@ <el-col :span="1.5"> <el-button v-hasPermi="['monitor:logininfor:export']" type="warning" plain icon="Download" @click="handleExport">瀵煎嚭</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> @@ -94,7 +94,7 @@ <el-table-column label="鎻忚堪" align="center" prop="msg" :show-overflow-tooltip="true" /> <el-table-column label="璁块棶鏃堕棿" align="center" prop="loginTime" sortable="custom" :sort-orders="['descending', 'ascending']" width="180"> <template #default="scope"> - <span>{{ parseTime(scope.row.loginTime) }}</span> + <span>{{ proxy.parseTime(scope.row.loginTime) }}</span> </template> </el-table-column> </el-table> diff --git a/src/views/monitor/online/index.vue b/src/views/monitor/online/index.vue index eb12364..7a58bb7 100644 --- a/src/views/monitor/online/index.vue +++ b/src/views/monitor/online/index.vue @@ -42,7 +42,7 @@ <el-table-column label="娴忚鍣�" align="center" prop="browser" :show-overflow-tooltip="true" /> <el-table-column label="鐧诲綍鏃堕棿" align="center" prop="loginTime" width="180"> <template #default="scope"> - <span>{{ parseTime(scope.row.loginTime) }}</span> + <span>{{ proxy.parseTime(scope.row.loginTime) }}</span> </template> </el-table-column> <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> diff --git a/src/views/monitor/operlog/index.vue b/src/views/monitor/operlog/index.vue index ed0d755..0c64af4 100644 --- a/src/views/monitor/operlog/index.vue +++ b/src/views/monitor/operlog/index.vue @@ -57,7 +57,7 @@ <el-col :span="1.5"> <el-button v-hasPermi="['monitor:operlog:export']" type="warning" plain icon="Download" @click="handleExport">瀵煎嚭</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> @@ -95,7 +95,7 @@ </el-table-column> <el-table-column label="鎿嶄綔鏃ユ湡" align="center" prop="operTime" width="180" sortable="custom" :sort-orders="['descending', 'ascending']"> <template #default="scope"> - <span>{{ parseTime(scope.row.operTime) }}</span> + <span>{{ proxy.parseTime(scope.row.operTime) }}</span> </template> </el-table-column> <el-table-column @@ -123,56 +123,14 @@ <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> </el-card> <!-- 鎿嶄綔鏃ュ織璇︾粏 --> - <el-dialog v-model="dialog.visible" title="鎿嶄綔鏃ュ織璇︾粏" width="700px" append-to-body> - <el-form :model="form" label-width="100px"> - <el-row> - <el-col :span="24"> - <el-form-item label="鐧诲綍淇℃伅锛�">{{ form.operName }} / {{ form.deptName }} / {{ form.operIp }} / {{ form.operLocation }}</el-form-item> - </el-col> - <el-col :span="12"> - <el-form-item label="璇锋眰淇℃伅锛�">{{ form.requestMethod }} {{ form.operUrl }}</el-form-item> - </el-col> - <el-col :span="12"> - <el-form-item label="鎿嶄綔妯″潡锛�">{{ form.title }} / {{ typeFormat(form) }}</el-form-item> - </el-col> - <el-col :span="24"> - <el-form-item label="鎿嶄綔鏂规硶锛�">{{ form.method }}</el-form-item> - </el-col> - <el-col :span="24"> - <el-form-item label="璇锋眰鍙傛暟锛�">{{ form.operParam }}</el-form-item> - </el-col> - <el-col :span="24"> - <el-form-item label="杩斿洖鍙傛暟锛�">{{ form.jsonResult }}</el-form-item> - </el-col> - <el-col :span="6"> - <el-form-item label="鎿嶄綔鐘舵�侊細"> - <div v-if="form.status === 0">姝e父</div> - <div v-else-if="form.status === 1">澶辫触</div> - </el-form-item> - </el-col> - <el-col :span="8"> - <el-form-item label="娑堣�楁椂闂达細">{{ form.costTime }}姣</el-form-item> - </el-col> - <el-col :span="10"> - <el-form-item label="鎿嶄綔鏃堕棿锛�">{{ parseTime(form.operTime) }}</el-form-item> - </el-col> - <el-col :span="24"> - <el-form-item v-if="form.status === 1" label="寮傚父淇℃伅锛�">{{ form.errorMsg }}</el-form-item> - </el-col> - </el-row> - </el-form> - <template #footer> - <div class="dialog-footer"> - <el-button @click="dialog.visible = false">鍏� 闂�</el-button> - </div> - </template> - </el-dialog> + <OperInfoDialog ref="operInfoDialogRef" /> </div> </template> <script setup name="Operlog" lang="ts"> import { list, delOperlog, cleanOperlog } from '@/api/monitor/operlog'; import { OperLogForm, OperLogQuery, OperLogVO } from '@/api/monitor/operlog/types'; +import OperInfoDialog from './oper-info-dialog.vue'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { sys_oper_type, sys_common_status } = toRefs<any>(proxy?.useDict('sys_oper_type', 'sys_common_status')); @@ -188,11 +146,6 @@ const operLogTableRef = ref<ElTableInstance>(); const queryFormRef = ref<ElFormInstance>(); - -const dialog = reactive<DialogOption>({ - visible: false, - title: '' -}); const data = reactive<PageData<OperLogForm, OperLogQuery>>({ form: { @@ -267,11 +220,13 @@ queryParams.value.isAsc = column.order; getList(); }; + +const operInfoDialogRef = ref<InstanceType<typeof OperInfoDialog>>(); /** 璇︾粏鎸夐挳鎿嶄綔 */ const handleView = (row: OperLogVO) => { - dialog.visible = true; - form.value = row; + operInfoDialogRef.value.openDialog(row); }; + /** 鍒犻櫎鎸夐挳鎿嶄綔 */ const handleDelete = async (row?: OperLogVO) => { const operIds = row?.operId || ids.value; diff --git a/src/views/monitor/operlog/oper-info-dialog.vue b/src/views/monitor/operlog/oper-info-dialog.vue new file mode 100644 index 0000000..66491e2 --- /dev/null +++ b/src/views/monitor/operlog/oper-info-dialog.vue @@ -0,0 +1,111 @@ +<template> + <el-dialog v-model="open" title="鎿嶄綔鏃ュ織璇︾粏" width="700px" append-to-body close-on-click-modal @closed="info = null"> + <el-descriptions v-if="info" :column="1" border> + <el-descriptions-item label="鎿嶄綔鐘舵��"> + <template #default> + <el-tag v-if="info.status === 0" type="success">姝e父</el-tag> + <el-tag v-else-if="info.status === 1" type="danger">澶辫触</el-tag> + </template> + </el-descriptions-item> + <el-descriptions-item label="鐧诲綍淇℃伅"> + <template #default> {{ info.operName }} / {{ info.deptName }} / {{ info.operIp }} / {{ info.operLocation }} </template> + </el-descriptions-item> + <el-descriptions-item label="璇锋眰淇℃伅"> + <template #default> {{ info.requestMethod }} {{ info.operUrl }} </template> + </el-descriptions-item> + <el-descriptions-item label="鎿嶄綔妯″潡"> + <template #default> {{ info.title }} / {{ typeFormat(info) }} </template> + </el-descriptions-item> + <el-descriptions-item label="鎿嶄綔鏂规硶"> + <template #default> + {{ info.method }} + </template> + </el-descriptions-item> + <el-descriptions-item label="璇锋眰鍙傛暟"> + <template #default> + <div class="max-h-300px overflow-y-auto"> + <VueJsonPretty :data="formatToJsonObject(info.operParam)" /> + </div> + </template> + </el-descriptions-item> + <el-descriptions-item label="杩斿洖鍙傛暟"> + <template #default> + <div class="max-h-300px overflow-y-auto"> + <VueJsonPretty :data="formatToJsonObject(info.jsonResult)" /> + </div> + </template> + </el-descriptions-item> + <el-descriptions-item label="娑堣�楁椂闂�"> + <template #default> + <span> {{ info.costTime }}ms </span> + </template> + </el-descriptions-item> + <el-descriptions-item label="鎿嶄綔鏃堕棿"> + <template #default> {{ proxy.parseTime(info.operTime) }}</template> + </el-descriptions-item> + <el-descriptions-item v-if="info.status === 1" label="寮傚父淇℃伅"> + <template #default> + <span class="text-danger"> {{ info.errorMsg }}</span> + </template> + </el-descriptions-item> + </el-descriptions> + </el-dialog> +</template> + +<script setup lang="ts"> +import type { OperLogForm } from '@/api/monitor/operlog/types'; +import VueJsonPretty from 'vue-json-pretty'; +import 'vue-json-pretty/lib/styles.css'; + +const open = ref(false); +const info = ref<OperLogForm | null>(null); +function openDialog(row: OperLogForm) { + info.value = row; + open.value = true; +} + +function closeDialog() { + open.value = false; +} + +defineExpose({ + openDialog, + closeDialog +}); + +/** + * json杞负瀵硅薄 + * @param data 鍘熷鏁版嵁 + */ +function formatToJsonObject(data: string) { + try { + return JSON.parse(data); + } catch (error) { + return data; + } +} + +/** + * 瀛楀吀淇℃伅 + */ +const { proxy } = getCurrentInstance() as ComponentInternalInstance; +const { sys_oper_type } = toRefs<any>(proxy?.useDict('sys_oper_type')); +const typeFormat = (row: OperLogForm) => { + return proxy?.selectDictLabel(sys_oper_type.value, row.businessType); +}; +</script> + +<style scoped> +/** +label瀹藉害鍥哄畾 +*/ +:deep(.el-descriptions__label) { + min-width: 100px; +} +/** +鏂囧瓧瓒呰繃 鎹㈣鏄剧ず +*/ +:deep(.el-descriptions__content) { + max-width: 300px; +} +</style> diff --git a/src/views/register.vue b/src/views/register.vue index c3d1930..f1d1e5a 100644 --- a/src/views/register.vue +++ b/src/views/register.vue @@ -1,20 +1,30 @@ <template> <div class="register"> <el-form ref="registerRef" :model="registerForm" :rules="registerRules" class="register-form"> - <h3 class="title">RuoYi-Vue-Plus澶氱鎴风鐞嗙郴缁�</h3> + <div class="title-box"> + <h3 class="title">RuoYi-Vue-Plus澶氱鎴风鐞嗙郴缁�</h3> + <lang-select /> + </div> <el-form-item v-if="tenantEnabled" prop="tenantId"> - <el-select v-model="registerForm.tenantId" filterable placeholder="璇烽�夋嫨/杈撳叆鍏徃鍚嶇О" style="width: 100%"> + <el-select v-model="registerForm.tenantId" filterable :placeholder="proxy.$t('register.selectPlaceholder')" style="width: 100%"> <el-option v-for="item in tenantList" :key="item.tenantId" :label="item.companyName" :value="item.tenantId"> </el-option> <template #prefix><svg-icon icon-class="company" class="el-input__icon input-icon" /></template> </el-select> </el-form-item> <el-form-item prop="username"> - <el-input v-model="registerForm.username" type="text" size="large" auto-complete="off" placeholder="璐﹀彿"> + <el-input v-model="registerForm.username" type="text" size="large" auto-complete="off" :placeholder="proxy.$t('register.username')"> <template #prefix><svg-icon icon-class="user" class="el-input__icon input-icon" /></template> </el-input> </el-form-item> <el-form-item prop="password"> - <el-input v-model="registerForm.password" type="password" size="large" auto-complete="off" placeholder="瀵嗙爜" @keyup.enter="handleRegister"> + <el-input + v-model="registerForm.password" + type="password" + size="large" + auto-complete="off" + :placeholder="proxy.$t('register.password')" + @keyup.enter="handleRegister" + > <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template> </el-input> </el-form-item> @@ -24,14 +34,21 @@ type="password" size="large" auto-complete="off" - placeholder="纭瀵嗙爜" + :placeholder="proxy.$t('register.confirmPassword')" @keyup.enter="handleRegister" > <template #prefix><svg-icon icon-class="password" class="el-input__icon input-icon" /></template> </el-input> </el-form-item> <el-form-item v-if="captchaEnabled" prop="code"> - <el-input v-model="registerForm.code" size="large" auto-complete="off" placeholder="楠岃瘉鐮�" style="width: 63%" @keyup.enter="handleRegister"> + <el-input + v-model="registerForm.code" + size="large" + auto-complete="off" + :placeholder="proxy.$t('register.code')" + style="width: 63%" + @keyup.enter="handleRegister" + > <template #prefix><svg-icon icon-class="validCode" class="el-input__icon input-icon" /></template> </el-input> <div class="register-code"> @@ -40,11 +57,11 @@ </el-form-item> <el-form-item style="width: 100%"> <el-button :loading="loading" size="large" type="primary" style="width: 100%" @click.prevent="handleRegister"> - <span v-if="!loading">娉� 鍐�</span> - <span v-else>娉� 鍐� 涓�...</span> + <span v-if="!loading">{{ proxy.$t('register.register') }}</span> + <span v-else>{{ proxy.$t('register.registering') }}</span> </el-button> <div style="float: right"> - <router-link class="link-type" :to="'/login'">浣跨敤宸叉湁璐︽埛鐧诲綍</router-link> + <router-link class="link-type" :to="'/login'">{{ proxy.$t('register.switchLoginPage') }}</router-link> </div> </el-form-item> </el-form> @@ -59,8 +76,13 @@ import { getCodeImg, register, getTenantList } from '@/api/login'; import { RegisterForm, TenantVO } from '@/api/types'; import { to } from 'await-to-js'; +import { useI18n } from 'vue-i18n'; + +const { proxy } = getCurrentInstance() as ComponentInternalInstance; const router = useRouter(); + +const { t } = useI18n(); const registerForm = ref<RegisterForm>({ tenantId: '', @@ -77,28 +99,28 @@ const equalToPassword = (rule: any, value: string, callback: any) => { if (registerForm.value.password !== value) { - callback(new Error('涓ゆ杈撳叆鐨勫瘑鐮佷笉涓�鑷�')); + callback(new Error(t('register.rule.confirmPassword.equalToPassword'))); } else { callback(); } }; const registerRules: ElFormRules = { - tenantId: [{ required: true, trigger: 'blur', message: '璇疯緭鍏ユ偍鐨勭鎴风紪鍙�' }], + tenantId: [{ required: true, trigger: 'blur', message: t('register.rule.tenantId.required') }], username: [ - { required: true, trigger: 'blur', message: '璇疯緭鍏ユ偍鐨勮处鍙�' }, - { min: 2, max: 20, message: '鐢ㄦ埛璐﹀彿闀垮害蹇呴』浠嬩簬 2 鍜� 20 涔嬮棿', trigger: 'blur' } + { required: true, trigger: 'blur', message: t('register.rule.username.required') }, + { min: 2, max: 20, message: t('register.rule.username.length', { min: 2, max: 20 }), trigger: 'blur' } ], password: [ - { required: true, trigger: 'blur', message: '璇疯緭鍏ユ偍鐨勫瘑鐮�' }, - { min: 5, max: 20, message: '鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿', trigger: 'blur' }, - { pattern: /^[^<>"'|\\]+$/, message: '涓嶈兘鍖呭惈闈炴硶瀛楃锛�< > " \' \\\ |', trigger: 'blur' } + { required: true, trigger: 'blur', message: t('register.rule.password.required') }, + { min: 5, max: 20, message: t('register.rule.password.length', { min: 5, max: 20 }), trigger: 'blur' }, + { pattern: /^[^<>"'|\\]+$/, message: t('register.rule.password.pattern', { strings: '< > " \' \\ |' }), trigger: 'blur' } ], confirmPassword: [ - { required: true, trigger: 'blur', message: '璇峰啀娆¤緭鍏ユ偍鐨勫瘑鐮�' }, + { required: true, trigger: 'blur', message: t('register.rule.confirmPassword.required') }, { required: true, validator: equalToPassword, trigger: 'blur' } ], - code: [{ required: true, trigger: 'change', message: '璇疯緭鍏ラ獙璇佺爜' }] + code: [{ required: true, trigger: 'change', message: t('register.rule.code.required') }] }; const codeUrl = ref(''); const loading = ref(false); @@ -114,7 +136,8 @@ const [err] = await to(register(registerForm.value)); if (!err) { const username = registerForm.value.username; - await ElMessageBox.alert("<font color='red'>鎭枩浣狅紝鎮ㄧ殑璐﹀彿 " + username + ' 娉ㄥ唽鎴愬姛锛�</font>', '绯荤粺鎻愮ず', { + await ElMessageBox.alert('<span style="color: red; ">' + t('register.registerSuccess', { username }) + '</font>', '绯荤粺鎻愮ず', { + app: undefined, dangerouslyUseHTMLString: true, type: 'success' }); @@ -140,7 +163,7 @@ }; const initTenantList = async () => { - const { data } = await getTenantList(); + const { data } = await getTenantList(false); tenantEnabled.value = data.tenantEnabled === undefined ? true : data.tenantEnabled; if (tenantEnabled.value) { tenantList.value = data.voList; @@ -166,10 +189,20 @@ background-size: cover; } -.title { - margin: 0 auto 30px auto; - text-align: center; - color: #707070; +.title-box { + display: flex; + + .title { + margin: 0px auto 30px auto; + text-align: center; + color: #707070; + } + + :deep(.lang-select--style) { + line-height: 0; + color: #7483a3; + } + } .register-form { diff --git a/src/views/system/client/index.vue b/src/views/system/client/index.vue index c05dcdc..37e8609 100644 --- a/src/views/system/client/index.vue +++ b/src/views/system/client/index.vue @@ -41,7 +41,7 @@ <el-col :span="1.5"> <el-button v-hasPermi="['system:client:export']" type="warning" plain icon="Download" @click="handleExport">瀵煎嚭</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> diff --git a/src/views/system/config/index.vue b/src/views/system/config/index.vue index 1b67d48..ddc0753 100644 --- a/src/views/system/config/index.vue +++ b/src/views/system/config/index.vue @@ -56,7 +56,7 @@ <el-col :span="1.5"> <el-button v-hasPermi="['system:config:remove']" type="danger" plain icon="Refresh" @click="handleRefreshCache">鍒锋柊缂撳瓨</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> @@ -74,7 +74,7 @@ <el-table-column label="澶囨敞" align="center" prop="remark" :show-overflow-tooltip="true" /> <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> <template #default="scope"> - <span>{{ parseTime(scope.row.createTime) }}</span> + <span>{{ proxy.parseTime(scope.row.createTime) }}</span> </template> </el-table-column> <el-table-column label="鎿嶄綔" align="center" width="150" class-name="small-padding fixed-width"> @@ -101,7 +101,7 @@ <el-input v-model="form.configKey" placeholder="璇疯緭鍏ュ弬鏁伴敭鍚�" /> </el-form-item> <el-form-item label="鍙傛暟閿��" prop="configValue"> - <el-input v-model="form.configValue" placeholder="璇疯緭鍏ュ弬鏁伴敭鍊�" /> + <el-input v-model="form.configValue" type="textarea" placeholder="璇疯緭鍏ュ弬鏁伴敭鍊�" /> </el-form-item> <el-form-item label="绯荤粺鍐呯疆" prop="configType"> <el-radio-group v-model="form.configType"> diff --git a/src/views/system/dept/index.vue b/src/views/system/dept/index.vue index 199a997..1f5facb 100644 --- a/src/views/system/dept/index.vue +++ b/src/views/system/dept/index.vue @@ -33,7 +33,7 @@ <el-col :span="1.5"> <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">灞曞紑/鎶樺彔</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> @@ -55,7 +55,7 @@ </el-table-column> <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="200"> <template #default="scope"> - <span>{{ parseTime(scope.row.createTime) }}</span> + <span>{{ proxy.parseTime(scope.row.createTime) }}</span> </template> </el-table-column> <el-table-column fixed="right" align="center" label="鎿嶄綔"> diff --git a/src/views/system/dict/data.vue b/src/views/system/dict/data.vue index 33c7fc8..3e9b0a1 100644 --- a/src/views/system/dict/data.vue +++ b/src/views/system/dict/data.vue @@ -40,7 +40,7 @@ <el-col :span="1.5"> <el-button type="warning" plain icon="Close" @click="handleClose">鍏抽棴</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> @@ -66,7 +66,7 @@ <el-table-column label="澶囨敞" align="center" prop="remark" :show-overflow-tooltip="true" /> <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> <template #default="scope"> - <span>{{ parseTime(scope.row.createTime) }}</span> + <span>{{ proxy.parseTime(scope.row.createTime) }}</span> </template> </el-table-column> <el-table-column label="鎿嶄綔" align="center" width="160" class-name="small-padding fixed-width"> diff --git a/src/views/system/dict/index.vue b/src/views/system/dict/index.vue index 4ad70d0..d30ad54 100644 --- a/src/views/system/dict/index.vue +++ b/src/views/system/dict/index.vue @@ -49,10 +49,7 @@ <el-col :span="1.5"> <el-button v-hasPermi="['system:dict:remove']" type="danger" plain icon="Refresh" @click="handleRefreshCache">鍒锋柊缂撳瓨</el-button> </el-col> - <el-col :span="1.5"> - <el-button v-if="userId === 1" type="success" plain icon="Refresh" @click="handleSyncTenantDict">鍚屾绉熸埛瀛楀吀</el-button> - </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> @@ -70,7 +67,7 @@ <el-table-column label="澶囨敞" align="center" prop="remark" :show-overflow-tooltip="true" /> <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> <template #default="scope"> - <span>{{ parseTime(scope.row.createTime) }}</span> + <span>{{ proxy.parseTime(scope.row.createTime) }}</span> </template> </el-table-column> <el-table-column label="鎿嶄綔" align="center" width="160" class-name="small-padding fixed-width"> @@ -112,15 +109,11 @@ <script setup name="Dict" lang="ts"> import useDictStore from '@/store/modules/dict'; -import useUserStore from "@/store/modules/user"; import { listType, getType, delType, addType, updateType, refreshCache } from '@/api/system/dict/type'; import { DictTypeForm, DictTypeQuery, DictTypeVO } from '@/api/system/dict/type/types'; -import { syncTenantDict } from "@/api/system/tenant"; const { proxy } = getCurrentInstance() as ComponentInternalInstance; -const userStore = useUserStore(); -const userId = ref(userStore.userId); const typeList = ref<DictTypeVO[]>([]); const loading = ref(true); const showSearch = ref(true); @@ -245,12 +238,6 @@ await refreshCache(); proxy?.$modal.msgSuccess('鍒锋柊鎴愬姛'); useDictStore().cleanDict(); -}; -/**鍚屾绉熸埛瀛楀吀*/ -const handleSyncTenantDict = async () => { - await proxy?.$modal.confirm('纭瑕佸悓姝ユ墍鏈夌鎴峰瓧鍏稿悧锛�'); - let res = await syncTenantDict(); - proxy?.$modal.msgSuccess(res.msg); }; onMounted(() => { diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue index cf5f0fc..05630f4 100644 --- a/src/views/system/menu/index.vue +++ b/src/views/system/menu/index.vue @@ -30,7 +30,7 @@ <el-col :span="1.5"> <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">灞曞紑/鎶樺彔</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> diff --git a/src/views/system/notice/index.vue b/src/views/system/notice/index.vue index 7d4bbe0..5d7d9ba 100644 --- a/src/views/system/notice/index.vue +++ b/src/views/system/notice/index.vue @@ -40,7 +40,7 @@ 鍒犻櫎 </el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> @@ -61,7 +61,7 @@ <el-table-column label="鍒涘缓鑰�" align="center" prop="createByName" width="100" /> <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="100"> <template #default="scope"> - <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span> + <span>{{ proxy.parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span> </template> </el-table-column> <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> diff --git a/src/views/system/oss/config.vue b/src/views/system/oss/config.vue index 41766f6..0563a02 100644 --- a/src/views/system/oss/config.vue +++ b/src/views/system/oss/config.vue @@ -41,7 +41,7 @@ 鍒犻櫎 </el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> @@ -159,8 +159,8 @@ // 鍒楁樉闅愪俊鎭� const columns = ref<FieldOption[]>([ - { key: 0, label: `涓诲缓`, visible: true }, - { key: 1, label: `閰嶇疆key`, visible: false }, + { key: 0, label: `涓诲缓`, visible: false }, + { key: 1, label: `閰嶇疆key`, visible: true }, { key: 2, label: `璁块棶绔欑偣`, visible: true }, { key: 3, label: `鑷畾涔夊煙鍚峘, visible: true }, { key: 4, label: `妗跺悕绉癭, visible: true }, diff --git a/src/views/system/oss/index.vue b/src/views/system/oss/index.vue index d057c23..f76dbab 100644 --- a/src/views/system/oss/index.vue +++ b/src/views/system/oss/index.vue @@ -62,7 +62,7 @@ <el-col :span="1.5"> <el-button v-hasPermi="['system:ossConfig:list']" type="info" plain icon="Operation" @click="handleOssConfig">閰嶇疆绠$悊</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> @@ -93,7 +93,7 @@ </el-table-column> <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180" sortable="custom"> <template #default="scope"> - <span>{{ parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span> + <span>{{ proxy.parseTime(scope.row.createTime, '{y}-{m}-{d}') }}</span> </template> </el-table-column> <el-table-column label="涓婁紶浜�" align="center" prop="createByName" /> diff --git a/src/views/system/post/index.vue b/src/views/system/post/index.vue index 49b735b..4aa4e3a 100644 --- a/src/views/system/post/index.vue +++ b/src/views/system/post/index.vue @@ -81,7 +81,7 @@ <el-col :span="1.5"> <el-button v-hasPermi="['system:post:export']" type="warning" plain icon="Download" @click="handleExport">瀵煎嚭</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> <el-table v-loading="loading" :data="postList" @selection-change="handleSelectionChange"> @@ -99,7 +99,7 @@ </el-table-column> <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> <template #default="scope"> - <span>{{ parseTime(scope.row.createTime) }}</span> + <span>{{ proxy.parseTime(scope.row.createTime) }}</span> </template> </el-table-column> <el-table-column label="鎿嶄綔" width="180" align="center" class-name="small-padding fixed-width"> diff --git a/src/views/system/role/authUser.vue b/src/views/system/role/authUser.vue index 6394804..0af7b6d 100644 --- a/src/views/system/role/authUser.vue +++ b/src/views/system/role/authUser.vue @@ -30,7 +30,7 @@ <el-col :span="1.5"> <el-button type="warning" plain icon="Close" @click="handleClose">鍏抽棴</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" :search="true" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" :search="true" @query-table="getList"></right-toolbar> </el-row> </template> <el-table v-loading="loading" :data="userList" @selection-change="handleSelectionChange"> diff --git a/src/views/system/role/index.vue b/src/views/system/role/index.vue index f2299d7..fc42cd5 100644 --- a/src/views/system/role/index.vue +++ b/src/views/system/role/index.vue @@ -51,7 +51,7 @@ <el-col :span="1.5"> <el-button v-hasPermi="['system:role:export']" type="warning" plain icon="Download" @click="handleExport">瀵煎嚭</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> @@ -68,7 +68,7 @@ </el-table-column> <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime"> <template #default="scope"> - <span>{{ parseTime(scope.row.createTime) }}</span> + <span>{{ proxy.parseTime(scope.row.createTime) }}</span> </template> </el-table-column> @@ -223,7 +223,8 @@ { value: '2', label: '鑷畾鏁版嵁鏉冮檺' }, { value: '3', label: '鏈儴闂ㄦ暟鎹潈闄�' }, { value: '4', label: '鏈儴闂ㄥ強浠ヤ笅鏁版嵁鏉冮檺' }, - { value: '5', label: '浠呮湰浜烘暟鎹潈闄�' } + { value: '5', label: '浠呮湰浜烘暟鎹潈闄�' }, + { value: '6', label: '閮ㄩ棬鍙婁互涓嬫垨鏈汉鏁版嵁鏉冮檺' } ]); const queryFormRef = ref<ElFormInstance>(); diff --git a/src/views/system/role/selectUser.vue b/src/views/system/role/selectUser.vue index ec7a257..e55120a 100644 --- a/src/views/system/role/selectUser.vue +++ b/src/views/system/role/selectUser.vue @@ -27,7 +27,7 @@ </el-table-column> <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> <template #default="scope"> - <span>{{ parseTime(scope.row.createTime) }}</span> + <span>{{ proxy.parseTime(scope.row.createTime) }}</span> </template> </el-table-column> </el-table> diff --git a/src/views/system/tenant/index.vue b/src/views/system/tenant/index.vue index fabe18d..df97b64 100644 --- a/src/views/system/tenant/index.vue +++ b/src/views/system/tenant/index.vue @@ -44,7 +44,10 @@ <el-col :span="1.5"> <el-button v-hasPermi="['system:tenant:export']" type="warning" plain icon="Download" @click="handleExport">瀵煎嚭</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <el-col :span="1.5"> + <el-button v-if="userId === 1" type="success" plain icon="Refresh" @click="handleSyncTenantDict">鍚屾绉熸埛瀛楀吀</el-button> + </el-col> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> @@ -58,7 +61,7 @@ <el-table-column label="绀句細淇$敤浠g爜" align="center" prop="licenseNumber" /> <el-table-column label="杩囨湡鏃堕棿" align="center" prop="expireTime" width="180"> <template #default="scope"> - <span>{{ parseTime(scope.row.expireTime, '{y}-{m}-{d}') }}</span> + <span>{{ proxy.parseTime(scope.row.expireTime, '{y}-{m}-{d}') }}</span> </template> </el-table-column> <el-table-column label="绉熸埛鐘舵��" align="center" prop="status"> @@ -141,13 +144,25 @@ </template> <script setup name="Tenant" lang="ts"> -import { listTenant, getTenant, delTenant, addTenant, updateTenant, changeTenantStatus, syncTenantPackage } from '@/api/system/tenant'; +import { + listTenant, + getTenant, + delTenant, + addTenant, + updateTenant, + changeTenantStatus, + syncTenantPackage, + syncTenantDict +} from '@/api/system/tenant'; import { selectTenantPackage } from '@/api/system/tenantPackage'; +import useUserStore from '@/store/modules/user'; import { TenantForm, TenantQuery, TenantVO } from '@/api/system/tenant/types'; import { TenantPkgVO } from '@/api/system/tenantPackage/types'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; +const userStore = useUserStore(); +const userId = ref(userStore.userId); const tenantList = ref<TenantVO[]>([]); const packageList = ref<TenantPkgVO[]>([]); const buttonLoading = ref(false); @@ -343,6 +358,13 @@ ); }; +/**鍚屾绉熸埛瀛楀吀*/ +const handleSyncTenantDict = async () => { + await proxy?.$modal.confirm('纭瑕佸悓姝ユ墍鏈夌鎴峰瓧鍏稿悧锛�'); + let res = await syncTenantDict(); + proxy?.$modal.msgSuccess(res.msg); +}; + onMounted(() => { getList(); }); diff --git a/src/views/system/tenantPackage/index.vue b/src/views/system/tenantPackage/index.vue index 05a0b41..f97bb35 100644 --- a/src/views/system/tenantPackage/index.vue +++ b/src/views/system/tenantPackage/index.vue @@ -35,7 +35,7 @@ <el-col :span="1.5"> <el-button v-hasPermi="['system:tenantPackage:export']" type="warning" plain icon="Download" @click="handleExport">瀵煎嚭 </el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> diff --git a/src/views/system/user/authRole.vue b/src/views/system/user/authRole.vue index fe119ae..fe2e974 100644 --- a/src/views/system/user/authRole.vue +++ b/src/views/system/user/authRole.vue @@ -39,7 +39,7 @@ <el-table-column label="鏉冮檺瀛楃" align="center" prop="roleKey" /> <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180"> <template #default="scope"> - <span>{{ parseTime(scope.row.createTime) }}</span> + <span>{{ proxy.parseTime(scope.row.createTime) }}</span> </template> </el-table-column> </el-table> @@ -80,7 +80,7 @@ /** 鍗曞嚮閫変腑琛屾暟鎹� */ const clickRow = (row: RoleVO) => { - row.flag = !row.flag + row.flag = !row.flag; tableRef.value?.toggleRowSelection(row, row.flag); }; /** 澶氶�夋閫変腑鏁版嵁 */ diff --git a/src/views/system/user/index.vue b/src/views/system/user/index.vue index 46bffd2..430c55a 100644 --- a/src/views/system/user/index.vue +++ b/src/views/system/user/index.vue @@ -63,12 +63,12 @@ <el-button v-has-permi="['system:user:add']" type="primary" plain icon="Plus" @click="handleAdd()">鏂板</el-button> </el-col> <el-col :span="1.5"> - <el-button v-has-permi="['system:user:add']" type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()"> + <el-button v-has-permi="['system:user:edit']" type="success" plain :disabled="single" icon="Edit" @click="handleUpdate()"> 淇敼 </el-button> </el-col> <el-col :span="1.5"> - <el-button v-has-permi="['system:user:delete']" type="danger" plain :disabled="multiple" icon="Delete" @click="handleDelete()"> + <el-button v-has-permi="['system:user:remove']" type="danger" plain :disabled="multiple" icon="Delete" @click="handleDelete()"> 鍒犻櫎 </el-button> </el-col> @@ -81,13 +81,13 @@ <template #dropdown> <el-dropdown-menu> <el-dropdown-item icon="Download" @click="importTemplate">涓嬭浇妯℃澘</el-dropdown-item> - <el-dropdown-item icon="Top" @click="handleImport"> 瀵煎叆鏁版嵁</el-dropdown-item> - <el-dropdown-item icon="Download" @click="handleExport"> 瀵煎嚭鏁版嵁</el-dropdown-item> + <el-dropdown-item v-has-permi="['system:user:import']" icon="Top" @click="handleImport">瀵煎叆鏁版嵁</el-dropdown-item> + <el-dropdown-item v-has-permi="['system:user:export']" icon="Download" @click="handleExport">瀵煎嚭鏁版嵁</el-dropdown-item> </el-dropdown-menu> </template> </el-dropdown> </el-col> - <right-toolbar v-model:showSearch="showSearch" :columns="columns" :search="true" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" :columns="columns" :search="true" @query-table="getList"></right-toolbar> </el-row> </template> @@ -154,7 +154,7 @@ <el-form-item label="褰掑睘閮ㄩ棬" prop="deptId"> <el-tree-select v-model="form.deptId" - :data="deptOptions" + :data="enabledDeptOptions" :props="{ value: 'id', label: 'label', children: 'children' }" value-key="id" placeholder="璇烽�夋嫨褰掑睘閮ㄩ棬" @@ -287,7 +287,7 @@ <script setup name="User" lang="ts"> import api from '@/api/system/user'; import { UserForm, UserQuery, UserVO } from '@/api/system/user/types'; -import { DeptVO } from '@/api/system/dept/types'; +import {DeptTreeVO, DeptVO} from '@/api/system/dept/types'; import { RoleVO } from '@/api/system/role/types'; import { PostQuery, PostVO } from '@/api/system/post/types'; import { treeselect } from '@/api/system/dept'; @@ -307,7 +307,8 @@ const total = ref(0); const dateRange = ref<[DateModelType, DateModelType]>(['', '']); const deptName = ref(''); -const deptOptions = ref<DeptVO[]>([]); +const deptOptions = ref<DeptTreeVO[]>([]); +const enabledDeptOptions = ref<DeptTreeVO[]>([]); const initPassword = ref<string>(''); const postOptions = ref<PostVO[]>([]); const roleOptions = ref<RoleVO[]>([]); @@ -393,7 +394,7 @@ message: '鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿', trigger: 'blur' }, - { pattern: /^[^<>"'|\\]+$/, message: '涓嶈兘鍖呭惈闈炴硶瀛楃锛�< > " \' \\\ |', trigger: 'blur' } + { pattern: /^[^<>"'|\\]+$/, message: '涓嶈兘鍖呭惈闈炴硶瀛楃锛�< > " \' \\ |', trigger: 'blur' } ], email: [ { @@ -431,12 +432,6 @@ } ); -/** 鏌ヨ閮ㄩ棬涓嬫媺鏍戠粨鏋� */ -const getTreeSelect = async () => { - const res = await api.deptTreeSelect(); - deptOptions.value = res.data; -}; - /** 鏌ヨ鐢ㄦ埛鍒楄〃 */ const getList = async () => { loading.value = true; @@ -444,6 +439,26 @@ loading.value = false; userList.value = res.rows; total.value = res.total; +}; + +/** 鏌ヨ閮ㄩ棬涓嬫媺鏍戠粨鏋� */ +const getDeptTree = async () => { + const res = await api.deptTreeSelect(); + deptOptions.value = res.data; + enabledDeptOptions.value = filterDisabledDept(res.data); +}; + +/** 杩囨护绂佺敤鐨勯儴闂� */ +const filterDisabledDept = (deptList: DeptTreeVO[]) => { + return deptList.filter(dept => { + if (dept.disabled) { + return false; + } + if (dept.children && dept.children.length) { + dept.children = filterDisabledDept(dept.children); + } + return true; + }); }; /** 鑺傜偣鍗曞嚮浜嬩欢 */ @@ -506,7 +521,7 @@ inputErrorMessage: '鐢ㄦ埛瀵嗙爜闀垮害蹇呴』浠嬩簬 5 鍜� 20 涔嬮棿', inputValidator: (value) => { if (/<|>|"|'|\||\\/.test(value)) { - return '涓嶈兘鍖呭惈闈炴硶瀛楃锛�< > " \' \\\ |'; + return '涓嶈兘鍖呭惈闈炴硶瀛楃锛�< > " \' \\ |'; } } }) @@ -564,15 +579,6 @@ uploadRef.value?.submit(); } -/** 鍒濆鍖栭儴闂ㄦ暟鎹� */ -const initTreeData = async () => { - // 鍒ゆ柇閮ㄩ棬鐨勬暟鎹槸鍚﹀瓨鍦紝瀛樺湪涓嶈幏鍙栵紝涓嶅瓨鍦ㄥ垯鑾峰彇 - if (deptOptions.value === undefined) { - const { data } = await treeselect(); - deptOptions.value = data; - } -}; - /** 閲嶇疆鎿嶄綔琛ㄥ崟 */ const reset = () => { form.value = { ...initFormData }; @@ -590,7 +596,6 @@ const { data } = await api.getUser(); dialog.visible = true; dialog.title = '鏂板鐢ㄦ埛'; - await initTreeData(); postOptions.value = data.posts; roleOptions.value = data.roles; form.value.password = initPassword.value.toString(); @@ -603,7 +608,6 @@ const { data } = await api.getUser(userId); dialog.visible = true; dialog.title = '淇敼鐢ㄦ埛'; - await initTreeData(); Object.assign(form.value, data.user); postOptions.value = data.posts; roleOptions.value = data.roles; @@ -643,7 +647,7 @@ form.value.status = '1'; }; onMounted(() => { - getTreeSelect(); // 鍒濆鍖栭儴闂ㄦ暟鎹� + getDeptTree(); // 鍒濆鍖栭儴闂ㄦ暟鎹� getList(); // 鍒濆鍖栧垪琛ㄦ暟鎹� proxy?.getConfigKey('sys.user.initPassword').then((response) => { initPassword.value = response.data; diff --git a/src/views/system/user/profile/onlineDevice.vue b/src/views/system/user/profile/onlineDevice.vue index bd7c822..7634b06 100644 --- a/src/views/system/user/profile/onlineDevice.vue +++ b/src/views/system/user/profile/onlineDevice.vue @@ -12,7 +12,7 @@ <el-table-column label="娴忚鍣�" align="center" prop="browser" :show-overflow-tooltip="true" /> <el-table-column label="鐧诲綍鏃堕棿" align="center" prop="loginTime" width="180"> <template #default="scope"> - <span>{{ parseTime(scope.row.loginTime) }}</span> + <span>{{ proxy.parseTime(scope.row.loginTime) }}</span> </template> </el-table-column> <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> diff --git a/src/views/system/user/profile/resetPwd.vue b/src/views/system/user/profile/resetPwd.vue index aae5ef8..3ca5ee9 100644 --- a/src/views/system/user/profile/resetPwd.vue +++ b/src/views/system/user/profile/resetPwd.vue @@ -45,7 +45,7 @@ message: '闀垮害鍦� 6 鍒� 20 涓瓧绗�', trigger: 'blur' }, - { pattern: /^[^<>"'|\\]+$/, message: '涓嶈兘鍖呭惈闈炴硶瀛楃锛�< > " \' \\\ |', trigger: 'blur' } + { pattern: /^[^<>"'|\\]+$/, message: '涓嶈兘鍖呭惈闈炴硶瀛楃锛�< > " \' \\ |', trigger: 'blur' } ], confirmPassword: [ { required: true, message: '纭瀵嗙爜涓嶈兘涓虹┖', trigger: 'blur' }, diff --git a/src/views/tool/gen/importTable.vue b/src/views/tool/gen/importTable.vue index 50ec0ee..f6e75cc 100644 --- a/src/views/tool/gen/importTable.vue +++ b/src/views/tool/gen/importTable.vue @@ -63,14 +63,18 @@ /** 鏌ヨ鍙傛暟鍒楄〃 */ const show = (dataName: string) => { - getDataNameList(); - if (dataName) { - queryParams.dataName = dataName; - } else { - queryParams.dataName = 'master'; - } - getList(); - visible.value = true; + getDataNames().then((res) => { + if (res.code == 200) { + dataNameList.value = res.data; + if (dataName) { + queryParams.dataName = dataName; + } else { + queryParams.dataName = dataNameList.value[0]; + } + getList(); + visible.value = true; + } + }); }; /** 鍗曞嚮閫夋嫨琛� */ const clickRow = (row: DbTableVO) => { @@ -110,11 +114,6 @@ visible.value = false; emit('ok'); } -}; -/** 鏌ヨ澶氭暟鎹簮鍚嶇О */ -const getDataNameList = async () => { - const res = await getDataNames(); - dataNameList.value = res.data; }; defineExpose({ diff --git a/src/views/tool/gen/index.vue b/src/views/tool/gen/index.vue index 2618a20..b4df31b 100644 --- a/src/views/tool/gen/index.vue +++ b/src/views/tool/gen/index.vue @@ -52,7 +52,7 @@ 鍒犻櫎 </el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> @@ -113,8 +113,8 @@ </template> <script setup name="Gen" lang="ts"> -import { listTable, previewTable, delTable, genCode, synchDb, getDataNames } from '@/api/tool/gen'; -import { TableQuery, TableVO } from '@/api/tool/gen/types'; +import {delTable, genCode, getDataNames, listTable, previewTable, synchDb} from '@/api/tool/gen'; +import {TableQuery, TableVO} from '@/api/tool/gen/types'; import router from '@/router'; import ImportTable from './importTable.vue'; @@ -153,17 +153,6 @@ const dialog = reactive<DialogOption>({ visible: false, title: '浠g爜棰勮' -}); - -onActivated(() => { - const time = route.query.t; - if (time != null && time != uniqueId.value) { - uniqueId.value = time as string; - queryParams.value.pageNum = Number(route.query.pageNum); - dateRange.value = ['', '']; - queryFormRef.value?.resetFields(); - getList(); - } }); /** 鏌ヨ澶氭暟鎹簮鍚嶇О */ @@ -248,6 +237,13 @@ }; onMounted(() => { + const time = route.query.t; + if (time != null && time != uniqueId.value) { + uniqueId.value = time as string; + queryParams.value.pageNum = Number(route.query.pageNum); + dateRange.value = ['', '']; + queryFormRef.value?.resetFields(); + } getList(); getDataNameList(); }); diff --git a/src/views/workflow/category/index.vue b/src/views/workflow/category/index.vue index fd3bfc5..d3e87ea 100644 --- a/src/views/workflow/category/index.vue +++ b/src/views/workflow/category/index.vue @@ -6,9 +6,6 @@ <el-form-item label="鍒嗙被鍚嶇О" prop="categoryName"> <el-input v-model="queryParams.categoryName" placeholder="璇疯緭鍏ュ垎绫诲悕绉�" clearable @keyup.enter="handleQuery" /> </el-form-item> - <el-form-item label="鍒嗙被缂栫爜" prop="categoryCode"> - <el-input v-model="queryParams.categoryCode" placeholder="璇疯緭鍏ュ垎绫荤紪鐮�" clearable @keyup.enter="handleQuery" /> - </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button> <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button> @@ -21,64 +18,66 @@ <template #header> <el-row :gutter="10" class="mb8"> <el-col :span="1.5"> - <el-button v-hasPermi="['workflow:category:add']" type="primary" plain icon="Plus" @click="handleAdd()">鏂板</el-button> + <el-button type="primary" plain icon="Plus" @click="handleAdd()" v-hasPermi="['workflow:category:add']">鏂板</el-button> </el-col> <el-col :span="1.5"> <el-button type="info" plain icon="Sort" @click="handleToggleExpandAll">灞曞紑/鎶樺彔</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar> </el-row> </template> <el-table ref="categoryTableRef" v-loading="loading" :data="categoryList" - row-key="id" + row-key="categoryId" :default-expand-all="isExpandAll" :tree-props="{ children: 'children', hasChildren: 'hasChildren' }" > - <el-table-column label="鍒嗙被鍚嶇О" prop="categoryName" /> - <el-table-column label="鍒嗙被缂栫爜" align="center" prop="categoryCode" /> - <el-table-column label="鎺掑簭" align="center" prop="sortNum" /> - <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <el-table-column label="鍒嗙被鍚嶇О" prop="categoryName" width="260"/> + <el-table-column label="鏄剧ず椤哄簭" align="center" prop="orderNum" width="200" /> + <el-table-column label="鍒涘缓鏃堕棿" align="center" prop="createTime" width="180" /> + <el-table-column label="鎿嶄綔" fixed="right" align="center" class-name="small-padding fixed-width"> <template #default="scope"> <el-tooltip content="淇敼" placement="top"> - <el-button v-hasPermi="['workflow:category:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)" /> + <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['workflow:category:edit']" /> </el-tooltip> <el-tooltip content="鏂板" placement="top"> - <el-button v-hasPermi="['workflow:category:add']" link type="primary" icon="Plus" @click="handleAdd(scope.row)" /> + <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['workflow:category:add']" /> </el-tooltip> <el-tooltip content="鍒犻櫎" placement="top"> - <el-button v-hasPermi="['workflow:category:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)" /> + <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['workflow:category:remove']" /> </el-tooltip> </template> </el-table-column> </el-table> </el-card> - <!-- 娣诲姞鎴栦慨鏀规祦绋嬪垎绫诲璇濇 --> - <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> - <el-form ref="categoryFormRef" v-loading="loading" :model="form" :rules="rules" label-width="80px"> - <el-form-item label="鐖剁骇鍒嗙被" prop="parentId"> + <el-dialog :title="dialog.title" v-model="dialog.visible" width="500px" append-to-body> + <el-form ref="categoryFormRef" :model="form" :rules="rules" label-width="80px"> + <el-form-item label="涓婄骇鍒嗙被" prop="parentId"> <el-tree-select v-model="form.parentId" :data="categoryOptions" - :props="{ value: 'id', label: 'categoryName', children: 'children' }" - value-key="id" - placeholder="璇烽�夋嫨鐖剁骇id" + :props="{ value: 'categoryId', label: 'categoryName', children: 'children' }" + value-key="categoryId" + placeholder="璇烽�夋嫨涓婄骇鍒嗙被" check-strictly /> </el-form-item> - <el-form-item label="鍒嗙被鍚嶇О" prop="categoryName"> - <el-input v-model="form.categoryName" placeholder="璇疯緭鍏ュ垎绫诲悕绉�" /> - </el-form-item> - <el-form-item label="鍒嗙被缂栫爜" prop="categoryCode"> - <el-input v-model="form.categoryCode" placeholder="璇疯緭鍏ュ垎绫荤紪鐮�" /> - </el-form-item> - <el-form-item label="鎺掑簭" prop="sortNum"> - <el-input-number v-model="form.sortNum" placeholder="璇疯緭鍏ユ帓搴�" controls-position="right" :min="0" /> - </el-form-item> + <el-row :gutter="20"> + <el-col :span="12"> + <el-form-item label="鍒嗙被鍚嶇О" prop="categoryName"> + <el-input v-model="form.categoryName" placeholder="璇疯緭鍏ュ垎绫诲悕绉�" /> + </el-form-item> + </el-col> + <el-col :span="12"> + <el-form-item label="鎺掑簭" prop="orderNum"> + <el-input-number v-model="form.orderNum" controls-position="right" :min="0" /> + </el-form-item> + </el-col> + </el-row> </el-form> - <template #footer> + <template #footer> <div class="dialog-footer"> <el-button :loading="buttonLoading" type="primary" @click="submitForm">纭� 瀹�</el-button> <el-button @click="cancel">鍙� 娑�</el-button> @@ -89,16 +88,17 @@ </template> <script setup name="Category" lang="ts"> -import { listCategory, getCategory, delCategory, addCategory, updateCategory } from '@/api/workflow/category'; +import { listCategory, getCategory, delCategory, addCategory, updateCategory } from "@/api/workflow/category"; import { CategoryVO, CategoryQuery, CategoryForm } from '@/api/workflow/category/types'; type CategoryOption = { - id: number; + categoryId: number; categoryName: string; children?: CategoryOption[]; -}; +} -const { proxy } = getCurrentInstance() as ComponentInternalInstance; +const { proxy } = getCurrentInstance() as ComponentInternalInstance;; + const categoryList = ref<CategoryVO[]>([]); const categoryOptions = ref<CategoryOption[]>([]); @@ -109,34 +109,32 @@ const queryFormRef = ref<ElFormInstance>(); const categoryFormRef = ref<ElFormInstance>(); -const categoryTableRef = ref<ElTableInstance>(); +const categoryTableRef = ref<ElTableInstance>() const dialog = reactive<DialogOption>({ visible: false, title: '' }); + const initFormData: CategoryForm = { - id: undefined, - categoryName: undefined, - categoryCode: undefined, + categoryId: undefined, + categoryName: "", parentId: undefined, - sortNum: 0 -}; + orderNum: 0, +} const data = reactive<PageData<CategoryForm, CategoryQuery>>({ - form: { ...initFormData }, + form: {...initFormData}, queryParams: { - pageNum: 1, - pageSize: 10, categoryName: undefined, - categoryCode: undefined }, rules: { - id: [{ required: true, message: '涓婚敭涓嶈兘涓虹┖', trigger: 'blur' }], - categoryName: [{ required: true, message: '鍒嗙被鍚嶇О涓嶈兘涓虹┖', trigger: 'blur' }], - categoryCode: [{ required: true, message: '鍒嗙被缂栫爜涓嶈兘涓虹┖', trigger: 'blur' }], - parentId: [{ required: true, message: '鐖剁骇id涓嶈兘涓虹┖', trigger: 'blur' }] + categoryId: [ + { required: true, message: "娴佺▼鍒嗙被ID涓嶈兘涓虹┖", trigger: "blur" } + ], + parentId: [{ required: true, message: "璇烽�夋嫨涓婄骇鍒嗙被", trigger: "change" }], + categoryName: [{ required: true, message: "璇疯緭鍏ュ垎绫诲悕绉�", trigger: "blur" }] } }); @@ -146,116 +144,112 @@ const getList = async () => { loading.value = true; const res = await listCategory(queryParams.value); - const data = proxy?.handleTree<CategoryVO>(res.data, 'id', 'parentId'); + const data = proxy?.handleTree<CategoryVO>(res.data, "categoryId", "parentId"); if (data) { categoryList.value = data; loading.value = false; } -}; +} /** 鏌ヨ娴佺▼鍒嗙被涓嬫媺鏍戠粨鏋� */ const getTreeselect = async () => { const res = await listCategory(); categoryOptions.value = []; - const data: CategoryOption = { id: 0, categoryName: '椤剁骇鑺傜偣', children: [] }; - data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId'); - categoryOptions.value.push(data); + // 澶勭悊鏍戝舰鏁版嵁 + const data = proxy?.handleTree<CategoryOption>(res.data, "categoryId", "parentId"); + if (data) { + categoryOptions.value = data; // 灏嗗鐞嗗悗鐨勬爲褰㈡暟鎹祴鍊� + } }; // 鍙栨秷鎸夐挳 const cancel = () => { reset(); dialog.visible = false; -}; +} // 琛ㄥ崟閲嶇疆 const reset = () => { - form.value = { ...initFormData }; + form.value = {...initFormData} categoryFormRef.value?.resetFields(); -}; +} /** 鎼滅储鎸夐挳鎿嶄綔 */ const handleQuery = () => { getList(); -}; +} /** 閲嶇疆鎸夐挳鎿嶄綔 */ const resetQuery = () => { queryFormRef.value?.resetFields(); handleQuery(); -}; +} /** 鏂板鎸夐挳鎿嶄綔 */ const handleAdd = (row?: CategoryVO) => { + reset(); + getTreeselect(); + if (row?.categoryId) { + form.value.parentId = row.categoryId; + } else { + form.value.parentId = undefined; + } dialog.visible = true; - dialog.title = '娣诲姞娴佺▼鍒嗙被'; - nextTick(() => { - reset(); - getTreeselect(); - if (row != null && row.id) { - form.value.parentId = row.id; - } else { - form.value.parentId = 0; - } - }); -}; + dialog.title = "娣诲姞娴佺▼鍒嗙被"; +} /** 灞曞紑/鎶樺彔鎿嶄綔 */ const handleToggleExpandAll = () => { isExpandAll.value = !isExpandAll.value; - toggleExpandAll(categoryList.value, isExpandAll.value); -}; + toggleExpandAll(categoryList.value, isExpandAll.value) +} /** 灞曞紑/鎶樺彔鎿嶄綔 */ const toggleExpandAll = (data: CategoryVO[], status: boolean) => { data.forEach((item) => { - categoryTableRef.value?.toggleRowExpansion(item, status); - if (item.children && item.children.length > 0) toggleExpandAll(item.children, status); - }); -}; + categoryTableRef.value?.toggleRowExpansion(item, status) + if (item.children && item.children.length > 0) toggleExpandAll(item.children, status) + }) +} /** 淇敼鎸夐挳鎿嶄綔 */ -const handleUpdate = (row: CategoryVO) => { - loading.value = true; +const handleUpdate = async (row: CategoryVO) => { + reset(); + await getTreeselect(); + if (row != null) { + form.value.parentId = row.parentId; + } + const res = await getCategory(row.categoryId); + Object.assign(form.value, res.data); dialog.visible = true; - dialog.title = '淇敼娴佺▼鍒嗙被'; - nextTick(async () => { - reset(); - await getTreeselect(); - if (row != null) { - form.value.parentId = row.id; - } - const res = await getCategory(row.id); - loading.value = false; - Object.assign(form.value, res.data); - }); -}; + dialog.title = "淇敼娴佺▼鍒嗙被"; +} /** 鎻愪氦鎸夐挳 */ const submitForm = () => { - categoryFormRef.value.validate(async (valid: boolean) => { + categoryFormRef.value?.validate(async (valid: boolean) => { if (valid) { buttonLoading.value = true; - if (form.value.id) { - await updateCategory(form.value).finally(() => (buttonLoading.value = false)); + if (form.value.categoryId) { + await updateCategory(form.value).finally(() => buttonLoading.value = false); } else { - await addCategory(form.value).finally(() => (buttonLoading.value = false)); + await addCategory(form.value).finally(() => buttonLoading.value = false); } - proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); + proxy?.$modal.msgSuccess("鎿嶄綔鎴愬姛"); dialog.visible = false; - await getList(); + getList(); } }); -}; +} /** 鍒犻櫎鎸夐挳鎿嶄綔 */ const handleDelete = async (row: CategoryVO) => { - await proxy?.$modal.confirm('鏄惁纭鍒犻櫎娴佺▼鍒嗙被缂栧彿涓�"' + row.id + '"鐨勬暟鎹」锛�'); + await proxy?.$modal.confirm('鏄惁纭鍒犻櫎"' + row.categoryName + '"鐨勫垎绫伙紵'); loading.value = true; - await delCategory(row.id).finally(() => (loading.value = false)); + await delCategory(row.categoryId).finally(() => loading.value = false); await getList(); - proxy?.$modal.msgSuccess('鍒犻櫎鎴愬姛'); -}; + proxy?.$modal.msgSuccess("鍒犻櫎鎴愬姛"); +} onMounted(() => { getList(); diff --git a/src/views/workflow/formManage/index.vue b/src/views/workflow/formManage/index.vue deleted file mode 100644 index 9b9cfe2..0000000 --- a/src/views/workflow/formManage/index.vue +++ /dev/null @@ -1,243 +0,0 @@ -<template> - <div class="p-2"> - <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> - <div v-show="showSearch" class="search"> - <el-form ref="queryFormRef" :model="queryParams" :inline="true"> - <el-form-item label="琛ㄥ崟鍚嶇О" prop="formName"> - <el-input v-model="queryParams.formName" placeholder="璇疯緭鍏ヨ〃鍗曞悕绉�" clearable @keyup.enter="handleQuery" /> - </el-form-item> - <el-form-item> - <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button> - <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button> - </el-form-item> - </el-form> - </div> - </transition> - - <el-card shadow="never"> - <template #header> - <el-row :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-button v-hasPermi="['workflow:formManage:add']" type="primary" plain icon="Plus" @click="handleAdd">鏂板</el-button> - </el-col> - <el-col :span="1.5"> - <el-button v-hasPermi="['workflow:formManage:edit']" type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()" - >淇敼</el-button - > - </el-col> - <el-col :span="1.5"> - <el-button v-hasPermi="['workflow:formManage:remove']" type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()" - >鍒犻櫎</el-button - > - </el-col> - <el-col :span="1.5"> - <el-button v-hasPermi="['workflow:formManage:export']" type="warning" plain icon="Download" @click="handleExport">瀵煎嚭</el-button> - </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> - </el-row> - </template> - - <el-table v-loading="loading" :data="formManageList" @selection-change="handleSelectionChange"> - <el-table-column type="selection" width="55" align="center" /> - <el-table-column label="琛ㄥ崟鍚嶇О" align="center" prop="formName" /> - <el-table-column label="琛ㄥ崟绫诲瀷" align="center"> - <template #default="scope"> - <dict-tag :options="wf_form_type" :value="scope.row.formType"></dict-tag> - </template> - </el-table-column> - <el-table-column label="鍦板潃" align="center" prop="router" /> - <el-table-column label="澶囨敞" align="center" prop="remark" /> - <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> - <template #default="scope"> - <el-tooltip content="淇敼" placement="top"> - <el-button v-hasPermi="['workflow:formManage:edit']" link type="primary" icon="Edit" @click="handleUpdate(scope.row)"></el-button> - </el-tooltip> - <el-tooltip content="鍒犻櫎" placement="top"> - <el-button v-hasPermi="['workflow:formManage:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> - </el-tooltip> - </template> - </el-table-column> - </el-table> - - <pagination v-show="total > 0" v-model:page="queryParams.pageNum" v-model:limit="queryParams.pageSize" :total="total" @pagination="getList" /> - </el-card> - <!-- 娣诲姞鎴栦慨鏀硅〃鍗曠鐞嗗璇濇 --> - <el-dialog v-model="dialog.visible" :title="dialog.title" width="500px" append-to-body> - <el-form ref="formManageFormRef" :model="form" :rules="rules" label-width="80px"> - <el-form-item label="琛ㄥ崟鍚嶇О" prop="formName"> - <el-input v-model="form.formName" placeholder="璇疯緭鍏ヨ〃鍗曞悕绉�" /> - </el-form-item> - <el-form-item label="琛ㄥ崟绫诲瀷" prop="formType"> - <el-radio-group v-model="form.formType" @change="form.router = ''"> - <el-radio v-for="dict in wf_form_type" :key="dict.value" border :value="dict.value">{{ dict.label }}</el-radio> - </el-radio-group> - </el-form-item> - <el-form-item v-if="form.formType === 'static'" label="璺敱鍦板潃" prop="router"> - <el-input v-model="form.router" placeholder="璇疯緭鍏ヨ矾鐢卞湴鍧�" /> - </el-form-item> - <el-form-item v-else label="琛ㄥ崟" prop="router"> - <el-input v-model="form.router" disabled placeholder="璇烽�夋嫨琛ㄥ崟"> - <template #append> - <el-button icon="Search" /> - </template> - </el-input> - </el-form-item> - <el-form-item label="澶囨敞" prop="remark"> - <el-input v-model="form.remark" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" /> - </el-form-item> - </el-form> - <template #footer> - <div class="dialog-footer"> - <el-button :loading="buttonLoading" type="primary" @click="submitForm">纭� 瀹�</el-button> - <el-button @click="cancel">鍙� 娑�</el-button> - </div> - </template> - </el-dialog> - </div> -</template> - -<script setup name="FormManage" lang="ts"> -import { listFormManage, getFormManage, delFormManage, addFormManage, updateFormManage } from '@/api/workflow/formManage'; -import { FormManageVO, FormManageQuery, FormManageForm } from '@/api/workflow/formManage/types'; -const { proxy } = getCurrentInstance() as ComponentInternalInstance; -const { wf_form_type } = toRefs<any>(proxy?.useDict('wf_form_type')); - -const formManageList = ref<FormManageVO[]>([]); -const buttonLoading = ref(false); -const loading = ref(true); -const showSearch = ref(true); -const ids = ref<Array<string | number>>([]); -const single = ref(true); -const multiple = ref(true); -const total = ref(0); - -const queryFormRef = ref<ElFormInstance>(); -const formManageFormRef = ref<ElFormInstance>(); - -const dialog = reactive<DialogOption>({ - visible: false, - title: '' -}); - -const initFormData: FormManageForm = { - id: undefined, - formName: undefined, - formType: 'static', - remark: undefined -}; -const data = reactive<PageData<FormManageForm, FormManageQuery>>({ - form: { ...initFormData }, - queryParams: { - pageNum: 1, - pageSize: 10, - formName: undefined, - formType: undefined - }, - rules: { - id: [{ required: true, message: '涓婚敭涓嶈兘涓虹┖', trigger: 'blur' }], - formName: [{ required: true, message: '琛ㄥ崟鍚嶇О涓嶈兘涓虹┖', trigger: 'blur' }], - formType: [{ required: true, message: '琛ㄥ崟绫诲瀷涓嶈兘涓虹┖', trigger: 'change' }], - router: [{ required: true, message: '涓嶈兘涓虹┖', trigger: 'blur' }] - } -}); - -const { queryParams, form, rules } = toRefs(data); - -/** 鏌ヨ琛ㄥ崟绠$悊鍒楄〃 */ -const getList = async () => { - loading.value = true; - const res = await listFormManage(queryParams.value); - formManageList.value = res.rows; - total.value = res.total; - loading.value = false; -}; - -/** 鍙栨秷鎸夐挳 */ -const cancel = () => { - reset(); - dialog.visible = false; -}; - -/** 琛ㄥ崟閲嶇疆 */ -const reset = () => { - form.value = { ...initFormData }; - formManageFormRef.value?.resetFields(); -}; - -/** 鎼滅储鎸夐挳鎿嶄綔 */ -const handleQuery = () => { - queryParams.value.pageNum = 1; - getList(); -}; - -/** 閲嶇疆鎸夐挳鎿嶄綔 */ -const resetQuery = () => { - queryFormRef.value?.resetFields(); - handleQuery(); -}; - -/** 澶氶�夋閫変腑鏁版嵁 */ -const handleSelectionChange = (selection: FormManageVO[]) => { - ids.value = selection.map((item) => item.id); - single.value = selection.length != 1; - multiple.value = !selection.length; -}; - -/** 鏂板鎸夐挳鎿嶄綔 */ -const handleAdd = () => { - reset(); - dialog.visible = true; - dialog.title = '娣诲姞琛ㄥ崟绠$悊'; -}; - -/** 淇敼鎸夐挳鎿嶄綔 */ -const handleUpdate = async (row?: FormManageVO) => { - reset(); - const _id = row?.id || ids.value[0]; - const res = await getFormManage(_id); - Object.assign(form.value, res.data); - dialog.visible = true; - dialog.title = '淇敼琛ㄥ崟绠$悊'; -}; - -/** 鎻愪氦鎸夐挳 */ -const submitForm = () => { - formManageFormRef.value?.validate(async (valid: boolean) => { - if (valid) { - buttonLoading.value = true; - if (form.value.id) { - await updateFormManage(form.value).finally(() => (buttonLoading.value = false)); - } else { - await addFormManage(form.value).finally(() => (buttonLoading.value = false)); - } - proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); - dialog.visible = false; - await getList(); - } - }); -}; - -/** 鍒犻櫎鎸夐挳鎿嶄綔 */ -const handleDelete = async (row?: FormManageVO) => { - const _ids = row?.id || ids.value; - await proxy?.$modal.confirm('鏄惁纭鍒犻櫎琛ㄥ崟绠$悊缂栧彿涓�"' + _ids + '"鐨勬暟鎹」锛�').finally(() => (loading.value = false)); - await delFormManage(_ids); - proxy?.$modal.msgSuccess('鍒犻櫎鎴愬姛'); - await getList(); -}; - -/** 瀵煎嚭鎸夐挳鎿嶄綔 */ -const handleExport = () => { - proxy?.download( - 'workflow/formManage/export', - { - ...queryParams.value - }, - `formManage_${new Date().getTime()}.xlsx` - ); -}; - -onMounted(() => { - getList(); -}); -</script> diff --git a/src/views/workflow/leave/index.vue b/src/views/workflow/leave/index.vue index f413136..2c8da0e 100644 --- a/src/views/workflow/leave/index.vue +++ b/src/views/workflow/leave/index.vue @@ -27,11 +27,11 @@ <el-col :span="1.5"> <el-button v-hasPermi="['workflow:leave:export']" type="warning" plain icon="Download" @click="handleExport">瀵煎嚭</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> - <el-table v-loading="loading" :data="leaveList" @selection-change="handleSelectionChange"> + <el-table v-loading="loading" border :data="leaveList" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" align="center" /> <el-table-column v-if="false" label="涓婚敭" align="center" prop="id" /> <el-table-column label="璇峰亣绫诲瀷" align="center"> @@ -41,12 +41,12 @@ </el-table-column> <el-table-column label="寮�濮嬫椂闂�" align="center" prop="startDate"> <template #default="scope"> - <span>{{ parseTime(scope.row.startDate, '{y}-{m}-{d}') }}</span> + <span>{{ proxy.parseTime(scope.row.startDate, '{y}-{m}-{d}') }}</span> </template> </el-table-column> <el-table-column label="缁撴潫鏃堕棿" align="center" prop="endDate"> <template #default="scope"> - <span>{{ parseTime(scope.row.endDate, '{y}-{m}-{d}') }}</span> + <span>{{ proxy.parseTime(scope.row.endDate, '{y}-{m}-{d}') }}</span> </template> </el-table-column> <el-table-column label="璇峰亣澶╂暟" align="center" prop="leaveDays" /> @@ -56,38 +56,28 @@ <dict-tag :options="wf_business_status" :value="scope.row.status"></dict-tag> </template> </el-table-column> - <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <el-table-column label="鎿嶄綔" align="center" width="162"> <template #default="scope"> - <el-button - v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'" - v-hasPermi="['workflow:leave:edit']" - size="small" - link - type="primary" - icon="Edit" - @click="handleUpdate(scope.row)" - >淇敼</el-button - > - <el-button - v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'" - v-hasPermi="['workflow:leave:remove']" - size="small" - link - type="primary" - icon="Delete" - @click="handleDelete(scope.row)" - >鍒犻櫎</el-button - > - <el-button link type="primary" size="small" icon="View" @click="handleView(scope.row)">鏌ョ湅</el-button> - <el-button - v-if="scope.row.status === 'waiting'" - link - size="small" - type="primary" - icon="Notification" - @click="handleCancelProcessApply(scope.row.id)" - >鎾ら攢</el-button - > + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5" v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'"> + <el-button v-hasPermi="['workflow:leave:edit']" size="small" type="primary" icon="Edit" @click="handleUpdate(scope.row)" + >淇敼</el-button + > + </el-col> + <el-col :span="1.5" v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'"> + <el-button v-hasPermi="['workflow:leave:remove']" size="small" type="primary" icon="Delete" @click="handleDelete(scope.row)" + >鍒犻櫎</el-button + > + </el-col> + </el-row> + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">鏌ョ湅</el-button> + </el-col> + <el-col :span="1.5" v-if="scope.row.status === 'waiting'"> + <el-button size="small" type="primary" icon="Notification" @click="handleCancelProcessApply(scope.row.id)">鎾ら攢</el-button> + </el-col> + </el-row> </template> </el-table-column> </el-table> @@ -99,7 +89,7 @@ <script setup name="Leave" lang="ts"> import { delLeave, listLeave } from '@/api/workflow/leave'; -import { cancelProcessApply } from '@/api/workflow/processInstance'; +import { cancelProcessApply } from '@/api/workflow/instance'; import { LeaveForm, LeaveQuery, LeaveVO } from '@/api/workflow/leave/types'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; @@ -232,7 +222,11 @@ const handleCancelProcessApply = async (id: string) => { await proxy?.$modal.confirm('鏄惁纭鎾ら攢褰撳墠鍗曟嵁锛�'); loading.value = true; - await cancelProcessApply(id).finally(() => (loading.value = false)); + let data = { + businessId: id, + message: '鐢宠浜烘挙閿�娴佺▼锛�' + }; + await cancelProcessApply(data).finally(() => (loading.value = false)); await getList(); proxy?.$modal.msgSuccess('鎾ら攢鎴愬姛'); }; diff --git a/src/views/workflow/leave/leaveEdit.vue b/src/views/workflow/leave/leaveEdit.vue index 55556fd..8ef66a5 100644 --- a/src/views/workflow/leave/leaveEdit.vue +++ b/src/views/workflow/leave/leaveEdit.vue @@ -44,6 +44,17 @@ <submitVerify ref="submitVerifyRef" :task-variables="taskVariables" @submit-callback="submitCallback" /> <!-- 瀹℃壒璁板綍 --> <approvalRecord ref="approvalRecordRef" /> + <el-dialog v-model="dialogVisible.visible" :title="dialogVisible.title" :before-close="handleClose" width="500"> + <el-select v-model="flowCode" placeholder="Select" style="width: 240px"> + <el-option v-for="item in flowCodeOptions" :key="item.value" :label="item.label" :value="item.value" /> + </el-select> + <template #footer> + <div class="dialog-footer"> + <el-button @click="handleClose">鍙栨秷</el-button> + <el-button type="primary" @click="submitFlow()"> 纭 </el-button> + </div> + </template> + </el-dialog> </div> </template> @@ -80,6 +91,35 @@ label: '濠氬亣' } ]; +const flowCodeOptions = [ + { + value: 'leave1', + label: '璇峰亣鐢宠-鏅��' + }, + { + value: 'leave2', + label: '璇峰亣鐢宠-鎺掍粬缃戝叧' + }, + { + value: 'leave3', + label: '璇峰亣鐢宠-骞惰缃戝叧' + }, + { + value: 'leave4', + label: '璇峰亣鐢宠-浼氱' + }, + { + value: 'leave5', + label: '璇峰亣鐢宠-骞惰浼氱缃戝叧' + } +]; + +const flowCode = ref<string>(''); + +const dialogVisible = reactive<DialogOption>({ + visible: false, + title: '娴佺▼瀹氫箟' +}); //鎻愪氦缁勪欢 const submitVerifyRef = ref<InstanceType<typeof SubmitVerify>>(); //瀹℃壒璁板綍缁勪欢 @@ -88,8 +128,8 @@ const leaveFormRef = ref<ElFormInstance>(); const submitFormData = ref<StartProcessBo>({ - businessKey: '', - tableName: '', + businessId: '', + flowCode: '', variables: {} }); const taskVariables = ref<Record<string, any>>({}); @@ -119,6 +159,11 @@ } }); +const handleClose = () => { + dialogVisible.visible = false; + flowCode.value = ''; + buttonLoading.value = false; +}; const { form, rules } = toRefs(data); /** 琛ㄥ崟閲嶇疆 */ @@ -174,6 +219,15 @@ proxy.$tab.closePage(proxy.$route); proxy.$router.go(-1); } else { + if ((form.value.status === 'draft' && (flowCode.value === '' || flowCode.value === null)) || routeParams.value.type === 'add') { + flowCode.value = flowCodeOptions[0].value; + dialogVisible.visible = true; + return; + } + //璇存槑鍚姩杩囧厛闅忔剰绌夸釜鍙傛暟 + if (flowCode.value === '' || flowCode.value === null) { + flowCode.value = 'xx'; + } await handleStartWorkFlow(res.data); } } @@ -183,17 +237,19 @@ } }; +const submitFlow = async () => { + handleStartWorkFlow(form.value); + dialogVisible.visible = false; +}; //鎻愪氦鐢宠 const handleStartWorkFlow = async (data: LeaveVO) => { try { - submitFormData.value.tableName = 'test_leave'; - submitFormData.value.businessKey = data.id; + submitFormData.value.flowCode = flowCode.value; + submitFormData.value.businessId = data.id; //娴佺▼鍙橀噺 taskVariables.value = { - entity: data, leaveDays: data.leaveDays, - userList: ["1", "3"], - userList2: ["1", "3"] + userList: ['1', '3', '4'] }; submitFormData.value.variables = taskVariables.value; const resp = await startWorkFlow(submitFormData.value); diff --git a/src/views/workflow/model/index.vue b/src/views/workflow/model/index.vue deleted file mode 100644 index e83cd94..0000000 --- a/src/views/workflow/model/index.vue +++ /dev/null @@ -1,383 +0,0 @@ -<template> - <div class="p-2"> - <el-row :gutter="20"> - <!-- 娴佺▼鍒嗙被鏍� --> - <el-col :lg="4" :xs="24" style=""> - <el-card shadow="hover"> - <el-input v-model="categoryName" placeholder="璇疯緭鍏ユ祦绋嬪垎绫诲悕" prefix-icon="Search" clearable /> - <el-tree - ref="categoryTreeRef" - class="mt-2" - node-key="id" - :data="categoryOptions" - :props="{ label: 'categoryName', children: 'children' }" - :expand-on-click-node="false" - :filter-node-method="filterNode" - highlight-current - default-expand-all - @node-click="handleNodeClick" - ></el-tree> - </el-card> - </el-col> - <el-col :lg="20" :xs="24"> - <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> - <div v-show="showSearch" class="mb-[10px]"> - <el-card shadow="hover"> - <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true"> - <el-form-item label="妯″瀷鍚嶇О" prop="name"> - <el-input v-model="queryParams.name" placeholder="璇疯緭鍏ユā鍨嬪悕绉�" clearable @keyup.enter="handleQuery" /> - </el-form-item> - <el-form-item label="妯″瀷KEY" prop="key"> - <el-input v-model="queryParams.key" placeholder="璇疯緭鍏ユā鍨婯EY" clearable @keyup.enter="handleQuery" /> - </el-form-item> - <el-form-item> - <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button> - <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button> - </el-form-item> - </el-form> - </el-card> - </div> - </transition> - <el-card shadow="hover"> - <template #header> - <el-row :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-button type="primary" plain icon="Plus" @click="handleAdd">鏂板</el-button> - </el-col> - <el-col :span="1.5"> - <el-button type="success" plain icon="Edit" :disabled="single" @click="handleUpdate()">淇敼</el-button> - </el-col> - <el-col :span="1.5"> - <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete()">鍒犻櫎</el-button> - </el-col> - <el-col :span="1.5"> - <el-button type="primary" plain :disabled="multiple" icon="Download" @click="clickExportZip()">瀵煎嚭</el-button> - </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> - </el-row> - </template> - - <el-table v-loading="loading" border :data="modelList" @selection-change="handleSelectionChange"> - <el-table-column type="selection" width="55" align="center" /> - <el-table-column fixed align="center" type="index" label="搴忓彿" width="80"></el-table-column> - <el-table-column align="center" :show-overflow-tooltip="true" prop="name" label="妯″瀷鍚嶇О" width="200"></el-table-column> - <el-table-column align="center" prop="key" label="妯″瀷KEY"></el-table-column> - <el-table-column align="center" prop="version" label="鐗堟湰鍙�" width="90"> - <template #default="scope"> v{{ scope.row.version }}.0</template> - </el-table-column> - <el-table-column align="center" prop="metaInfo" label="澶囨敞璇存槑" min-width="130"></el-table-column> - <el-table-column align="center" :show-overflow-tooltip="true" prop="createTime" label="鍒涘缓鏃堕棿" width="160"></el-table-column> - <el-table-column align="center" :show-overflow-tooltip="true" prop="lastUpdateTime" label="鏇存柊鏃堕棿" width="160"></el-table-column> - <el-table-column fixed="right" label="鎿嶄綔" align="center" width="170" class-name="small-padding fixed-width"> - <template #default="scope"> - <el-row :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-button link type="primary" size="small" icon="Pointer" @click="clickDesign(scope.row.id)">璁捐娴佺▼</el-button> - </el-col> - <el-col :span="1.5"> - <el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">鍒犻櫎</el-button> - </el-col> - </el-row> - <el-row :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-button link type="primary" size="small" icon="ScaleToOriginal" @click="clickDeploy(scope.row.id, scope.row.key)"> - 娴佺▼閮ㄧ讲 - </el-button> - </el-col> - <el-col :span="1.5"> - <el-button link type="primary" size="small" icon="CopyDocument" @click="handleCopy(scope.row)"> 澶嶅埗妯″瀷 </el-button> - </el-col> - </el-row> - </template> - </el-table-column> - </el-table> - <pagination - v-show="total > 0" - v-model:page="queryParams.pageNum" - v-model:limit="queryParams.pageSize" - :total="total" - @pagination="getList" - /> - </el-card> - </el-col> - </el-row> - <!-- 璁捐娴佺▼寮�濮� --> - <Design ref="designRef" @close-call-back="handleQuery"></Design> - <!-- 璁捐娴佺▼缁撴潫 --> - <!-- 娣诲姞妯″瀷瀵硅瘽妗� --> - <el-dialog v-model="dialog.visible" :title="dialog.title" width="650px" append-to-body :close-on-click-modal="false"> - <el-form ref="formRef" :model="form" :rules="rules" label-width="100px"> - <el-form-item label="妯″瀷鍚嶇О锛�" prop="name"> - <el-input v-model="form.name" :disabled="ids && ids.length > 0 && billType === 'update'" maxlength="20" show-word-limit /> - </el-form-item> - <el-form-item label="妯″瀷KEY锛�" prop="key"> - <el-input v-model="form.key" :disabled="ids && ids.length > 0 && billType === 'update'" maxlength="20" show-word-limit /> - </el-form-item> - <el-form-item label="娴佺▼鍒嗙被" prop="categoryCode"> - <el-tree-select - v-model="form.categoryCode" - :data="categoryOptions" - :props="{ value: 'categoryCode', label: 'categoryName', children: 'children' }" - value-key="categoryCode" - placeholder="璇烽�夋嫨娴佺▼鍒嗙被" - check-strictly - /> - </el-form-item> - <el-form-item label="澶囨敞锛�" prop="description"> - <el-input v-model="form.description" type="textarea" maxlength="200" show-word-limit></el-input> - </el-form-item> - </el-form> - <template #footer> - <span class="dialog-footer"> - <el-button type="primary" @click="submitForm">纭� 瀹�</el-button> - <el-button @click="cancel">鍙� 娑�</el-button> - </span> - </template> - </el-dialog> - </div> -</template> - -<script lang="ts" setup name="Model"> -import Design from '../../../components/BpmnDesign/index.vue'; -import { listModel, addModel, delModel, modelDeploy, getInfo, update } from '@/api/workflow/model'; -import { ModelQuery, ModelForm, ModelVO } from '@/api/workflow/model/types'; -import { listCategory } from '@/api/workflow/category'; -import { copyModel } from '@/api/workflow/model'; - -const { proxy } = getCurrentInstance() as ComponentInternalInstance; - -const formRef = ref<ElFormInstance>(); -const queryFormRef = ref<ElFormInstance>(); -const categoryTreeRef = ref<ElTreeInstance>(); -const designRef = ref<InstanceType<typeof Design>>(); - -type CategoryOption = { - categoryCode: string; - categoryName: string; - children?: CategoryOption[]; -}; - -const buttonLoading = ref(false); -const loading = ref(true); -const ids = ref<string[]>([]); -const single = ref(true); -const multiple = ref(true); -const showSearch = ref(true); -const total = ref(0); -const modelList = ref<ModelVO[]>([]); -const categoryOptions = ref<CategoryOption[]>([]); -const categoryName = ref(''); -const billType = ref<string>(''); - -const dialog = reactive<DialogOption>({ - visible: false, - title: '' -}); - -const initFormData: ModelForm = { - id: '', - name: '', - key: '', - categoryCode: '', - xml: '', - svg: '', - description: '' -}; -const data = reactive<PageData<ModelForm, ModelQuery>>({ - form: { ...initFormData }, - queryParams: { - pageNum: 1, - pageSize: 10, - name: '', - key: '', - categoryCode: '' - }, - rules: { - name: [{ required: true, message: '妯″瀷涓嶈兘涓虹┖', trigger: 'blur' }], - key: [{ required: true, message: '妯″瀷KEY涓嶈兘涓虹┖', trigger: 'blur' }], - categoryCode: [{ required: true, message: '娴佺▼鍒嗙被涓嶈兘涓虹┖', trigger: 'blur' }] - } -}); -const { queryParams, form, rules } = toRefs(data); - -onMounted(() => { - getList(); - getTreeselect(); -}); - -/** 鑺傜偣鍗曞嚮浜嬩欢 */ -const handleNodeClick = (data: ModelForm) => { - queryParams.value.categoryCode = data.categoryCode; - if (data.categoryCode === 'ALL') { - queryParams.value.categoryCode = ''; - } - handleQuery(); -}; -/** 閫氳繃鏉′欢杩囨护鑺傜偣 */ -const filterNode = (value: string, data: any) => { - if (!value) return true; - return data.categoryName.indexOf(value) !== -1; -}; -/** 鏍规嵁鍚嶇О绛涢�夐儴闂ㄦ爲 */ -watchEffect( - () => { - categoryTreeRef.value?.filter(categoryName.value); - }, - { - flush: 'post' // watchEffect浼氬湪DOM鎸傝浇鎴栬�呮洿鏂颁箣鍓嶅氨浼氳Е鍙戯紝姝ゅ睘鎬ф帶鍒跺湪DOM鍏冪礌鏇存柊鍚庤繍琛� - } -); - -/** 鎼滅储鎸夐挳鎿嶄綔 */ -const handleQuery = () => { - queryParams.value.pageNum = 1; - getList(); -}; -/** 閲嶇疆鎸夐挳鎿嶄綔 */ -const resetQuery = () => { - queryFormRef.value?.resetFields(); - queryParams.value.categoryCode = ''; - queryParams.value.pageNum = 1; - queryParams.value.pageSize = 10; - handleQuery(); -}; -// 澶氶�夋閫変腑鏁版嵁 -const handleSelectionChange = (selection: ModelVO[]) => { - ids.value = selection.map((item: ModelVO) => item.id); - single.value = selection.length !== 1; - multiple.value = !selection.length; -}; -//鍒嗛〉 -const getList = async () => { - loading.value = true; - const resp = await listModel(queryParams.value); - modelList.value = resp.rows; - total.value = resp.total; - loading.value = false; -}; -/** 鍒犻櫎鎸夐挳鎿嶄綔 */ -const handleDelete = async (row?: ModelVO) => { - const id = row?.id || ids.value; - await proxy?.$modal.confirm('鏄惁纭鍒犻櫎妯″瀷id涓恒��' + id + '銆戠殑鏁版嵁椤癸紵'); - loading.value = true; - await delModel(id).finally(() => (loading.value = false)); - await getList(); - proxy?.$modal.msgSuccess('鍒犻櫎鎴愬姛'); -}; -// 娴佺▼閮ㄧ讲 -const clickDeploy = async (id: string, key: string) => { - await proxy?.$modal.confirm('鏄惁閮ㄧ讲妯″瀷key涓恒��' + key + '銆戞祦绋嬶紵'); - loading.value = true; - await modelDeploy(id).finally(() => (loading.value = false)); - await getList(); - proxy?.$modal.msgSuccess('閮ㄧ讲鎴愬姛'); -}; -//鏂板鎵撳紑 -const handleAdd = () => { - billType.value = 'add'; - ids.value = []; - getTreeselect(); - form.value = { ...initFormData }; - dialog.visible = true; - dialog.title = '鏂板妯″瀷'; -}; -//淇敼鎵撳紑 -const handleUpdate = () => { - billType.value = 'update'; - dialog.title = '淇敼妯″瀷'; - nextTick(async () => { - await getTreeselect(); - const _id = ids.value[0]; - const res = await getInfo(_id); - Object.assign(form.value, res.data); - dialog.visible = true; - }); -}; - -//澶嶅埗鎵撳紑 -const handleCopy = (row?: ModelVO) => { - billType.value = 'copy'; - dialog.title = '澶嶅埗妯″瀷'; - nextTick(async () => { - await getTreeselect(); - form.value = { ...initFormData }; - form.value.id = row.id; - dialog.visible = true; - }); -}; - -/** 鎻愪氦鎸夐挳 */ -const submitForm = () => { - formRef.value.validate(async (valid: boolean) => { - if (valid) { - buttonLoading.value = true; - if ('copy' === billType.value) { - await copyModel(form.value); - proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); - } else if (ids.value && ids.value.length > 0 && 'update' === billType.value) { - form.value.id = ids.value[0]; - await update(form.value); - proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); - } else { - initXml(form.value.key, form.value.name); - form.value.xml = xml.value; - await addModel(form.value); - proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); - } - dialog.visible = false; - await getList(); - } - }); -}; - -/** 鍙栨秷鎸夐挳 */ -const cancel = () => { - reset(); - dialog.visible = false; -}; - -/** 琛ㄥ崟閲嶇疆 */ -const reset = () => { - form.value = { ...initFormData }; - formRef.value.resetFields(); -}; - -// 鎵撳紑璁捐娴佺▼ -const clickDesign = async (id: string) => { - await designRef.value.open(id); -}; -// 瀵煎嚭娴佺▼妯″瀷 -const clickExportZip = () => { - proxy?.$download.zip('/workflow/model/export/zip/' + ids.value, '妯″瀷'); -}; -/** 鏌ヨ娴佺▼鍒嗙被涓嬫媺鏍戠粨鏋� */ -const getTreeselect = async () => { - const res = await listCategory(); - categoryOptions.value = []; - const data: CategoryOption = { categoryCode: 'ALL', categoryName: '椤剁骇鑺傜偣', children: [] }; - data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId'); - categoryOptions.value.push(data); -}; - -const xml = ref<string>(''); - -const initXml = async (key: string, name: string) => { - xml.value = `<?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:bioc="http://bpmn.io/schema/bpmn/biocolor/1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:flowable="http://flowable.org/bpmn" targetNamespace="http://www.flowable.org/processdef"> - <process id="${key}" name="${name}"> - <startEvent id="startNode1" name="寮�濮�" /> - </process> - <bpmndi:BPMNDiagram id="BPMNDiagram_flow"> - <bpmndi:BPMNPlane id="BPMNPlane_flow" bpmnElement="T-2d89e7a3-ba79-4abd-9f64-ea59621c258c"> - <bpmndi:BPMNShape id="BPMNShape_startNode1" bpmnElement="startNode1" bioc:stroke=""> - <omgdc:Bounds x="240" y="200" width="30" height="30" /> - <bpmndi:BPMNLabel> - <omgdc:Bounds x="242" y="237" width="23" height="14" /> - </bpmndi:BPMNLabel> - </bpmndi:BPMNShape> - </bpmndi:BPMNPlane> - </bpmndi:BPMNDiagram> -</definitions>`; - return xml; -}; -</script> diff --git a/src/views/workflow/processDefinition/components/processPreview.vue b/src/views/workflow/processDefinition/components/processPreview.vue deleted file mode 100644 index 19a95df..0000000 --- a/src/views/workflow/processDefinition/components/processPreview.vue +++ /dev/null @@ -1,45 +0,0 @@ -<template> - <el-dialog v-model="data.visible" title="棰勮" width="70%" append-to-body destroy-on-close> - <div v-if="data.type === 'bpmn' && data.xmlStr"> - <BpmnViewer ref="bpmnViewerRef"></BpmnViewer> - </div> - <div v-if="data.type === 'xml' && data.xmlStr"> - <highlightjs language="xml" :code="data.xmlStr" /> - </div> - <template #footer> - <span v-if="data.type === 'xml'" class="dialog-footer"> </span> - </template> - </el-dialog> -</template> - -<script setup lang="ts"> -import BpmnViewer from '@/components/BpmnView/index.vue'; - -const data = reactive({ - visible: false, - type: '', - xmlStr: '' -}); - -const bpmnViewerRef = ref<InstanceType<typeof BpmnViewer>>(); -type PreviewType = 'xml' | 'bpmn'; -//鎵撳紑 -const openDialog = (xmlStr: string, type: PreviewType) => { - data.visible = true; - data.xmlStr = xmlStr; - data.type = type; - /** 娴佺▼鍥� */ - if (type === 'bpmn') { - /** 蹇呴』鏀惧湪nextTick 鍚﹀垯绗竴娆℃墦寮�涓虹┖ */ - nextTick(() => { - bpmnViewerRef.value?.initXml(data.xmlStr); - }); - } -}; -/** - * 瀵瑰鏆撮湶瀛愮粍浠舵柟娉� - */ -defineExpose({ - openDialog -}); -</script> diff --git a/src/views/workflow/processDefinition/design.vue b/src/views/workflow/processDefinition/design.vue new file mode 100644 index 0000000..3ec44f7 --- /dev/null +++ b/src/views/workflow/processDefinition/design.vue @@ -0,0 +1,46 @@ +<template> + <div ref="container" class="w-full h-[calc(100vh-88px)]"> + <iframe ref="iframe" :src="iframeUrl" frameborder="0" height="100%" style="height: 100%; width: inherit"></iframe> + </div> +</template> + +<script setup name="WarmFlow"> +const { proxy } = getCurrentInstance(); +import { onMounted } from 'vue'; +import { getToken } from '@/utils/auth'; + +// definitionId涓洪渶瑕佹煡璇㈢殑娴佺▼瀹氫箟id锛� +// disabled涓烘槸鍚﹀彲缂栬緫, 渚嬪锛氭煡鐪嬬殑鏃跺�欎笉鍙紪杈戯紝涓嶅彲淇濆瓨 +const iframeUrl = ref(''); +const baseUrl = import.meta.env.VITE_APP_BASE_API; +const iframeLoaded = () => { + // iframe鐩戝惉缁勪欢鍐呰璁″櫒淇濆瓨浜嬩欢 + window.onmessage = (event) => { + switch (event.data.method) { + case 'close': + close(); + break; + } + }; +}; +const open = async (definitionId, disabled) => { + let url = baseUrl + `/warm-flow-ui/index.html?id=${definitionId}&disabled=${disabled}`; + iframeUrl.value = url + '&Authorization=Bearer ' + getToken() + '&clientid=' + import.meta.env.VITE_APP_CLIENT_ID; +}; +/** 鍏抽棴鎸夐挳 */ +function close() { + const obj = { path: '/workflow/processDefinition' }; + proxy.$tab.closeOpenPage(obj); +} + +onMounted(() => { + iframeLoaded(); + open(proxy.$route.query.definitionId, proxy.$route.query.disabled); +}); +/** + * 瀵瑰鏆撮湶瀛愮粍浠舵柟娉� + */ +defineExpose({ + open +}); +</script> diff --git a/src/views/workflow/processDefinition/index.vue b/src/views/workflow/processDefinition/index.vue index 1dacb80..a45e484 100644 --- a/src/views/workflow/processDefinition/index.vue +++ b/src/views/workflow/processDefinition/index.vue @@ -10,7 +10,7 @@ class="mt-2" node-key="id" :data="categoryOptions" - :props="{ label: 'categoryName', children: 'children' }" + :props="{ label: 'label', children: 'children' }" :expand-on-click-node="false" :filter-node-method="filterNode" highlight-current @@ -24,11 +24,11 @@ <div v-show="showSearch" class="mb-[10px]"> <el-card shadow="hover"> <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px"> - <el-form-item label="娴佺▼瀹氫箟鍚嶇О" prop="name"> - <el-input v-model="queryParams.name" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夊悕绉�" clearable @keyup.enter="handleQuery" /> + <el-form-item label="娴佺▼瀹氫箟鍚嶇О" prop="flowName"> + <el-input v-model="queryParams.flowName" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夊悕绉�" clearable @keyup.enter="handleQuery" /> </el-form-item> - <el-form-item label="娴佺▼瀹氫箟KEY" prop="key"> - <el-input v-model="queryParams.key" placeholder="璇疯緭鍏ユ祦绋嬪畾涔塊EY" clearable @keyup.enter="handleQuery" /> + <el-form-item label="娴佺▼瀹氫箟KEY" prop="flowCode"> + <el-input v-model="queryParams.flowCode" placeholder="璇疯緭鍏ユ祦绋嬪畾涔塊EY" clearable @keyup.enter="handleQuery" /> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button> @@ -42,93 +42,86 @@ <template #header> <el-row :gutter="10" class="mb8"> <el-col :span="1.5"> + <el-button type="primary" icon="Plus" @click="handleAdd()">娣诲姞</el-button> + </el-col> + <el-col :span="1.5"> + <el-button type="success" icon="Edit" :disabled="single" @click="handleUpdate()">淇敼</el-button> + </el-col> + <el-col :span="1.5"> <el-button type="danger" icon="Delete" :disabled="multiple" @click="handleDelete()">鍒犻櫎</el-button> </el-col> <el-col :span="1.5"> <el-button type="primary" icon="UploadFilled" @click="uploadDialog.visible = true">閮ㄧ讲娴佺▼鏂囦欢</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="getList"></right-toolbar> + <el-col :span="1.5"> + <el-button type="warning" icon="Download" :disabled="single" @click="handleExportDef">瀵煎嚭</el-button> + </el-col> + <right-toolbar v-model:show-search="showSearch" @query-table="getList"></right-toolbar> </el-row> </template> - - <el-table v-loading="loading" border :data="processDefinitionList" @selection-change="handleSelectionChange"> - <el-table-column type="selection" width="55" align="center" /> - <el-table-column align="center" type="index" label="搴忓彿" width="60"></el-table-column> - <el-table-column align="center" prop="name" label="娴佺▼瀹氫箟鍚嶇О" :show-overflow-tooltip="true"></el-table-column> - <el-table-column align="center" prop="key" label="鏍囪瘑KEY" width="80"></el-table-column> - <el-table-column align="center" prop="version" label="鐗堟湰鍙�" width="80"> - <template #default="scope"> v{{ scope.row.version }}.0</template> - </el-table-column> - <el-table-column align="center" prop="resourceName" label="娴佺▼XML" width="100" :show-overflow-tooltip="true"> - <template #default="scope"> - <el-link type="primary" @click="clickPreview(scope.row.id, 'xml')">{{ scope.row.resourceName }}</el-link> - </template> - </el-table-column> - <el-table-column align="center" prop="diagramResourceName" label="娴佺▼鍥剧墖" width="100" :show-overflow-tooltip="true"> - <template #default="scope"> - <el-link type="primary" @click="clickPreview(scope.row.id, 'bpmn')">{{ scope.row.diagramResourceName }}</el-link> - </template> - </el-table-column> - <el-table-column align="center" prop="suspensionState" label="鐘舵��" width="80"> - <template #default="scope"> - <el-tag v-if="scope.row.suspensionState == 1" type="success">婵�娲�</el-tag> - <el-tag v-else type="danger">鎸傝捣</el-tag> - </template> - </el-table-column> - <el-table-column align="center" prop="deploymentTime" label="閮ㄧ讲鏃堕棿" width="120" :show-overflow-tooltip="true"></el-table-column> - <el-table-column align="center" label="琛ㄥ悕/琛ㄥ崟KEY" width="120" :show-overflow-tooltip="true"> - <template #default="scope"> - <span v-if="scope.row.wfDefinitionConfigVo"> - {{ scope.row.wfDefinitionConfigVo.tableName }} - </span> - </template> - </el-table-column> - <el-table-column fixed="right" label="鎿嶄綔" align="center" width="220" class-name="small-padding fixed-width"> - <template #default="scope"> - <el-row :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-button - link - type="primary" - size="small" - :icon="scope.row.suspensionState === 1 ? 'Lock' : 'Unlock'" - @click="handleProcessDefState(scope.row)" - > - {{ scope.row.suspensionState === 1 ? '鎸傝捣娴佺▼' : '婵�娲绘祦绋�' }} - </el-button> - </el-col> - <el-col :span="1.5"> - <el-button link type="primary" size="small" icon="Document" @click="getProcessDefinitionHitoryList(scope.row.id, scope.row.key)"> - 鍘嗗彶鐗堟湰 - </el-button> - </el-col> - <el-col :span="1.5"> - <el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">鍒犻櫎</el-button> - </el-col> - </el-row> - <el-row :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-button link type="primary" size="small" icon="Sort" @click="handleConvertToModel(scope.row)"> 杞崲妯″瀷 </el-button> - </el-col> - <el-col :span="1.5"> - <el-button link type="primary" size="small" icon="Tickets" @click="handleDefinitionConfigOpen(scope.row)">缁戝畾涓氬姟</el-button> - </el-col> - </el-row> - </template> - </el-table-column> - </el-table> - <pagination - v-show="total > 0" - v-model:page="queryParams.pageNum" - v-model:limit="queryParams.pageSize" - :total="total" - @pagination="getList" - /> + <el-tabs v-model="activeName" class="demo-tabs" @tab-click="handleClick"> + <el-tab-pane label="宸插彂甯�" name="0"></el-tab-pane> + <el-tab-pane label="鏈彂甯�" name="1"></el-tab-pane> + <el-table v-loading="loading" border :data="processDefinitionList" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" align="center" /> + <el-table-column align="center" prop="id" label="涓婚敭" v-if="false"></el-table-column> + <el-table-column align="center" prop="flowName" label="娴佺▼瀹氫箟鍚嶇О" :show-overflow-tooltip="true"></el-table-column> + <el-table-column align="center" prop="flowCode" label="鏍囪瘑KEY" :show-overflow-tooltip="true"></el-table-column> + <el-table-column align="center" prop="version" label="鐗堟湰鍙�" width="80"> + <template #default="scope"> v{{ scope.row.version }}.0</template> + </el-table-column> + <el-table-column align="center" prop="activityStatus" label="婵�娲荤姸鎬�" width="130"> + <template #default="scope"> + <el-switch + v-model="scope.row.activityStatus" + :active-value="1" + :inactive-value="0" + @change="(status) => handleProcessDefState(scope.row, status)" + /> + </template> + </el-table-column> + <el-table-column align="center" prop="isPublish" label="鍙戝竷鐘舵��" width="100"> + <template #default="scope"> + <el-tag v-if="scope.row.isPublish == 0" type="danger">鏈彂甯�</el-tag> + <el-tag v-else-if="scope.row.isPublish == 1" type="success">宸插彂甯�</el-tag> + <el-tag v-else type="danger">澶辨晥</el-tag> + </template> + </el-table-column> + <el-table-column fixed="right" label="鎿嶄綔" align="center" width="170" class-name="small-padding fixed-width"> + <template #default="scope"> + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">鍒犻櫎娴佺▼</el-button> + </el-col> + <el-col :span="1.5"> + <el-button link type="primary" size="small" icon="CopyDocument" @click="handleCopyDef(scope.row)">澶嶅埗娴佺▼</el-button> + </el-col> + </el-row> + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button link type="primary" v-if="scope.row.isPublish === 0" icon="Pointer" size="small" @click="design(scope.row)" + >娴佺▼璁捐</el-button + > + <el-button link type="primary" v-else icon="View" size="small" @click="designView(scope.row)">鏌ョ湅娴佺▼</el-button> + </el-col> + <el-col v-if="scope.row.isPublish !== 1" :span="1.5"> + <el-button link type="primary" size="small" icon="CircleCheck" @click="handlePublish(scope.row)">鍙戝竷娴佺▼</el-button> + </el-col> + </el-row> + </template> + </el-table-column> + </el-table> + <pagination + v-show="total > 0" + v-model:page="queryParams.pageNum" + v-model:limit="queryParams.pageSize" + :total="total" + @pagination="handleQuery" + /> + </el-tabs> </el-card> </el-col> </el-row> - <!-- 棰勮鍥剧墖鎴杧ml --> - <process-preview ref="previewRef" /> <!-- 閮ㄧ讲鏂囦欢 --> <el-dialog v-if="uploadDialog.visible" v-model="uploadDialog.visible" :title="uploadDialog.title" width="30%"> @@ -138,9 +131,9 @@ <el-tree-select v-model="selectCategory" :data="categoryOptions" - :props="{ value: 'categoryCode', label: 'categoryName', children: 'children' }" + :props="{ value: 'id', label: 'label', children: 'children' }" filterable - value-key="categoryCode" + value-key="id" :render-after-expand="false" check-strictly style="width: 240px" @@ -150,100 +143,47 @@ class="upload-demo" drag multiple - accept="application/zip,application/xml,.bpmn" + accept="application/json,application/text" :before-upload="handlerBeforeUpload" - :http-request="handerDeployProcessFile" + :http-request="handlerImportDefinition" > <el-icon class="UploadFilled"><upload-filled /></el-icon> - <div class="el-upload__text"><em>鐐瑰嚮涓婁紶锛岄�夋嫨BPMN娴佺▼鏂囦欢</em></div> - <div class="el-upload__text">浠呮敮鎸� .zip銆�.bpmn20.xml銆乥pmn 鏍煎紡鏂囦欢</div> + <div class="el-upload__text"><em>鐐瑰嚮涓婁紶锛岄�夋嫨JSON娴佺▼鏂囦欢</em></div> + <div class="el-upload__text">浠呮敮鎸乯son鏍煎紡鏂囦欢</div> <div class="el-upload__text">PS:濡傝嫢閮ㄧ讲璇烽儴缃蹭粠鏈」鐩ā鍨嬬鐞嗗鍑虹殑鏁版嵁</div> </el-upload> </div> </el-dialog> - <!-- 鍘嗗彶鐗堟湰 --> - <el-dialog v-if="processDefinitionDialog.visible" v-model="processDefinitionDialog.visible" :title="processDefinitionDialog.title" width="70%"> - <el-table v-loading="loading" :data="processDefinitionHistoryList" @selection-change="handleSelectionChange"> - <el-table-column type="selection" width="55" align="center" /> - <el-table-column align="center" type="index" label="搴忓彿" width="60"></el-table-column> - <el-table-column align="center" prop="name" label="娴佺▼瀹氫箟鍚嶇О" :show-overflow-tooltip="true" min-width="80"></el-table-column> - <el-table-column align="center" prop="key" label="鏍囪瘑KEY"></el-table-column> - <el-table-column align="center" prop="version" label="鐗堟湰鍙�" width="90"> - <template #default="scope"> v{{ scope.row.version }}.0</template> - </el-table-column> - <el-table-column align="center" prop="resourceName" label="娴佺▼XML" min-width="80" :show-overflow-tooltip="true"> - <template #default="scope"> - <el-link type="primary" @click="clickPreviewXML(scope.row.id)">{{ scope.row.resourceName }}</el-link> - </template> - </el-table-column> - <el-table-column align="center" prop="diagramResourceName" label="娴佺▼鍥剧墖" min-width="80" :show-overflow-tooltip="true"> - <template #default="scope"> - <el-link type="primary" @click="clickPreviewImg(scope.row.id)">{{ scope.row.diagramResourceName }}</el-link> - </template> - </el-table-column> - <el-table-column align="center" prop="suspensionState" label="鐘舵��" min-width="70"> - <template #default="scope"> - <el-tag v-if="scope.row.suspensionState == 1" type="success">婵�娲�</el-tag> - <el-tag v-else type="danger">鎸傝捣</el-tag> - </template> - </el-table-column> - <el-table-column align="center" prop="deploymentTime" label="閮ㄧ讲鏃堕棿" :show-overflow-tooltip="true"></el-table-column> - <el-table-column fixed="right" label="鎿嶄綔" align="center" width="200" class-name="small-padding fixed-width"> - <template #default="scope"> - <el-row :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-button - link - type="primary" - size="small" - :icon="scope.row.suspensionState === 1 ? 'Lock' : 'Unlock'" - @click="handleProcessDefState(scope.row)" - > - {{ scope.row.suspensionState === 1 ? '鎸傝捣娴佺▼' : '婵�娲绘祦绋�' }} - </el-button> - </el-col> - <el-col :span="1.5"> - <el-button type="text" size="small" icon="Tickets" @click="handleDefinitionConfigOpen(scope.row)">缁戝畾涓氬姟</el-button> - </el-col> - </el-row> - <el-row :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-button link type="primary" icon="Sort" size="small" @click="handleConvertToModel(scope.row)"> 杞崲妯″瀷 </el-button> - </el-col> - <el-col :span="1.5"> - <el-button link type="primary" icon="Delete" size="small" @click="handleDelete(scope.row)">鍒犻櫎</el-button> - </el-col> - </el-row> - </template> - </el-table-column> - </el-table> - </el-dialog> - - <!-- 琛ㄥ崟閰嶇疆 --> - <el-dialog - v-model="definitionConfigDialog.visible" - :title="definitionConfigDialog.title" - width="650px" - append-to-body - :close-on-click-modal="false" - > - <el-form :model="definitionConfigForm" label-width="auto"> - <el-form-item label="娴佺▼KEY"> - <el-input v-model="definitionConfigForm.processKey" disabled /> - </el-form-item> - <el-form-item label="琛ㄥ悕" prop="formId"> - <el-input v-model="definitionConfigForm.tableName" placeholder="绀轰緥:test_leave" /> - </el-form-item> - <el-form-item label="澶囨敞"> - <el-input v-model="definitionConfigForm.remark" type="textarea" resize="none" /> - </el-form-item> - </el-form> - + <!-- 鏂板/缂栬緫娴佺▼瀹氫箟 --> + <el-dialog v-model="modelDialog.visible" :title="modelDialog.title" width="650px" append-to-body :close-on-click-modal="false"> <template #footer> + <el-form ref="defFormRef" :model="form" :rules="rules" label-width="110px"> + <el-form-item label="娴佺▼绫诲埆" prop="category"> + <el-tree-select + v-model="form.category" + :data="categoryOptions" + :props="{ value: 'id', label: 'label', children: 'children' }" + filterable + value-key="id" + :render-after-expand="false" + check-strictly + style="width: 100%" + /> + </el-form-item> + <el-form-item label="娴佺▼缂栫爜" prop="flowCode"> + <el-input v-model="form.flowCode" placeholder="璇疯緭鍏ユ祦绋嬬紪鐮�" maxlength="40" show-word-limit /> + </el-form-item> + <el-form-item label="娴佺▼鍚嶇О" prop="flowName"> + <el-input v-model="form.flowName" placeholder="璇疯緭鍏ユ祦绋嬪悕绉�" maxlength="100" show-word-limit /> + </el-form-item> + <el-form-item label="琛ㄥ崟璺緞" prop="flowName"> + <el-input v-model="form.formPath" placeholder="璇疯緭鍏ヨ〃鍗曡矾寰�" maxlength="100" show-word-limit /> + </el-form-item> + </el-form> <div class="dialog-footer"> - <el-button @click="definitionConfigDialog.visible = false">鍙栨秷</el-button> - <el-button type="primary" @click="handlerSaveForm">淇濆瓨</el-button> + <el-button @click="modelDialog.visible = false">鍙栨秷</el-button> + <el-button type="primary" @click="handleSubmit">淇濆瓨</el-button> </div> </template> </el-dialog> @@ -251,53 +191,32 @@ </template> <script lang="ts" setup name="processDefinition"> -import { - listProcessDefinition, - definitionImage, - definitionXml, - deleteProcessDefinition, - updateDefinitionState, - convertToModel, - deployProcessFile, - getListByKey -} from '@/api/workflow/processDefinition'; -import { getByTableNameNotDefId, getByDefId, saveOrUpdate } from '@/api/workflow/definitionConfig'; -import ProcessPreview from './components/processPreview.vue'; -import { listCategory } from '@/api/workflow/category'; -import { CategoryVO } from '@/api/workflow/category/types'; -import { ProcessDefinitionQuery, ProcessDefinitionVO } from '@/api/workflow/processDefinition/types'; -import { DefinitionConfigForm } from '@/api/workflow/definitionConfig/types'; -import { UploadRequestOptions, ElMessage, ElMessageBox } from 'element-plus'; +import { listDefinition, deleteDefinition, active, importDef, unPublishList, publish, add, edit, getInfo, copy } from '@/api/workflow/definition'; +import { categoryTree } from '@/api/workflow/category'; +import { CategoryTreeVO } from '@/api/workflow/category/types'; +import { FlowDefinitionQuery, FlowDefinitionVo, FlowDefinitionForm } from '@/api/workflow/definition/types'; +import { UploadRequestOptions, TabsPaneContext } from 'element-plus'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; -const previewRef = ref<InstanceType<typeof ProcessPreview>>(); const queryFormRef = ref<ElFormInstance>(); const categoryTreeRef = ref<ElTreeInstance>(); -const definitionConfigForm = ref<DefinitionConfigForm>({}); - -type CategoryOption = { - categoryCode: string; - categoryName: string; - children?: CategoryOption[]; -}; const loading = ref(true); const ids = ref<Array<any>>([]); -const deploymentIds = ref<Array<any>>([]); -const keys = ref<Array<any>>([]); +const flowCodeList = ref<Array<any>>([]); const single = ref(true); const multiple = ref(true); const showSearch = ref(true); const total = ref(0); const uploadDialogLoading = ref(false); -const processDefinitionList = ref<ProcessDefinitionVO[]>([]); -const processDefinitionHistoryList = ref<ProcessDefinitionVO[]>([]); -const categoryOptions = ref<CategoryOption[]>([]); +const processDefinitionList = ref<FlowDefinitionVo[]>([]); +const categoryOptions = ref<CategoryTreeVO[]>([]); const categoryName = ref(''); /** 閮ㄧ讲鏂囦欢鍒嗙被閫夋嫨 */ const selectCategory = ref(); - +const defFormRef = ref<ElFormInstance>(); +const activeName = ref('0'); const uploadDialog = reactive<DialogOption>({ visible: false, title: '閮ㄧ讲娴佺▼鏂囦欢' @@ -308,30 +227,49 @@ title: '鍘嗗彶鐗堟湰' }); -const definitionConfigDialog = reactive<DialogOption>({ +const modelDialog = reactive<DialogOption>({ visible: false, - title: '娴佺▼瀹氫箟閰嶇疆' + title: '' }); // 鏌ヨ鍙傛暟 -const queryParams = ref<ProcessDefinitionQuery>({ +const queryParams = ref<FlowDefinitionQuery>({ pageNum: 1, pageSize: 10, - name: undefined, - key: undefined, - categoryCode: undefined + flowName: undefined, + flowCode: undefined, + category: undefined }); - +const rules = { + category: [{ required: true, message: '鍒嗙被鍚嶇О涓嶈兘涓虹┖', trigger: 'blur' }], + flowName: [{ required: true, message: '娴佺▼瀹氫箟鍚嶇О涓嶈兘涓虹┖', trigger: 'blur' }], + flowCode: [{ required: true, message: '娴佺▼瀹氫箟缂栫爜涓嶈兘涓虹┖', trigger: 'blur' }] +}; +const initFormData: FlowDefinitionForm = { + id: '', + flowName: '', + flowCode: '', + category: '', + formPath: '' +}; +//娴佺▼瀹氫箟鍙傛暟 +const form = ref<FlowDefinitionForm>({ + id: '', + flowName: '', + flowCode: '', + category: '', + formPath: '' +}); onMounted(() => { - getList(); + handleQuery(); getTreeselect(); }); /** 鑺傜偣鍗曞嚮浜嬩欢 */ -const handleNodeClick = (data: CategoryVO) => { - queryParams.value.categoryCode = data.categoryCode; - if (data.categoryCode === 'ALL') { - queryParams.value.categoryCode = ''; +const handleNodeClick = (data: CategoryTreeVO) => { + queryParams.value.category = data.id; + if (data.id === '0') { + queryParams.value.category = ''; } handleQuery(); }; @@ -352,22 +290,27 @@ /** 鏌ヨ娴佺▼鍒嗙被涓嬫媺鏍戠粨鏋� */ const getTreeselect = async () => { - const res = await listCategory(); - categoryOptions.value = []; - const data: CategoryOption = { categoryCode: 'ALL', categoryName: '椤剁骇鑺傜偣', children: [] }; - data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId'); - categoryOptions.value.push(data); + const res = await categoryTree(); + categoryOptions.value = res.data; }; - +const handleClick = (tab: TabsPaneContext, event: Event) => { + // v-model澶勭悊鏈夊欢杩� 闇�瑕佹墜鍔ㄥ鐞� + activeName.value = tab.index; + handleQuery(); +}; /** 鎼滅储鎸夐挳鎿嶄綔 */ const handleQuery = () => { queryParams.value.pageNum = 1; - getList(); + if (activeName.value === '0') { + getList(); + } else { + getUnPublishList(); + } }; /** 閲嶇疆鎸夐挳鎿嶄綔 */ const resetQuery = () => { queryFormRef.value?.resetFields(); - queryParams.value.categoryCode = ''; + queryParams.value.category = ''; queryParams.value.pageNum = 1; queryParams.value.pageSize = 10; handleQuery(); @@ -375,73 +318,70 @@ // 澶氶�夋閫変腑鏁版嵁 const handleSelectionChange = (selection: any) => { ids.value = selection.map((item: any) => item.id); - deploymentIds.value = selection.map((item: any) => item.deploymentId); - keys.value = selection.map((item: any) => item.key); + flowCodeList.value = selection.map((item: any) => item.flowCode); single.value = selection.length !== 1; multiple.value = !selection.length; }; //鍒嗛〉 const getList = async () => { loading.value = true; - const resp = await listProcessDefinition(queryParams.value); + const resp = await listDefinition(queryParams.value); processDefinitionList.value = resp.rows; total.value = resp.total; loading.value = false; }; -//鑾峰彇鍘嗗彶娴佺▼瀹氫箟 -const getProcessDefinitionHitoryList = async (id: string, key: string) => { - processDefinitionDialog.visible = true; +//鏌ヨ鏈彂甯冪殑娴佺▼瀹氫箟鍒楄〃 +const getUnPublishList = async () => { loading.value = true; - const resp = await getListByKey(key); - if (resp.data && resp.data.length > 0) { - processDefinitionHistoryList.value = resp.data.filter((item: any) => item.id !== id); - } + const resp = await unPublishList(queryParams.value); + processDefinitionList.value = resp.rows; + total.value = resp.total; loading.value = false; }; -type PreviewType = 'xml' | 'bpmn'; -//棰勮 鍏叡鏂规硶 -const clickPreview = async (id: string, type: PreviewType) => { - loading.value = true; - const resp = await definitionXml(id); - if (previewRef.value) { - const xmlStr = resp.data.xmlStr; - loading.value = false; - previewRef.value.openDialog(xmlStr, type); - } -}; - /** 鍒犻櫎鎸夐挳鎿嶄綔 */ -const handleDelete = async (row?: ProcessDefinitionVO) => { +const handleDelete = async (row?: FlowDefinitionVo) => { const id = row?.id || ids.value; - const deployIds = row?.deploymentId || deploymentIds.value; - const defKeys = row?.key || keys.value; - await proxy?.$modal.confirm('鏄惁纭鍒犻櫎娴佺▼瀹氫箟KEY涓恒��' + defKeys + '銆戠殑鏁版嵁椤癸紵'); + const defList = processDefinitionList.value.filter((x) => id.indexOf(x.id) != -1).map((x) => x.flowCode); + await proxy?.$modal.confirm('鏄惁纭鍒犻櫎娴佺▼瀹氫箟KEY涓恒��' + defList + '銆戠殑鏁版嵁椤癸紵'); loading.value = true; - await deleteProcessDefinition(deployIds, id).finally(() => (loading.value = false)); - await getList(); + await deleteDefinition(id).finally(() => (loading.value = false)); + await handleQuery(); proxy?.$modal.msgSuccess('鍒犻櫎鎴愬姛'); }; -/** 鎸傝捣/婵�娲� */ -const handleProcessDefState = async (row: ProcessDefinitionVO) => { - let msg: string; - if (row.suspensionState === 1) { - msg = `鏆傚仠鍚庯紝姝ゆ祦绋嬩笅鐨勬墍鏈変换鍔¢兘涓嶅厑璁稿線鍚庢祦杞紝鎮ㄧ‘瀹氭寕璧枫��${row.name || row.key}銆戝悧锛焋; - } else { - msg = `鍚姩鍚庯紝姝ゆ祦绋嬩笅鐨勬墍鏈変换鍔¢兘鍏佽寰�鍚庢祦杞紝鎮ㄧ‘瀹氭縺娲汇��${row.name || row.key}銆戝悧锛焋; - } - await proxy?.$modal.confirm(msg); + +/** 鍙戝竷娴佺▼瀹氫箟 */ +const handlePublish = async (row?: FlowDefinitionVo) => { + await proxy?.$modal.confirm( + '鏄惁纭鍙戝竷娴佺▼瀹氫箟KEY涓恒��' + row.flowCode + '銆戠増鏈负銆�' + row.version + '銆戠殑鏁版嵁椤癸紵锛屽彂甯冨悗浼氬皢宸插彂甯冩祦绋嬪畾涔夋敼涓哄け鏁堬紒' + ); loading.value = true; - await updateDefinitionState(row.id).finally(() => (loading.value = false)); - await getList(); - proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); + await publish(row.id).finally(() => (loading.value = false)); + processDefinitionDialog.visible = false; + activeName.value = "0" + await handleQuery(); + proxy?.$modal.msgSuccess('鍙戝竷鎴愬姛'); }; -/** 娴佺▼瀹氫箟杞崲涓烘ā鍨� */ -const handleConvertToModel = async (row: ProcessDefinitionVO) => { - await proxy?.$modal.confirm('鏄惁纭杞崲娴佺▼瀹氫箟key涓恒��' + row.key + '銆戠殑鏁版嵁椤癸紵'); - await convertToModel(row.id).finally(() => (loading.value = false)); - getList(); - proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); +/** 鎸傝捣/婵�娲� */ +const handleProcessDefState = async (row: FlowDefinitionVo, status: number | string | boolean) => { + let msg: string; + if (status === 0) { + msg = `鏆傚仠鍚庯紝姝ゆ祦绋嬩笅鐨勬墍鏈変换鍔¢兘涓嶅厑璁稿線鍚庢祦杞紝鎮ㄧ‘瀹氭寕璧枫��${row.flowName || row.flowCode}銆戝悧锛焋; + } else { + msg = `鍚姩鍚庯紝姝ゆ祦绋嬩笅鐨勬墍鏈変换鍔¢兘鍏佽寰�鍚庢祦杞紝鎮ㄧ‘瀹氭縺娲汇��${row.flowName || row.flowCode}銆戝悧锛焋; + } + try { + loading.value = true; + await proxy?.$modal.confirm(msg); + await active(row.id, !!status); + await handleQuery(); + proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); + } catch (error) { + row.activityStatus = status === 0 ? 1 : 0; + console.error(error); + } finally { + loading.value = false; + } }; //涓婁紶鏂囦欢鍓嶇殑閽╁瓙 @@ -456,15 +396,16 @@ } }; //閮ㄧ讲鏂囦欢 -const handerDeployProcessFile = (data: UploadRequestOptions): XMLHttpRequest => { +const handlerImportDefinition = (data: UploadRequestOptions): XMLHttpRequest => { let formData = new FormData(); uploadDialogLoading.value = true; formData.append('file', data.file); - formData.append('categoryCode', selectCategory.value); - deployProcessFile(formData) + formData.append('category', selectCategory.value); + importDef(formData) .then(() => { uploadDialog.visible = false; proxy?.$modal.msgSuccess('閮ㄧ讲鎴愬姛'); + activeName.value = "1" handleQuery(); }) .finally(() => { @@ -472,46 +413,91 @@ }); return; }; -//鎵撳紑娴佺▼瀹氫箟閰嶇疆 -const handleDefinitionConfigOpen = async (row: ProcessDefinitionVO) => { - definitionConfigDialog.visible = true; - definitionConfigForm.value.processKey = row.key; - definitionConfigForm.value.definitionId = row.id; - definitionConfigForm.value.version = row.version; - const resp = await getByDefId(row.id); - if (resp.data) { - definitionConfigForm.value = resp.data; - } else { - definitionConfigForm.value.tableName = undefined; - definitionConfigForm.value.remark = undefined; - } -}; -//淇濆瓨琛ㄥ崟 -const handlerSaveForm = async () => { - getByTableNameNotDefId(definitionConfigForm.value.tableName, definitionConfigForm.value.definitionId).then((res) => { - if (res.data && res.data.length > 0) { - ElMessageBox.confirm('琛ㄥ悕宸茶銆�' + res.data[0].processKey + '銆戠増鏈瑅' + res.data[0].version + '.0缁戝畾纭鍚庡皢浼氬垹闄ょ粦瀹氱殑娴佺▼KEY!', '鎻愮ず', { - confirmButtonText: '纭', - cancelButtonText: '鍙栨秷', - type: 'warning' - }).then(() => { - saveOrUpdate(definitionConfigForm.value).then((resp) => { - if (resp.code === 200) { - proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); - definitionConfigDialog.visible = false; - getList(); - } - }); - }); - } else { - saveOrUpdate(definitionConfigForm.value).then((resp) => { - if (resp.code === 200) { - proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); - definitionConfigDialog.visible = false; - getList(); - } - }); +/** + * 璁捐娴佺▼ + * @param row + */ +const design = async (row: FlowDefinitionVo) => { + proxy.$router.push({ + path: `/workflow/design/index`, + query: { + definitionId: row.id, + disabled: false } }); }; + +/** + * 鏌ョ湅娴佺▼ + * @param row + */ +const designView = async (row: FlowDefinitionVo) => { + proxy.$router.push({ + path: `/workflow/design/index`, + query: { + definitionId: row.id, + disabled: true + } + }); +}; +/** 琛ㄥ崟閲嶇疆 */ +const reset = () => { + form.value = { ...initFormData }; + defFormRef.value?.resetFields(); +}; +/** + * 鏂板 + */ +const handleAdd = async () => { + reset(); + modelDialog.visible = true; + modelDialog.title = '鏂板娴佺▼'; +}; +/** 淇敼鎸夐挳鎿嶄綔 */ +const handleUpdate = async (row?: FlowDefinitionVo) => { + reset(); + const id = row?.id || ids.value[0]; + const res = await getInfo(id); + Object.assign(form.value, res.data); + modelDialog.visible = true; + modelDialog.title = '淇敼娴佺▼'; +}; + +const handleSubmit = async () => { + defFormRef.value.validate(async (valid: boolean) => { + if (valid) { + loading.value = true; + if (form.value.id) { + await edit(form.value).finally(() => loading.value = false); + } else { + await add(form.value).finally(() => loading.value = false); + } + proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); + modelDialog.visible = false; + handleQuery(); + } + }); +}; +//澶嶅埗 +const handleCopyDef = async (row: FlowDefinitionVo) => { + ElMessageBox.confirm(`鏄惁纭澶嶅埗銆�${row.flowCode}銆戠増鏈负銆�${row.version}銆戠殑娴佺▼瀹氫箟锛乣, '鎻愮ず', { + confirmButtonText: '纭', + cancelButtonText: '鍙栨秷', + type: 'warning' + }).then(() => { + loading.value = true; + copy(row.id).then((resp) => { + if (resp.code === 200) { + proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); + activeName.value = "1" + handleQuery(); + } + }).finally(() => loading.value = false); + }); +}; + +/** 瀵煎嚭鎸夐挳鎿嶄綔 */ +const handleExportDef = () => { + proxy?.download(`/workflow/definition/exportDef/${ids.value[0]}`, {}, `${flowCodeList.value[0]}.json`); +}; </script> diff --git a/src/views/workflow/processInstance/index.vue b/src/views/workflow/processInstance/index.vue index 7c60880..b58b189 100644 --- a/src/views/workflow/processInstance/index.vue +++ b/src/views/workflow/processInstance/index.vue @@ -10,7 +10,7 @@ class="mt-2" node-key="id" :data="categoryOptions" - :props="{ label: 'categoryName', children: 'children' }" + :props="{ label: 'label', children: 'children' }" :expand-on-click-node="false" :filter-node-method="filterNode" highlight-current @@ -20,23 +20,31 @@ </el-card> </el-col> <el-col :lg="20" :xs="24"> - <div class="mb-[10px]"> - <el-card shadow="hover" class="text-center"> - <el-radio-group v-model="tab" @change="changeTab(tab)"> - <el-radio-button value="running">杩愯涓�</el-radio-button> - <el-radio-button value="finish">宸插畬鎴�</el-radio-button> - </el-radio-group> - </el-card> - </div> + <!-- <div class="mb-[10px]"> + <el-card shadow="hover" class="text-center"> + <el-radio-group v-model="tab" @change="changeTab(tab)"> + <el-radio-button value="running">杩愯涓�</el-radio-button> + <el-radio-button value="finish">宸插畬鎴�</el-radio-button> + </el-radio-group> + </el-card> + </div>--> <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> <div v-show="showSearch" class="mb-[10px]"> <el-card shadow="hover"> - <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px"> - <el-form-item label="娴佺▼瀹氫箟鍚嶇О" prop="name"> - <el-input v-model="queryParams.name" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夊悕绉�" @keyup.enter="handleQuery" /> + <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true"> + <el-form-item> + <el-badge :value="userSelectCount" :max="10" class="item"> + <el-button type="primary" @click="openUserSelect">閫夋嫨鐢宠浜�</el-button> + </el-badge> </el-form-item> - <el-form-item label="娴佺▼瀹氫箟KEY" prop="key"> - <el-input v-model="queryParams.key" placeholder="璇疯緭鍏ユ祦绋嬪畾涔塊EY" @keyup.enter="handleQuery" /> + <el-form-item label="浠诲姟鍚嶇О" prop="nodeName"> + <el-input v-model="queryParams.nodeName" placeholder="璇疯緭鍏ヤ换鍔″悕绉�" @keyup.enter="handleQuery" /> + </el-form-item> + <el-form-item label="娴佺▼瀹氫箟鍚嶇О" label-width="100" prop="flowName"> + <el-input v-model="queryParams.flowName" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夊悕绉�" @keyup.enter="handleQuery" /> + </el-form-item> + <el-form-item label="娴佺▼瀹氫箟缂栫爜" label-width="100" prop="flowCode"> + <el-input v-model="queryParams.flowCode" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夌紪鐮�" @keyup.enter="handleQuery" /> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button> @@ -52,69 +60,77 @@ <el-col :span="1.5"> <el-button type="danger" plain icon="Delete" :disabled="multiple" @click="handleDelete">鍒犻櫎</el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="handleQuery"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar> </el-row> </template> - - <el-table v-loading="loading" border :data="processInstanceList" @selection-change="handleSelectionChange"> - <el-table-column type="selection" width="55" align="center" /> - <el-table-column align="center" type="index" label="搴忓彿" width="60"></el-table-column> - <el-table-column :show-overflow-tooltip="true" align="center" label="娴佺▼瀹氫箟鍚嶇О"> - <template #default="scope"> - <span>{{ scope.row.processDefinitionName }}v{{ scope.row.processDefinitionVersion }}.0</span> - </template> - </el-table-column> - <el-table-column align="center" prop="processDefinitionKey" label="娴佺▼瀹氫箟KEY"></el-table-column> - <el-table-column align="center" prop="processDefinitionVersion" label="鐗堟湰鍙�" width="90"> - <template #default="scope"> v{{ scope.row.processDefinitionVersion }}.0</template> - </el-table-column> - <el-table-column v-if="tab === 'running'" align="center" prop="isSuspended" label="鐘舵��" min-width="70"> - <template #default="scope"> - <el-tag v-if="!scope.row.isSuspended" type="success">婵�娲�</el-tag> - <el-tag v-else type="danger">鎸傝捣</el-tag> - </template> - </el-table-column> - <el-table-column align="center" label="娴佺▼鐘舵��" min-width="70"> - <template #default="scope"> - <dict-tag :options="wf_business_status" :value="scope.row.businessStatus"></dict-tag> - </template> - </el-table-column> - <el-table-column align="center" prop="startTime" label="鍚姩鏃堕棿" width="160"></el-table-column> - <el-table-column v-if="tab === 'finish'" align="center" prop="endTime" label="缁撴潫鏃堕棿" width="160"></el-table-column> - <el-table-column label="鎿嶄綔" align="center" :width="130"> - <template #default="scope"> - <el-row v-if="tab === 'running'" :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-popover :ref="`popoverRef${scope.$index}`" trigger="click" placement="left" :width="300"> - <el-input v-model="deleteReason" resize="none" :rows="3" type="textarea" placeholder="璇疯緭鍏ヤ綔搴熷師鍥�" /> - <div style="text-align: right; margin: 5px 0px 0px 0px"> - <el-button size="small" text @click="cancelPopover(scope.$index)">鍙栨秷</el-button> - <el-button size="small" type="primary" @click="handleInvalid(scope.row)">纭</el-button> - </div> - <template #reference> - <el-button link type="primary" size="small" icon="CircleClose">浣滃簾</el-button> - </template> - </el-popover> - </el-col> - <el-col :span="1.5"> - <el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">鍒犻櫎</el-button> - </el-col> - </el-row> - <el-row :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-button link type="primary" size="small" icon="View" @click="handleView(scope.row)">鏌ョ湅</el-button> - </el-col> - </el-row> - </template> - </el-table-column> - </el-table> - <pagination - v-show="total > 0" - v-model:page="queryParams.pageNum" - v-model:limit="queryParams.pageSize" - :total="total" - @pagination="handleQuery" - /> + <el-tabs v-model="tab" @tab-click="changeTab"> + <el-tab-pane name="running" label="杩愯涓�"></el-tab-pane> + <el-tab-pane name="finish" label="宸插畬鎴�"></el-tab-pane> + <el-table v-loading="loading" border :data="processInstanceList" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" align="center" /> + <el-table-column align="center" type="index" label="搴忓彿" width="60"></el-table-column> + <el-table-column :show-overflow-tooltip="true" align="center" label="娴佺▼瀹氫箟鍚嶇О"> + <template #default="scope"> + <span>{{ scope.row.flowName }}v{{ scope.row.version }}</span> + </template> + </el-table-column> + <el-table-column align="center" prop="nodeName" label="浠诲姟鍚嶇О"></el-table-column> + <el-table-column align="center" prop="flowCode" label="娴佺▼瀹氫箟缂栫爜"></el-table-column> + <el-table-column align="center" prop="createByName" label="鐢宠浜�"></el-table-column> + <el-table-column align="center" prop="version" label="鐗堟湰鍙�" width="90"> + <template #default="scope"> v{{ scope.row.version }}.0</template> + </el-table-column> + <el-table-column v-if="tab === 'running'" align="center" prop="isSuspended" label="鐘舵��" min-width="70"> + <template #default="scope"> + <el-tag v-if="!scope.row.isSuspended" type="success">婵�娲�</el-tag> + <el-tag v-else type="danger">鎸傝捣</el-tag> + </template> + </el-table-column> + <el-table-column align="center" label="娴佺▼鐘舵��" min-width="70"> + <template #default="scope"> + <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag> + </template> + </el-table-column> + <el-table-column align="center" prop="createTime" label="鍚姩鏃堕棿" width="160"></el-table-column> + <el-table-column v-if="tab === 'finish'" align="center" prop="updateTime" label="缁撴潫鏃堕棿" width="160"></el-table-column> + <el-table-column label="鎿嶄綔" align="center" :width="165"> + <template #default="scope"> + <el-row v-if="tab === 'running'" :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-popover :ref="`popoverRef${scope.$index}`" trigger="click" placement="left" :width="300"> + <el-input v-model="deleteReason" resize="none" :rows="3" type="textarea" placeholder="璇疯緭鍏ヤ綔搴熷師鍥�" /> + <div style="text-align: right; margin: 5px 0px 0px 0px"> + <el-button size="small" text @click="cancelPopover(scope.$index)">鍙栨秷</el-button> + <el-button size="small" type="primary" @click="handleInvalid(scope.row)">纭</el-button> + </div> + <template #reference> + <el-button type="danger" size="small" icon="CircleClose">浣滃簾</el-button> + </template> + </el-popover> + </el-col> + <el-col :span="1.5"> + <el-button type="danger" size="small" icon="Delete" @click="handleDelete(scope.row)">鍒犻櫎 </el-button> + </el-col> + </el-row> + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">鏌ョ湅</el-button> + </el-col> + <el-col :span="1.5"> + <el-button type="primary" size="small" icon="Document" @click="handleInstanceVariable(scope.row)"> 鍙橀噺 </el-button> + </el-col> + </el-row> + </template> + </el-table-column> + </el-table> + <pagination + v-show="total > 0" + v-model:page="queryParams.pageNum" + v-model:limit="queryParams.pageSize" + :total="total" + @pagination="handleQuery" + /> + </el-tabs> </el-card> </el-col> </el-row> @@ -122,6 +138,7 @@ <el-table v-loading="loading" :data="processDefinitionHistoryList"> <el-table-column fixed align="center" type="index" label="搴忓彿" width="60"></el-table-column> <el-table-column fixed align="center" prop="name" label="娴佺▼瀹氫箟鍚嶇О"></el-table-column> + <el-table-column fixed align="center" prop="nodeName" label="浠诲姟鍚嶇О"></el-table-column> <el-table-column align="center" prop="key" label="鏍囪瘑Key"></el-table-column> <el-table-column align="center" prop="version" label="鐗堟湰鍙�" width="90"> <template #default="scope"> v{{ scope.row.version }}.0</template> @@ -133,42 +150,55 @@ </template> </el-table-column> <el-table-column align="center" prop="deploymentTime" label="閮ㄧ讲鏃堕棿" :show-overflow-tooltip="true"></el-table-column> - <el-table-column fixed="right" label="鎿嶄綔" align="center" width="200" class-name="small-padding fixed-width"> - <template #default="scope"> - <el-button link type="primary" size="small" icon="Sort" @click="handleChange(scope.row.id)">鍒囨崲</el-button> - </template> - </el-table-column> </el-table> </el-dialog> + <!-- 娴佺▼鍙橀噺寮�濮� --> + <el-dialog v-model="variableVisible" draggable title="娴佺▼鍙橀噺" width="60%" :close-on-click-modal="false"> + <el-card v-loading="variableLoading" class="box-card"> + <template #header> + <div class="clearfix"> + <span + >娴佺▼瀹氫箟鍚嶇О锛�<el-tag>{{ processDefinitionName }}</el-tag></span + > + </div> + </template> + <div class="max-h-500px overflow-y-auto"> + <VueJsonPretty :data="formatToJsonObject(variables)" /> + </div> + </el-card> + </el-dialog> + <!-- 娴佺▼鍙橀噺缁撴潫 --> + + <!-- 鐢宠浜� --> + <UserSelect ref="userSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect> </div> </template> <script lang="ts" setup> -import { - getPageByRunning, - getPageByFinish, - deleteRunAndHisInstance, - deleteFinishAndHisInstance, - deleteRunInstance -} from '@/api/workflow/processInstance'; -import { getListByKey, migrationDefinition } from '@/api/workflow/processDefinition'; -import { listCategory } from '@/api/workflow/category'; -import { CategoryVO } from '@/api/workflow/category/types'; -import { ProcessInstanceQuery, ProcessInstanceVO } from '@/api/workflow/processInstance/types'; +import { pageByRunning, pageByFinish, deleteByInstanceIds, instanceVariable, invalid } from '@/api/workflow/instance'; +import { categoryTree } from '@/api/workflow/category'; +import { CategoryTreeVO } from '@/api/workflow/category/types'; +import { FlowInstanceQuery, FlowInstanceVO } from '@/api/workflow/instance/types'; import workflowCommon from '@/api/workflow/workflowCommon'; import { RouterJumpVo } from '@/api/workflow/workflowCommon/types'; +import VueJsonPretty from 'vue-json-pretty'; +import 'vue-json-pretty/lib/styles.css'; +import UserSelect from '@/components/UserSelect/index.vue'; //瀹℃壒璁板綍缁勪欢 const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status')); const queryFormRef = ref<ElFormInstance>(); const categoryTreeRef = ref<ElTreeInstance>(); +import { ref } from 'vue'; +import { UserVO } from '@/api/system/user/types'; +const userSelectRef = ref<InstanceType<typeof UserSelect>>(); // 閬僵灞� const loading = ref(true); // 閫変腑鏁扮粍 const ids = ref<Array<any>>([]); -// 閫変腑涓氬姟id鏁扮粍 -const businessKeys = ref<Array<any>>([]); +// 閫変腑瀹炰緥id鏁扮粍 +const instanceIds = ref<Array<number | string>>([]); // 闈炲崟涓鐢� const single = ref(true); // 闈炲涓鐢� @@ -177,10 +207,15 @@ const showSearch = ref(true); // 鎬绘潯鏁� const total = ref(0); -// 娴佺▼瀹氫箟id -const processDefinitionId = ref<string>(''); + +// 娴佺▼鍙橀噺鏄惁鏄剧ず +const variableVisible = ref(false); +const variableLoading = ref(true); +const variables = ref<string>(''); +//娴佺▼瀹氫箟鍚嶇О +const processDefinitionName = ref(); // 妯″瀷瀹氫箟琛ㄦ牸鏁版嵁 -const processInstanceList = ref<ProcessInstanceVO[]>([]); +const processInstanceList = ref<FlowInstanceVO[]>([]); const processDefinitionHistoryList = ref<Array<any>>([]); const categoryOptions = ref<CategoryOption[]>([]); const categoryName = ref(''); @@ -191,7 +226,7 @@ }); type CategoryOption = { - categoryCode: string; + id: string; categoryName: string; children?: CategoryOption[]; }; @@ -199,20 +234,27 @@ const tab = ref('running'); // 浣滃簾鍘熷洜 const deleteReason = ref(''); + +//鐢宠浜篿d +const selectUserIds = ref<Array<number | string>>([]); +//鐢宠浜洪�夋嫨鏁伴噺 +const userSelectCount = ref(0); // 鏌ヨ鍙傛暟 -const queryParams = ref<ProcessInstanceQuery>({ +const queryParams = ref<FlowInstanceQuery>({ pageNum: 1, pageSize: 10, - name: undefined, - key: undefined, - categoryCode: undefined + nodeName: undefined, + flowName: undefined, + flowCode: undefined, + createByIds: [], + category: undefined }); /** 鑺傜偣鍗曞嚮浜嬩欢 */ -const handleNodeClick = (data: CategoryVO) => { - queryParams.value.categoryCode = data.categoryCode; - if (data.categoryCode === 'ALL') { - queryParams.value.categoryCode = ''; +const handleNodeClick = (data: CategoryTreeVO) => { + queryParams.value.category = data.id; + if (data.id === '0') { + queryParams.value.category = ''; } handleQuery(); }; @@ -233,11 +275,8 @@ /** 鏌ヨ娴佺▼鍒嗙被涓嬫媺鏍戠粨鏋� */ const getTreeselect = async () => { - const res = await listCategory(); - categoryOptions.value = []; - const data: CategoryOption = { categoryCode: 'ALL', categoryName: '椤剁骇鑺傜偣', children: [] }; - data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId'); - categoryOptions.value.push(data); + const res = await categoryTree(); + categoryOptions.value = res.data; }; /** 鎼滅储鎸夐挳鎿嶄綔 */ @@ -251,22 +290,24 @@ /** 閲嶇疆鎸夐挳鎿嶄綔 */ const resetQuery = () => { queryFormRef.value?.resetFields(); - queryParams.value.categoryCode = ''; + queryParams.value.category = ''; queryParams.value.pageNum = 1; queryParams.value.pageSize = 10; + queryParams.value.createByIds = []; + userSelectCount.value = 0; handleQuery(); }; // 澶氶�夋閫変腑鏁版嵁 -const handleSelectionChange = (selection: ProcessInstanceVO[]) => { +const handleSelectionChange = (selection: FlowInstanceVO[]) => { ids.value = selection.map((item: any) => item.id); - businessKeys.value = selection.map((item: any) => item.businessKey); + instanceIds.value = selection.map((item: FlowInstanceVO) => item.id); single.value = selection.length !== 1; multiple.value = !selection.length; }; //鍒嗛〉 const getProcessInstanceRunningList = () => { loading.value = true; - getPageByRunning(queryParams.value).then((resp) => { + pageByRunning(queryParams.value).then((resp) => { processInstanceList.value = resp.rows; total.value = resp.total; loading.value = false; @@ -275,7 +316,7 @@ //鍒嗛〉 const getProcessInstanceFinishList = () => { loading.value = true; - getPageByFinish(queryParams.value).then((resp) => { + pageByFinish(queryParams.value).then((resp) => { processInstanceList.value = resp.rows; total.value = resp.total; loading.value = false; @@ -283,15 +324,15 @@ }; /** 鍒犻櫎鎸夐挳鎿嶄綔 */ -const handleDelete = async (row: any) => { - const businessKey = row.businessKey || businessKeys.value; - await proxy?.$modal.confirm('鏄惁纭鍒犻櫎涓氬姟id涓恒��' + businessKey + '銆戠殑鏁版嵁椤癸紵'); +const handleDelete = async (row: FlowInstanceVO) => { + const instanceIdList = row.id || instanceIds.value; + await proxy?.$modal.confirm('鏄惁纭鍒犻櫎锛�'); loading.value = true; if ('running' === tab.value) { - await deleteRunAndHisInstance(businessKey).finally(() => (loading.value = false)); + await deleteByInstanceIds(instanceIdList).finally(() => (loading.value = false)); getProcessInstanceRunningList(); } else { - await deleteFinishAndHisInstance(businessKey).finally(() => (loading.value = false)); + await deleteByInstanceIds(instanceIdList).finally(() => (loading.value = false)); getProcessInstanceFinishList(); } proxy?.$modal.msgSuccess('鍒犻櫎鎴愬姛'); @@ -299,22 +340,22 @@ const changeTab = async (data: string) => { processInstanceList.value = []; queryParams.value.pageNum = 1; - if ('running' === data) { + if ('running' === data.paneName) { getProcessInstanceRunningList(); } else { getProcessInstanceFinishList(); } }; /** 浣滃簾鎸夐挳鎿嶄綔 */ -const handleInvalid = async (row: ProcessInstanceVO) => { - await proxy?.$modal.confirm('鏄惁纭浣滃簾涓氬姟id涓恒��' + row.businessKey + '銆戠殑鏁版嵁椤癸紵'); +const handleInvalid = async (row: FlowInstanceVO) => { + await proxy?.$modal.confirm('鏄惁纭浣滃簾锛�'); loading.value = true; if ('running' === tab.value) { let param = { - businessKey: row.businessKey, - deleteReason: deleteReason.value + id: row.id, + comment: deleteReason.value }; - await deleteRunInstance(param).finally(() => (loading.value = false)); + await invalid(param).finally(() => (loading.value = false)); getProcessInstanceRunningList(); proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); } @@ -322,41 +363,53 @@ const cancelPopover = async (index: any) => { (proxy?.$refs[`popoverRef${index}`] as any).hide(); //鍏抽棴寮圭獥 }; -//鑾峰彇娴佺▼瀹氫箟 -const getProcessDefinitionHitoryList = (id: string, key: string) => { - processDefinitionDialog.visible = true; - processDefinitionId.value = id; - loading.value = true; - getListByKey(key).then((resp) => { - if (resp.data && resp.data.length > 0) { - processDefinitionHistoryList.value = resp.data.filter((item: any) => item.id !== id); - } - loading.value = false; - }); -}; -//鍒囨崲娴佺▼鐗堟湰 -const handleChange = async (id: string) => { - await proxy?.$modal.confirm('鏄惁纭鍒囨崲锛�'); - loading.value = true; - migrationDefinition(processDefinitionId.value, id).then((resp) => { - proxy?.$modal.msgSuccess('鎿嶄綔鎴愬姛'); - getProcessInstanceRunningList(); - processDefinitionDialog.visible = false; - loading.value = false; - }); -}; /** 鏌ョ湅鎸夐挳鎿嶄綔 */ const handleView = (row) => { const routerJumpVo = reactive<RouterJumpVo>({ - wfDefinitionConfigVo: row.wfDefinitionConfigVo, - wfNodeConfigVo: row.wfNodeConfigVo, - businessKey: row.businessKey, + businessId: row.businessId, taskId: row.id, - type: 'view' + type: 'view', + formCustom: row.formCustom, + formPath: row.formPath }); workflowCommon.routerJump(routerJumpVo, proxy); }; +//鏌ヨ娴佺▼鍙橀噺 +const handleInstanceVariable = async (row: FlowInstanceVO) => { + variableLoading.value = true; + variableVisible.value = true; + processDefinitionName.value = row.flowName; + let data = await instanceVariable(row.id); + variables.value = data.data.variable; + variableLoading.value = false; +}; + +/** + * json杞负瀵硅薄 + * @param data 鍘熷鏁版嵁 + */ +function formatToJsonObject(data: string) { + try { + return JSON.parse(data); + } catch (error) { + return data; + } +} + +//鎵撳紑鐢宠浜洪�夋嫨 +const openUserSelect = () => { + userSelectRef.value.open(); +}; +//纭閫夋嫨鐢宠浜� +const userSelectCallBack = (data: UserVO[]) => { + userSelectCount.value = 0; + if (data && data.length > 0) { + userSelectCount.value = data.length; + selectUserIds.value = data.map((item) => item.userId); + queryParams.value.createByIds = selectUserIds.value; + } +}; onMounted(() => { getProcessInstanceRunningList(); getTreeselect(); diff --git a/src/views/workflow/task/allTaskWaiting.vue b/src/views/workflow/task/allTaskWaiting.vue index fe530b8..1a01be2 100644 --- a/src/views/workflow/task/allTaskWaiting.vue +++ b/src/views/workflow/task/allTaskWaiting.vue @@ -1,25 +1,19 @@ <template> <div class="p-2"> - <div class="mb-[10px]"> - <el-card shadow="hover" class="text-center"> - <el-radio-group v-model="tab" @change="changeTab(tab)"> - <el-radio-button value="waiting">寰呭姙浠诲姟</el-radio-button> - <el-radio-button value="finish">宸插姙浠诲姟</el-radio-button> - </el-radio-group> - </el-card> - </div> <transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave"> <div v-show="showSearch" class="mb-[10px]"> <el-card shadow="hover"> <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true"> - <el-form-item label="浠诲姟鍚嶇О" prop="name"> - <el-input v-model="queryParams.name" placeholder="璇疯緭鍏ヤ换鍔″悕绉�" @keyup.enter="handleQuery" /> + <el-form-item> + <el-badge :value="userSelectCount" :max="10" class="item"> + <el-button type="primary" @click="openUserSelect">閫夋嫨鐢宠浜�</el-button> + </el-badge> </el-form-item> - <el-form-item label="娴佺▼瀹氫箟鍚嶇О" label-width="100" prop="processDefinitionName"> - <el-input v-model="queryParams.processDefinitionName" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夊悕绉�" @keyup.enter="handleQuery" /> + <el-form-item label="浠诲姟鍚嶇О" prop="nodeName"> + <el-input v-model="queryParams.nodeName" placeholder="璇疯緭鍏ヤ换鍔″悕绉�" @keyup.enter="handleQuery" /> </el-form-item> - <el-form-item label="娴佺▼瀹氫箟KEY" label-width="100" prop="processDefinitionKey"> - <el-input v-model="queryParams.processDefinitionKey" placeholder="璇疯緭鍏ユ祦绋嬪畾涔塊EY" @keyup.enter="handleQuery" /> + <el-form-item label="娴佺▼瀹氫箟鍚嶇О" label-width="100" prop="flowName"> + <el-input v-model="queryParams.flowName" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夊悕绉�" @keyup.enter="handleQuery" /> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button> @@ -32,122 +26,103 @@ <el-card shadow="hover"> <template #header> <el-row :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-button type="primary" plain icon="Edit" :disabled="multiple" @click="handleUpdate">淇敼鍔炵悊浜�</el-button> + <el-col :span="1.5" v-if="tab === 'waiting'"> + <el-button type="primary" plain icon="Edit" :disabled="multiple" @click="handleUpdate">淇敼鍔炵悊浜� </el-button> </el-col> - <right-toolbar v-model:showSearch="showSearch" @query-table="handleQuery"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar> </el-row> </template> - - <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange"> - <el-table-column type="selection" width="55" align="center" /> - <el-table-column align="center" type="index" label="搴忓彿" width="60"></el-table-column> - <el-table-column :show-overflow-tooltip="true" align="center" label="娴佺▼瀹氫箟鍚嶇О"> - <template #default="scope"> - <span>{{ scope.row.processDefinitionName }}v{{ scope.row.processDefinitionVersion }}.0</span> - </template> - </el-table-column> - <el-table-column align="center" prop="processDefinitionKey" label="娴佺▼瀹氫箟KEY"></el-table-column> - <el-table-column align="center" prop="name" label="浠诲姟鍚嶇О"></el-table-column> - <el-table-column align="center" prop="assigneeName" label="鍔炵悊浜�"> - <template v-if="tab === 'waiting'" #default="scope"> - <template v-if="scope.row.participantVo && scope.row.assignee === null"> - <el-tag v-for="(item, index) in scope.row.participantVo.candidateName" :key="index" type="success"> - {{ item }} - </el-tag> + <el-tabs v-model="tab" @tab-click="changeTab"> + <el-tab-pane name="waiting" label="寰呭姙浠诲姟"> </el-tab-pane> + <el-tab-pane name="finish" label="宸插姙浠诲姟"> </el-tab-pane> + <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange"> + <el-table-column type="selection" width="55" align="center" /> + <el-table-column align="center" type="index" label="搴忓彿" width="60"></el-table-column> + <el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="娴佺▼瀹氫箟鍚嶇О"></el-table-column> + <el-table-column align="center" prop="flowCode" label="娴佺▼瀹氫箟缂栫爜"></el-table-column> + <el-table-column align="center" prop="version" label="鐗堟湰鍙�" width="90"> + <template #default="scope"> v{{ scope.row.version }}.0</template> + </el-table-column> + <el-table-column align="center" prop="nodeName" label="浠诲姟鍚嶇О"></el-table-column> + <el-table-column align="center" prop="createByName" label="鐢宠浜�"></el-table-column> + <el-table-column align="center" label="鍔炵悊浜�"> + <template #default="scope"> + <template v-if="tab === 'waiting'"> + <template v-if="scope.row.assigneeNames"> + <el-tag v-for="(name, index) in scope.row.assigneeNames.split(',')" :key="index" type="success"> + {{ name }} + </el-tag> + </template> + <template v-else> + <el-tag type="success"> 鏃�</el-tag> + </template> + </template> + <template v-else> + <el-tag type="success"> {{ scope.row.approveName }}</el-tag> + </template> </template> - <template v-else> - <el-tag type="success"> - {{ scope.row.assigneeName || '鏃�' }} - </el-tag> + </el-table-column> + <el-table-column align="center" label="娴佺▼鐘舵��" prop="flowStatus" min-width="70"> + <template #default="scope"> + <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag> </template> - </template> - <template v-else-if="tab === 'finish'" #default="scope"> - <el-tag type="success"> - {{ scope.row.assigneeName || '鏃�' }} - </el-tag> - </template> - </el-table-column> - <el-table-column align="center" label="娴佺▼鐘舵��" min-width="70"> - <template #default="scope"> - <dict-tag v-if="tab === 'waiting'" :options="wf_business_status" :value="scope.row.businessStatus"></dict-tag> - <el-tag v-else type="success">宸插畬鎴�</el-tag> - </template> - </el-table-column> - <el-table-column v-if="tab === 'waiting'" align="center" prop="createTime" label="鍒涘缓鏃堕棿" width="160"></el-table-column> - <el-table-column v-if="tab === 'finish'" align="center" prop="startTime" label="鍒涘缓鏃堕棿" width="160"></el-table-column> - <el-table-column label="鎿嶄綔" align="center" :width="tab === 'finish' ? '80' : '151'"> - <template #default="scope"> - <el-row :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-button link type="primary" size="small" icon="View" @click="handleView(scope.row)">鏌ョ湅</el-button> - </el-col> - <el-col v-if="tab === 'waiting'" :span="1.5"> - <el-button link type="primary" size="small" icon="Document" @click="handleInstanceVariable(scope.row)">娴佺▼鍙橀噺</el-button> - </el-col> - </el-row> - <el-row v-if="scope.row.multiInstance" :gutter="10" class="mb8"> - <el-col :span="1.5"> - <el-button link type="primary" size="small" icon="Remove" @click="deleteMultiInstanceUser(scope.row)">鍑忕</el-button> - </el-col> - <el-col :span="1.5"> - <el-button link type="primary" size="small" icon="CirclePlus" @click="addMultiInstanceUser(scope.row)">鍔犵</el-button> - </el-col> - </el-row> - </template> - </el-table-column> - </el-table> - <pagination - v-show="total > 0" - v-model:page="queryParams.pageNum" - v-model:limit="queryParams.pageSize" - :total="total" - @pagination="handleQuery" - /> + </el-table-column> + <el-table-column v-if="tab === 'finish'" align="center" label="浠诲姟鐘舵��" prop="flowTaskStatus" min-width="70"> + <template #default="scope"> + <dict-tag :options="wf_task_status" :value="scope.row.flowTaskStatus"></dict-tag> + </template> + </el-table-column> + <el-table-column align="center" prop="createTime" label="鍒涘缓鏃堕棿" width="160"></el-table-column> + <el-table-column label="鎿嶄綔" align="center" :width="tab === 'finish' ? '88' : '188'"> + <template #default="scope"> + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5" v-if="tab === 'waiting' || tab === 'finish'"> + <el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">鏌ョ湅</el-button> + </el-col> + <el-col :span="1.5" v-if="tab === 'waiting'"> + <el-button type="primary" size="small" icon="Setting" @click="handleMeddle(scope.row)">娴佺▼骞查 </el-button> + </el-col> + </el-row> + </template> + </el-table-column> + </el-table> + <pagination + v-show="total > 0" + v-model:page="queryParams.pageNum" + v-model:limit="queryParams.pageSize" + :total="total" + @pagination="handleQuery" + /> + </el-tabs> </el-card> - <!-- 鍔犵缁勪欢 --> - <multiInstanceUser ref="multiInstanceUserRef" :title="title" @submit-callback="handleQuery" /> <!-- 閫変汉缁勪欢 --> <UserSelect ref="userSelectRef" :multiple="false" @confirm-call-back="submitCallback"></UserSelect> - <!-- 娴佺▼鍙橀噺寮�濮� --> - <el-dialog v-model="variableVisible" draggable title="娴佺▼鍙橀噺" width="60%" :close-on-click-modal="false"> - <el-card v-loading="variableLoading" class="box-card"> - <template #header> - <div class="clearfix"> - <span - >娴佺▼瀹氫箟鍚嶇О锛�<el-tag>{{ processDefinitionName }}</el-tag></span - > - </div> - </template> - <div v-for="(v, index) in variableList" :key="index"> - <el-form v-if="v.key !== '_FLOWABLE_SKIP_EXPRESSION_ENABLED'" :label-position="'right'" label-width="150px"> - <el-form-item :label="v.key + '锛�'"> - {{ v.value }} - </el-form-item> - </el-form> - </div> - </el-card> - </el-dialog> - <!-- 娴佺▼鍙橀噺缁撴潫 --> + <!-- 閫変汉缁勪欢 --> + <processMeddle ref="processMeddleRef" @submitCallback="getWaitingList"></processMeddle> + <!-- 鐢宠浜� --> + <UserSelect ref="applyUserSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect> </div> </template> <script lang="ts" setup> -import { getPageByAllTaskWait, getPageByAllTaskFinish, updateAssignee, getInstanceVariable } from '@/api/workflow/task'; -import MultiInstanceUser from '@/components/Process/multiInstanceUser.vue'; +import { pageByAllTaskWait, pageByAllTaskFinish, updateAssignee } from '@/api/workflow/task'; import UserSelect from '@/components/UserSelect'; -import { TaskQuery, TaskVO, VariableVo } from '@/api/workflow/task/types'; +import { TaskQuery } from '@/api/workflow/task/types'; import workflowCommon from '@/api/workflow/workflowCommon'; import { RouterJumpVo } from '@/api/workflow/workflowCommon/types'; -//瀹℃壒璁板綍缁勪欢 -//鍔犵缁勪欢 -const multiInstanceUserRef = ref<InstanceType<typeof MultiInstanceUser>>(); +import processMeddle from '@/components/Process/processMeddle'; +import { UserVO } from '@/api/system/user/types'; +import { TabsPaneContext } from 'element-plus'; //閫変汉缁勪欢 const userSelectRef = ref<InstanceType<typeof UserSelect>>(); - +//娴佺▼骞查缁勪欢 +const processMeddleRef = ref<InstanceType<typeof processMeddle>>(); +//閫変汉缁勪欢 +const applyUserSelectRef = ref<InstanceType<typeof UserSelect>>(); const queryFormRef = ref<ElFormInstance>(); const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status')); +const { wf_task_status } = toRefs<any>(proxy?.useDict('wf_task_status')); // 閬僵灞� const loading = ref(true); // 閫変腑鏁扮粍 @@ -163,40 +138,21 @@ // 妯″瀷瀹氫箟琛ㄦ牸鏁版嵁 const taskList = ref([]); const title = ref(''); -// 娴佺▼鍙橀噺鏄惁鏄剧ず -const variableVisible = ref(false); -const variableLoading = ref(true); -// 娴佺▼鍙橀噺 -const variableList = ref<VariableVo>({ - key: '', - value: '' -}); -//娴佺▼瀹氫箟鍚嶇О -const processDefinitionName = ref(); +//鐢宠浜篿d +const selectUserIds = ref<Array<number | string>>([]); +//鐢宠浜洪�夋嫨鏁伴噺 +const userSelectCount = ref(0); // 鏌ヨ鍙傛暟 const queryParams = ref<TaskQuery>({ pageNum: 1, pageSize: 10, - name: undefined, - processDefinitionName: undefined, - processDefinitionKey: undefined + nodeName: undefined, + flowName: undefined, + flowCode: undefined, + createByIds: [] }); const tab = ref('waiting'); -//鍔犵 -const addMultiInstanceUser = (row: TaskVO) => { - if (multiInstanceUserRef.value) { - title.value = '鍔犵浜哄憳'; - multiInstanceUserRef.value.getAddMultiInstanceList(row.id, []); - } -}; -//鍑忕 -const deleteMultiInstanceUser = (row: TaskVO) => { - if (multiInstanceUserRef.value) { - title.value = '鍑忕浜哄憳'; - multiInstanceUserRef.value.getDeleteMultiInstanceList(row.id); - } -}; /** 鎼滅储鎸夐挳鎿嶄綔 */ const handleQuery = () => { if ('waiting' === tab.value) { @@ -210,6 +166,8 @@ queryFormRef.value?.resetFields(); queryParams.value.pageNum = 1; queryParams.value.pageSize = 10; + queryParams.value.createByIds = []; + userSelectCount.value = 0; handleQuery(); }; // 澶氶�夋閫変腑鏁版嵁 @@ -218,10 +176,10 @@ single.value = selection.length !== 1; multiple.value = !selection.length; }; -const changeTab = async (data: string) => { +const changeTab = async (data: TabsPaneContext) => { taskList.value = []; queryParams.value.pageNum = 1; - if ('waiting' === data) { + if ('waiting' === data.paneName) { getWaitingList(); } else { getFinishList(); @@ -230,7 +188,7 @@ //鍒嗛〉 const getWaitingList = () => { loading.value = true; - getPageByAllTaskWait(queryParams.value).then((resp) => { + pageByAllTaskWait(queryParams.value).then((resp) => { taskList.value = resp.rows; total.value = resp.total; loading.value = false; @@ -238,7 +196,7 @@ }; const getFinishList = () => { loading.value = true; - getPageByAllTaskFinish(queryParams.value).then((resp) => { + pageByAllTaskFinish(queryParams.value).then((resp) => { taskList.value = resp.rows; total.value = resp.total; loading.value = false; @@ -260,26 +218,33 @@ proxy?.$modal.msgWarning('璇烽�夋嫨鐢ㄦ埛锛�'); } }; -//鏌ヨ娴佺▼鍙橀噺 -const handleInstanceVariable = async (row: TaskVO) => { - variableLoading.value = true; - variableVisible.value = true; - processDefinitionName.value = row.processDefinitionName; - let data = await getInstanceVariable(row.id); - variableList.value = data.data; - variableLoading.value = false; -}; /** 鏌ョ湅鎸夐挳鎿嶄綔 */ const handleView = (row) => { const routerJumpVo = reactive<RouterJumpVo>({ - wfDefinitionConfigVo: row.wfDefinitionConfigVo, - wfNodeConfigVo: row.wfNodeConfigVo, - businessKey: row.businessKey, + businessId: row.businessId, taskId: row.id, - type: 'view' + type: 'view', + formCustom: row.formCustom, + formPath: row.formPath }); workflowCommon.routerJump(routerJumpVo, proxy); }; +const handleMeddle = (row) => { + processMeddleRef.value.open(row.id); +}; +//鎵撳紑鐢宠浜洪�夋嫨 +const openUserSelect = () => { + applyUserSelectRef.value.open(); +}; +//纭閫夋嫨鐢宠浜� +const userSelectCallBack = (data: UserVO[]) => { + userSelectCount.value = 0; + if (data && data.length > 0) { + userSelectCount.value = data.length; + selectUserIds.value = data.map((item) => item.userId); + queryParams.value.createByIds = selectUserIds.value; + } +}; onMounted(() => { getWaitingList(); }); diff --git a/src/views/workflow/task/myDocument.vue b/src/views/workflow/task/myDocument.vue index 1bf5bbf..baee949 100644 --- a/src/views/workflow/task/myDocument.vue +++ b/src/views/workflow/task/myDocument.vue @@ -10,7 +10,7 @@ class="mt-2" node-key="id" :data="categoryOptions" - :props="{ label: 'categoryName', children: 'children' }" + :props="{ label: 'label', children: 'children' }" :expand-on-click-node="false" :filter-node-method="filterNode" highlight-current @@ -24,8 +24,8 @@ <div v-show="showSearch" class="mb-[10px]"> <el-card shadow="hover"> <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true" label-width="120px"> - <el-form-item label="娴佺▼瀹氫箟鍚嶇О" prop="name"> - <el-input v-model="queryParams.name" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夊悕绉�" @keyup.enter="handleQuery" /> + <el-form-item label="娴佺▼瀹氫箟缂栫爜" prop="flowCode"> + <el-input v-model="queryParams.flowCode" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夌紪鐮�" @keyup.enter="handleQuery" /> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button> @@ -38,7 +38,7 @@ <el-card shadow="hover"> <template #header> <el-row :gutter="10" class="mb8"> - <right-toolbar v-model:showSearch="showSearch" @query-table="handleQuery"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar> </el-row> </template> @@ -46,14 +46,10 @@ <el-table-column type="selection" width="55" align="center" /> <el-table-column align="center" type="index" label="搴忓彿" width="60"></el-table-column> <el-table-column v-if="false" align="center" prop="id" label="id"></el-table-column> - <el-table-column :show-overflow-tooltip="true" align="center" label="娴佺▼瀹氫箟鍚嶇О"> - <template #default="scope"> - <span>{{ scope.row.processDefinitionName }}v{{ scope.row.processDefinitionVersion }}.0</span> - </template> - </el-table-column> - <el-table-column align="center" prop="processDefinitionKey" label="娴佺▼瀹氫箟KEY"></el-table-column> - <el-table-column align="center" prop="processDefinitionVersion" label="鐗堟湰鍙�" width="90"> - <template #default="scope"> v{{ scope.row.processDefinitionVersion }}.0</template> + <el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="娴佺▼瀹氫箟鍚嶇О"> </el-table-column> + <el-table-column align="center" prop="flowCode" label="娴佺▼瀹氫箟缂栫爜"></el-table-column> + <el-table-column align="center" prop="version" label="鐗堟湰鍙�" width="90"> + <template #default="scope"> v{{ scope.row.version }}.0</template> </el-table-column> <el-table-column v-if="tab === 'running'" align="center" prop="isSuspended" label="鐘舵��" min-width="70"> <template #default="scope"> @@ -63,33 +59,30 @@ </el-table-column> <el-table-column align="center" label="娴佺▼鐘舵��" min-width="70"> <template #default="scope"> - <dict-tag :options="wf_business_status" :value="scope.row.businessStatus"></dict-tag> + <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag> </template> </el-table-column> - <el-table-column align="center" prop="startTime" label="鍚姩鏃堕棿" width="160"></el-table-column> - <el-table-column v-if="tab === 'finish'" align="center" prop="endTime" label="缁撴潫鏃堕棿" width="160"></el-table-column> - <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width"> + <el-table-column align="center" prop="createTime" label="鍚姩鏃堕棿" width="160"></el-table-column> + <el-table-column label="鎿嶄綔" align="center" width="162"> <template #default="scope"> - <el-tooltip - v-if="scope.row.businessStatus === 'draft' || scope.row.businessStatus === 'cancel' || scope.row.businessStatus === 'back'" - content="淇敼" - placement="top" - > - <el-button link type="primary" icon="Edit" @click="handleOpen(scope.row, 'update')"></el-button> - </el-tooltip> - <el-tooltip - v-if="scope.row.businessStatus === 'draft' || scope.row.businessStatus === 'cancel' || scope.row.businessStatus === 'back'" - content="鍒犻櫎" - placement="top" - > - <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button> - </el-tooltip> - <el-tooltip placement="top" content="鏌ョ湅"> - <el-button link type="primary" icon="View" @click="handleOpen(scope.row, 'view')"></el-button> - </el-tooltip> - <el-tooltip v-if="scope.row.businessStatus === 'waiting'" content="鎾ら攢" placement="top"> - <el-button link type="primary" icon="Notification" @click="handleCancelProcessApply(scope.row.businessKey)"></el-button> - </el-tooltip> + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5" v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'cancel' || scope.row.flowStatus === 'back'"> + <el-button type="primary" size="small" icon="Edit" @click="handleOpen(scope.row, 'update')">缂栬緫</el-button> + </el-col> + <el-col :span="1.5" v-if="scope.row.flowStatus === 'draft' || scope.row.flowStatus === 'cancel' || scope.row.flowStatus === 'back'"> + <el-button type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">鍒犻櫎</el-button> + </el-col> + </el-row> + <el-row :gutter="10" class="mb8"> + <el-col :span="1.5"> + <el-button type="primary" size="small" icon="View" @click="handleOpen(scope.row, 'view')">鏌ョ湅</el-button> + </el-col> + <el-col :span="1.5" v-if="scope.row.flowStatus === 'waiting'"> + <el-button type="primary" size="small" icon="Notification" @click="handleCancelProcessApply(scope.row.businessId)" + >鎾ら攢</el-button + > + </el-col> + </el-row> </template> </el-table-column> </el-table> @@ -109,10 +102,10 @@ </template> <script lang="ts" setup> -import { getPageByCurrent, deleteRunAndHisInstance, cancelProcessApply } from '@/api/workflow/processInstance'; -import { listCategory } from '@/api/workflow/category'; -import { CategoryVO } from '@/api/workflow/category/types'; -import { ProcessInstanceQuery, ProcessInstanceVO } from '@/api/workflow/processInstance/types'; +import { pageByCurrent, deleteByInstanceIds, cancelProcessApply } from '@/api/workflow/instance'; +import { categoryTree } from '@/api/workflow/category'; +import { CategoryTreeVO } from '@/api/workflow/category/types'; +import { FlowInstanceQuery, FlowInstanceVO } from '@/api/workflow/instance/types'; import workflowCommon from '@/api/workflow/workflowCommon'; import { RouterJumpVo } from '@/api/workflow/workflowCommon/types'; const { proxy } = getCurrentInstance() as ComponentInternalInstance; @@ -123,7 +116,8 @@ // 閬僵灞� const loading = ref(true); // 閫変腑鏁扮粍 -const businessKeys = ref<Array<any>>([]); +const businessIds = ref<Array<number | string>>([]); +const instanceIds = ref<Array<number | string>>([]); // 闈炲崟涓鐢� const single = ref(true); // 闈炲涓鐢� @@ -133,24 +127,18 @@ // 鎬绘潯鏁� const total = ref(0); // 妯″瀷瀹氫箟琛ㄦ牸鏁版嵁 -const processInstanceList = ref<ProcessInstanceVO[]>([]); +const processInstanceList = ref<FlowInstanceVO[]>([]); -const categoryOptions = ref<CategoryOption[]>([]); +const categoryOptions = ref<CategoryTreeVO[]>([]); const categoryName = ref(''); - -interface CategoryOption { - categoryCode: string; - categoryName: string; - children?: CategoryOption[]; -} const tab = ref('running'); // 鏌ヨ鍙傛暟 -const queryParams = ref<ProcessInstanceQuery>({ +const queryParams = ref<FlowInstanceQuery>({ pageNum: 1, pageSize: 10, - name: undefined, - categoryCode: undefined + flowCode: undefined, + category: undefined }); onMounted(() => { @@ -159,10 +147,10 @@ }); /** 鑺傜偣鍗曞嚮浜嬩欢 */ -const handleNodeClick = (data: CategoryVO) => { - queryParams.value.categoryCode = data.categoryCode; - if (data.categoryCode === 'ALL') { - queryParams.value.categoryCode = ''; +const handleNodeClick = (data: CategoryTreeVO) => { + queryParams.value.category = data.id; + if (data.id === '0') { + queryParams.value.category = ''; } handleQuery(); }; @@ -183,11 +171,8 @@ /** 鏌ヨ娴佺▼鍒嗙被涓嬫媺鏍戠粨鏋� */ const getTreeselect = async () => { - const res = await listCategory(); - categoryOptions.value = []; - const data: CategoryOption = { categoryCode: 'ALL', categoryName: '椤剁骇鑺傜偣', children: [] }; - data.children = proxy?.handleTree<CategoryOption>(res.data, 'id', 'parentId'); - categoryOptions.value.push(data); + const res = await categoryTree(); + categoryOptions.value = res.data; }; /** 鎼滅储鎸夐挳鎿嶄綔 */ @@ -197,21 +182,22 @@ /** 閲嶇疆鎸夐挳鎿嶄綔 */ const resetQuery = () => { queryFormRef.value?.resetFields(); - queryParams.value.categoryCode = ''; + queryParams.value.category = ''; queryParams.value.pageNum = 1; queryParams.value.pageSize = 10; handleQuery(); }; // 澶氶�夋閫変腑鏁版嵁 -const handleSelectionChange = (selection: ProcessInstanceVO[]) => { - businessKeys.value = selection.map((item: any) => item.businessKey); +const handleSelectionChange = (selection: FlowInstanceVO[]) => { + businessIds.value = selection.map((item: any) => item.businessId); + instanceIds.value = selection.map((item: FlowInstanceVO) => item.id); single.value = selection.length !== 1; multiple.value = !selection.length; }; //鍒嗛〉 const getList = () => { loading.value = true; - getPageByCurrent(queryParams.value).then((resp) => { + pageByCurrent(queryParams.value).then((resp) => { processInstanceList.value = resp.rows; total.value = resp.total; loading.value = false; @@ -219,23 +205,27 @@ }; /** 鍒犻櫎鎸夐挳鎿嶄綔 */ -const handleDelete = async (row: ProcessInstanceVO) => { - const businessKey = row.businessKey || businessKeys.value; - await proxy?.$modal.confirm('鏄惁纭鍒犻櫎涓氬姟id涓恒��' + businessKey + '銆戠殑鏁版嵁椤癸紵'); +const handleDelete = async (row: FlowInstanceVO) => { + const instanceIdList = row.id || instanceIds.value; + await proxy?.$modal.confirm('鏄惁纭鍒犻櫎锛�'); loading.value = true; if ('running' === tab.value) { - await deleteRunAndHisInstance(businessKey).finally(() => (loading.value = false)); + await deleteByInstanceIds(instanceIdList).finally(() => (loading.value = false)); getList(); } proxy?.$modal.msgSuccess('鍒犻櫎鎴愬姛'); }; /** 鎾ら攢鎸夐挳鎿嶄綔 */ -const handleCancelProcessApply = async (businessKey: string) => { +const handleCancelProcessApply = async (businessId: string) => { await proxy?.$modal.confirm('鏄惁纭鎾ら攢褰撳墠鍗曟嵁锛�'); loading.value = true; if ('running' === tab.value) { - await cancelProcessApply(businessKey).finally(() => (loading.value = false)); + let data = { + businessId: businessId, + message: '鐢宠浜烘挙閿�娴佺▼锛�' + }; + await cancelProcessApply(data).finally(() => (loading.value = false)); getList(); } proxy?.$modal.msgSuccess('鎾ら攢鎴愬姛'); @@ -244,11 +234,11 @@ //鍔炵悊 const handleOpen = async (row, type) => { const routerJumpVo = reactive<RouterJumpVo>({ - wfDefinitionConfigVo: row.wfDefinitionConfigVo, - wfNodeConfigVo: row.wfNodeConfigVo, - businessKey: row.businessKey, + businessId: row.businessId, taskId: row.id, - type: type + type: type, + formCustom: row.formCustom, + formPath: row.formPath }); workflowCommon.routerJump(routerJumpVo, proxy); }; diff --git a/src/views/workflow/task/taskCopyList.vue b/src/views/workflow/task/taskCopyList.vue index 7784a08..6224fff 100644 --- a/src/views/workflow/task/taskCopyList.vue +++ b/src/views/workflow/task/taskCopyList.vue @@ -4,14 +4,14 @@ <div v-show="showSearch" class="mb-[10px]"> <el-card shadow="hover"> <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true"> - <el-form-item label="浠诲姟鍚嶇О" prop="name"> - <el-input v-model="queryParams.name" placeholder="璇疯緭鍏ヤ换鍔″悕绉�" @keyup.enter="handleQuery" /> + <el-form-item label="浠诲姟鍚嶇О" prop="nodeName"> + <el-input v-model="queryParams.nodeName" placeholder="璇疯緭鍏ヤ换鍔″悕绉�" @keyup.enter="handleQuery" /> </el-form-item> - <el-form-item label="娴佺▼瀹氫箟鍚嶇О" label-width="100" prop="processDefinitionName"> - <el-input v-model="queryParams.processDefinitionName" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夊悕绉�" @keyup.enter="handleQuery" /> + <el-form-item label="娴佺▼瀹氫箟鍚嶇О" label-width="100" prop="flowName"> + <el-input v-model="queryParams.flowName" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夊悕绉�" @keyup.enter="handleQuery" /> </el-form-item> - <el-form-item label="娴佺▼瀹氫箟KEY" label-width="100" prop="processDefinitionKey"> - <el-input v-model="queryParams.processDefinitionKey" placeholder="璇疯緭鍏ユ祦绋嬪畾涔塊EY" @keyup.enter="handleQuery" /> + <el-form-item label="娴佺▼瀹氫箟缂栫爜" label-width="100" prop="flowCode"> + <el-input v-model="queryParams.flowCode" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夌紪鐮�" @keyup.enter="handleQuery" /> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button> @@ -24,37 +24,22 @@ <el-card shadow="hover"> <template #header> <el-row :gutter="10" class="mb8"> - <right-toolbar v-model:showSearch="showSearch" @query-table="handleQuery"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar> </el-row> </template> <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" align="center" /> <el-table-column align="center" type="index" label="搴忓彿" width="60"></el-table-column> - <el-table-column :show-overflow-tooltip="true" align="center" label="娴佺▼瀹氫箟鍚嶇О"> - <template #default="scope"> - <span>{{ scope.row.processDefinitionName }}v{{ scope.row.processDefinitionVersion }}.0</span> - </template> + <el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="娴佺▼瀹氫箟鍚嶇О"></el-table-column> + <el-table-column align="center" prop="flowCode" label="娴佺▼瀹氫箟KEY"></el-table-column> + <el-table-column align="center" prop="version" label="鐗堟湰鍙�" width="90"> + <template #default="scope"> v{{ scope.row.version }}.0</template> </el-table-column> - <el-table-column align="center" prop="processDefinitionKey" label="娴佺▼瀹氫箟KEY"></el-table-column> - <el-table-column align="center" prop="name" label="浠诲姟鍚嶇О"></el-table-column> - <el-table-column align="center" prop="assigneeName" label="鍔炵悊浜�"> - <template #default="scope"> - <template v-if="scope.row.participantVo && scope.row.assignee === null"> - <el-tag v-for="(item, index) in scope.row.participantVo.candidateName" :key="index" type="success"> - {{ item }} - </el-tag> - </template> - <template v-else> - <el-tag type="success"> - {{ scope.row.assigneeName || '鏃�' }} - </el-tag> - </template> - </template> - </el-table-column> + <el-table-column align="center" prop="nodeName" label="浠诲姟鍚嶇О"></el-table-column> <el-table-column align="center" label="娴佺▼鐘舵��" min-width="70"> <template #default="scope"> - <dict-tag :options="wf_business_status" :value="scope.row.businessStatus"></dict-tag> + <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag> </template> </el-table-column> <el-table-column label="鎿嶄綔" align="center" width="200"> @@ -75,7 +60,7 @@ </template> <script lang="ts" setup> -import { getPageByTaskCopy } from '@/api/workflow/task'; +import { pageByTaskCopy } from '@/api/workflow/task'; import { TaskQuery } from '@/api/workflow/task/types'; import workflowCommon from '@/api/workflow/workflowCommon'; import { RouterJumpVo } from '@/api/workflow/workflowCommon/types'; @@ -101,9 +86,9 @@ const queryParams = ref<TaskQuery>({ pageNum: 1, pageSize: 10, - name: undefined, - processDefinitionName: undefined, - processDefinitionKey: undefined + nodeName: undefined, + flowName: undefined, + flowCode: undefined }); /** 鎼滅储鎸夐挳鎿嶄綔 */ const handleQuery = () => { @@ -125,7 +110,7 @@ //鍒嗛〉 const getTaskCopyList = () => { loading.value = true; - getPageByTaskCopy(queryParams.value).then((resp) => { + pageByTaskCopy(queryParams.value).then((resp) => { taskList.value = resp.rows; total.value = resp.total; loading.value = false; @@ -135,11 +120,11 @@ /** 鏌ョ湅鎸夐挳鎿嶄綔 */ const handleView = (row) => { const routerJumpVo = reactive<RouterJumpVo>({ - wfDefinitionConfigVo: row.wfDefinitionConfigVo, - wfNodeConfigVo: row.wfNodeConfigVo, - businessKey: row.businessKey, + businessId: row.businessId, taskId: row.id, - type: 'view' + type: 'view', + formCustom: row.formCustom, + formPath: row.formPath }); workflowCommon.routerJump(routerJumpVo, proxy); }; diff --git a/src/views/workflow/task/taskFinish.vue b/src/views/workflow/task/taskFinish.vue index 155bd4f..298ddcf 100644 --- a/src/views/workflow/task/taskFinish.vue +++ b/src/views/workflow/task/taskFinish.vue @@ -4,14 +4,19 @@ <div v-show="showSearch" class="mb-[10px]"> <el-card shadow="hover"> <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true"> - <el-form-item label="浠诲姟鍚嶇О" prop="name"> - <el-input v-model="queryParams.name" placeholder="璇疯緭鍏ヤ换鍔″悕绉�" @keyup.enter="handleQuery" /> + <el-form-item> + <el-badge :value="userSelectCount" :max="10" class="item"> + <el-button type="primary" @click="openUserSelect">閫夋嫨鐢宠浜�</el-button> + </el-badge> </el-form-item> - <el-form-item label="娴佺▼瀹氫箟鍚嶇О" label-width="100" prop="processDefinitionName"> - <el-input v-model="queryParams.processDefinitionName" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夊悕绉�" @keyup.enter="handleQuery" /> + <el-form-item label="浠诲姟鍚嶇О" prop="nodeName"> + <el-input v-model="queryParams.nodeName" placeholder="璇疯緭鍏ヤ换鍔″悕绉�" @keyup.enter="handleQuery" /> </el-form-item> - <el-form-item label="娴佺▼瀹氫箟KEY" label-width="100" prop="processDefinitionKey"> - <el-input v-model="queryParams.processDefinitionKey" placeholder="璇疯緭鍏ユ祦绋嬪畾涔塊EY" @keyup.enter="handleQuery" /> + <el-form-item label="娴佺▼瀹氫箟鍚嶇О" label-width="100" prop="flowName"> + <el-input v-model="queryParams.flowName" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夊悕绉�" @keyup.enter="handleQuery" /> + </el-form-item> + <el-form-item label="娴佺▼瀹氫箟缂栫爜" label-width="100" prop="flowCode"> + <el-input v-model="queryParams.flowCode" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夌紪鐮�" @keyup.enter="handleQuery" /> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button> @@ -24,28 +29,38 @@ <el-card shadow="hover"> <template #header> <el-row :gutter="10" class="mb8"> - <right-toolbar v-model:showSearch="showSearch" @query-table="handleQuery"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar> </el-row> </template> <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" align="center" /> <el-table-column align="center" type="index" label="搴忓彿" width="60"></el-table-column> - <el-table-column :show-overflow-tooltip="true" align="center" label="娴佺▼瀹氫箟鍚嶇О"> - <template #default="scope"> - <span>{{ scope.row.processDefinitionName }}v{{ scope.row.processDefinitionVersion }}.0</span> - </template> + <el-table-column align="center" prop="flowName" label="娴佺▼瀹氫箟鍚嶇О"></el-table-column> + <el-table-column align="center" prop="flowCode" label="娴佺▼瀹氫箟缂栫爜"></el-table-column> + <el-table-column align="center" prop="version" label="鐗堟湰鍙�" width="90"> + <template #default="scope"> v{{ scope.row.version }}.0</template> </el-table-column> - <el-table-column align="center" prop="processDefinitionKey" label="娴佺▼瀹氫箟KEY"></el-table-column> - <el-table-column align="center" prop="name" label="浠诲姟鍚嶇О"></el-table-column> - <el-table-column align="center" prop="assigneeName" label="鍔炵悊浜�"> + <el-table-column align="center" prop="nodeName" label="浠诲姟鍚嶇О"></el-table-column> + <el-table-column align="center" prop="createByName" label="鐢宠浜�"></el-table-column> + <el-table-column align="center" prop="approverName" label="鍔炵悊浜�"> <template #default="scope"> <el-tag type="success"> - {{ scope.row.assigneeName || '鏃�' }} + {{ scope.row.approveName || '鏃�' }} </el-tag> </template> </el-table-column> - <el-table-column align="center" prop="startTime" label="鍒涘缓鏃堕棿" width="160"></el-table-column> + <el-table-column align="center" label="娴佺▼鐘舵��" prop="flowStatus" min-width="70"> + <template #default="scope"> + <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag> + </template> + </el-table-column> + <el-table-column align="center" label="浠诲姟鐘舵��" prop="flowTaskStatus" min-width="70"> + <template #default="scope"> + <dict-tag :options="wf_task_status" :value="scope.row.flowTaskStatus"></dict-tag> + </template> + </el-table-column> + <el-table-column align="center" prop="createTime" label="鍒涘缓鏃堕棿" width="160"></el-table-column> <el-table-column label="鎿嶄綔" align="center" width="200"> <template #default="scope"> <el-button type="primary" size="small" icon="View" @click="handleView(scope.row)">鏌ョ湅</el-button> @@ -60,17 +75,26 @@ @pagination="handleQuery" /> </el-card> + <!-- 鐢宠浜� --> + <UserSelect ref="userSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect> </div> </template> <script lang="ts" setup> -import { getPageByTaskFinish } from '@/api/workflow/task'; -import { TaskQuery, TaskVO } from '@/api/workflow/task/types'; +import { pageByTaskFinish } from '@/api/workflow/task'; +import { TaskQuery, FlowTaskVO } from '@/api/workflow/task/types'; import workflowCommon from '@/api/workflow/workflowCommon'; import { RouterJumpVo } from '@/api/workflow/workflowCommon/types'; //瀹℃壒璁板綍缁勪欢 const queryFormRef = ref<ElFormInstance>(); const { proxy } = getCurrentInstance() as ComponentInternalInstance; +const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status')); +const { wf_task_status } = toRefs<any>(proxy?.useDict('wf_task_status')); +import UserSelect from '@/components/UserSelect'; +import { ref } from 'vue'; +import { UserVO } from '@/api/system/user/types'; + +const userSelectRef = ref<InstanceType<typeof UserSelect>>(); // 閬僵灞� const loading = ref(true); // 閫変腑鏁扮粍 @@ -89,10 +113,15 @@ const queryParams = ref<TaskQuery>({ pageNum: 1, pageSize: 10, - name: undefined, - processDefinitionName: undefined, - processDefinitionKey: undefined + nodeName: undefined, + flowName: undefined, + flowCode: undefined, + createByIds: [] }); +//鐢宠浜篿d +const selectUserIds = ref<Array<number | string>>([]); +//鐢宠浜洪�夋嫨鏁伴噺 +const userSelectCount = ref(0); /** 鎼滅储鎸夐挳鎿嶄綔 */ const handleQuery = () => { getFinishList(); @@ -102,6 +131,8 @@ queryFormRef.value?.resetFields(); queryParams.value.pageNum = 1; queryParams.value.pageSize = 10; + queryParams.value.createByIds = []; + userSelectCount.value = 0; handleQuery(); }; // 澶氶�夋閫変腑鏁版嵁 @@ -112,24 +143,36 @@ }; const getFinishList = () => { loading.value = true; - getPageByTaskFinish(queryParams.value).then((resp) => { + pageByTaskFinish(queryParams.value).then((resp) => { taskList.value = resp.rows; total.value = resp.total; loading.value = false; }); }; /** 鏌ョ湅鎸夐挳鎿嶄綔 */ -const handleView = (row: TaskVO) => { +const handleView = (row: FlowTaskVO) => { const routerJumpVo = reactive<RouterJumpVo>({ - wfDefinitionConfigVo: row.wfDefinitionConfigVo, - wfNodeConfigVo: row.wfNodeConfigVo, - businessKey: row.businessKey, + businessId: row.businessId, taskId: row.id, - type: 'view' + type: 'view', + formCustom: row.formCustom, + formPath: row.formPath }); workflowCommon.routerJump(routerJumpVo, proxy); }; - +//鎵撳紑鐢宠浜洪�夋嫨 +const openUserSelect = () => { + userSelectRef.value.open(); +}; +//纭閫夋嫨鐢宠浜� +const userSelectCallBack = (data: UserVO[]) => { + userSelectCount.value = 0; + if (data && data.length > 0) { + userSelectCount.value = data.length; + selectUserIds.value = data.map((item) => item.userId); + queryParams.value.createByIds = selectUserIds.value; + } +}; onMounted(() => { getFinishList(); }); diff --git a/src/views/workflow/task/taskWaiting.vue b/src/views/workflow/task/taskWaiting.vue index dc6546a..876e335 100644 --- a/src/views/workflow/task/taskWaiting.vue +++ b/src/views/workflow/task/taskWaiting.vue @@ -4,14 +4,19 @@ <div v-show="showSearch" class="mb-[10px]"> <el-card shadow="hover"> <el-form v-show="showSearch" ref="queryFormRef" :model="queryParams" :inline="true"> - <el-form-item label="浠诲姟鍚嶇О" prop="name"> - <el-input v-model="queryParams.name" placeholder="璇疯緭鍏ヤ换鍔″悕绉�" @keyup.enter="handleQuery" /> + <el-form-item> + <el-badge :value="userSelectCount" :max="10" class="item"> + <el-button type="primary" @click="openUserSelect">閫夋嫨鐢宠浜�</el-button> + </el-badge> </el-form-item> - <el-form-item label="娴佺▼瀹氫箟鍚嶇О" label-width="100" prop="processDefinitionName"> - <el-input v-model="queryParams.processDefinitionName" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夊悕绉�" @keyup.enter="handleQuery" /> + <el-form-item label="浠诲姟鍚嶇О" prop="nodeName"> + <el-input v-model="queryParams.nodeName" placeholder="璇疯緭鍏ヤ换鍔″悕绉�" @keyup.enter="handleQuery" /> </el-form-item> - <el-form-item label="娴佺▼瀹氫箟KEY" label-width="100" prop="processDefinitionKey"> - <el-input v-model="queryParams.processDefinitionKey" placeholder="璇疯緭鍏ユ祦绋嬪畾涔塊EY" @keyup.enter="handleQuery" /> + <el-form-item label="娴佺▼瀹氫箟鍚嶇О" label-width="100" prop="flowName"> + <el-input v-model="queryParams.flowName" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夊悕绉�" @keyup.enter="handleQuery" /> + </el-form-item> + <el-form-item label="娴佺▼瀹氫箟缂栫爜" label-width="100" prop="flowCode"> + <el-input v-model="queryParams.flowCode" placeholder="璇疯緭鍏ユ祦绋嬪畾涔夌紪鐮�" @keyup.enter="handleQuery" /> </el-form-item> <el-form-item> <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button> @@ -24,37 +29,32 @@ <el-card shadow="hover"> <template #header> <el-row :gutter="10" class="mb8"> - <right-toolbar v-model:showSearch="showSearch" @query-table="handleQuery"></right-toolbar> + <right-toolbar v-model:show-search="showSearch" @query-table="handleQuery"></right-toolbar> </el-row> </template> <el-table v-loading="loading" border :data="taskList" @selection-change="handleSelectionChange"> <el-table-column type="selection" width="55" align="center" /> <el-table-column align="center" type="index" label="搴忓彿" width="60"></el-table-column> - <el-table-column :show-overflow-tooltip="true" align="center" label="娴佺▼瀹氫箟鍚嶇О"> + <el-table-column :show-overflow-tooltip="true" prop="flowName" align="center" label="娴佺▼瀹氫箟鍚嶇О"></el-table-column> + <el-table-column align="center" prop="flowCode" label="娴佺▼瀹氫箟缂栫爜"></el-table-column> + <el-table-column align="center" prop="nodeName" label="浠诲姟鍚嶇О"></el-table-column> + <el-table-column align="center" prop="createByName" label="鐢宠浜�"></el-table-column> + <el-table-column align="center" label="鍔炵悊浜�"> <template #default="scope"> - <span>{{ scope.row.processDefinitionName }}v{{ scope.row.processDefinitionVersion }}.0</span> - </template> - </el-table-column> - <el-table-column align="center" prop="processDefinitionKey" label="娴佺▼瀹氫箟KEY"></el-table-column> - <el-table-column align="center" prop="name" label="浠诲姟鍚嶇О"></el-table-column> - <el-table-column align="center" prop="assigneeName" label="鍔炵悊浜�"> - <template #default="scope"> - <template v-if="scope.row.participantVo && scope.row.assignee === null"> - <el-tag v-for="(item, index) in scope.row.participantVo.candidateName" :key="index" type="success"> - {{ item }} + <template v-if="scope.row.assigneeNames"> + <el-tag v-for="(name, index) in scope.row.assigneeNames.split(',')" :key="index" type="success"> + {{ name }} </el-tag> </template> <template v-else> - <el-tag type="success"> - {{ scope.row.assigneeName || '鏃�' }} - </el-tag> + <el-tag type="success"> 鏃�</el-tag> </template> </template> </el-table-column> - <el-table-column align="center" label="娴佺▼鐘舵��" min-width="70"> + <el-table-column align="center" label="娴佺▼鐘舵��" prop="flowStatusName" min-width="70"> <template #default="scope"> - <dict-tag :options="wf_business_status" :value="scope.row.businessStatus"></dict-tag> + <dict-tag :options="wf_business_status" :value="scope.row.flowStatus"></dict-tag> </template> </el-table-column> <el-table-column align="center" prop="createTime" label="鍒涘缓鏃堕棿" width="160"></el-table-column> @@ -72,16 +72,24 @@ @pagination="handleQuery" /> </el-card> + <!-- 鐢宠浜� --> + <UserSelect ref="userSelectRef" :multiple="true" :data="selectUserIds" @confirm-call-back="userSelectCallBack"></UserSelect> </div> </template> <script lang="ts" setup> -import { getPageByTaskWait } from '@/api/workflow/task'; -import { TaskQuery, TaskVO } from '@/api/workflow/task/types'; +import { pageByTaskWait } from '@/api/workflow/task'; +import { TaskQuery, FlowTaskVO } from '@/api/workflow/task/types'; import workflowCommon from '@/api/workflow/workflowCommon'; import { RouterJumpVo } from '@/api/workflow/workflowCommon/types'; + const { proxy } = getCurrentInstance() as ComponentInternalInstance; const { wf_business_status } = toRefs<any>(proxy?.useDict('wf_business_status')); +import UserSelect from '@/components/UserSelect'; +import { ref } from 'vue'; +import { UserVO } from '@/api/system/user/types'; + +const userSelectRef = ref<InstanceType<typeof UserSelect>>(); //鎻愪氦缁勪欢 const queryFormRef = ref<ElFormInstance>(); // 閬僵灞� @@ -98,13 +106,19 @@ const total = ref(0); // 妯″瀷瀹氫箟琛ㄦ牸鏁版嵁 const taskList = ref([]); + +//鐢宠浜篿d +const selectUserIds = ref<Array<number | string>>([]); +//鐢宠浜洪�夋嫨鏁伴噺 +const userSelectCount = ref(0); // 鏌ヨ鍙傛暟 const queryParams = ref<TaskQuery>({ pageNum: 1, pageSize: 10, - name: undefined, - processDefinitionName: undefined, - processDefinitionKey: undefined + nodeName: undefined, + flowName: undefined, + flowCode: undefined, + createByIds: [] }); onMounted(() => { getWaitingList(); @@ -118,6 +132,8 @@ queryFormRef.value?.resetFields(); queryParams.value.pageNum = 1; queryParams.value.pageSize = 10; + queryParams.value.createByIds = []; + userSelectCount.value = 0; handleQuery(); }; // 澶氶�夋閫変腑鏁版嵁 @@ -129,21 +145,34 @@ //鍒嗛〉 const getWaitingList = () => { loading.value = true; - getPageByTaskWait(queryParams.value).then((resp) => { + pageByTaskWait(queryParams.value).then((resp) => { taskList.value = resp.rows; total.value = resp.total; loading.value = false; }); }; //鍔炵悊 -const handleOpen = async (row: TaskVO) => { +const handleOpen = async (row: FlowTaskVO) => { const routerJumpVo = reactive<RouterJumpVo>({ - wfDefinitionConfigVo: row.wfDefinitionConfigVo, - wfNodeConfigVo: row.wfNodeConfigVo, - businessKey: row.businessKey, + businessId: row.businessId, taskId: row.id, - type: 'approval' + type: 'approval', + formCustom: row.formCustom, + formPath: row.formPath }); workflowCommon.routerJump(routerJumpVo, proxy); }; +//鎵撳紑鐢宠浜洪�夋嫨 +const openUserSelect = () => { + userSelectRef.value.open(); +}; +//纭閫夋嫨鐢宠浜� +const userSelectCallBack = (data: UserVO[]) => { + userSelectCount.value = 0; + if (data && data.length > 0) { + userSelectCount.value = data.length; + selectUserIds.value = data.map((item) => item.userId); + queryParams.value.createByIds = selectUserIds.value; + } +}; </script> diff --git a/tsconfig.json b/tsconfig.json index bb287e9..6315891 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,7 +2,7 @@ "compilerOptions": { "target": "esnext", "module": "esnext", -// "useDefineForClassFields": true, + // "useDefineForClassFields": true, "moduleResolution": "bundler", "strict": true, "jsx": "preserve", diff --git a/vite.config.ts b/vite.config.ts index 97c8d9d..e125e36 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -64,16 +64,6 @@ 'echarts', 'vue-i18n', '@vueup/vue-quill', - 'bpmn-js/lib/Viewer', - 'bpmn-js/lib/Modeler.js', - 'bpmn-js-properties-panel', - 'min-dash', - 'diagram-js/lib/navigation/movecanvas', - 'diagram-js/lib/navigation/zoomscroll', - 'bpmn-js/lib/features/palette/PaletteProvider', - 'bpmn-js/lib/features/context-pad/ContextPadProvider', - 'diagram-js/lib/draw/BaseRenderer', - 'tiny-svg', 'image-conversion', 'element-plus/es/components/**/css' ] diff --git a/vite/plugins/i18n.ts b/vite/plugins/i18n.ts deleted file mode 100644 index 8777d1a..0000000 --- a/vite/plugins/i18n.ts +++ /dev/null @@ -1,6 +0,0 @@ -import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite'; -export default (path: any) => { - return VueI18nPlugin({ - include: [path.resolve(__dirname, '../../src/lang/**.json')] - }); -}; diff --git a/vite/plugins/index.ts b/vite/plugins/index.ts index 0ec5b8d..30b2835 100644 --- a/vite/plugins/index.ts +++ b/vite/plugins/index.ts @@ -6,7 +6,6 @@ import createSvgIconsPlugin from './svg-icon'; import createCompression from './compression'; import createSetupExtend from './setup-extend'; -import createI18n from './i18n'; import path from 'path'; export default (viteEnv: any, isBuild = false): [] => { @@ -19,6 +18,5 @@ vitePlugins.push(createIcons()); vitePlugins.push(createSvgIconsPlugin(path, isBuild)); vitePlugins.push(createSetupExtend()); - vitePlugins.push(createI18n(path)); return vitePlugins; }; -- Gitblit v1.9.3