<template>
	<a-card class="base-card-full-screen">
		<a-space class="action custom-action">
			<div>
				<span class="process-design-name">{{ deployProcessName }}</span>

				<span
					v-if="deployProcessIsCurrent"
					class="process-design-isCurrent"
					style=""
					>当前版本</span
				>
				<span class="process-design-info">
					<span v-if="!operationSymbolStatus"
						>版本号：{{ deployProcessVersion }}</span
					>
					<span
						:class="
							deployProcessStatus === '1'
								? 'publish'
								: 'unpublish'
						"
					>
						{{
							deployProcessStatus === '1'
								? '（已发布）'
								: '（未发布）'
						}}</span
					>
				</span>
			</div>

			<a-button @click="viewHistoryManagement" type="primary">
				<ClockCircleOutlined />
				版本管理
			</a-button>
			<a-button @click="onProcessDesignAddClick" type="primary">
				<plus-outlined />
				新增版本
			</a-button>
			<a-button @click="saveBpmn" type="primary">
				<SaveOutlined />
				保存流程
			</a-button>
			<!-- 发布流程 未发布的流程设计 可以发布 -->
			<a-button
				v-if="deployProcessStatus === '0'"
				@click="publishBpmn"
				type="primary"
			>
				<SendOutlined :rotate="320" />
				发布流程
			</a-button>
			<!-- 复制流程  已发布的流程设计 可以复制流程-->
			<a-button
				v-if="deployProcessStatus === '1'"
				@click="copyBpmn"
				type="primary"
			>
				<CopyOutlined />
				修改流程
			</a-button>

			<a-button
				v-if="
					deployProcessStatus === '0' &&
					operationSymbolStatus === 'copy'
				"
				@click="copyBpmnCancel"
			>
				<CopyOutlined />
				取消修改
			</a-button>
			<a-button class="edit-bpmn" @click="editBpmn">
				<FormOutlined />
				编辑源文件
			</a-button>
			<!-- <a-button-group>
					<a-button @click="handlerZoom(0.1)">放大</a-button>
					<a-button @click="handlerZoom(-0.1)">缩小</a-button>
					<a-button @click="handlerZoom(0)">还原</a-button>
				</a-button-group> -->
			<a-button @click="downloadBpmn">
				<VerticalAlignBottomOutlined />
				导出BPMN文件
			</a-button>
			<!-- <a-button @click="downloadSvg">
					<VerticalAlignBottomOutlined />
					导出SVG
				</a-button> -->
			<a-upload
				class="import-bpmn"
				:file-list="uploadBpmnFileList"
				:before-upload="beforeUpload"
			>
				<a-button>
					<VerticalAlignTopOutlined />
					导入BPMN文件
				</a-button>
			</a-upload>
			<!-- <a-button @click="handlerRedo">恢复</a-button> -->
			<!-- 关闭 -->
			<a-button @click="onCloseClick" danger>
				<CloseOutlined />
				关闭
			</a-button>
			<a hidden ref="downloadLink"></a>
		</a-space>

		<a-spin
			:spinning="dataLoading"
			size="large"
			wrapper-class-name="design-canvas-spin"
		>
			<div
				class="containers design-canvas-wrapper custom-design-container"
				:class="isHiddenMenu ? ' hidden-menu' : ''"
				ref="content"
			>
				<div class="canvas" ref="canvas"></div>
				<!-- 右边属性部分 -->
				<div id="js-properties-panel" class="panel"></div>
			</div>
		</a-spin>
	</a-card>

	<!-- 编辑源文件 -->
	<edit-bpmn-modal
		:confirm-modal-visible="editBpmnModalVisible"
		:source-bpmn-code="sourceBpmnCode"
		@confirm-edit-modal-cancel="onEditBpmnModalCancel"
		@confirm-edit-modal-refresh="onEditBpmnModalConfirm"
	/>

	<!-- 用户选择  -->
	<design-applications-select
		:confirm-modal-visible="confirmUsersModalVisible"
		:users-data="usersData"
		:current-definition-id="deployProcessDesignId"
		:is-start-event-node="isStartEventNode"
		@confirm-add-modal-cancel="onUsersModalCancel"
		@confirm-add-modal-refresh="onUsersModalConfirm"
	/>

	<!-- 定时器设置 -->
	<design-user-timer-definition-modal
		:confirm-modal-visible="confirmTimersModalVisible"
		:timer-definition-data="timerData"
		@confirm-add-modal-cancel="onTimersModalCancel"
		@confirm-add-modal-refresh="onTimersModalConfirm"
	/>

	<!-- 连接器 -->
	<design-connectors
		:confirm-modal-visible="confirmConnectorModalVisible"
		:current-select-id="connectorServiceId"
		@confirm-add-modal-refresh="onConnectorModalConfirm"
		@confirm-add-modal-cancel="onConnectorModalCancel"
	/>

	<!-- 表单Key  -->
	<!-- :current-form-key-select="formKeySelectId"
		:current-form-name-select="formNameSelectName" -->
	<design-form-key
		:confirm-modal-visible="confirmFormKeyModalVisible"
		:current-form-data-select="formSelectData"
		@confirm-add-modal-cancel="onFormKeyModalCancel"
		@confirm-add-modal-refresh="onFormKeyModalConfirm"
	/>

	<!-- 资源配置 -->
	<!-- <design-form-fields -->
	<design-form-fields-tab
		:confirm-modal-visible="confirmFormFieldsModalVisible"
		:select-form-data="formSelectData"
		:select-form-fields-data="formKFieldsData"
		:is-form-engine="isFormEngine"
		@confirm-add-modal-cancel="onFormFieldsModalCancel"
		@confirm-add-modal-refresh="onFormFieldsModalConfirm"
	/>

	<!-- 超期设置 -->
	<design-user-timer-definition-modal
		:confirm-modal-visible="confirmDueDateVisible"
		:timer-definition-data="dueDateData"
		:model-text="getI18n('system', 'SYSTEM_Process_OverdueDateSetting')"
		@confirm-add-modal-cancel="onDueDateModalCancel"
		@confirm-add-modal-refresh="onDueDateModalConfirm"
	/>

	<!-- 服务组件 -->
	<design-microflow
		:confirm-modal-visible="confirmMicroflowModalVisible"
		:select-data="microflowData"
		@confirm-add-modal-cancel="onMicroflowModalCancel"
		@confirm-add-modal-refresh="onMicroflowModalConfirm"
	/>

	<!-- 权限按钮 -->
	<design-permission-button
		:confirm-modal-visible="confirmPermissionButtonModalVisible"
		:select-permission-button-data="permissionButtonData"
		:is-show-add-sub-sign-btn="isShowAddSubSignBtn"
		@confirm-add-modal-cancel="onPermissionButtonModalCancel"
		@confirm-add-modal-refresh="onPermissionButtonModalConfirm"
	/>

	<!-- 调用活动 -->
	<design-call-activity
		:confirm-modal-visible="confirmCallActivityModalVisible"
		:call-activity-select-key="callActivitySelectKey"
		:current-process-design-key="processDesignKey"
		@confirm-add-modal-cancel="onCallActivityModalCancel"
		@confirm-add-modal-refresh="onCallActivityModalConfirm"
	/>

	<!-- 内联脚本-脚本文本框 脚本任务节点、连接线、监听器 -->
	<design-script-value
		:confirm-modal-visible="confirmScriptValueModalVisible"
		:script-value-data="scriptValueData"
		@confirm-add-modal-cancel="onScriptValueModalCancel"
		@confirm-add-modal-refresh="onScriptValueModalConfirm"
	/>

	<!-- 条件类型 - 表达式 -->
	<design-flow-conditional
		:confirm-modal-visible="conditionExpressionVisible"
		:flow-condition-expression-value="conditionExpression"
		:flow-condition-form-data="conditionExpressionFormData"
		@confirm-add-modal-cancel="onConditionExpressionCancel"
		@confirm-add-modal-refresh="onConditionExpressionConfirm"
	/>
