【feat】集成warm-flow实现工作流

This commit is contained in:
Kris 2025-02-14 11:00:59 +08:00
parent 4012710d2b
commit 412e8cb931
15 changed files with 2726 additions and 0 deletions

133
src/api/flow/definition.js Normal file
View File

@ -0,0 +1,133 @@
import request from '@/utils/request'
// 查询流程定义列表
export function listDefinition(query) {
return request({
url: '/flow/definition/list',
method: 'get',
params: query
})
}
// 查询流程定义详细
export function getDefinition(id) {
return request({
url: '/flow/definition/' + id,
method: 'get'
})
}
// 获取流程定义xml字符串
export function saveXml(data) {
return request({
url: '/flow/definition/saveXml',
method: 'post',
data: data
})
}
// 导出流程定义详细
export function exportDefinition(id) {
return request({
url: '/flow/definition/exportDefinition/' + id,
method: 'get'
})
}
// 获取流程定义xml字符串
export function xmlString(id) {
return request({
url: '/flow/definition/xmlString/' + id,
method: 'get'
})
}
// 新增流程定义
export function addDefinition(data) {
return request({
url: '/flow/definition',
method: 'post',
data: data
})
}
// 修改流程定义
export function updateDefinition(data) {
return request({
url: '/flow/definition',
method: 'put',
data: data
})
}
// 删除流程定义
export function delDefinition(id) {
return request({
url: '/flow/definition/' + id,
method: 'delete'
})
}
// 发布流程定义
export function publish(id) {
return request({
url: '/flow/definition/publish/' + id,
method: 'get'
})
}
// 取消发布流程定义
export function unPublish(id) {
return request({
url: '/flow/definition/unPublish/' + id,
method: 'get'
})
}
// 复制流程定义
export function copyDef(id) {
return request({
url: '/flow/definition/copyDef/' + id,
method: 'get'
})
}
// 查看流程图
export function chartDef(definitionId) {
return request({
url: '/flow/definition/chartDef/' + definitionId,
method: 'get'
})
}
// 查看流程图
export function flowImage(instanceId) {
return request({
url: '/flow/definition/flowChart/' + instanceId,
method: 'get'
})
}
// 激活流程
export function active(definitionId) {
return request({
url: '/flow/definition/active/' + definitionId,
method: 'get'
})
}
// 挂起流程
export function unActive(definitionId) {
return request({
url: '/flow/definition/unActive/' + definitionId,
method: 'get'
})
}
// 查询已发布表单定义列表
export function publishedList() {
return request({
url: '/warm-flow/published-form',
method: 'get'
})
}

81
src/api/flow/execute.js Normal file
View File

@ -0,0 +1,81 @@
import request from '@/utils/request'
// 查询待办任务列表
export function toDoPage(query) {
return request({
url: '/flow/execute/toDoPage',
method: 'get',
params: query
})
}
// 查询已办任务列表
export function donePage(query) {
return request({
url: '/flow/execute/donePage',
method: 'get',
params: query
})
}
// 查询抄送任务列表
export function copyPage(query) {
return request({
url: '/flow/execute/copyPage',
method: 'get',
params: query
})
}
// 查询已办任务列表
export function doneList(instanceId) {
return request({
url: '/flow/execute/doneList/' + instanceId,
method: 'get'
})
}
// 查询跳转任意节点列表
export function anyNodeList(instanceId) {
return request({
url: '/flow/execute/anyNodeList/' + instanceId,
method: 'get'
})
}
// 转办|加签|委派|减签
export function interactiveType(taskId, assigneePermission, operatorType) {
return request({
url: '/flow/execute/interactiveType',
method: 'post',
params: {
taskId: taskId,
addHandlers: assigneePermission,
operatorType: operatorType
}
})
}
// 查询跳转任意节点列表
export function getTaskById(taskId) {
return request({
url: '/flow/execute/getTaskById/' + taskId,
method: 'get'
})
}
// 激活流程
export function active(instanceId) {
return request({
url: '/flow/execute/active/' + instanceId,
method: 'get'
})
}
// 挂起流程
export function unActive(instanceId) {
return request({
url: '/flow/execute/unActive/' + instanceId,
method: 'get'
})
}

View File

@ -0,0 +1,77 @@
import request from '@/utils/request'
// 查询表单定义列表
export function listDefinition(query) {
return request({
url: '/flow/form/list',
method: 'get',
params: query
})
}
// 查询表单定义详细
export function getDefinition(id) {
return request({
url: '/flow/form/' + id,
method: 'get'
})
}
// 新增表单定义
export function addDefinition(data) {
return request({
url: '/flow/form/add',
method: 'post',
data: data
})
}
// 修改表单定义
export function updateDefinition(data) {
return request({
url: '/flow/form/edit',
method: 'put',
data: data
})
}
// 删除表单定义
export function delDefinition(id) {
return request({
url: '/flow/form/' + id,
method: 'delete'
})
}
// 发布表单定义
export function publish(id) {
return request({
url: '/flow/form/publish/' + id,
method: 'get'
})
}
// 取消发布表单定义
export function unPublish(id) {
return request({
url: '/flow/form/unPublish/' + id,
method: 'get'
})
}
// 复制表单定义
export function copyDef(id) {
return request({
url: '/flow/form/copyForm/' + id,
method: 'post'
})
}
// 保存表单设计
export function saveFormContent(data) {
return request({
url: '/flow/form/saveFormContent',
method: 'post',
data: data
})
}

View File

