办公管理

This commit is contained in:
cxc
2023-01-03 17:23:10 +08:00
parent 70ad69fdfe
commit 6c8b216476
21 changed files with 2896 additions and 164 deletions

View File

@ -0,0 +1,10 @@
import request from '@/utils/request'
// 撤回任务
export function revokeProcess(data) {
return request({
url: '/workflow/task/revokeProcess',
method: 'post',
data: data
})
}

141
src/api/flowable/process.js Normal file
View File

@ -0,0 +1,141 @@
import request from '@/utils/request'
// 查询流程列表
export function listProcess(query) {
return request({
url: '/workflow/process/list',
method: 'get',
params: query
})
}
// 查询流程列表
export function getProcessForm(query) {
return request({
url: '/workflow/process/getProcessForm',
method: 'get',
params: query
})
}
// 部署流程实例
export function startProcess(processDefId, data) {
return request({
url: '/workflow/process/start/' + processDefId,
method: 'post',
data: data
})
}
// 获取流程图
export function getBpmnXml(processDefId) {
return request({
url: '/workflow/process/bpmnXml/' + processDefId,
method: 'get'
})
}
export function detailProcess(query) {
return request({
url: '/workflow/process/detail',
method: 'get',
params: query
})
}
// 我的发起的流程
export function listOwnProcess(query) {
return request({
url: '/workflow/process/ownList',
method: 'get',
params: query
})
}
// 我待办的流程
export function listTodoProcess(query) {
return request({
url: '/workflow/process/todoList',
method: 'get',
params: query
})
}
// 我待签的流程
export function listClaimProcess(query) {
return request({
url: '/workflow/process/claimList',
method: 'get',
params: query
})
}
// 我已办的流程
export function listFinishedProcess(query) {
return request({
url: '/workflow/process/finishedList',
method: 'get',
params: query
})
}
// 查询流程抄送列表
export function listCopyProcess(query) {
return request({
url: '/workflow/process/copyList',
method: 'get',
params: query
})
}
// 完成任务
export function complete(data) {
return request({
url: '/workflow/task/complete',
method: 'post',
data: data
})
}
// 取消申请
export function stopProcess(data) {
return request({
url: '/workflow/task/stopProcess',
method: 'post',
data: data
})
}
// 驳回任务
export function rejectTask(data) {
return request({
url: '/workflow/task/reject',
method: 'post',
data: data
})
}
// 可退回任务列表
export function returnList(data) {
return request({
url: '/workflow/task/returnList',
method: 'post',
data: data
})
}
// 部署流程实例
export function deployStart(deployId) {
return request({
url: '/workflow/process/startFlow/' + deployId,
method: 'get',
})
}
// 删除流程实例
export function delProcess(id) {
return request({
url: '/workflow/instance/delete/?instanceId=' + id,
method: 'delete'
})
}

81
src/api/flowable/todo.js Normal file
View File

@ -0,0 +1,81 @@
import request from '@/utils/request'
// 完成任务
export function complete(data) {
return request({
url: '/workflow/task/complete',
method: 'post',
data: data
})
}
// 委派任务
export function delegate(data) {
return request({
url: '/workflow/task/delegate',
method: 'post',
data: data
})
}
// 转办任务
export function transfer(data) {
return request({
url: '/workflow/task/transfer',
method: 'post',
data: data
})
}
// 退回任务
export function returnTask(data) {
return request({
url: '/workflow/task/return',
method: 'post',
data: data
})
}
// 拒绝任务
export function rejectTask(data) {
return request({
url: '/workflow/task/reject',
method: 'post',
data: data
})
}
// 签收任务
export function claimTask(data) {
return request({
url: '/workflow/task/claim',
method: 'post',
data: data
})
}
// 可退回任务列表
export function returnList(data) {
return request({
url: '/workflow/task/returnList',
method: 'post',
data: data
})
}
// 下一节点
export function getNextFlowNode(data) {
return request({
url: '/workflow/task/nextFlowNode',
method: 'post',
data: data
})
}
// 部署流程实例
export function deployStart(deployId) {
return request({
url: '/workflow/process/startFlow/' + deployId,
method: 'get',
})
}

View File

@ -1,135 +1,142 @@
import request from '@/utils/request'
import request from "@/utils/request";
import { parseStrEmpty } from "@/utils/ruoyi";
// 查询用户列表
export function listUser(query) {
return request({
url: '/system/user/list',
method: 'get',
params: query
})
url: "/system/user/list",
method: "get",
params: query,
});
}
// 查询用户详细
export function getUser(userId) {
return request({
url: '/system/user/' + parseStrEmpty(userId),
method: 'get'
})
url: "/system/user/" + parseStrEmpty(userId),
method: "get",
});
}
// 查询用户列表,用于流程里的用户选择
export function selectUser(query) {
return request({
url: "/system/user/selectUser",
method: "get",
params: query,
});
}
// 新增用户
export function addUser(data) {
return request({
url: '/system/user',
method: 'post',
data: data
})
url: "/system/user",
method: "post",
data: data,
});
}
// 修改用户
export function updateUser(data) {
return request({
url: '/system/user',
method: 'put',
data: data
})
url: "/system/user",
method: "put",
data: data,
});
}
// 删除用户
export function delUser(userId) {
return request({
url: '/system/user/' + userId,
method: 'delete'
})
url: "/system/user/" + userId,
method: "delete",
});
}
// 用户密码重置
export function resetUserPwd(userId, password) {
const data = {
userId,
password
}
password,
};
return request({
url: '/system/user/resetPwd',
method: 'put',
data: data
})
url: "/system/user/resetPwd",
method: "put",
data: data,
});
}
// 用户状态修改
export function changeUserStatus(userId, status) {
const data = {
userId,
status
}
status,
};
return request({
url: '/system/user/changeStatus',
method: 'put',
data: data
})
url: "/system/user/changeStatus",
method: "put",
data: data,
});
}
// 查询用户个人信息
export function getUserProfile() {
return request({
url: '/system/user/profile',
method: 'get'
})
url: "/system/user/profile",
method: "get",
});
}
// 修改用户个人信息
export function updateUserProfile(data) {
return request({
url: '/system/user/profile',
method: 'put',
data: data
})
url: "/system/user/profile",
method: "put",
data: data,
});
}
// 用户密码重置
export function updateUserPwd(oldPassword, newPassword) {
const data = {
oldPassword,
newPassword
}
newPassword,
};
return request({
url: '/system/user/profile/updatePwd',
method: 'put',
params: data
})
url: "/system/user/profile/updatePwd",
method: "put",
params: data,
});
}
// 用户头像上传
export function uploadAvatar(data) {
return request({
url: '/system/user/profile/avatar',
method: 'post',
data: data
})
url: "/system/user/profile/avatar",
method: "post",
data: data,
});
}
// 查询授权角色
export function getAuthRole(userId) {
return request({
url: '/system/user/authRole/' + userId,
method: 'get'
})
url: "/system/user/authRole/" + userId,
method: "get",
});
}
// 保存授权角色
export function updateAuthRole(data) {
return request({
url: '/system/user/authRole',
method: 'put',
params: data
})
url: "/system/user/authRole",
method: "put",
params: data,
});
}
// 查询部门下拉树结构
export function deptTreeSelect() {
return request({
url: '/system/dept/treeselect',
method: 'get'
})
url: "/system/dept/treeselect",
method: "get",
});
}

View File

@ -120,12 +120,11 @@
width="100px"
align="center"
/>
<el-table-column
label="处理时间"
prop="createTime"
width="140px"
align="center"
/>
<el-table-column label="处理时间" width="140px" align="center">
<template #default="{ row }">
{{ parseTime(row.createTime) }}
</template>
</el-table-column>
<el-table-column
label="办结时间"
prop="finishTime"
@ -187,6 +186,7 @@
<script setup name="">
import "@/plugins/package/theme/index.scss";
import { parseTime } from "@/utils/ruoyi";
import BpmnViewer from "bpmn-js/lib/Viewer";
import MoveCanvasModule from "diagram-js/lib/navigation/movecanvas";
import { nextTick, onBeforeUnmount, toRefs } from "vue";

View File