</template>

<script>
import { message } from 'ant-design-vue'
import { ProcessConstant } from '@/utils/constant'
import { useRoute } from 'vue-router'
import Storage from 'web-storage-cache'
import { TOKEN_KEY } from '@/global/cacheKey'
import { getI18n } from '@/utils/i18n'

import router from '@/router'
import {
	deployBpmnsProcessApi,
	saveProcessModelApi,
	getProcessModelByIdApi,
	getProcessDeploymentsByDefinitionIdApi,
	getProcessModelsTemplateApi,
	publishProcessModelApi,
	publishProcessApi,
} from '@/api/process-deployments'

import {
	VerticalAlignBottomOutlined,
	VerticalAlignTopOutlined,
	SaveOutlined,
	SendOutlined,
	CopyOutlined,
	CloseOutlined,
	ClockCircleOutlined,
	PlusOutlined,
	FormOutlined,
} from '@ant-design/icons-vue'

import {
	DesignUserTimerDefinitionModal,
	DesignApplicationsSelect,
	EditBpmnModal,
	DesignConnectors,
	DesignFormKey,
	// DesignFormFields,
	DesignFormFieldsTab,
	DesignPermissionButton,
	DesignMicroflow,
	DesignCallActivity,
	DesignScriptValue,
	DesignFlowConditional,
} from './components'
import { validatenull } from '@/utils/tool/translateValue'
import { encode, decode } from 'js-base64'

// 必须导入
import CustomModeler from './components/CustomModelers'
// 右边工具栏属性模块
import propertiesPanelModule from 'bpmn-js-properties-panel'
// 左边工具栏配置模块
import propertiesProviderModule from 'jc-server-bpmn-js-properties-panel-activiti/lib/provider/activiti'
import jcBpmnPropertiesPanel from 'jc-server-bpmn-js-properties-panel-activiti'
import activitiModdle from './activiti'
import customTranslate from '@/assets/bpmn-js/customTranslate'
import 'bpmn-js/dist/assets/diagram-js.css'
/* 左边工具栏内各个工具的样式，不添加该样式，左边工具栏内不显示任何工具 */
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
/* 右边工具栏样式*/
import 'jc-server-bpmn-js-properties-panel-activiti/dist/assets/bpmn-js-properties-panel.css'
/* lint */
import lintModule from 'bpmn-js-bpmnlint'
import {
	resolver,
	rules,
} from './components/CustomBpmnLintModule/CustomBpmnLintModule.js'
/* lint 信息提示的样式*/
import 'bpmn-js-bpmnlint/dist/assets/css/bpmn-js-bpmnlint.css'

// 自定义汉化模块
var customTranslateModule = {
	translate: ['value', customTranslate],
}