@ -0,0 +1,345 @@
<template>
<!-- 选择用户 -->
<div class="selectUser">
<el-row :gutter="20">
<!--部门数据-->
<el-col :span="4" :xs="24">
<div class="head-container">
<el-input
v-model="deptName"
placeholder="请输入部门名称"
clearable
size="small"
prefix-icon="el-icon-search"
style="margin-bottom: 20px"
/>
</div>
<div class="head-container">
<el-tree
:data="deptOptions"
:props="defaultProps"
:expand-on-click-node="false"
:filter-node-method="filterNode"
ref="tree"
node-key="id"
default-expand-all
highlight-current
@node-click="handleNodeClick"
/>
</div>
</el-col>
<!--用户数据-->
<el-col :span="20" :xs="24">
<el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
<el-form-item label="用户名称" prop="userName">
<el-input
v-model="queryParams.userName"
placeholder="请输入用户名称"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="手机号码" prop="phonenumber">
<el-input
v-model="queryParams.phonenumber"
placeholder="请输入手机号码"
clearable
style="width: 240px"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="创建时间">
<el-date-picker
v-model="dateRange"
style="width: 240px"
value-format="yyyy-MM-dd"
type="daterange"
range-separator="-"
start-placeholder="开始日期"
end-placeholder="结束日期"
></el-date-picker>
</el-form-item>
<div style="text-align: right">
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
<el-button type="primary" size="mini" :disabled="checkedItemList.length === 0" @click="submitForm"> </el-button>
</div>
</el-form>
<el-row class="mb8">
<el-tag style="margin-right: 10px" v-for="tag in checkedItemList" :key="tag.userId" closable @close="handleClose(tag.userId)">{{tag.userId}}</el-tag>
</el-row>
<el-table ref="table" v-loading="loading" :data="userList" @row-click="handleCheck">
<el-table-column width="50" align="center">
<template #header v-if="!['转办', '委派'].includes(type)">
<el-checkbox
:indeterminate="checkAllInfo.isIndeterminate"
v-model="checkAllInfo.isChecked"
@change="handleCheckAll"
></el-checkbox>
</template>
<template slot-scope="{ row }">
<el-checkbox v-model="row.isChecked" @change.capture="handleCheck(row)"></el-checkbox>
</template>
</el-table-column>
<el-table-column label="用户编号" align="center" key="userId" prop="userId" v-if="columns[0].visible" />
<el-table-column label="用户名称" align="center" key="userName" prop="userName" v-if="columns[1].visible" :show-overflow-tooltip="true" />
<el-table-column label="用户昵称" align="center" key="nickName" prop="nickName" v-if="columns[2].visible" :show-overflow-tooltip="true" />
<el-table-column label="部门" align="center" key="deptName" prop="dept.deptName" v-if="columns[3].visible" :show-overflow-tooltip="true" />
<el-table-column label="手机号码" align="center" key="phonenumber" prop="phonenumber" v-if="columns[4].visible" width="120" />
<el-table-column label="状态" align="center" key="status" v-if="columns[5].visible">
<template slot-scope="scope">
<el-tag :type="scope.row.status === '0' ? '' : 'warning'">{{ scope.row.status === '0' ? '正常' : '停用' }}</el-tag>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[6].visible" width="160">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
style="margin-bottom: 35px;"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
</el-col>
</el-row>
</div>
</template>
<script>
import * as api from "@/api/system/user";
import Treeselect from "@riophae/vue-treeselect";
import "@riophae/vue-treeselect/dist/vue-treeselect.css";
export default {
name: "User",
dicts: ['sys_normal_disable', 'sys_user_sex'],
components: { Treeselect },
props: ["userVisible", "selectUser", "postParams", "type"],
data() {
return {
//
loading: true,
//
showSearch: true,
//
total: 0,
//
userList: null,
//
title: "",
//
deptOptions: undefined,
//
open: false,
//
deptName: undefined,
//
initPassword: undefined,
//
dateRange: [],
//
postOptions: [],
//
roleOptions: [],
//
form: {},
defaultProps: {
children: "children",
label: "label"
},
//
queryParams: {
pageNum: 1,
pageSize: 10,
userName: undefined,
phonenumber: undefined,
status: "0",
deptId: undefined
},
//
columns: [
{ key: 0, label: `用户编号`, visible: true },
{ key: 1, label: `用户名称`, visible: true },
{ key: 2, label: `用户昵称`, visible: true },
{ key: 3, label: `部门`, visible: true },
{ key: 4, label: `手机号码`, visible: true },
{ key: 5, label: `状态`, visible: true },
{ key: 6, label: `创建时间`, visible: true }
],
checkedItemList: [], // itemList
checkAllInfo: {
isIndeterminate: false,
isChecked: false,
}
};
},
watch: {
//
deptName(val) {
this.$refs.tree.filter(val);
},
selectUser: {
handler(val, oldVal) {
if (oldVal) {
this.$nextTick(() => {
this.checkedItemList = this.checkedItemList.filter(e => {
let index = val ? val.findIndex(v => v === e.userId) : -1;
this.userList.forEach(u => {
if (u.userId === e.userId) u.isChecked = index !== -1;
});
return index !== -1;
});
});
} else {
this.checkedItemList = val.map(e => { return { userId: e } });
}
},
deep: true,
immediate: true
}
},
created() {
this.getList();
this.getDeptTree();
},
methods: {
/** 查询用户列表 */
getList() {
this.loading = true;
let params = this.addDateRange(this.queryParams, this.dateRange);
let url = "listUser"
if (this.type) {
let postParams = JSON.parse(JSON.stringify(this.postParams));
url = postParams.url;
delete postParams.url;
params = { ...postParams, deptId: this.queryParams.deptId };
}
api[url](params).then(response => {
this.total = response.total;
this.loading = false;
response.rows.forEach(item => {
item.isChecked = this.checkedItemList.findIndex(e => e.userId === item.userId) !== -1;
})
this.userList = response.rows;
this.isCheckedAll();
}
);
},
/** 查询部门下拉树结构 */
getDeptTree() {
api.deptTreeSelect().then(response => {
this.deptOptions = response.data;
});
},
//
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
//
handleNodeClick(data) {
this.queryParams.deptId = data.id;
this.handleQuery();
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.dateRange = [];
this.resetForm("queryForm");
this.queryParams.deptId = undefined;
this.$refs.tree.setCurrentKey(null);
this.handleQuery();
},
//
isCheckedAll() {
const len = this.userList.length;
let count = 0;
this.userList.map(item => {
if (item.isChecked) count += 1;
});
this.checkAllInfo.isChecked = len === count && len > 0;
this.checkAllInfo.isIndeterminate = count > 0 && count < len;
},
//
handleCheckAll() {
const checkedItemList = this.checkedItemList;
this.checkAllInfo.isIndeterminate = false;
if (this.checkAllInfo.isChecked) {
this.userList = this.userList.map(item => {
item.isChecked = true;
if (this.checkedItemList.findIndex(e => e.userId === item.userId) === -1) {
checkedItemList.push({ userId: item.userId });
}
return item;
});
} else {
this.userList = this.userList.map(item => {
item.isChecked = false;
let index = checkedItemList.findIndex(e => e.userId === item.userId);
if (index !== -1) checkedItemList.splice(index, 1);
return item;
});
}
this.checkedItemList = checkedItemList
},
//
handleCheck(row) {
// |
if (['转办', '委派'].includes(this.type)) {
this.userList.forEach(e => {
if (e.userId === row.userId) e.isChecked = true;
else e.isChecked = false;
});
this.checkedItemList = [{ userId: row.userId }];
} else {
this.userList.forEach(e => {
if (e.userId === row.userId) e.isChecked = !e.isChecked;
});
const checkedItemList = this.checkedItemList;
if (row.isChecked) {
checkedItemList.push({ userId: row.userId });
} else {
const index = checkedItemList.findIndex(n => n.userId === row.userId);
if (index !== -1) checkedItemList.splice(index, 1);
}
this.checkedItemList = checkedItemList;
this.isCheckedAll();
}
},
//
handleClose(userId) {
this.userList.forEach(e => {
if (e.userId === userId) e.isChecked = !e.isChecked;
});
const checkedItemList = this.checkedItemList
const index = checkedItemList.findIndex(n => n.userId === userId);
if (index !== -1) checkedItemList.splice(index, 1);
this.checkedItemList = checkedItemList;
this.isCheckedAll();
},
//
cancel() {
this.$emit("update:userVisible", false);
},
//
submitForm() {
this.$emit("handleUserSelect", this.checkedItemList);
this.cancel();
}
}
};
</script>

View File

