<!-- 
    filename: ProcessGraph.vue
    author: liubin
    date: 2023-10-20 15:00:58
    description: 
-->

<template>
	<section class="process-graph">
		<SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" />

		<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">
				撤销
			</el-button>
			<el-button type="warning" @click="redo" plain v-if="allowRedo" :disabled="!allowRedo">
				下一步
				<i class="el-icon-right el-icon--right"></i>
			</el-button>
			<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">
				新建工序
			</el-button>
			<el-button class="btn-serialize" @click="handleToJson">序列化</el-button>
			<el-button class="btn-antiserialize" @click="handleLoadJson">
				反序列化
			</el-button>
			<el-button class="btn-edit" @click="handleEdit">编辑</el-button>
			<el-button type="error" class="btn-delete" @click="handleDelete">
				删除
			</el-button>
		</div>

		<div class="process-graph__panel" ref="panel"></div>

		<!-- 对话框(添加 / 修改) -->
		<base-dialog :dialogTitle="title" :dialogVisible="open" width="35%" @close="cancel" @cancel="cancel"
			@confirm="submitForm">
			<DialogForm v-if="open" ref="form" v-model="form" :rows="rows" />
		</base-dialog>
	</section>
</template>

<script>
import { Graph } from '@antv/x6';
import ProcessNode, { createProcessNode, CACHE_NAME } from './ProcessNode';
import DialogForm from '@/components/DialogForm';
// import { IdToName } from '@/utils'

Graph.registerNode('process-node', ProcessNode);

