add 添加warm-ui设计器,删除无用代码

update 调整流程图预览
This commit is contained in:
gssong 2024-10-26 17:44:36 +08:00
parent 681758494b
commit 42a4ef4c96
26 changed files with 93 additions and 1903 deletions

View File

@ -45,9 +45,7 @@
"vue-i18n": "9.10.2",
"vue-router": "4.3.2",
"vue-types": "5.1.1",
"vxe-table": "4.5.22",
"@logicflow/core": "^1.2.15",
"@logicflow/extension": "^1.2.16"
"vxe-table": "4.5.22"
},
"devDependencies": {
"@iconify/json": "2.2.201",

View File

@ -1,6 +1,7 @@
import request from '@/utils/request';
import { ProcessInstanceQuery, ProcessInstanceVO } from '@/api/workflow/processInstance/types';
import { AxiosPromise } from 'axios';
import { number } from 'vue-types';
/**
*
@ -31,9 +32,9 @@ export const getPageByFinish = (query: ProcessInstanceQuery): AxiosPromise<Proce
/**
* id获取历史流程图
*/
export const getHistoryImage = (businessKey: string) => {
export const getFlowImage = (businessKey: string | number) => {
return request({
url: `/workflow/processInstance/getHistoryImage/${businessKey}` + '?t' + Math.random(),
url: `/workflow/processInstance/getFlowImage/${businessKey}` + '?t' + Math.random(),
method: 'get'
});
};
@ -48,18 +49,6 @@ export const getHistoryList = (businessKey: string): AxiosPromise<Record<string,
});
};
/**
*
* @param businessKey id
* @returns
*/
export const getHistoryRecord = (businessKey: string | number) => {
return request({
url: `/workflow/processInstance/getHistoryRecord/${businessKey}`,
method: 'get'
});
};
/**
*
* @param data
@ -125,9 +114,8 @@ export const cancelProcessApply = (businessKey: string) => {
export default {
getPageByRunning,
getPageByFinish,
getHistoryImage,
getFlowImage,
getHistoryList,
getHistoryRecord,
deleteRunInstance,
deleteRunAndHisInstance,
deleteFinishAndHisInstance,

View File

@ -2,27 +2,22 @@
<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>
<el-tag type="success">{{ scope.row.approveName || '无' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="状态" sortable align="center">
<template #default="scope">
<el-tag type="success">{{ scope.row.statusName }}</el-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="message" label="审批意见" sortable align="center"></el-table-column>
<el-table-column prop="createTime" label="开始时间" sortable align="center"></el-table-column>
<el-table-column prop="updateTime" 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">
<template #default="scope">
@ -49,7 +44,6 @@
</div>
</template>
<script lang="ts" setup>
import BpmnView from '@/components/BpmnView/index.vue';
import processApi from '@/api/workflow/processInstance';
import { propTypes } from '@/utils/propTypes';
@ -63,8 +57,7 @@ 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) => {
@ -72,12 +65,12 @@ const init = async (businessKey: string | number) => {
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);
processApi.getFlowImage(businessKey).then((resp) => {
if (resp.data) {
historyList.value = resp.data.list;
imgUrl.value = 'data:image/gif;base64,' + resp.data.image;
loading.value = false;
}
});
};

View File

@ -1,267 +0,0 @@
<template>
<div class="between">
<el-form ref="form" :model="form" label-width="120px" :rules="rules" size="small" :disabled="disabled">
<slot name="form-item-task-nodeCode" :model="form" field="nodeCode">
<el-form-item label="节点编码">
<el-input v-model="form.nodeCode" :disabled="disabled"></el-input>
</el-form-item>
</slot>
<slot name="form-item-task-nodeName" :model="form" field="nodeName">
<el-form-item label="节点名称">
<el-input v-model="form.nodeName" :disabled="disabled"></el-input>
</el-form-item>
</slot>
<slot name="form-item-task-collaborativeWay" :model="form" field="collaborativeWay">
<el-form-item label="协作方式">
<el-radio-group v-model="form.collaborativeWay" @change="collaborativeWayChange">
<el-radio v-if="form.collaborativeWay === '1'" label="1">
或签
<el-tooltip class="item" effect="dark" content="只需一个人审批">
<i class="el-icon-question" style="color: #000"></i>
</el-tooltip>
</el-radio>
<el-radio v-if="form.collaborativeWay === '2'" label="2">
票签
<el-tooltip class="item" effect="dark" content="部分办理人审批,只支持选择用户">
<i class="el-icon-question" style="color: #000"></i>
</el-tooltip>
</el-radio>
<el-radio v-if="form.collaborativeWay === '3'" label="3">
会签
<el-tooltip class="item" effect="dark" content="所有办理都需要审批,只支持选择用户">
<i class="el-icon-question" style="color: #000"></i>
</el-tooltip>
</el-radio>
</el-radio-group>
</el-form-item>
</slot>
<slot v-if="form.collaborativeWay === '2'" name="form-item-task-nodeRatio" :model="form" field="nodeRatio">
<el-form-item label="票签占比" prop="nodeRatio">
<el-input v-model="form.nodeRatio" type="number" placeholder="请输入"></el-input>
<div class="placeholder">票签比例范围(0-100)的值</div>
</el-form-item>
</slot>
<slot name="form-item-task-permissionFlag" :model="form" field="permissionFlag">
<el-tooltip effect="dark" :content="userNameList" :disabled="!disabled">
<el-form-item label="办理人选择">
<el-select
v-if="form.collaborativeWay === '1'"
v-model="form.permissionFlag"
multiple
collapse-tags
:disabled="disabled"
allow-create
:clearable="!disabled"
filterable
>
<el-option-group v-for="groupOption in groupOptions" :key="groupOption.label" :label="groupOption.label" :disabled="disabled">
<el-option v-for="item in groupOption.options" :key="item.value" :label="item.label" :value="item.value"> </el-option>
</el-option-group>
</el-select>
<el-select
v-else
v-model="form.permissionFlag"
multiple
collapse-tags
:disabled="disabled"
:clearable="!disabled"
popper-class="dialogSelect"
:popper-append-to-body="false"
@focus="initUser"
>
<el-option v-for="item in form.permissionFlag" :key="item" :label="item" :value="item"> </el-option>
</el-select>
</el-form-item>
</el-tooltip>
</slot>
<slot name="form-item-task-listenerType" :model="form" field="listenerType">
<el-form-item label="监听器类型">
<el-select v-model="form.listenerType" multiple>
<el-option label="任务创建" value="create"></el-option>
<el-option label="任务开始办理" value="start"></el-option>
<el-option label="分派监听器" value="assignment"></el-option>
<el-option label="任务完成" value="finish"></el-option>
</el-select>
</el-form-item>
</slot>
<slot name="form-item-task-listenerPath" :model="form" field="listenerPath">
<el-form-item label="监听器路径" description="输入监听器的路径,以@@分隔,顺序与监听器类型一致">
<el-input v-model="form.listenerPath" type="textarea" rows="8"></el-input>
<el-tooltip class="item" effect="dark" content="输入监听器的路径,以@@分隔,顺序与监听器类型一致">
<i class="el-icon-question"></i>
</el-tooltip>
</el-form-item>
</slot>
<slot name="form-item-task-formCustom" :model="form" field="formCustom">
<el-form-item label="审批表单是否自定义">
<el-select v-model="form.formCustom">
<el-option label="使用流程表单" :value="''"></el-option>
<!-- <el-option label="节点自定义表单" value="Y"></el-option> -->
<el-option label="节点表单路径" value="N"></el-option>
</el-select>
</el-form-item>
</slot>
<slot v-if="form.formCustom === 'N'" name="form-item-task-formPath" :model="form" field="formPath">
<el-form-item label="审批表单路径">
<el-input v-model="form.formPath"></el-input>
</el-form-item>
</slot>
</el-form>
<!-- 权限标识会签票签选择用户 -->
<el-dialog v-model:visible="userVisible" title="用户选择" width="80%" append-to-body>
<!-- <selectUser v-model:select-user="form.permissionFlag" v-model:user-visible="userVisible" @handle-user-select="handleUserSelect"></selectUser> -->
</el-dialog>
</div>
</template>
<script>
import { optionSelect as listRole } from '@/api/system/role';
import { optionSelect as listUser } from '@/api/system/user';
import { optionSelect as listDept } from '@/api/system/dept';
//import selectUser from '@/views/components/selectUser';
export default {
name: 'Between',
components: {
//selectUser
},
props: {
value: {
type: Object,
default() {
return {};
}
},
disabled: {
//
type: Boolean,
default: false
}
},
data() {
return {
form: this.value,
userNameList: '',
groupOptions: [],
rules: {
nodeRatio: [
{ required: false, message: '请输入', trigger: 'change' },
{ pattern: /^(?:[1-9]\d?|0\.\d{1,3}|[1-9]\d?\.\d{1,3})$/, message: '请输入(0, 100)的值,最多保留三位小数', trigger: ['change', 'blur'] }
]
},
userVisible: false
};
},
watch: {
form: {
handler(n) {
this.$emit('change', n);
},
deep: true
}
},
created() {
if (this.form.permissionFlag) {
this.form.permissionFlag = this.form.permissionFlag.split(',');
}
if (this.form.listenerType) {
this.form.listenerType = this.form.listenerType.split(',');
}
this.getPermissionFlag();
if (this.disabled) this.getIdReverseDisplayName();
},
methods: {
// id
getIdReverseDisplayName() {
if (this.form.collaborativeWay !== '1') {
idReverseDisplayName(this.form.permissionFlag.join(',')).then((res) => {
this.userNameList = res.data ? res.data.map((e) => e.nickName).join(',') : '';
});
}
},
/** 选择角色权限范围触发 */
getPermissionFlag() {
let groupOptionCreateBy = {
label: '创建人',
options: [
{
value: 'warmFlowInitiator',
label: '流程发起人'
}
]
};
this.groupOptions.push(groupOptionCreateBy);
listRole([]).then((response) => {
let groupOption = {
label: '角色',
options: response.data.map((item) => {
return {
value: 'role:' + item.roleId,
label: item.roleName
};
})
};
this.groupOptions.push(groupOption);
listUser([]).then((response) => {
let groupOption = {
label: '用户',
options: response.data.map((item) => {
return {
value: item.userId,
label: item.nickName
};
})
};
this.groupOptions.push(groupOption);
listDept([]).then((response) => {
let groupOption = {
label: '部门',
options: response.data.map((item) => {
return {
value: 'dept:' + item.deptId,
label: item.deptName
};
})
};
this.groupOptions.push(groupOption);
if (this.disabled && this.form.collaborativeWay === '1') {
let userNameList = [];
this.groupOptions.forEach((e) => {
e.options.forEach((o) => {
if (this.form.permissionFlag.includes(o.value)) userNameList.push(o.label);
});
});
this.userNameList = userNameList.join(',');
}
});
});
});
},
collaborativeWayChange(val) {
this.form.permissionFlag = [];
this.$set(this.form, 'nodeRatio', val === '1' ? '0.000' : val === '3' ? '100.000' : '');
},
//
initUser() {
this.userVisible = true;
},
//
handleUserSelect(checkedItemList) {
this.form.permissionFlag = checkedItemList.map((e) => {
return e.userId;
});
}
}
};
</script>
<style scoped>
.dialogSelect {
display: none;
}
.placeholder {
color: #828f9e;
font-size: 12px;
}
</style>

