yudao-dev/src/views/extend/processFlowView/components/ProcessDetail.vue

520 lines
11 KiB
Vue
Raw Normal View History

2023-11-10 17:02:52 +08:00
<!--
2023-10-20 16:03:40 +08:00
filename: ProcessGraph.vue
author: liubin
date: 2023-10-20 15:00:58
2023-11-10 17:02:52 +08:00
description:
2023-10-20 16:03:40 +08:00
-->
<template>
<section class="process-graph">
<SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" />
2023-11-16 22:00:50 +08:00
<div
class="btns"
style="text-align: right; position: absolute; top: 20px; right: 20px">
<el-button
type="warning"
@click="undo"
plain
v-if="allowUndo"
:disabled="!allowUndo"
icon="el-icon-back">
2023-10-24 11:17:07 +08:00
撤销
</el-button>
2023-11-16 22:00:50 +08:00
<el-button
type="warning"
@click="redo"
plain
v-if="allowRedo"
:disabled="!allowRedo">
2023-10-24 11:17:07 +08:00
下一步
<i class="el-icon-right el-icon--right"></i>
</el-button>
2023-11-16 22:00:50 +08:00
<el-button
class="btn-refresh"
@click="handleUpdateLayout"
icon="el-icon-refresh">
刷新布局
</el-button>
<el-button
type="primary"
plain
class="btn-create"
icon="el-icon-plus"
@click="handleAdd">
2023-10-20 16:42:28 +08:00
新建工序
</el-button>
2023-11-16 22:00:50 +08:00
<el-button
class="btn-edit"
:disabled="currentDet == null"
@click="handleEdit">
编辑
</el-button>
2023-10-20 16:42:28 +08:00
</div>
2023-10-20 16:03:40 +08:00
<div class="process-graph__panel" ref="panel"></div>
2023-10-24 11:17:07 +08:00
2023-11-16 22:00:50 +08:00
<base-dialog
:dialogTitle="title"
:dialogVisible="open"
width="35%"
@close="cancel"
@cancel="cancel"
2023-10-24 11:17:07 +08:00
@confirm="submitForm">
<DialogForm v-if="open" ref="form" v-model="form" :rows="rows" />
</base-dialog>
2023-10-20 16:03:40 +08:00
</section>
</template>
<script>
import { Graph } from '@antv/x6';
2023-11-16 22:00:50 +08:00
import ProcessNode, {
createProcessNode,
CACHE_NAME,
getSectionFrom,
} from './ProcessNode';
2023-10-24 11:17:07 +08:00
import DialogForm from '@/components/DialogForm';
2023-10-24 15:56:15 +08:00
// import { IdToName } from '@/utils'
2023-10-20 16:03:40 +08:00
2023-11-16 22:00:50 +08:00
Graph.registerNode('process-node', ProcessNode, true);
2023-10-20 16:03:40 +08:00
export default {
name: 'ProcessGraph',
2023-10-24 11:17:07 +08:00
components: { DialogForm },
2023-10-20 16:03:40 +08:00
props: {},
2023-10-24 11:17:07 +08:00
inject: ['getFlowId'],
2023-10-20 16:03:40 +08:00
data() {
return {
2023-10-24 11:17:07 +08:00
allowRedo: false,
allowUndo: false,
2023-10-20 16:42:28 +08:00
graph: null,
2023-10-20 16:03:40 +08:00
searchBarFormConfig: [{ label: '工序列表' }],
2023-10-24 11:17:07 +08:00
title: '',
open: false,
form: {
name: '', // 工序名称
sectionId: '', // 工段id
remark: '', // 描述
},
rows: [
[
{
input: true,
label: '工序名称',
prop: 'name',
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
},
],
[
{
select: true,
label: '工段',
prop: 'sectionId',
url: '/base/core-workshop-section/listAll',
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
bind: {
filterable: true,
},
2023-11-16 22:00:50 +08:00
cache: CACHE_NAME,
2023-10-24 11:17:07 +08:00
},
],
[
{
textarea: true,
label: '工序说明',
prop: 'remark',
},
],
],
2023-10-26 11:28:24 +08:00
updateUrl: '/extend/process-flow-det/update',
deleteUrl: '/extend/process-flow-det/delete',
addUrl: '/extend/process-flow-det/create',
2023-10-24 11:17:07 +08:00
// pageUrl: '/extend/process-flow-det/get',
2023-10-25 17:02:43 +08:00
infoUrl: '/extend/process-flow-view/getByFlowId',
2023-10-24 17:07:32 +08:00
layout: {
id: null,
flowId: null,
content: '',
2023-11-16 22:00:50 +08:00
createTime: null,
2023-10-24 17:07:32 +08:00
},
2023-10-25 17:02:43 +08:00
currentDet: null,
2023-11-16 22:00:50 +08:00
currentNode: null,
2023-10-20 16:03:40 +08:00
};
},
2023-10-24 11:17:07 +08:00
watch: {
'form.sectionId': {
2023-11-16 22:00:50 +08:00
handler(id) {},
2023-10-24 11:17:07 +08:00
immediate: false,
},
2023-10-25 17:02:43 +08:00
currentDet: {
handler(val) {
2023-11-16 22:00:50 +08:00
this.$emit('det-selected', val);
2023-10-25 17:02:43 +08:00
},
deep: true,
2023-11-16 22:00:50 +08:00
immediate: true,
},
2023-10-24 11:17:07 +08:00
},
2023-10-24 17:07:32 +08:00
activated() {
2023-11-16 22:00:50 +08:00
this.loadLayout().then((json) => {
this.initGraph(json);
});
2023-10-20 16:03:40 +08:00
},
2023-10-25 17:02:43 +08:00
deactivated() {
this.graph.dispose();
this.$nextTick(() => {
this.resetLayout();
this.graph = null;
2023-11-16 22:00:50 +08:00
});
2023-10-25 17:02:43 +08:00
},
2023-10-20 16:03:40 +08:00
computed: {},
2023-10-20 16:42:28 +08:00
methods: {
2023-10-24 15:56:15 +08:00
initGraph(json) {
const graph = new Graph({
container: this.$refs.panel,
grid: {
size: 10,
visible: true,
},
2023-10-25 17:02:43 +08:00
history: true,
selecting: {
2023-11-16 22:00:50 +08:00
className: 'my-select',
2023-10-25 17:02:43 +08:00
},
connecting: {
snap: true,
allowBlank: false,
allowLoop: false,
allowNode: false,
allowPort: true,
allowEdge: false,
},
2023-10-26 11:28:24 +08:00
panning: true,
2023-10-25 17:02:43 +08:00
mousewheel: {
enabled: true,
2023-11-16 22:00:50 +08:00
modifiers: ['ctrl', 'meta'],
},
2023-10-24 15:56:15 +08:00
});
2023-11-16 22:00:50 +08:00
graph.fromJSON(json);
2023-10-24 15:56:15 +08:00
this.graph = graph;
2023-10-25 17:02:43 +08:00
this.$nextTick(() => {
this.registerGraphEvents();
2023-11-16 22:00:50 +08:00
});
2023-10-25 17:02:43 +08:00
},
registerGraphEvents() {
const reset = () => {
const nodes = this.graph.getNodes();
const edges = this.graph.getEdges();
this.currentDet = null;
2023-10-26 11:28:24 +08:00
this.currentNode = null;
2023-11-16 22:00:50 +08:00
nodes.forEach((node) => {
2023-10-25 17:02:43 +08:00
node.attr('container/stroke', '#ccc');
});
2023-11-16 22:00:50 +08:00
edges.forEach((edge) => {
edge.attr('line/stroke', '#ccc');
});
};
2023-10-25 17:02:43 +08:00
this.graph.on('node:click', ({ e, x, y, node, view }) => {
reset();
node.attr('container/stroke', '#0b58ff');
2023-11-16 22:00:50 +08:00
const { detId, detName, detDesc, processId, sectionId, sectionName } =
node.attrs;
console.log('node clicked!', node)
this.currentDet = {};
2023-11-17 09:48:39 +08:00
this.$set(this.currentDet, 'detId', detId?.text);
this.$set(this.currentDet, 'sectionId', sectionId?.text);
this.$set(this.currentDet, 'detName', detName?.text);
this.$set(this.currentDet, 'detDesc', detDesc?.text);
this.$set(this.currentDet, 'flowId', processId?.text);
this.$set(this.currentDet, 'sectionName', sectionName?.text);
2023-11-16 22:00:50 +08:00
this.currentNode = node;
2023-10-25 17:02:43 +08:00
});
this.graph.on('edge:click', ({ e, x, y, edge, view }) => {
// console.log('edge clicked!', edge)
reset();
2023-11-16 22:00:50 +08:00
edge.attr('line/stroke', '#0b58ff');
2023-10-25 17:02:43 +08:00
});
this.graph.on('blank:click', ({ e, x, y }) => {
reset();
});
this.graph.on('node:mouseenter', ({ node }) => {
node.addTools({
name: 'button-remove',
args: {
x: '100%',
y: 0,
offset: { x: 0, y: 0 },
onClick: ({ e, cell, view }) => {
2023-11-16 22:00:50 +08:00
this.$confirm('确定删除这个工序吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
2023-10-25 17:02:43 +08:00
})
2023-11-16 22:00:50 +08:00
.then(async () => {
const id = node.attrs.detId.text;
const status = await this.handleDelete(id);
if (status) {
view.cell.remove();
2023-11-17 09:48:39 +08:00
// 更新布局,不然下次打开删除的节点还在
this.handleUpdateLayout();
2023-11-16 22:00:50 +08:00
}
})
.catch((err) => {
return;
});
},
},
});
2023-10-25 17:02:43 +08:00
});
this.graph.on('node:mouseleave', ({ node }) => {
node.removeTools();
2023-11-16 22:00:50 +08:00
});
2023-10-24 15:56:15 +08:00
},
2023-10-24 17:07:32 +08:00
resetLayout() {
this.layout = {
id: null,
flowId: null,
content: '',
2023-11-16 22:00:50 +08:00
createTime: null,
};
2023-10-24 17:07:32 +08:00
},
async loadLayout() {
const flowId = this.$route.params.id;
2023-11-16 22:00:50 +08:00
if (!flowId) return { cells: [] };
2023-10-24 17:07:32 +08:00
const { code, data } = await this.info({ id: flowId });
if (code == 0) {
if (data) {
this.layout = data;
return JSON.parse(data?.content) || { cells: [] };
}
return { cells: [] };
}
this.resetLayout();
return Promise.reject(this.infoUrl + ' 接口出错!');
2023-10-24 15:56:15 +08:00
},
2023-11-16 22:00:50 +08:00
handleToJson() {},
2023-10-24 15:56:15 +08:00
2023-11-16 22:00:50 +08:00
handleLoadJson() {},
2023-10-24 15:56:15 +08:00
handleDumpJson() {
2023-10-20 16:42:28 +08:00
if (this.graph) {
console.log(JSON.stringify(this.graph.toJSON(), null, 2));
}
},
2023-10-24 15:56:15 +08:00
2023-10-24 17:07:32 +08:00
async handleUpdateLayout() {
this.layout.content = JSON.stringify(this.graph.toJSON());
let code, data;
2023-11-16 22:00:50 +08:00
console.table([this.layout, this.$route.params.id]);
2023-10-24 15:56:15 +08:00
// 手动刷新布局
2023-10-24 17:07:32 +08:00
if (this.layout.id) {
2023-11-16 22:00:50 +08:00
({ code, data } = await this.http(
'/extend/process-flow-view/update',
'put',
this.layout
));
2023-10-24 17:07:32 +08:00
} else {
this.layout.flowId = this.$route.params.id;
2023-11-16 22:00:50 +08:00
({ code, data } = await this.http(
'/extend/process-flow-view/create',
'post',
this.layout
));
2023-10-24 17:07:32 +08:00
}
if (code == 0) {
2023-11-16 22:00:50 +08:00
this.$modal.msgSuccess('布局已刷新!');
2023-10-24 17:07:32 +08:00
}
2023-10-24 15:56:15 +08:00
},
2023-10-24 11:17:07 +08:00
reset() {
this.form = {
name: '', // 工序名称
sectionId: '', // 工段id
remark: '', // 描述
};
this.resetForm('form');
},
2023-10-24 15:56:15 +08:00
2023-10-24 11:17:07 +08:00
/** 取消按钮 */
cancel() {
this.open = false;
this.reset();
},
2023-10-24 15:56:15 +08:00
2023-10-24 11:17:07 +08:00
handleAdd() {
this.reset();
this.open = true;
this.title = '添加工序';
},
2023-10-24 15:56:15 +08:00
2023-10-24 11:17:07 +08:00
handleEdit() {
2023-10-26 11:28:24 +08:00
this.form.name = this.currentDet.detName;
this.form.sectionId = this.currentDet.sectionId;
this.form.remark = this.currentDet.detDesc;
this.form.id = this.currentDet.detId;
2023-10-24 11:17:07 +08:00
this.title = '编辑工序';
2023-10-26 11:28:24 +08:00
this.$nextTick(() => {
this.open = true;
2023-11-16 22:00:50 +08:00
});
2023-10-24 11:17:07 +08:00
},
2023-10-24 15:56:15 +08:00
2023-10-26 11:28:24 +08:00
async handleDelete(id) {
const { code, data } = await this.delete({ id });
if (code == 0) {
2023-10-26 14:07:36 +08:00
this.$modal.msgSuccess('成功删除一个工序!');
2023-10-26 11:28:24 +08:00
return true;
}
return false;
},
2023-10-24 15:56:15 +08:00
2023-10-24 11:17:07 +08:00
/** 提交按钮 */
submitForm() {
this.$refs['form'].validate((valid) => {
if (!valid) {
return;
}
// 修改的提交
if (this.form.id != null) {
2023-10-26 11:28:24 +08:00
this.updateProcess()
.then((form) => {
const { name, sectionId, remark } = form;
2023-11-16 22:00:50 +08:00
getSectionFrom(sectionId).then((sectionName) => {
2023-11-10 17:02:52 +08:00
// 修改当前node的信息
2023-10-26 11:28:24 +08:00
this.currentNode.setAttrs({
detName: { text: name },
sectionId: { text: sectionId },
sectionName: { text: sectionName },
2023-11-16 22:00:50 +08:00
detDesc: { text: remark },
});
});
2023-10-26 11:28:24 +08:00
})
2023-11-16 22:00:50 +08:00
.catch((err) => {});
2023-10-24 11:17:07 +08:00
return;
}
2023-10-24 15:56:15 +08:00
this.createProcess()
2023-10-26 11:28:24 +08:00
.then(({ id, name, sectionId, remark, flowId }) => {
if (!id) return null;
2023-10-24 15:56:15 +08:00
return createProcessNode({
flowId: flowId,
2023-11-16 22:00:50 +08:00
name,
sectionId,
remark,
2023-10-24 11:17:07 +08:00
id,
2023-11-16 22:00:50 +08:00
});
})
.then((node) => {
2023-10-24 15:56:15 +08:00
if (!node) {
this.$modal.msgError('创建节点失败');
return;
2023-11-16 22:00:50 +08:00
}
2023-10-24 15:56:15 +08:00
this.graph.addNode(node);
2023-11-16 22:00:50 +08:00
})
.catch((err) => {
2023-10-26 11:28:24 +08:00
return;
2023-10-24 15:56:15 +08:00
});
2023-10-24 11:17:07 +08:00
});
},
2023-10-24 15:56:15 +08:00
2023-10-24 11:17:07 +08:00
updateProcess() {
2023-10-26 11:28:24 +08:00
const flowId = this.getFlowId();
if (!flowId) {
this.$modal.msgError('工艺ID不能为空');
return Promise.reject('工艺ID不能为空');
}
2023-11-16 22:00:50 +08:00
return this.put({ flowId, ...this.form }).then(({ code, data }) => {
if (code == 0) {
this.$modal.msgSuccess('修改成功');
} else {
this.$modal.msgError('修改失败');
}
const formCopy = { ...this.form };
this.open = false;
return formCopy;
});
2023-10-24 11:17:07 +08:00
},
2023-10-24 15:56:15 +08:00
2023-10-24 11:17:07 +08:00
createProcess() {
2023-10-24 15:56:15 +08:00
// const flowId = this.$route.params.id;
const flowId = this.getFlowId(); // it also works
2023-10-24 11:17:07 +08:00
if (!flowId) {
this.$modal.msgError('工艺ID不能为空');
2023-10-26 11:28:24 +08:00
return Promise.reject('工艺ID不能为空');
2023-10-24 11:17:07 +08:00
}
2023-11-16 22:00:50 +08:00
console.log('create process', this.form);
2023-10-24 11:17:07 +08:00
// 添加的提交
2023-11-16 22:00:50 +08:00
return this.post({ flowId, ...this.form })
.then(({ code, data }) => {
2023-10-24 11:17:07 +08:00
this.$modal.msgSuccess('新增成功');
this.open = false;
// this.getList();
2023-10-24 15:56:15 +08:00
return {
id: data, // 服务器返回的新建的工段id
2023-11-16 22:00:50 +08:00
...this.form, // 保存一份 this.form 副本,当 open->false 时 this.form 里的信息就清空了
flowId,
2023-10-24 15:56:15 +08:00
};
2023-11-16 22:00:50 +08:00
})
.catch((err) => {
this.$modal.msgError(err);
});
2023-10-24 11:17:07 +08:00
},
2023-10-24 15:56:15 +08:00
2023-10-24 11:17:07 +08:00
put(payload) {
return this.http(this.updateUrl, 'put', payload);
},
post(payload) {
return this.http(this.addUrl, 'post', payload);
},
recv(payload) {
return this.http(this.pageUrl, 'get', payload);
},
info(payload) {
return this.http(this.infoUrl, 'get', payload);
},
2023-10-26 14:07:36 +08:00
delete({ id }) {
return this.$axios({
url: this.deleteUrl + `?id=${id}`,
method: 'delete',
});
2023-10-26 11:28:24 +08:00
},
2023-10-24 11:17:07 +08:00
http(url, method, payload) {
return this.$axios({
url,
method,
params: method === 'get' ? payload : null,
data: method !== 'get' ? payload : null,
2023-11-16 22:00:50 +08:00
});
2023-10-24 11:17:07 +08:00
},
2023-10-20 16:42:28 +08:00
},
2023-10-20 16:03:40 +08:00
};
</script>
<style scoped lang="scss">
.process-graph {
padding: 12px 20px 20px;
background: #fff;
border-radius: 8px;
2023-10-20 16:42:28 +08:00
position: relative;
2023-10-20 16:03:40 +08:00
}
.process-graph__panel {
height: 300px;
}
</style>
2023-10-24 11:17:07 +08:00
<style>
.x6-widget-selection-selected {
border: 1px solid red;
}
2023-10-25 17:02:43 +08:00
.my-select {
border: 1px solid red;
}
2023-10-24 11:17:07 +08:00
</style>