@ -0,0 +1,258 @@
<template>
<div class="app-container">
<!-- 添加或修改流程定义对话框 -->
<el-dialog :title="title" :visible.sync="open" width="800px" v-if="open" append-to-body>
<el-tabs type="border-card" class="Tabs" v-model="tabsValue">
<el-tab-pane label="基础设置" name="1"></el-tab-pane>
<el-tab-pane label="监听器" name="2"></el-tab-pane>
</el-tabs>
<el-form ref="form" :model="form" class="dialogForm" :rules="rules" label-width="150px" :disabled="disabled">
<div v-show="tabsValue === '1'">
<el-form-item label="流程编码" prop="flowCode">
<el-input v-model="form.flowCode" placeholder="请输入流程编码" maxlength="40" show-word-limit/>
</el-form-item>
<el-form-item label="流程名称" prop="flowName">
<el-input v-model="form.flowName" placeholder="请输入流程名称" maxlength="100" show-word-limit/>
</el-form-item>
<el-form-item label="流程类别" prop="category">
<el-input v-model="form.category" placeholder="请输入流程类别" maxlength="20" show-word-limit/>
</el-form-item>
<el-form-item label="是否发布" prop="isPublish" v-if="disabled">
<el-select v-model="form.isPublish" placeholder="请选择是否开启流程">
<el-option
v-for="dict in dict.type.is_publish"
:key="dict.value"
:label="dict.label"
:value="parseInt(dict.value)"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="审批表单是否自定义" prop="formCustom">
<el-select v-model="form.formCustom" clearable>
<el-option label="表单路径" value="N"></el-option>
<!--TODO form 开发中-->
<!-- <el-option label="动态表单" value="Y"></el-option>-->
</el-select>
</el-form-item>
<el-form-item label="审批表单路径" prop="formPath" v-if="form.formCustom === 'N'">
<el-input v-model="form.formPath" placeholder="请输入审批表单路径" maxlength="100" show-word-limit/>
</el-form-item>
<el-form-item label="审批流程表单" v-else-if="form.formCustom === 'Y'">
<el-select v-model="form.formPath">
<el-option v-for="item in definitionList" :key="item.id" :label="`${item.formName} - v${item.version}`" :value="item.id"></el-option>
</el-select>
</el-form-item>
</div>
<div v-show="tabsValue === '2'">
<el-form-item prop="listenerRows" class="listenerItem">
<el-table :data="form.listenerRows" style="width: 100%">
<el-table-column prop="listenerType" width="150" label="类型">
<template slot-scope="scope">
<el-form-item :prop="'listenerRows.' + scope.$index + '.listenerType'" :rules="rules.listenerType">
<el-select v-model="scope.row.listenerType" placeholder="请选择类型">
<el-option label="开始" value="start"></el-option>
<el-option label="分派" value="assignment"></el-option>
<el-option label="完成" value="finish"></el-option>
<el-option label="创建" value="create"></el-option>
</el-select>
</el-form-item>
</template>
</el-table-column>
<el-table-column prop="listenerPath" label="路径">
<template slot-scope="scope">
<el-form-item :prop="'listenerRows.' + scope.$index + '.listenerPath'" :rules="rules.listenerPath">
<el-input v-model="scope.row.listenerPath" placeholder="请输入路径"></el-input>
</el-form-item>
</template>
</el-table-column>
<el-table-column label="操作" width="65" v-if="!disabled">
<template slot-scope="scope">
<el-button size="mini" type="danger" icon="el-icon-delete" @click="handleDeleteRow(scope.$index)"/>
</template>
</el-table-column>
</el-table>
<el-button v-if="!disabled" style="margin-top: 10px;" type="primary" @click="handleAddRow">增加行</el-button>
</el-form-item>
</div>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" v-if="!disabled" @click="submitForm"> </el-button>
<el-button @click="cancel" v-if="!disabled"> </el-button>
<el-button @click="cancel" v-if="disabled"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { getDefinition, addDefinition, updateDefinition, publishedList } from "@/api/flow/definition";
export default {
name: "Dialog",
dicts: ['sys_yes_no', 'is_publish'],
data() {
return {
//
disabled: false,
//
title: "",
//
open: false,
tabsValue: "1",
//
form: {
listenerRows: [] //
},
definitionList: [],
//
rules: {
flowCode: [
{ required: true, message: "流程编码不能为空", trigger: "blur" }
],
flowName: [
{ required: true, message: "流程名称不能为空", trigger: "blur" }
],
isPublish: [
{ required: true, message: "是否开启流程不能为空", trigger: "change" }
],
formCustom: [
{ required: true, message: "请选择审批表单是否自定义", trigger: "change" }
],
listenerType: [{ required: true, message: '监听器不能为空', trigger: ['change', 'blur'] }],
listenerPath: [{ required: true, message: '监听器不能为空', trigger: ['change', 'blur'] }]
}
};
},
methods: {
/** 打开流程定义弹框 */
async show(id, disabled) {
this.reset();
this.disabled = disabled
// TODO form
// this.getDefinition();
if (id) {
await getDefinition(id).then(response => {
this.form = response.data;
if (this.form.listenerType) {
const listenerTypes = this.form.listenerType.split(",");
const listenerPaths = this.form.listenerPath.split("@@");
this.form.listenerRows = listenerTypes.map((type, index) => ({
listenerType: type,
listenerPath: listenerPaths[index]
}));
} else {
this.form.listenerRows = [];
}
});
}
this.open = true
if (this.disabled) {
this.title = "详情"
} else if (id) {
this.title = "修改"
} else {
this.title = "新增"
}
},
/** 查询表单定义列表 */
getDefinition() {
publishedList().then(response => {
this.definitionList = response.data;
});
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {
id: null,
flowCode: null,
flowName: null,
version: null,
isPublish: null,
formCustom: null,
formPath: null,
createTime: null,
updateTime: null,
delFlag: null,
listenerRows: [] //
};
this.resetForm("form");
this.tabsValue = "1";
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate((valid, err) => {
if (valid) {
this.form.listenerType = this.form.listenerRows.map(row => row.listenerType).join(",")
this.form.listenerPath = this.form.listenerRows.map(row => row.listenerPath).join("@@")
if (this.form.id != null) {
updateDefinition(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.$emit('refresh');
});
} else {
addDefinition(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.$emit('refresh');
});
}
} else {
let errItems = Object.keys(err);
if (errItems.length > 0) {
this.tabsValue = "1";
if (errItems.every(e => e.includes("listenerRows"))) this.tabsValue = "2";
}
}
});
},
//
handleAddRow() {
this.form.listenerRows.push({ listenerType: '', listenerPath: '' });
this.$refs.form.clearValidate("listenerRows");
},
//
handleDeleteRow(index) {
this.form.listenerRows.splice(index, 1);
}
}
};
</script>
<style scoped lang="scss">
::v-deep.Tabs {
margin-top: -20px;
box-shadow: none;
border-bottom: 0;
.el-tabs__content {
display: none;
}
.el-tabs__item.is-active {
margin-left: 0;
border-top: 1px solid var(--el-border-color);
margin-top: 0;
}
}
.dialogForm {
border: 1px solid #e4e7ed;
border-top: 0;
padding: 15px;
}
::v-deep.listenerItem {
.el-form-item__label {
float: none;
display: inline-block;
text-align: left;
}
.el-form-item__content {
margin-left: 0 !important;
}
}
</style>

View File