export default {
	name: 'ProcessGraph',
	components: { DialogForm },
	props: {},
	inject: ['getFlowId'],
	data() {
		return {
			allowRedo: false,
			allowUndo: false,
			graph: null,
			searchBarFormConfig: [{ label: '工序列表' }],
			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,
						},
						cache: CACHE_NAME
					},
				],
				[
					{
						textarea: true,
						label: '工序说明',
						prop: 'remark',
					},
				],
			],
			updateUrl: '/extend/process-flow-view/update',
			addUrl: '/extend/process-flow-view/create',
			// pageUrl: '/extend/process-flow-det/get',
			infoUrl: '/extend/process-flow-view/get',
			layout: {
				id: null,
				flowId: null,
				content: '',
				createTime: null
			},

		};
	},
	watch: {
		'form.sectionId': {
			handler(id) {
				// const { form } = this;
				// const { sectionId } = form;
				// if (sectionId) {
				// 	const { label } = this.$refs['form'].getSelectItem(
				// 		'sectionId',
				// 		sectionId
				// 	);
				// 	form.workshopName = label;
				// }
			},
			immediate: false,
		},
	},
	activated() {
		this.loadLayout().then(json => {
			this.initGraph(json)
		})

		// const pn1 = graph.addNode({
		// 	shape: 'process-node',
		// 	x: 30,
		// 	y: 30,
		// 	processName: '工序00A',
		// 	workshopName: '工段1',
		// 	processDesc: 'test test test',
		// 	processId: '1',
		// 	tools: [{ name: 'button-remove' }],
		// });
		// const pn2 = graph.addNode({
		// 	shape: 'process-node',
		// 	x: 240,
		// 	y: 30,
		// 	processName: '工序00B',
		// 	workshopName: '工段1',
		// 	processDesc: 'test test test',
		// 	processId: '1',
		// });

		// const pn3 = graph.addNode({
		// 	shape: 'process-node',
		// 	x: 360,
		// 	y: 30,
		// 	processName: '工序00C',
		// 	workshopName: '工段1',
		// 	processDesc: 'test test test',
		// 	processId: '1',
		// });

		// const pn4 = graph.addNode({
		// 	shape: 'process-node',
		// 	x: 360,
		// 	y: 120,
		// 	processName: '工序00D',
		// 	workshopName: '工段1',
		// 	processDesc: 'test test test',
		// 	processId: '1',
		// });

		// const pn5 = graph.addNode({
		// 	shape: 'process-node',
		// 	x: 500,
		// 	y: 30,
		// 	processName: '工序00E',
		// 	workshopName: '工段1',
		// 	processDesc: 'test test test',
		// 	processId: '1',
		// });

		// graph.addEdge({
		// 	source: pn1,
		// 	target: pn2,
		// 	router: {
		// 		name: 'er',
		// 	},
		// 	attrs: {
		// 		line: {
		// 			stroke: '#0b58ff',
		// 			strokeWidth: 1,
		// 			targetMarker: {
		// 				// name: 'classic',
		// 				// name: 'async',
		// 				size: 0,
		// 			},
		// 		},
		// 	},
		// });
		// graph.addEdge({
		// 	source: pn2,
		// 	target: pn3,
		// 	router: {
		// 		name: 'er',
		// 	},
		// 	attrs: {
		// 		line: {
		// 			stroke: '#0b58ff',
		// 			strokeWidth: 1,
		// 			targetMarker: {
		// 				// name: 'classic',
		// 				// name: 'async',
		// 				size: 0,
		// 			},
		// 		},
		// 	},
		// });
		// graph.addEdge({
		// 	source: pn2,
		// 	target: pn4,
		// 	router: {
		// 		name: 'er',
		// 	},
		// 	attrs: {
		// 		line: {
		// 			stroke: '#0b58ff',
		// 			strokeWidth: 1,
		// 			targetMarker: {
		// 				// name: 'classic',
		// 				// name: 'async',
		// 				size: 0,
		// 			},
		// 		},
		// 	},
		// });
		// graph.addEdge({
		// 	source: pn3,
		// 	target: pn5,
		// 	router: {
		// 		name: 'er',
		// 	},
		// 	attrs: {
		// 		line: {
		// 			stroke: '#0b58ff',
		// 			strokeWidth: 1,
		// 			targetMarker: {
		// 				// name: 'classic',
		// 				// name: 'async',
		// 				size: 0,
		// 			},
		// 		},
		// 	},
		// });
		// graph.addEdge({
		// 	source: pn4,
		// 	target: pn5,
		// 	router: {
		// 		name: 'er',
		// 	},
		// 	attrs: {
		// 		line: {
		// 			stroke: '#0b58ff',
		// 			strokeWidth: 1,
		// 			targetMarker: {
		// 				// name: 'classic',
		// 				// name: 'async',
		// 				size: 0,
		// 			},
		// 		},
		// 	},
		// });

		// const pn1 = graph.addNode({
		// 	shape: 'process-node',
		// 	x: 0,
		// 	y: 0,
		// 	detName: '测试工序', // 工序名称
		// 	sectionName: 'default', // 工段
		// 	detDesc: 'loremakdfkd...', // 工序说明
		// 	processId: 'p-1', // 工艺ID
		// 	detId: 'det-id-1', // 工序ID
		// 	tools: [{ name: 'button-remove' }],
		// });

		// const htmlNode = graph.addNode({
		// 	x: 0,
		// 	y: 0,
		// 	width: 200,
		// 	height: 100,
		// 	shape: 'html',
		// 	html() {
		// 		const ctn = document.createElement('div');
		// 		ctn.style.width = '100%';
		// 		ctn.style.height = '100%';
		// 		ctn.style.border = '1px solid #ccc';
		// 		ctn.style.background = '#fff';
		// 		ctn.innerText = 'hello';

		// 		return ctn;
		// 	},
		// });
	},
	computed: {},
	methods: {
		initGraph(json) {
			const graph = new Graph({
				container: this.$refs.panel,
				grid: {
					size: 10,
					visible: true,
				},
				history: true
			});
			graph.fromJSON(json)

			this.graph = graph;
		},

		resetLayout() {
			this.layout = {
				id: null,
				flowId: null,
				content: '',
				createTime: null
			}
		},

		async loadLayout() {
			const flowId = this.$route.params.id;
			if (!flowId) return { cells: [] }
			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 + ' 接口出错!');
		},

		handleToJson() { },

		handleLoadJson() { },

		handleDumpJson() {
			if (this.graph) {
				console.log(JSON.stringify(this.graph.toJSON(), null, 2));
			}
		},

		async handleUpdateLayout() {
			this.layout.content = JSON.stringify(this.graph.toJSON());
			let code, data;
			// 手动刷新布局
			if (this.layout.id) {
				({ code, data } = await this.put(this.layout));
			} else {
				this.layout.flowId = this.$route.params.id;
				({ code, data } = await this.post(this.layout));
			}

			if (code == 0) {
				this.$modal.msgSuccess('布局已刷新!')
			}
		},

		reset() {
			this.form = {
				name: '', // 工序名称
				sectionId: '', // 工段id
				remark: '', // 描述
			};
			this.resetForm('form');
		},

		/** 取消按钮 */
		cancel() {
			this.open = false;
			this.reset();
		},

		handleAdd() {
			this.reset();
			this.open = true;
			this.title = '添加工序';
		},

		handleEdit() {
			this.open = true;
			this.title = '编辑工序';
		},

		handleDelete(id) { },

		/** 提交按钮 */
		submitForm() {
			this.$refs['form'].validate((valid) => {
				if (!valid) {
					return;
				}
				// 修改的提交
				if (this.form.id != null) {
					this.updateProcess();
					return;
				}

				const flowId = this.getFlowId();
				this.createProcess()
					.then(({ id, name, sectionId, remark }) => {
						if (!id || !flowId) return null;
						return createProcessNode({
							flowId: flowId,
							name, sectionId, remark,
							id,
						})
					}
					).then(node => {
						if (!node) {
							this.$modal.msgError('创建节点失败');
							return;
						};
						this.graph.addNode(node);
					});

			});
		},

		updateProcess() {
			return updateEquipmentType(this.form).then((response) => {
				this.$modal.msgSuccess('修改成功');
				this.open = false;
				// this.getList();
			});
		},

		createProcess() {
			// const flowId = this.$route.params.id;
			const flowId = this.getFlowId(); // it also works
			if (!flowId) {
				this.$modal.msgError('工艺ID不能为空');
				return Promise.reject(null);
			}
			console.log('create process', this.form)
			// 添加的提交
			return this.post({ flowId: this.flowId, ...this.form }).then(
				({ code, data }) => {
					this.$modal.msgSuccess('新增成功');
					this.open = false;
					// this.getList();
					return {
						id: data, // 服务器返回的新建的工段id
						...this.form,  // 保存一份 this.form 副本，当 open->false 时 this.form 里的信息就清空了
					};
				}
			);
		},

		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);
		},
		http(url, method, payload) {
			return this.$axios({
				url,
				method,
				params: method === 'get' ? payload : null,
				data: method !== 'get' ? payload : null,
			})
		},
	},
};
</script>

<style scoped lang="scss">
.process-graph {
	padding: 12px 20px 20px;
	background: #fff;
	border-radius: 8px;
	position: relative;
}

.process-graph__panel {
	height: 300px;
}
</style>

<style>
.x6-widget-selection-selected {
	border: 1px solid red;
}
</style>
