From 02fa679d625a069a3cc88e0be5a5abde48215edf Mon Sep 17 00:00:00 2001 From: zhuguojian <984737666@qq.com> Date: Tue, 24 Dec 2024 11:48:24 +0800 Subject: [PATCH 01/62] =?UTF-8?q?feat:=E8=8F=9C=E5=8D=95=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E8=99=9A=E6=8B=9F=E5=8C=96=E6=A0=91=E5=BD=A2?= =?UTF-8?q?=E6=8E=A7=E4=BB=B6=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/system/menu/index.vue | 275 +++++++++++++++++++++++++------- 1 file changed, 219 insertions(+), 56 deletions(-) diff --git a/src/views/system/menu/index.vue b/src/views/system/menu/index.vue index b2c93bbe5..82177cf46 100644 --- a/src/views/system/menu/index.vue +++ b/src/views/system/menu/index.vue @@ -67,65 +67,87 @@ - - - - - - - - - - - - - - - - + + @@ -155,13 +177,26 @@ const queryParams = reactive({ const queryFormRef = ref() // 搜索的表单 const isExpandAll = ref(false) // 是否展开,默认全部折叠 const refreshTable = ref(true) // 重新渲染表格状态 +const currentNode = ref(null) // 当前选中节点 /** 查询列表 */ const getList = async () => { loading.value = true try { const data = await MenuApi.getMenuList(queryParams) - list.value = handleTree(data) + // 为每个节点添加 showInfo 属性和样式对象 + const addProps = (items: any[]) => { + items.forEach(item => { + item.showInfo = false + item.popupStyle = {} + if (item.children && item.children.length > 0) { + addProps(item.children) + } + }) + } + const processedData = handleTree(data) + addProps(processedData) + list.value = processedData } finally { loading.value = false } @@ -233,8 +268,136 @@ const handleStatusChanged = async (menu: MenuVO, val: number) => { } } +const handleCurrentChange = (data: any) => { + currentNode.value = data + // 关闭所有信息面板 + list.value.forEach((item: any) => { + item.showInfo = false + }) +} + +// 添加点击外部关闭弹出层的处理 +onMounted(() => { + document.addEventListener('click', (event: MouseEvent) => { + const target = event.target as HTMLElement + if (!target.closest('.menu-info-popup') && !target.closest('.info-button')) { + list.value.forEach((item: any) => { + item.showInfo = false + }) + } + }) +}) + /** 初始化 **/ onMounted(() => { getList() }) + + \ No newline at end of file From d815c60340ecf6c13ce1dc4493e701bc93d8b4ae Mon Sep 17 00:00:00 2001 From: AhJindeg Date: Thu, 26 Dec 2024 11:40:25 +0800 Subject: [PATCH 02/62] feat: add hiddenSearch function to manage search visibility in RouterSearch component --- src/components/RouterSearch/index.vue | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/components/RouterSearch/index.vue b/src/components/RouterSearch/index.vue index ed2a08cc2..42a41744d 100644 --- a/src/components/RouterSearch/index.vue +++ b/src/components/RouterSearch/index.vue @@ -79,9 +79,14 @@ function remoteMethod(data) { function handleChange(path) { router.push({ path }) + hiddenSearch() hiddenTopSearch() } +function hiddenSearch() { + showSearch.value = false +} + function hiddenTopSearch() { showTopSearch.value = false } From 74b62bf05ea52ae12eeae89a1315a4a48b010981 Mon Sep 17 00:00:00 2001 From: jinmh716 Date: Sat, 28 Dec 2024 12:59:42 +0800 Subject: [PATCH 03/62] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E3=80=91=E6=96=87=E4=BB=B6=E5=88=97=E8=A1=A8:=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E5=A4=8D=E5=88=B6=E9=93=BE=E6=8E=A5=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/infra/file/index.vue | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/views/infra/file/index.vue b/src/views/infra/file/index.vue index 3fcda6e8d..8281d9b31 100644 --- a/src/views/infra/file/index.vue +++ b/src/views/infra/file/index.vue @@ -95,6 +95,13 @@ /> - + @@ -84,8 +87,17 @@ const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.ROUTE const routerGroups = ref([]) const nodeOptions = ref() +const conditionRef = ref([]) // 保存配置 const saveConfig = async () => { + // 校验表单 + let valid = true + for (const item of conditionRef.value) { + if (!(await item.validate())) { + valid = false + } + } + if (!valid) return false const showText = getShowText() if (!showText) return false currentNode.value.name = nodeName.value! diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue index e8fe1d766..85f6e4a0d 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue @@ -59,15 +59,24 @@
- - - + + + + +
@@ -80,7 +89,16 @@
- + + +
@@ -122,8 +140,8 @@ import { ConditionType, ProcessVariableEnum } from '../../consts' -import {BpmModelFormType} from '@/utils/constants' -import {useFormFields} from '../../node' +import { BpmModelFormType } from '@/utils/constants' +import { useFormFields } from '../../node' const props = defineProps({ modelValue: { @@ -202,10 +220,10 @@ const addConditionGroup = (conditions) => { const validate = async () => { if (!formRef) return false - return await formRef.value.validate(); + return await formRef.value.validate() } -defineExpose({validate}) +defineExpose({ validate }) diff --git a/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue b/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue index 9d2fa5ba6..5b3d14f43 100644 --- a/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue +++ b/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue @@ -308,28 +308,6 @@ const props = defineProps({ } }) -// 监听value变化,重新加载流程图 -watch( - () => props.value, - (newValue) => { - if (newValue && bpmnModeler) { - createNewDiagram(newValue) - } - }, - { immediate: true } -) - -// 监听processId和processName变化 -watch( - [() => props.processId, () => props.processName], - ([newId, newName]) => { - if (newId && newName && !props.value) { - createNewDiagram(null) - } - }, - { immediate: true } -) - provide('configGlobal', props) let bpmnModeler: any = null const defaultZoom = ref(1) @@ -480,6 +458,7 @@ const initModelListeners = () => { emit('commandStack-changed', event) emit('input', xml) emit('change', xml) + emit('save', xml) } catch (e: any) { console.error(`[Process Designer Warn]: ${e.message || e}`) } diff --git a/src/views/bpm/model/editor/index.vue b/src/views/bpm/model/editor/index.vue index 37eff739e..512eb1522 100644 --- a/src/views/bpm/model/editor/index.vue +++ b/src/views/bpm/model/editor/index.vue @@ -3,6 +3,7 @@ () @@ -51,10 +52,11 @@ const formType = ref(20) provide('formFields', formFields) provide('formType', formType) -const xmlString = ref('') // BPMN XML +//注入 流程数据 +const xmlString = inject('processData') as Ref + const modeler = shallowRef() // BPMN Modeler const processDesigner = ref() -const isModelerReady = ref(false) const controlForm = ref({ simulation: true, labelEditing: false, @@ -65,154 +67,27 @@ const controlForm = ref({ }) const model = ref() // 流程模型的信息 -// 初始化 bpmnInstances -const initBpmnInstances = () => { - if (!modeler.value) return false - try { - const instances = { - modeler: modeler.value, - modeling: modeler.value.get('modeling'), - moddle: modeler.value.get('moddle'), - eventBus: modeler.value.get('eventBus'), - bpmnFactory: modeler.value.get('bpmnFactory'), - elementFactory: modeler.value.get('elementFactory'), - elementRegistry: modeler.value.get('elementRegistry'), - replace: modeler.value.get('replace'), - selection: modeler.value.get('selection') - } - - // 检查所有实例是否都存在 - return Object.values(instances).every((instance) => instance) - } catch (error) { - console.error('初始化 bpmnInstances 失败:', error) - return false - } -} /** 初始化 modeler */ const initModeler = async (item) => { - try { - modeler.value = item - // 等待 modeler 初始化完成 - await nextTick() - - // 确保 modeler 的所有实例都已经准备好 - if (initBpmnInstances()) { - isModelerReady.value = true - emit('init-finished') - - // 初始化完成后,设置初始值 - if (props.modelId) { - // 编辑模式 - const data = await ModelApi.getModel(props.modelId) - model.value = { - ...data, - bpmnXml: undefined // 清空 bpmnXml 属性 - } - xmlString.value = data.bpmnXml || getDefaultBpmnXml(data.key, data.name) - } else if (props.modelKey && props.modelName) { - // 新建模式 - xmlString.value = props.value || getDefaultBpmnXml(props.modelKey, props.modelName) - model.value = { - key: props.modelKey, - name: props.modelName - } as ModelApi.ModelVO - } - - // 导入XML并刷新视图 - await nextTick() - try { - await modeler.value.importXML(xmlString.value) - if (processDesigner.value?.refresh) { - processDesigner.value.refresh() - } - } catch (error) { - console.error('导入XML失败:', error) - } - } else { - console.error('modeler 实例未完全初始化') - } - } catch (error) { - console.error('初始化 modeler 失败:', error) - } + modeler.value = item } -/** 获取默认的BPMN XML */ -const getDefaultBpmnXml = (key: string, name: string) => { - return ` - - - - - -` -} /** 添加/修改模型 */ const save = async (bpmnXml: string) => { try { xmlString.value = bpmnXml - if (props.modelId) { - // 编辑模式 - const data = { - ...model.value, - bpmnXml: bpmnXml - } as unknown as ModelApi.ModelVO - await ModelApi.updateModelBpmn(data) - emit('success') - } else { - // 新建模式,直接返回XML - emit('success', bpmnXml) - } + emit('success', bpmnXml) } catch (error) { console.error('保存失败:', error) message.error('保存失败') } } -// 监听 key、name 和 value 的变化 -watch( - [() => props.modelKey, () => props.modelName, () => props.value], - async ([newKey, newName, newValue]) => { - if (!props.modelId && isModelerReady.value) { - let shouldRefresh = false - - if (newKey && newName) { - const newXml = newValue || getDefaultBpmnXml(newKey, newName) - if (newXml !== xmlString.value) { - xmlString.value = newXml - shouldRefresh = true - } - model.value = { - ...model.value, - key: newKey, - name: newName - } as ModelApi.ModelVO - } else if (newValue && newValue !== xmlString.value) { - xmlString.value = newValue - shouldRefresh = true - } - - if (shouldRefresh) { - // 确保更新后重新渲染 - await nextTick() - if (processDesigner.value?.refresh) { - try { - await modeler.value?.importXML(xmlString.value) - processDesigner.value.refresh() - } catch (error) { - console.error('导入XML失败:', error) - } - } - } - } - }, - { deep: true } -) // 在组件卸载时清理 onBeforeUnmount(() => { - isModelerReady.value = false modeler.value = null // 清理全局实例 const w = window as any @@ -221,54 +96,7 @@ onBeforeUnmount(() => { } }) -/** 获取 XML 字符串 */ -const saveXML = async () => { - if (!modeler.value) { - return { xml: xmlString.value } - } - try { - const result = await modeler.value.saveXML({ format: true }) - xmlString.value = result.xml - return result - } catch (error) { - console.error('获取XML失败:', error) - return { xml: xmlString.value } - } -} -/** 获取SVG字符串 */ -const saveSVG = async () => { - if (!modeler.value) { - return { svg: undefined } - } - try { - return await modeler.value.saveSVG() - } catch (error) { - console.error('获取SVG失败:', error) - return { svg: undefined } - } -} - -/** 刷新视图 */ -const refresh = async () => { - if (processDesigner.value?.refresh && modeler.value) { - try { - await modeler.value.importXML(xmlString.value) - processDesigner.value.refresh() - } catch (error) { - console.error('刷新视图失败:', error) - } - } -} - -// 暴露必要的属性和方法给父组件 -defineExpose({ - modeler, - isModelerReady, - saveXML, - saveSVG, - refresh -}) From 42c1618202242bb193da1768fd0a9548ecee86c7 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Tue, 14 Jan 2025 09:12:53 +0800 Subject: [PATCH 30/62] =?UTF-8?q?fix:=20=E5=88=9B=E5=BB=BAUserTask?= =?UTF-8?q?=E6=97=A0signEnable=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/nodes-config/UserTaskNodeConfig.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 131f7b9ef..00ed6cfea 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -990,7 +990,7 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => { configForm.value.taskCompleteListenerHeader = node.taskCompleteListener?.header ?? [] configForm.value.taskCompleteListenerBody = node.taskCompleteListener?.body ?? [] // 6. 签名 - configForm.value.signEnable = node.signEnable ?? false + configForm.value.signEnable = node?.signEnable ?? false } defineExpose({ openDrawer, showUserTaskNodeConfig }) // 暴露方法给父组件 From 4fe158b2ec5d03bf5ca206c9e04e85bc1aa38bc7 Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Tue, 14 Jan 2025 12:00:08 +0800 Subject: [PATCH 31/62] =?UTF-8?q?perf:=20bpm=20=E4=BF=AE=E5=A4=8Dbpmn?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E5=99=A8=E4=B8=8D=E6=98=BE=E7=A4=BA=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/bpm/model/editor/index.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/src/views/bpm/model/editor/index.vue b/src/views/bpm/model/editor/index.vue index 512eb1522..101ea1b87 100644 --- a/src/views/bpm/model/editor/index.vue +++ b/src/views/bpm/model/editor/index.vue @@ -3,7 +3,6 @@ Date: Tue, 14 Jan 2025 17:17:30 +0800 Subject: [PATCH 32/62] =?UTF-8?q?fix:=E8=A1=A8=E5=8D=95=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=EF=BC=8Cjson=E6=98=BE=E7=A4=BA=E5=92=8C?= =?UTF-8?q?=E7=94=9F=E6=88=90=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/infra/build/index.vue | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/views/infra/build/index.vue b/src/views/infra/build/index.vue index ed1091e7b..2eb63b6a9 100644 --- a/src/views/infra/build/index.vue +++ b/src/views/infra/build/index.vue @@ -135,7 +135,8 @@ const makeTemplate = () => { /** 复制 **/ const copy = async (text: string) => { - const { copy, copied, isSupported } = useClipboard({ source: text }) + const textToCopy = JSON.stringify(text, null, 2) + const { copy, copied, isSupported } = useClipboard({ source: textToCopy }) if (!isSupported) { message.error(t('common.copyError')) } else { @@ -149,18 +150,19 @@ const copy = async (text: string) => { /** * 代码高亮 */ -const highlightedCode = (code) => { +const highlightedCode = (code: string) => { // 处理语言和代码 let language = 'json' if (formType.value === 2) { language = 'xml' } + // debugger if (!isString(code)) { - code = JSON.stringify(code) + code = JSON.stringify(code, null, 2) } // 高亮 - const result = hljs.highlight(language, code, true) - return result.value || ' ' + const result = hljs.highlight(code, { language: language, ignoreIllegals: true }) + return result.value } /** 初始化 **/ From 0fa31be851d0fcd30f34d577480ae219761dcaa3 Mon Sep 17 00:00:00 2001 From: lizhixian <18210040298@163.com> Date: Tue, 14 Jan 2025 17:20:51 +0800 Subject: [PATCH 33/62] =?UTF-8?q?fix:=E8=A1=A8=E5=8D=95=E6=9E=84=E5=BB=BA?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=EF=BC=8Cjson=E6=98=BE=E7=A4=BA=E5=92=8C?= =?UTF-8?q?=E7=94=9F=E6=88=90=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/infra/build/index.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/infra/build/index.vue b/src/views/infra/build/index.vue index 2eb63b6a9..260b8b7a0 100644 --- a/src/views/infra/build/index.vue +++ b/src/views/infra/build/index.vue @@ -162,7 +162,7 @@ const highlightedCode = (code: string) => { } // 高亮 const result = hljs.highlight(code, { language: language, ignoreIllegals: true }) - return result.value + return result.value || ' ' } /** 初始化 **/ From e76eda8af3c1e533b0689d3859f23ac5b9d15def Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Wed, 15 Jan 2025 14:54:23 +0800 Subject: [PATCH 34/62] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E5=9C=A8keepAlive=E4=B8=8B=E5=88=B7=E6=96=B0=E4=B8=8D?= =?UTF-8?q?=E8=A7=A6=E5=8F=91onActivated=E9=92=A9=E5=AD=90=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/components/TagsView/src/TagsView.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layout/components/TagsView/src/TagsView.vue b/src/layout/components/TagsView/src/TagsView.vue index dcbb90fdb..3bfb69df8 100644 --- a/src/layout/components/TagsView/src/TagsView.vue +++ b/src/layout/components/TagsView/src/TagsView.vue @@ -243,7 +243,7 @@ const move = (to: number) => { start() } -onMounted(() => { +onBeforeMount(() => { initTags() addTags() }) From 8df285aefb5abfbc1573988dc03da5718008738f Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Wed, 15 Jan 2025 14:57:23 +0800 Subject: [PATCH 35/62] =?UTF-8?q?fix:=20bpm=20=E7=94=A8onActivated?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2onMounted=20=E8=A7=A3=E5=86=B3=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=A8=A1=E5=9E=8B=E8=BF=94=E5=9B=9E=E5=90=8E=E4=B8=8D?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E6=96=B0=E7=9A=84=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/bpm/model/index.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/views/bpm/model/index.vue b/src/views/bpm/model/index.vue index c7d941708..8132bf738 100644 --- a/src/views/bpm/model/index.vue +++ b/src/views/bpm/model/index.vue @@ -207,6 +207,8 @@ const getList = async () => { /** 初始化 **/ onMounted(() => { +}) +onActivated(()=>{ getList() }) From b1174313185998677be5a7142a0f716563e0b478 Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Wed, 15 Jan 2025 15:04:23 +0800 Subject: [PATCH 36/62] =?UTF-8?q?feat:=20bpm=20=E6=B7=BB=E5=8A=A0=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E6=A8=A1=E5=9E=8B=E5=A4=8D=E5=88=B6=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/router/modules/remaining.ts | 2 +- src/views/bpm/model/CategoryDraggableModel.vue | 11 ++++++++++- src/views/bpm/model/form/index.vue | 5 ++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts index 806f954da..344660794 100644 --- a/src/router/modules/remaining.ts +++ b/src/router/modules/remaining.ts @@ -344,7 +344,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ } }, { - path: 'manager/model/update/:id', + path: 'manager/model/:type/:id', component: () => import('@/views/bpm/model/form/index.vue'), name: 'BpmModelUpdate', meta: { diff --git a/src/views/bpm/model/CategoryDraggableModel.vue b/src/views/bpm/model/CategoryDraggableModel.vue index f3b5a422f..8fe6e14d5 100644 --- a/src/views/bpm/model/CategoryDraggableModel.vue +++ b/src/views/bpm/model/CategoryDraggableModel.vue @@ -163,6 +163,15 @@ > 修改 + + 复制 + { } else { push({ name: 'BpmModelUpdate', - params: { id } + params: { id, type } }) } } diff --git a/src/views/bpm/model/form/index.vue b/src/views/bpm/model/form/index.vue index 3a45e7160..6c5cb21a2 100644 --- a/src/views/bpm/model/form/index.vue +++ b/src/views/bpm/model/form/index.vue @@ -162,7 +162,10 @@ const initData = async () => { if (modelId) { // 修改场景 formData.value = await ModelApi.getModel(modelId) - + // 复制场景 + if (route.params.type === 'copy') { + delete formData.value.id + } } else { // 新增场景 formData.value.managerUserIds.push(userStore.getUser.id) From 6fba4b722805f742e0e6804827b6f34d8444bdac Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 15 Jan 2025 20:25:07 +0800 Subject: [PATCH 37/62] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91BPM=EF=BC=9A=E6=B5=81=E7=A8=8B=E7=BC=96?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/SimpleProcessDesigner.vue | 7 +-- .../src/SimpleProcessModel.vue | 53 +++++++++---------- src/router/modules/remaining.ts | 1 + src/views/bpm/model/editor/index.vue | 8 +-- src/views/bpm/model/form/ProcessDesign.vue | 10 ---- src/views/bpm/model/form/index.vue | 40 +++++++------- src/views/bpm/model/index.vue | 4 +- src/views/bpm/simple/SimpleModelDesign.vue | 14 +---- 8 files changed, 51 insertions(+), 86 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue index 1125d8e7d..70eade33f 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue @@ -63,8 +63,6 @@ const props = defineProps({ }) const processData = inject('processData') as Ref - - const loading = ref(false) const formFields = ref([]) const formType = ref(20) @@ -110,7 +108,6 @@ const updateModel = () => { } } - const saveSimpleFlowModel = async (simpleModelNode: SimpleFlowNode) => { if (!simpleModelNode) { return @@ -201,7 +198,5 @@ onMounted(async () => { const simpleProcessModelRef = ref() - -defineExpose({ -}) +defineExpose({}) diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue index b9a264751..23f2d7913 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue @@ -3,10 +3,15 @@
- 导出 - 导入 + + 导出 + + + 导入 + {{ scaleValue }}% - - - - - - - - -
@@ -53,7 +49,7 @@ import ProcessNodeTree from './ProcessNodeTree.vue' import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from './consts' import { useWatchNode } from './node' -import { ZoomOut, ZoomIn, ScaleToOriginal, Select } from '@element-plus/icons-vue' +import { ZoomOut, ZoomIn, ScaleToOriginal } from '@element-plus/icons-vue' import { isString } from '@/utils/is' defineOptions({ @@ -73,7 +69,7 @@ const props = defineProps({ }) const emits = defineEmits<{ - 'save': [node: SimpleFlowNode | undefined] + save: [node: SimpleFlowNode | undefined] }>() const processNodeTree = useWatchNode(props) @@ -175,25 +171,28 @@ defineExpose({ getCurrentFlowData }) +/** 导出 JSON */ +// TODO @zws:增加一个 download 里面搞个 json 更好 const exportJson = () => { - const blob = new Blob([JSON.stringify(processNodeTree.value)]); - const tempLink = document.createElement('a'); // 创建a标签 - const href = window.URL.createObjectURL(blob); // 创建下载的链接 - //filename - const fileName = `model.json`; - tempLink.href = href; - tempLink.target = '_blank'; - tempLink.download = fileName; - document.body.appendChild(tempLink); - tempLink.click(); // 点击下载 - document.body.removeChild(tempLink); // 下载完成移除元素 - window.URL.revokeObjectURL(href); // 释放掉blob对象 + const blob = new Blob([JSON.stringify(processNodeTree.value)]) + const tempLink = document.createElement('a') // 创建a标签 + const href = window.URL.createObjectURL(blob) // 创建下载的链接 + // filename + const fileName = `model.json` + tempLink.href = href + tempLink.target = '_blank' + tempLink.download = fileName + document.body.appendChild(tempLink) + tempLink.click() // 点击下载 + document.body.removeChild(tempLink) // 下载完成移除元素 + window.URL.revokeObjectURL(href) // 释放掉 blob 对象 } + +/** 导入 JSON */ +const refFile = ref() const importJson = () => { refFile.value.click() } -const refFile = ref() -// 加载本地文件 const importLocalFile = () => { const file = refFile.value.files[0] const reader = new FileReader() diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts index 344660794..4b177ae87 100644 --- a/src/router/modules/remaining.ts +++ b/src/router/modules/remaining.ts @@ -344,6 +344,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ } }, { + // TODO @zws:1)建议,在加一个路由。然后标题是“复制流程”,这样体验会好点;2)复制出来的数据,在名字前面,加“副本 ”,和钉钉保持一致! path: 'manager/model/:type/:id', component: () => import('@/views/bpm/model/form/index.vue'), name: 'BpmModelUpdate', diff --git a/src/views/bpm/model/editor/index.vue b/src/views/bpm/model/editor/index.vue index 101ea1b87..b91c250e9 100644 --- a/src/views/bpm/model/editor/index.vue +++ b/src/views/bpm/model/editor/index.vue @@ -51,7 +51,7 @@ const formType = ref(20) provide('formFields', formFields) provide('formType', formType) -//注入 流程数据 +// 注入流程数据 const xmlString = inject('processData') as Ref const modeler = shallowRef() // BPMN Modeler @@ -66,13 +66,12 @@ const controlForm = ref({ }) const model = ref() // 流程模型的信息 - /** 初始化 modeler */ +// TODO @zws:需要初始化,不然首次创建后,无法发布!相当于说,key、name 要去赋值下 const initModeler = async (item) => { modeler.value = item } - /** 添加/修改模型 */ const save = async (bpmnXml: string) => { try { @@ -84,7 +83,6 @@ const save = async (bpmnXml: string) => { } } - // 在组件卸载时清理 onBeforeUnmount(() => { modeler.value = null @@ -94,8 +92,6 @@ onBeforeUnmount(() => { w.bpmnInstances = null } }) - - From 026b2f2ba5bb4957359aa96ffd3ee3fac4ac458b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8A=8B=E9=81=93=E6=BA=90=E7=A0=81?= Date: Wed, 15 Jan 2025 20:45:49 +0800 Subject: [PATCH 38/62] Revert "fix:Vite CJS Node API deprecated waring" --- .eslintrc.cjs => .eslintrc.js | 0 .vscode/settings.json | 2 +- package.json | 1 - postcss.config.js | 2 +- prettier.config.cjs => prettier.config.js | 0 5 files changed, 2 insertions(+), 3 deletions(-) rename .eslintrc.cjs => .eslintrc.js (100%) rename prettier.config.cjs => prettier.config.js (100%) diff --git a/.eslintrc.cjs b/.eslintrc.js similarity index 100% rename from .eslintrc.cjs rename to .eslintrc.js diff --git a/.vscode/settings.json b/.vscode/settings.json index a14646c92..f145f386a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -138,7 +138,7 @@ "*.ts": "$(capture).test.ts, $(capture).test.tsx", "*.tsx": "$(capture).test.ts, $(capture).test.tsx", "*.env": "$(capture).env.*", - "package.json": "pnpm-lock.yaml,yarn.lock,LICENSE,README*,CHANGELOG*,CNAME,.gitattributes,.eslintrc-auto-import.json,.gitignore,prettier.config.cjs,stylelint.config.js,commitlint.config.js,.stylelintignore,.prettierignore,.gitpod.yml,.eslintrc.cjs,.eslintignore" + "package.json": "pnpm-lock.yaml,yarn.lock,LICENSE,README*,CHANGELOG*,CNAME,.gitattributes,.eslintrc-auto-import.json,.gitignore,prettier.config.js,stylelint.config.js,commitlint.config.js,.stylelintignore,.prettierignore,.gitpod.yml,.eslintrc.js,.eslintignore" }, "terminal.integrated.scrollback": 10000, "nuxt.isNuxtApp": false diff --git a/package.json b/package.json index 95b5345b7..ff94abd74 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,6 @@ "description": "基于vue3、vite4、element-plus、typesScript", "author": "xingyu", "private": false, - "type": "module", "scripts": { "i": "pnpm install", "dev": "vite --mode env.local", diff --git a/postcss.config.js b/postcss.config.js index e712f561b..961986e2b 100644 --- a/postcss.config.js +++ b/postcss.config.js @@ -1,4 +1,4 @@ -export default { +module.exports = { plugins: { autoprefixer: {} } diff --git a/prettier.config.cjs b/prettier.config.js similarity index 100% rename from prettier.config.cjs rename to prettier.config.js From 9849a040c00fef3d6214876241a38549b2b881cb Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 09:20:57 +0800 Subject: [PATCH 39/62] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0download.json()?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/download.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utils/download.ts b/src/utils/download.ts index 5bbfb9fe6..0820136fa 100644 --- a/src/utils/download.ts +++ b/src/utils/download.ts @@ -33,6 +33,10 @@ const download = { markdown: (data: Blob, fileName: string) => { download0(data, fileName, 'text/markdown') }, + // 下载 Json 方法 + json: (data: Blob, fileName: string) => { + download0(data, fileName, 'application/json') + }, // 下载图片(允许跨域) image: ({ url, From 2f7200abdb576ec8bebe0d222f18525c29bea52f Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 09:26:38 +0800 Subject: [PATCH 40/62] =?UTF-8?q?feat:=20=E4=BB=8Evue-element-plus-admin?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=20=E5=90=8C=E6=AD=A5TagsView=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=20=E5=AE=9E=E7=8E=B0=E8=AE=BE=E7=BD=AE=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=E6=A0=87=E9=A2=98=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/TagsView/src/TagsView.vue | 107 ++++++++++-------- src/store/modules/tagsView.ts | 26 ++++- 2 files changed, 84 insertions(+), 49 deletions(-) diff --git a/src/layout/components/TagsView/src/TagsView.vue b/src/layout/components/TagsView/src/TagsView.vue index 3bfb69df8..ce041b2b4 100644 --- a/src/layout/components/TagsView/src/TagsView.vue +++ b/src/layout/components/TagsView/src/TagsView.vue @@ -12,6 +12,11 @@ import { useDesign } from '@/hooks/web/useDesign' import { useTemplateRefsList } from '@vueuse/core' import { ElScrollbar } from 'element-plus' import { useScrollTo } from '@/hooks/event/useScrollTo' +import { useTagsView } from '@/hooks/web/useTagsView' +import { cloneDeep } from 'lodash-es' + + +defineOptions({ name: 'TagsView' }) const { getPrefixCls } = useDesign() @@ -19,7 +24,9 @@ const prefixCls = getPrefixCls('tags-view') const { t } = useI18n() -const { currentRoute, push, replace } = useRouter() +const { currentRoute, push } = useRouter() + +const { closeAll, closeLeft, closeRight, closeOther, closeCurrent, refreshPage } = useTagsView() const permissionStore = usePermissionStore() @@ -31,6 +38,10 @@ const visitedViews = computed(() => tagsViewStore.getVisitedViews) const affixTagArr = ref([]) +const selectedTag = computed(() => tagsViewStore.getSelectedTag) + +const setSelectTag = tagsViewStore.setSelectedTag + const appStore = useAppStore() const tagsViewImmerse = computed(() => appStore.getTagsViewImmerse) @@ -45,66 +56,30 @@ const initTags = () => { for (const tag of unref(affixTagArr)) { // Must have tag name if (tag.name) { - tagsViewStore.addVisitedView(tag) + tagsViewStore.addVisitedView(cloneDeep(tag)) } } } -const selectedTag = ref() - // 新增tag const addTags = () => { const { name } = unref(currentRoute) if (name) { - selectedTag.value = unref(currentRoute) + setSelectTag(unref(currentRoute)) tagsViewStore.addView(unref(currentRoute)) } - return false } // 关闭选中的tag const closeSelectedTag = (view: RouteLocationNormalizedLoaded) => { - if (view?.meta?.affix) return - tagsViewStore.delView(view) - if (isActive(view)) { - toLastView() - } -} - -// 关闭全部 -const closeAllTags = () => { - tagsViewStore.delAllViews() - toLastView() -} - -// 关闭其它 -const closeOthersTags = () => { - tagsViewStore.delOthersViews(unref(selectedTag) as RouteLocationNormalizedLoaded) -} - -// 重新加载 -const refreshSelectedTag = async (view?: RouteLocationNormalizedLoaded) => { - if (!view) return - tagsViewStore.delCachedView() - const { path, query } = view - await nextTick() - replace({ - path: '/redirect' + path, - query: query + closeCurrent(view, () => { + if (isActive(view)) { + toLastView() + } }) } -// 关闭左侧 -const closeLeftTags = () => { - tagsViewStore.delLeftViews(unref(selectedTag) as RouteLocationNormalizedLoaded) -} - -// 关闭右侧 -const closeRightTags = () => { - tagsViewStore.delRightViews(unref(selectedTag) as RouteLocationNormalizedLoaded) -} - -// 跳转到最后一个 +// 去最后一个 const toLastView = () => { const visitedViews = tagsViewStore.getVisitedViews const latestView = visitedViews.slice(-1)[0] @@ -118,11 +93,38 @@ const toLastView = () => { addTags() return } - // TODO: You can set another route - push('/') + // You can set another route + push(permissionStore.getAddRouters[0].path) } } +// 关闭全部 +const closeAllTags = () => { + closeAll(() => { + toLastView() + }) +} + +// 关闭其它 +const closeOthersTags = () => { + closeOther() +} + +// 重新加载 +const refreshSelectedTag = async (view?: RouteLocationNormalizedLoaded) => { + refreshPage(view) +} + +// 关闭左侧 +const closeLeftTags = () => { + closeLeft() +} + +// 关闭右侧 +const closeRightTags = () => { + closeRight() +} + // 滚动到选中的tag const moveToCurrentTag = async () => { await nextTick() @@ -209,13 +211,14 @@ const isActive = (route: RouteLocationNormalizedLoaded): boolean => { // 所有右键菜单组件的元素 const itemRefs = useTemplateRefsList>() -// 右键菜单装填改变的时候 +// 右键菜单状态改变的时候 const visibleChange = (visible: boolean, tagItem: RouteLocationNormalizedLoaded) => { if (visible) { for (const v of unref(itemRefs)) { const elDropdownMenuRef = v.elDropdownMenuRef if (tagItem.fullPath !== v.tagItem.fullPath) { elDropdownMenuRef?.handleClose() + setSelectTag(tagItem) } } } @@ -243,6 +246,16 @@ const move = (to: number) => { start() } +const canShowIcon = (item: RouteLocationNormalizedLoaded) => { + if ( + (item?.matched?.[1]?.meta?.icon && unref(tagsViewIcon)) || + (item?.meta?.affix && unref(tagsViewIcon) && item?.meta?.icon) + ) { + return true + } + return false +} + onBeforeMount(() => { initTags() addTags() diff --git a/src/store/modules/tagsView.ts b/src/store/modules/tagsView.ts index 4368efe0b..f565ef956 100644 --- a/src/store/modules/tagsView.ts +++ b/src/store/modules/tagsView.ts @@ -4,16 +4,19 @@ import { getRawRoute } from '@/utils/routerHelper' import { defineStore } from 'pinia' import { store } from '../index' import { findIndex } from '@/utils' +import { useUserStoreWithOut } from './user' export interface TagsViewState { visitedViews: RouteLocationNormalizedLoaded[] cachedViews: Set + selectedTag?: RouteLocationNormalizedLoaded } export const useTagsViewStore = defineStore('tagsView', { state: (): TagsViewState => ({ visitedViews: [], - cachedViews: new Set() + cachedViews: new Set(), + selectedTag: undefined }), getters: { getVisitedViews(): RouteLocationNormalizedLoaded[] { @@ -21,6 +24,9 @@ export const useTagsViewStore = defineStore('tagsView', { }, getCachedViews(): string[] { return Array.from(this.cachedViews) + }, + getSelectedTag(): RouteLocationNormalizedLoaded | undefined { + return this.selectedTag } }, actions: { @@ -98,8 +104,12 @@ export const useTagsViewStore = defineStore('tagsView', { }, // 删除所有tag delAllVisitedViews() { + const userStore = useUserStoreWithOut() + // const affixTags = this.visitedViews.filter((tag) => tag.meta.affix) - this.visitedViews = [] + this.visitedViews = userStore.getUser + ? this.visitedViews.filter((tag) => tag?.meta?.affix) + : [] }, // 删除其他 delOthersViews(view: RouteLocationNormalizedLoaded) { @@ -145,6 +155,18 @@ export const useTagsViewStore = defineStore('tagsView', { break } } + }, + // 设置当前选中的tag + setSelectedTag(tag: RouteLocationNormalizedLoaded) { + this.selectedTag = tag + }, + setTitle(title: string, path?: string) { + for (const v of this.visitedViews) { + if (v.path === (path ?? this.selectedTag?.path)) { + v.meta.title = title + break + } + } } }, persist: false From e44f48c0c4bb371913242a00981e96e9f774a0f6 Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 09:27:30 +0800 Subject: [PATCH 41/62] =?UTF-8?q?perf:=20bpm=E6=A8=A1=E5=9E=8B=E5=A4=8D?= =?UTF-8?q?=E5=88=B6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/bpm/model/CategoryDraggableModel.vue | 6 ++++++ src/views/bpm/model/form/index.vue | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/views/bpm/model/CategoryDraggableModel.vue b/src/views/bpm/model/CategoryDraggableModel.vue index 8fe6e14d5..9c5b9b13c 100644 --- a/src/views/bpm/model/CategoryDraggableModel.vue +++ b/src/views/bpm/model/CategoryDraggableModel.vue @@ -254,6 +254,7 @@ import { checkPermi } from '@/utils/permission' import { useUserStoreWithOut } from '@/store/modules/user' import { useAppStore } from '@/store/modules/app' import { cloneDeep } from 'lodash-es' +import {useTagsView} from "@/hooks/web/useTagsView"; defineOptions({ name: 'BpmModel' }) @@ -474,6 +475,7 @@ const handleDeleteCategory = async () => { } catch {} } +const tagsView = useTagsView(); /** 添加流程模型弹窗 */ const modelFormRef = ref() const openModelForm = (type: string, id?: number) => { @@ -483,6 +485,10 @@ const openModelForm = (type: string, id?: number) => { push({ name: 'BpmModelUpdate', params: { id, type } + }).then((_) => { + if (type === 'copy') { + tagsView.setTitle('复制流程') + } }) } } diff --git a/src/views/bpm/model/form/index.vue b/src/views/bpm/model/form/index.vue index 0d20e7ce2..37fa6bf03 100644 --- a/src/views/bpm/model/form/index.vue +++ b/src/views/bpm/model/form/index.vue @@ -160,6 +160,8 @@ const initData = async () => { // 复制场景 if (route.params.type === 'copy') { delete formData.value.id + formData.value.name += '副本' + formData.value.key += '_copy' } } else { // 新增场景 From 9febee7abe0f9a05714a6e54600a5b9a63111fd6 Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 09:29:11 +0800 Subject: [PATCH 42/62] =?UTF-8?q?perf:=20=E7=94=A8download.json=20?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E6=A8=A1=E5=9E=8Bjson=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/SimpleProcessModel.vue | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue index 23f2d7913..5d3071b4a 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue @@ -51,6 +51,7 @@ import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from './consts' import { useWatchNode } from './node' import { ZoomOut, ZoomIn, ScaleToOriginal } from '@element-plus/icons-vue' import { isString } from '@/utils/is' +import download from "@/utils/download"; defineOptions({ name: 'SimpleProcessModel' @@ -174,18 +175,7 @@ defineExpose({ /** 导出 JSON */ // TODO @zws:增加一个 download 里面搞个 json 更好 const exportJson = () => { - const blob = new Blob([JSON.stringify(processNodeTree.value)]) - const tempLink = document.createElement('a') // 创建a标签 - const href = window.URL.createObjectURL(blob) // 创建下载的链接 - // filename - const fileName = `model.json` - tempLink.href = href - tempLink.target = '_blank' - tempLink.download = fileName - document.body.appendChild(tempLink) - tempLink.click() // 点击下载 - document.body.removeChild(tempLink) // 下载完成移除元素 - window.URL.revokeObjectURL(href) // 释放掉 blob 对象 + download.json(new Blob([JSON.stringify(processNodeTree.value)]), 'model.json') } /** 导入 JSON */ From 84552a62533f8943f4a5ec8d86aaeacb3dc1edcb Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 09:29:34 +0800 Subject: [PATCH 43/62] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E6=A8=A1=E5=9E=8Bjson=20=E6=95=B0=E6=8D=AE=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E4=BF=9D=E5=AD=98=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SimpleProcessDesignerV2/src/SimpleProcessModel.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue index 5d3071b4a..ad0c7b195 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue @@ -190,6 +190,7 @@ const importLocalFile = () => { reader.onload = function () { if (isString(this.result)) { processNodeTree.value = JSON.parse(this.result) + emits('save', processNodeTree.value) } } } From 66d8cf1233504e4a865264a47a368e8f68354df7 Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 10:10:46 +0800 Subject: [PATCH 44/62] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3bpmn=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E5=99=A8=20=E5=88=9D=E6=AC=A1=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E6=B5=81=E7=A8=8Bkey=E4=B8=8D=E4=B8=80=E8=87=B4=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../package/penal/base/ElementBaseInfo.vue | 3 +++ src/views/bpm/model/editor/index.vue | 6 ++++++ src/views/bpm/model/form/index.vue | 1 + 3 files changed, 10 insertions(+) diff --git a/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue b/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue index 70ad4f8b6..3172338d9 100644 --- a/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue +++ b/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue @@ -152,6 +152,9 @@ watch( handleKeyUpdate(props.model.key) handleNameUpdate(props.model.name) } + }, + { + immediate: true } ) diff --git a/src/views/bpm/model/editor/index.vue b/src/views/bpm/model/editor/index.vue index b91c250e9..1076cf563 100644 --- a/src/views/bpm/model/editor/index.vue +++ b/src/views/bpm/model/editor/index.vue @@ -12,6 +12,8 @@ :additionalModel="controlForm.additionalModel" :model="model" @save="save" + :process-id="modelKey" + :process-name="modelName" /> () // 流程模型的信息 /** 初始化 modeler */ // TODO @zws:需要初始化,不然首次创建后,无法发布!相当于说,key、name 要去赋值下 const initModeler = async (item) => { + //先初始化模型数据 + model.value = modelData.value modeler.value = item } diff --git a/src/views/bpm/model/form/index.vue b/src/views/bpm/model/form/index.vue index 37fa6bf03..43e5c0a7c 100644 --- a/src/views/bpm/model/form/index.vue +++ b/src/views/bpm/model/form/index.vue @@ -145,6 +145,7 @@ const formData: any = ref({ const processData = ref() provide('processData', processData) +provide('modelData', formData) // 数据列表 const formList = ref([]) From d52e77913125820fd3f198be5edcc2b3d95ed5cf Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 10:18:20 +0800 Subject: [PATCH 45/62] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E6=A8=A1=E5=9E=8Bxml=20=E6=95=B0=E6=8D=AE=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E4=BF=9D=E5=AD=98=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpmnProcessDesigner/package/designer/ProcessDesigner.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue b/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue index 5b3d14f43..83d40fbfc 100644 --- a/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue +++ b/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue @@ -547,6 +547,7 @@ const importLocalFile = () => { reader.onload = function () { let xmlStr = this.result createNewDiagram(xmlStr) + emit('save', xmlStr) } } /* ------------------------------------------------ refs methods ------------------------------------------------------ */ From 8e5271a6d6724e6ad336634fea25d8ed65ec6189 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 16 Jan 2025 13:01:06 +0800 Subject: [PATCH 46/62] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91Bpm=EF=BC=9A=E5=AE=A1=E6=89=B9=E7=AD=BE?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pnpm-lock.yaml | 103 ++++++----------- src/api/bpm/processInstance/index.ts | 4 +- .../src/nodes-config/RouterNodeConfig.vue | 11 +- .../src/nodes-config/UserTaskNodeConfig.vue | 1 + .../detail/ProcessInstanceOperationButton.vue | 104 ++++++++++-------- .../detail/ProcessInstanceTimeline.vue | 8 +- .../bpm/processInstance/detail/SignDialog.vue | 39 +++---- 7 files changed, 126 insertions(+), 144 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 50e9bf968..ec016eb17 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ dependencies: specifier: ^1.1.5 version: 1.1.5 bpmn-js-token-simulation: - specifier: ^0.10.0 - version: 0.10.0 + specifier: ^0.36.0 + version: 0.36.0 camunda-bpmn-moddle: specifier: ^7.0.1 version: 7.0.1 @@ -149,6 +149,9 @@ dependencies: vue-types: specifier: ^5.1.1 version: 5.1.3(vue@3.5.12) + vue3-signature: + specifier: ^0.2.4 + version: 0.2.4(vue@3.5.12) vuedraggable: specifier: ^4.1.0 version: 4.1.0(vue@3.5.12) @@ -4581,12 +4584,14 @@ packages: min-dom: 4.2.1 dev: true - /bpmn-js-token-simulation@0.10.0: - resolution: {integrity: sha512-QuZQ/KVXKt9Vl+XENyOBoTW2Aw+uKjuBlKdCJL6El7AyM7DkJ5bZkSYURshId1SkBDdYg2mJ1flSmsrhGuSfwg==, tarball: https://registry.npmmirror.com/bpmn-js-token-simulation/-/bpmn-js-token-simulation-0.10.0.tgz} + /bpmn-js-token-simulation@0.36.0: + resolution: {integrity: sha512-vz+RHlbZCev/6dzk6FhJRz8M0aZ1GL7Xrza0ecWqeg4tHbgPozgyOm3tXTz75XdtOwRVVBzmCjcciXQX7A55wQ==, tarball: https://registry.npmmirror.com/bpmn-js-token-simulation/-/bpmn-js-token-simulation-0.36.0.tgz} + engines: {node: '>= 16'} dependencies: - min-dash: 3.8.1 - min-dom: 0.2.0 - svg.js: 2.7.1 + inherits-browser: 0.1.0 + min-dash: 4.2.2 + min-dom: 4.2.1 + randomcolor: 0.6.2 dev: false /bpmn-js@17.11.1: @@ -4927,51 +4932,13 @@ packages: dot-prop: 5.3.0 dev: true - /component-classes@1.2.6: - resolution: {integrity: sha512-hPFGULxdwugu1QWW3SvVOCUHLzO34+a2J6Wqy0c5ASQkfi9/8nZcBB0ZohaEbXOQlCflMAEMmEWk7u7BVs4koA==, tarball: https://registry.npmmirror.com/component-classes/-/component-classes-1.2.6.tgz} - dependencies: - component-indexof: 0.0.3 - dev: false - - /component-closest@0.1.4: - resolution: {integrity: sha512-NF9hMj6JKGM5sb6wP/dg7GdJOttaIH9PcTsUNdWcrvu7Kw/5R5swQAFpgaYEHlARrNMyn4Wf7O1PlRej+pt76Q==, tarball: https://registry.npmmirror.com/component-closest/-/component-closest-0.1.4.tgz} - dependencies: - component-matches-selector: 0.1.7 - dev: false - - /component-delegate@0.2.4: - resolution: {integrity: sha512-OlpcB/6Fi+kXQPh/TfXnSvvmrU04ghz7vcJh/jgLF0Ni+I+E3WGlKJQbBGDa5X+kVUG8WxOgjP+8iWbz902fPg==, tarball: https://registry.npmmirror.com/component-delegate/-/component-delegate-0.2.4.tgz} - dependencies: - component-closest: 0.1.4 - component-event: 0.1.4 - dev: false - /component-emitter@1.3.1: resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==, tarball: https://registry.npmmirror.com/component-emitter/-/component-emitter-1.3.1.tgz} dev: true - /component-event@0.1.4: - resolution: {integrity: sha512-GMwOG8MnUHP1l8DZx1ztFO0SJTFnIzZnBDkXAj8RM2ntV2A6ALlDxgbMY1Fvxlg6WPQ+5IM/a6vg4PEYbjg/Rw==, tarball: https://registry.npmmirror.com/component-event/-/component-event-0.1.4.tgz} - dev: false - /component-event@0.2.1: resolution: {integrity: sha512-wGA++isMqiDq1jPYeyv2as/Bt/u+3iLW0rEa+8NQ82jAv3TgqMiCM+B2SaBdn2DfLilLjjq736YcezihRYhfxw==, tarball: https://registry.npmmirror.com/component-event/-/component-event-0.2.1.tgz} - /component-indexof@0.0.3: - resolution: {integrity: sha512-puDQKvx/64HZXb4hBwIcvQLaLgux8o1CbWl39s41hrIIZDl1lJiD5jc22gj3RBeGK0ovxALDYpIbyjqDUUl0rw==, tarball: https://registry.npmmirror.com/component-indexof/-/component-indexof-0.0.3.tgz} - dev: false - - /component-matches-selector@0.1.7: - resolution: {integrity: sha512-Yb2+pVBvrqkQVpPaDBF0DYXRreBveXJNrpJs9FnFu8PF6/5IIcz5oDZqiH9nB5hbD2/TmFVN5ZCxBzqu7yFFYQ==, tarball: https://registry.npmmirror.com/component-matches-selector/-/component-matches-selector-0.1.7.tgz} - dependencies: - component-query: 0.0.3 - global-object: 1.0.0 - dev: false - - /component-query@0.0.3: - resolution: {integrity: sha512-VgebQseT1hz1Ps7vVp2uaSg+N/gsI5ts3AZUSnN6GMA2M82JH7o+qYifWhmVE/e8w/H48SJuA3nA9uX8zRe95Q==, tarball: https://registry.npmmirror.com/component-query/-/component-query-0.0.3.tgz} - dev: false - /compute-scroll-into-view@1.0.20: resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==, tarball: https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz} dev: false @@ -5521,6 +5488,10 @@ packages: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, tarball: https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz} dev: true + /default-passive-events@2.0.0: + resolution: {integrity: sha512-eMtt76GpDVngZQ3ocgvRcNCklUMwID1PaNbCNxfpDXuiOXttSh0HzBbda1HU9SIUsDc02vb7g9+3I5tlqe/qMQ==, tarball: https://registry.npmmirror.com/default-passive-events/-/default-passive-events-2.0.0.tgz} + dev: false + /define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==, tarball: https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz} engines: {node: '>= 0.4'} @@ -6674,10 +6645,6 @@ packages: global-prefix: 3.0.0 dev: true - /global-object@1.0.0: - resolution: {integrity: sha512-mSPSkY6UsHv6hgW0V2dfWBWTS8TnPnLx3ECVNoWp6rBI2Bg66VYoqGoTFlH/l7XhAZ/l+StYlntXlt87BEeCcg==, tarball: https://registry.npmmirror.com/global-object/-/global-object-1.0.0.tgz} - dev: false - /global-prefix@3.0.0: resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==, tarball: https://registry.npmmirror.com/global-prefix/-/global-prefix-3.0.0.tgz} engines: {node: '>=6'} @@ -7899,10 +7866,6 @@ packages: engines: {node: '>=18'} dev: true - /min-dash@3.8.1: - resolution: {integrity: sha512-evumdlmIlg9mbRVPbC4F5FuRhNmcMS5pvuBUbqb1G9v09Ro0ImPEgz5n3khir83lFok1inKqVDjnKEg3GpDxQg==, tarball: https://registry.npmmirror.com/min-dash/-/min-dash-3.8.1.tgz} - dev: false - /min-dash@4.2.2: resolution: {integrity: sha512-qbhSYUxk6mBaF096B3JOQSumXbKWHenmT97cSpdNzgkWwGjhjhE/KZODCoDNhI2I4C9Cb6R/Q13S4BYkUSXoXQ==, tarball: https://registry.npmmirror.com/min-dash/-/min-dash-4.2.2.tgz} @@ -7912,18 +7875,6 @@ packages: dom-walk: 0.1.2 dev: false - /min-dom@0.2.0: - resolution: {integrity: sha512-VmxugbnAcVZGqvepjhOA4d4apmrpX8mMaRS+/jo0dI5Yorzrr4Ru9zc9KVALlY/+XakVCb8iQ+PYXljihQcsNw==, tarball: https://registry.npmmirror.com/min-dom/-/min-dom-0.2.0.tgz} - dependencies: - component-classes: 1.2.6 - component-closest: 0.1.4 - component-delegate: 0.2.4 - component-event: 0.1.4 - component-matches-selector: 0.1.7 - component-query: 0.0.3 - domify: 1.4.2 - dev: false - /min-dom@4.2.1: resolution: {integrity: sha512-TMoL8SEEIhUWYgkj7XMSgxmwSyGI+4fP2KFFGnN3FbHfbGHVdsLYSz8LoIsgPhz4dWRmLvxWWSMgzZMJW5sZuA==, tarball: https://registry.npmmirror.com/min-dom/-/min-dom-4.2.1.tgz} dependencies: @@ -8714,6 +8665,10 @@ packages: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, tarball: https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz} dev: true + /randomcolor@0.6.2: + resolution: {integrity: sha512-Mn6TbyYpFgwFuQ8KJKqf3bqqY9O1y37/0jgSK/61PUxV4QfIMv0+K2ioq8DfOjkBslcjwSzRfIDEXfzA9aCx7A==, tarball: https://registry.npmmirror.com/randomcolor/-/randomcolor-0.6.2.tgz} + dev: false + /rd@2.0.1: resolution: {integrity: sha512-/XdKU4UazUZTXFmI0dpABt8jSXPWcEyaGdk340KdHnsEOdkTctlX23aAK7ChQDn39YGNlAJr1M5uvaKt4QnpNw==, tarball: https://registry.npmmirror.com/rd/-/rd-2.0.1.tgz} dependencies: @@ -9128,6 +9083,10 @@ packages: engines: {node: '>=14'} dev: true + /signature_pad@3.0.0-beta.4: + resolution: {integrity: sha512-cOf2NhVuTiuNqe2X/ycEmizvCDXk0DoemhsEpnkcGnA4kS5iJYTCqZ9As7tFBbsch45Q1EdX61833+6sjJ8rrw==, tarball: https://registry.npmmirror.com/signature_pad/-/signature_pad-3.0.0-beta.4.tgz} + dev: false + /sirv@2.0.4: resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==, tarball: https://registry.npmmirror.com/sirv/-/sirv-2.0.4.tgz} engines: {node: '>= 10'} @@ -9561,10 +9520,6 @@ packages: resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==, tarball: https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz} dev: true - /svg.js@2.7.1: - resolution: {integrity: sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==, tarball: https://registry.npmmirror.com/svg.js/-/svg.js-2.7.1.tgz} - dev: false - /svgo@2.8.0: resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==, tarball: https://registry.npmmirror.com/svgo/-/svgo-2.8.0.tgz} engines: {node: '>=10.13.0'} @@ -10324,6 +10279,16 @@ packages: vue: 3.5.12(typescript@5.3.3) dev: false + /vue3-signature@0.2.4(vue@3.5.12): + resolution: {integrity: sha512-XFwwFVK9OG3F085pKIq2SlNVqx32WdFH+TXbGEWc5FfEKpx8oMmZuAwZZ50K/pH2FgmJSE8IRwU9DDhrLpd6iA==, tarball: https://registry.npmmirror.com/vue3-signature/-/vue3-signature-0.2.4.tgz} + peerDependencies: + vue: ^3.2.0 + dependencies: + default-passive-events: 2.0.0 + signature_pad: 3.0.0-beta.4 + vue: 3.5.12(typescript@5.3.3) + dev: false + /vue@3.5.12(typescript@5.3.3): resolution: {integrity: sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==, tarball: https://registry.npmmirror.com/vue/-/vue-3.5.12.tgz} peerDependencies: diff --git a/src/api/bpm/processInstance/index.ts b/src/api/bpm/processInstance/index.ts index 06dc3f883..a0f263de6 100644 --- a/src/api/bpm/processInstance/index.ts +++ b/src/api/bpm/processInstance/index.ts @@ -36,7 +36,7 @@ export type ApprovalTaskInfo = { assigneeUser: User status: number reason: string - sign: string + sign: string // TODO @lesan:字段改成 signPicUrl 签名照片。只有 sign 感觉是签名文本哈。 } // 审批节点信息 @@ -90,7 +90,7 @@ export const getProcessInstanceCopyPage = async (params: any) => { // 获取审批详情 export const getApprovalDetail = async (params: any) => { - return await request.get({ url: 'bpm/process-instance/get-approval-detail' , params }) + return await request.get({ url: 'bpm/process-instance/get-approval-detail', params }) } // 获取表单字段权限 diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/RouterNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/RouterNodeConfig.vue index 442cf337d..6748a7367 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/RouterNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/RouterNodeConfig.vue @@ -37,9 +37,9 @@ :value="node.value" /> - 删除 + + 删除 +
([]) const nodeOptions = ref() - const conditionRef = ref([]) -// 保存配置 + +/** 保存配置 */ const saveConfig = async () => { // 校验表单 let valid = true diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 00ed6cfea..64acc2c30 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -440,6 +440,7 @@
+
diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue b/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue index 7f0696cf7..a4ecee650 100644 --- a/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue +++ b/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue @@ -44,14 +44,26 @@ :rows="4" /> - + 点击签名 - + - + {{ getButtonDisplayName(OperationButtonType.APPROVE) }} 取消 @@ -92,7 +104,11 @@ /> - + {{ getButtonDisplayName(OperationButtonType.REJECT) }} 取消 @@ -478,7 +494,8 @@
- + + - + From 37964e740f8691a58f9a43f976fb9c047e034e28 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Thu, 16 Jan 2025 13:55:15 +0800 Subject: [PATCH 47/62] =?UTF-8?q?feat:=20=E5=AE=A1=E6=89=B9=E7=AD=BE?= =?UTF-8?q?=E5=90=8D=E4=BB=A3=E7=A0=81=E8=AF=84=E5=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/bpm/processInstance/index.ts | 2 +- src/utils/download.ts | 27 ++++++++++++++ .../detail/ProcessInstanceOperationButton.vue | 16 ++++----- .../detail/ProcessInstanceTimeline.vue | 6 ++-- .../bpm/processInstance/detail/SignDialog.vue | 35 ++----------------- 5 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/api/bpm/processInstance/index.ts b/src/api/bpm/processInstance/index.ts index a0f263de6..9a99a91e2 100644 --- a/src/api/bpm/processInstance/index.ts +++ b/src/api/bpm/processInstance/index.ts @@ -36,7 +36,7 @@ export type ApprovalTaskInfo = { assigneeUser: User status: number reason: string - sign: string // TODO @lesan:字段改成 signPicUrl 签名照片。只有 sign 感觉是签名文本哈。 + signPicUrl: string } // 审批节点信息 diff --git a/src/utils/download.ts b/src/utils/download.ts index 5bbfb9fe6..bd58845f2 100644 --- a/src/utils/download.ts +++ b/src/utils/download.ts @@ -65,6 +65,33 @@ const download = { a.download = 'image.png' a.click() } + }, + base64ToFile: (base64, fileName) => { + // 将base64按照 , 进行分割 将前缀 与后续内容分隔开 + const data = base64.split(',') + // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等) + const type = data[0].match(/:(.*?);/)[1] + // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp) + const suffix = type.split('/')[1] + // 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出 + const bstr = window.atob(data[1]) + // 获取解码结果字符串的长度 + let n = bstr.length + // 根据解码结果字符串的长度创建一个等长的整形数字数组 + // 但在创建时 所有元素初始值都为 0 + const u8arr = new Uint8Array(n) + // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元 + while (n--) { + // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元 + u8arr[n] = bstr.charCodeAt(n) + } + // 利用构造函数创建File文件对象 + // new File(bits, name, options) + const file = new File([u8arr], `${fileName}.${suffix}`, { + type: type + }) + // 将File文件对象返回给方法的调用者 + return file } } diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue b/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue index a4ecee650..402644e93 100644 --- a/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue +++ b/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue @@ -47,15 +47,15 @@ 点击签名 @@ -553,11 +553,11 @@ const signRef = ref() const approveSignFormRef = ref() const approveReasonForm = reactive({ reason: '', - sign: '' + signPicUrl: '' }) const approveReasonRule = reactive>({ reason: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }], - sign: [{ required: true, message: '签名不能为空', trigger: 'change' }] + signPicUrl: [{ required: true, message: '签名不能为空', trigger: 'change' }] }) // 拒绝表单 const rejectFormRef = ref() @@ -705,7 +705,7 @@ const handleAudit = async (pass: boolean, formRef: FormInstance | undefined) => } // 签名 if (runningTask.value.signEnable) { - data.sign = approveReasonForm.sign + data.signPicUrl = approveReasonForm.signPicUrl } // 多表单处理,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交 // TODO 芋艿 任务有多表单这里要如何处理,会和可编辑的字段冲突 @@ -1002,7 +1002,7 @@ const getUpdatedProcessInstanceVariables = () => { /** 处理签名完成 */ const handleSignFinish = (url: string) => { - approveReasonForm.sign = url + approveReasonForm.signPicUrl = url approveSignFormRef.value.validate('change') } diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue b/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue index 1fd31dcf8..fcd5ec899 100644 --- a/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue +++ b/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue @@ -124,14 +124,14 @@ 审批意见:{{ task.reason }}
签名:
diff --git a/src/views/bpm/processInstance/detail/SignDialog.vue b/src/views/bpm/processInstance/detail/SignDialog.vue index 211cfcdab..744a3556f 100644 --- a/src/views/bpm/processInstance/detail/SignDialog.vue +++ b/src/views/bpm/processInstance/detail/SignDialog.vue @@ -2,9 +2,8 @@
- import Vue3Signature from 'vue3-signature' import * as FileApi from '@/api/infra/file' +import download from '@/utils/download' const message = useMessage() // 消息弹窗 const signDialogVisible = ref(false) @@ -40,40 +40,11 @@ const emits = defineEmits(['success']) const submit = async () => { message.success('签名上传中请稍等。。。') const res = await FileApi.updateFile({ - file: base64ToFile(signature.value.save('image/png'), '签名') + file: download.base64ToFile(signature.value.save('image/png'), '签名') }) emits('success', res.data) signDialogVisible.value = false } - -// TODO @lesan:这个要不抽到 download.js 里,让这个组件更简洁干净? -const base64ToFile = (base64, fileName) => { - // 将base64按照 , 进行分割 将前缀 与后续内容分隔开 - let data = base64.split(',') - // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等) - let type = data[0].match(/:(.*?);/)[1] - // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp) - let suffix = type.split('/')[1] - // 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出 - const bstr = window.atob(data[1]) - // 获取解码结果字符串的长度 - let n = bstr.length - // 根据解码结果字符串的长度创建一个等长的整形数字数组 - // 但在创建时 所有元素初始值都为 0 - const u8arr = new Uint8Array(n) - // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元 - while (n--) { - // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元 - u8arr[n] = bstr.charCodeAt(n) - } - // 利用构造函数创建File文件对象 - // new File(bits, name, options) - const file = new File([u8arr], `${fileName}.${suffix}`, { - type: type - }) - // 将File文件对象返回给方法的调用者 - return file -} From 69ccd83af31c33a92def15100706fe336419d6c0 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Thu, 16 Jan 2025 14:40:14 +0800 Subject: [PATCH 48/62] =?UTF-8?q?feat:=20bpmn=E8=AE=BE=E8=AE=A1=E5=99=A8?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0UserTask=E7=AD=BE=E5=90=8D=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugins/descriptor/flowableDescriptor.json | 14 ++++++++++++++ .../package/penal/PropertiesPanel.vue | 2 +- .../components/UserTaskCustomConfig.vue | 17 ++++++++++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json index 7fe1fa795..e50d3ce31 100644 --- a/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json @@ -1438,6 +1438,20 @@ "isBody": true } ] + }, + { + "name": "SignEnable", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Boolean", + "isBody": true + } + ] } ], "emumerations": [] diff --git a/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue b/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue index e53ad9943..ff08dd33d 100644 --- a/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue +++ b/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue @@ -1,5 +1,5 @@