refactor: 重构 bpmnProcessDesigner 组件 ele => antd
This commit is contained in:
@@ -46,18 +46,18 @@
|
|||||||
"@vueuse/core": "catalog:",
|
"@vueuse/core": "catalog:",
|
||||||
"@vueuse/integrations": "catalog:",
|
"@vueuse/integrations": "catalog:",
|
||||||
"ant-design-vue": "catalog:",
|
"ant-design-vue": "catalog:",
|
||||||
"bpmn-js": "^17.11.1",
|
"bpmn-js": "catalog:",
|
||||||
"bpmn-js-properties-panel": "5.23.0",
|
"bpmn-js-properties-panel": "catalog:",
|
||||||
"bpmn-js-token-simulation": "^0.36.3",
|
"bpmn-js-token-simulation": "catalog:",
|
||||||
"camunda-bpmn-moddle": "^7.0.1",
|
"camunda-bpmn-moddle": "catalog:",
|
||||||
"cropperjs": "catalog:",
|
"cropperjs": "catalog:",
|
||||||
"dayjs": "catalog:",
|
"dayjs": "catalog:",
|
||||||
"diagram-js": "^12.8.1",
|
"diagram-js": "catalog:",
|
||||||
"fast-xml-parser": "^4.5.3",
|
"fast-xml-parser": "catalog:",
|
||||||
"highlight.js": "catalog:",
|
"highlight.js": "catalog:",
|
||||||
"min-dash": "^4.2.3",
|
"min-dash": "catalog:",
|
||||||
"pinia": "catalog:",
|
"pinia": "catalog:",
|
||||||
"steady-xml": "^0.1.0",
|
"steady-xml": "catalog:",
|
||||||
"tinymce": "catalog:",
|
"tinymce": "catalog:",
|
||||||
"vue": "catalog:",
|
"vue": "catalog:",
|
||||||
"vue-dompurify-html": "catalog:",
|
"vue-dompurify-html": "catalog:",
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { nextTick, onBeforeUnmount, onMounted, provide, ref, watch } from 'vue';
|
import { nextTick, onBeforeUnmount, onMounted, provide, ref, watch } from 'vue';
|
||||||
|
|
||||||
import { Icon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
|
|
||||||
import { Collapse, CollapsePanel } from 'ant-design-vue';
|
import { Collapse } from 'ant-design-vue';
|
||||||
|
|
||||||
|
import ElementCustomConfig from '#/components/bpmnProcessDesigner/package/penal/custom-config/ElementCustomConfig.vue';
|
||||||
|
import ElementForm from '#/components/bpmnProcessDesigner/package/penal/form/ElementForm.vue';
|
||||||
|
|
||||||
import ElementBaseInfo from './base/ElementBaseInfo.vue';
|
import ElementBaseInfo from './base/ElementBaseInfo.vue';
|
||||||
import FlowCondition from './flow-condition/FlowCondition.vue';
|
import FlowCondition from './flow-condition/FlowCondition.vue';
|
||||||
@@ -29,7 +32,7 @@ defineOptions({ name: 'MyPropertiesPanel' });
|
|||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
bpmnModeler: {
|
bpmnModeler: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {},
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
prefix: {
|
prefix: {
|
||||||
type: String,
|
type: String,
|
||||||
@@ -43,12 +46,21 @@ const props = defineProps({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
model: Object, // 流程模型的数据
|
businessObject: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
},
|
||||||
|
model: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({}),
|
||||||
|
}, // 流程模型的数据
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const CollapsePanel = Collapse.Panel;
|
||||||
|
|
||||||
const activeTab = ref('base');
|
const activeTab = ref('base');
|
||||||
const elementId = ref('');
|
const elementId = ref('');
|
||||||
const elementType = ref('');
|
const elementType = ref<any>('');
|
||||||
const elementBusinessObject = ref<any>({}); // 元素 businessObject 镜像,提供给需要做判断的组件使用
|
const elementBusinessObject = ref<any>({}); // 元素 businessObject 镜像,提供给需要做判断的组件使用
|
||||||
const conditionFormVisible = ref(false); // 流转条件设置
|
const conditionFormVisible = ref(false); // 流转条件设置
|
||||||
const formVisible = ref(false); // 表单配置
|
const formVisible = ref(false); // 表单配置
|
||||||
@@ -77,9 +89,7 @@ const initBpmnInstances = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 检查所有实例是否都存在
|
// 检查所有实例是否都存在
|
||||||
const allInstancesExist = Object.values(instances).every(
|
const allInstancesExist = Object.values(instances).every(Boolean);
|
||||||
Boolean,
|
|
||||||
);
|
|
||||||
if (allInstancesExist) {
|
if (allInstancesExist) {
|
||||||
const w = window as any;
|
const w = window as any;
|
||||||
w.bpmnInstances = instances;
|
w.bpmnInstances = instances;
|
||||||
@@ -95,12 +105,12 @@ const initBpmnInstances = () => {
|
|||||||
const bpmnInstances = () => (window as any)?.bpmnInstances;
|
const bpmnInstances = () => (window as any)?.bpmnInstances;
|
||||||
|
|
||||||
// 监听 props.bpmnModeler 然后 initModels
|
// 监听 props.bpmnModeler 然后 initModels
|
||||||
const unwatchBpmn = watch(
|
watch(
|
||||||
() => props.bpmnModeler,
|
() => props.bpmnModeler,
|
||||||
async () => {
|
async () => {
|
||||||
// 避免加载时 流程图 并未加载完成
|
// 避免加载时 流程图 并未加载完成
|
||||||
if (!props.bpmnModeler) {
|
if (!props.bpmnModeler) {
|
||||||
console.log('缺少props.bpmnModeler');
|
// console.log('缺少props.bpmnModeler');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -128,15 +138,18 @@ const getActiveElement = () => {
|
|||||||
|
|
||||||
// 初始第一个选中元素 bpmn:Process
|
// 初始第一个选中元素 bpmn:Process
|
||||||
initFormOnChanged(null);
|
initFormOnChanged(null);
|
||||||
props.bpmnModeler.on('import.done', (e) => {
|
props.bpmnModeler.on('import.done', (_: any) => {
|
||||||
console.log(e, 'eeeee');
|
// console.log(e, 'eeeee');
|
||||||
initFormOnChanged(null);
|
initFormOnChanged(null);
|
||||||
});
|
});
|
||||||
// 监听选择事件,修改当前激活的元素以及表单
|
// 监听选择事件,修改当前激活的元素以及表单
|
||||||
props.bpmnModeler.on('selection.changed', ({ newSelection }) => {
|
props.bpmnModeler.on(
|
||||||
|
'selection.changed',
|
||||||
|
({ newSelection }: { newSelection: any }) => {
|
||||||
initFormOnChanged(newSelection[0] || null);
|
initFormOnChanged(newSelection[0] || null);
|
||||||
});
|
},
|
||||||
props.bpmnModeler.on('element.changed', ({ element }) => {
|
);
|
||||||
|
props.bpmnModeler.on('element.changed', ({ element }: { element: any }) => {
|
||||||
// 保证 修改 "默认流转路径" 类似需要修改多个元素的事件发生的时候,更新表单的元素与原选中元素不一致。
|
// 保证 修改 "默认流转路径" 类似需要修改多个元素的事件发生的时候,更新表单的元素与原选中元素不一致。
|
||||||
if (element && element.id === elementId.value) {
|
if (element && element.id === elementId.value) {
|
||||||
initFormOnChanged(element);
|
initFormOnChanged(element);
|
||||||
@@ -145,42 +158,41 @@ const getActiveElement = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
const initFormOnChanged = (element) => {
|
const initFormOnChanged = (element: any) => {
|
||||||
if (!isReady.value || !bpmnInstances()) return;
|
if (!isReady.value || !bpmnInstances()) return;
|
||||||
|
|
||||||
let activatedElement = element;
|
let activatedElement = element;
|
||||||
if (!activatedElement) {
|
if (!activatedElement) {
|
||||||
activatedElement =
|
activatedElement =
|
||||||
bpmnInstances().elementRegistry.find(
|
bpmnInstances().elementRegistry.find(
|
||||||
(el) => el.type === 'bpmn:Process',
|
(el: any) => el.type === 'bpmn:Process',
|
||||||
) ??
|
) ??
|
||||||
bpmnInstances().elementRegistry.find(
|
bpmnInstances().elementRegistry.find(
|
||||||
(el) => el.type === 'bpmn:Collaboration',
|
(el: any) => el.type === 'bpmn:Collaboration',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!activatedElement) return;
|
if (!activatedElement) return;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
console.log(`
|
// console.log(`
|
||||||
----------
|
// ----------
|
||||||
select element changed:
|
// select element changed:
|
||||||
id: ${activatedElement.id}
|
// id: ${activatedElement.id}
|
||||||
type: ${activatedElement.businessObject.$type}
|
// type: ${activatedElement.businessObject.$type}
|
||||||
----------
|
// ----------
|
||||||
`);
|
// `);
|
||||||
console.log('businessObject:', activatedElement.businessObject);
|
// console.log('businessObject:', activatedElement.businessObject);
|
||||||
bpmnInstances().bpmnElement = activatedElement;
|
bpmnInstances().bpmnElement = activatedElement;
|
||||||
bpmnElement.value = activatedElement;
|
bpmnElement.value = activatedElement;
|
||||||
elementId.value = activatedElement.id;
|
elementId.value = activatedElement.id;
|
||||||
elementType.value = activatedElement.type.split(':')[1] || '';
|
elementType.value = activatedElement.type.split(':')[1] || '';
|
||||||
elementBusinessObject.value = JSON.parse(
|
elementBusinessObject.value = structuredClone(
|
||||||
JSON.stringify(activatedElement.businessObject),
|
activatedElement.businessObject,
|
||||||
);
|
);
|
||||||
conditionFormVisible.value = !!(
|
conditionFormVisible.value =
|
||||||
elementType.value === 'SequenceFlow' &&
|
elementType.value === 'SequenceFlow' &&
|
||||||
activatedElement.source &&
|
activatedElement.source &&
|
||||||
!activatedElement.source.type.indexOf('StartEvent') === -1
|
(activatedElement.source.type as string).includes('StartEvent');
|
||||||
);
|
|
||||||
formVisible.value =
|
formVisible.value =
|
||||||
elementType.value === 'UserTask' || elementType.value === 'StartEvent';
|
elementType.value === 'UserTask' || elementType.value === 'StartEvent';
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -200,46 +212,46 @@ watch(
|
|||||||
activeTab.value = 'base';
|
activeTab.value = 'base';
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
//
|
||||||
function updateNode() {
|
// function updateNode() {
|
||||||
const moddle = window.bpmnInstances?.moddle;
|
// const moddle = window.bpmnInstances?.moddle;
|
||||||
const modeling = window.bpmnInstances?.modeling;
|
// const modeling = window.bpmnInstances?.modeling;
|
||||||
const elementRegistry = window.bpmnInstances?.elementRegistry;
|
// const elementRegistry = window.bpmnInstances?.elementRegistry;
|
||||||
if (!moddle || !modeling || !elementRegistry) return;
|
// if (!moddle || !modeling || !elementRegistry) return;
|
||||||
|
//
|
||||||
const element = elementRegistry.get(props.businessObject.id);
|
// const element = elementRegistry.get(props.businessObject.id);
|
||||||
if (!element) return;
|
// if (!element) return;
|
||||||
|
//
|
||||||
const timerDef = moddle.create('bpmn:TimerEventDefinition', {});
|
// const timerDef = moddle.create('bpmn:TimerEventDefinition', {});
|
||||||
switch (type.value) {
|
// switch (type.value) {
|
||||||
case 'cycle': {
|
// case 'cycle': {
|
||||||
timerDef.timeCycle = moddle.create('bpmn:FormalExpression', {
|
// timerDef.timeCycle = moddle.create('bpmn:FormalExpression', {
|
||||||
body: condition.value,
|
// body: condition.value,
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case 'duration': {
|
// case 'duration': {
|
||||||
timerDef.timeDuration = moddle.create('bpmn:FormalExpression', {
|
// timerDef.timeDuration = moddle.create('bpmn:FormalExpression', {
|
||||||
body: condition.value,
|
// body: condition.value,
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
case 'time': {
|
// case 'time': {
|
||||||
timerDef.timeDate = moddle.create('bpmn:FormalExpression', {
|
// timerDef.timeDate = moddle.create('bpmn:FormalExpression', {
|
||||||
body: condition.value,
|
// body: condition.value,
|
||||||
});
|
// });
|
||||||
|
//
|
||||||
break;
|
// break;
|
||||||
}
|
// }
|
||||||
// No default
|
// // No default
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
modeling.updateModdleProperties(element, element.businessObject, {
|
// modeling.updateModdleProperties(element, element.businessObject, {
|
||||||
eventDefinitions: [timerDef],
|
// eventDefinitions: [timerDef],
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
// 初始化和监听
|
// 初始化和监听
|
||||||
function syncFromBusinessObject() {
|
function syncFromBusinessObject() {
|
||||||
@@ -269,9 +281,8 @@ watch(() => props.businessObject, syncFromBusinessObject, { deep: true });
|
|||||||
>
|
>
|
||||||
<Collapse v-model:active-key="activeTab" v-if="isReady">
|
<Collapse v-model:active-key="activeTab" v-if="isReady">
|
||||||
<CollapsePanel key="base" header="常规">
|
<CollapsePanel key="base" header="常规">
|
||||||
<template #title>
|
<template #extra>
|
||||||
<Icon icon="ant-design:info-circle-filled" />
|
<IconifyIcon icon="ep:info-filled" />
|
||||||
常规
|
|
||||||
</template>
|
</template>
|
||||||
<ElementBaseInfo
|
<ElementBaseInfo
|
||||||
:id-edit-disabled="idEditDisabled"
|
:id-edit-disabled="idEditDisabled"
|
||||||
@@ -282,51 +293,50 @@ watch(() => props.businessObject, syncFromBusinessObject, { deep: true });
|
|||||||
</CollapsePanel>
|
</CollapsePanel>
|
||||||
<CollapsePanel
|
<CollapsePanel
|
||||||
key="message"
|
key="message"
|
||||||
|
header="消息与信号"
|
||||||
v-if="elementType === 'Process'"
|
v-if="elementType === 'Process'"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #extra>
|
||||||
<Icon icon="ant-design:message-filled" />
|
<IconifyIcon icon="ep:comment" />
|
||||||
消息与信号
|
|
||||||
</template>
|
</template>
|
||||||
<SignalAndMassage />
|
<SignalAndMassage />
|
||||||
</CollapsePanel>
|
</CollapsePanel>
|
||||||
<CollapsePanel
|
<CollapsePanel
|
||||||
key="condition"
|
key="condition"
|
||||||
|
header="流转条件"
|
||||||
v-if="conditionFormVisible"
|
v-if="conditionFormVisible"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #extra>
|
||||||
<Icon icon="ant-design:swap-right" />
|
<IconifyIcon icon="ep:promotion" />
|
||||||
流转条件
|
|
||||||
</template>
|
</template>
|
||||||
<FlowCondition
|
<FlowCondition
|
||||||
:business-object="elementBusinessObject"
|
:business-object="elementBusinessObject"
|
||||||
:type="elementType"
|
:type="elementType"
|
||||||
/>
|
/>
|
||||||
</CollapsePanel>
|
</CollapsePanel>
|
||||||
<CollapsePanel key="form" v-if="formVisible">
|
<CollapsePanel key="form" header="表单" v-if="formVisible">
|
||||||
<template #title>
|
<template #extra>
|
||||||
<Icon icon="ant-design:unordered-list-outlined" />
|
<IconifyIcon icon="ep:list" />
|
||||||
表单
|
|
||||||
</template>
|
</template>
|
||||||
<element-form :id="elementId" :type="elementType" />
|
<ElementForm :id="elementId" :type="elementType" />
|
||||||
</CollapsePanel>
|
</CollapsePanel>
|
||||||
<CollapsePanel
|
<CollapsePanel
|
||||||
key="task"
|
key="task"
|
||||||
|
:header="getTaskCollapseItemName(elementType)"
|
||||||
v-if="isTaskCollapseItemShow(elementType)"
|
v-if="isTaskCollapseItemShow(elementType)"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #extra>
|
||||||
<Icon icon="ant-design:check-circle-filled" />
|
<IconifyIcon icon="ep:checked" />
|
||||||
{{ getTaskCollapseItemName(elementType) }}
|
|
||||||
</template>
|
</template>
|
||||||
<ElementTask :id="elementId" :type="elementType" />
|
<ElementTask :id="elementId" :type="elementType" />
|
||||||
</CollapsePanel>
|
</CollapsePanel>
|
||||||
<CollapsePanel
|
<CollapsePanel
|
||||||
key="multiInstance"
|
key="multiInstance"
|
||||||
|
header="多人审批方式"
|
||||||
v-if="elementType.includes('Task')"
|
v-if="elementType.includes('Task')"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #extra>
|
||||||
<Icon icon="ant-design:question-circle-filled" />
|
<IconifyIcon icon="ep:help-filled" />
|
||||||
多人审批方式
|
|
||||||
</template>
|
</template>
|
||||||
<ElementMultiInstance
|
<ElementMultiInstance
|
||||||
:id="elementId"
|
:id="elementId"
|
||||||
@@ -334,43 +344,39 @@ watch(() => props.businessObject, syncFromBusinessObject, { deep: true });
|
|||||||
:type="elementType"
|
:type="elementType"
|
||||||
/>
|
/>
|
||||||
</CollapsePanel>
|
</CollapsePanel>
|
||||||
<CollapsePanel key="listeners">
|
<CollapsePanel key="listeners" header="执行监听器">
|
||||||
<template #title>
|
<template #extra>
|
||||||
<Icon icon="ant-design:bell-filled" />
|
<IconifyIcon icon="ep:bell-filled" />
|
||||||
执行监听器
|
|
||||||
</template>
|
</template>
|
||||||
<ElementListeners :id="elementId" :type="elementType" />
|
<ElementListeners :id="elementId" :type="elementType" />
|
||||||
</CollapsePanel>
|
</CollapsePanel>
|
||||||
<CollapsePanel
|
<CollapsePanel
|
||||||
key="taskListeners"
|
key="taskListeners"
|
||||||
|
header="任务监听器"
|
||||||
v-if="elementType === 'UserTask'"
|
v-if="elementType === 'UserTask'"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #extra>
|
||||||
<Icon icon="ant-design:bell-filled" />
|
<IconifyIcon icon="ep:bell-filled" />
|
||||||
任务监听器
|
|
||||||
</template>
|
</template>
|
||||||
<UserTaskListeners :id="elementId" :type="elementType" />
|
<UserTaskListeners :id="elementId" :type="elementType" />
|
||||||
</CollapsePanel>
|
</CollapsePanel>
|
||||||
<CollapsePanel key="extensions">
|
<CollapsePanel key="extensions" header="扩展属性">
|
||||||
<template #title>
|
<template #extra>
|
||||||
<Icon icon="ant-design:plus-circle-filled" />
|
<IconifyIcon icon="ep:circle-plus-filled" />
|
||||||
扩展属性
|
|
||||||
</template>
|
</template>
|
||||||
<ElementProperties :id="elementId" :type="elementType" />
|
<ElementProperties :id="elementId" :type="elementType" />
|
||||||
</CollapsePanel>
|
</CollapsePanel>
|
||||||
<CollapsePanel key="other">
|
<CollapsePanel key="other" header="其他">
|
||||||
<template #title>
|
<template #extra>
|
||||||
<Icon icon="ant-design:swap-right" />
|
<IconifyIcon icon="ep:promotion" />
|
||||||
其他
|
|
||||||
</template>
|
</template>
|
||||||
<ElementOtherConfig :id="elementId" />
|
<ElementOtherConfig :id="elementId" />
|
||||||
</CollapsePanel>
|
</CollapsePanel>
|
||||||
<CollapsePanel key="customConfig">
|
<CollapsePanel key="customConfig" header="自定义配置">
|
||||||
<template #title>
|
<template #extra>
|
||||||
<Icon icon="ant-design:tool-filled" />
|
<IconifyIcon icon="ep:tools" />
|
||||||
自定义配置
|
|
||||||
</template>
|
</template>
|
||||||
<element-custom-config
|
<ElementCustomConfig
|
||||||
:id="elementId"
|
:id="elementId"
|
||||||
:type="elementType"
|
:type="elementType"
|
||||||
:business-object="elementBusinessObject"
|
:business-object="elementBusinessObject"
|
||||||
@@ -379,212 +385,11 @@ watch(() => props.businessObject, syncFromBusinessObject, { deep: true });
|
|||||||
<!-- 新增的时间事件配置项 -->
|
<!-- 新增的时间事件配置项 -->
|
||||||
<CollapsePanel
|
<CollapsePanel
|
||||||
key="timeEvent"
|
key="timeEvent"
|
||||||
|
header="时间事件"
|
||||||
v-if="elementType === 'IntermediateCatchEvent'"
|
v-if="elementType === 'IntermediateCatchEvent'"
|
||||||
>
|
>
|
||||||
<template #title>
|
<template #extra>
|
||||||
<Icon icon="ant-design:clock-circle-filled" />
|
<IconifyIcon icon="ep:timer" />
|
||||||
时间事件
|
|
||||||
</template>
|
|
||||||
<TimeEventConfig
|
|
||||||
:business-object="bpmnElement.value?.businessObject"
|
|
||||||
:key="elementId"
|
|
||||||
/>
|
|
||||||
</CollapsePanel>
|
|
||||||
</Collapse>
|
|
||||||
</div>
|
|
||||||
</template>.includes('StartEvent')
|
|
||||||
);
|
|
||||||
formVisible.value =
|
|
||||||
elementType.value === 'UserTask' || elementType.value === 'StartEvent';
|
|
||||||
} catch (error) {
|
|
||||||
console.error('初始化表单数据失败:', error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
onBeforeUnmount(() => {
|
|
||||||
const w = window as any;
|
|
||||||
w.bpmnInstances = null;
|
|
||||||
isReady.value = false;
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(
|
|
||||||
() => elementId.value,
|
|
||||||
() => {
|
|
||||||
activeTab.value = 'base';
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
function updateNode() {
|
|
||||||
const moddle = window.bpmnInstances?.moddle;
|
|
||||||
const modeling = window.bpmnInstances?.modeling;
|
|
||||||
const elementRegistry = window.bpmnInstances?.elementRegistry;
|
|
||||||
if (!moddle || !modeling || !elementRegistry) return;
|
|
||||||
|
|
||||||
const element = elementRegistry.get(props.businessObject.id);
|
|
||||||
if (!element) return;
|
|
||||||
|
|
||||||
const timerDef = moddle.create('bpmn:TimerEventDefinition', {});
|
|
||||||
switch (type.value) {
|
|
||||||
case 'time': {
|
|
||||||
timerDef.timeDate = moddle.create('bpmn:FormalExpression', {
|
|
||||||
body: condition.value,
|
|
||||||
});
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'duration': {
|
|
||||||
timerDef.timeDuration = moddle.create('bpmn:FormalExpression', {
|
|
||||||
body: condition.value,
|
|
||||||
});
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'cycle': {
|
|
||||||
timerDef.timeCycle = moddle.create('bpmn:FormalExpression', {
|
|
||||||
body: condition.value,
|
|
||||||
});
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// No default
|
|
||||||
}
|
|
||||||
|
|
||||||
modeling.updateModdleProperties(element, element.businessObject, {
|
|
||||||
eventDefinitions: [timerDef],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化和监听
|
|
||||||
function syncFromBusinessObject() {
|
|
||||||
if (props.businessObject) {
|
|
||||||
const timerDef = (props.businessObject.eventDefinitions || [])[0];
|
|
||||||
if (timerDef) {
|
|
||||||
if (timerDef.timeDate) {
|
|
||||||
type.value = 'time';
|
|
||||||
condition.value = timerDef.timeDate.body;
|
|
||||||
} else if (timerDef.timeDuration) {
|
|
||||||
type.value = 'duration';
|
|
||||||
condition.value = timerDef.timeDuration.body;
|
|
||||||
} else if (timerDef.timeCycle) {
|
|
||||||
type.value = 'cycle';
|
|
||||||
condition.value = timerDef.timeCycle.body;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
onMounted(syncFromBusinessObject);
|
|
||||||
watch(() => props.businessObject, syncFromBusinessObject, { deep: true });
|
|
||||||
</script>
|
|
||||||
<template>
|
|
||||||
<div
|
|
||||||
class="process-panel__container"
|
|
||||||
:style="{ width: `${width}px`, maxHeight: '600px' }"
|
|
||||||
>
|
|
||||||
<Collapse v-model:active-key="activeTab" v-if="isReady">
|
|
||||||
<CollapsePanel key="base" header="常规">
|
|
||||||
<template #title>
|
|
||||||
<Icon icon="ant-design:info-circle-filled" />
|
|
||||||
常规
|
|
||||||
</template>
|
|
||||||
<ElementBaseInfo
|
|
||||||
:id-edit-disabled="idEditDisabled"
|
|
||||||
:business-object="elementBusinessObject"
|
|
||||||
:type="elementType"
|
|
||||||
:model="model"
|
|
||||||
/>
|
|
||||||
</CollapsePanel>
|
|
||||||
<CollapsePanel key="message" v-if="elementType === 'Process'">
|
|
||||||
<template #title>
|
|
||||||
<Icon icon="ant-design:message-filled" />
|
|
||||||
消息与信号
|
|
||||||
</template>
|
|
||||||
<SignalAndMassage />
|
|
||||||
</CollapsePanel>
|
|
||||||
<CollapsePanel key="condition" v-if="conditionFormVisible">
|
|
||||||
<template #title>
|
|
||||||
<Icon icon="ant-design:swap-right" />
|
|
||||||
流转条件
|
|
||||||
</template>
|
|
||||||
<FlowCondition
|
|
||||||
:business-object="elementBusinessObject"
|
|
||||||
:type="elementType"
|
|
||||||
/>
|
|
||||||
</CollapsePanel>
|
|
||||||
<CollapsePanel key="form" v-if="formVisible">
|
|
||||||
<template #title>
|
|
||||||
<Icon icon="ant-design:unordered-list-outlined" />
|
|
||||||
表单
|
|
||||||
</template>
|
|
||||||
<element-form :id="elementId" :type="elementType" />
|
|
||||||
</CollapsePanel>
|
|
||||||
<CollapsePanel key="task" v-if="isTaskCollapseItemShow(elementType)">
|
|
||||||
<template #title>
|
|
||||||
<Icon icon="ant-design:check-circle-filled" />
|
|
||||||
{{ getTaskCollapseItemName(elementType) }}
|
|
||||||
</template>
|
|
||||||
<ElementTask :id="elementId" :type="elementType" />
|
|
||||||
</CollapsePanel>
|
|
||||||
<CollapsePanel
|
|
||||||
key="multiInstance"
|
|
||||||
v-if="elementType.includes('Task')"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<Icon icon="ant-design:question-circle-filled" />
|
|
||||||
多人审批方式
|
|
||||||
</template>
|
|
||||||
<ElementMultiInstance
|
|
||||||
:id="elementId"
|
|
||||||
:business-object="elementBusinessObject"
|
|
||||||
:type="elementType"
|
|
||||||
/>
|
|
||||||
</CollapsePanel>
|
|
||||||
<CollapsePanel key="listeners">
|
|
||||||
<template #title>
|
|
||||||
<Icon icon="ant-design:bell-filled" />
|
|
||||||
执行监听器
|
|
||||||
</template>
|
|
||||||
<ElementListeners :id="elementId" :type="elementType" />
|
|
||||||
</CollapsePanel>
|
|
||||||
<CollapsePanel key="taskListeners" v-if="elementType === 'UserTask'">
|
|
||||||
<template #title>
|
|
||||||
<Icon icon="ant-design:bell-filled" />
|
|
||||||
任务监听器
|
|
||||||
</template>
|
|
||||||
<UserTaskListeners :id="elementId" :type="elementType" />
|
|
||||||
</CollapsePanel>
|
|
||||||
<CollapsePanel key="extensions">
|
|
||||||
<template #title>
|
|
||||||
<Icon icon="ant-design:plus-circle-filled" />
|
|
||||||
扩展属性
|
|
||||||
</template>
|
|
||||||
<ElementProperties :id="elementId" :type="elementType" />
|
|
||||||
</CollapsePanel>
|
|
||||||
<CollapsePanel key="other">
|
|
||||||
<template #title>
|
|
||||||
<Icon icon="ant-design:swap-right" />
|
|
||||||
其他
|
|
||||||
</template>
|
|
||||||
<ElementOtherConfig :id="elementId" />
|
|
||||||
</CollapsePanel>
|
|
||||||
<CollapsePanel key="customConfig">
|
|
||||||
<template #title>
|
|
||||||
<Icon icon="ant-design:tool-filled" />
|
|
||||||
自定义配置
|
|
||||||
</template>
|
|
||||||
<element-custom-config
|
|
||||||
:id="elementId"
|
|
||||||
:type="elementType"
|
|
||||||
:business-object="elementBusinessObject"
|
|
||||||
/>
|
|
||||||
</CollapsePanel>
|
|
||||||
<!-- 新增的时间事件配置项 -->
|
|
||||||
<CollapsePanel
|
|
||||||
key="timeEvent"
|
|
||||||
v-if="elementType === 'IntermediateCatchEvent'"
|
|
||||||
>
|
|
||||||
<template #title>
|
|
||||||
<Icon icon="ant-design:clock-circle-filled" />
|
|
||||||
时间事件
|
|
||||||
</template>
|
</template>
|
||||||
<TimeEventConfig
|
<TimeEventConfig
|
||||||
:business-object="bpmnElement.value?.businessObject"
|
:business-object="bpmnElement.value?.businessObject"
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
import { Form } from 'ant-design-vue';
|
import { Checkbox, Form, FormItem } from 'ant-design-vue';
|
||||||
|
|
||||||
import { installedComponent } from './data';
|
import { installedComponent } from './data';
|
||||||
|
|
||||||
defineOptions({ name: 'ElementTaskConfig' });
|
defineOptions({ name: 'ElementTaskConfig' });
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
id: String,
|
id: {
|
||||||
type: String,
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
type: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
});
|
});
|
||||||
const taskConfigForm = ref({
|
const taskConfigForm = ref({
|
||||||
asyncAfter: false,
|
asyncAfter: false,
|
||||||
@@ -47,6 +53,7 @@ watch(
|
|||||||
() => props.type,
|
() => props.type,
|
||||||
() => {
|
() => {
|
||||||
if (props.type) {
|
if (props.type) {
|
||||||
|
// @ts-ignore
|
||||||
witchTaskComponent.value = installedComponent[props.type].component;
|
witchTaskComponent.value = installedComponent[props.type].component;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -58,7 +65,7 @@ watch(
|
|||||||
<div class="panel-tab__content">
|
<div class="panel-tab__content">
|
||||||
<Form :label-col="{ span: 9 }" :wrapper-col="{ span: 15 }">
|
<Form :label-col="{ span: 9 }" :wrapper-col="{ span: 15 }">
|
||||||
<!-- add by 芋艿:由于「异步延续」暂时用不到,所以这里 display 为 none -->
|
<!-- add by 芋艿:由于「异步延续」暂时用不到,所以这里 display 为 none -->
|
||||||
<Form.Item label="异步延续" style="display: none">
|
<FormItem label="异步延续" style="display: none">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
v-model:checked="taskConfigForm.asyncBefore"
|
v-model:checked="taskConfigForm.asyncBefore"
|
||||||
@change="changeTaskAsync"
|
@change="changeTaskAsync"
|
||||||
@@ -78,7 +85,7 @@ watch(
|
|||||||
>
|
>
|
||||||
排除
|
排除
|
||||||
</Checkbox>
|
</Checkbox>
|
||||||
</Form.Item>
|
</FormItem>
|
||||||
<component :is="witchTaskComponent" v-bind="$props" />
|
<component :is="witchTaskComponent" v-bind="$props" />
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,76 +12,79 @@ packages:
|
|||||||
- scripts/*
|
- scripts/*
|
||||||
- docs
|
- docs
|
||||||
- playground
|
- playground
|
||||||
|
|
||||||
catalog:
|
catalog:
|
||||||
'@ast-grep/napi': ^0.37.0
|
"@ast-grep/napi": ^0.37.0
|
||||||
'@changesets/changelog-github': ^0.5.1
|
"@changesets/changelog-github": ^0.5.1
|
||||||
'@changesets/cli': ^2.29.5
|
"@changesets/cli": ^2.29.5
|
||||||
'@changesets/git': ^3.0.4
|
"@changesets/git": ^3.0.4
|
||||||
'@clack/prompts': ^0.10.1
|
"@clack/prompts": ^0.10.1
|
||||||
'@commitlint/cli': ^19.8.1
|
"@commitlint/cli": ^19.8.1
|
||||||
'@commitlint/config-conventional': ^19.8.1
|
"@commitlint/config-conventional": ^19.8.1
|
||||||
'@ctrl/tinycolor': ^4.1.0
|
"@ctrl/tinycolor": ^4.1.0
|
||||||
'@eslint/js': ^9.30.1
|
"@eslint/js": ^9.30.1
|
||||||
'@faker-js/faker': ^9.9.0
|
"@faker-js/faker": ^9.9.0
|
||||||
'@iconify/json': ^2.2.354
|
"@form-create/ant-design-vue": ^3.2.27
|
||||||
'@iconify/tailwind': ^1.2.0
|
"@form-create/antd-designer": ^3.3.0
|
||||||
'@iconify/vue': ^5.0.0
|
"@form-create/designer": ^3.3.0
|
||||||
'@intlify/core-base': ^11.1.7
|
"@form-create/element-ui": ^3.2.27
|
||||||
'@intlify/unplugin-vue-i18n': ^6.0.8
|
"@form-create/naive-ui": ^3.2.27
|
||||||
'@jspm/generator': ^2.6.2
|
"@iconify/json": ^2.2.354
|
||||||
'@manypkg/get-packages': ^3.0.0
|
"@iconify/tailwind": ^1.2.0
|
||||||
'@microsoft/fetch-event-source': ^2.0.1
|
"@iconify/vue": ^5.0.0
|
||||||
'@nolebase/vitepress-plugin-git-changelog': ^2.18.0
|
"@intlify/core-base": ^11.1.7
|
||||||
'@playwright/test': ^1.53.2
|
"@intlify/unplugin-vue-i18n": ^6.0.8
|
||||||
'@pnpm/workspace.read-manifest': ^1000.2.0
|
"@jspm/generator": ^2.6.2
|
||||||
'@stylistic/stylelint-plugin': ^3.1.3
|
"@manypkg/get-packages": ^3.0.0
|
||||||
'@tailwindcss/nesting': 0.0.0-insiders.565cd3e
|
"@microsoft/fetch-event-source": ^2.0.1
|
||||||
'@tailwindcss/typography': ^0.5.16
|
"@nolebase/vitepress-plugin-git-changelog": ^2.18.0
|
||||||
'@tanstack/vue-query': ^5.81.5
|
"@playwright/test": ^1.53.2
|
||||||
'@tanstack/vue-store': ^0.7.1
|
"@pnpm/workspace.read-manifest": ^1000.2.0
|
||||||
'@tinymce/tinymce-vue': ^6.1.0
|
"@stylistic/stylelint-plugin": ^3.1.3
|
||||||
'@tinyflow-ai/vue': ^1.1.1
|
"@tailwindcss/nesting": 0.0.0-insiders.565cd3e
|
||||||
'@form-create/ant-design-vue': ^3.2.27
|
"@tailwindcss/typography": ^0.5.16
|
||||||
'@form-create/antd-designer': ^3.3.0
|
"@tanstack/vue-query": ^5.81.5
|
||||||
'@form-create/designer': ^3.3.0
|
"@tanstack/vue-store": ^0.7.1
|
||||||
'@form-create/naive-ui': ^3.2.27
|
"@tinyflow-ai/vue": ^1.1.1
|
||||||
'@form-create/element-ui': ^3.2.27
|
"@tinymce/tinymce-vue": ^6.1.0
|
||||||
'@types/archiver': ^6.0.3
|
"@types/archiver": ^6.0.3
|
||||||
'@types/eslint': ^9.6.1
|
"@types/crypto-js": ^4.2.2
|
||||||
'@types/html-minifier-terser': ^7.0.2
|
"@types/eslint": ^9.6.1
|
||||||
'@types/json-bigint': ^1.0.4
|
"@types/html-minifier-terser": ^7.0.2
|
||||||
'@types/jsonwebtoken': ^9.0.10
|
"@types/json-bigint": ^1.0.4
|
||||||
'@types/lodash.clonedeep': ^4.5.9
|
"@types/jsonwebtoken": ^9.0.10
|
||||||
'@types/lodash.get': ^4.4.9
|
"@types/lodash.clonedeep": ^4.5.9
|
||||||
'@types/lodash.isequal': ^4.5.8
|
"@types/lodash.get": ^4.4.9
|
||||||
'@types/lodash.set': ^4.3.9
|
"@types/lodash.isequal": ^4.5.8
|
||||||
'@types/markdown-it': ^14.1.2
|
"@types/lodash.set": ^4.3.9
|
||||||
'@types/node': ^22.16.0
|
"@types/markdown-it": ^14.1.2
|
||||||
'@types/nprogress': ^0.2.3
|
"@types/node": ^22.16.0
|
||||||
'@types/postcss-import': ^14.0.3
|
"@types/nprogress": ^0.2.3
|
||||||
'@types/qrcode': ^1.5.5
|
"@types/postcss-import": ^14.0.3
|
||||||
'@types/qs': ^6.14.0
|
"@types/qrcode": ^1.5.5
|
||||||
'@types/sortablejs': ^1.15.8
|
"@types/qs": ^6.14.0
|
||||||
'@types/crypto-js': ^4.2.2
|
"@types/sortablejs": ^1.15.8
|
||||||
'@typescript-eslint/eslint-plugin': ^8.35.1
|
"@typescript-eslint/eslint-plugin": ^8.35.1
|
||||||
'@typescript-eslint/parser': ^8.35.1
|
"@typescript-eslint/parser": ^8.35.1
|
||||||
'@vee-validate/zod': ^4.15.1
|
"@vee-validate/zod": ^4.15.1
|
||||||
'@vite-pwa/vitepress': ^1.0.0
|
"@vite-pwa/vitepress": ^1.0.0
|
||||||
'@vitejs/plugin-vue': ^6.0.1
|
"@vitejs/plugin-vue": ^6.0.1
|
||||||
'@vitejs/plugin-vue-jsx': ^5.0.1
|
"@vitejs/plugin-vue-jsx": ^5.0.1
|
||||||
'@vue/reactivity': ^3.5.17
|
"@vue/reactivity": ^3.5.17
|
||||||
'@vue/shared': ^3.5.17
|
"@vue/shared": ^3.5.17
|
||||||
'@vue/test-utils': ^2.4.6
|
"@vue/test-utils": ^2.4.6
|
||||||
'@vueuse/core': ^13.4.0
|
"@vueuse/core": ^13.4.0
|
||||||
'@vueuse/integrations': ^13.4.0
|
"@vueuse/integrations": ^13.4.0
|
||||||
'@vueuse/motion': ^3.0.3
|
"@vueuse/motion": ^3.0.3
|
||||||
ant-design-vue: ^4.2.6
|
ant-design-vue: ^4.2.6
|
||||||
archiver: ^7.0.1
|
archiver: ^7.0.1
|
||||||
autoprefixer: ^10.4.21
|
autoprefixer: ^10.4.21
|
||||||
axios: ^1.10.0
|
axios: ^1.10.0
|
||||||
axios-mock-adapter: ^2.1.0
|
axios-mock-adapter: ^2.1.0
|
||||||
|
bpmn-js: ^17.11.1
|
||||||
|
bpmn-js-properties-panel: 5.23.0
|
||||||
|
bpmn-js-token-simulation: ^0.36.3
|
||||||
cac: ^6.7.14
|
cac: ^6.7.14
|
||||||
|
camunda-bpmn-moddle: ^7.0.1
|
||||||
chalk: ^5.4.1
|
chalk: ^5.4.1
|
||||||
cheerio: ^1.1.0
|
cheerio: ^1.1.0
|
||||||
circular-dependency-scanner: ^2.3.0
|
circular-dependency-scanner: ^2.3.0
|
||||||
@@ -89,17 +92,17 @@ catalog:
|
|||||||
clsx: ^2.1.1
|
clsx: ^2.1.1
|
||||||
commitlint-plugin-function-rules: ^4.0.2
|
commitlint-plugin-function-rules: ^4.0.2
|
||||||
consola: ^3.4.2
|
consola: ^3.4.2
|
||||||
cross-env: ^7.0.3
|
|
||||||
cropperjs: ^1.6.2
|
cropperjs: ^1.6.2
|
||||||
|
cross-env: ^7.0.3
|
||||||
crypto-js: ^4.2.0
|
crypto-js: ^4.2.0
|
||||||
cspell: ^8.19.4
|
cspell: ^8.19.4
|
||||||
jsencrypt: ^3.3.2
|
|
||||||
cssnano: ^7.0.7
|
cssnano: ^7.0.7
|
||||||
cz-git: ^1.11.2
|
cz-git: ^1.11.2
|
||||||
czg: ^1.11.1
|
czg: ^1.11.1
|
||||||
dayjs: ^1.11.13
|
dayjs: ^1.11.13
|
||||||
defu: ^6.1.4
|
defu: ^6.1.4
|
||||||
depcheck: ^1.4.7
|
depcheck: ^1.4.7
|
||||||
|
diagram-js: ^12.8.1
|
||||||
dotenv: ^16.6.1
|
dotenv: ^16.6.1
|
||||||
echarts: ^5.6.0
|
echarts: ^5.6.0
|
||||||
element-plus: ^2.10.2
|
element-plus: ^2.10.2
|
||||||
@@ -120,13 +123,16 @@ catalog:
|
|||||||
eslint-plugin-vitest: ^0.5.4
|
eslint-plugin-vitest: ^0.5.4
|
||||||
eslint-plugin-vue: ^10.2.0
|
eslint-plugin-vue: ^10.2.0
|
||||||
execa: ^9.6.0
|
execa: ^9.6.0
|
||||||
|
fast-xml-parser: ^4.5.3
|
||||||
find-up: ^7.0.0
|
find-up: ^7.0.0
|
||||||
get-port: ^7.1.0
|
get-port: ^7.1.0
|
||||||
globals: ^16.3.0
|
globals: ^16.3.0
|
||||||
h3: ^1.15.3
|
h3: ^1.15.3
|
||||||
happy-dom: ^17.6.3
|
happy-dom: ^17.6.3
|
||||||
|
highlight.js: ^11.11.1
|
||||||
html-minifier-terser: ^7.2.0
|
html-minifier-terser: ^7.2.0
|
||||||
is-ci: ^4.1.0
|
is-ci: ^4.1.0
|
||||||
|
jsencrypt: ^3.3.2
|
||||||
json-bigint: ^1.0.0
|
json-bigint: ^1.0.0
|
||||||
jsonc-eslint-parser: ^2.4.0
|
jsonc-eslint-parser: ^2.4.0
|
||||||
jsonwebtoken: ^9.0.2
|
jsonwebtoken: ^9.0.2
|
||||||
@@ -142,6 +148,7 @@ catalog:
|
|||||||
markmap-toolbar: ^0.17.0
|
markmap-toolbar: ^0.17.0
|
||||||
markmap-view: ^0.16.0
|
markmap-view: ^0.16.0
|
||||||
medium-zoom: ^1.1.0
|
medium-zoom: ^1.1.0
|
||||||
|
min-dash: ^4.2.3
|
||||||
naive-ui: ^2.42.0
|
naive-ui: ^2.42.0
|
||||||
nitropack: ^2.11.13
|
nitropack: ^2.11.13
|
||||||
nprogress: ^0.2.0
|
nprogress: ^0.2.0
|
||||||
@@ -169,6 +176,7 @@ catalog:
|
|||||||
sass: ^1.89.2
|
sass: ^1.89.2
|
||||||
secure-ls: ^2.0.0
|
secure-ls: ^2.0.0
|
||||||
sortablejs: ^1.15.6
|
sortablejs: ^1.15.6
|
||||||
|
steady-xml: ^0.1.0
|
||||||
stylelint: ^16.21.0
|
stylelint: ^16.21.0
|
||||||
stylelint-config-recess-order: ^6.1.0
|
stylelint-config-recess-order: ^6.1.0
|
||||||
stylelint-config-recommended: ^16.0.0
|
stylelint-config-recommended: ^16.0.0
|
||||||
@@ -182,8 +190,8 @@ catalog:
|
|||||||
tailwindcss: ^3.4.17
|
tailwindcss: ^3.4.17
|
||||||
tailwindcss-animate: ^1.0.7
|
tailwindcss-animate: ^1.0.7
|
||||||
theme-colors: ^0.1.0
|
theme-colors: ^0.1.0
|
||||||
tippy.js: ^6.3.7
|
|
||||||
tinymce: ^7.3.0
|
tinymce: ^7.3.0
|
||||||
|
tippy.js: ^6.3.7
|
||||||
turbo: ^2.5.4
|
turbo: ^2.5.4
|
||||||
typescript: ^5.8.3
|
typescript: ^5.8.3
|
||||||
unbuild: ^3.6.1
|
unbuild: ^3.6.1
|
||||||
@@ -207,11 +215,10 @@ catalog:
|
|||||||
vue-router: ^4.5.1
|
vue-router: ^4.5.1
|
||||||
vue-tippy: ^6.7.1
|
vue-tippy: ^6.7.1
|
||||||
vue-tsc: 2.2.10
|
vue-tsc: 2.2.10
|
||||||
|
vue3-signature: ^0.2.4
|
||||||
|
vuedraggable: ^4.1.0
|
||||||
vxe-pc-ui: ^4.7.12
|
vxe-pc-ui: ^4.7.12
|
||||||
vxe-table: ^4.14.4
|
vxe-table: ^4.14.4
|
||||||
watermark-js-plus: ^1.6.2
|
watermark-js-plus: ^1.6.2
|
||||||
zod: ^3.25.67
|
zod: ^3.25.67
|
||||||
zod-defaults: ^0.1.3
|
zod-defaults: ^0.1.3
|
||||||
highlight.js: ^11.11.1
|
|
||||||
vue3-signature: ^0.2.4
|
|
||||||
vuedraggable: ^4.1.0
|
|
||||||
|
|||||||
Reference in New Issue
Block a user