!172 合并 warmflow 功能分支
* update 优化 流程定义页面 点击复制之后跳转到未发布列表 * update 优化 流程定义页面 增加加载loading层 * fix: v-model处理有延迟 需要手动处理 * update 调整流程定义查询 * Merge remote-tracking branch 'origin/dev' into warm-flw-future * update 调整可驳回的节点 * update: 调整文案 * update: 激活/挂起改为switch操作 * update 优化 代码删除无用输出 * update 统一抄送人使用昵称展示 * update 调整分类接口 * update 统一业务id参数 * update 删除默认顶节点 * !168 优化流程分类 * update 恢复误删除代码 * update 优化流程分类 * update 修复 路由跳转未改全 * [update] * fix 修复一些问题 * update 重构流程分类表 * update 流程定义增加表单路径与编辑功能 修复一些其他bug * fix 修复 一些问题 * update 变量统一命名 * add 增加示例 * Merge branch 'warm-flw-future' of https://gitee.com/JavaLionLi/plus-ui… * update 调整办理人 * Merge remote-tracking branch 'origin/dev' into warm-flw-future * add 增加示例 * update 调整审批记录 添加流程导出 * remove 删除无用代码 * remove 删除无用代码 * [update] * [fix] * 流程干预删除委托 * 增加附件 * 附件修改 * 申请人查询修改 * 1.修改查询条件 * !167 fix 修复 import路径修改不全问题 * fix 修复 import路径修改不全问题 * !166 update 清除 ProcessPreview 引用 * update 清除 ProcessPreview 引用 * remove 删除 bpmn.js 设计器 * remove 删除 bpmn.js 设计器 * remove 删除 bpmn.js 设计器 * remove 删除 bpmn.js 设计器 * fix 修复 前端路径修改不全问题 * update 优化接口请求路径 * add 添加作废 * add 添加流程干预 * update 调整加签,减签 * update 调整加签,减签 * add 增加流程查看 * update 调整委托,转办 * update 调整流程变量显示 * update 调整办理人修改 * update 调整流程实例状态页面 * update 调整已办页面 * add 添加流程撤销 * update 调整任务,流程实例 ,流程定义页面 * Merge branch 'dev' into warm-flw-future * update 调整流程定义页面 * add 添加流程变量查看 * update 调整设计器路由名称 * update 调整办理人 * update 调整设计器uri * update 调整设计器请求uri 调整待办状态 * update 调整办理 驳回 终止等状态 * add 添加模型新增 * add 添加warm-ui设计器,删除无用代码 * Merge remote-tracking branch 'origin/dev' into warm-flw-future * add 添加流程设计 * update 调整驳回 * update 调整视图类型错误 * Merge branch 'warm-flw-future' of https://gitee.com/JavaLionLi/plus-ui… * 添加已办,未办 * Merge remote-tracking branch 'origin/dev' into warm-flw-future * update 调整流程实例,待办查询 * add 添加代办人,调整提交按钮校验 * update 调整流程定义查询 * add添加流程定义激活 挂起 * add 添加流程文件部署 调整流程发布 * update 优化 时间搜索组件统一 * Merge remote-tracking branch 'origin/dev' into warm-flw-future * fix 修复 用户管理编辑安全权限错误问题 * Merge remote-tracking branch 'origin/dev' into warm-flw-future * update 优化 类型报错问题 * update 优化 切换租户后刷新首页 * update 优化 实现表格行选中切换 * update 优化 使用 vueuse 重构 websocket 实现 * update 优化 使用 vueuse 重构 websocket 实现 * fix 修复 登出后重新登录 sse推送报错问题 * reset 回滚 代码修改 采用其他方案 * fix 修复 登出后重新登录 sse推送报错问题 * update 优化 删除无用代码 * update element-plus 2.7.5 => 2.7.8 * reset 回滚 错误修复 * update 优化 代码生成器编辑页禁用缓存 防止同步后页面不更新问题 * fix 修复 代码生成同步点击取消报错问题 * 初始化添加warm-flow
This commit is contained in:
@ -1,71 +0,0 @@
|
||||
<template>
|
||||
<div class="design">
|
||||
<el-dialog v-model="visible" width="100%" fullscreen :title="title">
|
||||
<div class="modeler">
|
||||
<bpmn-design ref="bpmnDesignRef" @save-call-back="saveCallBack"></bpmn-design>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup name="Design">
|
||||
import { getInfo, editModelXml } from '@/api/workflow/model';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
import { ModelForm } from '@/api/workflow/model/types';
|
||||
import BpmnDesign from '@/bpmn/index.vue';
|
||||
import useDialog from '@/hooks/useDialog';
|
||||
const bpmnDesignRef = ref<InstanceType<typeof BpmnDesign>>();
|
||||
const modelForm = ref<ModelForm>();
|
||||
const emit = defineEmits(['closeCallBack']);
|
||||
const { visible, title } = useDialog({
|
||||
title: '编辑流程'
|
||||
});
|
||||
const modelId = ref('');
|
||||
const open = async (id) => {
|
||||
visible.value = true;
|
||||
modelId.value = id;
|
||||
const { data } = await getInfo(id);
|
||||
modelForm.value = data;
|
||||
bpmnDesignRef.value.initDiagram(modelForm.value.xml);
|
||||
};
|
||||
//保存模型
|
||||
const saveCallBack = async (data) => {
|
||||
await proxy?.$modal.confirm('是否确认保存?');
|
||||
data.loading.value = true;
|
||||
modelForm.value.id = modelId.value;
|
||||
modelForm.value.xml = data.xml;
|
||||
modelForm.value.svg = data.svg;
|
||||
modelForm.value.key = data.key;
|
||||
modelForm.value.name = data.name;
|
||||
editModelXml(modelForm.value).then((res) => {
|
||||
if (res.code === 200) {
|
||||
visible.value = false;
|
||||
proxy?.$modal.msgSuccess('保存成功');
|
||||
emit('closeCallBack', data);
|
||||
}
|
||||
});
|
||||
data.loading.value = false;
|
||||
};
|
||||
|
||||
/**
|
||||
* 对外暴露子组件方法
|
||||
*/
|
||||
defineExpose({
|
||||
open
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.design {
|
||||
:deep(.el-dialog .el-dialog__body) {
|
||||
max-height: 100% !important;
|
||||
min-height: calc(100vh - 80px);
|
||||
padding: 10px 0 10px 0 !important;
|
||||
}
|
||||
:deep(.el-dialog__header) {
|
||||
padding: 0 0 5px 0 !important;
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,411 +0,0 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="bpmnDialogContainers">
|
||||
<el-header style="border-bottom: 1px solid rgb(218 218 218); height: auto">
|
||||
<div class="header-div">
|
||||
<div>
|
||||
<el-tooltip effect="dark" content="自适应屏幕" placement="bottom">
|
||||
<el-button size="small" icon="Rank" @click="fitViewport" />
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" content="放大" placement="bottom">
|
||||
<el-button size="small" icon="ZoomIn" @click="zoomViewport(true)" />
|
||||
</el-tooltip>
|
||||
<el-tooltip effect="dark" content="缩小" placement="bottom">
|
||||
<el-button size="small" icon="ZoomOut" @click="zoomViewport(false)" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div>
|
||||
<div class="tips-label">
|
||||
<div class="un-complete">未完成</div>
|
||||
<div class="in-progress">进行中</div>
|
||||
<div class="complete">已完成</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</el-header>
|
||||
<div class="flow-containers">
|
||||
<el-container class="bpmn-el-container" style="align-items: stretch">
|
||||
<el-main style="padding: 0">
|
||||
<div ref="canvas" class="canvas" />
|
||||
</el-main>
|
||||
</el-container>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import BpmnViewer from 'bpmn-js/lib/Viewer';
|
||||
import MoveCanvasModule from 'diagram-js/lib/navigation/movecanvas';
|
||||
import ZoomScrollModule from 'diagram-js/lib/navigation/zoomscroll';
|
||||
import { ModuleDeclaration } from 'didi';
|
||||
import type { Canvas, ModdleElement } from 'bpmn';
|
||||
import EventBus from 'diagram-js/lib/core/EventBus';
|
||||
import Overlays from 'diagram-js/lib/features/overlays/Overlays';
|
||||
import processApi from '@/api/workflow/processInstance/index';
|
||||
|
||||
const canvas = ref<HTMLElement>();
|
||||
const modeler = ref<BpmnViewer>();
|
||||
const taskList = ref([]);
|
||||
const zoom = ref(1);
|
||||
const xml = ref('');
|
||||
const loading = ref(false);
|
||||
const bpmnVisible = ref(true);
|
||||
const historyList = ref([]);
|
||||
|
||||
const init = (businessKey) => {
|
||||
loading.value = true;
|
||||
bpmnVisible.value = true;
|
||||
nextTick(async () => {
|
||||
if (modeler.value) modeler.value.destroy();
|
||||
modeler.value = new BpmnViewer({
|
||||
container: canvas.value,
|
||||
additionalModules: [
|
||||
{
|
||||
//禁止滚轮滚动
|
||||
zoomScroll: ['value', '']
|
||||
},
|
||||
ZoomScrollModule,
|
||||
MoveCanvasModule
|
||||
] as ModuleDeclaration[]
|
||||
});
|
||||
const resp = await processApi.getHistoryList(businessKey);
|
||||
xml.value = resp.data.xml;
|
||||
taskList.value = resp.data.taskList;
|
||||
historyList.value = resp.data.historyList;
|
||||
await createDiagram(xml.value);
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const initXml = (xmlStr: string) => {
|
||||
loading.value = true;
|
||||
bpmnVisible.value = true;
|
||||
nextTick(async () => {
|
||||
if (modeler.value) modeler.value.destroy();
|
||||
modeler.value = new BpmnViewer({
|
||||
container: canvas.value,
|
||||
additionalModules: [
|
||||
{
|
||||
//禁止滚轮滚动
|
||||
zoomScroll: ['value', '']
|
||||
},
|
||||
ZoomScrollModule,
|
||||
MoveCanvasModule
|
||||
] as ModuleDeclaration[]
|
||||
});
|
||||
xml.value = xmlStr;
|
||||
await createDiagram(xml.value);
|
||||
loading.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const createDiagram = async (data) => {
|
||||
try {
|
||||
await modeler.value.importXML(data);
|
||||
fitViewport();
|
||||
fillColor();
|
||||
loading.value = false;
|
||||
addEventBusListener();
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
const addEventBusListener = () => {
|
||||
const eventBus = modeler.value.get<EventBus>('eventBus');
|
||||
const overlays = modeler.value.get<Overlays>('overlays');
|
||||
eventBus.on<ModdleElement>('element.hover', (e) => {
|
||||
let data = historyList.value.find((t) => t.taskDefinitionKey === e.element.id);
|
||||
if (e.element.type === 'bpmn:UserTask' && data) {
|
||||
setTimeout(() => {
|
||||
genNodeDetailBox(e, overlays, data);
|
||||
}, 10);
|
||||
}
|
||||
});
|
||||
eventBus.on('element.out', (e) => {
|
||||
overlays.clear();
|
||||
});
|
||||
};
|
||||
const genNodeDetailBox = (e, overlays, data) => {
|
||||
overlays.add(e.element.id, {
|
||||
position: { top: e.element.height, left: 0 },
|
||||
html: `<div class="verlays">
|
||||
<p>审批人员: ${data.nickName || ''}<p/>
|
||||
<p>节点状态:${data.status || ''}</p>
|
||||
<p>开始时间:${data.startTime || ''}</p>
|
||||
<p>结束时间:${data.endTime || ''}</p>
|
||||
<p>审批耗时:${data.runDuration || ''}</p>
|
||||
<p>流程版本:v${data.version || ''}</p>
|
||||
</div>`
|
||||
});
|
||||
};
|
||||
// 让图能自适应屏幕
|
||||
const fitViewport = () => {
|
||||
zoom.value = modeler.value.get<Canvas>('canvas').zoom('fit-viewport');
|
||||
const bbox = document.querySelector<SVGGElement>('.flow-containers .viewport').getBBox();
|
||||
const currentViewBox = modeler.value.get('canvas').viewbox();
|
||||
const elementMid = {
|
||||
x: bbox.x + bbox.width / 2 - 65,
|
||||
y: bbox.y + bbox.height / 2
|
||||
};
|
||||
modeler.value.get<Canvas>('canvas').viewbox({
|
||||
x: elementMid.x - currentViewBox.width / 2,
|
||||
y: elementMid.y - currentViewBox.height / 2,
|
||||
width: currentViewBox.width,
|
||||
height: currentViewBox.height
|
||||
});
|
||||
zoom.value = (bbox.width / currentViewBox.width) * 1.8;
|
||||
};
|
||||
// 放大缩小
|
||||
const zoomViewport = (zoomIn = true) => {
|
||||
zoom.value = modeler.value.get<Canvas>('canvas').zoom();
|
||||
zoom.value += zoomIn ? 0.1 : -0.1;
|
||||
modeler.value.get<Canvas>('canvas').zoom(zoom.value);
|
||||
};
|
||||
//上色
|
||||
const fillColor = () => {
|
||||
const canvas = modeler.value.get<Canvas>('canvas');
|
||||
bpmnNodeList(modeler.value._definitions.rootElements[0].flowElements, canvas);
|
||||
};
|
||||
//递归上色
|
||||
const bpmnNodeList = (flowElements, canvas) => {
|
||||
flowElements.forEach((n) => {
|
||||
if (n.$type === 'bpmn:UserTask') {
|
||||
const completeTask = taskList.value.find((m) => m.key === n.id);
|
||||
if (completeTask) {
|
||||
canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo');
|
||||
n.outgoing?.forEach((nn) => {
|
||||
const targetTask = taskList.value.find((m) => m.key === nn.targetRef.id);
|
||||
if (targetTask) {
|
||||
canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo');
|
||||
} else if (nn.targetRef.$type === 'bpmn:ExclusiveGateway') {
|
||||
canvas.addMarker(nn.id, completeTask.completed ? 'highlight' : 'highlight-todo');
|
||||
canvas.addMarker(nn.targetRef.id, completeTask.completed ? 'highlight' : 'highlight-todo');
|
||||
nn.targetRef.outgoing.forEach((e) => {
|
||||
gateway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed);
|
||||
});
|
||||
} else if (nn.targetRef.$type === 'bpmn:ParallelGateway') {
|
||||
canvas.addMarker(nn.id, completeTask.completed ? 'highlight' : 'highlight-todo');
|
||||
canvas.addMarker(nn.targetRef.id, completeTask.completed ? 'highlight' : 'highlight-todo');
|
||||
nn.targetRef.outgoing.forEach((e) => {
|
||||
gateway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed);
|
||||
});
|
||||
} else if (nn.targetRef.$type === 'bpmn:InclusiveGateway') {
|
||||
canvas.addMarker(nn.id, completeTask.completed ? 'highlight' : 'highlight-todo');
|
||||
canvas.addMarker(nn.targetRef.id, completeTask.completed ? 'highlight' : 'highlight-todo');
|
||||
nn.targetRef.outgoing.forEach((e) => {
|
||||
gateway(e.id, e.targetRef.$type, e.targetRef.id, canvas, completeTask.completed);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (n.$type === 'bpmn:ExclusiveGateway') {
|
||||
n.outgoing.forEach((nn) => {
|
||||
const targetTask = taskList.value.find((m) => m.key === nn.targetRef.id);
|
||||
if (targetTask) {
|
||||
canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo');
|
||||
}
|
||||
});
|
||||
} else if (n.$type === 'bpmn:ParallelGateway') {
|
||||
n.outgoing.forEach((nn) => {
|
||||
const targetTask = taskList.value.find((m) => m.key === nn.targetRef.id);
|
||||
if (targetTask) {
|
||||
canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo');
|
||||
}
|
||||
});
|
||||
} else if (n.$type === 'bpmn:InclusiveGateway') {
|
||||
n.outgoing.forEach((nn) => {
|
||||
const targetTask = taskList.value.find((m) => m.key === nn.targetRef.id);
|
||||
if (targetTask) {
|
||||
canvas.addMarker(nn.id, targetTask.completed ? 'highlight' : 'highlight-todo');
|
||||
}
|
||||
});
|
||||
} else if (n.$type === 'bpmn:SubProcess') {
|
||||
const completeTask = taskList.value.find((m) => m.key === n.id);
|
||||
if (completeTask) {
|
||||
canvas.addMarker(n.id, completeTask.completed ? 'highlight' : 'highlight-todo');
|
||||
}
|
||||
bpmnNodeList(n.flowElements, canvas);
|
||||
} else if (n.$type === 'bpmn:StartEvent') {
|
||||
canvas.addMarker(n.id, 'startEvent');
|
||||
if (n.outgoing) {
|
||||
n.outgoing.forEach((nn) => {
|
||||
const completeTask = taskList.value.find((m) => m.key === nn.targetRef.id);
|
||||
if (completeTask) {
|
||||
canvas.addMarker(nn.id, 'highlight');
|
||||
canvas.addMarker(n.id, 'highlight');
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (n.$type === 'bpmn:EndEvent') {
|
||||
canvas.addMarker(n.id, 'endEvent');
|
||||
const completeTask = taskList.value.find((m) => m.key === n.id);
|
||||
if (completeTask) {
|
||||
canvas.addMarker(completeTask.key, 'highlight');
|
||||
canvas.addMarker(n.id, 'highlight');
|
||||
return;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
const gateway = (id, targetRefType, targetRefId, canvas, completed) => {
|
||||
if (targetRefType === 'bpmn:ExclusiveGateway') {
|
||||
canvas.addMarker(id, completed ? 'highlight' : 'highlight-todo');
|
||||
canvas.addMarker(targetRefId, completed ? 'highlight' : 'highlight-todo');
|
||||
}
|
||||
if (targetRefType === 'bpmn:ParallelGateway') {
|
||||
canvas.addMarker(id, completed ? 'highlight' : 'highlight-todo');
|
||||
canvas.addMarker(targetRefId, completed ? 'highlight' : 'highlight-todo');
|
||||
}
|
||||
if (targetRefType === 'bpmn:InclusiveGateway') {
|
||||
canvas.addMarker(id, completed ? 'highlight' : 'highlight-todo');
|
||||
canvas.addMarker(targetRefId, completed ? 'highlight' : 'highlight-todo');
|
||||
}
|
||||
};
|
||||
defineExpose({
|
||||
init,
|
||||
initXml
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.header-div {
|
||||
display: flex;
|
||||
padding: 10px 0;
|
||||
justify-content: space-between;
|
||||
|
||||
.tips-label {
|
||||
display: flex;
|
||||
div {
|
||||
margin-right: 10px;
|
||||
padding: 5px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.un-complete {
|
||||
border: 1px solid #000;
|
||||
}
|
||||
.in-progress {
|
||||
background-color: rgb(255, 237, 204);
|
||||
border: 1px dashed orange;
|
||||
}
|
||||
.complete {
|
||||
background-color: rgb(204, 230, 204);
|
||||
border: 1px solid green;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.view-mode {
|
||||
.el-header,
|
||||
.el-aside,
|
||||
.djs-palette,
|
||||
.bjs-powered-by {
|
||||
display: none;
|
||||
}
|
||||
.el-loading-mask {
|
||||
background-color: initial;
|
||||
}
|
||||
.el-loading-spinner {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.bpmn-el-container {
|
||||
height: calc(100vh - 350px);
|
||||
}
|
||||
.flow-containers {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
.canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.load {
|
||||
margin-right: 10px;
|
||||
}
|
||||
:deep(.el-form-item__label) {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
:deep(.djs-palette) {
|
||||
left: 0 !important;
|
||||
top: 0;
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
:deep(.djs-container svg) {
|
||||
min-height: 650px;
|
||||
}
|
||||
|
||||
:deep(.startEvent.djs-shape .djs-visual > :nth-child(1)) {
|
||||
fill: #77df6d !important;
|
||||
}
|
||||
:deep(.endEvent.djs-shape .djs-visual > :nth-child(1)) {
|
||||
fill: #ee7b77 !important;
|
||||
}
|
||||
:deep(.highlight.djs-shape .djs-visual > :nth-child(1)) {
|
||||
fill: green !important;
|
||||
stroke: green !important;
|
||||
fill-opacity: 0.2 !important;
|
||||
}
|
||||
:deep(.highlight.djs-shape .djs-visual > :nth-child(2)) {
|
||||
fill: green !important;
|
||||
}
|
||||
:deep(.highlight.djs-shape .djs-visual > path) {
|
||||
fill: green !important;
|
||||
fill-opacity: 0.2 !important;
|
||||
stroke: green !important;
|
||||
}
|
||||
:deep(.highlight.djs-connection > .djs-visual > path) {
|
||||
stroke: green !important;
|
||||
}
|
||||
|
||||
// 边框滚动动画
|
||||
@keyframes path-animation {
|
||||
from {
|
||||
stroke-dashoffset: 100%;
|
||||
}
|
||||
|
||||
to {
|
||||
stroke-dashoffset: 0%;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.highlight-todo.djs-connection > .djs-visual > path) {
|
||||
animation: path-animation 60s;
|
||||
animation-timing-function: linear;
|
||||
animation-iteration-count: infinite;
|
||||
stroke-dasharray: 4px !important;
|
||||
stroke: orange !important;
|
||||
fill-opacity: 0.2 !important;
|
||||
marker-end: url('#sequenceflow-end-_E7DFDF-_E7DFDF-803g1kf6zwzmcig1y2ulm5egr');
|
||||
}
|
||||
|
||||
:deep(.highlight-todo.djs-shape .djs-visual > :nth-child(1)) {
|
||||
animation: path-animation 60s;
|
||||
animation-timing-function: linear;
|
||||
animation-iteration-count: infinite;
|
||||
stroke-dasharray: 4px !important;
|
||||
stroke: orange !important;
|
||||
fill: orange !important;
|
||||
fill-opacity: 0.2 !important;
|
||||
}
|
||||
}
|
||||
:deep(.verlays) {
|
||||
width: 250px;
|
||||
background: rgb(102, 102, 102);
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ebeef5;
|
||||
color: #fff;
|
||||
padding: 15px 10px;
|
||||
p {
|
||||
line-height: 28px;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
cursor: pointer;
|
||||
}
|
||||
</style>
|
@ -2,39 +2,49 @@
|
||||
<div class="container">
|
||||
<el-dialog v-model="visible" draggable title="审批记录" :width="props.width" :height="props.height" :close-on-click-modal="false">
|
||||
<el-tabs v-model="tabActiveName" class="demo-tabs">
|
||||
<el-tab-pane label="流程图" name="bpmn">
|
||||
<BpmnView ref="bpmnViewRef"></BpmnView>
|
||||
<el-tab-pane v-loading="loading" label="流程图" name="bpmn">
|
||||
<img :src="imgUrl" width="100%" style="margin: 0 auto" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane v-loading="loading" label="审批信息" name="info">
|
||||
<div>
|
||||
<el-table :data="historyList" style="width: 100%" border fit>
|
||||
<el-table-column type="index" label="序号" align="center" width="60"></el-table-column>
|
||||
<el-table-column prop="name" label="任务名称" sortable align="center"></el-table-column>
|
||||
<el-table-column prop="nickName" :show-overflow-tooltip="true" label="办理人" sortable align="center">
|
||||
<el-table-column prop="nodeName" label="任务名称" sortable align="center"></el-table-column>
|
||||
<el-table-column prop="approveName" :show-overflow-tooltip="true" label="办理人" sortable align="center">
|
||||
<template #default="scope">
|
||||
<el-tag type="success">{{ scope.row.nickName || '无' }}</el-tag>
|
||||
<template v-if="scope.row.approveName">
|
||||
<el-tag v-for="(item, index) in scope.row.approveName.split(',')" :key="index" type="success">{{ item }}</el-tag>
|
||||
</template>
|
||||
<template v-else> <el-tag type="success">无</el-tag></template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" sortable align="center">
|
||||
<el-table-column prop="flowStatus" label="状态" width="80" sortable align="center">
|
||||
<template #default="scope">
|
||||
<el-tag type="success">{{ scope.row.statusName }}</el-tag>
|
||||
<dict-tag :options="wf_task_status" :value="scope.row.flowStatus"></dict-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="comment" label="审批意见" sortable align="center"></el-table-column>
|
||||
<el-table-column prop="startTime" label="开始时间" sortable align="center"></el-table-column>
|
||||
<el-table-column prop="endTime" label="结束时间" sortable align="center"></el-table-column>
|
||||
<el-table-column prop="runDuration" label="运行时长" sortable align="center"></el-table-column>
|
||||
<el-table-column prop="attachmentList" label="附件" sortable align="center">
|
||||
<el-table-column prop="message" label="审批意见" :show-overflow-tooltip="true" sortable align="center"></el-table-column>
|
||||
<el-table-column prop="createTime" label="开始时间" width="160" :show-overflow-tooltip="true" sortable align="center"></el-table-column>
|
||||
<el-table-column prop="updateTime" label="结束时间" width="160" :show-overflow-tooltip="true" sortable align="center"></el-table-column>
|
||||
<el-table-column
|
||||
prop="runDuration"
|
||||
label="运行时常"
|
||||
width="140"
|
||||
:show-overflow-tooltip="true"
|
||||
sortable
|
||||
align="center"
|
||||
></el-table-column>
|
||||
<el-table-column prop="attachmentList" width="120" label="附件" align="center">
|
||||
<template #default="scope">
|
||||
<el-popover v-if="scope.row.attachmentList && scope.row.attachmentList.length > 0" placement="right" :width="310" trigger="click">
|
||||
<template #reference>
|
||||
<el-button style="margin-right: 16px">附件</el-button>
|
||||
<el-button type="primary" style="margin-right: 16px">附件</el-button>
|
||||
</template>
|
||||
<el-table border :data="scope.row.attachmentList">
|
||||
<el-table-column prop="name" width="202" :show-overflow-tooltip="true" label="附件名称"></el-table-column>
|
||||
<el-table-column prop="originalName" width="202" :show-overflow-tooltip="true" label="附件名称"></el-table-column>
|
||||
<el-table-column prop="name" width="80" align="center" :show-overflow-tooltip="true" label="操作">
|
||||
<template #default="tool">
|
||||
<el-button type="text" @click="handleDownload(tool.row.contentId)">下载</el-button>
|
||||
<el-button type="text" @click="handleDownload(tool.row.ossId)">下载</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -49,37 +59,51 @@
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import BpmnView from '@/components/BpmnView/index.vue';
|
||||
import processApi from '@/api/workflow/processInstance';
|
||||
import { flowImage } from '@/api/workflow/instance';
|
||||
import { propTypes } from '@/utils/propTypes';
|
||||
import { listByIds } from '@/api/system/oss';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
const { wf_task_status } = toRefs<any>(proxy?.useDict('wf_task_status'));
|
||||
const props = defineProps({
|
||||
width: propTypes.string.def('70%'),
|
||||
width: propTypes.string.def('80%'),
|
||||
height: propTypes.string.def('100%')
|
||||
});
|
||||
const loading = ref(false);
|
||||
const visible = ref(false);
|
||||
const historyList = ref<Array<any>>([]);
|
||||
const tabActiveName = ref('bpmn');
|
||||
|
||||
const bpmnViewRef = ref<BpmnView>();
|
||||
const imgUrl = ref('');
|
||||
|
||||
//初始化查询审批记录
|
||||
const init = async (businessKey: string | number) => {
|
||||
const init = async (businessId: string | number) => {
|
||||
visible.value = true;
|
||||
loading.value = true;
|
||||
tabActiveName.value = 'bpmn';
|
||||
historyList.value = [];
|
||||
processApi.getHistoryRecord(businessKey).then((resp) => {
|
||||
historyList.value = resp.data;
|
||||
loading.value = false;
|
||||
});
|
||||
await nextTick(() => {
|
||||
bpmnViewRef.value.init(businessKey);
|
||||
flowImage(businessId).then((resp) => {
|
||||
if (resp.data) {
|
||||
historyList.value = resp.data.list;
|
||||
imgUrl.value = 'data:image/gif;base64,' + resp.data.image;
|
||||
if (historyList.value.length > 0) {
|
||||
historyList.value.forEach((item) => {
|
||||
if (item.ext) {
|
||||
getIds(item.ext).then((res) => {
|
||||
item.attachmentList = res.data;
|
||||
});
|
||||
} else {
|
||||
item.attachmentList = [];
|
||||
}
|
||||
});
|
||||
}
|
||||
loading.value = false;
|
||||
}
|
||||
});
|
||||
};
|
||||
const getIds = async (ids: string | number) => {
|
||||
const res = await listByIds(ids);
|
||||
return res;
|
||||
};
|
||||
|
||||
/** 下载按钮操作 */
|
||||
const handleDownload = (ossId: string) => {
|
||||
|
@ -1,378 +0,0 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" draggable :title="title" :width="width" :height="height" append-to-body :close-on-click-modal="false">
|
||||
<div v-if="multiInstance === 'add'" class="p-2">
|
||||
<el-row :gutter="20">
|
||||
<!-- 部门树 -->
|
||||
<el-col :lg="4" :xs="24" style="">
|
||||
<el-card shadow="hover">
|
||||
<el-input v-model="deptName" placeholder="请输入部门名称" prefix-icon="Search" clearable />
|
||||
<el-tree
|
||||
ref="deptTreeRef"
|
||||
class="mt-2"
|
||||
node-key="id"
|
||||
:data="deptOptions"
|
||||
:props="{ label: 'label', children: 'children' }"
|
||||
:expand-on-click-node="false"
|
||||
:filter-node-method="filterNode"
|
||||
highlight-current
|
||||
default-expand-all
|
||||
@node-click="handleNodeClick"
|
||||
></el-tree>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-col :lg="20" :xs="24">
|
||||
<transition :enter-active-class="proxy?.animate.searchAnimate.enter" :leave-active-class="proxy?.animate.searchAnimate.leave">
|
||||
<div v-show="showSearch" class="search">
|
||||
<el-form ref="queryFormRef" :model="queryParams" :inline="true">
|
||||
<el-form-item label="用户名称" prop="userName">
|
||||
<el-input v-model="queryParams.userName" placeholder="请输入用户名称" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item label="手机号码" prop="phonenumber">
|
||||
<el-input v-model="queryParams.phonenumber" placeholder="请输入手机号码" clearable @keyup.enter="handleQuery" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
</transition>
|
||||
|
||||
<el-card shadow="hover">
|
||||
<template #header>
|
||||
<el-row :gutter="10">
|
||||
<right-toolbar v-model:show-search="showSearch" :search="true" @query-table="handleQuery"></right-toolbar>
|
||||
</el-row>
|
||||
</template>
|
||||
|
||||
<el-table ref="multipleTableRef" v-loading="loading" :data="userList" row-key="userId" @selection-change="handleSelectionChange">
|
||||
<el-table-column type="selection" width="50" align="center" />
|
||||
<el-table-column key="userId" label="用户编号" align="center" prop="userId" />
|
||||
<el-table-column key="userName" label="用户名称" align="center" prop="userName" :show-overflow-tooltip="true" />
|
||||
<el-table-column key="nickName" label="用户昵称" align="center" prop="nickName" :show-overflow-tooltip="true" />
|
||||
<el-table-column key="phonenumber" label="手机号码" align="center" prop="phonenumber" width="120" />
|
||||
<el-table-column label="创建时间" align="center" prop="createTime" width="160">
|
||||
<template #default="scope">
|
||||
<span>{{ scope.row.createTime }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<pagination
|
||||
v-show="total > 0"
|
||||
v-model:page="queryParams.pageNum"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
:total="total"
|
||||
@pagination="handleQuery"
|
||||
/>
|
||||
</el-card>
|
||||
<el-card shadow="hover">
|
||||
<el-tag v-for="(user, index) in chooseUserList" :key="user.userId" style="margin: 2px" closable @close="handleCloseTag(user, index)"
|
||||
>{{ user.userName }}
|
||||
</el-tag>
|
||||
</el-card>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</div>
|
||||
<div v-if="multiInstance === 'delete'" class="p-2">
|
||||
<el-table v-loading="loading" :data="taskList" @selection-change="handleTaskSelection">
|
||||
<el-table-column type="selection" width="55" />
|
||||
<el-table-column prop="name" label="任务名称" />
|
||||
<el-table-column prop="assigneeName" label="办理人" />
|
||||
</el-table>
|
||||
</div>
|
||||
<template #footer>
|
||||
<div class="dialog-footer">
|
||||
<el-button type="primary" @click="submitFileForm">确 定</el-button>
|
||||
<el-button @click="visible = false">取 消</el-button>
|
||||
</div>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script setup name="User" lang="ts">
|
||||
import { deptTreeSelect, listUser, optionSelect } from '@/api/system/user';
|
||||
import {
|
||||
addMultiInstanceExecution,
|
||||
deleteMultiInstanceExecution,
|
||||
getTaskUserIdsByAddMultiInstance,
|
||||
getListByDeleteMultiInstance
|
||||
} from '@/api/workflow/task';
|
||||
import { UserVO } from '@/api/system/user/types';
|
||||
import { DeptVO } from '@/api/system/dept/types';
|
||||
import { ComponentInternalInstance } from 'vue';
|
||||
import { ElTree, ElTable } from 'element-plus';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
|
||||
const props = defineProps({
|
||||
// 宽
|
||||
width: {
|
||||
type: String,
|
||||
default: '70%'
|
||||
},
|
||||
// 高
|
||||
height: {
|
||||
type: String,
|
||||
default: '100%'
|
||||
},
|
||||
// 标题
|
||||
title: {
|
||||
type: String,
|
||||
default: '加签人员'
|
||||
},
|
||||
//是否多选
|
||||
multiple: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
//回显用户id
|
||||
userIdList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
}
|
||||
});
|
||||
const deptTreeRef = ref(ElTree);
|
||||
const multipleTableRef = ref(ElTable);
|
||||
|
||||
const userList = ref<UserVO[]>();
|
||||
const taskList = ref<Array<any>[]>();
|
||||
const loading = ref(true);
|
||||
const showSearch = ref(true);
|
||||
const selectionTask = ref<Array<any>[]>();
|
||||
const visible = ref(false);
|
||||
const total = ref(0);
|
||||
const deptName = ref('');
|
||||
const deptOptions = ref<DeptVO[]>([]);
|
||||
const chooseUserList = ref(ref<UserVO[]>());
|
||||
const userIds = ref<Array<number | string>>([]);
|
||||
//加签或者减签
|
||||
const multiInstance = ref('');
|
||||
const queryParams = ref<Record<string, any>>({
|
||||
pageNum: 1,
|
||||
pageSize: 10,
|
||||
userName: '',
|
||||
nickName: '',
|
||||
taskId: ''
|
||||
});
|
||||
/** 查询用户列表 */
|
||||
const getAddMultiInstanceList = async (taskId: string, userIdList: Array<number | string>) => {
|
||||
deptOptions.value = [];
|
||||
getTreeSelect();
|
||||
multiInstance.value = 'add';
|
||||
userIds.value = userIdList;
|
||||
visible.value = true;
|
||||
queryParams.value.taskId = taskId;
|
||||
loading.value = true;
|
||||
const res1 = await getTaskUserIdsByAddMultiInstance(taskId);
|
||||
queryParams.value.excludeUserIds = res1.data;
|
||||
const res = await listUser(queryParams.value);
|
||||
loading.value = false;
|
||||
userList.value = res.rows;
|
||||
total.value = res.total;
|
||||
if (userList.value && userIds.value.length > 0) {
|
||||
const data = await optionSelect(userIds.value);
|
||||
if (data.data && data.data.length > 0) {
|
||||
chooseUserList.value = data.data;
|
||||
data.data.forEach((user: UserVO) => {
|
||||
multipleTableRef.value!.toggleRowSelection(
|
||||
userList.value.find((item) => {
|
||||
return item.userId == user.userId;
|
||||
}),
|
||||
true
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getList = async () => {
|
||||
loading.value = true;
|
||||
const res1 = await getTaskUserIdsByAddMultiInstance(queryParams.value.taskId);
|
||||
queryParams.value.excludeUserIds = res1.data;
|
||||
const res = await listUser(queryParams.value);
|
||||
loading.value = false;
|
||||
userList.value = res.rows;
|
||||
total.value = res.total;
|
||||
if (userList.value && userIds.value.length > 0) {
|
||||
const data = await optionSelect(userIds.value);
|
||||
if (data.data && data.data.length > 0) {
|
||||
chooseUserList.value = data.data;
|
||||
data.data.forEach((user: UserVO) => {
|
||||
multipleTableRef.value!.toggleRowSelection(
|
||||
userList.value.find((item) => {
|
||||
return item.userId == user.userId;
|
||||
}),
|
||||
true
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getDeleteMultiInstanceList = async (taskId: string) => {
|
||||
deptOptions.value = [];
|
||||
loading.value = true;
|
||||
queryParams.value.taskId = taskId;
|
||||
multiInstance.value = 'delete';
|
||||
visible.value = true;
|
||||
const res = await getListByDeleteMultiInstance(taskId);
|
||||
taskList.value = res.data;
|
||||
loading.value = false;
|
||||
};
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.value.pageNum = 1;
|
||||
getAddMultiInstanceList(queryParams.value.taskId, userIds.value);
|
||||
};
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
queryParams.value.pageNum = 1;
|
||||
queryParams.value.deptId = undefined;
|
||||
queryParams.value.userName = undefined;
|
||||
queryParams.value.nickName = undefined;
|
||||
deptTreeRef.value.setCurrentKey(null);
|
||||
handleQuery();
|
||||
};
|
||||
|
||||
/** 选择条数 */
|
||||
const handleSelectionChange = (selection: UserVO[]) => {
|
||||
if (props.multiple) {
|
||||
chooseUserList.value = selection.filter((element, index, self) => {
|
||||
return self.findIndex((x) => x.userId === element.userId) === index;
|
||||
});
|
||||
selection.forEach((u) => {
|
||||
if (chooseUserList.value && !chooseUserList.value.includes(u)) {
|
||||
multipleTableRef.value!.toggleRowSelection(u, undefined);
|
||||
}
|
||||
});
|
||||
userIds.value = chooseUserList.value.map((item) => {
|
||||
return item.userId;
|
||||
});
|
||||
} else {
|
||||
chooseUserList.value = selection;
|
||||
if (selection.length > 1) {
|
||||
let delRow = selection.shift();
|
||||
multipleTableRef.value!.toggleRowSelection(delRow, undefined);
|
||||
}
|
||||
if (selection.length === 0) {
|
||||
chooseUserList.value = [];
|
||||
}
|
||||
}
|
||||
};
|
||||
/** 选择条数 */
|
||||
const handleTaskSelection = (selection: any) => {
|
||||
selectionTask.value = selection;
|
||||
};
|
||||
|
||||
/** 查询部门下拉树结构 */
|
||||
const getTreeSelect = async () => {
|
||||
const res = await deptTreeSelect();
|
||||
deptOptions.value = res.data;
|
||||
};
|
||||
|
||||
/** 通过条件过滤节点 */
|
||||
const filterNode = (value: string, data: any) => {
|
||||
if (!value) return true;
|
||||
return data.label.indexOf(value) !== -1;
|
||||
};
|
||||
/** 根据名称筛选部门树 */
|
||||
watchEffect(
|
||||
() => {
|
||||
if (visible.value && deptOptions.value && deptOptions.value.length > 0) {
|
||||
deptTreeRef.value.filter(deptName.value);
|
||||
}
|
||||
},
|
||||
{
|
||||
flush: 'post' // watchEffect会在DOM挂载或者更新之前就会触发,此属性控制在DOM元素更新后运行
|
||||
}
|
||||
);
|
||||
/** 节点单击事件 */
|
||||
const handleNodeClick = (data: DeptVO) => {
|
||||
queryParams.value.deptId = data.id;
|
||||
getList();
|
||||
};
|
||||
//删除tag
|
||||
const handleCloseTag = (user: UserVO, index: any) => {
|
||||
if (multipleTableRef.value.selection && multipleTableRef.value.selection.length > 0) {
|
||||
multipleTableRef.value.selection.forEach((u: UserVO, i: number) => {
|
||||
if (user.userId === u.userId) {
|
||||
multipleTableRef.value.selection.splice(i, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (chooseUserList.value && chooseUserList.value.length > 0) {
|
||||
chooseUserList.value.splice(index, 1);
|
||||
}
|
||||
multipleTableRef.value.toggleRowSelection(user, undefined);
|
||||
|
||||
if (userIds.value && userIds.value.length > 0) {
|
||||
userIds.value.forEach((userId, i) => {
|
||||
if (userId === user.userId) {
|
||||
userIds.value.splice(i, 1);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
const submitFileForm = async () => {
|
||||
if (multiInstance.value === 'add') {
|
||||
if (chooseUserList.value && chooseUserList.value.length > 0) {
|
||||
loading.value = true;
|
||||
let userIds = chooseUserList.value.map((item) => {
|
||||
return item.userId;
|
||||
});
|
||||
let nickNames = chooseUserList.value.map((item) => {
|
||||
return item.nickName;
|
||||
});
|
||||
let params = {
|
||||
taskId: queryParams.value.taskId,
|
||||
assignees: userIds,
|
||||
assigneeNames: nickNames
|
||||
};
|
||||
await addMultiInstanceExecution(params);
|
||||
emits('submitCallback');
|
||||
loading.value = false;
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
visible.value = false;
|
||||
}
|
||||
} else {
|
||||
if (selectionTask.value && selectionTask.value.length > 0) {
|
||||
loading.value = true;
|
||||
let taskIds = selectionTask.value.map((item: any) => {
|
||||
return item.id;
|
||||
});
|
||||
let executionIds = selectionTask.value.map((item: any) => {
|
||||
return item.executionId;
|
||||
});
|
||||
let assigneeIds = selectionTask.value.map((item: any) => {
|
||||
return item.assignee;
|
||||
});
|
||||
let assigneeNames = selectionTask.value.map((item: any) => {
|
||||
return item.assigneeName;
|
||||
});
|
||||
let params = {
|
||||
taskId: queryParams.value.taskId,
|
||||
taskIds: taskIds,
|
||||
executionIds: executionIds,
|
||||
assigneeIds: assigneeIds,
|
||||
assigneeNames: assigneeNames
|
||||
};
|
||||
await deleteMultiInstanceExecution(params);
|
||||
emits('submitCallback');
|
||||
loading.value = false;
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
visible.value = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
//事件
|
||||
const emits = defineEmits(['submitCallback']);
|
||||
|
||||
/**
|
||||
* 对外暴露子组件方法
|
||||
*/
|
||||
defineExpose({
|
||||
getAddMultiInstanceList,
|
||||
getDeleteMultiInstanceList
|
||||
});
|
||||
</script>
|
207
src/components/Process/processMeddle.vue
Normal file
207
src/components/Process/processMeddle.vue
Normal file
@ -0,0 +1,207 @@
|
||||
<template>
|
||||
<el-dialog v-model="visible" draggable title="流程干预" :width="props.width" :height="props.height" :close-on-click-modal="false">
|
||||
<el-descriptions v-loading="loading" class="margin-top" :title="`${task.flowName}(${task.flowCode})`" :column="2" border>
|
||||
<el-descriptions-item label="任务名称">{{ task.nodeName }}</el-descriptions-item>
|
||||
<el-descriptions-item label="节点编码">{{ task.nodeCode }}</el-descriptions-item>
|
||||
<el-descriptions-item label="开始时间">{{ task.createTime }}</el-descriptions-item>
|
||||
<el-descriptions-item label="流程实例ID">{{ task.instanceId }}</el-descriptions-item>
|
||||
<el-descriptions-item label="版本号">{{ task.version }}.0</el-descriptions-item>
|
||||
<el-descriptions-item label="业务ID">{{ task.businessId }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openTransferTask"> 转办 </el-button>
|
||||
<el-button
|
||||
v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0"
|
||||
:disabled="buttonDisabled"
|
||||
type="primary"
|
||||
@click="openMultiInstanceUser"
|
||||
>
|
||||
加签
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0"
|
||||
:disabled="buttonDisabled"
|
||||
type="primary"
|
||||
@click="handleTaskUser"
|
||||
>
|
||||
减签
|
||||
</el-button>
|
||||
<el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleTerminationTask"> 终止 </el-button>
|
||||
</span>
|
||||
</template>
|
||||
<!-- 转办 -->
|
||||
<UserSelect ref="transferTaskRef" :multiple="false" @confirm-call-back="handleTransferTask"></UserSelect>
|
||||
<!-- 加签组件 -->
|
||||
<UserSelect ref="multiInstanceUserRef" :multiple="true" @confirm-call-back="addMultiInstanceUser"></UserSelect>
|
||||
<el-dialog v-model="deleteSignatureVisible" draggable title="减签人员" width="700px" height="400px" append-to-body :close-on-click-modal="false"
|
||||
><div>
|
||||
<el-table :data="deleteUserList" border>
|
||||
<el-table-column prop="nodeName" label="任务名称" />
|
||||
<el-table-column prop="nickName" label="办理人" />
|
||||
<el-table-column label="操作" align="center" width="160">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" size="small" icon="Delete" @click="deleteMultiInstanceUser(scope.row)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { propTypes } from '@/utils/propTypes';
|
||||
import { FlowTaskVO, TaskOperationBo } from '@/api/workflow/task/types';
|
||||
import UserSelect from '@/components/UserSelect';
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
import { getTask, taskOperation, currentTaskAllUser, terminationTask } from '@/api/workflow/task';
|
||||
const props = defineProps({
|
||||
width: propTypes.string.def('50%'),
|
||||
height: propTypes.string.def('100%')
|
||||
});
|
||||
const emits = defineEmits(['submitCallback']);
|
||||
const transferTaskRef = ref<InstanceType<typeof UserSelect>>();
|
||||
const multiInstanceUserRef = ref<InstanceType<typeof UserSelect>>();
|
||||
//遮罩层
|
||||
const loading = ref(true);
|
||||
//按钮
|
||||
const buttonDisabled = ref(true);
|
||||
const visible = ref(false);
|
||||
//减签弹窗
|
||||
const deleteSignatureVisible = ref(false);
|
||||
//可减签的人员
|
||||
const deleteUserList = ref<any>([]);
|
||||
//任务
|
||||
const task = ref<FlowTaskVO>({
|
||||
id: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined,
|
||||
tenantId: undefined,
|
||||
definitionId: undefined,
|
||||
instanceId: undefined,
|
||||
flowName: undefined,
|
||||
businessId: undefined,
|
||||
nodeCode: undefined,
|
||||
nodeName: undefined,
|
||||
flowCode: undefined,
|
||||
flowStatus: undefined,
|
||||
nodeType: undefined,
|
||||
nodeRatio: undefined,
|
||||
version: undefined
|
||||
});
|
||||
|
||||
const open = (taskId: string) => {
|
||||
visible.value = true;
|
||||
getTask(taskId).then((response) => {
|
||||
loading.value = false;
|
||||
buttonDisabled.value = false;
|
||||
task.value = response.data;
|
||||
});
|
||||
};
|
||||
|
||||
//打开转办
|
||||
const openTransferTask = () => {
|
||||
transferTaskRef.value.open();
|
||||
};
|
||||
//转办
|
||||
const handleTransferTask = async (data) => {
|
||||
if (data && data.length > 0) {
|
||||
const taskOperationBo = reactive<TaskOperationBo>({
|
||||
userId: data[0].userId,
|
||||
taskId: task.value.id,
|
||||
message: ''
|
||||
});
|
||||
await proxy?.$modal.confirm('是否确认提交?');
|
||||
loading.value = true;
|
||||
buttonDisabled.value = true;
|
||||
await taskOperation(taskOperationBo, 'transferTask').finally(() => {
|
||||
loading.value = false;
|
||||
buttonDisabled.value = false;
|
||||
});
|
||||
visible.value = false;
|
||||
emits('submitCallback');
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
} else {
|
||||
proxy?.$modal.msgWarning('请选择用户!');
|
||||
}
|
||||
};
|
||||
//加签
|
||||
const openMultiInstanceUser = async () => {
|
||||
multiInstanceUserRef.value.open();
|
||||
};
|
||||
//加签
|
||||
const addMultiInstanceUser = async (data) => {
|
||||
if (data && data.length > 0) {
|
||||
const taskOperationBo = reactive<TaskOperationBo>({
|
||||
userIds: data.map((e) => e.userId),
|
||||
taskId: task.value.id,
|
||||
message: ''
|
||||
});
|
||||
await proxy?.$modal.confirm('是否确认提交?');
|
||||
loading.value = true;
|
||||
buttonDisabled.value = true;
|
||||
await taskOperation(taskOperationBo, 'addSignature').finally(() => {
|
||||
loading.value = false;
|
||||
buttonDisabled.value = false;
|
||||
});
|
||||
visible.value = false;
|
||||
emits('submitCallback');
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
} else {
|
||||
proxy?.$modal.msgWarning('请选择用户!');
|
||||
}
|
||||
};
|
||||
//减签
|
||||
const deleteMultiInstanceUser = async (row) => {
|
||||
await proxy?.$modal.confirm('是否确认提交?');
|
||||
loading.value = true;
|
||||
buttonDisabled.value = true;
|
||||
const taskOperationBo = reactive<TaskOperationBo>({
|
||||
userIds: [row.userId],
|
||||
taskId: task.value.id,
|
||||
message: ''
|
||||
});
|
||||
await taskOperation(taskOperationBo, 'reductionSignature').finally(() => {
|
||||
loading.value = false;
|
||||
buttonDisabled.value = false;
|
||||
});
|
||||
visible.value = false;
|
||||
emits('submitCallback');
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
};
|
||||
//获取办理人
|
||||
const handleTaskUser = async () => {
|
||||
let data = await currentTaskAllUser(task.value.id);
|
||||
deleteUserList.value = data.data;
|
||||
if (deleteUserList.value && deleteUserList.value.length > 0) {
|
||||
deleteUserList.value.forEach((e) => {
|
||||
e.nodeName = task.value.nodeName;
|
||||
});
|
||||
}
|
||||
deleteSignatureVisible.value = true;
|
||||
};
|
||||
|
||||
//终止任务
|
||||
const handleTerminationTask = async () => {
|
||||
let params = {
|
||||
taskId: task.value.id,
|
||||
comment: ''
|
||||
};
|
||||
await proxy?.$modal.confirm('是否确认终止?');
|
||||
loading.value = true;
|
||||
buttonDisabled.value = true;
|
||||
await terminationTask(params).finally(() => {
|
||||
loading.value = false;
|
||||
buttonDisabled.value = false;
|
||||
});
|
||||
visible.value = false;
|
||||
emits('submitCallback');
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
};
|
||||
/**
|
||||
* 对外暴露子组件方法
|
||||
*/
|
||||
defineExpose({
|
||||
open
|
||||
});
|
||||
</script>
|
@ -3,47 +3,47 @@
|
||||
<el-form v-loading="loading" :model="form" label-width="120px">
|
||||
<el-form-item label="消息提醒">
|
||||
<el-checkbox-group v-model="form.messageType">
|
||||
<el-checkbox label="1" name="type" disabled>站内信</el-checkbox>
|
||||
<el-checkbox label="2" name="type">邮件</el-checkbox>
|
||||
<el-checkbox label="3" name="type">短信</el-checkbox>
|
||||
<el-checkbox value="1" name="type" disabled>站内信</el-checkbox>
|
||||
<el-checkbox value="2" name="type">邮件</el-checkbox>
|
||||
<el-checkbox value="3" name="type">短信</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="task.businessStatus === 'waiting'" label="附件">
|
||||
<fileUpload v-model="form.fileId" :file-type="['doc', 'xls', 'ppt', 'txt', 'pdf', 'xlsx', 'docx', 'zip']" :file-size="'20'" />
|
||||
<el-form-item v-if="task.flowStatus === 'waiting'" label="附件">
|
||||
<fileUpload v-model="form.fileId" :file-type="['png', 'jpg', 'jpeg', 'doc', 'docx', 'xlsx', 'xls', 'ppt', 'txt', 'pdf']" :file-size="20" />
|
||||
</el-form-item>
|
||||
<el-form-item label="抄送">
|
||||
<el-button type="primary" icon="Plus" circle @click="openUserSelectCopy" />
|
||||
<el-tag v-for="user in selectCopyUserList" :key="user.userId" closable style="margin: 2px" @close="handleCopyCloseTag(user)">
|
||||
{{ user.userName }}
|
||||
{{ user.nickName }}
|
||||
</el-tag>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="task.businessStatus === 'waiting'" label="审批意见">
|
||||
<el-form-item v-if="task.flowStatus === 'waiting'" label="审批意见">
|
||||
<el-input v-model="form.message" type="textarea" resize="none" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button :disabled="buttonDisabled" type="primary" @click="handleCompleteTask"> 提交 </el-button>
|
||||
<el-button v-if="task.businessStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openDelegateTask"> 委托 </el-button>
|
||||
<el-button v-if="task.businessStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openTransferTask"> 转办 </el-button>
|
||||
<el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openDelegateTask"> 委托 </el-button>
|
||||
<el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="primary" @click="openTransferTask"> 转办 </el-button>
|
||||
<el-button
|
||||
v-if="task.businessStatus === 'waiting' && task.multiInstance"
|
||||
v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0"
|
||||
:disabled="buttonDisabled"
|
||||
type="primary"
|
||||
@click="addMultiInstanceUser"
|
||||
@click="openMultiInstanceUser"
|
||||
>
|
||||
加签
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="task.businessStatus === 'waiting' && task.multiInstance"
|
||||
v-if="task.flowStatus === 'waiting' && Number(task.nodeRatio) > 0"
|
||||
:disabled="buttonDisabled"
|
||||
type="primary"
|
||||
@click="deleteMultiInstanceUser"
|
||||
@click="handleTaskUser"
|
||||
>
|
||||
减签
|
||||
</el-button>
|
||||
<el-button v-if="task.businessStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleTerminationTask"> 终止 </el-button>
|
||||
<el-button v-if="task.businessStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleBackProcessOpen"> 退回 </el-button>
|
||||
<el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleTerminationTask"> 终止 </el-button>
|
||||
<el-button v-if="task.flowStatus === 'waiting'" :disabled="buttonDisabled" type="danger" @click="handleBackProcessOpen"> 退回 </el-button>
|
||||
<el-button :disabled="buttonDisabled" @click="cancel">取消</el-button>
|
||||
</span>
|
||||
</template>
|
||||
@ -54,14 +54,14 @@
|
||||
<!-- 委托 -->
|
||||
<UserSelect ref="delegateTaskRef" :multiple="false" @confirm-call-back="handleDelegateTask"></UserSelect>
|
||||
<!-- 加签组件 -->
|
||||
<multiInstanceUser ref="multiInstanceUserRef" :title="title" @submit-callback="closeDialog" />
|
||||
<UserSelect ref="multiInstanceUserRef" :multiple="true" @confirm-call-back="addMultiInstanceUser"></UserSelect>
|
||||
|
||||
<!-- 驳回开始 -->
|
||||
<el-dialog v-model="backVisible" draggable title="驳回" width="40%" :close-on-click-modal="false">
|
||||
<el-form v-if="task.businessStatus === 'waiting'" v-loading="backLoading" :model="backForm" label-width="120px">
|
||||
<el-form v-if="task.flowStatus === 'waiting'" v-loading="backLoading" :model="backForm" label-width="120px">
|
||||
<el-form-item label="驳回节点">
|
||||
<el-select v-model="backForm.targetActivityId" clearable placeholder="请选择" style="width: 300px">
|
||||
<el-option v-for="item in taskNodeList" :key="item.nodeId" :label="item.nodeName" :value="item.nodeId" />
|
||||
<el-select v-model="backForm.nodeCode" clearable placeholder="请选择" style="width: 300px">
|
||||
<el-option v-for="item in taskNodeList" :key="item.nodeCode" :label="item.nodeName" :value="item.nodeCode" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="消息提醒">
|
||||
@ -83,6 +83,19 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
<!-- 驳回结束 -->
|
||||
<el-dialog v-model="deleteSignatureVisible" draggable title="减签人员" width="700px" height="400px" append-to-body :close-on-click-modal="false">
|
||||
<div>
|
||||
<el-table :data="deleteUserList" border>
|
||||
<el-table-column prop="nodeName" label="任务名称" />
|
||||
<el-table-column prop="nickName" label="办理人" />
|
||||
<el-table-column label="操作" align="center" width="160">
|
||||
<template #default="scope">
|
||||
<el-button type="danger" size="small" icon="Delete" @click="deleteMultiInstanceUser(scope.row)">删除 </el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
@ -90,18 +103,17 @@
|
||||
import { ref } from 'vue';
|
||||
import { ComponentInternalInstance } from 'vue';
|
||||
import { ElForm } from 'element-plus';
|
||||
import { completeTask, backProcess, getTaskById, transferTask, terminationTask, getTaskNodeList, delegateTask } from '@/api/workflow/task';
|
||||
import { completeTask, backProcess, getTask, taskOperation, terminationTask, getBackTaskNode, currentTaskAllUser } from '@/api/workflow/task';
|
||||
import UserSelect from '@/components/UserSelect';
|
||||
import MultiInstanceUser from '@/components/Process/multiInstanceUser.vue';
|
||||
|
||||
const { proxy } = getCurrentInstance() as ComponentInternalInstance;
|
||||
import { UserVO } from '@/api/system/user/types';
|
||||
import { TaskVO } from '@/api/workflow/task/types';
|
||||
import { FlowTaskVO, TaskOperationBo } from '@/api/workflow/task/types';
|
||||
|
||||
const userSelectCopyRef = ref<InstanceType<typeof UserSelect>>();
|
||||
const transferTaskRef = ref<InstanceType<typeof UserSelect>>();
|
||||
const delegateTaskRef = ref<InstanceType<typeof UserSelect>>();
|
||||
|
||||
//加签组件
|
||||
const multiInstanceUserRef = ref<InstanceType<typeof MultiInstanceUser>>();
|
||||
const multiInstanceUserRef = ref<InstanceType<typeof UserSelect>>();
|
||||
|
||||
const props = defineProps({
|
||||
taskVariables: {
|
||||
@ -119,65 +131,53 @@ const taskId = ref<string>('');
|
||||
const selectCopyUserList = ref<UserVO[]>([]);
|
||||
//抄送人id
|
||||
const selectCopyUserIds = ref<string>(undefined);
|
||||
// 驳回是否显示
|
||||
//可减签的人员
|
||||
const deleteUserList = ref<any>([]);
|
||||
//驳回是否显示
|
||||
const backVisible = ref(false);
|
||||
const backLoading = ref(true);
|
||||
const backButtonDisabled = ref(true);
|
||||
// 可驳回得任务节点
|
||||
const taskNodeList = ref([]);
|
||||
//任务
|
||||
const task = ref<TaskVO>({
|
||||
const task = ref<FlowTaskVO>({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
description: undefined,
|
||||
priority: undefined,
|
||||
owner: undefined,
|
||||
assignee: undefined,
|
||||
assigneeName: undefined,
|
||||
processInstanceId: undefined,
|
||||
executionId: undefined,
|
||||
taskDefinitionId: undefined,
|
||||
processDefinitionId: undefined,
|
||||
endTime: undefined,
|
||||
taskDefinitionKey: undefined,
|
||||
dueDate: undefined,
|
||||
category: undefined,
|
||||
parentTaskId: undefined,
|
||||
createTime: undefined,
|
||||
updateTime: undefined,
|
||||
tenantId: undefined,
|
||||
claimTime: undefined,
|
||||
businessStatus: undefined,
|
||||
businessStatusName: undefined,
|
||||
processDefinitionName: undefined,
|
||||
processDefinitionKey: undefined,
|
||||
participantVo: undefined,
|
||||
multiInstance: undefined,
|
||||
businessKey: undefined,
|
||||
wfNodeConfigVo: undefined
|
||||
definitionId: undefined,
|
||||
instanceId: undefined,
|
||||
flowName: undefined,
|
||||
businessId: undefined,
|
||||
nodeCode: undefined,
|
||||
nodeName: undefined,
|
||||
flowCode: undefined,
|
||||
flowStatus: undefined,
|
||||
formCustom: undefined,
|
||||
formPath: undefined,
|
||||
nodeType: undefined,
|
||||
nodeRatio: undefined
|
||||
});
|
||||
//加签 减签标题
|
||||
const title = ref('');
|
||||
const dialog = reactive<DialogOption>({
|
||||
visible: false,
|
||||
title: '提示'
|
||||
});
|
||||
|
||||
//减签弹窗
|
||||
const deleteSignatureVisible = ref(false);
|
||||
const form = ref<Record<string, any>>({
|
||||
taskId: undefined,
|
||||
message: undefined,
|
||||
variables: {},
|
||||
messageType: ['1'],
|
||||
wfCopyList: []
|
||||
flowCopyList: []
|
||||
});
|
||||
const backForm = ref<Record<string, any>>({
|
||||
taskId: undefined,
|
||||
targetActivityId: undefined,
|
||||
nodeCode: undefined,
|
||||
message: undefined,
|
||||
variables: {},
|
||||
messageType: ['1']
|
||||
});
|
||||
const closeDialog = () => {
|
||||
dialog.visible = false;
|
||||
};
|
||||
//打开弹窗
|
||||
const openDialog = (id?: string) => {
|
||||
selectCopyUserIds.value = undefined;
|
||||
@ -189,7 +189,7 @@ const openDialog = (id?: string) => {
|
||||
loading.value = true;
|
||||
buttonDisabled.value = true;
|
||||
nextTick(() => {
|
||||
getTaskById(taskId.value).then((response) => {
|
||||
getTask(taskId.value).then((response) => {
|
||||
task.value = response.data;
|
||||
loading.value = false;
|
||||
buttonDisabled.value = false;
|
||||
@ -205,15 +205,15 @@ const handleCompleteTask = async () => {
|
||||
form.value.taskId = taskId.value;
|
||||
form.value.taskVariables = props.taskVariables;
|
||||
if (selectCopyUserList.value && selectCopyUserList.value.length > 0) {
|
||||
let wfCopyList = [];
|
||||
let flowCopyList = [];
|
||||
selectCopyUserList.value.forEach((e) => {
|
||||
let copyUser = {
|
||||
userId: e.userId,
|
||||
userName: e.nickName
|
||||
};
|
||||
wfCopyList.push(copyUser);
|
||||
flowCopyList.push(copyUser);
|
||||
});
|
||||
form.value.wfCopyList = wfCopyList;
|
||||
form.value.flowCopyList = flowCopyList;
|
||||
}
|
||||
await proxy?.$modal.confirm('是否确认提交?');
|
||||
loading.value = true;
|
||||
@ -236,11 +236,11 @@ const handleBackProcessOpen = async () => {
|
||||
backVisible.value = true;
|
||||
backLoading.value = true;
|
||||
backButtonDisabled.value = true;
|
||||
let data = await getTaskNodeList(task.value.processInstanceId);
|
||||
let data = await getBackTaskNode(task.value.definitionId, task.value.nodeCode);
|
||||
taskNodeList.value = data.data;
|
||||
backLoading.value = false;
|
||||
backButtonDisabled.value = false;
|
||||
backForm.value.targetActivityId = taskNodeList.value[0].nodeId;
|
||||
backForm.value.nodeCode = taskNodeList.value[0].nodeCode;
|
||||
};
|
||||
/** 驳回流程 */
|
||||
const handleBackProcess = async () => {
|
||||
@ -249,7 +249,10 @@ const handleBackProcess = async () => {
|
||||
loading.value = true;
|
||||
backLoading.value = true;
|
||||
backButtonDisabled.value = true;
|
||||
await backProcess(backForm.value).finally(() => (loading.value = false));
|
||||
await backProcess(backForm.value).finally(() => {
|
||||
loading.value = false;
|
||||
buttonDisabled.value = false;
|
||||
});
|
||||
dialog.visible = false;
|
||||
backLoading.value = false;
|
||||
backButtonDisabled.value = false;
|
||||
@ -282,18 +285,48 @@ const handleCopyCloseTag = (user: UserVO) => {
|
||||
selectCopyUserIds.value = selectCopyUserList.value.map((item) => item.userId).join(',');
|
||||
};
|
||||
//加签
|
||||
const addMultiInstanceUser = () => {
|
||||
if (multiInstanceUserRef.value) {
|
||||
title.value = '加签人员';
|
||||
multiInstanceUserRef.value.getAddMultiInstanceList(taskId.value, []);
|
||||
const openMultiInstanceUser = async () => {
|
||||
multiInstanceUserRef.value.open();
|
||||
};
|
||||
//加签
|
||||
const addMultiInstanceUser = async (data) => {
|
||||
if (data && data.length > 0) {
|
||||
const taskOperationBo = reactive<TaskOperationBo>({
|
||||
userIds: data.map((e) => e.userId),
|
||||
taskId: taskId.value,
|
||||
message: form.value.message
|
||||
});
|
||||
await proxy?.$modal.confirm('是否确认提交?');
|
||||
loading.value = true;
|
||||
buttonDisabled.value = true;
|
||||
await taskOperation(taskOperationBo, 'addSignature').finally(() => {
|
||||
loading.value = false;
|
||||
buttonDisabled.value = false;
|
||||
});
|
||||
dialog.visible = false;
|
||||
emits('submitCallback');
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
} else {
|
||||
proxy?.$modal.msgWarning('请选择用户!');
|
||||
}
|
||||
};
|
||||
//减签
|
||||
const deleteMultiInstanceUser = () => {
|
||||
if (multiInstanceUserRef.value) {
|
||||
title.value = '减签人员';
|
||||
multiInstanceUserRef.value.getDeleteMultiInstanceList(taskId.value);
|
||||
}
|
||||
const deleteMultiInstanceUser = async (row) => {
|
||||
await proxy?.$modal.confirm('是否确认提交?');
|
||||
loading.value = true;
|
||||
buttonDisabled.value = true;
|
||||
const taskOperationBo = reactive<TaskOperationBo>({
|
||||
userIds: [row.userId],
|
||||
taskId: taskId.value,
|
||||
message: form.value.message
|
||||
});
|
||||
await taskOperation(taskOperationBo, 'reductionSignature').finally(() => {
|
||||
loading.value = false;
|
||||
buttonDisabled.value = false;
|
||||
});
|
||||
dialog.visible = false;
|
||||
emits('submitCallback');
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
};
|
||||
//打开转办
|
||||
const openTransferTask = () => {
|
||||
@ -302,15 +335,18 @@ const openTransferTask = () => {
|
||||
//转办
|
||||
const handleTransferTask = async (data) => {
|
||||
if (data && data.length > 0) {
|
||||
let params = {
|
||||
taskId: taskId.value,
|
||||
const taskOperationBo = reactive<TaskOperationBo>({
|
||||
userId: data[0].userId,
|
||||
comment: form.value.message
|
||||
};
|
||||
taskId: taskId.value,
|
||||
message: form.value.message
|
||||
});
|
||||
await proxy?.$modal.confirm('是否确认提交?');
|
||||
loading.value = true;
|
||||
buttonDisabled.value = true;
|
||||
await transferTask(params).finally(() => (loading.value = false));
|
||||
await taskOperation(taskOperationBo, 'transferTask').finally(() => {
|
||||
loading.value = false;
|
||||
buttonDisabled.value = false;
|
||||
});
|
||||
dialog.visible = false;
|
||||
emits('submitCallback');
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
@ -326,15 +362,18 @@ const openDelegateTask = () => {
|
||||
//委托
|
||||
const handleDelegateTask = async (data) => {
|
||||
if (data && data.length > 0) {
|
||||
let params = {
|
||||
taskId: taskId.value,
|
||||
const taskOperationBo = reactive<TaskOperationBo>({
|
||||
userId: data[0].userId,
|
||||
nickName: data[0].nickName
|
||||
};
|
||||
taskId: taskId.value,
|
||||
message: form.value.message
|
||||
});
|
||||
await proxy?.$modal.confirm('是否确认提交?');
|
||||
loading.value = true;
|
||||
buttonDisabled.value = true;
|
||||
await delegateTask(params).finally(() => (loading.value = false));
|
||||
await taskOperation(taskOperationBo, 'delegateTask').finally(() => {
|
||||
loading.value = false;
|
||||
buttonDisabled.value = false;
|
||||
});
|
||||
dialog.visible = false;
|
||||
emits('submitCallback');
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
@ -343,7 +382,7 @@ const handleDelegateTask = async (data) => {
|
||||
}
|
||||
};
|
||||
//终止任务
|
||||
const handleTerminationTask = async (data) => {
|
||||
const handleTerminationTask = async () => {
|
||||
let params = {
|
||||
taskId: taskId.value,
|
||||
comment: form.value.message
|
||||
@ -351,11 +390,24 @@ const handleTerminationTask = async (data) => {
|
||||
await proxy?.$modal.confirm('是否确认终止?');
|
||||
loading.value = true;
|
||||
buttonDisabled.value = true;
|
||||
await terminationTask(params).finally(() => (loading.value = false));
|
||||
await terminationTask(params).finally(() => {
|
||||
loading.value = false;
|
||||
buttonDisabled.value = false;
|
||||
});
|
||||
dialog.visible = false;
|
||||
emits('submitCallback');
|
||||
proxy?.$modal.msgSuccess('操作成功');
|
||||
};
|
||||
const handleTaskUser = async () => {
|
||||
let data = await currentTaskAllUser(taskId.value);
|
||||
deleteUserList.value = data.data;
|
||||
if (deleteUserList.value && deleteUserList.value.length > 0) {
|
||||
deleteUserList.value.forEach((e) => {
|
||||
e.nodeName = task.value.nodeName;
|
||||
});
|
||||
}
|
||||
deleteSignatureVisible.value = true;
|
||||
};
|
||||
|
||||
/**
|
||||
* 对外暴露子组件方法
|
||||
|
@ -43,7 +43,7 @@
|
||||
<el-card shadow="hover">
|
||||
<template v-if="prop.multiple" #header>
|
||||
<el-tag v-for="user in selectUserList" :key="user.userId" closable style="margin: 2px" @close="handleCloseTag(user)">
|
||||
{{ user.userName }}
|
||||
{{ user.nickName }}
|
||||
</el-tag>
|
||||
</template>
|
||||
|
||||
@ -100,14 +100,14 @@
|
||||
<script setup lang="ts">
|
||||
import api from '@/api/system/user';
|
||||
import { UserQuery, UserVO } from '@/api/system/user/types';
|
||||
import { DeptVO } from '@/api/system/dept/types';
|
||||
import { DeptTreeVO, DeptVO } from '@/api/system/dept/types';
|
||||
import { VxeTableInstance } from 'vxe-table';
|
||||
import useDialog from '@/hooks/useDialog';
|
||||
|
||||
interface PropType {
|
||||
modelValue?: UserVO[] | UserVO | undefined;
|
||||
multiple?: boolean;
|
||||
data?: string | number | (string | number)[];
|
||||
data?: string | number | (string | number)[] | undefined;
|
||||
}
|
||||
const prop = withDefaults(defineProps<PropType>(), {
|
||||
multiple: true,
|
||||
@ -125,7 +125,7 @@ const showSearch = ref(true);
|
||||
const total = ref(0);
|
||||
const dateRange = ref<[DateModelType, DateModelType]>(['', '']);
|
||||
const deptName = ref('');
|
||||
const deptOptions = ref<DeptVO[]>([]);
|
||||
const deptOptions = ref<DeptTreeVO[]>([]);
|
||||
const selectUserList = ref<UserVO[]>([]);
|
||||
|
||||
const deptTreeRef = ref<ElTreeInstance>();
|
||||
|
Reference in New Issue
Block a user