hberp/hb_client/src/views/workflow/index.vue

566 lines
16 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="app-container">
<el-card>
<div>
<el-button
v-if="checkPermission(['workflow_create'])"
type="primary"
icon="el-icon-plus"
@click="handleCreate"
>
新增
</el-button>
<el-input
v-model="listQuery.search"
placeholder="名称"
style="width: 300px"
class="filter-item"
@keyup.enter.native="handleFilter"
/>
<el-button
class="filter-item"
type="primary"
icon="el-icon-search"
@click="handleFilter"
>
搜索
</el-button>
<el-button
class="filter-item"
type="primary"
icon="el-icon-refresh-left"
@click="resetFilter"
>
重置
</el-button>
</div>
</el-card>
<el-card style="margin-top: 2px">
<el-table
v-loading="listLoading"
:data="workflowList.results"
border fit stripe
style="width: 100%"
height="100"
highlight-current-row
v-el-height-adaptive-table="{bottomOffset: 50}"
>
<el-table-column type="index" width="50"/>
<el-table-column label="名称" prop="name">
</el-table-column>
<el-table-column label="描述" prop="description">
</el-table-column>
<el-table-column label="工单查看权限校验">
<template slot-scope="scope">
{{ !!(scope.row.view_permission_check)?'':'' }}
</template>
</el-table-column>
<el-table-column width="180" prop="create_time" label="创建时间">
</el-table-column>
<el-table-column
align="center"
label="操作"
width="300px"
>
<template slot-scope="scope">
<el-link
v-if="checkPermission(['workflow_update'])"
@click="handlecfgt(scope)"
>
配置
</el-link>
<el-link
v-if="checkPermission(['workflow_update'])"
@click="handleEdit(scope)"
>
编辑
</el-link>
<el-link
v-if="checkPermission(['workflow_delete'])"
type="danger"
@click="handleDelete(scope)"
>
删除
</el-link>
<el-link
v-if="checkPermission(['workflow_update'])"
type="primary"
@click="handleTicket(scope)"
>
查看工单
</el-link>
<el-link
v-if="checkPermission(['workflow_update'])"
type="primary"
@click="handleWatch(scope)"
>
查看流程图
</el-link>
</template>
</el-table-column>
</el-table>
<pagination
v-show="workflowList.count > 0"
:total="workflowList.count"
:page.sync="listQuery.page"
:limit.sync="listQuery.page_size"
@pagination="getList"
/>
</el-card>
<div class="svgMark" v-if="limitedWatch" @click="closeMark">
<div class="svgWrapper">
<div class="svgItem">工作流流程图<i class="el-dialog__close el-icon el-icon-close" @click="closeMark"></i></div>
<el-row>
<el-col :span="12">
<p>工作流名称 {{watchedName}}</p>
</el-col>
<el-col :span="12">
<p>创建时间 {{watchedCreateTime}}</p>
</el-col>
</el-row>
<div style="width: 90%;margin: auto;">
<svg height=1000 id="mySvg" style="width:100%!important;">
</svg>
</div>
</div>
</div>
<el-dialog
:visible.sync="dialogVisible"
:title="dialogType === 'edit' ? '编辑工作流' : '新增工作流'">
<el-form
ref="Form"
:model="workflow"
label-width="100px"
label-position="right"
:rules="rule1"
>
<el-form-item label="名称" prop="name">
<el-input v-model="workflow.name" placeholder="名称"/>
</el-form-item>
<el-form-item label="流水号前缀">
<el-input v-model="workflow.sn_prefix " placeholder="流水号前缀"/>
</el-form-item>
<el-form-item label="描述" prop="description">
<el-input
v-model="workflow.description"
type="textarea"
:rows="4"
placeholder="描述"
/>
</el-form-item>
<el-form-item
label="查看权限校验"
prop="view_permission_check"
label-width="120px"
>
<el-switch v-model="workflow.view_permission_check"></el-switch>
</el-form-item>
<el-form-item label="展现表单字段">
<el-transfer
v-model="workflow.display_form_str"
:data="choiceOption"
:titles="['未展示字段', '展示字段']"
:props="{ key: 'id', label: 'field_name' }"
/>
</el-form-item>
<el-form-item label="标题模板" prop="title_template">
<el-input v-model="workflow.title_template" placeholder="你有一个待办工单:{title}"/>
</el-form-item>
<el-form-item label="内容模板" prop="content_template">
<el-input v-model="workflow.content_template" placeholder="标题:{title}, 创建时间:{create_time}"/>
</el-form-item>
</el-form>
<div style="text-align: right">
<el-button type="danger" @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="confirm('Form')">确认</el-button>
</div>
</el-dialog>
</div>
</template>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
import {
getWfTransitionList,
getWorkflowList,
createWorkflow,
updateWorkflow,
deleteWorkflow,
getWfCustomfieldList,
getWfStateList
} from "@/api/workflow";
import checkPermission from "@/utils/permission";
// import vueJsonEditor from 'vue-json-editor'
import Pagination from "@/components/Pagination"; // secondary package based on el-pagination
import dagreD3 from 'dagre-d3'
import * as d3 from 'd3'
const defaultworkflow = {
name: "",
number: "",
};
export default {
components: {Pagination},
data() {
return {
// workflow: defaultworkflow,
workflow: {
name: '',
sn_prefix: '',
description: '',
view_permission_check: '',
display_form_str: '',
title_template: '',
content_template: '',
},
limitedWatch: false,
view_permission_check: false,
hasJsonFlag: true, // json是否验证通过
hasJsonFlag1: true, // json是否验证通过
workflowList: {
count: 0,
},
listQuery: {
page: 1,
page_size: 20,
},
choiceOption: [],
display_form_str: [],
limit_expression: [],
listLoading: true,
dialogVisible: false,
dialogType: "new",
watchedName: '',
watchedCreateTime: '',
rule1: {
name: [{required: true, message: "请输入", trigger: "blur"}],
description: [{required: true, message: "请输入", trigger: "blur"}]
},
};
},
computed: {},
watch: {},
created() {
this.getList();
},
methods: {
checkPermission,
getList() {
this.listLoading = true;
getWorkflowList(this.listQuery).then((response) => {
if (response.data) {
this.workflowList = response.data;
}
this.listLoading = false;
});
},
handleFilter() {
this.listQuery.page = 1;
this.getList();
},
resetFilter() {
this.listQuery = {
page: 1,
page_size: 20,
}
this.getList();
},
handleCreate() {
this.workflow = Object.assign({}, defaultworkflow);
this.dialogType = "new";
this.dialogVisible = true;
this.$nextTick(() => {
this.$refs["Form"].clearValidate();
});
},
handleEdit(scope) {
this.workflow = Object.assign({}, scope.row); // copy obj
this.dialogType = "edit";
this.dialogVisible = true;
this.$nextTick(() => {
this.$refs["Form"].clearValidate();
});
getWfCustomfieldList(scope.row.id).then((response) => {
if (response.data) {
this.choiceOption = response.data;
}
});
},
handlecfgt(scope) {
this.$router.push({name: "configuration", params: {workflow: scope.row.id}})
},
handleDelete(scope) {
this.$confirm("确认删除?", "警告", {
confirmButtonText: "确认",
cancelButtonText: "取消",
type: "error",
})
.then(async () => {
await deleteWorkflow(scope.row.id);
this.getList();
this.$message.success("成功");
})
.catch((err) => {
console.error(err);
});
},
handleTicket(scope) {
this.$router.push({name: "workFlowTickets", params: {workflow: scope.row.id}})
},
async confirm(form) {
// console.log(this.workflow.display_form_str)
this.$refs[form].validate((valid) => {
if (valid) {
const isEdit = this.dialogType === "edit";
if (isEdit) {
this.checkJson();
this.checkJson2();
updateWorkflow(this.workflow.id, this.workflow).then((res) => {
if (res.code >= 200) {
this.getList();
this.dialogVisible = false;
this.$message.success("成功");
}
});
} else {
this.checkJson();
this.checkJson2();
createWorkflow(this.workflow).then((res) => {
if (res.code >= 200) {
this.getList();
this.dialogVisible = false;
this.$message.success("成功");
}
});
}
} else {
return false;
}
});
},
handleWatch(scope) {
let that = this;
let workFlow = scope.row.id;
that.watchedName = scope.row.name;
that.watchedCreateTime = scope.row.create_time;
that.limitedWatch = true;
that.$nextTick(() => {
var g = new dagreD3.graphlib.Graph().setGraph({
rankdir: 'DL',
nodesep: 100,
edgesep: 10,//两条线之间的距离
ranksep: 50,//节点之间的距离
marginx: 160,
marginy: 20,
});
//获取state得到节点
getWfStateList(workFlow).then((response) => {
if (response.data) {
let nodes = response.data;
// 添加节点
nodes.forEach((item) => {
g.setNode(item.id, {
// 节点标签
label: item.name,
// 节点形状
shape: 'rect',
toolText: item.name,
//节点样式
style: "fill:#fff;stroke:#000",
labelStyle: "fill:#000;",
rx: 5,//矩形节点圆角度
ry: 5
});
});
g.nodes().forEach(function (v) {
console.log("Node " + v + ": " + JSON.stringify(g.node(v)));
});
//获取流转得到线 链接关系
getWfTransitionList(workFlow).then((res) => {
if (res.data) {
let transitionList = res.data;
transitionList.forEach((transition0) => {
if (transition0.condition_expression.length > 0) {
debugger;
g.setNode(transition0.source_state_.id + 100000, {
label: "条件表达式",
style: "stroke: #000;fill: #afa",
shape: "diamond"
});
g.setEdge(transition0.source_state_.id, transition0.source_state_.id + 100000, {
// 边标签
label: transition0.name,
style: "fill:#ffffff;stroke:#c0c1c3;stroke-width:1.5px"
});
let condition_expression = transition0.condition_expression;
condition_expression.forEach(condition_expression0 => {
g.setEdge(transition0.source_state_.id + 100000, condition_expression0.target_state, {
label: condition_expression0.label,
style: "fill:#ffffff;stroke:#c0c1c3;stroke-width:1.5px"
})
})
} else {
g.setEdge(transition0.source_state_.id, transition0.destination_state_.id, {
// 边标签
label: transition0.name,
// 边样式
style: "fill:#ffffff;stroke:#c0c1c3;stroke-width:1.5px" // 根据后台数据来改变连线的颜色
});
}
})
g.nodes().length - 1
g.nodes().forEach(function (v) {
console.log("Node " + v + ": " + JSON.stringify(g.node(v)));
});
// 创建渲染器
let render = new dagreD3.render();
// 选择 svg 并添加一个g元素作为绘图容器.
let svg = d3.select('#mySvg');
let svgGroup = svg.append('g');
// 在绘图容器上运行渲染器生成流程图.
render(d3.select("svg g"), g);
} else {
}
});
}
});
})
},
closeMark() {
this.limitedWatch = false;
},
onJsonChange(value) {
// console.log('更改value:', value);
// 实时保存
this.onJsonSave(value)
},
onJsonSave(value) {
// console.log('保存value:', value);
this.limit_expression = value
this.hasJsonFlag = true
},
onError(value) {
this.hasJsonFlag = false
},
onJsonChange1(value) {
// 实时保存
this.onJsonSave1(value)
},
onJsonSave1(value) {
this.display_form_str = value
this.hasJsonFlag1 = true
},
onError1(value) {
this.hasJsonFlag1 = false
},
// 检查json
checkJson() {
if (this.hasJsonFlag == false) {
// alert("限制表达式json验证失败")
return false
} else {
// alert("限制表达式json验证成功")
return true
}
},
// 检查json
checkJson2() {
if (this.hasJsonFlag1 == false) {
// alert("展现表单字段json验证失败")
return false
} else {
// alert("展现表单字段json1验证成功")
return true
}
},
},
};
</script>
<style scoped>
::-webkit-scrollbar {
width: 15px;
}
::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .2);
background-color: #fefefe;
border-radius: 7px;
}
::-webkit-scrollbar-thumb {
border-radius: 7px;
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .5);
background-color: #f5f5f5;
}
.svgMark {
width: 100%;
height: 100%;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
overflow: auto;
margin: 0;
z-index: 2000;
background: rgba(0, 0, 0, .3);
}
.svgWrapper {
background: #fff;
width: 800px;
margin: 10vh auto 0;
text-align: center;
border-radius: 2px;
max-height: 80vh;
overflow-y: scroll;
}
.svgItem {
padding: 20px 40px 0;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Arial, sans-serif;
font-size: 18px;
display: flex;
justify-content: space-between;
}
svg {
font-size: 14px;
}
.node rect {
stroke: #606266;
fill: #fff;
}
.edgePath path {
stroke: #606266;
fill: #333;
stroke-width: 1.5px;
}
g.conditions > rect {
fill: #00ffd0;
stroke: #000;
}
.el-icon-close {
cursor: pointer;
}
</style>