View File

@ -1,52 +0,0 @@
<template>
<div>
<el-form ref="form" :model="form" label-width="120px" size="small" :disabled="disabled">
<slot name="form-item-task-name" :model="form" field="nodeCode">
<el-form-item label="节点编码">
<el-input v-model="form.nodeCode" :disabled="disabled"></el-input>
</el-form-item>
</slot>
<slot name="form-item-task-name" :model="form" field="nodeName">
<el-form-item label="节点名称">
<el-input v-model="form.nodeName" :disabled="disabled"></el-input>
</el-form-item>
</slot>
</el-form>
</div>
</template>
<script>
export default {
name: 'End',
props: {
value: {
type: Object,
default() {
return {};
}
},
disabled: {
//
type: Boolean,
default: false
}
},
data() {
return {
form: this.value
};
},
watch: {
form: {
handler(n) {
this.$emit('change', n);
},
deep: true
}
},
created() {},
methods: {}
};
</script>
<style scoped></style>

View File

@ -1,246 +0,0 @@
<template>
<div>
<el-drawer ref="drawer" v-model="drawer" :title="title" destroy-on-close direction="rtl" :append-to-body="true" :before-close="handleClose">
<component
:is="node ? node.type : ''"
:ref="node ? node.type : ''"
v-model="form"
:disabled="disabled"
:skip-condition-show="skipConditionShow"
>
<template v-for="(item, key) in $slots" #[key]="data">
<slot :name="key" v-bind="data || {}"></slot>
</template>
</component>
</el-drawer>
</div>
</template>
<script>
import Start from './start.vue';
import Between from './between.vue';
import Serial from './serial.vue';
import Parallel from './parallel.vue';
import End from './end.vue';
import Skip from './skip.vue';
export default {
components: {
Start,
Between,
Serial,
Parallel,
End,
Skip
},
props: {
value: {
type: Object,
default() {
return {};
}
},
node: {
type: Object,
default() {
return {};
}
},
lf: {
type: Object,
default() {
return null;
}
},
disabled: {
//
type: Boolean,
default: false
},
skipConditionShow: {
//
type: Boolean,
default: true
}
},
data() {
return {
drawer: false,
form: {},
objId: undefined,
nodeCode: null
};
},
computed: {
title() {
if (this.node && this.node.type === 'skip') {
return '设置边属性';
} else if (this.node && this.node.type === 'serial') {
return '设置串行网关属性';
} else if (this.node && this.node.type === 'parallel') {
return '设置并行网关属性';
} else if (this.node && this.node.type === 'start') {
return '设置开始属性';
} else if (this.node && this.node.type === 'end') {
return '设置结束属性';
}
return '设置中间属性';
}
},
watch: {
node(n) {
if (n) {
this.objId = n.id;
let skipCondition = n.properties.skipCondition;
let conditionSpl = skipCondition ? skipCondition.split('@@|') : [];
let conditionSplTwo = conditionSpl && conditionSpl.length > 0 ? conditionSpl[1] : [];
let condition,
conditionType,
conditionValue = '';
if (conditionSpl && conditionSpl.length > 0 && conditionSpl[0] === '@@spel') {
conditionType = 'spel';
conditionValue = conditionSplTwo;
} else if (conditionSpl && conditionSpl.length > 0 && conditionSpl[0] !== '@@spel') {
condition = conditionSplTwo && conditionSplTwo.length > 0 ? conditionSplTwo.split('@@')[0] : '';
conditionType = conditionSplTwo && conditionSplTwo.length > 0 ? conditionSplTwo.split('@@')[1] : '';
conditionValue = conditionSplTwo && conditionSplTwo.length > 0 ? conditionSplTwo.split('@@')[2] : '';
}
if (n.type === 'skip') {
this.form = {
nodeType: n.type,
skipType: n.properties.skipType,
skipName: n.properties.skipName,
skipCondition: skipCondition,
condition: condition,
conditionType: conditionType,
conditionValue: conditionValue
};
} else {
let nodeRatio = n.properties.nodeRatio || '';
if (!n.properties.collaborativeWay) {
n.properties.collaborativeWay = nodeRatio === '0.000' ? '1' : nodeRatio === '100.000' ? '3' : nodeRatio ? '2' : '1';
}
n.properties.formCustom = JSON.stringify(n.properties) === '{}' ? 'N' : n.properties.formCustom || '';
this.form = {
nodeType: n.type,
nodeCode: n.id,
nodeName: n.text instanceof Object ? n.text.value : n.text,
...n.properties
};
}
}
},
'form.nodeCode'(n) {
this.nodeCode = n;
},
'form.skipType'(n) {
//
this.lf.setProperties(this.objId, {
skipType: n
});
},
'form.nodeName'(n) {
//
this.lf.updateText(this.objId, n);
//
this.lf.setProperties(this.objId, {
nodeName: n
});
},
'form.collaborativeWay'(n) {
this.lf.setProperties(this.objId, {
nodeRatio: n === '1' ? '0.000' : n === '3' ? '100.000' : ''
});
},
'form.nodeRatio'(n) {
this.lf.setProperties(this.objId, {
nodeRatio: n
});
},
'form.permissionFlag'(n) {
//
this.lf.setProperties(this.objId, {
permissionFlag: Array.isArray(n) ? n.join(',') : n
});
},
'form.skipAnyNode'(n) {
//
this.lf.setProperties(this.objId, {
skipAnyNode: n
});
},
'form.listenerType'(n) {
//
this.lf.setProperties(this.objId, {
listenerType: Array.isArray(n) ? n.join(',') : n
});
},
'form.listenerPath'(n) {
//
this.lf.setProperties(this.objId, {
listenerPath: n
});
},
'form.formCustom'(n) {
this.lf.setProperties(this.objId, {
formCustom: n || ''
});
},
'form.formPath'(n) {
this.lf.setProperties(this.objId, {
formPath: n
});
},
'form.skipCondition'(n) {
//
this.lf.setProperties(this.objId, {
skipCondition: n
});
},
'form.skipName'(n) {
if (['skip'].includes(this.node.type)) {
debugger;
//
this.lf.updateText(this.objId, n);
//
this.lf.setProperties(this.objId, {
skipName: n
});
}
}
},
created() {},
methods: {
show() {
this.drawer = true;
},
handleClose() {
//
if (this.nodeCode && this.objId) {
if (['skip'].includes(this.node?.type)) {
if (!this.lf.getEdgeModelById(this.nodeCode)) {
this.lf.changeEdgeId(this.objId, this.nodeCode);
}
} else {
if (!this.lf.getNodeModelById(this.nodeCode)) {
this.lf.changeNodeId(this.objId, this.nodeCode);
}
}
}
if (this.node?.type === 'between') {
this.$refs.between.$refs.form.validate((valid) => {
if (valid) {
this.drawer = false;
}
});
} else this.drawer = false;
}
}
};
</script>
<style scoped>
.el-drawer__container ::-webkit-scrollbar {
display: none;
}
</style>

View File

@ -1,52 +0,0 @@
<template>
<div>
<el-form ref="form" :model="form" label-width="120px" size="small" :disabled="disabled">
<slot name="form-item-task-name" :model="form" field="nodeCode">
<el-form-item label="节点编码">
<el-input v-model="form.nodeCode" :disabled="disabled"></el-input>
</el-form-item>
</slot>
<slot name="form-item-task-name" :model="form" field="nodeName">
<el-form-item label="节点名称">
<el-input v-model="form.nodeName" :disabled="disabled"></el-input>
</el-form-item>
</slot>
</el-form>
</div>
</template>
<script>
export default {
name: 'Parallel',
props: {
value: {
type: Object,
default() {
return {};
}
},
disabled: {
//
type: Boolean,
default: false
}
},
data() {
return {
form: this.value
};
},
watch: {
form: {
handler(n) {
this.$emit('change', n);
},
deep: true
}
},
created() {},
methods: {}
};
</script>
<style scoped></style>

View File

@ -1,52 +0,0 @@
<template>
<div>
<el-form ref="form" :model="form" label-width="120px" size="small" :disabled="disabled">
<slot name="form-item-task-name" :model="form" field="nodeCode">
<el-form-item label="节点编码">
<el-input v-model="form.nodeCode" :disabled="disabled"></el-input>
</el-form-item>
</slot>
<slot name="form-item-task-name" :model="form" field="nodeName">
<el-form-item label="节点名称">
<el-input v-model="form.nodeName" :disabled="disabled"></el-input>
</el-form-item>
</slot>
</el-form>
</div>
</template>
<script>
export default {
name: 'Serial',
props: {
value: {
type: Object,
default() {
return {};
}
},
disabled: {
//
type: Boolean,
default: false
}
},
data() {
return {
form: this.value
};
},
watch: {
form: {
handler(n) {
this.$emit('change', n);
},
deep: true
}
},
created() {},
methods: {}
};
</script>
<style scoped></style>

View File