@ -337,7 +337,6 @@ function resetListenersList() {
bpmnElement.businessObject?.extensionElements?.values?.filter(
(ex) => ex.$type === `${prefix}:ExecutionListener`
) ?? [];
debugger;
elementListenersList.value = bpmnElementListeners.map((listener) =>
initListenerType(listener)
);

View File

@ -1,5 +0,0 @@
{
"msg": "操作成功",
"code": 200,
"data": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<definitions xmlns=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:flowable=\"http://flowable.org/bpmn\" xmlns:bpmndi=\"http://www.omg.org/spec/BPMN/20100524/DI\" xmlns:omgdc=\"http://www.omg.org/spec/DD/20100524/DC\" xmlns:omgdi=\"http://www.omg.org/spec/DD/20100524/DI\" xmlns:bpmn2=\"http://www.omg.org/spec/BPMN/20100524/MODEL\" xmlns:dc=\"http://www.omg.org/spec/DD/20100524/DC\" xmlns:di=\"http://www.omg.org/spec/DD/20100524/DI\" typeLanguage=\"http://www.w3.org/2001/XMLSchema\" expressionLanguage=\"http://www.w3.org/1999/XPath\" targetNamespace=\"http://flowable.org/bpmn\" id=\"diagram_Process_1671673403370\" xsi:schemaLocation=\"http://www.omg.org/spec/BPMN/20100524/MODEL BPMN20.xsd\">\n <process id=\"Process_1671673403370\" name=\"请假\" isExecutable=\"true\">\n <startEvent id=\"Event_0o5vpsf\" flowable:formKey=\"key_1\"></startEvent>\n <userTask id=\"Activity_1qoq75d\" flowable:candidateGroups=\"DEPT100,DEPT103,DEPT209\" xmlns:flowable=\"http://flowable.org/bpmn\" flowable:dataType=\"DEPTS\" flowable:text=\"若依科技,研发部门,高新分公司\">\n <extensionElements>\n <flowable:taskListener event=\"complete\" class=\"print('1233);\"></flowable:taskListener>\n <flowable:taskListener event=\"create\" expression=\"阿萨大大\"></flowable:taskListener>\n <flowable:taskListener event=\"delete\" delegateExpression=\"rr24344\"></flowable:taskListener>\n <flowable:taskListener event=\"update\" delegateExpression=\"tertert\"></flowable:taskListener>\n <flowable:taskListener event=\"delete\" delegateExpression=\"34er13232\"></flowable:taskListener>\n <flowable:taskListener event=\"update\" expression=\"4234\"></flowable:taskListener>\n </extensionElements>\n </userTask>\n <sequenceFlow id=\"Flow_01oskyz\" sourceRef=\"Event_0o5vpsf\" targetRef=\"Activity_1qoq75d\"></sequenceFlow>\n <userTask id=\"Activity_0iuhaqx\"></userTask>\n <sequenceFlow id=\"Flow_0f843wd\" sourceRef=\"Activity_1qoq75d\" targetRef=\"Activity_0iuhaqx\"></sequenceFlow>\n <intermediateThrowEvent id=\"Event_10fq4h9\"></intermediateThrowEvent>\n <sequenceFlow id=\"Flow_0ditwq0\" sourceRef=\"Activity_0iuhaqx\" targetRef=\"Event_10fq4h9\"></sequenceFlow>\n </process>\n <bpmndi:BPMNDiagram id=\"BPMNDiagram_Process_1671673403370\">\n <bpmndi:BPMNPlane bpmnElement=\"Process_1671673403370\" id=\"BPMNPlane_Process_1671673403370\">\n <bpmndi:BPMNShape bpmnElement=\"Event_0o5vpsf\" id=\"BPMNShape_Event_0o5vpsf\">\n <omgdc:Bounds height=\"36.0\" width=\"36.0\" x=\"292.0\" y=\"152.0\"></omgdc:Bounds>\n </bpmndi:BPMNShape>\n <bpmndi:BPMNShape bpmnElement=\"Activity_1qoq75d\" id=\"BPMNShape_Activity_1qoq75d\">\n <omgdc:Bounds height=\"80.0\" width=\"100.0\" x=\"380.0\" y=\"130.0\"></omgdc:Bounds>\n </bpmndi:BPMNShape>\n <bpmndi:BPMNShape bpmnElement=\"Activity_0iuhaqx\" id=\"BPMNShape_Activity_0iuhaqx\">\n <omgdc:Bounds height=\"80.0\" width=\"100.0\" x=\"540.0\" y=\"130.0\"></omgdc:Bounds>\n </bpmndi:BPMNShape>\n <bpmndi:BPMNShape bpmnElement=\"Event_10fq4h9\" id=\"BPMNShape_Event_10fq4h9\">\n <omgdc:Bounds height=\"36.0\" width=\"36.0\" x=\"702.0\" y=\"152.0\"></omgdc:Bounds>\n </bpmndi:BPMNShape>\n <bpmndi:BPMNEdge bpmnElement=\"Flow_0ditwq0\" id=\"BPMNEdge_Flow_0ditwq0\">\n <omgdi:waypoint x=\"640.0\" y=\"170.0\"></omgdi:waypoint>\n <omgdi:waypoint x=\"702.0\" y=\"170.0\"></omgdi:waypoint>\n </bpmndi:BPMNEdge>\n <bpmndi:BPMNEdge bpmnElement=\"Flow_0f843wd\" id=\"BPMNEdge_Flow_0f843wd\">\n <omgdi:waypoint x=\"480.0\" y=\"170.0\"></omgdi:waypoint>\n <omgdi:waypoint x=\"540.0\" y=\"170.0\"></omgdi:waypoint>\n </bpmndi:BPMNEdge>\n <bpmndi:BPMNEdge bpmnElement=\"Flow_01oskyz\" id=\"BPMNEdge_Flow_01oskyz\">\n <omgdi:waypoint x=\"328.0\" y=\"170.0\"></omgdi:waypoint>\n <omgdi:waypoint x=\"380.0\" y=\"170.0\"></omgdi:waypoint>\n </bpmndi:BPMNEdge>\n </bpmndi:BPMNPlane>\n </bpmndi:BPMNDiagram>\n</definitions>"
}

View File

@ -1,13 +1,13 @@
// 初始化表单数据
export function initListenerForm(listener) {
let self = {
...listener
...listener,
};
if (listener.script) {
self = {
...listener,
...listener.script,
scriptType: listener.script.resource ? "externalScript" : "inlineScript"
scriptType: listener.script.resource ? "externalScript" : "inlineScript",
};
}
if (listener.event === "timeout" && listener.eventDefinitions) {
@ -28,15 +28,17 @@ export function initListenerForm(listener) {
}
export function initListenerType(listener) {
// debugger;
let listenerType;
if (listener.class) listenerType = "classListener";
if (listener.expression) listenerType = "expressionListener";
if (listener.delegateExpression) listenerType = "delegateExpressionListener";
if (listener.script) listenerType = "scriptListener";
return {
...JSON.parse(JSON.stringify(listener)),
...(listener.script ?? {}),
listenerType: listenerType
listenerType: listenerType,
};
}
@ -44,7 +46,7 @@ export const listenerType = {
classListener: "Java 类",
expressionListener: "表达式",
delegateExpressionListener: "代理表达式",
scriptListener: "脚本"
scriptListener: "脚本",
};
export const eventType = {
@ -53,10 +55,10 @@ export const eventType = {
complete: "完成",
delete: "删除",
update: "更新",
timeout: "超时"
timeout: "超时",
};
export const fieldType = {
string: "字符串",
expression: "表达式"
expression: "表达式",
};

View File

@ -21,7 +21,7 @@
show-overflow-tooltip
/>
<el-table-column label="操作" width="90px">
<template slot-scope="{ row, $index }">
<template #default="{ row, $index }">
<el-button size="small" link @click="openAttributesForm(row, $index)"
>编辑</el-button
>
@ -29,7 +29,7 @@
<el-button
size="small"
link
style="color: #ff4d4f"
type="danger"
@click="removeAttributes(row, $index)"
>移除</el-button
>

View File

@ -2,8 +2,20 @@
<div class="panel-tab__content">
<div class="panel-tab__content--title">
<span
><i class="el-icon-menu" style="margin-right: 8px; color: #555555"></i
>消息列表</span
:style="{
display: 'flex',
alignItems: 'center',
}"
>
<el-icon
:style="{
marginRight: '8px',
color: '#555555',
}"
>
<Menu />
</el-icon>
消息列表</span
>
<el-button
size="small"
@ -33,8 +45,20 @@
style="padding-top: 8px; margin-top: 8px; border-top: 1px solid #eeeeee"
>
<span
><i class="el-icon-menu" style="margin-right: 8px; color: #555555"></i
>信号列表</span
:style="{
display: 'flex',
alignItems: 'center',
}"
>
<el-icon
:style="{
marginRight: '8px',
color: '#555555',
}"
>
<Menu />
</el-icon>
信号列表</span
>
<el-button
size="small"

View File