@ -0,0 +1,422 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="mini" :inline="true" v-show="showSearch" label-width="100px">
<el-form-item label="流程编码" prop="flowCode">
<el-input
v-model="queryParams.flowCode"
placeholder="请输入流程编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="流程名称" prop="flowName">
<el-input
v-model="queryParams.flowName"
placeholder="请输入流程名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="流程类别" prop="category">
<el-input
v-model="queryParams.category"
placeholder="请输入流程类别"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="流程版本" prop="version">
<el-input
v-model="queryParams.version"
placeholder="请输入流程版本"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['flow:definition:add']"
>新增</el-button>
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleImport"
v-hasPermi="['flow:definition:importDefinition']"
>导入流程定义</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="definitionList" @selection-change="handleSelectionChange" @sort-change="handleSortChange">
<el-table-column type="selection" width="55" align="center" fixed />
<el-table-column label="序号" width="50" align="center" key="id" prop="id">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column label="流程编码" align="center" prop="flowCode" width="150" sortable="custom" :show-overflow-tooltip="true"/>
<el-table-column label="流程名称" align="center" prop="flowName" sortable="custom" :show-overflow-tooltip="true"/>
<el-table-column label="流程版本" align="center" prop="version" width="100" sortable="custom" :show-overflow-tooltip="true">
<template slot-scope="scope">
<el-tag>{{scope.row.version}}</el-tag>
</template>
</el-table-column>
<el-table-column label="流程类别" align="center" prop="category" sortable="custom" :show-overflow-tooltip="true"/>
<el-table-column label="是否发布" align="center" prop="isPublish" width="140" sortable="custom" :show-overflow-tooltip="true">
<template slot-scope="scope">
<dict-tag :options="dict.type.is_publish" :value="scope.row.isPublish"/>
</template>
</el-table-column>
<el-table-column label="激活状态" align="center" prop="activityStatus" width="140" sortable="custom" :show-overflow-tooltip="true">
<template slot-scope="scope">
<dict-tag :options="dict.type.activity_status" :value="scope.row.activityStatus"/>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="160" sortable="custom" :sort-orders="['descending', 'ascending']" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="200" fixed="right" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="handleDesign(scope.row.id, scope.row.isPublish)"
v-hasPermi="['flow:definition:queryDesign']"
>流程设计</el-button>
<el-button
size="mini"
type="text"
@click="toFlowImage(scope.row.id)"
>流程图</el-button>
<el-button
size="mini"
type="text"
v-if="scope.row.isPublish === 0"
@click="handlePublish(scope.row.id)"
v-hasPermi="['flow:definition:publish']"
>发布</el-button>
<el-button
size="mini"
type="text"
v-if="scope.row.isPublish === 1"
@click="handleUpPublish(scope.row.id)"
v-hasPermi="['flow:definition:upPublish']"
>取消发布</el-button>
<el-button
size="mini"
type="text"
v-if="scope.row.activityStatus === 0"
@click="toActive(scope.row.id)"
>激活</el-button>
<el-button
size="mini"
type="text"
v-if="scope.row.activityStatus === 1"
@click="toUnActive(scope.row.id)"
>挂起</el-button>
<el-button
size="mini"
type="text"
@click="handleCopyDef(scope.row.id)"
v-hasPermi="['flow:definition:upPublish']"
>复制流程</el-button>
<el-button
size="mini"
type="text"
v-if="scope.row.isPublish === 0"
@click="handleUpdate(scope.row.id)"
v-hasPermi="['flow:definition:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
@click="handleExport(scope.row)"
v-hasPermi="['flow:definition:exportDefinition']"
>导出流程</el-button>
<el-button
size="mini"
type="text"
v-if="scope.row.isPublish === 0"
@click="handleDelete(scope.row)"
v-hasPermi="['flow:definition:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<Dialog ref="dialog" @refresh="getList"></Dialog>
<!-- 用户导入对话框 -->
<el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
<el-upload
ref="upload"
multiple
:limit="20"
accept=".json"
:headers="upload.headers"
:action="upload.url"
:disabled="upload.isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:auto-upload="false"
drag
>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div class="el-upload__tip text-center" slot="tip">
<span>仅允许导入json格式文件</span>
</div>
</el-upload>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="submitFileForm"> </el-button>
<el-button @click="upload.open = false"> </el-button>
</div>
</el-dialog>
<el-dialog title="流程图" :visible.sync="flowChart" width="80%">
<img :src="imgUrl" width="100%" style="margin:0 auto"/>
</el-dialog>
</div>
</template>
<script>
import {
listDefinition,
delDefinition,
publish,
unPublish,
copyDef,
chartDef, active, unActive
} from '@/api/flow/definition'
import Dialog from "@/views/flow/definition/dialog";
import { getToken } from '@/utils/auth'
export default {
name: "Definition",
dicts: ['is_publish', 'activity_status'],
components: {
Dialog
},
data() {
return {
//
loading: true,
imgUrl: "",
flowChart: false,
//
uniqueId: "",
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
definitionList: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
flowCode: null,
flowName: null,
version: null,
},
//
upload: {
//
open: false,
//
title: "",
//
isUploading: false,
//
headers: { Authorization: "Bearer " + getToken() },
//
url: process.env.VUE_APP_BASE_API + "/flow/definition/importDefinition"
},
};
},
created() {
this.getList();
},
activated() {
const time = this.$route.query.t;
if (time != null && time != this.uniqueId) {
this.uniqueId = time;
this.queryParams.pageNum = Number(this.$route.query.pageNum);
this.getList();
}
},
methods: {
active,
/** 查询流程定义列表 */
getList() {
this.loading = true;
listDefinition(this.queryParams).then(response => {
this.definitionList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.$refs.dialog.show();
},
/** 流程设计按钮操作 */
handleDesign(id, isPublish) {
const params = { disabled: isPublish === 1, pageNum: this.queryParams.pageNum };
this.$tab.openPage("流程设计", '/flow/flow-design/index/' + id, params);
},
/** 发布按钮操作 */
handlePublish(id) {
this.$modal.confirm('是否确认发布流程定义编号为"' + id + '"的数据项?').then(function() {
return publish(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("发布成功");
}).catch(() => {});
},
/** 取消发布按钮操作 */
handleUpPublish(id) {
this.$modal.confirm('是否确认取消发布流程定义编号为"' + id + '"的数据项?').then(function() {
return unPublish(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("取消成功");
}).catch(() => {});
},
/** 修改按钮操作 */
handleUpdate(id) {
this.$refs.dialog.show(id);
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除流程定义编号为"' + ids + '"的数据项?').then(function() {
return delDefinition(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 复制流程按钮操作 */
handleCopyDef(id) {
this.$modal.confirm('是否确认复制流程定义编号为"' + id + '"的数据项?').then(function() {
return copyDef(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("复制成功");
}).catch(() => {});
},
/** 导入按钮操作 */
handleImport() {
this.upload.title = "用户导入";
this.upload.open = true;
},
handleExport(row) {
this.download('/flow/definition/exportDefinition/' + row.id, {
...this.queryParams
}, row.flowCode + '_' + row.version + '.json')
},
//
handleFileUploadProgress(event, file, fileList) {
this.upload.isUploading = true;
},
//
handleFileSuccess(response, file, fileList) {
this.upload.open = false;
this.upload.isUploading = false;
this.$refs.upload.clearFiles();
this.$alert("<div style='overflow: auto;overflow-x: hidden;max-height: 70vh;padding: 10px 20px 0;'>" + response.msg + "</div>", "导入结果", { dangerouslyUseHTMLString: true });
this.getList();
},
//
submitFileForm() {
this.$refs.upload.submit();
},
/** 排序触发事件 */
handleSortChange(column, prop, order) {
this.queryParams.orderByColumn = column.prop;
this.queryParams.isAsc = column.order;
this.getList();
},
toFlowImage(id) {
chartDef(id).then(response => {
this.flowChart = true
this.imgUrl = "data:image/gif;base64," + response.data;
});
},
toActive(id) {
this.$modal.confirm('是否确认激活流程定义编号为"' + id + '"的数据项?').then(function() {
return active(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("激活成功");
}).catch(() => {});
},
toUnActive(id) {
this.$modal.confirm('是否确认挂起流程定义编号为"' + id + '"的数据项?').then(function() {
return unActive(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("挂起成功");
}).catch(() => {});
},
}
};
</script>

View File

@ -0,0 +1,39 @@
<template>
<div :style="'height:' + height">
<iframe :src="url" style="width: 100%; height: 100%"/>
</div>
</template>
<script>
import {getToken} from "@/utils/auth";
export default {
name: "WarmFlow",
data() {
return {
height: document.documentElement.clientHeight - 94.5 + "px;",
url: ""
};
},
mounted() {
this.url = `${process.env.VUE_APP_FLOW_API}/warm-flow-ui/index.html?id=${this.$route.params.id}&disabled=${this.$route.query.disabled}&Authorization=Bearer ` + getToken();
window.addEventListener("message", this.handleMessage);
},
beforeDestroy() {
window.removeEventListener("message", this.handleMessage);
},
methods: {
handleMessage(event) {
console.log(event.data.method, event);
switch (event.data.method) {
case "close":
this.close();
break;
}
},
close() {
const obj = { path: "/flow/definition" };
this.$tab.closeOpenPage(obj);
}
}
};
</script>

View File

@ -0,0 +1,169 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="mini" :inline="true" v-show="showSearch" label-width="100px">
<el-form-item label="任务名称" prop="nodeName">
<el-input
v-model="queryParams.nodeName"
placeholder="请输入任务名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="流程状态" prop="flowStatus">
<el-select v-model="queryParams.nodeType" placeholder="请选择流程状态" clearable>
<el-option
v-for="dict in dict.type.flow_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="抄送人" prop="flowName">
<el-input
v-model="queryParams.flowName"
placeholder="请输入任抄送人"
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="instanceList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" fixed />
<el-table-column label="序号" width="55" align="center" key="id" prop="id">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column label="流程实例id" width="100" align="center" prop="id" :show-overflow-tooltip="true"/>
<el-table-column label="流程名称" align="center" prop="flowName" :show-overflow-tooltip="true"/>
<el-table-column label="任务名称" align="center" prop="nodeName" :show-overflow-tooltip="true"/>
<el-table-column label="抄送人" align="center" prop="approver" :show-overflow-tooltip="true"/>
<el-table-column label="流程状态" align="center" prop="flowStatus" :show-overflow-tooltip="true">
<template slot-scope="scope">
<dict-tag :options="dict.type.flow_status" :value="scope.row.flowStatus"/>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="160" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="240" fixed="right" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="toFlowImage(scope.row.id)"
>流程图</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<component v-bind:is="approve" v-model="businessId" :taskId="taskId" @refresh="getList"></component>
<el-dialog title="流程图" :visible.sync="flowChart" width="80%">
<img :src="imgUrl" width="100%" style="margin:0 auto"/>
</el-dialog>
</div>
</template>
<script>
import * as api from "@/api/flow/execute";
import { flowImage } from "@/api/flow/definition";
export default {
name: "Todo",
dicts: ['flow_status'],
data() {
return {
//
loading: true,
imgUrl: "",
flowChart: false,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
instanceList: [],
//
approve: null,
taskId: "",
businessId: "",
//
queryParams: {
pageNum: 1,
pageSize: 10,
nodeName: null,
flowStatus: null,
approver: null,
flowName: null,
createTime: null,
},
};
},
created() {
this.getList();
},
methods: {
/** 查询流程实例列表 */
getList() {
this.loading = true;
api.copyPage(this.queryParams).then(response => {
this.instanceList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 办理按钮操作 */
handle(row) {
this.taskId = row.id
this.businessId = row.businessId
if (row.formCustom == 'N' && row.formPath) {
//
this.approve = (resolve) => require([`@/views/${row.formPath}`], resolve)
}
},
toFlowImage(instanceId) {
flowImage(instanceId).then(response => {
this.flowChart = true
this.imgUrl = "data:image/gif;base64," + response.data;
});
},
}
};
</script>

View File

@ -0,0 +1,125 @@
<template>
<div class="app-container">
<el-table :data="taskList">
<el-table-column label="序号" width="50" align="center" key="id" prop="id">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column label="开始节点名称" align="center" prop="nodeName" :show-overflow-tooltip="true"/>
<el-table-column label="结束节点名称" align="center" prop="targetNodeName" :show-overflow-tooltip="true"/>
<el-table-column label="审批人" align="center" prop="approver" :show-overflow-tooltip="true"/>
<el-table-column label="协作类型" align="center" prop="cooperateType" :show-overflow-tooltip="true">
<template slot-scope="scope">
<dict-tag :options="dict.type.cooperate_type" :value="scope.row.cooperateType"/>
</template>
</el-table-column>
<el-table-column label="协作人" align="center" prop="collaborator" :show-overflow-tooltip="true"/>
<!-- <el-table-column label="流转类型" align="center" prop="skipType" :show-overflow-tooltip="true">
<template slot-scope="scope">
<el-tag v-if="scope.row.skipType==='PASS'">通过</el-tag>
<el-tag v-if="scope.row.skipType==='REJECT'" type="danger">退回</el-tag>
<el-tag v-if="scope.row.skipType==='NONE'" type="info">无动作</el-tag>
</template>
</el-table-column> -->
<el-table-column label="流程状态" align="center" prop="flowStatus" :show-overflow-tooltip="true">
<template slot-scope="scope">
<dict-tag :options="dict.type.flow_status" :value="scope.row.flowStatus"/>
</template>
</el-table-column>
<el-table-column label="审批意见" align="center" prop="message" :show-overflow-tooltip="true"/>
<el-table-column label="创建时间" align="center" prop="createTime" width="160" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="业务详情" align="center" width="100">
<template slot-scope="scope">
<el-button size="mini" v-if="scope.row.ext" @click="handle(scope.row)">查看</el-button>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="110" fixed="right" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
v-if="scope.row.nodeType === 1 && scope.row.formCustom === 'Y'"
@click="handleForm(scope.row.id)"
>查看</el-button>
</template>
</el-table-column>
</el-table>
<component v-if="approve" v-bind:is="approve" :businessId="businessId" :taskId="taskId" :testLeaveVo="testLeaveVo" @refresh="fetchTaskList"></component>
<formDialog v-if="showFormDialog" :disabled="true" :formName="'查看'" :visible.sync="showFormDialog" :showApproval="false" :taskId="taskId" :type="'1'"></formDialog>
</div>
</template>
<script>
import {doneList} from '@/api/flow/execute';
import formDialog from "../../../form/definition/formDialog";
export default {
name: "DoneList",
dicts: ['flow_status', 'cooperate_type'],
components: {
formDialog
},
data() {
return {
instanceId: "",
formPath: "",
//
taskList: [],
taskId: "",
businessId: "",
approve: null,
testLeaveVo: null,
showFormDialog: false
};
},
activated() {
this.instanceId = this.$route.params.instanceId;
this.formPath = this.$route.query.formPath;
this.testLeaveVo = this.$route.query.testLeaveVo; // testLeaveVo
this.fetchTaskList();
},
methods: {
fetchTaskList() {
doneList(this.instanceId).then(response => {
this.taskList = response.data;
});
},
handle(row) {
// IDID
this.taskId = row.id;
this.businessId = row.businessId;
// testLeaveVo
// extJSON
if (row.ext) {
try {
const parsedExt = JSON.parse(row.ext);
this.testLeaveVo = {...parsedExt};
} catch (e) {
console.error('Invalid ext JSON format:', row.ext);
}
}
// formPath
const formPath = row.formPath || this.formPath;
// formPath
if (formPath) {
// require
this.approve = (resolve) => require([`@/views/${formPath}`], resolve);
} else {
this.approve = null;
}
},
//
handleForm(id) {
this.taskId = id;
this.showFormDialog = true;
}
}
};
</script>

View File

@ -0,0 +1,228 @@
<template>
<div class="app-container">
<!-- 搜索表单 -->
<el-form :model="queryParams" ref="queryForm" size="mini" :inline="true" v-show="showSearch" label-width="100px">
<!-- 任务名称输入框 -->
<el-form-item label="任务名称" prop="nodeName">
<el-input
v-model="queryParams.nodeName"
placeholder="请输入任务名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<!-- 流程状态选择框 -->
<el-form-item label="流程状态" prop="flowStatus">
<el-select v-model="queryParams.flowStatus" placeholder="请选择流程状态" clearable>
<el-option
v-for="dict in dict.type.flow_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<!-- 审批时间选择器 -->
<el-form-item label="审批时间" prop="createTime">
<el-date-picker
clearable size="small"
v-model="queryParams.createTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择创建时间">
</el-date-picker>
</el-form-item>
<!-- 搜索和重置按钮 -->
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<!-- 流程实例表格 -->
<el-table :data="instanceList">
<!-- 表格列定义 -->
<el-table-column type="selection" width="55" align="center" fixed />
<el-table-column label="序号" width="55" align="center" key="id" prop="id">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column label="流程实例id" align="center" prop="instanceId" :show-overflow-tooltip="true"/>
<el-table-column label="流程名称" align="center" prop="flowName" :show-overflow-tooltip="true"/>
<el-table-column label="任务名称" align="center" prop="targetNodeName" :show-overflow-tooltip="true"/>
<el-table-column label="审批人" align="center" prop="approver" :show-overflow-tooltip="true"/>
<el-table-column label="协作类型" align="center" prop="cooperateType" :show-overflow-tooltip="true">
<template slot-scope="scope">
<dict-tag :options="dict.type.cooperate_type" :value="scope.row.cooperateType"/>
</template>
</el-table-column>
<el-table-column label="协作人" align="center" prop="collaborator" :show-overflow-tooltip="true"/>
<el-table-column label="流程状态" align="center" prop="flowStatus" :show-overflow-tooltip="true">
<template slot-scope="scope">
<dict-tag :options="dict.type.flow_status" :value="scope.row.flowStatus"/>
</template>
</el-table-column>
<el-table-column label="审批时间" align="center" prop="createTime" width="160" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="110" fixed="right" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="showDoneList(scope.row.instanceId, scope.row.formPath, scope.row.testLeaveVo)"
v-hasPermi="['flow:execute:doneList']"
>审批记录</el-button>
<el-button
size="mini"
type="text"
@click="toFlowImage(scope.row.instanceId)"
>流程图</el-button>
<el-button
size="mini"
type="text"
v-if="scope.row.ext"
@click="handle(scope.row)"
>查看</el-button>
<el-button
size="mini"
type="text"
@click="handleComponent"
>多组件加载</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<el-dialog
title="流程图"
:visible.sync="flowChart"
width="80%">
<img
:src="imgUrl"
width="100%"
style="margin:0 auto"/>
</el-dialog>
<component v-if="approve" v-bind:is="approve" :businessId="businessId" :taskId="taskId" :testLeaveVo="testLeaveVo" @refresh="getList"></component>
<!-- 动态加载的组件 -->
<el-dialog title="审批详情" :visible.sync="approveDialogVisible" width="80%">
<component :is="dynamicComponent" v-if="dynamicComponent" :testLeaveVo="testLeaveVo" :taskId="taskId" :disabled="false"/>
</el-dialog>
<!-- 多组件加载 -->
<el-dialog title="多组件加载" :visible.sync="componentVisible" width="80%">
<component v-for="(item, index) in componentList" :key="index" v-bind:is="item.approve"></component>
</el-dialog>
</div>
</template>
<script>
import { donePage } from "@/api/flow/execute";
import { flowImage } from "@/api/flow/definition";
export default {
name: "Done",
dicts: ['flow_status', 'cooperate_type'],
data() {
return {
//
ids: [],
//
showSearch: true,
flowChart: false,
imgUrl: "",
//
total: 0,
//
instanceList: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
nodeName: null,
flowStatus: null,
createBy: null,
createTime: null,
},
//
approve: null,
dynamicComponent: null,
approveDialogVisible: false,
testLeaveVo: null,
taskId: null,
componentVisible: false,
componentList: []
};
},
created() {
this.getList();
},
methods: {
/** 查询流程实例列表 */
getList() {
donePage(this.queryParams).then(response => {
this.instanceList = response.rows;
this.total = response.total;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
/** 办理按钮操作 */
showDoneList(instanceId, formPath, testLeaveVo) {
const params = { disabled: false, pageNum: this.queryParams.pageNum, formPath, testLeaveVo };
this.$router.push({ path: `/done/doneList/index/${instanceId}`, query: params });
},
toFlowImage(instanceId) {
flowImage(instanceId).then(response => {
this.flowChart = true;
this.imgUrl = "data:image/gif;base64," + response.data;
});
},
handle(row) {
// IDID
this.taskId = row.id;
this.businessId = row.businessId;
// extJSON
if (row.ext) {
try {
const parsedExt = JSON.parse(row.ext);
this.testLeaveVo = { ...parsedExt };
} catch (e) {
console.error('Invalid ext JSON format:', row.ext);
}
}
// formPath
const formPath = row.formPath || this.formPath;
// formPath
if (formPath) {
// require
this.approve = (resolve) => require([`@/views/${formPath}`], resolve);
} else {
this.approve = null;
}
},
handleComponent() {
this.componentList.push({ approve: (resolve) => require([`@/views/system/role`], resolve) });
this.componentList.push({ approve: (resolve) => require([`@/views/system/user`], resolve) });
this.componentVisible = true;
}
}
};
</script>

View File

@ -0,0 +1,313 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="mini" :inline="true" v-show="showSearch" label-width="100px">
<el-form-item label="任务名称" prop="nodeName">
<el-input
v-model="queryParams.nodeName"
placeholder="请输入任务名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="流程状态" prop="flowStatus">
<el-select v-model="queryParams.flowStatus" placeholder="请选择流程状态" clearable>
<el-option
v-for="dict in dict.type.flow_status"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item label="创建时间" prop="createTime">
<el-date-picker
clearable size="small"
v-model="queryParams.createTime"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
placeholder="选择创建时间">
</el-date-picker>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" :data="instanceList" @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" align="center" fixed />
<el-table-column label="序号" width="55" align="center" key="id" prop="id">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column label="id" width="100" align="center" prop="id" :show-overflow-tooltip="true"/>
<el-table-column label="流程名称" align="center" prop="flowName" :show-overflow-tooltip="true"/>
<el-table-column label="任务名称" width="200" align="center" prop="nodeName" :show-overflow-tooltip="true"/>
<el-table-column label="审批人" align="center" prop="approver" :show-overflow-tooltip="true"/>
<el-table-column label="转办人" align="center" prop="transferredBy" :show-overflow-tooltip="true"/>
<el-table-column label="委派人" align="center" prop="delegate" :show-overflow-tooltip="true"/>
<el-table-column label="流程状态" align="center" prop="flowStatus" :show-overflow-tooltip="true">
<template slot-scope="scope">
<dict-tag :options="dict.type.flow_status" :value="scope.row.flowStatus"/>
</template>
</el-table-column>
<el-table-column label="激活状态" align="center" prop="activityStatus" width="140" sortable="custom" :show-overflow-tooltip="true">
<template slot-scope="scope">
<dict-tag :options="dict.type.activity_status" :value="scope.row.activityStatus"/>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" width="160" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="240" fixed="right" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
@click="handle(scope.row, false)"
v-hasPermi="['flow:execute:handle']"
>办理</el-button>
<el-button
size="mini"
type="text"
@click="handle(scope.row, true)"
v-hasPermi="['flow:execute:handle']"
>任意跳转</el-button>
<el-button
size="mini"
type="text"
@click="transferShow(scope.row, '转办')"
v-hasPermi="['flow:execute:handle']"
>转办</el-button>
<el-button
size="mini"
type="text"
@click="transferShow(scope.row, '加签')"
v-hasPermi="['flow:execute:handle']"
>加签</el-button>
<el-button
size="mini"
type="text"
@click="transferShow(scope.row, '委派')"
v-hasPermi="['flow:execute:handle']"
>委派</el-button>
<el-button
size="mini"
type="text"
@click="transferShow(scope.row, '减签')"
v-hasPermi="['flow:execute:handle']"
>减签</el-button>
<el-button
size="mini"
type="text"
v-if="scope.row.activityStatus === 0"
@click="toActive(scope.row.instanceId)"
>激活</el-button>
<el-button
size="mini"
type="text"
v-if="scope.row.activityStatus === 1"
@click="toUnActive(scope.row.instanceId)"
>挂起</el-button>
<el-button
size="mini"
type="text"
@click="toFlowImage(scope.row.instanceId)"
>流程图</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<component v-bind:is="approve" v-model="businessId" :type="'0'" :taskId="taskId" :showAnyNode="showAnyNode" :formId="formPath" @refresh="getList"></component>
<el-dialog title="流程图" :visible.sync="flowChart" width="80%">
<img :src="imgUrl" width="100%" style="margin:0 auto"/>
</el-dialog>
<!-- 权限标识选择用户 -->
<el-dialog :title="`${dialogTitle}用户选择`" v-if="userVisible" :visible.sync="userVisible" width="80%" append-to-body>
<selectUser :postParams="postParams" :type="dialogTitle" :selectUser.sync="form.assigneePermission" :userVisible.sync="userVisible" @handleUserSelect="handleUserSelect"></selectUser>
</el-dialog>
</div>
</template>
<script>
import * as api from "@/api/flow/execute";
import { flowImage } from "@/api/flow/definition";
import {active, unActive} from "@/api/flow/execute";
import selectUser from "@/views/components/selectUser";
export default {
name: "Todo",
dicts: ['flow_status', 'activity_status'],
components: {
selectUser
},
data() {
return {
//
loading: true,
imgUrl: "",
flowChart: false,
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
instanceList: [],
//
approve: null,
taskId: "",
businessId: "",
formPath: "",
showAnyNode: false,
//
queryParams: {
pageNum: 1,
pageSize: 10,
nodeName: null,
flowStatus: null,
approver: null,
createTime: null,
},
//
form: {},
//
rules: {
assigneePermission: [
{ required: true, message: "请选择", trigger: "change" }
],
},
dialogTitle: "",
postParams: {},
userVisible: false
};
},
activated() {
this.getList();
},
methods: {
/** 查询流程实例列表 */
getList() {
this.loading = true;
api.toDoPage(this.queryParams).then(response => {
this.instanceList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 办理按钮操作 */
handle(row, showAnyNode) {
this.taskId = row.id
this.businessId = row.businessId
this.showAnyNode = showAnyNode
if(!row.formPath){
row.formPath='system/leave/approve.vue'
}
if (row.formCustom == 'N') {
//
this.approve = (resolve) => require([`@/views/${row.formPath}`], resolve)
} else if (row.formCustom === "Y") {
this.formPath = row.formPath;
this.approve = (resolve) => require([`@/views/form/definition/formDialog.vue`], resolve)
}
},
toFlowImage(instanceId) {
flowImage(instanceId).then(response => {
this.flowChart = true
this.imgUrl = "data:image/gif;base64," + response.data;
});
},
/** 转办|加签|委派|减签弹框显示按钮操作 */
transferShow(row, title) {
this.form.assigneePermission = null;
this.taskId = row.id;
this.dialogTitle = title;
api.getTaskById(this.taskId).then(res => {
this.form.assigneePermission = res.data.assigneePermission ? res.data.assigneePermission.split(",") : [];
});
this.userVisible = true;
let operatorTypeObj = {
"转办": "1",
"加签": "6",
"委派": "3",
"减签": "7"
};
this.postParams = {
url: "interactiveTypeSysUser",
taskId: row.id,
operatorType: operatorTypeObj[title]
};
},
//
handleUserSelect(checkedItemList) {
this.form.assigneePermission = checkedItemList.map(e => {
return e.userId;
});
let assigneePermission = JSON.parse(JSON.stringify(this.form.assigneePermission));
let operatorTypeObj = {
"转办": "2",
"加签": "6",
"委派": "3",
"减签": "7"
};
api.interactiveType(this.taskId, Array.isArray(assigneePermission) ? assigneePermission.join(',') : assigneePermission, operatorTypeObj[this.dialogTitle])
.then(() => {
this.$modal.msgSuccess(`${this.dialogTitle}成功`);
this.getList();
});
},
toActive(instanceId) {
this.$modal.confirm('是否确认激活流程编号为"' + instanceId + '"的数据项?').then(function() {
return active(instanceId);
}).then(() => {
this.getList();
this.$modal.msgSuccess("激活成功");
}).catch(() => {});
},
toUnActive(instanceId) {
this.$modal.confirm('是否确认挂起流程编号为"' + instanceId + '"的数据项?').then(function() {
return unActive(instanceId);
}).then(() => {
this.getList();
this.$modal.msgSuccess("挂起成功");
}).catch(() => {});
},
}
};
</script>

View File

@ -0,0 +1,119 @@
<template>
<div class="app-container">
<!-- 添加或修改表单定义对话框 -->
<el-dialog :title="title" :visible.sync="open" width="400px" v-if="open" append-to-body>
<el-form ref="form" :model="form" :rules="rules" label-width="77.45px" :disabled="disabled">
<el-form-item label="表单编码" prop="formCode">
<el-input v-model="form.formCode" placeholder="请输入表单编码" maxlength="40" show-word-limit/>
</el-form-item>
<el-form-item label="表单名称" prop="formName">
<el-input v-model="form.formName" placeholder="请输入表单名称" maxlength="100" show-word-limit/>
</el-form-item>
<el-form-item label="表单版本" prop="version">
<el-input v-model="form.version" placeholder="请输入表单版本" maxlength="20" show-word-limit/>
</el-form-item>
<el-form-item label="表单类型" prop="formType">
<el-select v-model="form.formType" placeholder="请选择表单类型">
<el-option label="内置表单" :value="0"></el-option>
<el-option label="外挂表单" :value="1"></el-option>
</el-select>
</el-form-item>
<el-form-item label="表单路径" v-if="form.formType === 1" prop="formPath">
<el-input v-model="form.formPath" placeholder="请输入表单路径" maxlength="100" show-word-limit/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="primary" v-if="!disabled" @click="submitForm"> </el-button>
<el-button @click="cancel" v-if="!disabled"> </el-button>
<el-button @click="cancel" v-if="disabled"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { getDefinition, addDefinition, updateDefinition } from "@/api/form/definition";
export default {
name: "Dialog",
data() {
return {
//
disabled: false,
//
title: "",
//
open: false,
//
form: {},
//
rules: {
formCode: [{ required: true, message: "表单编码不能为空", trigger: "blur" }],
formName: [{ required: true, message: "表单名称不能为空", trigger: "blur" }],
version: [{ required: true, message: "表单版本不能为空", trigger: "blur" }],
formType: [{ required: true, message: "表单类型不能为空", trigger: "blur" }],
formPath: [{ required: true, message: "表单路径不能为空", trigger: "blur" }]
}
};
},
methods: {
/** 打开表单定义弹框 */
async show(id, disabled) {
this.reset();
this.disabled = disabled
if (id) {
await getDefinition(id).then(response => {
this.form = response.data;
});
}
this.open = true
if (this.disabled) {
this.title = "详情"
} else if (id) {
this.title = "修改"
} else {
this.title = "新增"
}
},
//
cancel() {
this.open = false;
this.reset();
},
//
reset() {
this.form = {
id: null,
formCode: null,
formName: null,
version: null,
formType: null,
formPath: null
};
this.resetForm("form");
},
/** 提交按钮 */
submitForm() {
this.$refs["form"].validate(valid => {
if (valid) {
if (this.form.formType === 0) this.form.formPath = "";
if (this.form.id != null) {
updateDefinition(this.form).then(response => {
this.$modal.msgSuccess("修改成功");
this.open = false;
this.$emit('refresh');
});
} else {
delete this.form.id;
addDefinition(this.form).then(response => {
this.$modal.msgSuccess("新增成功");
this.open = false;
this.$emit('refresh');
});
}
}
});
}
}
};
</script>

View File

@ -0,0 +1,96 @@
<template>
<div class="app-container">
<!-- 添加或修改OA 自定义流程表单对话框 -->
<el-dialog :title="formName" :visible.sync="showFormDialog" width="500px" v-if="showFormDialog" append-to-body @close="cancel">
<iframe ref="FormCreate" :src="url" :style="`width: 100%; max-height: 60vh; height: ${offsetHeight}px; border: none;`"/>
</el-dialog>
</div>
</template>
<script>
import { getToken } from "@/utils/auth";
export default {
name: "formDialog",
props: {
// 0- 1- 2
type: {
type: String,
default: "0"
},
/* 业务id */
value: {
type: String,
default: "",
},
/* 实例id */
taskId: {
type: String,
default: "",
},
/* 是否可以标编辑 */
disabled: {
type: Boolean,
default: false,
},
//
visible: {
type: Boolean,
default: true
},
//
formName: {
type: String,
default: "办理"
},
// id
formId: {
type: String,
default: ""
}
},
data() {
return {
url: "",
offsetHeight: null, // iframe
showFormDialog: true
};
},
mounted() {
this.url = `${process.env.VUE_APP_FLOW_API}/warm-flow-ui/index.html?type=formCreate&Authorization=Bearer ` + getToken();
window.addEventListener("message", this.handleMessage);
},
beforeDestroy() {
window.removeEventListener("message", this.handleMessage);
},
methods: {
handleMessage(event) {
switch (event.data.method) {
case "formInit":
let data = {
type: this.type,
formId: this.formId,
taskId: this.taskId,
disabled: this.disabled
};
this.$refs.FormCreate.contentWindow.postMessage({ method: "formInit", data }, '*');
break;
case "getOffsetHeight":
//
this.offsetHeight = event.data.offsetHeight;
break;
case "submitSuccess":
this.$modal.msgSuccess("办理成功");
this.cancel();
break;
}
},
//
cancel() {
this.showFormDialog = false;
this.$emit("update:visible", false);
this.$refs.FormCreate.contentWindow.postMessage({ method: "reset" }, '*');
this.$emit('refresh');
}
}
};
</script>

View File

@ -0,0 +1,283 @@
<template>
<div class="app-container">
<el-form :model="queryParams" ref="queryForm" size="mini" :inline="true" v-show="showSearch" label-width="100px">
<el-form-item label="表单编码" prop="formCode">
<el-input
v-model="queryParams.formCode"
placeholder="请输入表单编码"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="表单名称" prop="formName">
<el-input
v-model="queryParams.formName"
placeholder="请输入表单名称"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item label="表单版本" prop="version">
<el-input
v-model="queryParams.version"
placeholder="请输入表单版本"
clearable
@keyup.enter.native="handleQuery"
/>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
<el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
</el-form-item>
</el-form>
<el-row :gutter="10" class="mb8">
<el-col :span="1.5">
<el-button
type="primary"
plain
icon="el-icon-plus"
size="mini"
@click="handleAdd"
v-hasPermi="['form:definition:add']"
>新增</el-button>
</el-col>
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
</el-row>
<el-table v-loading="loading" :data="definitionList" @selection-change="handleSelectionChange" @sort-change="handleSortChange">
<el-table-column type="selection" width="55" align="center" fixed />
<el-table-column label="序号" width="50" align="center" key="id" prop="id">
<template slot-scope="scope">
{{ scope.$index + 1 }}
</template>
</el-table-column>
<el-table-column label="表单编码" align="center" prop="formCode" sortable="custom" :show-overflow-tooltip="true"/>
<el-table-column label="表单名称" align="center" prop="formName" sortable="custom" :show-overflow-tooltip="true"/>
<el-table-column label="表单版本" align="center" prop="version" sortable="custom" :show-overflow-tooltip="true">
<template slot-scope="scope">
<el-tag>{{scope.row.version}}</el-tag>
</template>
</el-table-column>
<el-table-column label="是否发布" align="center" prop="isPublish" sortable="custom" :show-overflow-tooltip="true">
<template slot-scope="scope">
<dict-tag :options="dict.type.is_publish" :value="scope.row.isPublish"/>
</template>
</el-table-column>
<el-table-column label="创建时间" align="center" prop="createTime" sortable="custom" :sort-orders="['descending', 'ascending']" :show-overflow-tooltip="true">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column label="操作" align="center" fixed="right" width="230" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
v-if="scope.row.formType === 0"
size="mini"
type="text"
@click="handleDesign(scope.row)"
v-hasPermi="['form:design:queryDesign']"
>表单设计</el-button>
<el-button
size="mini"
type="text"
v-if="scope.row.isPublish === 0"
@click="handlePublish(scope.row.id)"
v-hasPermi="['form:definition:publish']"
>发布</el-button>
<el-button
size="mini"
type="text"
v-if="scope.row.isPublish === 1"
@click="handleUpPublish(scope.row.id)"
v-hasPermi="['form:definition:upPublish']"
>取消发布</el-button>
<el-button
size="mini"
type="text"
@click="handleCopyDef(scope.row.id)"
v-hasPermi="['form:definition:upPublish']"
>复制表单</el-button>
<el-button
size="mini"
type="text"
v-if="scope.row.isPublish === 0"
@click="handleUpdate(scope.row.id)"
v-hasPermi="['form:definition:edit']"
>修改</el-button>
<el-button
size="mini"
type="text"
v-if="scope.row.isPublish === 0"
@click="handleDelete(scope.row)"
v-hasPermi="['form:definition:remove']"
>删除</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total>0"
:total="total"
:page.sync="queryParams.pageNum"
:limit.sync="queryParams.pageSize"
@pagination="getList"
/>
<Dialog ref="dialog" @refresh="getList"></Dialog>
<formDialog v-if="showFormDialog" :visible.sync="showFormDialog" :type="'2'" :formName="formName" :formId="formId"></formDialog>
</div>
</template>
<script>
import {
listDefinition,
delDefinition,
publish,
unPublish,
copyDef
} from "@/api/form/definition";
import Dialog from "./dialog";
import formDialog from "./formDialog";
export default {
name: "formDefinition",
dicts: ['is_publish', 'activity_status'],
components: {
Dialog,
formDialog
},
data() {
return {
//
loading: true,
imgUrl: "",
flowChart: false,
//
uniqueId: "",
//
ids: [],
//
single: true,
//
multiple: true,
//
showSearch: true,
//
total: 0,
//
definitionList: [],
//
queryParams: {
pageNum: 1,
pageSize: 10,
formCode: null,
formName: null,
version: null,
},
formName: "",
formId: "",
showFormDialog: false
};
},
created() {
this.getList();
},
activated() {
const time = this.$route.query.t;
if (time != null && time != this.uniqueId) {
this.uniqueId = time;
this.queryParams.pageNum = Number(this.$route.query.pageNum);
this.getList();
}
},
methods: {
/** 查询表单定义列表 */
getList() {
this.loading = true;
listDefinition(this.queryParams).then(response => {
this.definitionList = response.rows;
this.total = response.total;
this.loading = false;
});
},
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNum = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
//
handleSelectionChange(selection) {
this.ids = selection.map(item => item.id)
this.single = selection.length!==1
this.multiple = !selection.length
},
/** 新增按钮操作 */
handleAdd() {
this.$refs.dialog.show();
},
/** 表单设计按钮操作 */
handleDesign(row) {
if (row.isPublish === 1) {
this.formName = row.formName;
this.formId = row.id;
this.showFormDialog = true;
} else {
const params = { pageNum: this.queryParams.pageNum };
this.$tab.openPage("表单设计", '/form/form-design/index/' + row.id, params);
}
},
/** 发布按钮操作 */
handlePublish(id) {
this.$modal.confirm('是否确认发布表单定义编号为"' + id + '"的数据项?').then(function() {
return publish(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("发布成功");
}).catch(() => {});
},
/** 取消发布按钮操作 */
handleUpPublish(id) {
this.$modal.confirm('是否确认取消发布表单定义编号为"' + id + '"的数据项?').then(function() {
return unPublish(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("取消成功");
}).catch(() => {});
},
/** 修改按钮操作 */
handleUpdate(id) {
this.$refs.dialog.show(id);
},
/** 删除按钮操作 */
handleDelete(row) {
const ids = row.id || this.ids;
this.$modal.confirm('是否确认删除表单定义编号为"' + ids + '"的数据项?').then(function() {
return delDefinition(ids);
}).then(() => {
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
/** 复制表单按钮操作 */
handleCopyDef(id) {
this.$modal.confirm('是否确认复制表单定义编号为"' + id + '"的数据项?').then(function() {
return copyDef(id);
}).then(() => {
this.getList();
this.$modal.msgSuccess("复制成功");
}).catch(() => {});
},
/** 排序触发事件 */
handleSortChange(column, prop, order) {
this.queryParams.orderByColumn = column.prop;
this.queryParams.isAsc = column.order;
this.getList();
}
}
};
</script>

View File

@ -0,0 +1,38 @@
<template>
<div :style="'height:' + height">
<iframe :src="url" style="width: 100%; height: 100%"/>
</div>
</template>
<script>
import {getToken} from "@/utils/auth";
export default {
name: "WarmForm",
data() {
return {
height: document.documentElement.clientHeight - 94.5 + "px;",
url: ""
};
},
mounted() {
this.url = `${process.env.VUE_APP_FLOW_API}/warm-flow-ui/index.html?type=form&id=${this.$route.params.id}&disabled=${this.$route.query.disabled}&Authorization=Bearer ` + getToken();
window.addEventListener("message", this.handleMessage);
},
beforeDestroy() {
window.removeEventListener("message", this.handleMessage);
},
methods: {
handleMessage(event) {
switch (event.data.method) {
case "close":
this.close();
break;
}
},
close() {
const obj = { path: "/flow/form" };
this.$tab.closeOpenPage(obj);
}
}
};
</script>