!173 发布 5.3.0-BETA 公测版本
Merge pull request !173 from 疯狂的狮子Li/dev
已添加8个文件
已删除55个文件
已修改89个文件
| | |
| | | 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' |
| | |
| | | |
| | | - æ¬ä»åºä¸ºåç«¯ææ¯æ [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) |
| | | - é
å¥å端代ç ä»åºå°å |
| | | - [RuoYi-Vue-Plus 5.X(注æçæ¬å·)](https://gitee.com/dromara/RuoYi-Vue-Plus) |
| | | - [RuoYi-Cloud-Plus 2.X(注æçæ¬å·)](https://gitee.com/dromara/RuoYi-Cloud-Plus) |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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', |
| | | // å
许使ç¨ç©ºObjectç±»å {} |
| | | '@typescript-eslint/no-empty-object-type': 'off', |
| | | '@typescript-eslint/no-unused-expressions': 'off' |
| | | } |
| | | } |
| | | ]; |
| | |
| | | { |
| | | "$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", |
| | |
| | | "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": { |
| | |
| | | "@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" |
| | | } |
| | | } |
| | |
| | | * 注é |
| | | */ |
| | | 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' |
| | |
| | | } |
| | | |
| | | // è·åç§æ·å表 |
| | | 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' |
| | | }); |
| | |
| | | // å é¤å½åå¨çº¿è®¾å¤ |
| | | export function delOnline(tokenId: string) { |
| | | return request({ |
| | | url: '/monitor/online/' + tokenId, |
| | | method: 'post' |
| | | url: '/monitor/online/myself/' + tokenId, |
| | | method: 'delete' |
| | | }); |
| | | } |
| | |
| | | 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) => { |
| | |
| | | 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' |
| | | }); |
| | | }; |
| | | |
| | |
| | | }; |
| | | |
| | | // æ¥è¯¢é¨é¨ä¸ææ ç»æ |
| | | export const treeselect = (): AxiosPromise<DeptVO[]> => { |
| | | export const treeselect = (): AxiosPromise<DeptTreeVO[]> => { |
| | | return request({ |
| | | url: '/system/dept/treeselect', |
| | | method: 'get' |
| | |
| | | } |
| | | |
| | | /** |
| | | * é¨é¨ç±»å |
| | | */ |
| | | export interface DeptTreeVO extends BaseEntity { |
| | | id: number | string; |
| | | label: string; |
| | | parentId: number | string; |
| | | weight: number; |
| | | children: DeptTreeVO[]; |
| | | disabled: boolean; |
| | | } |
| | | |
| | | /** |
| | | * é¨é¨è¡¨åç±»å |
| | | */ |
| | | export interface DeptForm { |
| | |
| | | export function syncTenantDict() { |
| | | return request({ |
| | | url: '/system/tenant/syncTenantDict', |
| | | method: 'get', |
| | | method: 'get' |
| | | }); |
| | | } |
| | |
| | | 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'; |
| | |
| | | /** |
| | | * æ¥è¯¢é¨é¨ä¸ææ ç»æ |
| | | */ |
| | | export const deptTreeSelect = (): AxiosPromise<DeptVO[]> => { |
| | | export const deptTreeSelect = (): AxiosPromise<DeptTreeVO[]> => { |
| | | return request({ |
| | | url: '/system/user/deptTree', |
| | | method: 'get' |
| | |
| | | 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'; |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨åç±»å表 |
| | |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨åç±»è¯¦ç» |
| | | * @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' |
| | | }); |
| | | }; |
| | |
| | | |
| | | /** |
| | | * å 餿µç¨åç±» |
| | | * @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 |
| | | }); |
| | | }; |
| | |
| | | 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 |
| | |
| | | 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 |
| | | * ç¶æµç¨åç±»id |
| | | */ |
| | | parentId?: string | number; |
| | | |
| | | /** |
| | | * æåº |
| | | * æ¾ç¤ºé¡ºåº |
| | | */ |
| | | sortNum?: number; |
| | | orderNum?: number; |
| | | |
| | | } |
| | | |
| | | export interface CategoryQuery extends PageQuery { |
| | | export interface CategoryQuery { |
| | | |
| | | /** |
| | | * åç±»åç§° |
| | | * æµç¨åç±»åç§° |
| | | */ |
| | | categoryName?: string; |
| | | |
| | | /** |
| | | * åç±»ç¼ç |
| | | */ |
| | | categoryCode?: string; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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æxmlé¨ç½²æµç¨å®ä¹ |
| | | * @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' |
| | | }); |
| | | }; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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 |
| | | }); |
| | | }; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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[]; |
| | | } |
| | |
| | | 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 |
| | | }); |
| | |
| | | * @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 |
| | | }); |
| | |
| | | * @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 |
| | | }); |
| | |
| | | * @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 |
| | | }); |
| | |
| | | * @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 |
| | | }); |
| | |
| | | }; |
| | | |
| | | /** |
| | | * 认é¢ä»»å¡ |
| | | * @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 {*} |
| | |
| | | * @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 |
| | | }); |
| | | }; |
| | | |
| | |
| | | }; |
| | | |
| | | /** |
| | | * æ¥è¯¢æµç¨åé |
| | | * @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' |
| | | }); |
| | | }; |
| | |
| | | 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 { |
| | |
| | | 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; |
| | | } |
| | |
| | | |
| | | 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 |
| | | } |
| | | }); |
| | | } |
| | | }; |
| | |
| | | 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; |
| | | } |
| | |
| | | |
| | | .el-collapse { |
| | | .collapse__title { |
| | | font-weight: 600; |
| | |
| | | --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; |
| | |
| | | .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 |
| | |
| | | dangerColor: $--color-danger; |
| | | infoColor: $--color-info; |
| | | warningColor: $--color-warning; |
| | | } |
| | | } |
| | |
| | | |
| | | <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) { |
| | |
| | | return false; |
| | | } |
| | | } |
| | | // æ ¡æ£æä»¶åæ¯å¦å
å«ç¹æ®å符 |
| | | if (file.name.includes(',')) { |
| | | proxy?.$modal.msgError('æä»¶å䏿£ç¡®ï¼ä¸è½å
å«è±æéå·!'); |
| | | return false; |
| | | } |
| | | // æ ¡æ£æä»¶å¤§å° |
| | | if (props.fileSize) { |
| | | const isLt = file.size / 1024 / 1024 < props.fileSize; |
| | |
| | | proxy?.$modal.msgError(`æä»¶æ ¼å¼ä¸æ£ç¡®, 请ä¸ä¼ ${props.fileType.join('/')}å¾çæ ¼å¼æä»¶!`); |
| | | return false; |
| | | } |
| | | if (file.name.includes(',')) { |
| | | proxy?.$modal.msgError('æä»¶å䏿£ç¡®ï¼ä¸è½å
å«è±æéå·!'); |
| | | return false; |
| | | } |
| | | if (props.fileSize) { |
| | | const isLt = file.size / 1024 / 1024 < props.fileSize; |
| | | if (!isLt) { |
| | |
| | | <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> |
| | |
| | | </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' |
| | | })); |
| | | |
| | | /** |
| | | * 坹夿´é²åç»ä»¶æ¹æ³ |
| | | */ |
| | |
| | | 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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |
| | |
| | | <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> |
| | |
| | | <!-- å§æ --> |
| | | <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="æ¶æ¯æé"> |
| | |
| | | </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> |
| | | |
| | |
| | | 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: { |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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; |
| | |
| | | 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 () => { |
| | |
| | | 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; |
| | |
| | | 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 = () => { |
| | |
| | | //转å |
| | | 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('æä½æå'); |
| | |
| | | //å§æ |
| | | 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('æä½æå'); |
| | |
| | | } |
| | | }; |
| | | //ç»æ¢ä»»å¡ |
| | | const handleTerminationTask = async (data) => { |
| | | const handleTerminationTask = async () => { |
| | | let params = { |
| | | taskId: taskId.value, |
| | | comment: form.value.message |
| | |
| | | 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; |
| | | }; |
| | | |
| | | /** |
| | | * 坹夿´é²åç»ä»¶æ¹æ³ |
| | |
| | | </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> |
| | |
| | | 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) { |
| | |
| | | <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> |
| | | |
| | |
| | | <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, |
| | |
| | | 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>(); |
| | |
| | | |
| | | 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') { |
| | |
| | | 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); |
| | |
| | | }, |
| | | // ç»å½é¡µé¢å½é
å |
| | | 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: { |
| | |
| | | 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'; |
| | | |
| | | /** |
| | | * è·åå½åè¯è¨ |
| | |
| | | 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; |
| | |
| | | }, |
| | | // ç»å½é¡µé¢å½é
å |
| | | 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: 'è¯è¨', |
| | |
| | | |
| | | import IframeToggle from './IframeToggle/index.vue'; |
| | | const { proxy } = getCurrentInstance() as ComponentInternalInstance; |
| | | const route = useRoute(); |
| | | const tagsViewStore = useTagsViewStore(); |
| | | |
| | | // éæºå¨ç»éå |
| | |
| | | }, |
| | | { immediate: true } |
| | | ); |
| | | |
| | | onMounted(() => { |
| | | addIframe() |
| | | }) |
| | | |
| | | watchEffect((route) => { |
| | | addIframe() |
| | | }) |
| | | |
| | | function addIframe() { |
| | | if (route.meta.link) { |
| | | useTagsViewStore().addIframeView(route) |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | clearable |
| | | filterable |
| | | reserve-keyword |
| | | :placeholder="$t('navbar.selectTenant')" |
| | | :placeholder="proxy.$t('navbar.selectTenant')" |
| | | @change="dynamicTenantEvent" |
| | | @clear="dynamicClearEvent" |
| | | > |
| | |
| | | </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> |
| | |
| | | <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> |
| | |
| | | <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> |
| | |
| | | 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(); |
| | |
| | | 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; |
| | |
| | | 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']); |
| | |
| | | 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 |
| | |
| | | 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) => { |
| | |
| | | } |
| | | if (name) { |
| | | useTagsViewStore().addView(route as any); |
| | | if (route.meta.link) { |
| | | useTagsViewStore().addIframeView(route as any); |
| | | } |
| | | } |
| | | return false; |
| | | }; |
| | | const moveToCurrentTag = () => { |
| | | nextTick(() => { |
| | |
| | | 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; |
| | | }); |
| | |
| | | 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); |
| | |
| | | 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(); |
| | |
| | | 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) { |
| | |
| | | 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 { |
| | |
| | | } |
| | | } else { |
| | | // 没ætoken |
| | | if (whiteList.indexOf(to.path as string) !== -1) { |
| | | if (isWhiteList(to.path)) { |
| | | // å¨å
ç»å½ç½ååï¼ç´æ¥è¿å
¥ |
| | | next(); |
| | | } else { |
| | |
| | | if (value != null) { |
| | | return JSON.parse(value); |
| | | } |
| | | return null; |
| | | }, |
| | | remove(key: string) { |
| | | sessionStorage.removeItem(key); |
| | |
| | | if (value != null) { |
| | | return JSON.parse(value); |
| | | } |
| | | return null; |
| | | }, |
| | | remove(key: string) { |
| | | localStorage.removeItem(key); |
| | |
| | | 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 { |
| | |
| | | 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 } |
| | | } |
| | | ] |
| | | }, |
| | |
| | | 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 } |
| | | } |
| | | ] |
| | | }, |
| | |
| | | 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 } |
| | | } |
| | | ] |
| | | }, |
| | |
| | | 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 } |
| | | } |
| | | ] |
| | | }, |
| | |
| | | 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 } |
| | | } |
| | | ] |
| | | } |
| | | ]; |
| | | |
| | |
| | | scrollBehavior(to, from, savedPosition) { |
| | | if (savedPosition) { |
| | | return savedPosition; |
| | | } else { |
| | | return { top: 0 }; |
| | | } |
| | | return { top: 0 }; |
| | | } |
| | | }); |
| | | |
| | |
| | | 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; |
| | | }; |
| | | |
| | | /** |
| | |
| | | * @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; |
| | | } |
| | | }; |
| | | |
| | |
| | | * @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 { |
| | |
| | | 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; |
| | |
| | | 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 => { |
| | |
| | | delCachedView(view); |
| | | } |
| | | resolve({ |
| | | visitedViews: [...visitedViews.value as RouteLocationNormalized[]], |
| | | visitedViews: [...(visitedViews.value as RouteLocationNormalized[])], |
| | | cachedViews: [...cachedViews.value] |
| | | }); |
| | | }); |
| | |
| | | break; |
| | | } |
| | | } |
| | | resolve([...visitedViews.value as RouteLocationNormalized[]]); |
| | | resolve([...(visitedViews.value as RouteLocationNormalized[])]); |
| | | }); |
| | | }; |
| | | const delCachedView = (view?: RouteLocationNormalized): Promise<string[]> => { |
| | |
| | | delOthersVisitedViews(view); |
| | | delOthersCachedViews(view); |
| | | resolve({ |
| | | visitedViews: [...visitedViews.value as RouteLocationNormalized[]], |
| | | visitedViews: [...(visitedViews.value as RouteLocationNormalized[])], |
| | | cachedViews: [...cachedViews.value] |
| | | }); |
| | | }); |
| | |
| | | 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[]> => { |
| | |
| | | delAllVisitedViews(); |
| | | delAllCachedViews(); |
| | | resolve({ |
| | | visitedViews: [...visitedViews.value as RouteLocationNormalized[]], |
| | | visitedViews: [...(visitedViews.value as RouteLocationNormalized[])], |
| | | cachedViews: [...cachedViews.value] |
| | | }); |
| | | }); |
| | |
| | | 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[])]); |
| | | }); |
| | | }; |
| | | |
| | |
| | | } |
| | | return false; |
| | | }); |
| | | resolve([...visitedViews.value as RouteLocationNormalized[]]); |
| | | resolve([...(visitedViews.value as RouteLocationNormalized[])]); |
| | | }); |
| | | }; |
| | | const delLeftTags = (view: RouteLocationNormalized): Promise<RouteLocationNormalized[]> => { |
| | |
| | | } |
| | | return false; |
| | | }); |
| | | resolve([...visitedViews.value as RouteLocationNormalized[]]); |
| | | resolve([...(visitedViews.value as RouteLocationNormalized[])]); |
| | | }); |
| | | }; |
| | | |
| | |
| | | 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; |
| | |
| | | $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; |
| | |
| | | } |
| | | } |
| | | |
| | | 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; |
| | | |
| | |
| | | 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; |
| | |
| | | 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, |
| | |
| | | /** |
| | | * è·¯å¾å¹é
å¨ |
| | | * @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æ¯å¦æ¯httpæhttps |
| | | * @returns {Boolean} |
| | | * @param url |
| | |
| | | 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: { |
| | | // éè¿æå¤§æ¬¡æ° |
| | |
| | | delay: 1000, |
| | | onFailed() { |
| | | console.log('websocketéè¿å¤±è´¥'); |
| | | }, |
| | | } |
| | | }, |
| | | heartbeat: { |
| | | message: JSON.stringify({type: 'ping'}), |
| | | message: JSON.stringify({ type: 'ping' }), |
| | | // åéå¿è·³çé´é |
| | | interval: 10000, |
| | | // æ¥æ¶å°å¿è·³responseçè¶
æ¶æ¶é´ |
| | | pongTimeout: 2000, |
| | | pongTimeout: 2000 |
| | | }, |
| | | onConnected() { |
| | | console.log('websocketå·²ç»è¿æ¥'); |
| | |
| | | <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> |
| | | |
| | |
| | | <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 |
| | |
| | | * é¨ç½²æ¹å¼ 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> |
| | |
| | | <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> |
| | |
| | | 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', |
| | |
| | | } 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(''); |
| | |
| | | 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 } |
| | | ); |
| | |
| | | * è·åç§æ·å表 |
| | | */ |
| | | 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; |
| | |
| | | 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 { |
| | |
| | | <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> |
| | | |
| | |
| | | <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> |
| | |
| | | <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"> |
| | |
| | | <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> |
| | | |
| | |
| | | </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 |
| | |
| | | <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">æ£å¸¸</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')); |
| | |
| | | |
| | | const operLogTableRef = ref<ElTableInstance>(); |
| | | const queryFormRef = ref<ElFormInstance>(); |
| | | |
| | | const dialog = reactive<DialogOption>({ |
| | | visible: false, |
| | | title: '' |
| | | }); |
| | | |
| | | const data = reactive<PageData<OperLogForm, OperLogQuery>>({ |
| | | form: { |
| | |
| | | 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; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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">æ£å¸¸</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> |
| | |
| | | <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> |
| | |
| | | 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"> |
| | |
| | | </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> |
| | |
| | | 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: '', |
| | |
| | | |
| | | 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); |
| | |
| | | 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' |
| | | }); |
| | |
| | | }; |
| | | |
| | | 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; |
| | |
| | | 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 { |
| | |
| | | <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> |
| | | |
| | |
| | | <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> |
| | | |
| | |
| | | <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"> |
| | |
| | | <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"> |
| | |
| | | <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-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="æä½"> |
| | |
| | | <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> |
| | | |
| | |
| | | <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"> |
| | |
| | | <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> |
| | | |
| | |
| | | <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"> |
| | |
| | | |
| | | <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); |
| | |
| | | await refreshCache(); |
| | | proxy?.$modal.msgSuccess('å·æ°æå'); |
| | | useDictStore().cleanDict(); |
| | | }; |
| | | /**åæ¥ç§æ·åå
¸*/ |
| | | const handleSyncTenantDict = async () => { |
| | | await proxy?.$modal.confirm('确认è¦åæ¥ææç§æ·åå
¸åï¼'); |
| | | let res = await syncTenantDict(); |
| | | proxy?.$modal.msgSuccess(res.msg); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | |
| | | <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-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-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"> |
| | |
| | | å é¤ |
| | | </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> |
| | | |
| | |
| | | |
| | | // åæ¾éä¿¡æ¯ |
| | | 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 }, |
| | |
| | | <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> |
| | | |
| | |
| | | </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" /> |
| | |
| | | <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"> |
| | |
| | | </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"> |
| | |
| | | <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"> |
| | |
| | | <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> |
| | | |
| | |
| | | </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> |
| | | |
| | |
| | | { value: '2', label: 'èªå®æ°æ®æé' }, |
| | | { value: '3', label: 'æ¬é¨é¨æ°æ®æé' }, |
| | | { value: '4', label: 'æ¬é¨é¨å以䏿°æ®æé' }, |
| | | { value: '5', label: 'ä»
æ¬äººæ°æ®æé' } |
| | | { value: '5', label: 'ä»
æ¬äººæ°æ®æé' }, |
| | | { value: '6', label: 'é¨é¨å以䏿æ¬äººæ°æ®æé' } |
| | | ]); |
| | | |
| | | const queryFormRef = ref<ElFormInstance>(); |
| | |
| | | </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> |
| | |
| | | <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> |
| | | |
| | |
| | | <el-table-column label="社ä¼ä¿¡ç¨ä»£ç " 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"> |
| | |
| | | </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); |
| | |
| | | ); |
| | | }; |
| | | |
| | | /**åæ¥ç§æ·åå
¸*/ |
| | | const handleSyncTenantDict = async () => { |
| | | await proxy?.$modal.confirm('确认è¦åæ¥ææç§æ·åå
¸åï¼'); |
| | | let res = await syncTenantDict(); |
| | | proxy?.$modal.msgSuccess(res.msg); |
| | | }; |
| | | |
| | | onMounted(() => { |
| | | getList(); |
| | | }); |
| | |
| | | <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> |
| | | |
| | |
| | | <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> |
| | |
| | | |
| | | /** åå»éä¸è¡æ°æ® */ |
| | | const clickRow = (row: RoleVO) => { |
| | | row.flag = !row.flag |
| | | row.flag = !row.flag; |
| | | tableRef.value?.toggleRowSelection(row, row.flag); |
| | | }; |
| | | /** å¤éæ¡é䏿°æ® */ |
| | |
| | | <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> |
| | |
| | | <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> |
| | | |
| | |
| | | <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="è¯·éæ©å½å±é¨é¨" |
| | |
| | | <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'; |
| | |
| | | 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[]>([]); |
| | |
| | | message: 'ç¨æ·å¯ç é¿åº¦å¿
é¡»ä»äº 5 å 20 ä¹é´', |
| | | trigger: 'blur' |
| | | }, |
| | | { pattern: /^[^<>"'|\\]+$/, message: 'ä¸è½å
å«éæ³å符ï¼< > " \' \\\ |', trigger: 'blur' } |
| | | { pattern: /^[^<>"'|\\]+$/, message: 'ä¸è½å
å«éæ³å符ï¼< > " \' \\ |', trigger: 'blur' } |
| | | ], |
| | | email: [ |
| | | { |
| | |
| | | } |
| | | ); |
| | | |
| | | /** æ¥è¯¢é¨é¨ä¸ææ ç»æ */ |
| | | const getTreeSelect = async () => { |
| | | const res = await api.deptTreeSelect(); |
| | | deptOptions.value = res.data; |
| | | }; |
| | | |
| | | /** æ¥è¯¢ç¨æ·å表 */ |
| | | const getList = async () => { |
| | | loading.value = true; |
| | |
| | | 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; |
| | | }); |
| | | }; |
| | | |
| | | /** èç¹åå»äºä»¶ */ |
| | |
| | | inputErrorMessage: 'ç¨æ·å¯ç é¿åº¦å¿
é¡»ä»äº 5 å 20 ä¹é´', |
| | | inputValidator: (value) => { |
| | | if (/<|>|"|'|\||\\/.test(value)) { |
| | | return 'ä¸è½å
å«éæ³å符ï¼< > " \' \\\ |'; |
| | | return 'ä¸è½å
å«éæ³å符ï¼< > " \' \\ |'; |
| | | } |
| | | } |
| | | }) |
| | |
| | | uploadRef.value?.submit(); |
| | | } |
| | | |
| | | /** åå§åé¨é¨æ°æ® */ |
| | | const initTreeData = async () => { |
| | | // 夿é¨é¨çæ°æ®æ¯å¦åå¨ï¼åå¨ä¸è·åï¼ä¸åå¨åè·å |
| | | if (deptOptions.value === undefined) { |
| | | const { data } = await treeselect(); |
| | | deptOptions.value = data; |
| | | } |
| | | }; |
| | | |
| | | /** éç½®æä½è¡¨å */ |
| | | const reset = () => { |
| | | form.value = { ...initFormData }; |
| | |
| | | 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(); |
| | |
| | | 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; |
| | |
| | | form.value.status = '1'; |
| | | }; |
| | | onMounted(() => { |
| | | getTreeSelect(); // åå§åé¨é¨æ°æ® |
| | | getDeptTree(); // åå§åé¨é¨æ°æ® |
| | | getList(); // åå§ååè¡¨æ°æ® |
| | | proxy?.getConfigKey('sys.user.initPassword').then((response) => { |
| | | initPassword.value = response.data; |
| | |
| | | <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"> |
| | |
| | | message: 'é¿åº¦å¨ 6 å° 20 个å符', |
| | | trigger: 'blur' |
| | | }, |
| | | { pattern: /^[^<>"'|\\]+$/, message: 'ä¸è½å
å«éæ³å符ï¼< > " \' \\\ |', trigger: 'blur' } |
| | | { pattern: /^[^<>"'|\\]+$/, message: 'ä¸è½å
å«éæ³å符ï¼< > " \' \\ |', trigger: 'blur' } |
| | | ], |
| | | confirmPassword: [ |
| | | { required: true, message: '确认å¯ç ä¸è½ä¸ºç©º', trigger: 'blur' }, |
| | |
| | | |
| | | /** æ¥è¯¢åæ°å表 */ |
| | | 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) => { |
| | |
| | | visible.value = false; |
| | | emit('ok'); |
| | | } |
| | | }; |
| | | /** æ¥è¯¢å¤æ°æ®æºåç§° */ |
| | | const getDataNameList = async () => { |
| | | const res = await getDataNames(); |
| | | dataNameList.value = res.data; |
| | | }; |
| | | |
| | | defineExpose({ |
| | |
| | | å é¤ |
| | | </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> |
| | | |
| | |
| | | </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'; |
| | | |
| | |
| | | const dialog = reactive<DialogOption>({ |
| | | visible: false, |
| | | title: '代ç é¢è§' |
| | | }); |
| | | |
| | | 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(); |
| | | } |
| | | }); |
| | | |
| | | /** æ¥è¯¢å¤æ°æ®æºåç§° */ |
| | |
| | | }; |
| | | |
| | | 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(); |
| | | }); |
| | |
| | | <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> |
| | |
| | | <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> |
| | |
| | | </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[]>([]); |
| | |
| | | |
| | | 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" }] |
| | | } |
| | | }); |
| | | |
| | |
| | | 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(); |
| | |
| | | <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"> |
| | |
| | | </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" /> |
| | |
| | | <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> |
| | |
| | | |
| | | <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; |
| | |
| | | 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('æ¤éæå'); |
| | | }; |
| | |
| | | <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> |
| | | |
| | |
| | | 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>>(); |
| | | //审æ¹è®°å½ç»ä»¶ |
| | |
| | | const leaveFormRef = ref<ElFormInstance>(); |
| | | |
| | | const submitFormData = ref<StartProcessBo>({ |
| | | businessKey: '', |
| | | tableName: '', |
| | | businessId: '', |
| | | flowCode: '', |
| | | variables: {} |
| | | }); |
| | | const taskVariables = ref<Record<string, any>>({}); |
| | |
| | | } |
| | | }); |
| | | |
| | | const handleClose = () => { |
| | | dialogVisible.visible = false; |
| | | flowCode.value = ''; |
| | | buttonLoading.value = false; |
| | | }; |
| | | const { form, rules } = toRefs(data); |
| | | |
| | | /** 表åéç½® */ |
| | |
| | | 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); |
| | | } |
| | | } |
| | |
| | | } |
| | | }; |
| | | |
| | | 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); |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |
| | |
| | | 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 |
| | |
| | | <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="请è¾å
¥æµç¨å®ä¹KEY" clearable @keyup.enter="handleQuery" /> |
| | | <el-form-item label="æµç¨å®ä¹KEY" prop="flowCode"> |
| | | <el-input v-model="queryParams.flowCode" placeholder="请è¾å
¥æµç¨å®ä¹KEY" clearable @keyup.enter="handleQuery" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" icon="Search" @click="handleQuery">æç´¢</el-button> |
| | |
| | | <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> |
| | | <!-- é¢è§å¾çæxml --> |
| | | <process-preview ref="previewRef" /> |
| | | |
| | | <!-- é¨ç½²æä»¶ --> |
| | | <el-dialog v-if="uploadDialog.visible" v-model="uploadDialog.visible" :title="uploadDialog.title" width="30%"> |
| | |
| | | <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" |
| | |
| | | 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ãbpmn æ ¼å¼æä»¶</div> |
| | | <div class="el-upload__text"><em>ç¹å»ä¸ä¼ ï¼éæ©JSONæµç¨æä»¶</em></div> |
| | | <div class="el-upload__text">ä»
æ¯æjsonæ ¼å¼æä»¶</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> |
| | |
| | | </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: 'é¨ç½²æµç¨æä»¶' |
| | |
| | | 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(); |
| | | }; |
| | |
| | | |
| | | /** æ¥è¯¢æµç¨åç±»ä¸ææ ç»æ */ |
| | | 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(); |
| | |
| | | // å¤éæ¡é䏿°æ® |
| | | 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; |
| | | } |
| | | }; |
| | | |
| | | //ä¸ä¼ æä»¶åçé©å |
| | |
| | | } |
| | | }; |
| | | //é¨ç½²æä»¶ |
| | | 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(() => { |
| | |
| | | }); |
| | | 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 + 'ãçæ¬v' + 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> |
| | |
| | | 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 |
| | |
| | | </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="请è¾å
¥æµç¨å®ä¹KEY" @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> |
| | |
| | | <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> |
| | |
| | | <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> |
| | |
| | | </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); |
| | | // éå¤ä¸ªç¦ç¨ |
| | |
| | | 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(''); |
| | |
| | | }); |
| | | |
| | | type CategoryOption = { |
| | | categoryCode: string; |
| | | id: string; |
| | | categoryName: string; |
| | | children?: CategoryOption[]; |
| | | }; |
| | |
| | | const tab = ref('running'); |
| | | // ä½åºåå |
| | | const deleteReason = ref(''); |
| | | |
| | | //ç³è¯·äººid |
| | | 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(); |
| | | }; |
| | |
| | | |
| | | /** æ¥è¯¢æµç¨åç±»ä¸ææ ç»æ */ |
| | | 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 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; |
| | |
| | | //å页 |
| | | 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; |
| | |
| | | }; |
| | | |
| | | /** å é¤æé®æä½ */ |
| | | 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('å 餿å'); |
| | |
| | | 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('æä½æå'); |
| | | } |
| | |
| | | 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(); |
| | |
| | | <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="请è¾å
¥æµç¨å®ä¹KEY" @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> |
| | |
| | | <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); |
| | | // é䏿°ç» |
| | |
| | | // 模åå®ä¹è¡¨æ ¼æ°æ® |
| | | const taskList = ref([]); |
| | | const title = ref(''); |
| | | // æµç¨å鿝妿¾ç¤º |
| | | const variableVisible = ref(false); |
| | | const variableLoading = ref(true); |
| | | // æµç¨åé |
| | | const variableList = ref<VariableVo>({ |
| | | key: '', |
| | | value: '' |
| | | }); |
| | | //æµç¨å®ä¹åç§° |
| | | const processDefinitionName = ref(); |
| | | //ç³è¯·äººid |
| | | 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) { |
| | |
| | | queryFormRef.value?.resetFields(); |
| | | queryParams.value.pageNum = 1; |
| | | queryParams.value.pageSize = 10; |
| | | queryParams.value.createByIds = []; |
| | | userSelectCount.value = 0; |
| | | handleQuery(); |
| | | }; |
| | | // å¤éæ¡é䏿°æ® |
| | |
| | | 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(); |
| | |
| | | //å页 |
| | | 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; |
| | |
| | | }; |
| | | 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; |
| | |
| | | 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(); |
| | | }); |
| | |
| | | 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 |
| | |
| | | <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> |
| | |
| | | <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-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"> |
| | |
| | | </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> |
| | |
| | | </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; |
| | |
| | | // é®ç½©å± |
| | | 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); |
| | | // éå¤ä¸ªç¦ç¨ |
| | |
| | | // æ»æ¡æ° |
| | | 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(() => { |
| | |
| | | }); |
| | | |
| | | /** èç¹åå»äºä»¶ */ |
| | | 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(); |
| | | }; |
| | |
| | | |
| | | /** æ¥è¯¢æµç¨åç±»ä¸ææ ç»æ */ |
| | | 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 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; |
| | |
| | | }; |
| | | |
| | | /** å é¤æé®æä½ */ |
| | | 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('æ¤éæå'); |
| | |
| | | //åç |
| | | 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); |
| | | }; |
| | |
| | | <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="请è¾å
¥æµç¨å®ä¹KEY" @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> |
| | |
| | | <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"> |
| | |
| | | </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'; |
| | |
| | | const queryParams = ref<TaskQuery>({ |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | name: undefined, |
| | | processDefinitionName: undefined, |
| | | processDefinitionKey: undefined |
| | | nodeName: undefined, |
| | | flowName: undefined, |
| | | flowCode: undefined |
| | | }); |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | |
| | | //å页 |
| | | 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; |
| | |
| | | /** æ¥çæé®æä½ */ |
| | | 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); |
| | | }; |
| | |
| | | <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="请è¾å
¥æµç¨å®ä¹KEY" @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> |
| | |
| | | <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> |
| | |
| | | @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); |
| | | // é䏿°ç» |
| | |
| | | const queryParams = ref<TaskQuery>({ |
| | | pageNum: 1, |
| | | pageSize: 10, |
| | | name: undefined, |
| | | processDefinitionName: undefined, |
| | | processDefinitionKey: undefined |
| | | nodeName: undefined, |
| | | flowName: undefined, |
| | | flowCode: undefined, |
| | | createByIds: [] |
| | | }); |
| | | //ç³è¯·äººid |
| | | const selectUserIds = ref<Array<number | string>>([]); |
| | | //ç³è¯·äººéæ©æ°é |
| | | const userSelectCount = ref(0); |
| | | /** æç´¢æé®æä½ */ |
| | | const handleQuery = () => { |
| | | getFinishList(); |
| | |
| | | queryFormRef.value?.resetFields(); |
| | | queryParams.value.pageNum = 1; |
| | | queryParams.value.pageSize = 10; |
| | | queryParams.value.createByIds = []; |
| | | userSelectCount.value = 0; |
| | | handleQuery(); |
| | | }; |
| | | // å¤éæ¡é䏿°æ® |
| | |
| | | }; |
| | | 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(); |
| | | }); |
| | |
| | | <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="请è¾å
¥æµç¨å®ä¹KEY" @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> |
| | |
| | | <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> |
| | |
| | | @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>(); |
| | | // é®ç½©å± |
| | |
| | | const total = ref(0); |
| | | // 模åå®ä¹è¡¨æ ¼æ°æ® |
| | | const taskList = ref([]); |
| | | |
| | | //ç³è¯·äººid |
| | | 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(); |
| | |
| | | queryFormRef.value?.resetFields(); |
| | | queryParams.value.pageNum = 1; |
| | | queryParams.value.pageSize = 10; |
| | | queryParams.value.createByIds = []; |
| | | userSelectCount.value = 0; |
| | | handleQuery(); |
| | | }; |
| | | // å¤éæ¡é䏿°æ® |
| | |
| | | //å页 |
| | | 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> |
| | |
| | | "compilerOptions": { |
| | | "target": "esnext", |
| | | "module": "esnext", |
| | | // "useDefineForClassFields": true, |
| | | // "useDefineForClassFields": true, |
| | | "moduleResolution": "bundler", |
| | | "strict": true, |
| | | "jsx": "preserve", |
| | |
| | | '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' |
| | | ] |
| | |
| | | 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): [] => { |
| | |
| | | vitePlugins.push(createIcons()); |
| | | vitePlugins.push(createSvgIconsPlugin(path, isBuild)); |
| | | vitePlugins.push(createSetupExtend()); |
| | | vitePlugins.push(createI18n(path)); |
| | | return vitePlugins; |
| | | }; |