@ -65,12 +65,14 @@ export function createScriptObject(options, prefix) {
// 更新元素扩展属性
export function updateElementExtensions(element, extensionList) {
// debugger;
const extensions = window.bpmnInstances.moddle.create(
"bpmn:ExtensionElements",
{
values: extensionList,
}
);
debugger;
window.bpmnInstances.modeling.updateProperties(element, {
extensionElements: extensions,
});

View File

@ -1,6 +1,6 @@
import { createWebHistory, createRouter } from 'vue-router'
import { createWebHistory, createRouter } from "vue-router";
/* Layout */
import Layout from '@/layout'
import Layout from "@/layout";
/**
* Note: 路由配置项
@ -27,147 +27,167 @@ import Layout from '@/layout'
// 公共路由
export const constantRoutes = [
{
path: '/redirect',
path: "/redirect",
component: Layout,
hidden: true,
children: [
{
path: '/redirect/:path(.*)',
component: () => import('@/views/redirect/index.vue')
}
]
path: "/redirect/:path(.*)",
component: () => import("@/views/redirect/index.vue"),
},
],
},
{
path: '/login',
component: () => import('@/views/login'),
hidden: true
path: "/login",
component: () => import("@/views/login"),
hidden: true,
},
{
path: '/register',
component: () => import('@/views/register'),
hidden: true
path: "/register",
component: () => import("@/views/register"),
hidden: true,
},
{
path: "/:pathMatch(.*)*",
component: () => import('@/views/error/404'),
hidden: true
component: () => import("@/views/error/404"),
hidden: true,
},
{
path: '/401',
component: () => import('@/views/error/401'),
hidden: true
path: "/401",
component: () => import("@/views/error/401"),
hidden: true,
},
{
path: '',
path: "",
component: Layout,
redirect: '/index',
redirect: "/index",
children: [
{
path: '/index',
component: () => import('@/views/index'),
name: 'Index',
meta: { title: '首页', icon: 'dashboard', affix: true }
}
]
path: "/index",
component: () => import("@/views/index"),
name: "Index",
meta: { title: "首页", icon: "dashboard", affix: true },
},
],
},
{
path: '/user',
path: "/user",
component: Layout,
hidden: true,
redirect: 'noredirect',
redirect: "noredirect",
children: [
{
path: 'profile',
component: () => import('@/views/system/user/profile/index'),
name: 'Profile',
meta: { title: '个人中心', icon: 'user' }
}
]
}
]
path: "profile",
component: () => import("@/views/system/user/profile/index"),
name: "Profile",
meta: { title: "个人中心", icon: "user" },
},
],
},
];
// 动态路由,基于用户权限动态去加载
export const dynamicRoutes = [
{
path: '/system/user-auth',
path: "/system/user-auth",
component: Layout,
hidden: true,
permissions: ['system:user:edit'],
permissions: ["system:user:edit"],
children: [
{
path: 'role/:userId(\\d+)',
component: () => import('@/views/system/user/authRole'),
name: 'AuthRole',
meta: { title: '分配角色', activeMenu: '/system/user' }
}
]
path: "role/:userId(\\d+)",
component: () => import("@/views/system/user/authRole"),
name: "AuthRole",
meta: { title: "分配角色", activeMenu: "/system/user" },
},
],
},
{
path: '/system/role-auth',
path: "/system/role-auth",
component: Layout,
hidden: true,
permissions: ['system:role:edit'],
permissions: ["system:role:edit"],
children: [
{
path: 'user/:roleId(\\d+)',
component: () => import('@/views/system/role/authUser'),
name: 'AuthUser',
meta: { title: '分配用户', activeMenu: '/system/role' }
}
]
path: "user/:roleId(\\d+)",
component: () => import("@/views/system/role/authUser"),
name: "AuthUser",
meta: { title: "分配用户", activeMenu: "/system/role" },
},
],
},
{
path: '/system/dict-data',
path: "/system/dict-data",
component: Layout,
hidden: true,
permissions: ['system:dict:list'],
permissions: ["system:dict:list"],
children: [
{
path: 'index/:dictId(\\d+)',
component: () => import('@/views/system/dict/data'),
name: 'Data',
meta: { title: '字典数据', activeMenu: '/system/dict' }
}
]
path: "index/:dictId(\\d+)",
component: () => import("@/views/system/dict/data"),
name: "Data",
meta: { title: "字典数据", activeMenu: "/system/dict" },
},
],
},
{
path: '/monitor/job-log',
path: "/monitor/job-log",
component: Layout,
hidden: true,
permissions: ['monitor:job:list'],
permissions: ["monitor:job:list"],
children: [
{
path: 'index/:jobId(\\d+)',
component: () => import('@/views/monitor/job/log'),
name: 'JobLog',
meta: { title: '调度日志', activeMenu: '/monitor/job' }
}
]
path: "index/:jobId(\\d+)",
component: () => import("@/views/monitor/job/log"),
name: "JobLog",
meta: { title: "调度日志", activeMenu: "/monitor/job" },
},
],
},
{
path: '/tool/gen-edit',
path: "/tool/gen-edit",
component: Layout,
hidden: true,
permissions: ['tool:gen:edit'],
permissions: ["tool:gen:edit"],
children: [
{
path: 'index/:tableId(\\d+)',
component: () => import('@/views/tool/gen/editTable'),
name: 'GenEdit',
meta: { title: '修改生成配置', activeMenu: '/tool/gen' }
}
]
}
]
path: "index/:tableId(\\d+)",
component: () => import("@/views/tool/gen/editTable"),
name: "GenEdit",
meta: { title: "修改生成配置", activeMenu: "/tool/gen" },
},
],
},
{
path: "/flowable/process",
component: Layout,
hidden: true,
permissions: ["flowable:process:query"],
children: [
{
path: "start/:deployId([\\w|\\-]+)",
component: () => import("@/views/office/start"),
name: "WorkStart",
meta: { title: "发起流程", icon: "" },
},
{
path: "detail/:procInsId([\\w|\\-]+)",
component: () => import("@/views/office/detail"),
name: "WorkDetail",
meta: { title: "流程详情", activeMenu: "/office/own" },
},
],
},
];
const router = createRouter({
history: createWebHistory(),
routes: constantRoutes,
scrollBehavior(to, from, savedPosition) {
if (savedPosition) {
return savedPosition
return savedPosition;
} else {
return { top: 0 }
return { top: 0 };
}
},
});

184
src/views/office/claim.vue Normal file
View File

@ -0,0 +1,184 @@
<template>
<div class="app-container">
<el-form
:model="queryParams"
ref="queryFormRef"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="流程名称" prop="processName">
<el-input
v-model="queryParams.processName"
placeholder="请输入流程名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="search"
size="small"
@click="handleQuery"
>搜索</el-button
>
<el-button icon="refresh" size="small" @click="resetQuery"
>重置</el-button
>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<right-toolbar
v-model:showSearch="showSearch"
@queryTable="getList"
></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="claimList">
<el-table-column type="selection" width="55" align="center" />
<el-table-column
label="任务编号"
align="center"
prop="taskId"
:show-overflow-tooltip="true"
/>
<el-table-column label="流程名称" align="center" prop="procDefName" />
<el-table-column label="任务节点" align="center" prop="taskName" />
<el-table-column label="流程版本" align="center">
<template #default="{ row }">
<el-tag size="medium">v{{ row.procDefVersion }}</el-tag>
</template>
</el-table-column>
<el-table-column label="流程发起人" align="center">
<template #default="{ row }">
<label
>{{ row.startUserName }}
<el-tag type="info" size="small">{{
row.startDeptName
}}</el-tag></label
>
</template>
</el-table-column>
<el-table-column
label="接收时间"
align="center"
prop="createTime"
width="180"
/>
<el-table-column
label="操作"
align="center"
class-name="small-padding fixed-width"
>
<template #default="{ row }">
<el-button
size="small"
type="primary"
link
icon="s-claim"
@click="handleClaim(row)"
v-hasPermi="['flowable:process:claim']"
>签收
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</div>
</template>
<script setup name="Claim">
import { listClaimProcess } from "@/api/flowable/process";
import { claimTask } from "@/api/flowable/todo";
import { ElMessage } from "element-plus";
import { ref, reactive, toRefs } from "vue";
import { useRouter } from "vue-router";
const queryFormRef = ref();
// 遮罩层
const loading = ref(true);
// 选中数组
const ids = ref([]);
// 非单个禁用
const single = ref(true);
// 非多个禁用
const multiple = ref(true);
// 显示搜索条件
const showSearch = ref(true);
// 总条数
const total = ref(0);
// 流程待办任务表格数据
const claimList = ref([]);
// 弹出层标题
const title = ref("");
// 是否显示弹出层
const open = ref(false);
const data = reactive({
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
name: null,
processName: null,
},
// 表单参数
form: {},
// 表单校验
rules: {},
});
const { queryParams, form, rules } = toRefs(data);
/** 查询流程定义列表 */
function getList() {
loading.value = true;
listClaimProcess(queryParams.value).then((response) => {
claimList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
if (queryFormRef.value) {
queryFormRef.value.resetFields();
}
handleQuery();
}
/** 签收 */
const router = useRouter();
function handleClaim(row) {
claimTask({ taskId: row.taskId }).then((response) => {
ElMessage.success(response.msg);
router.push({
path: "/work/todo",
});
});
}
defineExpose({
getList,
});
</script>
<script>
export default {
beforeRouteEnter(to, from, next) {
next((vm) => {
vm.getList();
});
},
};
</script>
<style scoped></style>

221
src/views/office/copy.vue Normal file
View File

@ -0,0 +1,221 @@
<template>
<div class="app-container">
<el-form
:model="queryParams"
ref="queryFormRef"
size="small"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="流程名称" prop="processName">
<el-input
v-model="queryParams.processName"
placeholder="请输入流程名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="发起人" prop="originatorName">
<el-input
v-model="queryParams.originatorName"
placeholder="请输入发起人"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="search"
size="small"
@click="handleQuery"
>搜索</el-button
>
<el-button icon="refresh" size="small" @click="resetQuery"
>重置</el-button
>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="download"
size="small"
@click="handleExport"
v-hasPermi="['workflow:process:export']"
>导出</el-button
>
</el-col>
<right-toolbar
:showSearch.sync="showSearch"
@queryTable="getList"
></right-toolbar>
</el-row>
<el-table
v-loading="loading"
:data="copyList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column label="抄送编号" align="center" prop="copyId" />
<el-table-column
label="标题"
align="center"
prop="title"
:show-overflow-tooltip="true"
/>
<el-table-column
label="流程名称"
align="center"
prop="processName"
:show-overflow-tooltip="true"
/>
<el-table-column label="发起人" align="center" prop="originatorName" />
<el-table-column label="创建时间" align="center" prop="createTime">
<template #default="{ row }">
<span>{{ parseTime(row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
class-name="small-padding fixed-width"
>
<template #default="{ row }">
<el-button
size="small"
type="primary"
link
icon="tickets"
@click="handleFlowRecord(row)"
v-hasPermi="['flowable:process:query']"
>详情</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</template>
<script setup>
import { listCopyProcess } from "@/api/flowable/process";
import { reactive, ref, toRefs } from "vue";
import { useRouter } from "vue-router";
const router = useRouter();
const queryFormRef = ref();
// 按钮loading
// const buttonLoading = ref(false);
// 遮罩层
const loading = ref(true);
// 选中数组
const ids = ref([]);
// 非单个禁用
const single = ref(true);
// 非多个禁用
const multiple = ref(true);
// 显示搜索条件
const showSearch = ref(true);
// 总条数
const total = ref(0);
// 流程抄送表格数据
const copyList = ref([]);
// 弹出层标题
// const title = ref("");
// 是否显示弹出层
const open = ref(false);
const data = reactive({
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
processId: undefined,
processName: undefined,
categoryId: undefined,
taskId: undefined,
userId: undefined,
originatorName: undefined,
},
// 表单参数
form: {},
// 表单校验
rules: {
copyId: [{ required: true, message: "抄送主键不能为空", trigger: "blur" }],
processId: [
{ required: true, message: "流程主键不能为空", trigger: "blur" },
],
processName: [
{ required: true, message: "流程名称不能为空", trigger: "blur" },
],
categoryId: [
{ required: true, message: "流程分类主键不能为空", trigger: "blur" },
],
taskId: [{ required: true, message: "任务主键不能为空", trigger: "blur" }],
userId: [{ required: true, message: "用户主键不能为空", trigger: "blur" }],
},
});
const { queryParams, form, rules } = toRefs(data);
/** 查询流程抄送列表 */
function getList() {
loading.value = true;
listCopyProcess(queryParams.value).then((response) => {
copyList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
if (queryFormRef.value) {
queryFormRef.value.resetFields();
}
handleQuery();
}
// 多选框选中数据
function handleSelectionChange(selection) {
ids.value = selection.map((item) => item.copyId);
single.value = selection.length !== 1;
multiple.value = !selection.length;
}
/** 查看详情 */
function handleFlowRecord(row) {
router.push({
path: "/flowable/process/detail/" + row.instanceId,
query: {
definitionId: row.processId,
deployId: row.deploymentId,
taskId: row.taskId,
finished: false,
},
});
}
/** 导出按钮操作 */
function handleExport() {
this.download(
"workflow/copy/export",
{
...queryParams.value,
},
`copy_${new Date().getTime()}.xlsx`
);
}
getList();
</script>

831
src/views/office/detail.vue Normal file
View File

@ -0,0 +1,831 @@
<template>
<div class="app-container">
<el-tabs
tab-position="top"
:model-value="finished === 'true' ? 'approval' : 'form'"
>
<el-tab-pane label="任务办理" name="approval" v-if="finished === 'true'">
<el-card class="box-card" shadow="hover" v-if="taskFormOpen">
<div slot="header" class="clearfix">
<span>填写表单</span>
</div>
<el-col :span="20" :offset="2">
<parser :form-conf="taskFormData" ref="taskFormParser" />
</el-col>
</el-card>
<el-card class="box-card" shadow="hover">
<div slot="header" class="clearfix">
<span>审批流程</span>
</div>
<el-row>
<el-col :span="20" :offset="2">
<el-form
ref="taskFormRef"
:model="taskForm"
:rules="rules"
label-width="120px"
>
<el-form-item label="审批意见" prop="comment">
<el-input
type="textarea"
:rows="5"
v-model="taskForm.comment"
placeholder="请输入 审批意见"
/>
</el-form-item>
<el-form-item label="抄送人" prop="copyUserIds">
<el-tag
:key="index"
v-for="(item, index) in copyUser"
closable
:disable-transitions="false"
@close="handleClose('copy', item)"
>
{{ item.nickName }}
</el-tag>
<el-button
class="button-new-tag"
type="primary"
icon="plus"
size="small"
circle
@click="onSelectCopyUsers"
/>
</el-form-item>
<el-form-item label="指定审批人" prop="copyUserIds">
<el-tag
:key="index"
v-for="(item, index) in nextUser"
closable
:disable-transitions="false"
@close="handleClose('next', item)"
>
{{ item.nickName }}
</el-tag>
<el-button
class="button-new-tag"
type="primary"
icon="plus"
size="small"
circle
@click="onSelectNextUsers"
/>
</el-form-item>
</el-form>
</el-col>
</el-row>
<el-row :gutter="10" type="flex" justify="center">
<el-col :span="1.5">
<el-button
icon="circle-check"
type="success"
@click="handleComplete"
>通过</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
icon="chat-line-square"
type="primary"
@click="handleDelegate"
>委派</el-button
>
</el-col>
<el-col :span="1.5">
<el-button icon="pointer" type="success" @click="handleTransfer"
>转办</el-button
>
</el-col>
<!-- <el-col :span="2">-->
<!-- <el-button icon="edit-outline" type="primary"" @click="handle">签收</el-button>-->
<!-- </el-col>-->
<el-col :span="1.5">
<el-button
icon="refresh-left"
type="warning"
@click="handleReturn"
>退回</el-button
>
</el-col>
<el-col :span="1.5">
<el-button icon="circle-close" type="danger" @click="handleReject"
>拒绝</el-button
>
</el-col>
</el-row>
</el-card>
</el-tab-pane>
<el-tab-pane label="表单信息" name="form">
<div v-if="formOpen">
<el-card
class="box-card"
shadow="never"
v-for="(formInfo, index) in processFormList"
:key="index"
>
<div slot="header" class="clearfix">
<span>{{ formInfo.title }}</span>
</div>
<!--流程处理表单模块-->
<el-col :span="20" :offset="2">
<parser :form-conf="formInfo" />
</el-col>
</el-card>
</div>
</el-tab-pane>
<el-tab-pane label="流转记录" name="record">
<el-card class="box-card" shadow="never">
<el-col :span="20" :offset="2">
<div class="block">
<el-timeline>
<el-timeline-item
v-for="(item, index) in historyProcNodeList"
:key="index"
:icon="setIcon(item.endTime)"
:color="setColor(item.endTime)"
>
<p style="font-weight: 700">{{ item.activityName }}</p>
<el-card
v-if="item.activityType === 'startEvent'"
class="box-card"
shadow="hover"
>
{{ item.assigneeName }} 在
{{ parseTime(item.createTime) }} 发起流程
</el-card>
<el-card
v-if="item.activityType === 'userTask'"
class="box-card"
shadow="hover"
>
<el-descriptions
:column="5"
:labelStyle="{ 'font-weight': 'bold' }"
>
<el-descriptions-item label="实际办理">{{
item.assigneeName || "-"
}}</el-descriptions-item>
<el-descriptions-item label="候选办理">{{
item.candidate || "-"
}}</el-descriptions-item>
<el-descriptions-item label="接收时间">{{
parseTime(item.createTime) || "-"
}}</el-descriptions-item>
<el-descriptions-item label="办结时间">{{
parseTime(item.endTime) || "-"
}}</el-descriptions-item>
<el-descriptions-item label="耗时">{{
item.duration || "-"
}}</el-descriptions-item>
</el-descriptions>
<div v-if="item.commentList && item.commentList.length > 0">
<div
v-for="(comment, index) in item.commentList"
:key="index"
>
<el-divider content-position="left">
<el-tag
:type="approveTypeTag(comment.type)"
size="small"
>{{ commentType(comment.type) }}</el-tag
>
<el-tag type="info" effect="plain" size="small">{{
parseTime(comment.time)
}}</el-tag>
</el-divider>
<span>{{ comment.fullMessage }}</span>
</div>
</div>
</el-card>
<el-card
v-if="item.activityType === 'endEvent'"
class="box-card"
shadow="hover"
>
{{ parseTime(item.createTime) }} 结束流程
</el-card>
</el-timeline-item>
</el-timeline>
</div>
</el-col>
</el-card>
</el-tab-pane>
<el-tab-pane label="流程跟踪" name="track">
<el-card class="box-card" shadow="never">
<process-viewer
:key="`designer-${loadIndex}`"
:style="'height:' + height"
:xml="xmlData"
:finishedInfo="finishedInfo"
:allCommentList="historyProcNodeList"
/>
</el-card>
</el-tab-pane>
</el-tabs>
<!--退回流程-->
<el-dialog
:title="returnTitle"
v-model="returnOpen"
width="40%"
append-to-body
>
<el-form ref="taskForm" :model="taskForm" label-width="80px">
<el-form-item label="退回节点" prop="targetKey">
<el-radio-group v-model="taskForm.targetKey">
<el-radio-button
v-for="item in returnTaskList"
:key="item.id"
:label="item.id"
>{{ item.name }}</el-radio-button
>
</el-radio-group>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="returnOpen = false">取 消</el-button>
<el-button type="primary" @click="submitReturn">确 定</el-button>
</span>
</el-dialog>
<el-dialog
:title="userData.title"
v-model="userData.open"
width="60%"
append-to-body
>
<el-row type="flex" :gutter="20">
<!--部门数据-->
<el-col :span="5">
<el-card shadow="never" style="height: 100%">
<div slot="header">
<span>部门列表</span>
</div>
<div class="head-container">
<el-input
v-model="deptName"
placeholder="请输入部门名称"
clearable
size="small"
prefix-icon="el-icon-search"
/>
<el-tree
:data="deptOptions"
:props="deptProps"
:expand-on-click-node="false"
:filter-node-method="filterNode"
ref="tree"
default-expand-all
@node-click="handleNodeClick"
/>
</div>
</el-card>
</el-col>
<el-col :span="18">
<el-table
ref="userTableRef"
:key="userData.type"
height="500"
v-loading="userLoading"
:data="userList"
highlight-current-row
@current-change="changeCurrentUser"
@selection-change="handleSelectionChange"
>
<el-table-column
v-if="userData.type === 'copy' || userData.type === 'next'"
width="55"
type="selection"
/>
<el-table-column v-else width="30">
<template slot-scope="scope">
<el-radio :label="scope.row.userId" v-model="currentUserId">{{
""
}}</el-radio>
</template>
</el-table-column>
<el-table-column label="用户名" align="center" prop="nickName" />
<el-table-column label="手机" align="center" prop="phonenumber" />
<el-table-column label="部门" align="center" prop="dept.deptName" />
</el-table>
<pagination
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</el-col>
</el-row>
<span slot="footer" class="dialog-footer">
<el-button @click="userData.open = false"> </el-button>
<el-button type="primary" @click="submitUserData"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script setup>
import { detailProcess } from "@/api/flowable/process";
import Parser from "@/utils/generator/parser";
import {
complete,
delegate,
transfer,
rejectTask,
returnList,
returnTask,
} from "@/api/flowable/todo";
import tab from "@/plugins/tab";
import { selectUser, deptTreeSelect, listUser } from "@/api/system/user";
import ProcessViewer from "@/components/ProcessViewer";
import { computed, nextTick, reactive, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { addDateRange } from "@/utils/ruoyi";
import { ElMessage, ElMessageBox } from "element-plus";
import { parseTime } from "@/utils/ruoyi";
// import "@riophae/vue-treeselect/dist/vue-treeselect.css";
// import Treeselect from "@riophae/vue-treeselect";
const router = useRouter();
const taskFormRef = ref();
const userTableRef = ref();
const height = ref(document.documentElement.clientHeight - 205 + "px;");
// 模型xml数据
const loadIndex = ref(0);
const xmlData = ref(undefined);
const historyProcNodeList = ref([]);
// 部门名称
const deptName = ref(undefined);
// 部门树选项
const deptOptions = ref(undefined);
const userLoading = ref(false);
// 用户表格数据
const userList = ref(null);
const total = ref(0);
// 遮罩层
const loading = ref(true);
const currentUserId = ref(null);
const variables = ref([]); // 流程变量数
const taskFormOpen = ref(false);
const processFormList = ref([]); // 流程变量数
const formOpen = ref(false); // 是否加载流程变量数
const returnTaskList = ref([]); // 回退列表数
const finished = ref("false");
const returnTitle = ref(null);
const returnOpen = ref(false);
const rejectOpen = ref(false);
const rejectTitle = ref(null);
const copyUser = ref([]);
const nextUser = ref([]);
const userMultipleSelection = ref([]);
const userDialogTitle = ref("");
const userOpen = ref(false);
const commentType = computed(() => {
return (val) => {
switch (val) {
case "1":
return "通过";
case "2":
return "退回";
case "3":
return "驳回";
case "4":
return "委派";
case "5":
return "转办";
}
};
});
const approveTypeTag = computed(() => {
return (val) => {
switch (val) {
case "1":
return "success";
case "2":
return "warning";
case "3":
return "danger";
case "4":
return "primary";
case "5":
return "success";
}
};
});
const data = reactive({
deptProps: {
children: "children",
label: "label",
},
// 查询参数
queryParams: {
deptId: undefined,
},
taskForm: {
comment: "", // 意见内容
procInsId: "", // 流程实例编号
deployId: "", // 流程定义编号
taskId: "", // 流程任务编号
definitionId: "", // 流程编号
copyUserIds: "", // 抄送人Id
vars: "",
targetKey: "",
},
taskFormData: {}, // 流程变量数据
finishedInfo: {
finishedSequenceFlowSet: [],
finishedTaskSet: [],
unfinishedTaskSet: [],
rejectedTaskSet: [],
},
userData: {
title: "",
type: "",
open: false,
},
rules: {
comment: [{ required: true, message: "请输入审批意见", trigger: "blur" }],
},
});
const {
deptProps,
queryParams,
taskForm,
taskFormData,
finishedInfo,
userData,
rules,
} = toRefs(data);
const route = useRoute();
function initData() {
taskForm.value.procInsId = route.params && route.params.procInsId;
taskForm.value.deployId = route.query && route.query.deployId;
taskForm.value.definitionId = route.query && route.query.definitionId;
taskForm.value.taskId = route.query && route.query.taskId;
finished.value = route.query && route.query.finished;
// 流程任务重获取变量表单
if (taskForm.value.taskId) {
getProcessDetails(
taskForm.value.procInsId,
taskForm.value.deployId,
taskForm.value.taskId
);
}
loadIndex.value = taskForm.value.procInsId;
}
/** 查询部门下拉树结构 */
function getTreeSelect() {
deptTreeSelect().then((response) => {
deptOptions.value = response.data;
});
}
let dateRange;
/** 查询用户列表 */
function getList() {
userLoading.value = true;
// debugger;
listUser(addDateRange(queryParams.value, dateRange)).then((response) => {
userList.value = response.rows;
total.value = response.total;
toggleSelection(userMultipleSelection.value);
userLoading.value = false;
});
}
// 筛选节点
function filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
}
// 节点单击事件
function handleNodeClick(data) {
queryParams.value.deptId = data.id;
getList();
}
function setIcon(val) {
if (val) {
return "el-icon-check";
} else {
return "el-icon-time";
}
}
function setColor(val) {
if (val) {
return "#2bc418";
} else {
return "#b3bdbb";
}
}
// 多选框选中数据
function handleSelectionChange(selection) {
userMultipleSelection.value = selection;
}
function toggleSelection(selection) {
if (selection && selection.length > 0) {
nextTick(() => {
selection.forEach((item) => {
let row = userList.value.find((k) => k.userId === item.userId);
userTableRef.value.toggleRowSelection(row);
});
});
} else {
nextTick(() => {
userTableRef.value.clearSelection();
});
}
}
// 关闭标签
function handleClose(type, tag) {
let userObj = userMultipleSelection.value.find(
(item) => item.userId === tag.id
);
userMultipleSelection.value.splice(
userMultipleSelection.value.indexOf(userObj),
1
);
if (type === "copy") {
copyUser.value = userMultipleSelection.value;
// 设置抄送人ID
if (copyUser.value && copyUser.value.length > 0) {
const val = copyUser.value.map((item) => item.id);
taskForm.value.copyUserIds = val instanceof Array ? val.join(",") : val;
} else {
taskForm.value.copyUserIds = "";
}
} else if (type === "next") {
nextUser.value = userMultipleSelection.value;
// 设置抄送人ID
if (nextUser.value && nextUser.value.length > 0) {
const val = nextUser.value.map((item) => item.id);
taskForm.value.nextUserIds = val instanceof Array ? val.join(",") : val;
} else {
taskForm.value.nextUserIds = "";
}
}
}
/** 流程变量赋值 */
function handleCheckChange(val) {
if (val instanceof Array) {
taskForm.value.values = {
approval: val.join(","),
};
} else {
taskForm.value.values = {
approval: val,
};
}
}
function getProcessDetails(procInsId, deployId, taskId) {
const params = {
procInsId: procInsId,
deployId: deployId,
taskId: taskId,
};
detailProcess(params).then((res) => {
// const data = res.data;
const data = JSON.parse(res.msg);
// debugger;
xmlData.value = data.bpmnXml;
processFormList.value = data.processFormList;
taskFormOpen.value = data.existTaskForm;
if (taskFormOpen.value) {
taskFormData.value = data.taskFormData;
}
historyProcNodeList.value = data.historyProcNodeList;
finishedInfo.value = data.flowViewer;
formOpen.value = true;
});
}
function onSelectCopyUsers() {
userMultipleSelection.value = copyUser.value;
onSelectUsers("添加抄送人", "copy");
}
function onSelectNextUsers() {
userMultipleSelection.value = nextUser.value;
onSelectUsers("指定审批人", "next");
}
function onSelectUsers(title, type) {
userData.value.title = title;
userData.value.type = type;
getTreeSelect();
getList();
userData.value.open = true;
}
/** 通过任务 */
const taskFormParser = ref();
function handleComplete() {
// 校验表单
// console.log(taskFormParser.value);
// debugger;
// const taskFormRef = taskFormParser.value;
const isExistTaskForm = taskFormParser.value !== undefined;
// 若无任务表单,则 taskFormPromise 为 true即不需要校验
const taskFormPromise = !isExistTaskForm
? true
: new Promise((resolve, reject) => {
taskFormParser.value[
taskFormParser.value.formConfCopy.formRef
].validate((valid) => {
valid ? resolve() : reject();
});
});
const approvalPromise = new Promise((resolve, reject) => {
taskFormRef.value.validate((valid) => {
valid ? resolve() : reject();
});
});
Promise.all([taskFormPromise, approvalPromise]).then(() => {
if (isExistTaskForm) {
taskForm.value.variables =
taskFormParser.value[taskFormParser.value.formConfCopy.formModel];
}
complete(taskForm.value).then((response) => {
ElMessage.success(response.msg);
goBack();
});
});
}
/** 委派任务 */
function handleDelegate() {
taskFormRef.value.validate((valid) => {
if (valid) {
userData.value.type = "delegate";
userData.value.title = "委派任务";
userData.value.open = true;
getTreeSelect();
}
});
}
/** 转办任务 */
function handleTransfer() {
taskFormRef.value.validate((valid) => {
if (valid) {
userData.value.type = "transfer";
userData.value.title = "转办任务";
userData.value.open = true;
getTreeSelect();
}
});
}
/** 拒绝任务 */
function handleReject() {
taskFormRef.value.validate((valid) => {
if (valid) {
// const _this = this;
ElMessageBox.confirm("拒绝审批单流程会终止,是否继续?")
.then(function () {
return rejectTask(taskForm.value);
})
.then((res) => {
ElMessage.success(res.msg);
goBack();
});
}
});
}
function changeCurrentUser(val) {
currentUserId.value = val.userId;
}
/** 返回页面 */
function goBack() {
// 关闭当前标签页并返回上个页面
tab.closePage(route);
router.back();
}
/** 接收子组件传的值 */
function getData(data) {
if (data) {
const variables = [];
data.fields.forEach((item) => {
let variableData = {};
variableData.label = item.__config__.label;
// 表单值为多个选项时
if (item.__config__.defaultValue instanceof Array) {
const array = [];
item.__config__.defaultValue.forEach((val) => {
array.push(val);
});
variableData.val = array;
} else {
variableData.val = item.__config__.defaultValue;
}
variables.push(variableData);
});
variables.value = variables;
}
}
function submitUserData() {
let type = userData.value.type;
if (type === "copy" || type === "next") {
if (
!userMultipleSelection.value ||
userMultipleSelection.value.length <= 0
) {
ElMessage.error("请选择用户");
return false;
}
let userIds = userMultipleSelection.value.map((k) => k.userId);
if (type === "copy") {
// 设置抄送人ID信息
copyUser.value = userMultipleSelection.value;
taskForm.value.copyUserIds =
userIds instanceof Array ? userIds.join(",") : userIds;
} else if (type === "next") {
// 设置下一级审批人ID信息
nextUser.value = userMultipleSelection.value;
taskForm.value.nextUserIds =
userIds instanceof Array ? userIds.join(",") : userIds;
}
userData.value.open = false;
} else {
if (!taskForm.value.comment) {
ElMessage.error("请输入审批意见");
return false;
}
if (!currentUserId.value) {
ElMessage.error("请选择用户");
return false;
}
taskForm.value.userId = currentUserId.value;
if (type === "delegate") {
delegate(taskForm.value).then((res) => {
ElMessage.success(res.msg);
goBack();
});
}
if (type === "transfer") {
transfer(taskForm.value).then((res) => {
ElMessage.success(res.msg);
goBack();
});
}
}
}
/** 可退回任务列表 */
function handleReturn() {
taskFormRef.value.validate((valid) => {
if (valid) {
returnTitle.value = "退回流程";
returnList(taskForm.value).then((res) => {
returnTaskList.value = res.data;
taskForm.value.values = null;
returnOpen.value = true;
});
}
});
}
/** 提交退回任务 */
function submitReturn() {
taskFormRef.value.validate((valid) => {
if (valid) {
if (!taskForm.value.targetKey) {
ElMessage.error("请选择退回节点!");
}
returnTask(taskForm.value).then((res) => {
ElMessage.success(res.msg);
goBack();
});
}
});
}
initData();
</script>
<style lang="scss" scoped>
.clearfix:before,
.clearfix:after {
display: table;
content: "";
}
.clearfix:after {
clear: both;
}
.box-card {
width: 100%;
margin-bottom: 20px;
}
.el-tag + .el-tag {
margin-left: 10px;
}
.el-row {
margin-bottom: 20px;
&:last-child {
margin-bottom: 0;
}
}
.el-col {
border-radius: 4px;
}
.button-new-tag {
margin-left: 10px;
}
</style>

View File

@ -0,0 +1,275 @@
<template>
<div class="app-container">
<el-form
:model="queryParams"
ref="queryFormRef"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="开始时间" prop="deployTime">
<el-date-picker
clearable
size="small"
v-model="queryParams.deployTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="选择时间"
>
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="search"
size="small"
@click="handleQuery"
>搜索</el-button
>
<el-button icon="refresh" size="small" @click="resetQuery"
>重置</el-button
>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="delete"
size="small"
:disabled="multiple"
@click="handleDelete"
v-hasPermi="['workflow:process:remove']"
>删除</el-button
>
</el-col>
<right-toolbar
:showSearch.sync="showSearch"
@queryTable="getList"
></right-toolbar>
</el-row>
<el-table
v-loading="loading"
:data="finishedList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column
label="任务编号"
align="center"
prop="taskId"
:show-overflow-tooltip="true"
/>
<el-table-column
label="流程名称"
align="center"
prop="procDefName"
:show-overflow-tooltip="true"
/>
<el-table-column label="任务节点" align="center" prop="taskName" />
<el-table-column label="流程发起人" align="center">
<template #default="{ row }">
<label
>{{ row.startUserName }}
<el-tag type="info" size="small">{{
row.startDeptName
}}</el-tag></label
>
</template>
</el-table-column>
<el-table-column
label="接收时间"
align="center"
prop="createTime"
width="180"
/>
<el-table-column
label="审批时间"
align="center"
prop="finishTime"
width="180"
/>
<el-table-column
label="耗时"
align="center"
prop="duration"
width="180"
/>
<el-table-column
label="操作"
align="center"
class-name="small-padding fixed-width"
>
<template #default="{ row }">
<el-button
size="small"
type="primary"
link
icon="tickets"
@click="handleFlowRecord(row)"
v-hasPermi="['flowable:process:query']"
>流转记录</el-button
>
<el-button
size="small"
type="primary"
link
icon="tickets"
@click="handleRevoke(row)"
v-hasPermi="['flowable:process:revoke']"
>撤回
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</div>
</template>
<script setup name="Finished">
import { listFinishedProcess } from "@/api/flowable/process";
import { revokeProcess } from "@/api/flowable/finished";
import { useRouter } from "vue-router";
import { ref, reactive, toRefs } from "vue";
const queryFormRef = ref();
// 遮罩层
const loading = ref(true);
// 选中数组
const ids = ref([]);
// 非单个禁用
const single = ref(true);
// 非多个禁用
const multiple = ref(true);
// 显示搜索条件
const showSearch = ref(true);
// 总条数
const total = ref(0);
// 已办任务列表数据
const finishedList = ref([]);
// 弹出层标题
const title = ref("");
// 是否显示弹出层
const open = ref(false);
const src = ref("");
const data = reactive({
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
name: null,
category: null,
key: null,
tenantId: null,
deployTime: null,
derivedFrom: null,
derivedFromRoot: null,
parentDeploymentId: null,
engineVersion: null,
},
// 表单参数
form: {},
// 表单校验
rules: {},
});
const { queryParams, form, rules } = toRefs(data);
/** 查询流程定义列表 */
function getList() {
loading.value = true;
listFinishedProcess(queryParams.value).then((response) => {
finishedList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
/** 搜索按钮操作 */
function handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
}
/** 重置按钮操作 */
function resetQuery() {
if (queryFormRef.value) {
queryFormRef.value.resetFields();
}
handleQuery();
}
// 多选框选中数据
function handleSelectionChange(selection) {
ids.value = selection.map((item) => item.id);
single.value = selection.length !== 1;
multiple.value = !selection.length;
}
/** 流程流转记录 */
const router = useRouter();
function handleFlowRecord(row) {
router.push({
path: "/flowable/process/detail/" + row.procInsId,
query: {
definitionId: row.procDefId,
deployId: row.deployId,
taskId: row.taskId,
finished: false,
},
});
}
/** 撤回任务 */
function handleRevoke(row) {
const params = {
procInsId: row.procInsId,
};
revokeProcess(params).then((res) => {
this.$modal.msgSuccess(res.msg);
this.getList();
});
}
/** 删除按钮操作 */
function handleDelete(row) {
const ids = row.id || this.ids;
this.$confirm('是否确认删除流程定义编号为"' + ids + '"的数据项?', "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return delDeployment(ids);
})
.then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
});
}
defineExpose({
getList,
});
</script>
<script>
export default {
beforeRouteEnter(to, from, next) {
next((vm) => {
vm.getList();
});
},
};
</script>

221
src/views/office/index.vue Normal file
View File

@ -0,0 +1,221 @@
<template>
<div class="app-container">
<el-form
:model="queryParams"
ref="queryFormRef"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="开始时间" prop="deployTime">
<el-date-picker
clearable
size="small"
v-model="queryParams.deployTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="选择时间"
>
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="search"
size="small"
@click="handleQuery"
>搜索</el-button
>
<el-button icon="refresh" size="small" @click="resetQuery"
>重置</el-button
>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<right-toolbar
v-model:showSearch="showSearch"
@queryTable="getList"
></right-toolbar>
</el-row>
<el-table v-loading="loading" fit :data="processList">
<el-table-column label="序号" type="index" width="50"></el-table-column>
<el-table-column
label="流程标识"
align="center"
prop="processKey"
:show-overflow-tooltip="true"
/>
<el-table-column
label="流程名称"
align="center"
:show-overflow-tooltip="true"
>
<template #default="{ row }">
<el-button link type="primary" @click="handleProcessView(row)">
<span>{{ row.processName }}</span>
</el-button>
</template>
</el-table-column>
<el-table-column
label="流程分类"
align="center"
prop="categoryName"
:formatter="categoryFormat"
/>
<el-table-column label="流程版本" align="center">
<template #default="{ row }">
<el-tag size="default">v{{ row.version }}</el-tag>
</template>
</el-table-column>
<el-table-column label="状态" align="center">
<template #default="{ row }">
<el-tag type="success" v-if="!row.suspended">激活</el-tag>
<el-tag type="warning" v-if="row.suspended">挂起</el-tag>
</template>
</el-table-column>
<el-table-column
label="部署时间"
align="center"
prop="deploymentTime"
width="180"
/>
<el-table-column
label="操作"
align="center"
class-name="small-padding fixed-width"
>
<template #default="{ row }">
<el-button
type="primary"
link
size="small"
icon="video-play"
@click="handleStart(row)"
v-hasPermi="['flowable:process:start']"
>发起</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<!-- 流程图 -->
<el-dialog
:title="processView.title"
v-model="processView.open"
width="70%"
append-to-body
>
<process-viewer
:key="`designer-${processView.index}`"
:xml="processView.xmlData"
:style="{ height: '400px' }"
/>
</el-dialog>
</div>
</template>
<script setup name="WorkProcess">
import { listProcess, getBpmnXml } from "@/api/flowable/process";
import { listAllCategory } from "@/api/flowable/category";
import ProcessViewer from "@/components/ProcessViewer";
import { toRefs, reactive, ref } from "vue";
import { useRouter } from "vue-router";
const queryFormRef = ref();
// 遮罩层
const loading = ref(true);
// 显示搜索条件
const showSearch = ref(true);
// 总条数
const total = ref(0);
const filterCategoryText = ref("");
const categoryOptions = ref([]);
// 流程定义表格数据
const processList = ref([]);
const data = reactive({
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
},
categoryProps: {
label: "categoryName",
value: "code",
},
processView: {
title: "",
open: false,
index: undefined,
xmlData: "",
},
});
const { queryParams, categoryProps, processView } = toRefs(data);
/** 查询流程分类列表 */
function getCategoryList() {
listAllCategory().then((response) => (categoryOptions.value = response.rows));
}
/** 查询流程定义列表 */
function getList() {
listProcess(queryParams.value).then((response) => {
processList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
// 搜索按钮操作
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
// 重置按钮操作
function resetQuery() {
if (queryFormRef.value) {
queryFormRef.value.resetFields();
}
handleQuery();
}
/** 查看流程图 */
function handleProcessView(row) {
let definitionId = row.definitionId;
processView.value.title = "流程图";
processView.value.index = definitionId;
// 发送请求获取xml
getBpmnXml(definitionId).then((res) => {
processView.value.xmlData = res.data;
});
processView.value.open = true;
}
const router = useRouter();
function handleStart(row) {
router.push({
path: "/flowable/process/start/" + row.deploymentId,
query: {
definitionId: row.definitionId,
},
});
}
function categoryFormat(row, column) {
return (
categoryOptions.value.find((k) => k.code === row.category)?.categoryName ??
""
);
}
getCategoryList();
getList();
</script>

364
src/views/office/own.vue Normal file
View File

@ -0,0 +1,364 @@
<template>
<div class="app-container">
<el-form
:model="queryParams"
ref="queryFormRef"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="开始时间" prop="deployTime">
<el-date-picker
clearable
size="small"
v-model="queryParams.deployTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="选择时间"
>
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="search"
size="small"
@click="handleQuery"
>搜索</el-button
>
<el-button icon="refresh" size="small" @click="resetQuery"
>重置</el-button
>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="delete"
size="small"
:disabled="multiple"
@click="handleDelete"
>删除</el-button
>
</el-col>
<el-col :span="1.5">
<el-button
type="warning"
plain
icon="download"
size="small"
@click="handleExport"
>导出</el-button
>
</el-col>
<right-toolbar
v-model:showSearch="showSearch"
@queryTable="getList"
></right-toolbar>
</el-row>
<el-table
v-loading="loading"
:data="ownProcessList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column
label="流程编号"
align="center"
prop="procInsId"
:show-overflow-tooltip="true"
/>
<el-table-column
label="流程名称"
align="center"
prop="procDefName"
:show-overflow-tooltip="true"
/>
<el-table-column
label="流程类别"
align="center"
prop="category"
:formatter="categoryFormat"
/>
<el-table-column label="流程版本" align="center" width="80px">
<template #default="{ row }">
<el-tag size="default">v{{ row.procDefVersion }}</el-tag>
</template>
</el-table-column>
<el-table-column
label="提交时间"
align="center"
prop="createTime"
width="180"
/>
<el-table-column label="流程状态" align="center" width="100">
<template #default="{ row }">
<el-tag v-if="row.finishTime == null" size="small">进行中</el-tag>
<el-tag type="success" v-if="row.finishTime != null" size="small"
>已完成</el-tag
>
</template>
</el-table-column>
<el-table-column
label="耗时"
align="center"
prop="duration"
width="180"
/>
<el-table-column label="当前节点" align="center" prop="taskName" />
<el-table-column label="办理" align="center">
<template #default="{ row }">
<label v-if="row.assigneeName"
>{{ row.assigneeName }}
<el-tag type="info" size="small">{{ row.deptName }}</el-tag></label
>
<label v-if="row.candidate">{{ row.candidate }}</label>
</template>
</el-table-column>
<el-table-column
label="操作"
align="center"
class-name="small-padding fixed-width"
>
<template #default="{ row }">
<el-button
type="primary"
link
size="small"
icon="tickets"
@click="handleFlowRecord(row)"
v-hasPermi="['flowable:process:query']"
>详情</el-button
>
<el-button
type="primary"
link
size="small"
icon="delete"
@click="handleDelete(row)"
v-hasPermi="['flowable:process:remove']"
>删除</el-button
>
<el-button
type="primary"
link
size="small"
icon="circle-close"
@click="handleStop(row)"
v-hasPermi="['flowable:process:cancel']"
>取消</el-button
>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</div>
</template>
<script setup name="Own">
import {
listOwnProcess,
stopProcess,
delProcess,
} from "@/api/flowable/process";
import { download } from "@/utils/request";
import { listAllCategory } from "@/api/flowable/category";
import { ref, reactive, toRefs } from "vue";
import { useRouter } from "vue-router";
import { ElMessage, ElMessageBox } from "element-plus";
const queryFormRef = ref();
// 遮罩层
const loading = ref(true);
const processLoading = ref(true);
// 选中数组
const ids = ref([]);
// 非单个禁用
const single = ref(true);
// 非多个禁用
const multiple = ref(true);
// 显示搜索条件
const showSearch = ref(true);
// 总条数
const total = ref(0);
const categoryOptions = ref([]);
const processTotal = ref(0);
// 我发起的流程列表数据
const ownProcessList = ref([]);
// 弹出层标题
const title = ref("");
// 是否显示弹出层
const open = ref(false);
const src = ref("");
const definitionList = ref([]);
const data = reactive({
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
name: null,
category: null,
key: null,
tenantId: null,
deployTime: null,
derivedFrom: null,
derivedFromRoot: null,
parentDeploymentId: null,
engineVersion: null,
},
// 表单参数
form: {},
// 表单校验
rules: {},
});
const { queryParams, form, rules } = toRefs(data);
/** 查询流程分类列表 */
function getCategoryList() {
listAllCategory().then((response) => (categoryOptions.value = response.rows));
}
/** 查询流程定义列表 */
function getList() {
loading.value = true;
listOwnProcess(queryParams.value).then((response) => {
ownProcessList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
if (queryFormRef.value) {
queryFormRef.value.resetFields();
}
handleQuery();
}
// 多选框选中数据
function handleSelectionChange(selection) {
ids.value = selection.map((item) => item.procInsId);
single.value = selection.length !== 1;
multiple.value = !selection.length;
}
/** 取消流程申请 */
function handleStop(row) {
const params = {
procInsId: row.procInsId,
};
stopProcess(params).then((res) => {
ElMessage.success(res.msg);
getList();
});
}
const router = useRouter();
/** 流程流转记录 */
function handleFlowRecord(row) {
router.push({
path: "/flowable/process/detail/" + row.procInsId,
query: {
definitionId: row.procDefId,
deployId: row.deployId,
taskId: row.taskId,
finished: false,
},
});
}
/** 删除按钮操作 */
function handleDelete(row) {
// const ids = row.procInsId;
const deleteIds = row.procInsId ? [row.procInsId] : ids.value;
ElMessageBox.confirm(
'是否确认删除流程定义编号为"' + deleteIds.join(",") + '"的数据项?',
"警告",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
)
.then(function () {
return delProcess(deleteIds.join(","));
})
.then(() => {
getList();
ElMessage.success("删除成功");
});
}
/** 导出按钮操作 */
function handleExport() {
// const queryParams = queryParams.value;
ElMessageBox.confirm("是否确认导出所有流程定义数据项?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
// return exportDeployment(queryParams);
})
.then((response) => {
download(response.msg);
});
}
function categoryFormat(row, column) {
return (
categoryOptions.value.find((k) => k.code === row.category)?.categoryName ??
""
);
}
getCategoryList();
defineExpose({
getList,
});
</script>
<script>
export default {
beforeRouteEnter(to, from, next) {
next((vm) => {
vm.getList();
});
},
};
</script>
<!-- <script>
export default {
name: "Own",
components: {},
data() {
return {};
},
created() {
this.getCategoryList();
},
beforeRouteEnter(to, from, next) {
next((vm) => {
vm.getList();
});
},
methods: {},
};
</script> -->

View File

@ -0,0 +1,95 @@
<template>
<div class="app-container">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>发起流程</span>
</div>
<el-col :span="18" :offset="3">
<div class="form-conf" v-if="formOpen">
<parser
:key="new Date().getTime()"
:form-conf="formData"
@submit="submit"
ref="parser"
@getData="getData"
/>
</div>
</el-col>
</el-card>
</div>
</template>
<script setup name="WorkStart">
import { getProcessForm, startProcess } from "@/api/flowable/process";
import Parser from "@/utils/generator/parser";
import { ElMessage } from "element-plus";
import { reactive, toRefs, ref } from "vue";
import tab from "@/plugins/tab";
import { useRoute } from "vue-router";
const definitionId = ref(null);
const deployId = ref(null);
const formOpen = ref(false);
const data = reactive({
formData: {},
});
const { formData } = toRefs(data);
const route = useRoute();
function initData() {
deployId.value = route.params && route.params.deployId;
definitionId.value = route.query && route.query.definitionId;
getProcessForm({
definitionId: definitionId.value,
deployId: deployId.value,
}).then((res) => {
if (res.msg) {
formData.value = JSON.parse(res.msg);
formOpen.value = true;
}
});
}
/** 接收子组件传的值 */
function getData(data) {
if (data) {
const variables = [];
data.fields.forEach((item) => {
let variableData = {};
variableData.label = item.__config__.label;
// 表单值为多个选项时
if (item.__config__.defaultValue instanceof Array) {
const array = [];
item.__config__.defaultValue.forEach((val) => {
array.push(val);
});
variableData.val = array;
} else {
variableData.val = item.__config__.defaultValue;
}
variables.push(variableData);
});
variables.value = variables;
}
}
function submit(data) {
if (data && definitionId.value) {
// 启动流程并将表单数据加入流程变量
startProcess(definitionId.value, JSON.stringify(data.valData)).then(
(res) => {
ElMessage.success(res.msg);
tab.closeOpenPage({
path: "/office/own",
});
}
);
}
}
initData();
</script>
<style lang="scss" scoped>
.form-conf {
margin: 15px auto;
width: 80%;
padding: 15px;
}
</style>

260
src/views/office/todo.vue Normal file
View File

@ -0,0 +1,260 @@
<template>
<div class="app-container">
<el-form
:model="queryParams"
ref="queryFormRef"
:inline="true"
v-show="showSearch"
label-width="68px"
>
<el-form-item label="名称" prop="name">
<el-input
v-model="queryParams.name"
placeholder="请输入名称"
clearable
size="small"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="开始时间" prop="deployTime">
<el-date-picker
clearable
size="small"
v-model="queryParams.deployTime"
type="date"
value-format="YYYY-MM-DD"
placeholder="选择时间"
>
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="search"
size="small"
@click="handleQuery"
>搜索</el-button
>
<el-button icon="refresh" size="small" @click="resetQuery"
>重置</el-button
>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="danger"
plain
icon="delete"
size="small"
:disabled="multiple"
@click="handleDelete"
>删除
</el-button>
</el-col>
<right-toolbar
v-model:showSearch="showSearch"
@queryTable="getList"
></right-toolbar>
</el-row>
<el-table
v-loading="loading"
:data="todoList"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" width="55" align="center" />
<el-table-column
label="任务编号"
align="center"
prop="taskId"
:show-overflow-tooltip="true"
/>
<el-table-column label="流程名称" align="center" prop="procDefName" />
<el-table-column label="任务节点" align="center" prop="taskName" />
<el-table-column label="流程版本" align="center">
<template #default="{ row }">
<el-tag size="default">v{{ row.procDefVersion }}</el-tag>
</template>
</el-table-column>
<el-table-column label="流程发起人" align="center">
<template #default="{ row }">
<label
>{{ row.startUserName }}
<el-tag type="info" size="small">{{
row.startDeptName
}}</el-tag></label
>
</template>
</el-table-column>
<el-table-column
label="接收时间"
align="center"
prop="createTime"
width="180"
/>
<el-table-column
label="操作"
align="center"
class-name="small-padding fixed-width"
>
<template #default="{ row }">
<el-button
size="small"
link
type="primary"
icon="edit"
@click="handleProcess(row)"
v-hasPermi="['flowable:process:approval']"
>办理
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="queryParams.pageNum"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</div>
</template>
<script setup name="Todo">
import { listTodoProcess } from "@/api/flowable/process";
// import { delDeployment, exportDeployment } from "@/api/flowable/todo";
import { ElMessage, ElMessageBox } from "element-plus";
import { ref, reactive, toRefs } from "vue";
import { useRouter } from "vue-router";
const queryFormRef = ref();
const router = useRouter();
// 遮罩层
const loading = ref(true);
// 选中数组
const ids = ref([]);
// 非单个禁用
const single = ref(true);
// 非多个禁用
const multiple = ref(true);
// 显示搜索条件
const showSearch = ref(true);
// 总条数
const total = ref(0);
// 流程待办任务表格数据
const todoList = ref([]);
// 弹出层标题
const title = ref("");
// 是否显示弹出层
const open = ref(false);
const data = reactive({
// 查询参数
queryParams: {
pageNum: 1,
pageSize: 10,
name: null,
category: null,
},
// 表单参数
form: {},
// 表单校验
rules: {},
});
const { queryParams, form, rules } = toRefs(data);
/** 查询流程定义列表 */
function getList() {
loading.value = true;
listTodoProcess(queryParams.value).then((response) => {
todoList.value = response.rows;
total.value = response.total;
loading.value = false;
});
}
// 跳转到处理页面
function handleProcess(row) {
router.push({
path: "/flowable/process/detail/" + row.procInsId,
query: {
definitionId: row.procDefId,
deployId: row.deployId,
taskId: row.taskId,
finished: true,
},
});
}
/** 搜索按钮操作 */
function handleQuery() {
queryParams.value.pageNum = 1;
getList();
}
/** 重置按钮操作 */
function resetQuery() {
if (queryFormRef.value) {
queryFormRef.value.resetFields();
}
handleQuery();
}
// 多选框选中数据
function handleSelectionChange(selection) {
ids.value = selection.map((item) => item.id);
single.value = selection.length !== 1;
multiple.value = !selection.length;
}
// /** 新增按钮操作 */
// function handleAdd() {
// reset();
// open.value = true;
// title.value = "添加流程定义";
// }
/** 删除按钮操作 */
function handleDelete(row) {
const ids = row.id || ids.value;
ElMessageBox.confirm(
'是否确认删除流程定义编号为"' + ids + '"的数据项?',
"警告",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}
)
.then(function () {
return delDeployment(ids);
})
.then(() => {
getList();
ElMessage.success("删除成功");
});
}
/** 导出按钮操作 */
function handleExport() {
const queryParams = queryParams.value;
ElMessageBox.confirm("是否确认导出所有流程定义数据项?", "警告", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return exportDeployment(queryParams);
})
.then((response) => {
this.download(response.msg);
});
}
defineExpose({
getList,
});
</script>
<script>
export default {
beforeRouteEnter(to, from, next) {
next((vm) => {
vm.getList();
});
},
};
</script>