@ -1,93 +0,0 @@
<template>
<div>
<el-form ref="form" :model="form" label-width="120px" size="small" :disabled="disabled">
<slot v-if="skipConditionShow" name="form-item-task-skipName" :model="form" field="skipName">
<el-form-item label="跳转名称">
<el-input v-model="form.skipName" placeholder="跳转名称" />
</el-form-item>
</slot>
<slot name="form-item-task-skipType" :model="form" field="skipType">
<el-form-item label="跳转类型">
<el-select v-model="form.skipType">
<el-option sel label="审批通过" value="PASS" />
<el-option label="退回" value="REJECT" />
</el-select>
</el-form-item>
</slot>
<slot v-if="skipConditionShow" name="form-item-task-skipCondition" :model="form" field="skipCondition">
<el-form-item label="跳转条件">
<el-input v-if="!spelFlag" v-model="form.condition" placeholder="条件名" style="width: 20%" />
<el-select v-model="form.conditionType" placeholder="请选择条件方式" style="width: 35%; margin-left: 1%" @change="changeOper">
<el-option label="大于" value="gt" />
<el-option label="大于等于" value="ge" />
<el-option label="等于" value="eq" />
<el-option label="不等于" value="ne" />
<el-option label="小于" value="lt" />
<el-option label="小于等于" value="le" />
<el-option label="包含" value="like" />
<el-option label="不包含" value="notNike" />
<el-option label="spel表达式" value="spel" />
</el-select>
<el-input v-model="form.conditionValue" placeholder="条件值" style="width: 42%; margin-left: 1%; margin-right: 1%" />
</el-form-item>
</slot>
</el-form>
</div>
</template>
<script>
export default {
name: 'Skip',
props: {
value: {
type: Object,
default() {
return {};
}
},
disabled: {
//
type: Boolean,
default: false
},
skipConditionShow: {
//
type: Boolean,
default: true
}
},
data() {
return {
spelFlag: false,
form: this.value
};
},
watch: {
form: {
handler(n) {
let skipCondition = n.skipCondition;
skipCondition = '@@' + n.conditionType + '@@|';
if (n.conditionType !== 'spel') {
skipCondition = skipCondition + (n.condition ? n.condition : '') + '@@' + n.conditionType + '@@';
}
n.skipCondition = skipCondition + (n.conditionValue ? n.conditionValue : '');
this.$emit('change', n);
},
deep: true
}
},
created() {
if (this.value.conditionType === 'spel') {
this.spelFlag = true;
}
},
methods: {
changeOper(obj) {
this.spelFlag = obj === 'spel';
}
}
};
</script>
<style scoped></style>

View File

@ -1,75 +0,0 @@
<template>
<div>
<el-form ref="form" :model="form" label-width="120px" size="small" :disabled="disabled">
<slot name="form-item-task-name" :model="form" field="nodeCode">
<el-form-item label="节点编码">
<el-input v-model="form.nodeCode" :disabled="disabled"></el-input>
</el-form-item>
</slot>
<slot name="form-item-task-name" :model="form" field="nodeName">
<el-form-item label="节点名称">
<el-input v-model="form.nodeName" :disabled="disabled"></el-input>
</el-form-item>
</slot>
<slot name="form-item-task-listenerType" :model="form" field="listenerType">
<el-form-item label="监听器类型">
<el-select v-model="form.listenerType" multiple>
<el-option label="任务创建" value="create"></el-option>
<el-option label="任务开始办理" value="start"></el-option>
<el-option label="分派监听器" value="assignment"></el-option>
<el-option label="权限认证" value="permission"></el-option>
<el-option label="任务完成" value="finish"></el-option>
</el-select>
</el-form-item>
</slot>
<slot name="form-item-task-listenerPath" :model="form" field="listenerPath">
<el-form-item label="监听器路径" description="输入监听器的路径,以@@分隔,顺序与监听器类型一致">
<el-input v-model="form.listenerPath" type="textarea" rows="8"></el-input>
<el-tooltip class="item" effect="dark" content="输入监听器的路径,以@@分隔,顺序与监听器类型一致">
<i class="el-icon-question"></i>
</el-tooltip>
</el-form-item>
</slot>
</el-form>
</div>
</template>
<script>
export default {
name: 'Start',
props: {
value: {
type: Object,
default() {
return {};
}
},
disabled: {
//
type: Boolean,
default: false
}
},
data() {
return {
form: this.value
};
},
watch: {
form: {
handler(n) {
this.$emit('change', n);
},
deep: true
}
},
created() {
if (this.form.listenerType) {
this.form.listenerType = this.form.listenerType.split(',');
}
},
methods: {}
};
</script>
<style scoped></style>

View File

@ -1,23 +0,0 @@
import { RectNode, RectNodeModel } from "@logicflow/core";
class BetweenModel extends RectNodeModel {
initNodeData(data) {
super.initNodeData(data);
this.width = 100;
this.height = 80;
this.radius = 5;
}
getNodeStyle() {
const style = super.getNodeStyle();
return style
}
}
class BetweenView extends RectNode {}
export default {
type: "between",
model: BetweenModel,
view: BetweenView,
};

View File

@ -1,139 +0,0 @@
// 测试数据
const graphData = {
flowName: "请假流程-串行1",
flowCode: "leaveFlow-serial1",
version: "1.0",
formCustom: "N",
formPath: "test/leave/approve",
nodes: [
{
id: "node_id_1",
type: "start",
x: 200,
y: 200,
text: { x: 200, y: 200, value: "开始" },
properties: {
status: "approval"
},
},
{
id: "node_id_2",
type: "between",
x: 400,
y: 200,
text: { x: 400, y: 200, value: "待提交" },
properties: {
status: "pass"
},
},
{
id: "node_id_3",
type: "between",
x: 600,
y: 200,
text: { x: 600, y: 200, value: "组长审批" },
properties: {
status: "approval"
},
},
{
id: "node_id_4",
type: "between",
x: 800,
y: 200,
text: { x: 800, y: 200, value: "部门审批" },
properties: {
status: "approval"
},
},
{
id: "node_id_5",
type: "between",
x: 1000,
y: 200,
text: { x: 1000, y: 200, value: "hr审批" },
properties: {
status: "approval"
},
},
{
id: "node_id_6",
type: "end",
x: 1200,
y: 200,
text: { x: 1200, y: 200, value: "结束" },
properties: {},
},
],
edges: [
{
id: "edge_id",
type: "skip",
sourceNodeId: "node_id_1",
targetNodeId: "node_id_2",
text: { x: 280, y: 200, value: "通过" },
startPoint: { x: 220, y: 200 },
endPoint: { x: 350, y: 200 },
properties: {},
},
{
id: "edge_id",
type: "skip",
sourceNodeId: "node_id_2",
targetNodeId: "node_id_3",
text: { x: 500, y: 200, value: "通过" },
startPoint: { x: 450, y: 200 },
endPoint: { x: 550, y: 200 },
properties: {},
},
{
id: "edge_id",
type: "skip",
sourceNodeId: "node_id_3",
targetNodeId: "node_id_4",
text: { x: 700, y: 200, value: "通过" },
startPoint: { x: 650, y: 200 },
endPoint: { x: 750, y: 200 },
properties: {},
},
{
id: "edge_id",
type: "skip",
sourceNodeId: "node_id_4",
targetNodeId: "node_id_5",
text: { x: 900, y: 200, value: "通过" },
startPoint: { x: 850, y: 200 },
endPoint: { x: 950, y: 200 },
properties: {},
},
{
id: "edge_id",
type: "skip",
sourceNodeId: "node_id_5",
targetNodeId: "node_id_6",
text: { x: 1120, y: 200, value: "通过" },
startPoint: { x: 1050, y: 200 },
endPoint: { x: 1180, y: 200 },
properties: {},
},
{
id: "edge_id",
type: "skip",
sourceNodeId: "node_id_4",
targetNodeId: "node_id_2",
text: { x: 600, y: 100, value: "退回" },
startPoint: { x: 800, y: 160 },
endPoint: { x: 400, y: 160 },
pointsList: [
{ x: 800, y: 160 },
{ x: 800, y: 100 },
{ x: 400, y: 100 },
{ x: 400, y: 160 },
],
properties: {},
},
],
};
export default graphData

View File

@ -1,17 +0,0 @@
import { CircleNode, CircleNodeModel } from "@logicflow/core";
class endModel extends CircleNodeModel {
initNodeData(data) {
super.initNodeData(data);
this.r = 20
}
}
class endView extends CircleNode {}
export default {
type: "end",
model: endModel,
view: endView,
};

View File

@ -1,57 +0,0 @@
import { h, PolygonNode, PolygonNodeModel } from '@logicflow/core'
class ParallelModel extends PolygonNodeModel {
static extendKey = 'ParallelModel';
constructor (data, graphModel) {
if (!data.text) {
data.text = ''
}
if (data.text && typeof data.text === 'string') {
data.text = {
value: data.text,
x: data.x,
y: data.y + 40
}
}
super(data, graphModel)
this.points = [
[25, 0],
[50, 25],
[25, 50],
[0, 25]
]
}
}
class ParallelView extends PolygonNode {
static extendKey = 'ParallelNode';
getShape () {
const { model } = this.props
const { x, y, width, height, points } = model
const style = model.getNodeStyle()
return h(
'g',
{
transform: `matrix(1 0 0 1 ${x - width / 2} ${y - height / 2})`
},
h('polygon', {
...style,
x,
y,
points
}),
h('path', {
d:
'm 23,10 0,12.5 -12.5,0 0,5 12.5,0 0,12.5 5,0 0,-12.5 12.5,0 0,-5 -12.5,0 0,-12.5 -5,0 z',
...style
})
)
}
}
export default {
type: 'parallel',
view: ParallelView,
model: ParallelModel
};

View File

@ -1,57 +0,0 @@
import { h, PolygonNode, PolygonNodeModel } from '@logicflow/core'
class SerialModel extends PolygonNodeModel {
static extendKey = 'SerialModel';
constructor (data, graphModel) {
if (!data.text) {
data.text = ''
}
if (data.text && typeof data.text === 'string') {
data.text = {
value: data.text,
x: data.x,
y: data.y + 40
}
}
super(data, graphModel)
this.points = [
[25, 0],
[50, 25],
[25, 50],
[0, 25]
]
}
}
class SerialView extends PolygonNode {
static extendKey = 'SerialNode';
getShape () {
const { model } = this.props
const { x, y, width, height, points } = model
const style = model.getNodeStyle()
return h(
'g',
{
transform: `matrix(1 0 0 1 ${x - width / 2} ${y - height / 2})`
},
h('polygon', {
...style,
x,
y,
points
}),
h('path', {
d:
'm 16,15 7.42857142857143,9.714285714285715 -7.42857142857143,9.714285714285715 3.428571428571429,0 5.714285714285715,-7.464228571428572 5.714285714285715,7.464228571428572 3.428571428571429,0 -7.42857142857143,-9.714285714285715 7.42857142857143,-9.714285714285715 -3.428571428571429,0 -5.714285714285715,7.464228571428572 -5.714285714285715,-7.464228571428572 -3.428571428571429,0 z',
...style
})
)
}
}
export default {
type: 'serial',
view: SerialView,
model: SerialModel
};

