Compare commits

..
Author SHA1 Message Date
疯狂的狮子Li ba24afce52 !131 ♥️发布 vue 版本 5.2.1 与 cloud 版本 2.2.0
Merge pull request !131 from 疯狂的狮子Li/dev
2024-07-09 03:02:34 +00:00
疯狂的狮子Li 93d3371768 ♥️发布 vue 版本 5.2.1 与 cloud 版本 2.2.0 2024-07-09 10:53:49 +08:00
疯狂的狮子Li 3f08ae6ac4 fix 修复 富文本编辑器 添加之后内容未清理问题 2024-07-02 16:51:03 +08:00
疯狂的狮子Li cc6284d3ac fix 修复 字段命名错误 2024-07-01 12:52:19 +08:00
疯狂的狮子Li 142effd4f2 !130 feat: 动态创建组件实例时, 设置路由name为组件名 解决缓存问题
Merge pull request !130 from 玲娜贝er/dev
2024-06-30 08:13:16 +00:00
dap e657a507e3 feat: 动态创建组件实例时, 设置路由name为组件名 解决缓存问题 2024-06-30 10:50:04 +08:00
疯狂的狮子Li ebaec24213 update 优化 eslint 2024-06-28 10:44:13 +08:00
疯狂的狮子Li 7637582437 update 优化 eslint 2024-06-28 10:18:26 +08:00
疯狂的狮子Li 27d36f7970 !129 feat: 路由name重复检查
Merge pull request !129 from 玲娜贝er/dev
2024-06-26 04:02:28 +00:00
dap 762ebd4ede chore: 增加提示 2024-06-26 11:59:41 +08:00
dap ad991e248a feat: 路由name重复检查 2024-06-26 11:34:40 +08:00
疯狂的狮子Li d1b58f0aaa fix 修复 单词拼写错误 2024-06-24 14:59:46 +08:00
疯狂的狮子Li 1be1eaf7b4 !128 fix: 选人无法回显
Merge pull request !128 from 玲娜贝er/dev
2024-06-24 00:37:32 +00:00
dap fbcc967b14 fix: 由于没有await 导致执行顺序不可控 2024-06-24 08:21:19 +08:00
疯狂的狮子Li 817c65f7e2 !126 fix: 进入审批页面会多次加载用户列表和部门等接口 进入点击取消之后也会重新加载接口
Merge pull request !126 from 玲娜贝er/dev
2024-06-21 04:31:25 +00:00
张代鹏 b6dcc62f9c refactor: 改为懒加载窗口 2024-06-21 12:07:19 +08:00
疯狂的狮子Li abb4f543b9 !125 ♥️发布 vue 版本 5.2.0 与 cloud 版本 2.2.0
Merge pull request !125 from 疯狂的狮子Li/dev
2024-06-20 02:15:41 +00:00
疯狂的狮子Li 71f4d36c21 ♥️发布 vue 版本 5.2.0 与 cloud 版本 2.2.0 2024-06-20 10:15:08 +08:00
gssong d1be442c6e fix 修复选着人员错误问题 2024-06-19 21:13:58 +08:00
疯狂的狮子Li 9ef7fd3844 !123 "types": ["element-plus/global"]层级错误,且element-plus按需引入不用配置tsconfig.json
Merge pull request !123 from zl/修复tsconfig.json
2024-06-19 06:41:11 +00:00
疯狂的狮子Li fec61f9650 update 优化 clientid写死问题 2024-06-19 14:30:19 +08:00
疯狂的狮子Li c206ab5b4a update 优化 三方登录不同域名问题 采用新方案 2024-06-19 14:29:44 +08:00
疯狂的狮子Li fe1942c247 update 更换三方回调方案 2024-06-19 10:16:21 +08:00
疯狂的狮子Li 1f2add4b6b update 更换三方回调方案 2024-06-19 10:11:32 +08:00
疯狂的狮子Li 3b254cc16b update 增加 用户信息缓存增加租户id 2024-06-18 23:05:40 +08:00
疯狂的狮子Li 3e7c2f26fa update 增加 用户信息缓存增加租户id 2024-06-18 22:54:30 +08:00
疯狂的狮子Li 4143285ec6 fix 修复 缺少协议头问题 2024-06-18 19:08:51 +08:00
疯狂的狮子Li 72610ab194 update 优化 三方登录不同域名获取不到租户id问题 2024-06-18 18:44:27 +08:00
疯狂的狮子Li 3c713c9258 update element 2.7.2 => 2.7.5 2024-06-15 15:53:02 +08:00
gssong f95f6e8390 update 优化审批按钮判断 2024-06-07 21:38:17 +08:00
疯狂的狮子Li 2c9c837c1b update 优化 请假天数计算不精确问题 2024-06-06 17:27:50 +08:00
zl 7904496df1 层级错误,且element-plus按需引入不用配置tsconfig.json
Signed-off-by: zl <11656279+xbbzjsj@user.noreply.gitee.com>
2024-06-06 08:53:59 +00:00
疯狂的狮子Li 15c3d84ca2 !122 修复单词拼写错误
Merge pull request !122 from LiYaoheng/dev
2024-06-06 06:27:36 +00:00
LiYaoheng e8a641f3a3 fix 修复单词拼写错误 2024-06-06 14:19:55 +08:00
疯狂的狮子Li e354db74a7 !121 ♥️发布 2.2.0-BETA 公测版本
Merge pull request !121 from 疯狂的狮子Li/dev
2024-06-06 03:00:23 +00:00
疯狂的狮子Li 61df97c4b9 update 优化 标识符错误 2024-06-06 10:59:20 +08:00
疯狂的狮子Li 75ecc4dd68 update 更改 关于mq说明 2024-06-04 15:00:40 +08:00
songgaoshuai c467d95703 https://gitee.com/dromara/RuoYi-Cloud-Plus/issues/I9US1Q fix修复我的单据撤销,删除参数错误 2024-06-04 11:26:38 +08:00
gssong 3fead37924 add 添加流程记录版本信息 2024-06-03 21:33:12 +08:00
gssong c8626b6893 remove 删除无用参数 2024-06-03 21:23:32 +08:00
gssong 38df345078 update 调整流程图预览校验 2024-06-03 21:04:42 +08:00
疯狂的狮子Li 212361dc94 update 优化 去除请假案例状态字段 2024-06-03 17:53:49 +08:00
疯狂的狮子Li f237ee145a update 优化 去除请假案例状态字段 2024-06-03 15:47:51 +08:00
疯狂的狮子Li 291d4b0040 !120 update 调整注释错误
Merge pull request !120 from lu_ming/dev
2024-06-02 11:52:43 +00:00
can 64c56e9dd9 update 调整注释错误 2024-06-02 19:44:38 +08:00
gssong 57d87df589 update 调整驳回按钮加载 2024-06-02 00:21:47 +08:00
gssong 9de3f25f6a update 调整审批按钮加载 2024-06-01 22:05:45 +08:00
gssong d98c2822d5 update 调整路由 2024-06-01 22:00:22 +08:00
gssong 58e6fdef78 update 优化流程实例接口全部按照业务id操作 2024-05-31 22:11:25 +08:00
疯狂的狮子Li 2c9daae153 update 更改 工作流 测试用例接口路径 2024-05-31 11:25:03 +08:00
疯狂的狮子Li c2fdbc66b2 update 移除 表单构建菜单(没有可用组件 用处不大以后再考虑) 2024-05-29 18:36:46 +08:00
dap 57fd309907 fix: 类型报错 2024-05-29 09:32:49 +08:00
疯狂的狮子Li 7a335b3438 update 优化 删除未使用依赖 2024-05-21 10:01:25 +08:00
dap 83bbac303e fix: bpmn相关type第一次安装依赖&运行报错 2024-05-21 09:37:28 +08:00
疯狂的狮子Li eb1b614eb1 fix 修复 部署路径错误 2024-05-20 11:45:08 +08:00
70 changed files with 452 additions and 400 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ VITE_APP_BASE_API = '/dev-api'
VITE_APP_CONTEXT_PATH = '/'
# 监控地址
VITE_APP_MONITRO_ADMIN = 'http://localhost:9090/admin/applications'
VITE_APP_MONITOR_ADMIN = 'http://localhost:9090/admin/applications'
# SnailJob 控制台地址
VITE_APP_SNAILJOB_ADMIN = 'http://localhost:8800/snail-job'
+2 -2
View File
@@ -8,10 +8,10 @@ VITE_APP_ENV = 'production'
VITE_APP_CONTEXT_PATH = '/'
# 监控地址
VITE_APP_MONITRO_ADMIN = '/admin/applications'
VITE_APP_MONITOR_ADMIN = '/admin/applications'
# SnailJob 控制台地址
VITE_APP_SNAILJOB_ADMIN = 'http://localhost:8800/snail-job'
VITE_APP_SNAILJOB_ADMIN = '/snail-job'
# 生产环境
VITE_APP_BASE_API = '/prod-api'
+3 -13
View File
@@ -1,6 +1,6 @@
{
"name": "ruoyi-vue-plus",
"version": "5.2.0-BETA",
"version": "5.2.1",
"description": "RuoYi-Vue-Plus多租户管理系统",
"author": "LionLi",
"license": "MIT",
@@ -20,41 +20,32 @@
"dependencies": {
"@element-plus/icons-vue": "2.3.1",
"@highlightjs/vue-plugin": "2.1.0",
"@lezer/common": "1.2.1",
"@vueup/vue-quill": "1.2.0",
"@vueuse/core": "10.9.0",
"animate.css": "4.1.1",
"await-to-js": "3.0.0",
"axios": "1.6.8",
"bpmn-js": "16.4.0",
"camunda-bpmn-js-behaviors": "1.2.2",
"camunda-bpmn-moddle": "7.0.1",
"crypto-js": "4.2.0",
"diagram-js": "12.3.0",
"didi": "9.0.2",
"echarts": "5.5.0",
"element-plus": "2.7.2",
"element-plus": "2.7.5",
"file-saver": "2.0.5",
"fuse.js": "7.0.0",
"highlight.js": "11.9.0",
"image-conversion": "^2.1.1",
"js-cookie": "3.0.5",
"jsencrypt": "3.3.2",
"moddle": "6.2.3",
"nprogress": "0.2.0",
"path-browserify": "1.0.1",
"path-to-regexp": "6.2.1",
"pinia": "2.1.7",
"preact": "10.19.7",
"screenfull": "6.0.2",
"vform3-builds": "3.0.10",
"vue": "3.4.25",
"vue-cropper": "1.1.1",
"vue-i18n": "9.10.2",
"vue-router": "4.3.2",
"vue-types": "5.1.1",
"vxe-table": "4.5.22",
"zeebe-bpmn-moddle": "1.0.0"
"vxe-table": "4.5.22"
},
"devDependencies": {
"@iconify/json": "2.2.201",
@@ -64,7 +55,6 @@
"@types/js-cookie": "3.0.6",
"@types/node": "18.18.2",
"@types/nprogress": "0.2.3",
"@types/path-browserify": "1.0.2",
"@typescript-eslint/eslint-plugin": "7.3.1",
"@typescript-eslint/parser": "7.3.1",
"@unocss/preset-attributify": "0.58.6",
+6 -2
View File
@@ -1,10 +1,14 @@
import request from '@/utils/request';
// 绑定账号
export function authBinding(source: string) {
export function authBinding(source: string, tenantId: string) {
return request({
url: '/auth/binding/' + source,
method: 'get'
method: 'get',
params: {
tenantId: tenantId,
domain: window.location.host
}
});
}
+1
View File
@@ -26,6 +26,7 @@ export interface UserQuery extends PageQuery {
*/
export interface UserVO extends BaseEntity {
userId: string | number;
tenantId: string;
deptId: number;
userName: string;
nickName: string;
+1 -1
View File
@@ -25,7 +25,7 @@ export const listFormManage = (query?: FormManageQuery): AxiosPromise<FormManage
export const selectListFormManage = (): AxiosPromise<FormManageVO[]> => {
return request({
url: '/workflow/formManage/list/selectList',
method: 'get',
method: 'get'
});
};
+2 -2
View File
@@ -26,7 +26,7 @@ export interface FormManageVO {
/**
* 备注
*/
remork: string;
remark: string;
}
export interface FormManageForm extends BaseEntity {
@@ -53,7 +53,7 @@ export interface FormManageForm extends BaseEntity {
/**
* 备注
*/
remork?: string;
remark?: string;
}
export interface FormManageQuery extends PageQuery {
+5 -5
View File
@@ -10,7 +10,7 @@ import { LeaveVO, LeaveQuery, LeaveForm } from '@/api/workflow/leave/types';
export const listLeave = (query?: LeaveQuery): AxiosPromise<LeaveVO[]> => {
return request({
url: '/demo/leave/list',
url: '/workflow/leave/list',
method: 'get',
params: query
});
@@ -22,7 +22,7 @@ export const listLeave = (query?: LeaveQuery): AxiosPromise<LeaveVO[]> => {
*/
export const getLeave = (id: string | number): AxiosPromise<LeaveVO> => {
return request({
url: '/demo/leave/' + id,
url: '/workflow/leave/' + id,
method: 'get'
});
};
@@ -33,7 +33,7 @@ export const getLeave = (id: string | number): AxiosPromise<LeaveVO> => {
*/
export const addLeave = (data: LeaveForm): AxiosPromise<LeaveVO> => {
return request({
url: '/demo/leave',
url: '/workflow/leave',
method: 'post',
data: data
});
@@ -45,7 +45,7 @@ export const addLeave = (data: LeaveForm): AxiosPromise<LeaveVO> => {
*/
export const updateLeave = (data: LeaveForm): AxiosPromise<LeaveVO> => {
return request({
url: '/demo/leave',
url: '/workflow/leave',
method: 'put',
data: data
});
@@ -57,7 +57,7 @@ export const updateLeave = (data: LeaveForm): AxiosPromise<LeaveVO> => {
*/
export const delLeave = (id: string | number | Array<string | number>) => {
return request({
url: '/demo/leave/' + id,
url: '/workflow/leave/' + id,
method: 'delete'
});
};
+2 -2
View File
@@ -5,7 +5,7 @@ export interface LeaveVO {
endDate: string;
leaveDays: number;
remark: string;
processInstanceVo: any;
status?: string;
}
export interface LeaveForm extends BaseEntity {
@@ -15,7 +15,7 @@ export interface LeaveForm extends BaseEntity {
endDate?: string;
leaveDays?: number;
remark?: string;
processInstanceVo?: any;
status?: string;
}
export interface LeaveQuery extends PageQuery {
+2 -2
View File
@@ -22,7 +22,7 @@ export const listModel = (query: ModelQuery): AxiosPromise<ModelVO[]> => {
*/
export const getInfo = (id: string): AxiosPromise<ModelForm> => {
return request({
url: '/workflow/model/getInfo/'+id,
url: '/workflow/model/getInfo/' + id,
method: 'get'
});
};
@@ -101,4 +101,4 @@ export const copyModel = (data: ModelForm): AxiosPromise<void> => {
method: 'post',
data: data
});
};
};
+3 -3
View File
@@ -1,10 +1,10 @@
export interface ModelForm {
id: string,
id: string;
name: string;
key: string;
categoryCode: string;
xml:string,
svg:string,
xml: string;
svg: string;
description: string;
}
-5
View File
@@ -35,9 +35,4 @@ export interface NodeConfigVO {
* 表单管理
*/
wfFormManageVo: FormManageVO;
}
+18 -18
View File
@@ -29,33 +29,33 @@ export const getPageByFinish = (query: ProcessInstanceQuery): AxiosPromise<Proce
};
/**
* 通过流程实例id获取历史流程图
* 通过业务id获取历史流程图
*/
export const getHistoryImage = (processInstanceId: string) => {
export const getHistoryImage = (businessKey: string) => {
return request({
url: `/workflow/processInstance/getHistoryImage/${processInstanceId}` + '?t' + Math.random(),
url: `/workflow/processInstance/getHistoryImage/${businessKey}` + '?t' + Math.random(),
method: 'get'
});
};
/**
* 通过流程实例id获取历史流程图运行中,历史等节点
* 通过业务id获取历史流程图运行中,历史等节点
*/
export const getHistoryList = (instanceId: string): AxiosPromise<Record<string, any>> => {
export const getHistoryList = (businessKey: string): AxiosPromise<Record<string, any>> => {
return request({
url: `/workflow/processInstance/getHistoryList/${instanceId}` + '?t' + Math.random(),
url: `/workflow/processInstance/getHistoryList/${businessKey}` + '?t' + Math.random(),
method: 'get'
});
};
/**
* 获取审批记录
* @param processInstanceId 流程实例id
* @param businessKey 业务id
* @returns
*/
export const getHistoryRecord = (processInstanceId: string) => {
export const getHistoryRecord = (businessKey: string | number) => {
return request({
url: `/workflow/processInstance/getHistoryRecord/${processInstanceId}`,
url: `/workflow/processInstance/getHistoryRecord/${businessKey}`,
method: 'get'
});
};
@@ -75,24 +75,24 @@ export const deleteRunInstance = (data: object) => {
/**
* 运行中的实例 删除程实例,删除历史记录,删除业务与流程关联信息
* @param processInstanceId 流程实例id
* @param businessKey 业务id
* @returns
*/
export const deleteRunAndHisInstance = (processInstanceId: string | string[]) => {
export const deleteRunAndHisInstance = (businessKey: string | string[]) => {
return request({
url: `/workflow/processInstance/deleteRunAndHisInstance/${processInstanceId}`,
url: `/workflow/processInstance/deleteRunAndHisInstance/${businessKey}`,
method: 'delete'
});
};
/**
* 已完成的实例 删除程实例,删除历史记录,删除业务与流程关联信息
* @param processInstanceId 流程实例id
* @param businessKey 业务id
* @returns
*/
export const deleteFinishAndHisInstance = (processInstanceId: string | string[]) => {
export const deleteFinishAndHisInstance = (businessKey: string | string[]) => {
return request({
url: `/workflow/processInstance/deleteFinishAndHisInstance/${processInstanceId}`,
url: `/workflow/processInstance/deleteFinishAndHisInstance/${businessKey}`,
method: 'delete'
});
};
@@ -112,12 +112,12 @@ export const getPageByCurrent = (query: ProcessInstanceQuery): AxiosPromise<Proc
/**
* 撤销流程
* @param processInstanceId 流程实例id
* @param businessKey 业务id
* @returns
*/
export const cancelProcessApply = (processInstanceId: string) => {
export const cancelProcessApply = (businessKey: string) => {
return request({
url: `/workflow/processInstance/cancelProcessApply/${processInstanceId}`,
url: `/workflow/processInstance/cancelProcessApply/${businessKey}`,
method: 'post'
});
};
+24 -24
View File
@@ -1,29 +1,29 @@
import { RouterJumpVo } from '@/api/workflow/workflowCommon/types';
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('请到模型配置菜单!');
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('请到模型配置菜单!');
}
}
}
};
@@ -40,7 +40,7 @@ class CustomContextPadProvider extends ContextPadProvider {
rules: Rules,
translate
) {
// @ts-ignore
// @ts-expect-error 忽略异常
super(config, injector, eventBus, contextPad, modeling, elementFactory, connect, create, popupMenu, canvas, rules, translate);
this._contextPad = contextPad;
+1 -1
View File
@@ -1,5 +1,5 @@
import showConfig from '../assets/showConfig';
import { ModdleElement } from 'bpmn';
import type { ModdleElement } from 'bpmn';
import useModelerStore from '@/store/modules/modeler';
import { MultiInstanceTypeEnum } from '@/enums/bpmn/IndexEnums';
interface Options {
+1 -1
View File
@@ -1,4 +1,4 @@
import { ModdleElement } from 'bpmn';
import type { ModdleElement } from 'bpmn';
interface Options {
element: ModdleElement;
+1 -1
View File
@@ -90,7 +90,7 @@ import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css';
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';
import './assets/style/index.scss';
import { Canvas, Modeler } from 'bpmn';
import type { Canvas, Modeler } from 'bpmn';
import PropertyPanel from './panel/index.vue';
import BpmnModeler from 'bpmn-js/lib/Modeler.js';
import defaultXML from './assets/defaultXML';
+2 -2
View File
@@ -41,8 +41,8 @@
<script setup lang="ts">
import useParseElement from '../hooks/useParseElement';
import usePanel from '../hooks/usePanel';
import { Modeler, ModdleElement } from 'bpmn';
import { GatewayPanel } from 'bpmnDesign';
import type { Modeler, ModdleElement } from 'bpmn';
import type { GatewayPanel } from 'bpmnDesign';
import ExecutionListener from './property/ExecutionListener.vue';
interface PropType {
+2 -2
View File
@@ -42,8 +42,8 @@
import useParseElement from '../hooks/useParseElement';
import usePanel from '../hooks/usePanel';
import ExecutionListener from './property/ExecutionListener.vue';
import { ModdleElement } from 'bpmn';
import { ParticipantPanel } from 'bpmnDesign';
import type { ModdleElement } from 'bpmn';
import type { ParticipantPanel } from 'bpmnDesign';
interface PropType {
element: ModdleElement;
+2 -2
View File
@@ -43,8 +43,8 @@
import ExecutionListener from './property/ExecutionListener.vue';
import useParseElement from '../hooks/useParseElement';
import usePanel from '../hooks/usePanel';
import { Modeler, ModdleElement } from 'bpmn';
import { ProcessPanel } from 'bpmnDesign';
import type { Modeler, ModdleElement } from 'bpmn';
import type { ProcessPanel } from 'bpmnDesign';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
+2 -2
View File
@@ -49,8 +49,8 @@ import useParseElement from '../hooks/useParseElement';
import useModelerStore from '@/store/modules/modeler';
import usePanel from '../hooks/usePanel';
import ExecutionListener from './property/ExecutionListener.vue';
import { Modeler, ModdleElement } from 'bpmn';
import { SequenceFlowPanel } from 'bpmnDesign';
import type { Modeler, ModdleElement } from 'bpmn';
import type { SequenceFlowPanel } from 'bpmnDesign';
interface PropType {
element: ModdleElement;
+2 -2
View File
@@ -42,8 +42,8 @@
import ExecutionListener from './property/ExecutionListener.vue';
import useParseElement from '../hooks/useParseElement';
import usePanel from '../hooks/usePanel';
import { Modeler, ModdleElement } from 'bpmn';
import { StartEndPanel } from 'bpmnDesign';
import type { Modeler, ModdleElement } from 'bpmn';
import type { StartEndPanel } from 'bpmnDesign';
interface PropType {
element: ModdleElement;
+2 -2
View File
@@ -111,8 +111,8 @@
import ExecutionListener from './property/ExecutionListener.vue';
import useParseElement from '../hooks/useParseElement';
import usePanel from '../hooks/usePanel';
import { ModdleElement } from 'bpmn';
import { SubProcessPanel } from 'bpmnDesign';
import type { ModdleElement } from 'bpmn';
import type { SubProcessPanel } from 'bpmnDesign';
import { MultiInstanceTypeEnum } from '@/enums/bpmn/IndexEnums';
interface PropType {
+3 -4
View File
@@ -243,8 +243,8 @@ import RoleSelect from '@/components/RoleSelect';
import ExecutionListener from './property/ExecutionListener.vue';
import TaskListener from './property/TaskListener.vue';
import DueDate from './property/DueDate.vue';
import { ModdleElement } from 'bpmn';
import { TaskPanel } from 'bpmnDesign';
import type { ModdleElement } from 'bpmn';
import type { TaskPanel } from 'bpmnDesign';
import { AllocationTypeEnum, MultiInstanceTypeEnum, SpecifyDescEnum } from '@/enums/bpmn/IndexEnums';
import { UserVO } from '@/api/system/user/types';
import { RoleVO } from '@/api/system/role/types';
@@ -281,12 +281,11 @@ const singleUserSelectRef = ref<InstanceType<typeof UserSelect>>();
const roleSelectRef = ref<InstanceType<typeof RoleSelect>>();
const dueDateRef = ref<InstanceType<typeof DueDate>>();
const isMultiple = ref(true);
const openUserSelect = () => {
userSelectRef.value.open();
};
const openSingleUserSelect = () => {
if (formData.value.assignee.includes('$')) {
if (formData.value.assignee?.includes('$')) {
formData.value.assignee = '';
}
singleUserSelectRef.value.open();
+1 -1
View File
@@ -13,7 +13,7 @@ import GatewayPanel from './GatewayPanel.vue';
import SequenceFlowPanel from './SequenceFlowPanel.vue';
import ParticipantPanel from './ParticipantPanel.vue';
import SubProcessPanel from './SubProcessPanel.vue';
import { Modeler, ModdleElement } from 'bpmn';
import type { Modeler, ModdleElement } from 'bpmn';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
interface propsType {
modeler: Modeler;
@@ -90,8 +90,8 @@
<script setup lang="ts">
import ListenerParam from './ListenerParam.vue';
import { VxeTableEvents, VxeTableInstance, VxeTablePropTypes } from 'vxe-table';
import { ExecutionListenerVO } from 'bpmnDesign';
import { Moddle, Modeler, ModdleElement } from 'bpmn';
import type { ExecutionListenerVO } from 'bpmnDesign';
import type { Moddle, Modeler, ModdleElement } from 'bpmn';
import usePanel from '../../hooks/usePanel';
import useDialog from '@/hooks/useDialog';
+1 -1
View File
@@ -47,7 +47,7 @@
<script setup lang="ts">
import { VXETable, VxeTableInstance, VxeTablePropTypes } from 'vxe-table';
import { ParamVO } from 'bpmnDesign';
import type { ParamVO } from 'bpmnDesign';
import useDialog from '@/hooks/useDialog';
interface PropType {
+2 -2
View File
@@ -91,8 +91,8 @@
<script setup lang="ts">
import ListenerParam from './ListenerParam.vue';
import { VxeTableEvents, VxeTableInstance, VxeTablePropTypes } from 'vxe-table';
import { TaskListenerVO } from 'bpmnDesign';
import { ModdleElement } from 'bpmn';
import type { TaskListenerVO } from 'bpmnDesign';
import type { ModdleElement } from 'bpmn';
import usePanel from '../../hooks/usePanel';
import useDialog from '@/hooks/useDialog';
+4 -3
View File
@@ -37,7 +37,7 @@ import BpmnViewer from 'bpmn-js/lib/Viewer';
import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas';
import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll';
import { ModuleDeclaration } from 'didi';
import { Canvas, ModdleElement } from 'bpmn';
import type { Canvas, ModdleElement } from 'bpmn';
import EventBus from 'diagram-js/lib/core/EventBus';
import Overlays from 'diagram-js/lib/features/overlays/Overlays';
import processApi from '@/api/workflow/processInstance/index';
@@ -51,7 +51,7 @@ const loading = ref(false);
const bpmnVisible = ref(true);
const historyList = ref([]);
const init = (instanceId) => {
const init = (businessKey) => {
loading.value = true;
bpmnVisible.value = true;
nextTick(async () => {
@@ -67,7 +67,7 @@ const init = (instanceId) => {
MoveCanvasModule
] as ModuleDeclaration[]
});
const resp = await processApi.getHistoryList(instanceId);
const resp = await processApi.getHistoryList(businessKey);
xml.value = resp.data.xml;
taskList.value = resp.data.taskList;
historyList.value = resp.data.historyList;
@@ -133,6 +133,7 @@ const genNodeDetailBox = (e, overlays, data) => {
<p>开始时间:${data.startTime || ''}</p>
<p>结束时间:${data.endTime || ''}</p>
<p>审批耗时:${data.runDuration || ''}</p>
<p>流程版本:v${data.version || ''}</p>
</div>`
});
};
+1 -1
View File
@@ -110,7 +110,7 @@ watch(
() => props.modelValue,
(v: string) => {
if (v !== content.value) {
content.value = v === undefined ? '<p></p>' : v;
content.value = v || '<p></p>';
}
},
{ immediate: true }
+1 -1
View File
@@ -38,7 +38,7 @@ const realSrcList = computed(() => {
let real_src_list = props.src.split(',');
let srcList: string[] = [];
real_src_list.forEach((item: string) => {
if(item.trim() === '') {
if (item.trim() === '') {
return;
}
return srcList.push(item);
+3 -3
View File
@@ -67,17 +67,17 @@ const tabActiveName = ref('bpmn');
const bpmnViewRef = ref<BpmnView>();
//初始化查询审批记录
const init = async (instanceId: string) => {
const init = async (businessKey: string | number) => {
visible.value = true;
loading.value = true;
tabActiveName.value = 'bpmn';
historyList.value = [];
processApi.getHistoryRecord(instanceId).then((resp) => {
processApi.getHistoryRecord(businessKey).then((resp) => {
historyList.value = resp.data;
loading.value = false;
});
await nextTick(() => {
bpmnViewRef.value.init(instanceId);
bpmnViewRef.value.init(businessKey);
});
};
+36 -26
View File
@@ -1,22 +1,28 @@
<template>
<el-dialog v-model="visible" draggable :title="title" :width="width" :height="height" append-to-body
:close-on-click-modal="false">
<div class="p-2" v-if="multiInstance === 'add'">
<el-dialog v-model="visible" draggable :title="title" :width="width" :height="height" append-to-body :close-on-click-modal="false">
<div v-if="multiInstance === 'add'" class="p-2">
<el-row :gutter="20">
<!-- 部门树 -->
<el-col :lg="4" :xs="24" style="">
<el-card shadow="hover">
<el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
<el-tree class="mt-2" ref="deptTreeRef" node-key="id" :data="deptOptions"
:props="{ label: 'label', children: 'children' }" :expand-on-click-node="false"
:filter-node-method="filterNode" highlight-current default-expand-all
@node-click="handleNodeClick"></el-tree>
<el-tree
ref="deptTreeRef"
class="mt-2"
node-key="id"
:data="deptOptions"
:props="{ label: 'label', children: 'children' }"
:expand-on-click-node="false"
:filter-node-method="filterNode"
highlight-current
default-expand-all
@node-click="handleNodeClick"
></el-tree>
</el-card>
</el-col>
<el-col :lg="20" :xs="24">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter"
:leave-active-class="proxy?.animate.searchAnimate.leave">
<div class="search" v-show="showSearch">
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
<div v-show="showSearch" class="search">
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
<el-form-item label="用户名称" prop="userName">
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
@@ -25,8 +31,8 @@
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleQuery" icon="Search">搜索</el-button>
<el-button @click="resetQuery" icon="Refresh">重置</el-button>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
</div>
@@ -35,17 +41,16 @@
<el-card shadow="hover">
<template #header>
<el-row :gutter="10">
<right-toolbar v-model:showSearch="showSearch" @queryTable="handleQuery" :search="true"></right-toolbar>
<right-toolbar v-model:showSearch="showSearch" :search="true" @query-table="handleQuery"></right-toolbar>
</el-row>
</template>
<el-table v-loading="loading" :data="userList" ref="multipleTableRef" row-key="userId"
@selection-change="handleSelectionChange">
<el-table ref="multipleTableRef" v-loading="loading" :data="userList" row-key="userId" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="50" align="center" />
<el-table-column label="用户编号" align="center" key="userId" prop="userId" />
<el-table-column label="用户名称" align="center" key="userName" prop="userName" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" width="120" />
<el-table-column key="userId" label="用户编号" align="center" prop="userId" />
<el-table-column key="userName" label="用户名称" align="center" prop="userName" :show-overflow-tooltip="true" />
<el-table-column key="nickName" label="用户昵称" align="center" prop="nickName" :show-overflow-tooltip="true" />
<el-table-column key="phonenumber" label="手机号码" align="center" prop="phonenumber" width="120" />
<el-table-column label="创建时间" align="center" prop="createTime" width="160">
<template #default="scope">
<span>{{ scope.row.createTime }}</span>
@@ -53,18 +58,23 @@
</el-table-column>
</el-table>
<pagination v-show="total > 0" :total="total" v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize" @pagination="handleQuery" />
<pagination
v-show="total > 0"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
:total="total"
@pagination="handleQuery"
/>
</el-card>
<el-card shadow="hover">
<el-tag v-for="(user, index) in chooseUserList" :key="user.userId" style="margin:2px" closable
@close="handleCloseTag(user, index)">{{ user.userName }}
<el-tag v-for="(user, index) in chooseUserList" :key="user.userId" style="margin: 2px" closable @close="handleCloseTag(user, index)"
>{{ user.userName }}
</el-tag>
</el-card>
</el-col>
</el-row>
</div>
<div class="p-2" v-if="multiInstance === 'delete'">
<div v-if="multiInstance === 'delete'" class="p-2">
<el-table v-loading="loading" :data="taskList" @selection-change="handleTaskSelection">
<el-table-column type="selection" width="55" />
<el-table-column prop="name" label="任务名称" />
@@ -118,7 +128,7 @@ const props = defineProps({
//回显用户id
userIdList: {
type: Array,
default: []
default: () => []
}
});
const deptTreeRef = ref(ElTree);
@@ -285,7 +295,7 @@ const handleNodeClick = (data: DeptVO) => {
//删除tag
const handleCloseTag = (user: UserVO, index: any) => {
if (multipleTableRef.value.selection && multipleTableRef.value.selection.length > 0) {
multipleTableRef.value.selection.forEach((u: UserVO, i: Number) => {
multipleTableRef.value.selection.forEach((u: UserVO, i: number) => {
if (user.userId === u.userId) {
multipleTableRef.value.selection.splice(i, 1);
}
+101 -88
View File
@@ -8,29 +8,43 @@
<el-checkbox label="3" name="type">短信</el-checkbox>
</el-checkbox-group>
</el-form-item>
<el-form-item label="附件" v-if="task.businessStatus === 'waiting'">
<fileUpload v-model="form.fileId" :fileType="['doc', 'xls', 'ppt', 'txt', 'pdf', 'xlsx', 'docx', 'zip']" :fileSize="'20'"/>
<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>
<el-form-item label="抄送">
<el-button type="primary" @click="openUserSelectCopy" icon="Plus" circle />
<el-tag v-for="user in selectCopyUserList" :key="user.userId" closable style="margin: 2px" @close="handleCopyCloseTag(user)">
{{ user.userName }}
</el-tag>
<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 }}
</el-tag>
</el-form-item>
<el-form-item label="审批意见" v-if="task.businessStatus === 'waiting'">
<el-form-item v-if="task.businessStatus === '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 v-loading="buttonLoading" type="primary" @click="handleCompleteTask"> 提交 </el-button>
<el-button v-if="task.businessStatus === 'waiting'" v-loading="buttonLoading" type="primary" @click="openDelegateTask"> 委托 </el-button>
<el-button v-if="task.businessStatus === 'waiting'" v-loading="buttonLoading" type="primary" @click="openTransferTask"> 转办 </el-button>
<el-button v-if="task.businessStatus === 'waiting' && task.multiInstance" v-loading="buttonLoading" type="primary" @click="addMultiInstanceUser"> 加签 </el-button>
<el-button v-if="task.businessStatus === 'waiting' && task.multiInstance" v-loading="buttonLoading" type="primary" @click="deleteMultiInstanceUser"> 减签 </el-button>
<el-button v-if="task.businessStatus === 'waiting'" v-loading="buttonLoading" type="danger" @click="handleTerminationTask"> 终止 </el-button>
<el-button v-if="task.businessStatus === 'waiting'" v-loading="buttonLoading" type="danger" @click="handleBackProcessOpen"> 退回 </el-button>
<el-button v-loading="buttonLoading" @click="cancel">取消</el-button>
<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.businessStatus === 'waiting' && task.multiInstance"
:disabled="buttonDisabled"
type="primary"
@click="addMultiInstanceUser"
>
加签
</el-button>
<el-button
v-if="task.businessStatus === 'waiting' && task.multiInstance"
:disabled="buttonDisabled"
type="primary"
@click="deleteMultiInstanceUser"
>
减签
</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 :disabled="buttonDisabled" @click="cancel">取消</el-button>
</span>
</template>
<!-- 抄送 -->
@@ -40,19 +54,14 @@
<!-- 委托 -->
<UserSelect ref="delegateTaskRef" :multiple="false" @confirm-call-back="handleDelegateTask"></UserSelect>
<!-- 加签组件 -->
<multiInstanceUser ref="multiInstanceUserRef" :title="title" @submit-callback='closeDialog' />
<multiInstanceUser ref="multiInstanceUserRef" :title="title" @submit-callback="closeDialog" />
<!-- 驳回开始 -->
<el-dialog v-model="backVisible" draggable title="驳回" width="40%" :close-on-click-modal="false">
<el-form v-loading="backLoading" :model="backForm" label-width="120px" v-if="task.businessStatus === 'waiting'">
<el-form v-if="task.businessStatus === 'waiting'" v-loading="backLoading" :model="backForm" label-width="120px">
<el-form-item label="驳回节点">
<el-select clearable placeholder="请选择" v-model="backForm.targetActivityId" style="width: 300px">
<el-option
v-for="item in taskNodeList"
:key="item.nodeId"
:label="item.nodeName"
:value="item.nodeId"
/>
<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>
</el-form-item>
<el-form-item label="消息提醒">
@@ -67,9 +76,9 @@
</el-form-item>
</el-form>
<template #footer>
<div class="dialog-footer" style="float: right;padding-bottom: 20px;">
<el-button type="primary" v-loading="backLoading" @click="handleBackProcess">确认</el-button>
<el-button v-loading="backLoading" @click="backVisible = false">取消</el-button>
<div class="dialog-footer" style="float: right; padding-bottom: 20px">
<el-button :disabled="backButtonDisabled" type="primary" @click="handleBackProcess">确认</el-button>
<el-button :disabled="backButtonDisabled" @click="backVisible = false">取消</el-button>
</div>
</template>
</el-dialog>
@@ -81,7 +90,7 @@
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, getTaskById, transferTask, terminationTask, getTaskNodeList, delegateTask } from '@/api/workflow/task';
import UserSelect from '@/components/UserSelect';
import MultiInstanceUser from '@/components/Process/multiInstanceUser.vue';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -91,19 +100,19 @@ 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 props = defineProps({
taskVariables: {
type: Object as () => Record<string, any>,
default: {}
default: () => {}
}
});
//遮罩层
const loading = ref(true);
//按钮
const buttonLoading = ref(true);
const buttonDisabled = ref(true);
//任务id
const taskId = ref<string>('');
//抄送人
@@ -113,6 +122,7 @@ const selectCopyUserIds = ref<string>(undefined);
// 驳回是否显示
const backVisible = ref(false);
const backLoading = ref(true);
const backButtonDisabled = ref(true);
// 可驳回得任务节点
const taskNodeList = ref([]);
//任务
@@ -166,23 +176,23 @@ const backForm = ref<Record<string, any>>({
messageType: ['1']
});
const closeDialog = () => {
dialog.visible = false
}
dialog.visible = false;
};
//打开弹窗
const openDialog = (id?: string) => {
selectCopyUserIds.value = undefined
selectCopyUserList.value = []
form.value.fileId = undefined
selectCopyUserIds.value = undefined;
selectCopyUserList.value = [];
form.value.fileId = undefined;
taskId.value = id;
form.value.message = undefined;
dialog.visible = true;
loading.value = true;
buttonLoading.value = true;
buttonDisabled.value = true;
nextTick(() => {
getTaskById(taskId.value).then((response) => {
task.value = response.data;
loading.value = false;
buttonLoading.value = false;
buttonDisabled.value = false;
});
});
};
@@ -194,58 +204,62 @@ const emits = defineEmits(['submitCallback', 'cancelCallback']);
const handleCompleteTask = async () => {
form.value.taskId = taskId.value;
form.value.taskVariables = props.taskVariables;
if(selectCopyUserList && selectCopyUserList.value.length > 0){
let wfCopyList = []
selectCopyUserList.value.forEach( e=> {
if (selectCopyUserList.value && selectCopyUserList.value.length > 0) {
let wfCopyList = [];
selectCopyUserList.value.forEach((e) => {
let copyUser = {
userId: e.userId,
userName: e.nickName
}
wfCopyList.push(copyUser)
})
form.value.wfCopyList = wfCopyList
};
wfCopyList.push(copyUser);
});
form.value.wfCopyList = wfCopyList;
}
await proxy?.$modal.confirm('是否确认提交?');
loading.value = true;
buttonLoading.value = true;
buttonDisabled.value = true;
try {
await completeTask(form.value);
dialog.visible = false;
emits('submitCallback');
proxy?.$modal.msgSuccess('操作成功');
} finally {
loading.value = false
buttonLoading.value = false
loading.value = false;
buttonDisabled.value = false;
}
};
/** 驳回弹窗打开 */
const handleBackProcessOpen = async () => {
backForm.value = {}
backForm.value.messageType = ['1']
backVisible.value = true
backLoading.value = true
let data = await getTaskNodeList(task.value.processInstanceId)
taskNodeList.value = data.data
backLoading.value = false
backForm.value.targetActivityId = taskNodeList.value[0].nodeId
}
backForm.value = {};
backForm.value.messageType = ['1'];
backVisible.value = true;
backLoading.value = true;
backButtonDisabled.value = true;
let data = await getTaskNodeList(task.value.processInstanceId);
taskNodeList.value = data.data;
backLoading.value = false;
backButtonDisabled.value = false;
backForm.value.targetActivityId = taskNodeList.value[0].nodeId;
};
/** 驳回流程 */
const handleBackProcess = async () => {
backForm.value.taskId = taskId.value;
await proxy?.$modal.confirm('是否确认驳回到申请人?');
loading.value = true;
backLoading.value = true;
backButtonDisabled.value = true;
await backProcess(backForm.value).finally(() => (loading.value = false));
dialog.visible = false;
backLoading.value = false
backLoading.value = false;
backButtonDisabled.value = false;
emits('submitCallback');
proxy?.$modal.msgSuccess('操作成功');
};
//取消
const cancel = async () => {
dialog.visible = false;
buttonLoading.value = false;
buttonDisabled.value = false;
emits('cancelCallback');
};
//打开抄送人员
@@ -254,11 +268,11 @@ const openUserSelectCopy = () => {
};
//确认抄送人员
const userSelectCopyCallBack = (data: UserVO[]) => {
if(data && data.length > 0){
selectCopyUserList.value = data
if (data && data.length > 0) {
selectCopyUserList.value = data;
selectCopyUserIds.value = selectCopyUserList.value.map((item) => item.userId).join(',');
}
}
};
//删除抄送人员
const handleCopyCloseTag = (user: UserVO) => {
const userId = user.userId;
@@ -286,63 +300,62 @@ const openTransferTask = () => {
transferTaskRef.value.open();
};
//转办
const handleTransferTask = async (data) => {
if(data && data.length > 0){
const handleTransferTask = async (data) => {
if (data && data.length > 0) {
let params = {
taskId: taskId.value,
userId: data[0].userId,
comment: form.value.message
}
};
await proxy?.$modal.confirm('是否确认提交?');
loading.value = true;
buttonLoading.value = true;
buttonDisabled.value = true;
await transferTask(params).finally(() => (loading.value = false));
dialog.visible = false;
emits('submitCallback');
proxy?.$modal.msgSuccess('操作成功');
}else{
} else {
proxy?.$modal.msgWarning('请选择用户!');
}
}
};
//打开委托
const openDelegateTask = () => {
delegateTaskRef.value.open();
};
//委托
const handleDelegateTask = async (data) => {
if(data && data.length > 0){
const handleDelegateTask = async (data) => {
if (data && data.length > 0) {
let params = {
taskId: taskId.value,
userId: data[0].userId,
nickName: data[0].nickName
}
};
await proxy?.$modal.confirm('是否确认提交?');
loading.value = true;
buttonLoading.value = true;
buttonDisabled.value = true;
await delegateTask(params).finally(() => (loading.value = false));
dialog.visible = false;
emits('submitCallback');
proxy?.$modal.msgSuccess('操作成功');
}else{
} else {
proxy?.$modal.msgWarning('请选择用户!');
}
}
};
//终止任务
const handleTerminationTask = async (data) => {
let params = {
taskId: taskId.value,
comment: form.value.message
}
await proxy?.$modal.confirm('是否确认终止?');
loading.value = true;
buttonLoading.value = true;
await terminationTask(params).finally(() => (loading.value = false));
dialog.visible = false;
emits('submitCallback');
proxy?.$modal.msgSuccess('操作成功');
}
const handleTerminationTask = async (data) => {
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));
dialog.visible = false;
emits('submitCallback');
proxy?.$modal.msgSuccess('操作成功');
};
/**
* 对外暴露子组件方法
+9 -17
View File
@@ -29,16 +29,11 @@
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input
v-model="queryParams.phonenumber"
placeholder="请输入手机号码"
clearable
@keyup.enter="handleQuery"
/>
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
<el-button icon="Refresh" @click="() => resetQuery()">重置</el-button>
</el-form-item>
</el-form>
</el-card>
@@ -223,13 +218,13 @@ const handleQuery = () => {
getList();
};
/** 重置按钮操作 */
const resetQuery = () => {
const resetQuery = (refresh = true) => {
dateRange.value = ['', ''];
queryFormRef.value?.resetFields();
queryParams.value.pageNum = 1;
queryParams.value.deptId = undefined;
deptTreeRef.value?.setCurrentKey(undefined);
handleQuery();
refresh && handleQuery();
};
const handleCheckboxChange = (checked) => {
@@ -288,23 +283,20 @@ const close = () => {
watch(
() => userDialog.visible.value,
(newValue: boolean) => {
async (newValue: boolean) => {
if (newValue) {
initSelectUser();
await getTreeSelect(); // 初始化部门数据
await getList(); // 初始化列表数据
await initSelectUser();
} else {
tableRef.value.clearCheckboxReserve();
tableRef.value.clearCheckboxRow();
resetQuery();
resetQuery(false);
selectUserList.value = [];
}
}
);
onMounted(() => {
getTreeSelect(); // 初始化部门数据
getList(); // 初始化列表数据
});
defineExpose({
open: userDialog.openDialog,
close: userDialog.closeDialog
+1 -1
View File
@@ -28,4 +28,4 @@ export default (ops?: Options): Return => {
openDialog,
closeDialog
};
};
};
+7 -7
View File
@@ -1,13 +1,13 @@
<template>
<section class="app-main">
<router-view v-slot="{ Component, route }">
<transition :enter-active-class="animante" mode="out-in">
<div>
<keep-alive :include="tagsViewStore.cachedViews" v-if="!route.meta.noCache">
<component v-if="!route.meta.link" :is="Component" :key="route.path" />
</keep-alive>
<component v-if="!route.meta.link && route.meta.noCache" :is="Component" :key="route.path" />
</div>
<transition v-if="!route.meta.noCache" :enter-active-class="animante" mode="out-in">
<keep-alive v-if="!route.meta.noCache" :include="tagsViewStore.cachedViews">
<component :is="Component" v-if="!route.meta.link" :key="route.path" />
</keep-alive>
</transition>
<transition v-if="route.meta.noCache" :enter-active-class="animante" mode="out-in">
<component :is="Component" v-if="!route.meta.link && route.meta.noCache" :key="route.path" />
</transition>
</router-view>
<iframe-toggle />
+13 -2
View File
@@ -17,7 +17,9 @@ const loading = ref(true);
const code = route.query.code as string;
const state = route.query.state as string;
const source = route.query.source as string;
const tenantId = localStorage.getItem('tenantId') ? (localStorage.getItem('tenantId') as string) : '000000';
const stateJson = JSON.parse(atob(state));
const tenantId = (stateJson.tenantId as string) ? (stateJson.tenantId as string) : '000000';
const domain = stateJson.domain as string;
const processResponse = async (res: any) => {
if (res.code !== 200) {
@@ -60,12 +62,21 @@ const loginByCode = async (data: LoginData) => {
};
const init = async () => {
// 如果域名不相等 则重定向处理
let host = window.location.host;
if (domain !== host) {
let urlFull = new URL(window.location.href);
urlFull.host = domain;
window.location.href = urlFull.toString();
return;
}
const data: LoginData = {
socialCode: code,
socialState: state,
tenantId: tenantId,
source: source,
clientId: 'e5cd7e4891bf95d1d19206ce24a7b32e',
clientId: import.meta.env.VITE_APP_CLIENT_ID,
grantType: 'social'
};
+1 -1
View File
@@ -53,7 +53,7 @@ router.beforeEach(async (to, from, next) => {
next();
} else {
const redirect = encodeURIComponent(to.fullPath || '/');
next(`/login?redirect=${redirect}`) // 否则全部重定向到登录页
next(`/login?redirect=${redirect}`); // 否则全部重定向到登录页
NProgress.done();
}
}
+3 -3
View File
@@ -164,16 +164,16 @@ export const dynamicRoutes: RouteRecordRaw[] = [
]
},
{
path: '/demo/leaveEdit',
path: '/workflow/leaveEdit',
component: Layout,
hidden: true,
permissions: ['demo:leave:edit'],
permissions: ['workflow:leave:edit'],
children: [
{
path: 'index',
component: () => import('@/views/workflow/leave/leaveEdit.vue'),
name: 'leaveEdit',
meta: { title: '请假申请', activeMenu: '/demo/leave', noCache: true }
meta: { title: '请假申请', activeMenu: '/workflow/leave', noCache: true }
}
]
}
+1 -1
View File
@@ -1,4 +1,4 @@
import { Modeler, Modeling, Canvas, ElementRegistry, Moddle, BpmnFactory } from 'bpmn';
import type { Modeler, Modeling, Canvas, ElementRegistry, Moddle, BpmnFactory } from 'bpmn';
type ModelerStore = {
modeler: Modeler | undefined;
+51 -3
View File
@@ -9,6 +9,8 @@ import Layout from '@/layout/index.vue';
import ParentView from '@/components/ParentView/index.vue';
import InnerLink from '@/layout/components/InnerLink/index.vue';
import { createCustomNameComponent } from '@/utils/createCustomNameComponent';
// 匹配views里面所有的.vue文件
const modules = import.meta.glob('./../../views/**/*.vue');
export const usePermissionStore = defineStore('permission', () => {
@@ -58,6 +60,8 @@ export const usePermissionStore = defineStore('permission', () => {
setSidebarRouters(constantRoutes.concat(sidebarRoutes));
setDefaultRoutes(sidebarRoutes);
setTopbarRoutes(defaultRoutes);
// 路由name重复检查
duplicateRouteChecker(asyncRoutes, sidebarRoutes);
return new Promise<RouteRecordRaw[]>((resolve) => resolve(rewriteRoutes));
};
@@ -80,7 +84,7 @@ export const usePermissionStore = defineStore('permission', () => {
} else if (route.component?.toString() === 'InnerLink') {
route.component = InnerLink;
} else {
route.component = loadView(route.component);
route.component = loadView(route.component, route.name as string);
}
if (route.children != null && route.children && route.children.length) {
route.children = filterAsyncRouter(route.children, route, type);
@@ -151,12 +155,12 @@ export const filterDynamicRoutes = (routes: RouteRecordRaw[]) => {
return res;
};
export const loadView = (view: any) => {
export const loadView = (view: any, name: string) => {
let res;
for (const path in modules) {
const dir = path.split('views/')[1].split('.vue')[0];
if (dir === view) {
res = () => modules[path]();
res = createCustomNameComponent(modules[path], { name });
}
}
return res;
@@ -167,4 +171,48 @@ export const usePermissionStoreHook = () => {
return usePermissionStore(store);
};
interface Route {
name?: string | symbol;
path: string;
children?: Route[];
}
/**
* 检查路由name是否重复
* @param localRoutes 本地路由
* @param routes 动态路由
*/
function duplicateRouteChecker(localRoutes: Route[], routes: Route[]) {
// 展平
function flatRoutes(routes: Route[]) {
const res: Route[] = [];
routes.forEach((route) => {
if (route.children) {
res.push(...flatRoutes(route.children));
} else {
res.push(route);
}
});
return res;
}
const allRoutes = flatRoutes([...localRoutes, ...routes]);
const nameList: string[] = [];
allRoutes.forEach((route) => {
const name = route.name.toString();
if (name && nameList.includes(name)) {
const message = `路由名称: [${name}] 重复, 会造成 404`;
console.error(message);
ElNotification({
title: '路由名称重复',
message,
type: 'error'
});
return;
}
nameList.push(route.name.toString());
});
}
export default usePermissionStore;
+3
View File
@@ -10,6 +10,7 @@ export const useUserStore = defineStore('user', () => {
const name = ref('');
const nickname = ref('');
const userId = ref<string | number>('');
const tenantId = ref<string>('');
const avatar = ref('');
const roles = ref<Array<string>>([]); // 用户角色编码集合 → 判断路由权限
const permissions = ref<Array<string>>([]); // 用户权限编码集合 → 判断按钮权限
@@ -49,6 +50,7 @@ export const useUserStore = defineStore('user', () => {
nickname.value = user.nickName;
avatar.value = profile;
userId.value = user.userId;
tenantId.value = user.tenantId;
return Promise.resolve();
}
return Promise.reject(err);
@@ -69,6 +71,7 @@ export const useUserStore = defineStore('user', () => {
return {
userId,
tenantId,
token,
nickname,
avatar,
+2 -3
View File
@@ -11,9 +11,8 @@ interface ImportMetaEnv {
VITE_APP_BASE_API: string;
VITE_APP_BASE_URL: string;
VITE_APP_CONTEXT_PATH: string;
VITE_APP_MONITRO_ADMIN: string;
VITE_APP_POWERJOB_ADMIN: string;
VITE_APP_EASYRETRY_ADMIN: string;
VITE_APP_MONITOR_ADMIN: string;
VITE_APP_SNAILJOB_ADMIN: string;
VITE_APP_ENV: string;
VITE_APP_ENCRYPT: string;
VITE_APP_RSA_PUBLIC_KEY: string;
-2
View File
@@ -4,8 +4,6 @@ import { LanguageEnum } from '@/enums/LanguageEnum';
declare global {
/** vue Instance */
declare type ComponentInternalInstance = ComponentInstance;
/**vue */
declare type PropType<T> = VuePropType<T>;
/**
* 界面字段隐藏属性
+39
View File
@@ -0,0 +1,39 @@
/**
* 后台返回的路由动态生成name 解决缓存问题
* 感谢 @fourteendp
* 详见 https://github.com/vbenjs/vue-vben-admin/issues/3927
*/
import { Component, defineComponent, h } from 'vue';
interface Options {
name?: string;
}
export function createCustomNameComponent(loader: () => Promise<any>, options: Options = {}): () => Promise<Component> {
const { name } = options;
let component: Component | null = null;
const load = async () => {
try {
const { default: loadedComponent } = await loader();
component = loadedComponent;
} catch (error) {
console.error(`Cannot resolve component ${name}, error:`, error);
}
};
return async () => {
if (!component) {
await load();
}
return Promise.resolve(
defineComponent({
name,
render() {
return h(component as Component);
}
})
);
};
}
+2 -3
View File
@@ -33,7 +33,7 @@
* 部署方式 Docker 容器编排 一键部署业务集群<br />
* 国际化 SpringMessage Spring标准国际化方案<br />
</p>
<p><b>当前版本:</b> <span>v5.2.0-BETA</span></p>
<p><b>当前版本:</b> <span>v5.2.1</span></p>
<p>
<el-tag type="danger">&yen;免费开源</el-tag>
</p>
@@ -68,7 +68,6 @@
* RPC远程调用 Apache Dubbo 原生态使用体验、高性能<br />
* 分布式限流熔断 Alibaba Sentinel 无侵入、高扩展<br />
* 分布式事务 Alibaba Seata 无侵入、高扩展 支持 四种模式<br />
* 分布式消息队列 Spring Cloud Stream 门面框架兼容各种MQ集成<br />
* 分布式消息队列 Apache Kafka 高性能高速度<br />
* 分布式消息队列 Apache RocketMQ 高可用功能多样<br />
* 分布式消息队列 RabbitMQ 支持各种扩展插件功能多样性<br />
@@ -78,7 +77,7 @@
* 分布式监控 Prometheus、Grafana 全方位性能监控<br />
* 其余与 Vue 版本一致<br />
</p>
<p><b>当前版本:</b> <span>v2.2.0-BETA</span></p>
<p><b>当前版本:</b> <span>v2.2.0</span></p>
<p>
<el-tag type="danger">&yen;免费开源</el-tag>
</p>
+1 -9
View File
@@ -186,20 +186,12 @@ const initTenantList = async () => {
}
};
//检测租户选择框的变化
watch(
() => loginForm.value.tenantId,
() => {
localStorage.setItem('tenantId', String(loginForm.value.tenantId));
}
);
/**
* 第三方登录
* @param type
*/
const doSocialLogin = (type: string) => {
authBinding(type).then((res: any) => {
authBinding(type, loginForm.value.tenantId).then((res: any) => {
if (res.code === HttpStatus.SUCCESS) {
// 获取授权地址跳转
window.location.href = res.data;
+1 -1
View File
@@ -5,5 +5,5 @@
</template>
<script setup lang="ts">
const url = ref(import.meta.env.VITE_APP_MONITRO_ADMIN);
const url = ref(import.meta.env.VITE_APP_MONITOR_ADMIN);
</script>
+1 -1
View File
@@ -11,7 +11,7 @@
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="登录状态" clearable >
<el-select v-model="queryParams.status" placeholder="登录状态" clearable>
<el-option v-for="dict in sys_common_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
+2 -2
View File
@@ -14,12 +14,12 @@
<el-input v-model="queryParams.operName" placeholder="请输入操作人员" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="类型" prop="businessType">
<el-select v-model="queryParams.businessType" placeholder="操作类型" clearable >
<el-select v-model="queryParams.businessType" placeholder="操作类型" clearable>
<el-option v-for="dict in sys_oper_type" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="操作状态" clearable >
<el-select v-model="queryParams.status" placeholder="操作状态" clearable>
<el-option v-for="dict in sys_common_status" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
+1 -1
View File
@@ -10,7 +10,7 @@
<el-input v-model="queryParams.clientSecret" placeholder="请输入客户端秘钥" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="状态" clearable >
<el-select v-model="queryParams.status" placeholder="状态" clearable>
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
+1 -1
View File
@@ -11,7 +11,7 @@
<el-input v-model="queryParams.configKey" placeholder="请输入参数键名" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="系统内置" prop="configType">
<el-select v-model="queryParams.configType" placeholder="系统内置" clearable >
<el-select v-model="queryParams.configType" placeholder="系统内置" clearable>
<el-option v-for="dict in sys_yes_no" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
+1 -1
View File
@@ -11,7 +11,7 @@
<el-input v-model="queryParams.deptCategory" placeholder="请输入类别编码" clearable style="width: 240px" @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="部门状态" clearable >
<el-select v-model="queryParams.status" placeholder="部门状态" clearable>
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
+1 -1
View File
@@ -8,7 +8,7 @@
<el-input v-model="queryParams.menuName" placeholder="请输入菜单名称" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="菜单状态" clearable >
<el-select v-model="queryParams.status" placeholder="菜单状态" clearable>
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
+4 -4
View File
@@ -13,7 +13,7 @@
<el-form-item label="文件后缀" prop="fileSuffix">
<el-input v-model="queryParams.fileSuffix" placeholder="请输入文件后缀" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="创建时间" style="width: 308px;">
<el-form-item label="创建时间" style="width: 308px">
<el-date-picker
v-model="dateRangeCreateTime"
value-format="YYYY-MM-DD HH:mm:ss"
@@ -198,9 +198,9 @@ const getList = async () => {
showTable.value = true;
};
function checkFileSuffix(fileSuffix: string | string[]) {
const arr = [".png", ".jpg", ".jpeg"];
const arr = ['.png', '.jpg', '.jpeg'];
const suffixArray = Array.isArray(fileSuffix) ? fileSuffix : [fileSuffix];
return suffixArray.some(suffix => arr.includes(suffix.toLowerCase()));
return suffixArray.some((suffix) => arr.includes(suffix.toLowerCase()));
}
/** 取消按钮 */
function cancel() {
@@ -304,7 +304,7 @@ const submitForm = () => {
const handleDownload = (row: OssVO) => {
proxy?.$download.oss(row.ossId);
};
/** 用户状态修改 */
/** 预览开关按钮 */
const handlePreviewListResource = async (preview: boolean) => {
let text = preview ? '启用' : '停用';
try {
+1 -1
View File
@@ -11,7 +11,7 @@
<el-input v-model="queryParams.roleKey" placeholder="请输入权限字符" clearable @keyup.enter="handleQuery" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="角色状态" clearable >
<el-select v-model="queryParams.status" placeholder="角色状态" clearable>
<el-option v-for="dict in sys_normal_disable" :key="dict.value" :label="dict.label" :value="dict.value" />
</el-select>
</el-form-item>
+3 -3
View File
@@ -58,8 +58,8 @@
<el-tab-pane label="第三方应用" name="thirdParty">
<thirdParty :auths="state.auths" />
</el-tab-pane>
<el-tab-pane label="在线设备" name="onlinDevice">
<onlinDevice :devices="state.devices" />
<el-tab-pane label="在线设备" name="onlineDevice">
<onlineDevice :devices="state.devices" />
</el-tab-pane>
</el-tabs>
</el-card>
@@ -73,7 +73,7 @@ import UserAvatar from './userAvatar.vue';
import UserInfo from './userInfo.vue';
import ResetPwd from './resetPwd.vue';
import ThirdParty from './thirdParty.vue';
import OnlinDevice from './onlineDevice.vue';
import OnlineDevice from './onlineDevice.vue';
import { getAuthList } from '@/api/system/social/auth';
import { getUserProfile } from '@/api/system/user';
import { getOnline } from '@/api/monitor/online';
@@ -18,8 +18,7 @@
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="删除" placement="top">
<el-button link type="primary" icon="Delete" @click="handldDelOnline(scope.row)">
</el-button>
<el-button link type="primary" icon="Delete" @click="handldDelOnline(scope.row)"> </el-button>
</el-tooltip>
</template>
</el-table-column>
@@ -55,5 +54,4 @@ const handldDelOnline = (row: any) => {
})
.catch(() => {});
};
</script>
+1 -1
View File
@@ -45,7 +45,7 @@ const rules = ref({
message: '长度在 6 到 20 个字符',
trigger: 'blur'
},
{ pattern: /^[^<>"'|\\]+$/, message: "不能包含非法字符:< > \" ' \\\ |", trigger: "blur" }
{ pattern: /^[^<>"'|\\]+$/, message: '不能包含非法字符:< > " \' \\\ |', trigger: 'blur' }
],
confirmPassword: [
{ required: true, message: '确认密码不能为空', trigger: 'blur' },
+2 -1
View File
@@ -58,6 +58,7 @@
<script lang="ts" setup>
import { authUnlock, authBinding } from '@/api/system/social/auth';
import { propTypes } from '@/utils/propTypes';
import useUserStore from '@/store/modules/user';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
@@ -83,7 +84,7 @@ const unlockAuth = (row: any) => {
};
const authUrl = (source: string) => {
authBinding(source).then((res: any) => {
authBinding(source, useUserStore().tenantId).then((res: any) => {
if (res.code === 200) {
window.location.href = res.data;
} else {
-3
View File
@@ -1,3 +0,0 @@
<template>
<div>表单构建(由于此功能的开源组件不支持 VUE3+TS 故暂时无法使用) <svg-icon icon-class="build" /></div>
</template>
+4 -4
View File
@@ -46,7 +46,7 @@
</template>
</el-table-column>
<el-table-column label="地址" align="center" prop="router" />
<el-table-column label="备注" align="center" prop="remork" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-tooltip content="修改" placement="top">
@@ -82,8 +82,8 @@
</template>
</el-input>
</el-form-item>
<el-form-item label="备注" prop="remork">
<el-input v-model="form.remork" type="textarea" placeholder="请输入内容" />
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark" type="textarea" placeholder="请输入内容" />
</el-form-item>
</el-form>
<template #footer>
@@ -123,7 +123,7 @@ const initFormData: FormManageForm = {
id: undefined,
formName: undefined,
formType: 'static',
remork: undefined
remark: undefined
};
const data = reactive<PageData<FormManageForm, FormManageQuery>>({
form: { ...initFormData },
+14 -22
View File
@@ -22,10 +22,10 @@
<template #header>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button v-hasPermi="['demo:leave:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
<el-button v-hasPermi="['workflow:leave:add']" type="primary" plain icon="Plus" @click="handleAdd">新增</el-button>
</el-col>
<el-col :span="1.5">
<el-button v-hasPermi="['demo:leave:export']" type="warning" plain icon="Download" @click="handleExport">导出</el-button>
<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>
</el-row>
@@ -53,18 +53,14 @@
<el-table-column label="请假原因" align="center" prop="remark" />
<el-table-column align="center" label="流程状态" min-width="70">
<template #default="scope">
<dict-tag :options="wf_business_status" :value="scope.row.processInstanceVo.businessStatus"></dict-tag>
<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">
<template #default="scope">
<el-button
v-if="
scope.row.processInstanceVo.businessStatus === 'draft' ||
scope.row.processInstanceVo.businessStatus === 'cancel' ||
scope.row.processInstanceVo.businessStatus === 'back'
"
v-hasPermi="['demo:leave:edit']"
v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'"
v-hasPermi="['workflow:leave:edit']"
size="small"
link
type="primary"
@@ -73,12 +69,8 @@
>修改</el-button
>
<el-button
v-if="
scope.row.processInstanceVo.businessStatus === 'draft' ||
scope.row.processInstanceVo.businessStatus === 'cancel' ||
scope.row.processInstanceVo.businessStatus === 'back'
"
v-hasPermi="['demo:leave:remove']"
v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'"
v-hasPermi="['workflow:leave:remove']"
size="small"
link
type="primary"
@@ -88,12 +80,12 @@
>
<el-button link type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
<el-button
v-if="scope.row.processInstanceVo.businessStatus === 'waiting'"
v-if="scope.row.status === 'waiting'"
link
size="small"
type="primary"
icon="Notification"
@click="handleCancelProcessApply(scope.row.processInstanceVo.id)"
@click="handleCancelProcessApply(scope.row.id)"
>撤销</el-button
>
</template>
@@ -184,9 +176,9 @@ const handleSelectionChange = (selection: LeaveVO[]) => {
/** 新增按钮操作 */
const handleAdd = () => {
proxy.$tab.closePage(proxy.$route);
proxy.$router.push(`/demo/leaveEdit/index/add/add`);
proxy.$router.push(`/workflow/leaveEdit/index/add/add`);
proxy.$router.push({
path: `/demo/leaveEdit/index`,
path: `/workflow/leaveEdit/index`,
query: {
type: 'add'
}
@@ -197,7 +189,7 @@ const handleAdd = () => {
const handleUpdate = (row?: LeaveVO) => {
proxy.$tab.closePage(proxy.$route);
proxy.$router.push({
path: `/demo/leaveEdit/index`,
path: `/workflow/leaveEdit/index`,
query: {
id: row.id,
type: 'update'
@@ -209,7 +201,7 @@ const handleUpdate = (row?: LeaveVO) => {
const handleView = (row?: LeaveVO) => {
proxy.$tab.closePage(proxy.$route);
proxy.$router.push({
path: `/demo/leaveEdit/index`,
path: `/workflow/leaveEdit/index`,
query: {
id: row.id,
type: 'view'
@@ -229,7 +221,7 @@ const handleDelete = async (row?: LeaveVO) => {
/** 导出按钮操作 */
const handleExport = () => {
proxy?.download(
'demo/leave/export',
'workflow/leave/export',
{
...queryParams.value
},
+22 -45
View File
@@ -3,43 +3,10 @@
<el-card shadow="never">
<div style="display: flex; justify-content: space-between">
<div>
<el-button
v-if="
routeParams.type === 'add' ||
(routeParams.type === 'update' &&
form.processInstanceVo &&
form.processInstanceVo.businessStatus &&
(form.processInstanceVo.businessStatus === 'draft' ||
form.processInstanceVo.businessStatus === 'cancel' ||
form.processInstanceVo.businessStatus === 'back'))
"
:loading="buttonLoading"
type="info"
@click="submitForm('draft')"
>暂存</el-button
>
<el-button
v-if="
routeParams.type === 'add' ||
(routeParams.type === 'update' &&
form.processInstanceVo &&
(form.processInstanceVo.businessStatus === 'draft' ||
form.processInstanceVo.businessStatus === 'cancel' ||
form.processInstanceVo.businessStatus === 'back'))
"
:loading="buttonLoading"
type="primary"
@click="submitForm('submit')"
>提 交</el-button
>
<el-button
v-if="routeParams.type === 'approval' && form.processInstanceVo && form.processInstanceVo.businessStatus === 'waiting'"
:loading="buttonLoading"
type="primary"
@click="approvalVerifyOpen"
>审批</el-button
>
<el-button v-if="processInstanceId" type="primary" @click="handleApprovalRecord">流程进度</el-button>
<el-button v-if="submitButtonShow" :loading="buttonLoading" type="info" @click="submitForm('draft')">暂存</el-button>
<el-button v-if="submitButtonShow" :loading="buttonLoading" type="primary" @click="submitForm('submit')">提 交</el-button>
<el-button v-if="approvalButtonShow" :loading="buttonLoading" type="primary" @click="approvalVerifyOpen">审批</el-button>
<el-button v-if="form && form.id && form.status !== 'draft'" type="primary" @click="handleApprovalRecord">流程进度</el-button>
</div>
<div>
<el-button style="float: right" @click="goBack()">返回</el-button>
@@ -91,8 +58,6 @@ const { proxy } = getCurrentInstance() as ComponentInternalInstance;
const buttonLoading = ref(false);
const loading = ref(true);
const leaveTime = ref<Array<string>>([]);
//流程实例id
const processInstanceId = ref('');
//路由参数
const routeParams = ref<Record<string, any>>({});
const options = [
@@ -134,7 +99,7 @@ const initFormData: LeaveForm = {
endDate: undefined,
leaveDays: undefined,
remark: undefined,
processInstanceVo: {}
status: undefined
};
const data = reactive<PageData<LeaveForm, LeaveQuery>>({
form: { ...initFormData },
@@ -165,7 +130,7 @@ const changeLeaveTime = () => {
const startDate = new Date(leaveTime.value[0]).getTime();
const endDate = new Date(leaveTime.value[1]).getTime();
const diffInMilliseconds = endDate - startDate;
form.value.leaveDays = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24));
form.value.leaveDays = Math.floor(diffInMilliseconds / (1000 * 60 * 60 * 24)) + 1;
};
/** 获取详情 */
const getInfo = () => {
@@ -177,9 +142,6 @@ const getInfo = () => {
leaveTime.value = [];
leaveTime.value.push(form.value.startDate);
leaveTime.value.push(form.value.endDate);
if (form.value.processInstanceVo) {
processInstanceId.value = form.value.processInstanceVo.id;
}
loading.value = false;
buttonLoading.value = false;
});
@@ -243,7 +205,7 @@ const handleStartWorkFlow = async (data: LeaveVO) => {
};
//审批记录
const handleApprovalRecord = () => {
approvalRecordRef.value.init(processInstanceId.value);
approvalRecordRef.value.init(form.value.id);
};
//提交回调
const submitCallback = async () => {
@@ -260,6 +222,21 @@ const goBack = () => {
const approvalVerifyOpen = async () => {
submitVerifyRef.value.openDialog(routeParams.value.taskId);
};
//校验提交按钮是否显示
const submitButtonShow = computed(() => {
return (
routeParams.value.type === 'add' ||
(routeParams.value.type === 'update' &&
form.value.status &&
(form.value.status === 'draft' || form.value.status === 'cancel' || form.value.status === 'back'))
);
});
//校验审批按钮是否显示
const approvalButtonShow = computed(() => {
return routeParams.value.type === 'approval' && form.value.status && form.value.status === 'waiting';
});
onMounted(() => {
nextTick(async () => {
routeParams.value = proxy.$route.query;
+8 -5
View File
@@ -167,6 +167,8 @@ const categoryTreeRef = ref<ElTreeInstance>();
const loading = ref(true);
// 选中数组
const ids = ref<Array<any>>([]);
// 选中业务id数组
const businessKeys = ref<Array<any>>([]);
// 非单个禁用
const single = ref(true);
// 非多个禁用
@@ -257,6 +259,7 @@ const resetQuery = () => {
// 多选框选中数据
const handleSelectionChange = (selection: ProcessInstanceVO[]) => {
ids.value = selection.map((item: any) => item.id);
businessKeys.value = selection.map((item: any) => item.businessKey);
single.value = selection.length !== 1;
multiple.value = !selection.length;
};
@@ -281,14 +284,14 @@ const getProcessInstanceFinishList = () => {
/** 删除按钮操作 */
const handleDelete = async (row: any) => {
const id = row.id || ids.value;
await proxy?.$modal.confirm('是否确认删除id为【' + id + '】的数据项?');
const businessKey = row.businessKey || businessKeys.value;
await proxy?.$modal.confirm('是否确认删除业务id为【' + businessKey + '】的数据项?');
loading.value = true;
if ('running' === tab.value) {
await deleteRunAndHisInstance(id).finally(() => (loading.value = false));
await deleteRunAndHisInstance(businessKey).finally(() => (loading.value = false));
getProcessInstanceRunningList();
} else {
await deleteFinishAndHisInstance(id).finally(() => (loading.value = false));
await deleteFinishAndHisInstance(businessKey).finally(() => (loading.value = false));
getProcessInstanceFinishList();
}
proxy?.$modal.msgSuccess('删除成功');
@@ -308,7 +311,7 @@ const handleInvalid = async (row: ProcessInstanceVO) => {
loading.value = true;
if ('running' === tab.value) {
let param = {
processInstanceId: row.id,
businessKey: row.businessKey,
deleteReason: deleteReason.value
};
await deleteRunInstance(param).finally(() => (loading.value = false));
+10 -16
View File
@@ -75,20 +75,20 @@
content="修改"
placement="top"
>
<el-button v-hasPermi="['demo:leave:edit']" link type="primary" icon="Edit" @click="handleOpen(scope.row, 'update')"></el-button>
<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 v-hasPermi="['demo:leave:remove']" link type="primary" icon="Delete" @click="handleDelete(scope.row)"></el-button>
<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.id)"></el-button>
<el-button link type="primary" icon="Notification" @click="handleCancelProcessApply(scope.row.businessKey)"></el-button>
</el-tooltip>
</template>
</el-table-column>
@@ -123,7 +123,7 @@ const categoryTreeRef = ref<ElTreeInstance>();
// 遮罩层
const loading = ref(true);
// 选中数组
const ids = ref<Array<any>>([]);
const businessKeys = ref<Array<any>>([]);
// 非单个禁用
const single = ref(true);
// 非多个禁用
@@ -190,12 +190,6 @@ const getTreeselect = async () => {
categoryOptions.value.push(data);
};
//审批记录
const handleApprovalRecord = (processInstanceId: string) => {
if (approvalRecordRef.value) {
approvalRecordRef.value.init(processInstanceId);
}
};
/** 搜索按钮操作 */
const handleQuery = () => {
getList();
@@ -210,7 +204,7 @@ const resetQuery = () => {
};
// 多选框选中数据
const handleSelectionChange = (selection: ProcessInstanceVO[]) => {
ids.value = selection.map((item: any) => item.id);
businessKeys.value = selection.map((item: any) => item.businessKey);
single.value = selection.length !== 1;
multiple.value = !selection.length;
};
@@ -226,22 +220,22 @@ const getList = () => {
/** 删除按钮操作 */
const handleDelete = async (row: ProcessInstanceVO) => {
const id = row.id || ids.value;
await proxy?.$modal.confirm('是否确认删除id为【' + id + '】的数据项?');
const businessKey = row.businessKey || businessKeys.value;
await proxy?.$modal.confirm('是否确认删除业务id为【' + businessKey + '】的数据项?');
loading.value = true;
if ('running' === tab.value) {
await deleteRunAndHisInstance(id).finally(() => (loading.value = false));
await deleteRunAndHisInstance(businessKey).finally(() => (loading.value = false));
getList();
}
proxy?.$modal.msgSuccess('删除成功');
};
/** 撤销按钮操作 */
const handleCancelProcessApply = async (processInstanceId: string) => {
const handleCancelProcessApply = async (businessKey: string) => {
await proxy?.$modal.confirm('是否确认撤销当前单据?');
loading.value = true;
if ('running' === tab.value) {
await cancelProcessApply(processInstanceId).finally(() => (loading.value = false));
await cancelProcessApply(businessKey).finally(() => (loading.value = false));
getList();
}
proxy?.$modal.msgSuccess('撤销成功');
-3
View File
@@ -19,9 +19,6 @@
"paths": {
"@/*": ["src/*"]
},
"compilerOptions": {
"types": ["element-plus/global"]
},
"types": ["vite/client"],
"skipLibCheck": true,
"removeComments": true,
-1
View File
@@ -61,7 +61,6 @@ export default defineConfig(({ mode, command }: ConfigEnv): UserConfig => {
'pinia',
'axios',
'@vueuse/core',
'path-to-regexp',
'echarts',
'vue-i18n',
'@vueup/vue-quill',