export default {
	name: 'Design',
	components: {
		VerticalAlignBottomOutlined,
		VerticalAlignTopOutlined,
		SaveOutlined,
		SendOutlined,
		CopyOutlined,
		CloseOutlined,
		ClockCircleOutlined,
		PlusOutlined,
		FormOutlined,
		DesignUserTimerDefinitionModal,
		DesignApplicationsSelect,
		EditBpmnModal,
		DesignConnectors,
		DesignFormKey,
		// DesignFormFields,
		DesignFormFieldsTab,
		DesignPermissionButton,
		DesignMicroflow,
		DesignCallActivity,
		DesignScriptValue,
		DesignFlowConditional,
	},
	props: {
		// 流程设计列表 返回的id
		processDesignId: {
			type: String,
			default: '',
			required: false,
		},
		// 流程设计列表 流程key
		processDesignKey: {
			type: String,
			default: '',
			required: false,
		},

		// 版本管理列表 返回的 definitionId
		definitionId: {
			type: String,
			required: false,
			default: '',
		},
		// 版本管理列表 返回的 id；从流程管理列表中未发布状态传递的modelId
		processDefId: {
			type: String,
			required: false,
			default: '',
		},

		// 用来判断使用哪个获取bpmn接口的 0、1 从版本管理传过来的 发布状态
		processStatus: {
			type: String,
			required: false,
			default: '',
		},
		// 版本管理- 复制流程按钮 'copy',新增流程按钮 'add',  左侧工具栏、右键菜单需要显示
		operationSymbol: {
			type: String,
			required: false,
			default: '',
		},
		// 版本管理列表 返回的 流程部署Id
		processDeployId: {
			type: String,
			required: false,
			default: '',
		},
		// 版本列表删除流程设计后返回的 这条流程设计id
		deleteProcessDesignIdValue: {
			type: String,
			required: false,
			default: '',
		},
	},
	emits: ['on-modal-close', 'on-history-modal-view'],
	data(props) {
		return {
			getI18n,
			isHiddenMenu: false, // 是否是已发布状态的 流程设计（已发布状态的流程设计，不展示左边工具栏、节点右键菜单）
			dataLoading: false,
			// 开始节点，设置抄送人时  只显示用户
			isStartEventNode: false,
			// 用户选择
			selectUserElementId: '',
			confirmUsersModalVisible: false,
			usersData: {
				assigneeSelectType: '1',
				users: [{ id: '', name: '' }],
			},
			// 定时器
			selectTimerElementId: '',
			confirmTimersModalVisible: false,
			timerData: '',
			// 编辑源文件
			editBpmnModalVisible: false,
			sourceBpmnCode: '',
			// 连接器
			confirmConnectorModalVisible: false,
			connectorElementId: '',
			connectorServiceId: '',
			// 表单Key
			confirmFormKeyModalVisible: false,
			formKeyElementId: '',
			// formKeySelectId: '', // 弹框反选用
			// formNameSelectName: '', // 弹框反显用
			formSelectData: [], // 弹框反显用
			// 资源配置
			isFormEngine: false, // 用来判断使用表单引擎的详情查询接口还是 自己系统的详情查询接口
			confirmFormFieldsModalVisible: false,
			formFieldsElementId: '', // 例：Activity_07z6l3o
			formFieldsElement: {}, // 对象
			formKFieldsData: [],
			// getFormFieldsByThisId: '',
			// 超期设置
			confirmDueDateVisible: false,
			dueDateElementId: '', // 例：Activity_07z6l3o
			dueDateResourceId: '', // 例：
			dueDateData: '',

			// 权限按钮
			confirmPermissionButtonModalVisible: false,
			permissionButtonData: [],
			permissionButtonElementId: '',
			isShowAddSubSignBtn: false, // 只有设置了多重并行事件的 用户节点 权限按钮列表里才能显示 加签、减签按钮
			// 服务组件
			confirmMicroflowModalVisible: false,
			microflowData: [],
			microflowResourceId: '', // 例：activiti-microflowList
			microflowElementId: '', // 例：Activity_0sad8xl
			// 调用活动
			callActivitySelectKey: '', // 弹框反选用
			callActivityElementId: '',
			confirmCallActivityModalVisible: false,
			// 脚本
			scriptValueElementId: '',
			scriptValueData: '',
			confirmScriptValueModalVisible: false,
			// 流程线-条件类型-表达式
			conditionExpression: '',
			conditionExpressionElementId: '',
			conditionExpressionFormData: '',
			conditionExpressionVisible: false,
			// 流程
			canvas: null,
			uploadBpmnFileList: [],

			deployProcessDefinitionId: props.definitionId || '', // 单条数据查询接口返回的 Id 或者是从版本管理列表 返回的 definitionId
			deployProcessDesignId: props.processDesignId || '', // 流程设计列表 返回的id 流程设计Id
			deployProcessDefId: props.processDefId || '', // 版本列表 返回的 Id；或者是 保存流程模型后返回的Id（接口/models）
			deleteProcessDesignId: props.deleteProcessDesignIdValue || '', // 版本列表删除流程设计后返回的 这条流程设计id
			processPublishedStatus: props.processStatus || '', // 流程是否发布的字段
			operationSymbolStatus: props.operationSymbol || '', // 版本管理- 复制流程按钮 'copy',新增流程按钮 'add', 左侧工具栏、右键菜单需要显示;
			deployProcessKey: '', // 从查询单条流程xml接口取回的 key
			deployProcessName: '', // 从查询单条流程xml接口取回的 名称
			deployProcessStatus: '', // 从查询单条流程xml接口取回的 发布状态
			deployProcessVersion: '1', // 从查询单条流程xml接口取回的 版本信息
			deployProcessId: props.processDeployId || '', // 版本管理列表过来的就给复制版本管理列表传的值， 从查询单条流程xml接口取回的部署Id有值则覆盖，没值就不覆盖
			deployProcessIsCurrent: false,

			scale: 1,
			templateBpmnXml: '',
		}
	},
	mounted() {
		const route = useRoute()
		if (route.query && route.query.token) {
			const localStorage = new Storage()
			localStorage.set(TOKEN_KEY, route.query.token?.toString())
			localStorage.set('token', route.query.token?.toString())
		}
		const self = this

		// 如果在版本列表删除的是当前正在显示的流程设计，那么直接显示新增流程设计的面板
		if (
			self.deployProcessDefId &&
			self.deployProcessDefId === self.deleteProcessDesignId
		) {
			self.onProcessDesignAddClick()
			return
		}

		// 右侧属性面板清空
		document.getElementById('js-properties-panel').innerHTML = ''
		// 获取到属性ref为“canvas”的dom节点
		const canvas = self.$refs.canvas

		// 未发布  用model接口查 流程设计
		if (
			self.processPublishedStatus &&
			self.processPublishedStatus === '0'
		) {
			// 	self.dataLoading = true
			self.getXmlFileProcess({
				definitionId: self.deployProcessDesignId,
				id: self.deployProcessDefId,
			})
				.then(res => {
					// return
					res.data.bpmStr &&
						(self.templateBpmnXml = decode(res.data.bpmStr)) // decode(res.data.bpmStr)
					self.deployProcessDefinitionId = res.data.definitionId
					self.deployProcessName = res.data.name
					self.deployProcessKey = res.data.key

					self.deployProcessStatus = res.data.status
					self.deployProcessVersion =
						self.operationSymbolStatus === 'copy'
							? '1'
							: res.data.flowVersion || '1'
					res.data.deployId &&
						(self.deployProcessId = res.data.deployId)

					// 避免缓存，每次清一下
					if (self.bpmnModeler) {
						self.additionalModules = []
						self.bpmnModeler.destroy()
					}
					// 建模，官方文档这里讲的很详细
					self.bpmnModeler = new CustomModeler({
						container: canvas,
						linting: {
							active: true, // 默认开启规则校验
							// bpmnlint: bpmnlintConfig,
							bpmnlint: {
								config: {
									rules: { ...rules },
								},
								resolver,
							},
						},
						// 添加控制板(右边属性配置栏部分)
						propertiesPanel: {
							parent: '#js-properties-panel',
						},
						// 左边工具栏和右边属性栏配置, 如果只需要左边工具栏可以不添加如下配置，如果需要右边属性栏则需要
						// 进行如下配置
						additionalModules: [
							lintModule,
							// 左边工具栏以及节点
							propertiesProviderModule,
							// 右边的工具栏
							propertiesPanelModule,
							// activitiExtensionModule,
							// 国际化
							customTranslateModule,
							// {
							// 	labelEditingProvider: ["value", ''], // 节点禁止双击事件（不能编辑名称）
							// }
						],
						moddleExtensions: {
							activiti: activitiModdle,
						},
						keyboard: { bindTo: document },
					})
					// 未发布状态并且不是复制流程 的 流程设计 可以显示操作栏、右键菜单，以及发布流程
					if (
						res.data.status ===
						ProcessConstant.processDesignStatus.publish.value
					) {
						self.isHiddenMenu = true
						self.bpmnModeler.get('keyboard').unbind()
					} else {
						self.isHiddenMenu = false
						self.bpmnModeler.get('keyboard').bind(document)
					}

					self.createNewDiagram(self.templateBpmnXml)
				})
				.catch(err => {
					if (err && err.code != 200) {
						self.onProcessDesignAddClick()
					}
				})
		} else {
			self.getXmlDefaultFileProcess({
				processDefId: self.deployProcessDefId,
				definitionId: self.deployProcessDesignId,
			})
				.then(res => {
					self.templateBpmnXml = decode(res.data.bpmStr)
					self.deployProcessDefinitionId = res.data.definitionId
					self.deployProcessName = res.data.name
					self.deployProcessKey = res.data.key

					self.deployProcessStatus =
						self.operationSymbolStatus === 'copy'
							? '0'
							: res.data.status
					self.deployProcessVersion =
						self.operationSymbolStatus === 'copy'
							? '1'
							: res.data.flowVersion || '1'
					self.deployProcessIsCurrent =
						self.operationSymbolStatus === 'copy'
							? false
							: res.data.curVersion || false

					res.data.deployId &&
						(self.deployProcessId = res.data.deployId)

					// 避免缓存，每次清一下
					if (self.bpmnModeler) {
						self.additionalModules = []
						self.bpmnModeler.destroy()
					}
					// 建模，官方文档这里讲的很详细
					self.bpmnModeler = new CustomModeler({
						container: canvas,
						linting: {
							active: true, // 默认开启规则校验
							// bpmnlint: bpmnlintConfig,
							bpmnlint: {
								config: {
									rules: { ...rules },
								},
								resolver,
							},
						},
						// 添加控制板(右边属性配置栏部分)
						propertiesPanel: {
							parent: '#js-properties-panel',
						},
						// 左边工具栏和右边属性栏配置, 如果只需要左边工具栏可以不添加如下配置，如果需要右边属性栏则需要
						// 进行如下配置
						additionalModules: [
							lintModule,
							// 左边工具栏以及节点
							propertiesProviderModule,
							// 右边的工具栏
							propertiesPanelModule,
							// activitiExtensionModule,
							// 国际化
							customTranslateModule,
						],
						moddleExtensions: {
							activiti: activitiModdle,
						},
						keyboard: { bindTo: document },
					})

					// 未发布状态并且不是复制流程 的 流程设计 可以显示操作栏、右键菜单，以及发布流程
					if (
						res.data.status ===
							ProcessConstant.processDesignStatus.publish.value &&
						self.operationSymbolStatus !== 'copy'
					) {
						self.isHiddenMenu = true
						self.bpmnModeler.get('keyboard').unbind()
					} else {
						self.isHiddenMenu = false
						self.bpmnModeler.get('keyboard').bind(document)
					}

					self.createNewDiagram(self.templateBpmnXml)
				})
				.catch(err => {
					if (err && err.code != 200) {
						self.onProcessDesignAddClick()
					}
				})
		}

		// 用户选择
		jcBpmnPropertiesPanel.userTaskSelectCallBack = (
			userTaskId,
			elementId,
			value
		) => {
			if (value) {
				this.usersData = JSON.parse(value)
			} else {
				this.usersData = undefined
			}
			this.selectUserElementId = elementId
			this.confirmUsersModalVisible = true
		}

		// 定时器
		jcBpmnPropertiesPanel.userTimerInputCallBack = (
			timerDefinitionId,
			elementId,
			value
		) => {
			this.selectTimerElementId = elementId
			this.timerData = value

			this.confirmTimersModalVisible = true
		}

		// 连接器
		jcBpmnPropertiesPanel.connectorIdCallBack = (
			resourceId,
			elementId,
			_value
		) => {
			this.connectorElementId = elementId
			this.confirmConnectorModalVisible = true
			this.connectorServiceId = _value || ''
		}

		// 表单key
		jcBpmnPropertiesPanel.formKeySetCallBack = (
			resourceId,
			elementId,
			// idValue,
			// nameValue,
			data
		) => {
			// self.formKeySelectId = idValue || ''
			// self.formNameSelectName = nameValue || ''
			self.formSelectData = data ? [...data] : []
			this.formKeyElementId = elementId
			this.confirmFormKeyModalVisible = true
		}

		// 资源配置
		jcBpmnPropertiesPanel.formFieldsSetCallBack = (
			element,
			elementId,
			selFormData,
			data
		) => {
			this.formFieldsElement = element
			this.formFieldsElementId = elementId
			this.confirmFormFieldsModalVisible = true

			if (selFormData) {
				this.formSelectData = [
					...JSON.parse(selFormData),
					...[{ type: 'form', name: '节点资源' }],
				]
			} else {
				this.formSelectData = [{ type: 'form', name: '节点资源' }]
			}

			!validatenull(data) &&
				(this.formKFieldsData = JSON.parse(data).filter(f => f))
		}

		// 超期设置
		jcBpmnPropertiesPanel.callDueDateSetCallBack = (
			resourceId,
			elementId,
			data
		) => {
			self.dueDateData = data || ''
			this.dueDateElementId = elementId
			this.dueDateResourceId = resourceId
			this.confirmDueDateVisible = true
		}

		// 权限按钮
		jcBpmnPropertiesPanel.buttonListSelectCallBack = (
			elementId,
			resourceId,
			data
		) => {
			this.confirmPermissionButtonModalVisible = true
			this.permissionButtonElementId = resourceId
			!validatenull(data) &&
				(this.permissionButtonData = JSON.parse(data))

			// 获取当前用户节点是否设置了 多重并行事件
			const elementRegistry = this.bpmnModeler.get('elementRegistry')
			var shape = elementRegistry.get(elementId)
			if (
				!validatenull(shape) &&
				!validatenull(shape.businessObject) &&
				!validatenull(shape.businessObject.loopCharacteristics)
			) {
				shape.businessObject.$type === 'bpmn:UserTask' &&
				shape.businessObject.loopCharacteristics.$type ===
					'bpmn:MultiInstanceLoopCharacteristics'
					? (this.isShowAddSubSignBtn = true)
					: (this.isShowAddSubSignBtn = false)
			} else {
				this.isShowAddSubSignBtn = false
			}
		}

		// 服务组件
		jcBpmnPropertiesPanel.microflowSelectCallBack = (
			elementId,
			resourceId,
			data
		) => {
			this.confirmMicroflowModalVisible = true
			this.microflowResourceId = resourceId
			this.microflowElementId = elementId
			this.microflowData = data && JSON.parse(data)
		}

		// 调用活动
		jcBpmnPropertiesPanel.callActivitySetCallBack = (
			resourceId,
			elementId,
			value
		) => {
			this.callActivitySelectKey = value || ''
			this.callActivityElementId = elementId
			this.confirmCallActivityModalVisible = true
		}

		// 脚本节点 - 脚本新增按钮
		jcBpmnPropertiesPanel.scriptValueCallBack = (elementId, value) => {
			this.scriptValueElementId = elementId
			this.scriptValueData = JSON.stringify(value)
			this.confirmScriptValueModalVisible = true
		}

		// 流程线 - 表达式
		jcBpmnPropertiesPanel.conditionalExpressionCallBack = (
			elementId,
			value,
			formIds
		) => {
			this.conditionExpression = value || ''
			this.conditionExpressionElementId = elementId
			this.conditionExpressionFormData = formIds
			this.conditionExpressionVisible = true
		}
	},
	methods: {
		// 已发布的 流程设计查询 返回xml字符串
		getXmlDefaultFileProcess(params) {
			const res = getProcessDeploymentsByDefinitionIdApi(params)
			return res
		},
		// 未发布的 流程设计查询 返回xml字符串
		getXmlFileProcess(params) {
			if (this.operationSymbolStatus === 'add') {
				// 新增流程设计，返回空白xml模板
				const res = getProcessModelsTemplateApi({
					id: params.definitionId,
				})
				return res
			}
			const res = getProcessModelByIdApi(params)
			return res
		},

		// 保存流程设计
		async saveProcessDeployments(params) {
			// 新增、复制流程时，都是未发布的模型，
			let _newModalparams = {
				definitionId: params.definitionId || this.deployProcessDesignId, //
				bpmStr: params.bpmStr,
				name: params.name,
				key: params.key,
			}

			if (
				this.operationSymbolStatus === 'copy' ||
				this.operationSymbolStatus === 'add'
			) {
				const res = await saveProcessModelApi(_newModalparams)
				return res
			}
			if (
				(this.processPublishedStatus &&
					this.processPublishedStatus === '1') ||
				(this.deployProcessStatus && this.deployProcessStatus === '1')
			) {
				let _pubparams = {
					id: params.publishId || undefined,
					bpmStr: params.bpmStr,
				}
				const res = await deployBpmnsProcessApi(_pubparams)
				return res
			}

			this.deployProcessDefId &&
				(_newModalparams.modelId = this.deployProcessDefId)
			const res = await saveProcessModelApi(_newModalparams)
			return res
		},
		// 初始化bpmn图
		// 创建bpmn图
		createNewDiagram(bpmnXmsStr) {
			const self = this
			const allowAdd = [
				'bpmn:CallActivity',
				'bpmn:ServiceTask',
				'bpmn:SubProcess',
				'bpmn:ScriptTask',
				'bpmn:UserTask',
			]
			try {
				const result = self.bpmnModeler
					.importXML(bpmnXmsStr)
					.then(() => {
						if (self.deployProcessKey && self.deployProcessName) {
							jcBpmnPropertiesPanel.setBpmnIdAndName(
								self.deployProcessKey,
								self.deployProcessName
							)
						}
					})
				const { warnings } = result
				warnings && message.info(warnings)

				const eventBus = this.bpmnModeler.get('eventBus')
				const modeling = this.bpmnModeler.get('modeling')
				const elementRegistry = this.bpmnModeler.get('elementRegistry')

				const eventTypes = ['element.click', 'element.changed']
				eventTypes.forEach(function (eventType) {
					eventBus.on(eventType, function (e) {
						if (!e || !e.element) {
							return
						}

						if (eventType === 'element.click') {
							var shape = e.element
								? elementRegistry.get(e.element.id)
								: e.shape
							var _type = shape.type
							var extensionElementsValues
							// 通过匹配节点名称，给节点属性添加当前的流程设计是否发布，=> 已发布的流程设计不能修改id编号和多实例类型
							if (allowAdd.includes(_type)) {
								modeling.updateProperties(shape, {
									deployProcessStatus:
										self.deployProcessStatus,
								})
							}

							// 开始节点，设置抄送人时  只显示用户
							self.isStartEventNode = _type === 'bpmn:StartEvent'

							if (
								!validatenull(e.element.businessObject) &&
								!validatenull(
									e.element.businessObject.extensionElements
								)
							) {
								extensionElementsValues =
									e.element.businessObject.extensionElements
										.values
							}

							if (_type === 'bpmn:ServiceTask') {
							}

							if (_type === 'bpmn:UserTask') {
								// 设置了多实例 的 用户节点
								if (
									!validatenull(e.element.businessObject) &&
									!validatenull(
										e.element.businessObject
											.loopCharacteristics
									)
								) {
									modeling.updateProperties(shape, {
										// name: '我是修改后的Task名称'
										'activiti:assignee': '${assignee}',
									})
								} else {
									modeling.updateProperties(shape, {
										// name: '我是修改后的Task名称'
										'activiti:candidateUsers':
											'${' + e.element.id + 'User}',
									})
								}
							}
							// 用户节点、活动节点 -人员选择
							if (
								(_type === 'bpmn:UserTask' ||
									_type === 'bpmn:CallActivity' ||
									_type === 'bpmn:StartEvent') &&
								!validatenull(extensionElementsValues) &&
								extensionElementsValues.constructor == Array
							) {
								let _userpropertiesValues =
									extensionElementsValues.filter(
										f =>
											f.$type ===
											'activiti:Userproperties'
									)
								if (_userpropertiesValues.length > 0) {
									let _alias = _userpropertiesValues[0]?.alias
									let _valueUserinfosTemp =
										_userpropertiesValues[0]?.userinfos
									let _valueRelationsTemp =
										_userpropertiesValues[0]?.relations

									let _valueUserinfos = _valueUserinfosTemp
										? JSON.parse(_valueUserinfosTemp)
										: undefined
									let _valueRelations = _valueRelationsTemp
										? JSON.parse(_valueRelationsTemp)
										: undefined
									let _values = {
										assigneeSelectType:
											_valueUserinfos?.assigneeSelectType,
										users: [
											...(_valueUserinfos
												? _valueUserinfos.users
												: []),
											...(_valueRelations
												? _valueRelations
												: []),
										],
									}

									let _domElement = document.getElementById(
										'activiti-userproperties'
									)

									_alias &&
										_domElement &&
										(_domElement.value = _alias)
									_values &&
										_domElement &&
										_domElement.setAttribute(
											'data-user-value',
											JSON.stringify(_values)
										)
								}
							}
							let selectFormData
							// 表单key
							if (!validatenull(shape.businessObject)) {
								selectFormData = shape.businessObject.formData
									? JSON.parse(shape.businessObject.formData)
									: ''

								let formKeyInput =
									document.getElementById('activiti-form-key')

								if (
									selectFormData &&
									!validatenull(selectFormData)
								) {
									formKeyInput &&
										(formKeyInput.value = selectFormData
											?.map(v => {
												return v.name
											})
											?.toString())

									self.formSelectData = [...selectFormData]

									formKeyInput &&
										formKeyInput.setAttribute(
											'data-form-data',
											JSON.stringify(selectFormData || '')
										)
								}
							}
							if (
								document.getElementById(
									'activiti-form-fields-btn'
								)
							) {
								let _dataFormId = ''
								if (selectFormData) {
									let _selFormData = selectFormData
										?.map(v => {
											return v.id
										})
										?.toString()
									_dataFormId = `${selectFormData[0].type}:${_selFormData}`
								}
								document
									.getElementById('activiti-form-fields-btn')
									.setAttribute('data-form-id', _dataFormId)
							}
							// 资源配置
							if (!validatenull(extensionElementsValues)) {
								let extensionElements =
									shape.businessObject.get(
										'extensionElements'
									)

								let _fieldsData = extensionElements.values
									.filter(f => f.id)
									.map(v => {
										if (
											v.$type === 'activiti:FormProperty'
										) {
											return {
												name: v.name,
												type: v.type || undefined,
												formId: v.formId,
												source:
													v.$attrs.source ||
													ProcessConstant
														.formFieldsSource.form
														.value,
												id: v.id, // v.$attrs.formName,
												formName: v.$attrs.formName,
												isEditable:
													v.writable &&
													v.writable != 'false'
														? true
														: false,
												isReadonly:
													v.readable &&
													v.readable != 'false'
														? true
														: false,
												isRequired:
													v.required &&
													v.required != 'false'
														? true
														: false,
												isVariable:
													v.variable &&
													v.variable != 'false'
														? true
														: false,
											}
										}
									})

								if (
									document.getElementById(
										'activiti-form-fields-btn'
									)
								) {
									document
										.getElementById(
											'activiti-form-fields-btn'
										)
										.setAttribute(
											'form-fields-value',
											JSON.stringify(_fieldsData)
										)
								}
							}
							// }
							// 用户节点 -
							if (
								_type === 'bpmn:UserTask' &&
								!validatenull(extensionElementsValues) &&
								extensionElementsValues.constructor == Array
							) {
								// 权限按钮
								let _bpmButtonListValues =
									extensionElementsValues.filter(
										f =>
											f.$type === 'activiti:BpmButtonList'
									)
								if (_bpmButtonListValues.length > 0) {
									let _alias = _bpmButtonListValues[0]?.alias
									let _value =
										_bpmButtonListValues[0]?.buttoninfos
									let _domElement = document.getElementById(
										'activiti-bpmButtonList'
									)

									_alias &&
										_domElement &&
										(_domElement.value = _alias)
									_value &&
										_domElement &&
										_domElement.setAttribute(
											'data-button-list',
											_value
										)
								}

								// 服务组件
								let _microflowList =
									extensionElementsValues.filter(
										f =>
											f.$type === 'activiti:MicroflowList'
									)
								if (
									_microflowList.length > 0 &&
									_microflowList[0]?.alias
								) {
									let _alias = _microflowList[0]?.alias
									let _value =
										_microflowList[0]?.microflowinfos
									let _domElement = document.getElementById(
										'activiti-microflowList'
									)

									_alias &&
										_domElement &&
										(_domElement.value = _alias)
									_value &&
										_domElement &&
										_domElement.setAttribute(
											'data-microflow-list',
											_value
										)

									let micoflowIds = _microflowList
										.map(v => {
											return (
												v.microflowinfos &&
												JSON.parse(
													v.microflowinfos
												).map(m => {
													return m.id || ''
												})
											)
										})
										?.toString()
									modeling.updateProperties(shape, {
										'activiti:candidateUsers': micoflowIds,
									})
								}
							}
						}
					})
				})
				self.dataLoading = false
			} catch (err) {
				if (err) {
					err.message && message.error(err.message)
				}
			}
		},
		// 编辑源文件
		async editBpmn() {
			const self = this
			try {
				const result = await self.bpmnModeler.saveXML({ format: true })
				const { xml } = result
				self.sourceBpmnCode = xml
				self.editBpmnModalVisible = true
			} catch (err) {
				// message.error(JSON.stringify(err))
			}
		},
		// 保存按钮
		async saveBpmn() {
			const self = this
			const _lintModule = this.bpmnModeler.get('linting')
			// _lintModule && !_lintModule._active && _lintModule.toggle()

			if (!validatenull(_lintModule._issues)) {
				message.error('流程存在错误！')
				return
			}

			try {
				const result = await self.bpmnModeler.saveXML({ format: true })
				const { xml } = result
				if (self.deployProcessName && self.deployProcessKey) {
					const params = {
						name: '', // 流程名称
						bpmStr: '', // 流程文件字符串
						definitionId: '', // 流程id
						key: '', // 流程key
						publishId: undefined, //
						modelId: '',
					}
					// 获取右侧面板的名称 值
					const elementRegistry =
						this.bpmnModeler.get('elementRegistry')

					params.name = self.deployProcessKey
						? elementRegistry.get(self.deployProcessKey)
								?.businessObject?.name
						: self.deployProcessName
					params.bpmStr = encode(xml) // encode(xml)
					params.definitionId = self.deployProcessDefinitionId
					params.key = self.deployProcessKey

					self.processPublishedStatus &&
						self.processPublishedStatus === '0' &&
						(params.modelId = self.deployProcessDefId || undefined)
					self.deployProcessId &&
						(params.publishId = self.deployProcessId || undefined)

					self.saveProcessDeployments(params).then(res => {
						if (res.code == 200) {
							if (res.data) {
								res.data.id &&
									(self.deployProcessDefId = res.data.id) // modelId
								res.data.version &&
									(self.deployProcessVersion =
										res.data.version) // version
								self.operationSymbolStatus = '' // 给状态置空 -> 显示版本号
							}
							message.success(res.msg)
						} else {
							message.error(res.msg)
						}
					})
				}
			} catch (err) {
				// message.error(JSON.stringify(err))
			}
		},
		// 发布流程
		async publishBpmn() {
			const self = this
			const _lintModule = this.bpmnModeler.get('linting')
			// _lintModule && !_lintModule._active && _lintModule.toggle()
			if (!validatenull(_lintModule._issues)) {
				message.error('流程存在错误！')
				return
			}
			try {
				const result = await self.bpmnModeler.saveXML({ format: true })
				const { xml } = result

				// 获取右侧面板的名称 值
				const elementRegistry = this.bpmnModeler.get('elementRegistry')
				let _processName = self.deployProcessKey
					? elementRegistry.get(self.deployProcessKey)?.businessObject
							?.name
					: self.deployProcessName

				if (
					!self.deployProcessDefId ||
					this.operationSymbolStatus === 'copy' ||
					this.operationSymbolStatus === 'add'
				) {
					let params = {
						name: _processName, // 流程名称
						bpmStr: encode(xml), // 流程文件字符串
						definitionId: self.deployProcessDefinitionId, //
						key: self.deployProcessKey, //
					}
					await publishProcessApi(params).then(res => {
						if (res.code == 200) {
							message.success(res.msg)
							self.viewHistoryManagement()
						} else {
							message.error(res.msg)
						}
					})
				} else {
					let params = {
						modelId: self.deployProcessDefId, //
						name: _processName, // 流程名称
						key: self.deployProcessKey, // 流程key
						bpmStr: encode(xml), // 流程文件字符串
						definitionId: self.deployProcessDefinitionId, //
					}
					await publishProcessModelApi(params).then(res => {
						if (res.code == 200) {
							message.success(res.msg)
							self.viewHistoryManagement()
						} else {
							message.error(res.msg)
						}
					})
				}
			} catch (err) {
				// message.error(JSON.stringify(err))
			}
		},
		// 复制流程
		copyBpmn() {
			const self = this
			// 右侧属性面板清空
			document.getElementById('js-properties-panel').innerHTML = ''
			// 获取到属性ref为“canvas”的dom节点
			const canvas = self.$refs.canvas
			// 未发布  用model接口查 流程设计
			self.processPublishedStatus = '1'
			self.operationSymbolStatus = 'copy'
			// 	self.dataLoading = true
			self.getXmlDefaultFileProcess({
				processDefId: self.deployProcessDefId,
				definitionId: self.deployProcessDesignId,
			})
				.then(res => {
					// self.initBpmn(res.data)
					self.templateBpmnXml = decode(res.data.bpmStr) // decode(res.data.bpmStr)
					self.deployProcessDefinitionId = res.data.definitionId
					self.deployProcessName = res.data.name
					self.deployProcessKey = res.data.key

					self.deployProcessStatus =
						self.operationSymbolStatus === 'copy'
							? '0'
							: res.data.status

					self.deployProcessIsCurrent =
						self.operationSymbolStatus === 'copy'
							? false
							: res.data.curVersion || false

					res.data.deployId &&
						(self.deployProcessId = res.data.deployId)

					// 未发布状态并且不是复制流程 的 流程设计 可以显示操作栏、右键菜单，以及发布流程
					self.isHiddenMenu =
						res.data.status ===
							ProcessConstant.processDesignStatus.publish.value &&
						self.operationSymbolStatus !== 'copy'
							? true
							: false

					// 避免缓存，每次清一下
					if (self.bpmnModeler) {
						self.additionalModules = []
						self.bpmnModeler.destroy()
					}
					// 建模，官方文档这里讲的很详细
					self.bpmnModeler = new CustomModeler({
						container: canvas,
						linting: {
							active: true, // 默认开启规则校验
							// bpmnlint: bpmnlintConfig,
							bpmnlint: {
								config: {
									rules: { ...rules },
								},
								resolver,
							},
						},
						// 添加控制板(右边属性配置栏部分)
						propertiesPanel: {
							parent: '#js-properties-panel',
						},
						// 左边工具栏和右边属性栏配置, 如果只需要左边工具栏可以不添加如下配置，如果需要右边属性栏则需要
						// 进行如下配置
						additionalModules: [
							lintModule,
							// 左边工具栏以及节点
							propertiesProviderModule,
							// 右边的工具栏
							propertiesPanelModule,
							// activitiExtensionModule,
							// 国际化
							customTranslateModule,
						],
						moddleExtensions: {
							// camunda: camundaModdleDescriptor,
							activiti: activitiModdle,
						},
						keyboard: { bindTo: document },
					})

					self.createNewDiagram(self.templateBpmnXml)
				})
				.catch(err => {
					if (err && err.code == 404) {
						router.push({
							name: 'Process', // ProcessManagementsList
						})
					}
				})
		},
		// 取消复制流程
		copyBpmnCancel() {
			let self = this
			// 右侧属性面板清空
			document.getElementById('js-properties-panel').innerHTML = ''
			// 获取到属性ref为“canvas”的dom节点
			const canvas = self.$refs.canvas
			self.operationSymbolStatus = '' // 给状态置空 -> 显示版本号

			self.getXmlDefaultFileProcess({
				processDefId: self.deployProcessDefId,
				definitionId: self.deployProcessDesignId,
			})
				.then(res => {
					// deployProcessIsCurrent

					self.templateBpmnXml = decode(res.data.bpmStr) // decode(res.data.bpmStr)
					self.deployProcessDefinitionId = res.data.definitionId
					self.deployProcessName = res.data.name
					self.deployProcessKey = res.data.key

					self.deployProcessStatus =
						self.operationSymbolStatus === 'copy'
							? '0'
							: res.data.status
					self.deployProcessVersion =
						self.operationSymbolStatus === 'copy'
							? '1'
							: res.data.flowVersion || '1'
					self.deployProcessIsCurrent =
						self.operationSymbolStatus === 'copy'
							? false
							: res.data.curVersion || false

					res.data.deployId &&
						(self.deployProcessId = res.data.deployId)

					// 避免缓存，每次清一下
					if (self.bpmnModeler) {
						self.additionalModules = []
						self.bpmnModeler.destroy()
					}
					// 建模，官方文档这里讲的很详细
					self.bpmnModeler = new CustomModeler({
						container: canvas,
						linting: {
							active: true, // 默认开启规则校验
							// bpmnlint: bpmnlintConfig,
							bpmnlint: {
								config: {
									rules: { ...rules },
								},
								resolver,
							},
						},
						// 添加控制板(右边属性配置栏部分)
						propertiesPanel: {
							parent: '#js-properties-panel',
						},
						// 左边工具栏和右边属性栏配置, 如果只需要左边工具栏可以不添加如下配置，如果需要右边属性栏则需要
						// 进行如下配置
						additionalModules: [
							lintModule,
							// 左边工具栏以及节点
							propertiesProviderModule,
							// 右边的工具栏
							propertiesPanelModule,
							// activitiExtensionModule,
							// 国际化
							customTranslateModule,
						],
						moddleExtensions: {
							// camunda: camundaModdleDescriptor,
							activiti: activitiModdle,
						},
						keyboard: { bindTo: document },
					})

					// 未发布状态并且不是复制流程 的 流程设计 可以显示操作栏、右键菜单，以及发布流程
					if (
						res.data.status ===
							ProcessConstant.processDesignStatus.publish.value &&
						self.operationSymbolStatus !== 'copy'
					) {
						self.isHiddenMenu = true
						self.bpmnModeler.get('keyboard').unbind()
					} else {
						self.isHiddenMenu = false
						self.bpmnModeler.get('keyboard').bind(document)
					}

					self.createNewDiagram(self.templateBpmnXml)
				})
				.catch(err => {
					if (err && err.code != 200) {
						// self.onCloseClick()
						self.onProcessDesignAddClick()
					}
				})
		},

		// 新增流程设计按钮
		onProcessDesignAddClick() {
			let self = this
			this.processPublishedStatus = '0' // 用models查
			this.operationSymbolStatus = 'add' //  'add'新增流程设计按钮 标记

			// 右侧属性面板清空
			document.getElementById('js-properties-panel').innerHTML = ''
			// 获取到属性ref为“canvas”的dom节点
			const canvas = self.$refs.canvas
			self.getXmlFileProcess({
				definitionId: self.deployProcessDesignId,
				id: self.deployProcessDefId,
			})
				.then(res => {
					// 未发布状态并且不是复制流程 的 流程设计 可以显示操作栏、右键菜单，以及发布流程
					self.isHiddenMenu =
						res.data.status ===
						ProcessConstant.processDesignStatus.publish.value
							? true
							: false

					self.templateBpmnXml = decode(res.data.bpmStr)
					self.deployProcessDefinitionId =
						res.data.definitionId || self.deployProcessDesignId
					self.deployProcessName = res.data.name
					self.deployProcessKey = res.data.key

					self.deployProcessStatus = res.data.status
					res.data.deployId &&
						(self.deployProcessId = res.data.deployId)

					self.deployProcessIsCurrent = res.data.curVersion

					// 避免缓存，每次清一下
					if (self.bpmnModeler) {
						self.additionalModules = []
						self.bpmnModeler.destroy()
					}
					// 建模，官方文档这里讲的很详细
					self.bpmnModeler = new CustomModeler({
						container: canvas,
						linting: {
							active: true, // 默认开启规则校验
							// bpmnlint: bpmnlintConfig,
							bpmnlint: {
								config: {
									rules: { ...rules },
								},
								resolver,
							},
						},
						// 添加控制板(右边属性配置栏部分)
						propertiesPanel: {
							parent: '#js-properties-panel',
						},
						// 左边工具栏和右边属性栏配置, 如果只需要左边工具栏可以不添加如下配置，如果需要右边属性栏则需要
						// 进行如下配置
						additionalModules: [
							lintModule,
							// 左边工具栏以及节点
							propertiesProviderModule,
							// 右边的工具栏
							propertiesPanelModule,
							// activitiExtensionModule,
							// 国际化
							customTranslateModule,
						],
						moddleExtensions: {
							// camunda: camundaModdleDescriptor,
							activiti: activitiModdle,
						},
						keyboard: { bindTo: document },
					})

					self.createNewDiagram(self.templateBpmnXml)
				})
				.catch(err => {
					if (err && err.code == 404) {
						message.info(err.msg || '')
					}
				})
		},
		// 关闭
		onCloseClick() {
			this.deployProcessDefinitionId = '' // 单条数据查询接口返回的 Id
			this.deployProcessDesignId = '' // 流程设计列表 返回的id 流程设计Id
			this.deployProcessDefId = '' // 版本列表 返回的 Id；或者是 保存流程模型后返回的Id（接口/models）
			this.processPublishedStatus = '' // 流程是否发布的字段
			this.operationSymbolStatus = '' // 版本管理- 复制流程按钮 'copy',新增流程按钮 'add', 左侧工具栏、右键菜单需要显示;
			this.deployProcessKey = '' // 从查询单条流程xml接口取回的 key
			this.deployProcessName = '' // 从查询单条流程xml接口取回的 名称
			this.deployProcessStatus = '' // 从查询单条流程xml接口取回的 发布状态
			this.deployProcessVersion = '1' // 从查询单条流程xml接口取回的 版本信息
			this.deployProcessIsCurrent = false
			this.scale = 1
			this.templateBpmnXml = ''

			this.$emit('on-modal-close', false)
		},

		handlerRedo() {
			const self = this
			self.bpmnModeler.get('commandStack').redo()
		},
		handlerUndo() {
			const self = this
			self.bpmnModeler.get('commandStack').undo()
		},
		handlerZoom(radio) {
			const self = this
			const newScale = !radio ? 1.0 : self.scale + radio
			self.bpmnModeler.get('canvas').zoom(newScale)
			self.scale = newScale
		},
		// 导入
		beforeUpload(file) {
			const self = this
			const reg = new RegExp(/^bpmn$/gi)
			if (
				file.name &&
				reg.test(file.name.substring(file.name.lastIndexOf('.') + 1))
			) {
				self.openBpmn(file)
			} else {
				message.warning('请导入bpmn类型的文件！')
			}
			return false
		},
		openBpmn(file) {
			const self = this
			const reader = new FileReader()
			// 读取File对象中的文本信息，编码格式为UTF-8
			reader.readAsText(file, 'utf-8')
			reader.onload = () => {
				self.operationSymbolStatus = 'add' // 导入的bpmn，即为新建
				self.deployProcessStatus = '0' // 发布状态 - 未发布
				self.deployProcessVersion = '1' // 从查询单条流程xml接口取回的 版本信息
				self.isHiddenMenu = false

				// 读取完毕后将文本信息导入到Bpmn建模器
				self.createNewDiagram(reader.result)
			}
			return false
		},
		downloadBpmn() {
			const self = this
			self.bpmnModeler.saveXML({ format: true }, (err, xml) => {
				if (!err) {
					// 获取文件名
					const name = `${self.getFilename(xml)}.bpmn`
					// 将文件名以及数据交给下载方法
					self.download({ name: name, data: xml })
				}
			})
		},
		downloadSvg() {
			const self = this
			self.bpmnModeler.saveXML({ format: true }, (err, xml) => {
				if (!err) {
					// 获取文件名
					const name = `${self.getFilename(xml)}.svg`

					// 从建模器画布中提取svg图形标签
					let context = ''
					const djsGroupAll =
						self.$refs.canvas.querySelectorAll('.djs-group')
					for (let item of djsGroupAll) {
						context += item.innerHTML
					}
					// 获取svg的基本数据，长宽高
					const viewport = self.$refs.canvas
						.querySelector('.viewport')
						.getBBox()

					// 将标签和数据拼接成一个完整正常的svg图形
					const svg = `
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          xmlns:xlink="http://www.w3.org/1999/xlink"
                          width="${viewport.width}"
                          height="${viewport.height}"
                          viewBox="${viewport.x} ${viewport.y} ${viewport.width} ${viewport.height}"
                          version="1.1"
                          >
                          ${context}
                        </svg>
                      `
					// 将文件名以及数据交给下载方法
					self.download({ name: name, data: svg })
				}
			})
		},
		download({ name = 'diagram.bpmn', data }) {
			// 这里就获取到了之前设置的隐藏链接
			const downloadLink = this.$refs.downloadLink
			// 把数据转换为URI，下载要用到的
			const encodedData = encodeURIComponent(data)
			if (data) {
				// 将数据给到链接
				downloadLink.href =
					'data:application/bpmn20-xml;charset=UTF-8,' + encodedData
				// 设置文件名
				downloadLink.download = name
				// 触发点击事件开始下载
				downloadLink.click()
			}
		},
		getFilename(xml) {
			let start = xml.indexOf('process')
			let filename = xml.substr(start, xml.indexOf('>'))
			filename = filename.substr(filename.indexOf('id') + 4)
			filename = filename.substr(0, filename.indexOf('"'))
			return filename
		},
		onUsersModalCancel() {
			// 用户节点 - 选人弹框取消按钮
			this.confirmUsersModalVisible = false
		},
		onUsersModalConfirm(data, _str) {
			this.usersData = data

			jcBpmnPropertiesPanel.setUserTask(
				this.selectUserElementId,
				data,
				_str
			)
			// 用户节点 - 选人弹框确定按钮
			this.confirmUsersModalVisible &&
				(this.confirmUsersModalVisible = false)
		},

		// 定时器
		onTimersModalCancel() {
			this.confirmTimersModalVisible = false
		},
		onTimersModalConfirm(data) {
			this.timerData = data
			jcBpmnPropertiesPanel.setUserTimerDefinitionTask(
				this.selectTimerElementId,
				data
			)
			this.confirmTimersModalVisible = false
		},

		// 超期设置
		onDueDateModalCancel() {
			this.confirmDueDateVisible = false
		},
		onDueDateModalConfirm(data) {
			this.dueDateData = data
			jcBpmnPropertiesPanel.setDueDateValue(this.dueDateElementId, data)
			this.confirmDueDateVisible = false
		},

		// 连接器
		onConnectorModalCancel() {
			this.confirmConnectorModalVisible = false
		},
		onConnectorModalConfirm(data) {
			jcBpmnPropertiesPanel.setProcessConnectorTask(
				this.connectorElementId,
				data
			)
			this.confirmConnectorModalVisible = false
		},

		// 表单key
		onFormKeyModalCancel() {
			this.confirmFormKeyModalVisible = false
			// this.formKeyElementId = ''
		},
		onFormKeyModalConfirm(data, actiKey) {
			actiKey === ProcessConstant.FormEngineKeyTab.value
				? (this.isFormEngine = true)
				: (this.isFormEngine = false)
			this.confirmFormKeyModalVisible = false
			jcBpmnPropertiesPanel.setFormKeyValue(this.formKeyElementId, data)
		},

		// 资源配置
		onFormFieldsModalCancel() {
			this.confirmFormFieldsModalVisible = false
		},
		onFormFieldsModalConfirm(data) {
			this.confirmFormFieldsModalVisible = false
			jcBpmnPropertiesPanel.setFormFieldsValue(data)
		},

		// 权限按钮
		onPermissionButtonModalCancel() {
			this.confirmPermissionButtonModalVisible = false
		},
		onPermissionButtonModalConfirm(data) {
			let _btnLabel =
				!validatenull(data) && data.length > 0
					? data
							.map(v => {
								return v.label
							})
							.join(',')
					: ''

			this.confirmPermissionButtonModalVisible = false
			jcBpmnPropertiesPanel.setButtonListValue(
				this.permissionButtonElementId,
				_btnLabel,
				data
			)
		},

		// 服务组件
		onMicroflowModalCancel() {
			this.confirmMicroflowModalVisible = false
		},
		onMicroflowModalConfirm(data) {
			let _microflowName =
				!validatenull(data) && data.length > 0
					? data
							.map(v => {
								return v.name
							})
							.join(',')
					: ''
			this.confirmMicroflowModalVisible = false
			jcBpmnPropertiesPanel.setMicroflowListValue(
				this.microflowResourceId,
				_microflowName,
				data
			)

			// 设置activiti:candidateUsers属性值为 所选微流程的id
			const modeling = this.bpmnModeler.get('modeling')
			const elementRegistry = this.bpmnModeler.get('elementRegistry')
			var shape = elementRegistry.get(this.microflowElementId)

			if (shape.type === 'bpmn:UserTask') {
				let micoflowIds = data
					.map(v => {
						return v.id
					})
					?.toString()
				modeling.updateProperties(shape, {
					// name: '我是修改后的Task名称'
					'activiti:candidateUsers': micoflowIds,
				})
			}
		},

		// 调用活动
		onCallActivityModalCancel() {
			this.confirmCallActivityModalVisible = false
		},
		onCallActivityModalConfirm(data) {
			this.confirmCallActivityModalVisible = false
			jcBpmnPropertiesPanel.setCallActivityValue(
				this.callActivityElementId,
				{ key: data.processKey, version: data.curVersion }
			)
		},

		// 内联脚本 - 脚本
		onScriptValueModalCancel() {
			this.scriptValueElementId = ''
			this.scriptValueData = ''
			this.confirmScriptValueModalVisible = false
		},
		onScriptValueModalConfirm(code) {
			jcBpmnPropertiesPanel.setScriptValue(
				this.scriptValueElementId,
				code
			)
			this.onScriptValueModalCancel()
		},

		// 流程线- 条件类型 - 表达式
		onConditionExpressionCancel() {
			this.conditionExpression = ''
			this.conditionExpressionElementId = ''
			this.conditionExpressionFormData = ''
			this.conditionExpressionVisible = false
		},
		onConditionExpressionConfirm(data) {
			jcBpmnPropertiesPanel.setConditionalExpressionValue(
				this.conditionExpressionElementId,
				data
			)
			this.onConditionExpressionCancel()
		},

		// 编辑源文件
		onEditBpmnModalCancel() {
			this.sourceBpmnCode = ''
			this.editBpmnModalVisible = false
		},
		onEditBpmnModalConfirm(val) {
			this.createNewDiagram(val)
			this.sourceBpmnCode = ''
			this.editBpmnModalVisible = false
		},

		// 打开历史管理弹框
		viewHistoryManagement() {
			this.operationSymbolStatus = ''
			this.$emit('on-history-modal-view')
		},
	},
}
</script>

<style scoped>
/* 左边工具栏的样式 去掉该样式左边工具栏不显示 */
@import 'bpmn-js/dist/assets/diagram-js.css';

/* 左边工具栏内各个工具的样式，不添加该样式，左边工具栏内不显示任何工具 */
@import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css';

/*右边工具栏样式*/
@import 'jc-server-bpmn-js-properties-panel-activiti/dist/assets/bpmn-js-properties-panel.css';

.containers {
	display: flex;
	min-height: 100%;
}
.canvas {
	flex: 1;
	min-height: 100%;
}
.panel {
	width: 300px;
}
.action {
	position: absolute;
	margin-top: 0;
	/* margin-left: 180px; */
	z-index: 1;
}
.design-canvas-spin {
	margin-top: 30px;
	height: calc(100vh - 115px) !important; /* 100% !important; */
	background-color: #fff;
}
</style>