View File

@ -1,33 +0,0 @@
import { PolylineEdge, PolylineEdgeModel } from "@logicflow/core";
class SkipModel extends PolylineEdgeModel {
setAttributes() {
this.offset = 20;
}
getEdgeStyle() {
const style = super.getEdgeStyle();
const { properties } = this;
if (properties.isActived) {
style.strokeDasharray = "4 4";
}
return style;
}
/**
* 重写此方法使保存数据是能带上锚点数据
*/
getData() {
const data = super.getData();
data.sourceAnchorId = this.sourceAnchorId;
data.targetAnchorId = this.targetAnchorId;
return data;
}
}
export default {
type: "skip",
view: PolylineEdge,
model: SkipModel,
};

View File

@ -1,17 +0,0 @@
import { CircleNode, CircleNodeModel } from "@logicflow/core";
class StartModel extends CircleNodeModel {
initNodeData(data) {
super.initNodeData(data);
this.r = 20
}
}
class StartView extends CircleNode {}
export default {
type: "start",
model: StartModel,
view: StartView,
};

View File

@ -1,356 +0,0 @@
/**
* 节点样式处理方法
* @param _this
* @param style
* @returns {*}
*/
export const nodeStyleHandle = (_this, style) => {
if (_this.properties.status === "pass") {
style.stroke = "green";
} else if (_this.properties.status === "reject") {
style.stroke = "#ffba00";
} else if (_this.properties.status === "approval") {
style.stroke = "red";
} else {
style.stroke = "#909399";
}
return style
}
/**
* 节点大小处理方法
* @param _this
* @param style
* @returns {*}
*/
export const nodeSizeHandle = (_this) => {
_this.width = 120;
_this.height = 80;
_this.radius = 5;
}
/**
* 节点大小处理方法
* @param _this
* @param style
* @returns {*}
*/
export const skipText = (skipType) => {
let text = ''
if (skipType && skipType === 'PASS') {
text = '审批通过'
} else if (skipType && skipType === 'REJECT') {
text = '退回'
}
return text
}
/**
* 解析xml成Dom对象
* @param {} xml
* @returns
*/
export const parseXml2Dom = (xml) => {
let xmlDoc = null
if (window.DOMParser) {
const parser = new DOMParser()
xmlDoc = parser.parseFromString(xml, 'text/xml')
} else { // Internet Explorer
// eslint-disable-next-line no-undef
xmlDoc = new ActiveXObject('Microsoft.XMLDOM')
xmlDoc.async = false
xmlDoc.loadXML(xml)
}
return xmlDoc
}
// 节点标签
const NODE_NAMES = ['start', 'between', 'serial', 'parallel', 'end']
// 流程节点属性
const DEFINITION_KEYS = ['flowCode', 'flowName', 'version', 'formCustom', 'formPath']
// 节点属性
const NODE_ATTR_KEYS = ['nodeType', 'nodeCode', 'nodeName', 'coordinate', 'nodeRatio', 'permissionFlag', "skipAnyNode"
, "listenerType", "listenerPath", "formCustom", "formPath"]
// 变迁节点属性
const SKIP_ATTR_KEYS = ['skipName', 'skipType', 'coordinate', 'skipCondition']
/**
* 将warm-flow的定义文件转成LogicFlow支持的数据格式
* @param {*} xml
* @returns
*/
export const snakerXml2LogicFlowJson = (xml) => {
const graphData = {
nodes: [],
edges: []
}
const xmlDoc = parseXml2Dom(xml)
const definitionDom = xmlDoc.getElementsByTagName('definition')
if (!definitionDom.length) {
return graphData
}
let value = null
// 解析definition属性
DEFINITION_KEYS.forEach(key => {
value = definitionDom[0].getAttribute(key)
if (value) {
graphData[key] = value
}
})
let nodeEles = null
let node = null
let lfNode = {}
// 解析节点
nodeEles = definitionDom[0].getElementsByTagName("node")
if (nodeEles.length) {
for (var i = 0, len = nodeEles.length; i < len; i++) {
node = nodeEles[i]
lfNode = {
text:{},
properties: {}
}
// 处理节点
NODE_ATTR_KEYS.forEach(attrKey => {
value = node.getAttribute(attrKey)
if (value) {
if (attrKey === 'nodeType') {
lfNode.type = value
} else if (attrKey === 'nodeCode') {
lfNode.id = value
} else if (attrKey === 'coordinate') {
const attr = value.split('|')
const nodeXy = attr[0].split(',')
lfNode.x = parseInt(nodeXy[0])
lfNode.y = parseInt(nodeXy[1])
if (attr.length === 2) {
const textXy = attr[1].split(',')
lfNode.text.x = parseInt(textXy[0])
lfNode.text.y = parseInt(textXy[1])
}
} else if (attrKey === 'nodeName') {
lfNode.text.value = value
} else {
lfNode.properties[attrKey] = value
}
}
})
graphData.nodes.push(lfNode)
// 处理边
let skipEles = null
let skipEle = null
let edge = {}
skipEles = node.getElementsByTagName('skip')
for (var j = 0, lenn = skipEles.length; j < lenn; j++) {
skipEle = skipEles[j]
edge = {
text: {},
properties: {},
}
edge.id = skipEle.getAttribute('id')
edge.type = 'skip'
edge.sourceNodeId = lfNode.id
edge.targetNodeId = skipEle.textContent
edge.text = {
value: skipEle.getAttribute('skipName')
}
edge.properties.skipCondition = skipEle.getAttribute('skipCondition')
edge.properties.skipName = skipEle.getAttribute('skipName')
edge.properties.skipType = skipEle.getAttribute('skipType')
const expr = skipEle.getAttribute('expr')
if (expr) {
edge.properties.expr = expr
}
const coordinate = skipEle.getAttribute('coordinate')
if (coordinate) {
const coordinateXy = coordinate.split('|')
edge.pointsList = []
coordinateXy[0].split(';').forEach((item) => {
const pointArr = item.split(',')
edge.pointsList.push({
x: parseInt(pointArr[0]),
y: parseInt(pointArr[1])
})
})
edge.startPoint = edge.pointsList[0]
edge.endPoint = edge.pointsList[edge.pointsList.length - 1]
if (coordinateXy.length > 1) {
let textXy = coordinateXy[1].split(",");
edge.text.x = parseInt(textXy[0])
edge.text.y = parseInt(textXy[1])
}
}
graphData.edges.push(edge)
}
}
}
return graphData
}
/**
* 将LogicFlow的数据转成warm-flow的定义文件
* @param {*} data(...definitionInfo,nodes,edges)
* @returns
*/
export const logicFlowJsonToFlowXml = (data) => {
let xml = ''
// data的数据由流程定义文件信息+logicFlow数据构成
// 先构建成流程对象
const definitionObj = {
flowCode: data.flowCode, // 流程定义编码
flowName: data.flowName, // 流程定义名称
version: data.version, // 流程定义版本号
formCustom: data.formCustom, // 表单自定义
formPath: data.formPath, // 表单自定义路径
}
/**
* 获取开始节点
* @returns
*/
const getStartNode = () => {
return data.nodes.find((node) => {
return node.type === 'start'
})
}
/**
* 获取当前节点的所有下一个节点集合
* @param {*} id 当前节点名称
* @returns
*/
const getNextNodes = (id) => {
return data.edges.filter(edge => {
return edge.sourceNodeId === id
}).map(edge => {
return data.nodes.find((node) => {
return node.id === edge.targetNodeId
})
})
}
/**
* 获取节点所有跳转
* @param {*} id
* @returns
*/
const getSkip = (id) => {
return data.edges.filter((edge) => {
return edge.sourceNodeId === id
}).map(edge => {
let coordinate = ''
for (let i = 0; i < edge.pointsList.length; i++) {
coordinate = coordinate + parseInt(edge.pointsList[i].x) + ',' + parseInt(edge.pointsList[i].y)
if (i !== edge.pointsList.length - 1) {
coordinate = coordinate + ';'
}
}
if (edge.text) {
coordinate = coordinate + '|' + parseInt(edge.text.x) + ',' + parseInt(edge.text.y)
}
return {
skipType: edge.properties.skipType,
skipCondition: edge.properties.skipCondition,
skipName: edge.properties.skipName,
textContent: edge.targetNodeId, // 目地节点id
coordinate: coordinate,
}
})
}
/**
* 构建节点属性
* @param {} node
* @returns
*/
const buildNode = (node) => {
let textXy = '';
if (node.text) {
textXy = '|' + node.text.x + ',' + node.text.y;
}
return {
nodeType: node.type,
nodeCode: node.id,
nodeName: (node.text instanceof String || node.text === undefined) ? node.text : node.text.value,
permissionFlag: node.properties.permissionFlag,
nodeRatio: node.properties.nodeRatio,
skipAnyNode: node.properties.skipAnyNode,
listenerType: node.properties.listenerType,
listenerPath: node.properties.listenerPath,
coordinate: node.x + ',' + node.y + textXy,
skip: getSkip(node.id),
formCustom: node.properties.formCustom,
formPath: node.properties.formPath,
}
}
/**
* 特殊字符转义
* @param {*} text
* @returns
*/
const textEncode = (text) => {
text = text.replace(/&/g, '&amp;')
.replace(/"/g, '&quot;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
return text
}
/**
* 递归构建节点属性
* @param {} node
*/
const recursionBuildNode = (node) => {
const nodeName = node.type
if (!definitionObj[nodeName + '_' + node.id]) {
definitionObj[nodeName + '_' + node.id] = buildNode(node)
const nextNodes = getNextNodes(node.id)
nextNodes.forEach(nextNode => {
recursionBuildNode(nextNode)
})
}
}
const startNode = getStartNode()
if (!startNode) {
// 开始节点不存在xml不合法
return ''
}
recursionBuildNode(startNode)
xml = '<?xml version="1.0" encoding="UTF-8"?>\n'
xml += '<definition'
Object.keys(definitionObj).forEach(key => {
const value = definitionObj[key]
if (DEFINITION_KEYS.includes(key) && value) {
xml += ' ' + key + '=' + '"' + textEncode(value) + '"'
}
})
xml += '>\n'
// 生成节点xml
Object.keys(definitionObj).forEach(key => {
const value = definitionObj[key]
let nodeName = key.split('_')[0]
if (NODE_NAMES.includes(nodeName)) {
xml += '\t<node'
// 构造属性
Object.keys(value).forEach(nodeAttrKey => {
if (NODE_ATTR_KEYS.includes(nodeAttrKey) && value[nodeAttrKey]) {
xml += ' ' + nodeAttrKey + '=' + '"' + textEncode(value[nodeAttrKey]) + '"'
}
})
xml += '>\n\t'
// 构建skip
if (value.skip) {
value.skip.forEach(skip => {
xml += '\t<skip'
// skip属性
Object.keys(skip).forEach(skipAttrKey => {
if (SKIP_ATTR_KEYS.includes(skipAttrKey) && skip[skipAttrKey]) {
xml += ' ' + skipAttrKey + '=' + '"' + textEncode(skip[skipAttrKey]) + '"'
}
})
xml += '>'
xml += skip['textContent'] + '</skip>\n'
})
}
xml += '\t</node>\n'
}
})
xml += '</definition>'
return xml
}

View File

@ -178,15 +178,15 @@ export const dynamicRoutes: RouteRecordRaw[] = [
]
},
{
path: '/workflow/modelDesign',
path: '/workflow/design',
component: Layout,
hidden: true,
permissions: ['workflow:leave:edit'],
children: [
{
path: 'index',
component: () => import('@/views/workflow/processDefinition/modelDesign.vue'),
name: 'modelDesign',
component: () => import('@/views/workflow/processDefinition/design.vue'),
name: 'design',
meta: { title: '请假申请', activeMenu: '/workflow/processDefinition', noCache: true }
}
]

View File

@ -59,7 +59,7 @@
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template #default="scope">
<el-button
v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'"
v-if="scope.row.status === '0' || scope.row.status === '9' || scope.row.status === '10'"
v-hasPermi="['workflow:leave:edit']"
size="small"
link
@ -69,7 +69,7 @@
>修改</el-button
>
<el-button
v-if="scope.row.status === 'draft' || scope.row.status === 'cancel' || scope.row.status === 'back'"
v-if="scope.row.status === '0' || scope.row.status === '9' || scope.row.status === '10'"
v-hasPermi="['workflow:leave:remove']"
size="small"
link
@ -80,7 +80,7 @@
>
<el-button link type="primary" size="small" icon="View" @click="handleView(scope.row)">查看</el-button>
<el-button
v-if="scope.row.status === 'waiting'"
v-if="scope.row.status === '1'"
link
size="small"
type="primary"

View File

@ -3,10 +3,10 @@
<el-card shadow="never">
<div style="display: flex; justify-content: space-between">
<div>
<el-button v-if="submitButtonShow" :loading="buttonLoading" type="info" @click="submitForm('draft')">暂存</el-button>
<el-button v-if="submitButtonShow" :loading="buttonLoading" type="info" @click="submitForm('0')">暂存</el-button>
<el-button v-if="submitButtonShow" :loading="buttonLoading" type="primary" @click="submitForm('submit')"> </el-button>
<el-button v-if="approvalButtonShow" :loading="buttonLoading" type="primary" @click="approvalVerifyOpen">审批</el-button>
<el-button v-if="form && form.id && form.status !== 'draft'" type="primary" @click="handleApprovalRecord">流程进度</el-button>
<el-button v-if="form && form.id && form.status !== '0'" type="primary" @click="handleApprovalRecord">流程进度</el-button>
</div>
<div>
<el-button style="float: right" @click="goBack()">返回</el-button>
@ -168,7 +168,7 @@ const submitForm = (status: string) => {
res = await addLeave(form.value);
}
form.value = res.data;
if (status === 'draft') {
if (status === '0') {
buttonLoading.value = false;
proxy?.$modal.msgSuccess('暂存成功');
proxy.$tab.closePage(proxy.$route);
@ -192,8 +192,8 @@ const handleStartWorkFlow = async (data: LeaveVO) => {
taskVariables.value = {
entity: data,
leaveDays: data.leaveDays,
userList: ["1", "3"],
userList2: ["1", "3"]
userList: ['1', '3'],
userList2: ['1', '3']
};
submitFormData.value.variables = taskVariables.value;
const resp = await startWorkFlow(submitFormData.value);
@ -230,13 +230,13 @@ const submitButtonShow = computed(() => {
routeParams.value.type === 'add' ||
(routeParams.value.type === 'update' &&
form.value.status &&
(form.value.status === 'draft' || form.value.status === 'cancel' || form.value.status === 'back'))
(form.value.status === '0' || form.value.status === '9' || form.value.status === '10'))
);
});
//
const approvalButtonShow = computed(() => {
return routeParams.value.type === 'approval' && form.value.status && form.value.status === 'waiting';
return routeParams.value.type === 'approval' && form.value.status && form.value.status === '1';
});
onMounted(() => {

View File

@ -0,0 +1,52 @@
<template>
<div ref="container" class="container">
<iframe ref="iframe" :src="iframeUrl" frameborder="0" width="100%" height="100%"></iframe>
</div>
</template>
<script setup name="WarmFlow">
const { proxy } = getCurrentInstance();
import { onMounted } from 'vue';
// definitionIdid
// disabled,
const iframeUrl = ref('');
const disabled = ref(false);
const iframeLoaded = () => {
// iframe
window.onmessage = (event) => {
switch (event.data.method) {
case 'close':
close();
break;
}
};
};
const open = async (definitionId) => {
iframeUrl.value = `http://localhost:8080/warm-flow-ui/${definitionId}`;
console.log(iframeUrl.value);
};
/** 关闭按钮 */
function close() {
const obj = { path: '/workflow/processDefinition' };
proxy.$tab.closeOpenPage(obj);
}
onMounted(() => {
iframeLoaded();
open(proxy.$route.query.definitionId);
});
/**
* 对外暴露子组件方法
*/
defineExpose({
open
});
</script>
<style scoped>
.container {
width: 100%;
height: calc(100vh - 84px);
}
</style>

View File

@ -104,16 +104,16 @@
历史版本
</el-button>
</el-col>
<el-col :span="1.5">
<el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
</el-col>
</el-row>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button link type="primary" size="small" icon="Tickets" @click="handleDefinitionConfigOpen(scope.row)">绑定业务</el-button>
</el-col>
<el-col :span="1.5">
<el-button link type="primary" size="small" icon="Delete" @click="handleDelete(scope.row)">删除</el-button>
</el-col>
<el-col :span="1.5">
<el-button link type="primary" icon="Delete" size="small" @click="design(scope.row)">设计</el-button>
<el-button link type="primary" icon="Pointer" size="small" @click="design(scope.row)">流程设计</el-button>
</el-col>
</el-row>
</template>
@ -261,11 +261,9 @@
<script lang="ts" setup name="processDefinition">
import {
listDefinition,
definitionImage,
definitionXml,
deleteDefinition,
updateDefinitionState,
convertToModel,
importDefinition,
getHisListByKey,
publish,
@ -305,6 +303,7 @@ const processDefinitionList = ref<FlowDefinitionVo[]>([]);
const processDefinitionHistoryList = ref<FlowDefinitionVo[]>([]);
const categoryOptions = ref<CategoryOption[]>([]);
const categoryName = ref('');
const disabled = ref(true);
/** 部署文件分类选择 */
const selectCategory = ref();
@ -539,9 +538,9 @@ const handlerSaveForm = async () => {
};
const design = async (row: FlowDefinitionVo) => {
proxy.$router.push({
path: `/workflow/modelDesign/index`,
path: `/workflow/design/index`,
query: {
id: row.id
definitionId: row.id
}
});
};

View File

@ -1,287 +0,0 @@
<template>
<div ref="container" class="container">
<PropertySetting
ref="propertySetting"
v-model="processForm"
:node="nodeClick"
:lf="lf"
:disabled="disabled"
:skip-condition-show="skipConditionShow"
>
<template v-for="(item, key) in $slots" #[key]="data">
<slot :name="key" v-bind="data || {}"></slot>
</template>
</PropertySetting>
</div>
</template>
<script>
import LogicFlow from '@logicflow/core';
import '@logicflow/core/dist/style/index.css';
import { Control, DndPanel, Menu, SelectionSelect } from '@logicflow/extension';
import '@logicflow/extension/lib/style/index.css';
import Start from '@/components/WarmFlow/js/start';
import Between from '@/components/WarmFlow/js/between';
import Serial from '@/components/WarmFlow/js/serial';
import Parallel from '@/components/WarmFlow/js/parallel';
import End from '@/components/WarmFlow/js/end';
import Skip from '@/components/WarmFlow/js/skip';
import PropertySetting from '@/components/WarmFlow/PropertySetting/index.vue';
import { xmlString } from '@/api/workflow/definition';
import { logicFlowJsonToFlowXml, skipText, snakerXml2LogicFlowJson } from '@/components/WarmFlow/js/tool';
export default {
name: 'Design',
components: {
PropertySetting
},
data() {
return {
lf: null,
nodeClick: null,
//
disabled: false,
processForm: {},
value: {},
xmlString: '',
skipConditionShow: true
};
},
created() {
this.definitionId = this.$route.query.id && this.$route.query.id;
if (this.$route.query.disabled == 'true') {
this.disabled = true;
}
},
mounted() {
this.use();
this.lf = new LogicFlow({ container: this.$refs.container, grid: true });
this.register();
this.initDndPanel();
this.initControl();
this.initMenu();
this.initEvent();
if (this.definitionId) {
xmlString(this.definitionId).then((res) => {
this.xmlString = res.data;
if (this.xmlString) {
this.value = snakerXml2LogicFlowJson(this.xmlString);
this.lf.render(this.value);
}
});
}
},
methods: {
/**
* 初始化拖拽面板
*/
initDndPanel() {
this.lf.extension.dndPanel.setPatternItems([
{
type: 'start',
text: '开始',
label: '开始节点',
icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAAH6ji2bAAAABGdBTUEAALGPC/xhBQAAAnBJREFUOBGdVL1rU1EcPfdGBddmaZLiEhdx1MHZQXApraCzQ7GKLgoRBxMfcRELuihWKcXFRcEWF8HBf0DdDCKYRZpnl7p0svLe9Zzbd29eQhTbC8nv+9zf130AT63jvooOGS8Vf9Nt5zxba7sXQwODfkWpkbjTQfCGUd9gIp3uuPP8bZ946g56dYQvnBg+b1HB8VIQmMFrazKcKSvFW2dQTxJnJdQ77urmXWOMBCmXM2Rke4S7UAW+/8ywwFoewmBps2tu7mbTdp8VMOkIRAkKfrVawalJTtIliclFbaOBqa0M2xImHeVIfd/nKAfVq/LGnPss5Kh00VEdSzfwnBXPUpmykNss4lUI9C1ga+8PNrBD5YeqRY2Zz8PhjooIbfJXjowvQJBqkmEkVnktWhwu2SM7SMx7Cj0N9IC0oQXRo8xwAGzQms+xrB/nNSUWVveI48ayrFGyC2+E2C+aWrZHXvOuz+CiV6iycWe1Rd1Q6+QUG07nb5SbPrL4426d+9E1axKjY3AoRrlEeSQo2Eu0T6BWAAr6COhTcWjRaYfKG5csnvytvUr/WY4rrPMB53Uo7jZRjXaG6/CFfNMaXEu75nG47X+oepU7PKJvvzGDY1YLSKHJrK7vFUwXKkaxwhCW3u+sDFMVrIju54RYYbFKpALZAo7sB6wcKyyrd+aBMryMT2gPyD6GsQoRFkGHr14TthZni9ck0z+Pnmee460mHXbRAypKNy3nuMdrWgVKj8YVV8E7PSzp1BZ9SJnJAsXdryw/h5ctboUVi4AFiCd+lQaYMw5z3LGTBKjLQOeUF35k89f58Vv/tGh+l+PE/wG0rgfIUbZK5AAAAABJRU5ErkJggg=='
},
{
type: 'between',
text: '中间节点-或签',
label: '中间节点-或签',
icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAEFVwZaAAAABGdBTUEAALGPC/xhBQAAAqlJREFUOBF9VM9rE0EUfrMJNUKLihGbpLGtaCOIR8VjQMGDePCgCCIiCNqzCAp2MyYUCXhUtF5E0D+g1t48qAd7CCLqQUQKEWkStcEfVGlLdp/fm3aW2QQdyLzf33zz5m2IsAZ9XhDpyaaIZkTS4ASzK41TFao88GuJ3hsr2pAbipHxuSYyKRugagICGANkfFnNh3HeE2N0b3nN2cgnpcictw5veJIzxmDamSlxxQZicq/mflxhbaH8BLRbuRwNtZp0JAhoplVRUdzmCe/vO27wFuuA3S5qXruGdboy5/PRGFsbFGKo/haRtQHIrM83bVeTrOgNhZReWaYGnE4aUQgTJNvijJFF4jQ8BxJE5xfKatZWmZcTQ+BVgh7s8SgPlCkcec4mGTmieTP4xd7PcpIEg1TX6gdeLW8rTVMVLVvb7ctXoH0Cydl2QOPJBG21STE5OsnbweVYzAnD3A7PVILuY0yiiyDwSm2g441r6rMSgp6iK42yqroI2QoXeJVeA+YeZSa47gZdXaZWQKTrG93rukk/l2Al6Kzh5AZEl7dDQy+JjgFahQjRopSxPbrbvK7GRe9ePWBo1wcU7sYrFZtavXALwGw/7Dnc50urrHJuTPSoO2IMV3gUQGNg87IbSOIY9BpiT9HV7FCZ94nPXb3MSnwHn/FFFE1vG6DTby+r31KAkUktB3Qf6ikUPWxW1BkXSPQeMHHiW0+HAd2GelJsZz1OJegCxqzl+CLVHa/IibuHeJ1HAKzhuDR+ymNaRFM+4jU6UWKXorRmbyqkq/D76FffevwdCp+jN3UAN/C9JRVTDuOxC/oh+EdMnqIOrlYteKSfadVRGLJFJPSB/ti/6K8f0CNymg/iH2gO/f0DwE0yjAFO6l8JaR5j0VPwPwfaYHqOqrCI319WzwhwzNW/aQAAAABJRU5ErkJggg==',
className: 'important-node',
properties: { collaborativeWay: '1' }
},
{
type: 'between',
text: '中间节点-票签',
label: '中间节点-票签',
icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAEFVwZaAAAABGdBTUEAALGPC/xhBQAAAqlJREFUOBF9VM9rE0EUfrMJNUKLihGbpLGtaCOIR8VjQMGDePCgCCIiCNqzCAp2MyYUCXhUtF5E0D+g1t48qAd7CCLqQUQKEWkStcEfVGlLdp/fm3aW2QQdyLzf33zz5m2IsAZ9XhDpyaaIZkTS4ASzK41TFao88GuJ3hsr2pAbipHxuSYyKRugagICGANkfFnNh3HeE2N0b3nN2cgnpcictw5veJIzxmDamSlxxQZicq/mflxhbaH8BLRbuRwNtZp0JAhoplVRUdzmCe/vO27wFuuA3S5qXruGdboy5/PRGFsbFGKo/haRtQHIrM83bVeTrOgNhZReWaYGnE4aUQgTJNvijJFF4jQ8BxJE5xfKatZWmZcTQ+BVgh7s8SgPlCkcec4mGTmieTP4xd7PcpIEg1TX6gdeLW8rTVMVLVvb7ctXoH0Cydl2QOPJBG21STE5OsnbweVYzAnD3A7PVILuY0yiiyDwSm2g441r6rMSgp6iK42yqroI2QoXeJVeA+YeZSa47gZdXaZWQKTrG93rukk/l2Al6Kzh5AZEl7dDQy+JjgFahQjRopSxPbrbvK7GRe9ePWBo1wcU7sYrFZtavXALwGw/7Dnc50urrHJuTPSoO2IMV3gUQGNg87IbSOIY9BpiT9HV7FCZ94nPXb3MSnwHn/FFFE1vG6DTby+r31KAkUktB3Qf6ikUPWxW1BkXSPQeMHHiW0+HAd2GelJsZz1OJegCxqzl+CLVHa/IibuHeJ1HAKzhuDR+ymNaRFM+4jU6UWKXorRmbyqkq/D76FffevwdCp+jN3UAN/C9JRVTDuOxC/oh+EdMnqIOrlYteKSfadVRGLJFJPSB/ti/6K8f0CNymg/iH2gO/f0DwE0yjAFO6l8JaR5j0VPwPwfaYHqOqrCI319WzwhwzNW/aQAAAABJRU5ErkJggg==',
className: 'important-node',
properties: { collaborativeWay: '2' }
},
{
type: 'between',
text: '中间节点-会签',
label: '中间节点-会签',
icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAEFVwZaAAAABGdBTUEAALGPC/xhBQAAAqlJREFUOBF9VM9rE0EUfrMJNUKLihGbpLGtaCOIR8VjQMGDePCgCCIiCNqzCAp2MyYUCXhUtF5E0D+g1t48qAd7CCLqQUQKEWkStcEfVGlLdp/fm3aW2QQdyLzf33zz5m2IsAZ9XhDpyaaIZkTS4ASzK41TFao88GuJ3hsr2pAbipHxuSYyKRugagICGANkfFnNh3HeE2N0b3nN2cgnpcictw5veJIzxmDamSlxxQZicq/mflxhbaH8BLRbuRwNtZp0JAhoplVRUdzmCe/vO27wFuuA3S5qXruGdboy5/PRGFsbFGKo/haRtQHIrM83bVeTrOgNhZReWaYGnE4aUQgTJNvijJFF4jQ8BxJE5xfKatZWmZcTQ+BVgh7s8SgPlCkcec4mGTmieTP4xd7PcpIEg1TX6gdeLW8rTVMVLVvb7ctXoH0Cydl2QOPJBG21STE5OsnbweVYzAnD3A7PVILuY0yiiyDwSm2g441r6rMSgp6iK42yqroI2QoXeJVeA+YeZSa47gZdXaZWQKTrG93rukk/l2Al6Kzh5AZEl7dDQy+JjgFahQjRopSxPbrbvK7GRe9ePWBo1wcU7sYrFZtavXALwGw/7Dnc50urrHJuTPSoO2IMV3gUQGNg87IbSOIY9BpiT9HV7FCZ94nPXb3MSnwHn/FFFE1vG6DTby+r31KAkUktB3Qf6ikUPWxW1BkXSPQeMHHiW0+HAd2GelJsZz1OJegCxqzl+CLVHa/IibuHeJ1HAKzhuDR+ymNaRFM+4jU6UWKXorRmbyqkq/D76FffevwdCp+jN3UAN/C9JRVTDuOxC/oh+EdMnqIOrlYteKSfadVRGLJFJPSB/ti/6K8f0CNymg/iH2gO/f0DwE0yjAFO6l8JaR5j0VPwPwfaYHqOqrCI319WzwhwzNW/aQAAAABJRU5ErkJggg==',
className: 'important-node',
properties: { collaborativeWay: '3' }
},
{
type: 'serial',
text: '',
label: '互斥网关',
properties: {},
icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAYAAAHeEJUAAAAABGdBTUEAALGPC/xhBQAAAvVJREFUOBGNVEFrE0EU/mY3bQoiFlOkaUJrQUQoWMGePLX24EH0IIoHKQiCV0G8iE1covgLiqA/QTzVm1JPogc9tIJYFaQtlhQxqYjSpunu+L7JvmUTU3AgmTfvffPNN++9WSA1DO182f6xwILzD5btfAoQmwL5KJEwiQyVbSVZ0IgRyV6PTpIJ81E5ZvqfHQR0HUOBHW4L5Et2kQ6Zf7iAOhTFAA8s0pEP7AXO1uAA52SbqGk6h/6J45LaLhO64ByfcUzM39V7ZiAdS2yCePPEIQYvTUHqM/n7dgQNfBKWPjpF4ISk8q3J4nB11qw6X8l+FsF3EhlkEMfrjIer3wJTLwS2aCNcj4DbGxXTw00JmAuO+Ni6bBxVUCvS5d9aa04+so4pHW5jLTywuXAL7jJ+D06sl82Sgl2JuVBQn498zkc2bGKxULHjCnSMadBKYDYYHAtsby1EQ5lNGrQd4Y3v4Zo0XdGEmDno46yCM9Tk+RiJmUYHS/aXHPNTcjxcbTFna000PFJHIVZ5lFRqRpJWk9/+QtlOUYJj9HG5pVFEU7zqIYDVsw2s+AJaD8wTd2umgSCCyUxgGsS1Y6TBwXQQTFuZaHcd8gAGioE90hlsY+wMcs30RduYtxanjMGal8H5dMW67dmT1JFtYUEe8LiQLRsPZ6IIc7A4J5tqco3T0pnv/4u0kyzrYUq7gASuEyI8VXKvB9Odytv6jS/PNaZBln0nioJG/AVQRZvApOdhjj3Jt8QC8Im09SafwdBdvIpztpxWxpeKCC+EsFdS8DCyuCn2munFpL7ctHKp+Xc5cMybeIyMAN33SPL3ZR9QV1XVwLyzHm6Iv0/yeUuUb7PPlZC4D4HZkeu6dpF4v9j9MreGtMbxMMRLIcjJic9yHi7WQ3yVKzZVWUr5UrViJvn1FfUlwe/KYVfYyWRLSGNu16hR01U9IacajXPei0wx/5BqgInvJN+MMNtNme7ReU9SBbgntovn0kKHpFg7UogZvaZiOue/q1SBo9ktHzQAAAAASUVORK5CYII='
},
{
type: 'parallel',
text: '',
label: '并行网关',
properties: {},
icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAVCAYAAAHeEJUAAAAABGdBTUEAALGPC/xhBQAAAvVJREFUOBGNVEFrE0EU/mY3bQoiFlOkaUJrQUQoWMGePLX24EH0IIoHKQiCV0G8iE1covgLiqA/QTzVm1JPogc9tIJYFaQtlhQxqYjSpunu+L7JvmUTU3AgmTfvffPNN++9WSA1DO182f6xwILzD5btfAoQmwL5KJEwiQyVbSVZ0IgRyV6PTpIJ81E5ZvqfHQR0HUOBHW4L5Et2kQ6Zf7iAOhTFAA8s0pEP7AXO1uAA52SbqGk6h/6J45LaLhO64ByfcUzM39V7ZiAdS2yCePPEIQYvTUHqM/n7dgQNfBKWPjpF4ISk8q3J4nB11qw6X8l+FsF3EhlkEMfrjIer3wJTLwS2aCNcj4DbGxXTw00JmAuO+Ni6bBxVUCvS5d9aa04+so4pHW5jLTywuXAL7jJ+D06sl82Sgl2JuVBQn498zkc2bGKxULHjCnSMadBKYDYYHAtsby1EQ5lNGrQd4Y3v4Zo0XdGEmDno46yCM9Tk+RiJmUYHS/aXHPNTcjxcbTFna000PFJHIVZ5lFRqRpJWk9/+QtlOUYJj9HG5pVFEU7zqIYDVsw2s+AJaD8wTd2umgSCCyUxgGsS1Y6TBwXQQTFuZaHcd8gAGioE90hlsY+wMcs30RduYtxanjMGal8H5dMW67dmT1JFtYUEe8LiQLRsPZ6IIc7A4J5tqco3T0pnv/4u0kyzrYUq7gASuEyI8VXKvB9Odytv6jS/PNaZBln0nioJG/AVQRZvApOdhjj3Jt8QC8Im09SafwdBdvIpztpxWxpeKCC+EsFdS8DCyuCn2munFpL7ctHKp+Xc5cMybeIyMAN33SPL3ZR9QV1XVwLyzHm6Iv0/yeUuUb7PPlZC4D4HZkeu6dpF4v9j9MreGtMbxMMRLIcjJic9yHi7WQ3yVKzZVWUr5UrViJvn1FfUlwe/KYVfYyWRLSGNu16hR01U9IacajXPei0wx/5BqgInvJN+MMNtNme7ReU9SBbgntovn0kKHpFg7UogZvaZiOue/q1SBo9ktHzQAAAAASUVORK5CYII='
},
{
type: 'end',
text: '结束',
label: '结束节点',
icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAYAAAH6ji2bAAAABGdBTUEAALGPC/xhBQAAA1BJREFUOBFtVE1IVUEYPXOf+tq40Y3vPcmFIdSjIorWoRG0ERWUgnb5FwVhYQSl72oUoZAboxKNFtWiwKRN0M+jpfSzqJAQclHo001tKkjl3emc8V69igP3znzfnO/M9zcDcKT67azmjYWTwl9Vn7Vumeqzj1DVb6cleQY4oAVnIOPb+mKAGxQmKI5CWNJ2aLPatxWa3aB9K7/fB+/Z0jUF6TmMlFLQqrkECWQzOZxYGjTlOl8eeKaIY5yHnFn486xBustDjWT6dG7pmjHOJd+33t0iitTPkK6tEvjxq4h2MozQ6WFSX/LkDUGfFwfhEZj1Auz/U4pyAi5Sznd7uKzznXeVHlI/Aywmk6j7fsUsEuCGADrWARXXwjxWQsUbIupDHJI7kF5dRktg0eN81IbiZXiTESic50iwS+t1oJgL83jAiBupLDCQqwziaWSoAFSeIR3P5Xv5az00wyIn35QRYTwdSYbz8pH8fxUUAtxnFvYmEmgI0wYXUXcCCSpeEVpXlsRhBnCEATxWylL9+EKCAYhe1NGstUa6356kS9NVvt3DU2fd+Wtbm/+lSbylJqsqkSm9CRhvoJVlvKPvF1RKY/FcPn5j4UfIMLn8D4UYb54BNsilTDXKnF4CfTobA0FpoW/LSp306wkXM+XaOJhZaFkcNM82ASNAWMrhrUbRfmyeI1FvRBTpN06WKxa9BK0o2E4Pd3zfBBEwPsv9sQBnmLVbLEIZ/Xe9LYwJu/Er17W6HYVBc7vmuk0xUQ+pqxdom5Fnp55SiytXLPYoMXNM4u4SNSCFWnrVIzKG3EGyMXo6n/BQOe+bX3FClY4PwydVhthOZ9NnS+ntiLh0fxtlUJHAuGaFoVmttpVMeum0p3WEXbcll94l1wM/gZ0Ccczop77VvN2I7TlsZCsuXf1WHvWEhjO8DPtyOVg2/mvK9QqboEth+7pD6NUQC1HN/TwvydGBARi9MZSzLE4b8Ru3XhX2PBxf8E1er2A6516o0w4sIA+lwURhAON82Kwe2iDAC1Watq4XHaGQ7skLcFOtI5lDxuM2gZe6WFIotPAhbaeYlU4to5cuarF1QrcZ/lwrLaCJl66JBocYZnrNlvm2+MBCTmUymPrYZVbjdlr/BxlMjmNmNI3SAAAAAElFTkSuQmCC'
}
]);
},
/**
* 初始化控制面板
*/
initControl() {
if (!this.disabled) {
// -
this.lf.extension.control.addItem({
iconClass: 'lf-control-clear',
title: 'clear',
text: '清空',
onClick: (lf, ev) => {
lf.clearData();
}
});
// -
this.lf.extension.control.addItem({
iconClass: 'lf-control-save',
title: '',
text: '保存',
onClick: (lf, ev) => {
this.graphData = lf.getGraphData();
this.value['nodes'] = this.graphData['nodes'];
this.value['edges'] = this.graphData['edges'];
console.log('this.value:', this.value);
let xmlString = logicFlowJsonToFlowXml(this.value);
console.log('this.xmlString:', xmlString);
let data = {
xmlString: xmlString,
id: this.definitionId
};
// saveXml(data).then((response) => {
// this.$modal.msgSuccess('');
// if (response.code === 200) {
// this.close();
// }
// });
}
});
}
},
/**
* 初始化菜单
*/
initMenu() {
// lf.render()
this.lf.extension.menu.addMenuConfig({
nodeMenu: [
{
text: '属性',
callback(node) {
alert(`
节点id${node.id}
节点类型${node.type}
节点坐标(x: ${node.x}, y: ${node.y})
文本坐标(x: ${node.text.x}, y: ${node.text.y})`);
}
}
],
edgeMenu: [
{
text: '属性',
callback(edge) {
alert(`
边id${edge.id}
边类型${edge.type}
边坐标(x: ${edge.x}, y: ${edge.y})
文本坐标(x: ${edge.text.x}, y: ${edge.text.y})
源节点id${edge.sourceNodeId}
目标节点id${edge.targetNodeId}`);
}
}
]
});
},
/**
* 注册自定义节点和边
*/
register() {
this.lf.register(Start);
this.lf.register(Between);
this.lf.register(Serial);
this.lf.register(Parallel);
this.lf.register(End);
this.lf.register(Skip);
},
/**
* 添加扩展
*/
use() {
LogicFlow.use(DndPanel);
LogicFlow.use(SelectionSelect);
LogicFlow.use(Control);
LogicFlow.use(Menu);
},
initEvent() {
const { eventCenter } = this.lf.graphModel;
eventCenter.on('node:click', (args) => {
this.nodeClick = args.data;
this.$nextTick(() => {
this.$refs.propertySetting.show();
});
});
eventCenter.on('edge:click', (args) => {
this.nodeClick = args.data;
const nodeModel = this.lf.getNodeModelById(this.nodeClick.sourceNodeId);
this.skipConditionShow = nodeModel.type === 'serial';
this.$nextTick(() => {
this.$refs.propertySetting.show(nodeModel.nodeType === 'serial');
});
});
eventCenter.on('edge:add', (args) => {
this.lf.changeEdgeType(args.data.id, 'skip');
//
this.lf.setProperties(args.data.id, {
skipType: 'PASS'
});
});
eventCenter.on('blank:click', (args) => {
this.nodeClick = null;
this.$nextTick(() => {
this.$refs.propertySetting.handleClose();
});
});
},
/** 关闭按钮 */
close() {
const obj = { path: '/flow/definition', query: { t: Date.now(), pageNum: this.$route.query.pageNum } };
this.$tab.closeOpenPage(obj);
}
}
};
</script>
<style scoped>
.container {
width: 100%;
height: 800px;
}
</style>
<style>
.lf-control-see {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNjQ1NjgyNDM0MzQxIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjEzNzgiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNNTEyIDE3MS4yODM2OTJjLTI1NS4wNTQ3NjkgMC00ODUuOTI3Mzg1IDMxMi40MzgxNTQtNDk2Ljc5NzUzOCAzMjcuMzI1NTM4bDAgMC42MzAxNTRDMjYuMDcyNjE1IDUxNC4xMjY3NjkgMjU2Ljk0NTIzMSA4MjYuNDg2MTU0IDUxMiA4MjYuNDg2MTU0YzI1NS4wMTUzODUgMCA0ODUuODg4LTMxMi4zOTg3NjkgNDk2Ljc5NzUzOC0zMjcuMzI1NTM4bDAtMC42MzAxNTRDOTk3LjkyNzM4NSA0ODMuNjgyNDYyIDc2Ny4wMTUzODUgMTcxLjI4MzY5MiA1MTIgMTcxLjI4MzY5Mkw1MTIgMTcxLjI4MzY5MnpNNTEyIDI5MS4yMDk4NDZjMTE0LjU2OTg0NiAwIDIwNy43NTM4NDYgOTMuMTA1MjMxIDIwNy43NTM4NDYgMjA3LjY3NTA3N1M2MjYuNTY5ODQ2IDcwNi42Mzg3NjkgNTEyIDcwNi42Mzg3NjljLTExNC41MzA0NjIgMC0yMDcuNzUzODQ2LTkzLjE4NC0yMDcuNzUzODQ2LTIwNy43NTM4NDZTMzk3LjQ2OTUzOCAyOTEuMjA5ODQ2IDUxMiAyOTEuMjA5ODQ2TTUxMiAzOTUuMjI0NjE1Yy01Ny4yNjUyMzEgMC0xMDMuNjYwMzA4IDQ2LjQzNDQ2Mi0xMDMuNjYwMzA4IDEwMy42NjAzMDhzNDYuMzk1MDc3IDEwMy42NjAzMDggMTAzLjY2MDMwOCAxMDMuNjYwMzA4YzU3LjIyNTg0NiAwIDEwMy42MjA5MjMtNDYuNDM0NDYyIDEwMy42MjA5MjMtMTAzLjY2MDMwOFM1NjkuMjI1ODQ2IDM5NS4yMjQ2MTUgNTEyIDM5NS4yMjQ2MTV6IiBwLWlkPSIxMzc5Ij48L3BhdGg+PC9zdmc+');
}
.lf-control-save {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNjQ1Nzg5MTgwOTgzIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjI4NDMiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNNDI2LjY2NjY2NyAxMjhoLTE0OS4zMzMzMzR2MjM0LjQ1MzMzM2MwIDEyLjA3NDY2NyA5LjQ1MDY2NyAyMS41NDY2NjcgMjEuMjA1MzM0IDIxLjU0NjY2N2gyOTguOTIyNjY2YzExLjYyNjY2NyAwIDIxLjIwNTMzMy05LjYgMjEuMjA1MzM0LTIxLjU0NjY2N1YxMjhoLTY0djE0OS41MDRjMCAyMy40NjY2NjctMTkuMTU3MzMzIDQyLjQ5Ni00Mi42MjQgNDIuNDk2aC00Mi43NTJBNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMSA0MjYuNjY2NjY3IDI3Ny41MDRWMTI4ek0xOTIgODk2VjY2MS41NDY2NjdDMTkyIDYwMi40NzQ2NjcgMjM5Ljc4NjY2NyA1NTQuNjY2NjY3IDI5OC44MzczMzMgNTU0LjY2NjY2N2g0MjYuMzI1MzM0QTEwNi43MDkzMzMgMTA2LjcwOTMzMyAwIDAgMSA4MzIgNjYxLjU0NjY2N1Y4OTZoNDIuNTE3MzMzQTIxLjMxMiAyMS4zMTIgMCAwIDAgODk2IDg3NC43NTJWMjczLjY2NEw3NTAuMzM2IDEyOEg3MDR2MjM0LjQ1MzMzM2MwIDU4Ljk2NTMzMy00Ny43MDEzMzMgMTA2Ljg4LTEwNi41Mzg2NjcgMTA2Ljg4SDI5OC41Mzg2NjdBMTA2LjU2IDEwNi41NiAwIDAgMSAxOTIgMzYyLjQ1MzMzM1YxMjhIMTQ5LjI0OEEyMS4yNjkzMzMgMjEuMjY5MzMzIDAgMCAwIDEyOCAxNDkuNDgyNjY3djcyNS4wMzQ2NjZDMTI4IDg4Ni40MjEzMzMgMTM3LjU3ODY2NyA4OTYgMTQ5LjQ4MjY2NyA4OTZIMTkyek00Mi42NjY2NjcgMTQ5LjQ4MjY2N0ExMDYuNjAyNjY3IDEwNi42MDI2NjcgMCAwIDEgMTQ5LjI0OCA0Mi42NjY2NjdINzY4YTQyLjY2NjY2NyA0Mi42NjY2NjcgMCAwIDEgMzAuMTY1MzMzIDEyLjUwMTMzM2wxNzAuNjY2NjY3IDE3MC42NjY2NjdBNDIuNjY2NjY3IDQyLjY2NjY2NyAwIDAgMSA5ODEuMzMzMzMzIDI1NnY2MTguNzUyQTEwNi42NDUzMzMgMTA2LjY0NTMzMyAwIDAgMSA4NzQuNTE3MzMzIDk4MS4zMzMzMzNIMTQ5LjQ4MjY2N0ExMDYuNzUyIDEwNi43NTIgMCAwIDEgNDIuNjY2NjY3IDg3NC41MTczMzNWMTQ5LjQ4MjY2N3ogbTcwNCA1MTIuMDQyNjY2YzAtMTIuMDEwNjY3LTkuNTM2LTIxLjUyNTMzMy0yMS41MDQtMjEuNTI1MzMzSDI5OC44MzczMzNDMjg2LjkzMzMzMyA2NDAgMjc3LjMzMzMzMyA2NDkuNiAyNzcuMzMzMzMzIDY2MS41NDY2NjdWODk2aDQ2OS4zMzMzMzRWNjYxLjU0NjY2N3oiIGZpbGw9IiMwMDAwMDAiIHAtaWQ9IjI4NDQiPjwvcGF0aD48L3N2Zz4=');
}
.lf-control-clear {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBzdGFuZGFsb25lPSJubyI/PjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+PHN2ZyB0PSIxNjQ1Nzg5MTYyODczIiBjbGFzcz0iaWNvbiIgdmlld0JveD0iMCAwIDEwMjQgMTAyNCIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHAtaWQ9IjIwNDYiIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCI+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48L3N0eWxlPjwvZGVmcz48cGF0aCBkPSJNODk5LjEgODY5LjZsLTUzLTMwNS42SDg2NGMxNC40IDAgMjYtMTEuNiAyNi0yNlYzNDZjMC0xNC40LTExLjYtMjYtMjYtMjZINjE4VjEzOGMwLTE0LjQtMTEuNi0yNi0yNi0yNkg0MzJjLTE0LjQgMC0yNiAxMS42LTI2IDI2djE4MkgxNjBjLTE0LjQgMC0yNiAxMS42LTI2IDI2djE5MmMwIDE0LjQgMTEuNiAyNiAyNiAyNmgxNy45bC01MyAzMDUuNmMtMC4zIDEuNS0wLjQgMy0wLjQgNC40IDAgMTQuNCAxMS42IDI2IDI2IDI2aDcyM2MxLjUgMCAzLTAuMSA0LjQtMC40IDE0LjItMi40IDIzLjctMTUuOSAyMS4yLTMwek0yMDQgMzkwaDI3MlYxODJoNzJ2MjA4aDI3MnYxMDRIMjA0VjM5MHogbTQ2OCA0NDBWNjc0YzAtNC40LTMuNi04LTgtOGgtNDhjLTQuNCAwLTggMy42LTggOHYxNTZINDE2VjY3NGMwLTQuNC0zLjYtOC04LThoLTQ4Yy00LjQgMC04IDMuNi04IDh2MTU2SDIwMi44bDQ1LjEtMjYwSDc3Nmw0NS4xIDI2MEg2NzJ6IiBwLWlkPSIyMDQ3Ij48L3BhdGg+PC9zdmc+');
}
</style>

View File

@ -133,11 +133,6 @@
</template>
</el-table-column>
<el-table-column align="center" prop="deploymentTime" label="部署时间" :show-overflow-tooltip="true"></el-table-column>
<el-table-column fixed="right" label="操作" align="center" width="200" class-name="small-padding fixed-width">
<template #default="scope">
<el-button link type="primary" size="small" icon="Sort" @click="handleChange(scope.row.id)">切换</el-button>
</template>
</el-table-column>
</el-table>
</el-dialog>
</div>
@ -151,7 +146,6 @@ import {
deleteFinishAndHisInstance,
deleteRunInstance
} from '@/api/workflow/processInstance';
import { migrationDefinition } from '@/api/workflow/definition';
import { listCategory } from '@/api/workflow/category';
import { CategoryVO } from '@/api/workflow/category/types';
import { ProcessInstanceQuery, ProcessInstanceVO } from '@/api/workflow/processInstance/types';
@ -321,17 +315,6 @@ const handleInvalid = async (row: ProcessInstanceVO) => {
const cancelPopover = async (index: any) => {
(proxy?.$refs[`popoverRef${index}`] as any).hide(); //
};
//
const handleChange = async (id: string) => {
await proxy?.$modal.confirm('是否确认切换?');
loading.value = true;
migrationDefinition(processDefinitionId.value, id).then((resp) => {
proxy?.$modal.msgSuccess('操作成功');
getProcessInstanceRunningList();
processDefinitionDialog.visible = false;
loading.value = false;
});
};
/** 查看按钮操作 */
const handleView = (row) => {
const routerJumpVo = reactive<RouterJumpVo>({

View File

@ -262,7 +262,7 @@ const handleView = (row) => {
const routerJumpVo = reactive<RouterJumpVo>({
wfDefinitionConfigVo: row.wfDefinitionConfigVo,
wfNodeConfigVo: row.wfNodeConfigVo,
businessKey: row.businessKey,
businessKey: row.businessId,
taskId: row.id,
type: 'view'
});