fix: 修复表单校验回调弃用与 BPMN 告警
- 将 web-antd、web-antdv-next、web-ele 中的表单 validator 从 callback 改为 Promise - 为 BPMN viewer 的 xml 增加空值兜底,避免 undefined prop warning - 移除流程详情用户选择弹窗的无效 title 透传 - 调整 simple-bpm-viewer 函数声明顺序,避免 immediate watch 初始化时报错
This commit is contained in:
@@ -112,41 +112,37 @@ export namespace ThingModelApi {
|
|||||||
|
|
||||||
/** 生成「必填 + 数字」类校验器:拼到 size / length / 枚举值上 */
|
/** 生成「必填 + 数字」类校验器:拼到 size / length / 枚举值上 */
|
||||||
function buildRequiredNumberValidator(label: string) {
|
function buildRequiredNumberValidator(label: string) {
|
||||||
return (_rule: any, value: any, callback: any) => {
|
return (_rule: any, value: any) => {
|
||||||
if (isEmpty(value)) {
|
if (isEmpty(value)) {
|
||||||
callback(new Error(`${label}不能为空`));
|
return Promise.reject(new Error(`${label}不能为空`));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (Number.isNaN(Number(value))) {
|
if (Number.isNaN(Number(value))) {
|
||||||
callback(new Error(`${label}必须是数字`));
|
return Promise.reject(new Error(`${label}必须是数字`));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 生成「标识符样式」名称校验器:开头需为中文 / 英文 / 数字,整体仅允许中文、英文、数字、下划线、短划线,长度 ≤ 20 */
|
/** 生成「标识符样式」名称校验器:开头需为中文 / 英文 / 数字,整体仅允许中文、英文、数字、下划线、短划线,长度 ≤ 20 */
|
||||||
export function buildIdentifierLikeNameValidator(label: string) {
|
export function buildIdentifierLikeNameValidator(label: string) {
|
||||||
return (_rule: any, value: string, callback: any) => {
|
return (_rule: any, value: string) => {
|
||||||
if (isEmpty(value)) {
|
if (isEmpty(value)) {
|
||||||
callback(new Error(`${label}不能为空`));
|
return Promise.reject(new Error(`${label}不能为空`));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!/^[一-龥A-Za-z0-9]/.test(value)) {
|
if (!/^[一-龥A-Za-z0-9]/.test(value)) {
|
||||||
callback(new Error(`${label}必须以中文、英文字母或数字开头`));
|
return Promise.reject(
|
||||||
return;
|
new Error(`${label}必须以中文、英文字母或数字开头`),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (!/^[一-龥A-Za-z0-9][\w一-龥-]*$/.test(value)) {
|
if (!/^[一-龥A-Za-z0-9][\w一-龥-]*$/.test(value)) {
|
||||||
callback(
|
return Promise.reject(
|
||||||
new Error(`${label}只能包含中文、英文字母、数字、下划线和短划线`),
|
new Error(`${label}只能包含中文、英文字母、数字、下划线和短划线`),
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (value.length > 20) {
|
if (value.length > 20) {
|
||||||
callback(new Error(`${label}长度不能超过 20 个字符`));
|
return Promise.reject(new Error(`${label}长度不能超过 20 个字符`));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +166,7 @@ export const ThingModelFormRules: Record<string, Rule[]> = {
|
|||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
validator: (_rule: any, value: string, callback: any) => {
|
validator: (_rule: any, value: string) => {
|
||||||
const reservedKeywords = [
|
const reservedKeywords = [
|
||||||
'set',
|
'set',
|
||||||
'get',
|
'get',
|
||||||
@@ -181,18 +177,16 @@ export const ThingModelFormRules: Record<string, Rule[]> = {
|
|||||||
'value',
|
'value',
|
||||||
];
|
];
|
||||||
if (reservedKeywords.includes(value)) {
|
if (reservedKeywords.includes(value)) {
|
||||||
callback(
|
return Promise.reject(
|
||||||
new Error(
|
new Error(
|
||||||
'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义',
|
'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (/^\d+$/.test(value)) {
|
if (/^\d+$/.test(value)) {
|
||||||
callback(new Error('标识符不能是纯数字'));
|
return Promise.reject(new Error('标识符不能是纯数字'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ import '../theme/index.scss';
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
xml: {
|
xml: {
|
||||||
|
default: '',
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
|
||||||
},
|
},
|
||||||
view: {
|
view: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -185,12 +185,12 @@ const onSelectElement = (element: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 初始化 BPMN 视图 */
|
/** 初始化 BPMN 视图 */
|
||||||
const importXML = async (xml: string) => {
|
const importXML = async (xml?: string) => {
|
||||||
// 清空流程图
|
// 清空流程图
|
||||||
clearViewer();
|
clearViewer();
|
||||||
|
|
||||||
// 初始化流程图
|
// 初始化流程图
|
||||||
if (xml !== null && xml !== '') {
|
if (xml) {
|
||||||
try {
|
try {
|
||||||
bpmnViewer.value = new BpmnViewer({
|
bpmnViewer.value = new BpmnViewer({
|
||||||
additionalModules: [MoveCanvasModule],
|
additionalModules: [MoveCanvasModule],
|
||||||
@@ -303,7 +303,7 @@ const setProcessStatus = (view: any) => {
|
|||||||
watch(
|
watch(
|
||||||
() => props.xml,
|
() => props.xml,
|
||||||
(newXml) => {
|
(newXml) => {
|
||||||
importXML(newXml);
|
importXML(newXml || '');
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
@@ -318,7 +318,7 @@ watch(
|
|||||||
|
|
||||||
/** mounted:初始化 */
|
/** mounted:初始化 */
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
importXML(props.xml);
|
importXML(props.xml || '');
|
||||||
setProcessStatus(props.view);
|
setProcessStatus(props.view);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -68,20 +68,18 @@ const rules: Record<string, Rule[]> = {
|
|||||||
key: [
|
key: [
|
||||||
{ required: true, message: '流程标识不能为空', trigger: 'blur' },
|
{ required: true, message: '流程标识不能为空', trigger: 'blur' },
|
||||||
{
|
{
|
||||||
validator: (_rule: any, value: string, callback: any) => {
|
validator: (_rule: any, value: string) => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
callback();
|
return Promise.resolve();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!/^[a-z_][-\w.$]*$/i.test(value)) {
|
if (!/^[a-z_][-\w.$]*$/i.test(value)) {
|
||||||
callback(
|
return Promise.reject(
|
||||||
new Error(
|
new Error(
|
||||||
'只能包含字母、数字、下划线、连字符和点号,且必须以字母或下划线开头',
|
'只能包含字母、数字、下划线、连字符和点号,且必须以字母或下划线开头',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ const startUserSelectTasks = ref<UserTask[]>([]);
|
|||||||
const startUserSelectAssignees = ref<Record<string, number[]>>({});
|
const startUserSelectAssignees = ref<Record<string, number[]>>({});
|
||||||
const tempStartUserSelectAssignees = ref<Record<string, number[]>>({});
|
const tempStartUserSelectAssignees = ref<Record<string, number[]>>({});
|
||||||
|
|
||||||
const bpmnXML = ref<string | undefined>(undefined);
|
const bpmnXML = ref('');
|
||||||
const simpleJson = ref<string | undefined>(undefined);
|
const simpleJson = ref<string | undefined>(undefined);
|
||||||
|
|
||||||
const activeTab = ref('form');
|
const activeTab = ref('form');
|
||||||
@@ -158,7 +158,7 @@ async function initProcessInfo(row: any, formVariables?: any) {
|
|||||||
const processDefinitionDetail: BpmProcessDefinitionApi.ProcessDefinition =
|
const processDefinitionDetail: BpmProcessDefinitionApi.ProcessDefinition =
|
||||||
await getProcessDefinition(row.id);
|
await getProcessDefinition(row.id);
|
||||||
if (processDefinitionDetail) {
|
if (processDefinitionDetail) {
|
||||||
bpmnXML.value = processDefinitionDetail.bpmnXml;
|
bpmnXML.value = processDefinitionDetail.bpmnXml || '';
|
||||||
simpleJson.value = processDefinitionDetail.simpleModel;
|
simpleJson.value = processDefinitionDetail.simpleModel;
|
||||||
}
|
}
|
||||||
// 情况二:业务表单
|
// 情况二:业务表单
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const props = withDefaults(
|
|||||||
defineProps<{
|
defineProps<{
|
||||||
bpmnXml?: string;
|
bpmnXml?: string;
|
||||||
loading?: boolean; // 是否加载中
|
loading?: boolean; // 是否加载中
|
||||||
modelView?: object;
|
modelView?: Record<string, any>;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -29,8 +29,10 @@ watch(
|
|||||||
async (newModelView) => {
|
async (newModelView) => {
|
||||||
// 加载最新
|
// 加载最新
|
||||||
if (newModelView) {
|
if (newModelView) {
|
||||||
// @ts-expect-error: viewer instance type is broader than local ref typing
|
view.value = {
|
||||||
view.value = newModelView;
|
...newModelView,
|
||||||
|
bpmnXml: newModelView.bpmnXml || '',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
@@ -40,7 +42,7 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
() => props.bpmnXml,
|
() => props.bpmnXml,
|
||||||
(value) => {
|
(value) => {
|
||||||
view.value.bpmnXml = value;
|
view.value.bpmnXml = value || '';
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
@@ -52,7 +54,7 @@ watch(
|
|||||||
>
|
>
|
||||||
<MyProcessViewer
|
<MyProcessViewer
|
||||||
key="processViewer"
|
key="processViewer"
|
||||||
:xml="view.bpmnXml"
|
:xml="view.bpmnXml || ''"
|
||||||
:view="view"
|
:view="view"
|
||||||
class="h-full min-h-[500px] w-full"
|
class="h-full min-h-[500px] w-full"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -26,57 +26,14 @@ const simpleModel = ref<any>({});
|
|||||||
const tasks = ref([]); // 用户任务
|
const tasks = ref([]); // 用户任务
|
||||||
const processInstance = ref(); // 流程实例
|
const processInstance = ref(); // 流程实例
|
||||||
|
|
||||||
/** 监控模型视图 包括任务列表、进行中的活动节点编号等 */
|
function setSimpleModelNodeTaskStatus(
|
||||||
watch(
|
|
||||||
() => props.modelView,
|
|
||||||
async (newModelView) => {
|
|
||||||
if (newModelView) {
|
|
||||||
tasks.value = newModelView.tasks;
|
|
||||||
processInstance.value = newModelView.processInstance;
|
|
||||||
// 已经拒绝的活动节点编号集合,只包括 UserTask
|
|
||||||
const rejectedTaskActivityIds: string[] =
|
|
||||||
newModelView.rejectedTaskActivityIds;
|
|
||||||
// 进行中的活动节点编号集合, 只包括 UserTask
|
|
||||||
const unfinishedTaskActivityIds: string[] =
|
|
||||||
newModelView.unfinishedTaskActivityIds;
|
|
||||||
// 已经完成的活动节点编号集合, 包括 UserTask、Gateway 等
|
|
||||||
const finishedActivityIds: string[] =
|
|
||||||
newModelView.finishedTaskActivityIds;
|
|
||||||
// 已经完成的连线节点编号集合,只包括 SequenceFlow
|
|
||||||
const finishedSequenceFlowActivityIds: string[] =
|
|
||||||
newModelView.finishedSequenceFlowActivityIds;
|
|
||||||
setSimpleModelNodeTaskStatus(
|
|
||||||
newModelView.simpleModel,
|
|
||||||
newModelView.processInstance?.status,
|
|
||||||
rejectedTaskActivityIds,
|
|
||||||
unfinishedTaskActivityIds,
|
|
||||||
finishedActivityIds,
|
|
||||||
finishedSequenceFlowActivityIds,
|
|
||||||
);
|
|
||||||
simpleModel.value = newModelView.simpleModel || {};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
);
|
|
||||||
|
|
||||||
/** 监控模型结构数据 */
|
|
||||||
watch(
|
|
||||||
() => props.simpleJson,
|
|
||||||
async (value) => {
|
|
||||||
if (value) {
|
|
||||||
simpleModel.value = JSON.parse(value);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const setSimpleModelNodeTaskStatus = (
|
|
||||||
simpleModel: SimpleFlowNode | undefined,
|
simpleModel: SimpleFlowNode | undefined,
|
||||||
processStatus: number,
|
processStatus: number,
|
||||||
rejectedTaskActivityIds: string[],
|
rejectedTaskActivityIds: string[],
|
||||||
unfinishedTaskActivityIds: string[],
|
unfinishedTaskActivityIds: string[],
|
||||||
finishedActivityIds: string[],
|
finishedActivityIds: string[],
|
||||||
finishedSequenceFlowActivityIds: string[],
|
finishedSequenceFlowActivityIds: string[],
|
||||||
) => {
|
) {
|
||||||
if (!simpleModel) {
|
if (!simpleModel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -166,7 +123,50 @@ const setSimpleModelNodeTaskStatus = (
|
|||||||
finishedActivityIds,
|
finishedActivityIds,
|
||||||
finishedSequenceFlowActivityIds,
|
finishedSequenceFlowActivityIds,
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/** 监控模型视图 包括任务列表、进行中的活动节点编号等 */
|
||||||
|
watch(
|
||||||
|
() => props.modelView,
|
||||||
|
async (newModelView) => {
|
||||||
|
if (newModelView) {
|
||||||
|
tasks.value = newModelView.tasks;
|
||||||
|
processInstance.value = newModelView.processInstance;
|
||||||
|
// 已经拒绝的活动节点编号集合,只包括 UserTask
|
||||||
|
const rejectedTaskActivityIds: string[] =
|
||||||
|
newModelView.rejectedTaskActivityIds;
|
||||||
|
// 进行中的活动节点编号集合, 只包括 UserTask
|
||||||
|
const unfinishedTaskActivityIds: string[] =
|
||||||
|
newModelView.unfinishedTaskActivityIds;
|
||||||
|
// 已经完成的活动节点编号集合, 包括 UserTask、Gateway 等
|
||||||
|
const finishedActivityIds: string[] =
|
||||||
|
newModelView.finishedTaskActivityIds;
|
||||||
|
// 已经完成的连线节点编号集合,只包括 SequenceFlow
|
||||||
|
const finishedSequenceFlowActivityIds: string[] =
|
||||||
|
newModelView.finishedSequenceFlowActivityIds;
|
||||||
|
setSimpleModelNodeTaskStatus(
|
||||||
|
newModelView.simpleModel,
|
||||||
|
newModelView.processInstance?.status,
|
||||||
|
rejectedTaskActivityIds,
|
||||||
|
unfinishedTaskActivityIds,
|
||||||
|
finishedActivityIds,
|
||||||
|
finishedSequenceFlowActivityIds,
|
||||||
|
);
|
||||||
|
simpleModel.value = newModelView.simpleModel || {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 监控模型结构数据 */
|
||||||
|
watch(
|
||||||
|
() => props.simpleJson,
|
||||||
|
async (value) => {
|
||||||
|
if (value) {
|
||||||
|
simpleModel.value = JSON.parse(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="loading">
|
<div v-loading="loading">
|
||||||
|
|||||||
@@ -482,7 +482,6 @@ defineExpose({ setCustomApproveUsers, batchSetCustomApproveUsers });
|
|||||||
class="w-3/5"
|
class="w-3/5"
|
||||||
v-model:value="selectedUsers"
|
v-model:value="selectedUsers"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
title="选择用户"
|
|
||||||
@confirm="handleUserSelectConfirm"
|
@confirm="handleUserSelectConfirm"
|
||||||
@closed="handleUserSelectClosed"
|
@closed="handleUserSelectClosed"
|
||||||
@cancel="handleUserSelectCancel"
|
@cancel="handleUserSelectCancel"
|
||||||
|
|||||||
@@ -122,23 +122,21 @@ function normalizeFormData(result: any): RuleSceneApi.SceneRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 触发器校验 */
|
/** 触发器校验 */
|
||||||
function validateTriggers(_rule: any, value: any, callback: any) {
|
function validateTriggers(_rule: any, value: any) {
|
||||||
const error = validateSceneRuleTriggers(value);
|
const error = validateSceneRuleTriggers(value);
|
||||||
if (error) {
|
if (error) {
|
||||||
callback(new Error(error));
|
return Promise.reject(new Error(error));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 执行器校验 */
|
/** 执行器校验 */
|
||||||
function validateActions(_rule: any, value: any, callback: any) {
|
function validateActions(_rule: any, value: any) {
|
||||||
const error = validateSceneRuleActions(value);
|
const error = validateSceneRuleActions(value);
|
||||||
if (error) {
|
if (error) {
|
||||||
callback(new Error(error));
|
return Promise.reject(new Error(error));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
const formRules = reactive({
|
const formRules = reactive({
|
||||||
|
|||||||
@@ -35,51 +35,44 @@ function deleteEnum(index: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 校验单项枚举值:必填、数字、不重复 */
|
/** 校验单项枚举值:必填、数字、不重复 */
|
||||||
function validateEnumValue(_rule: any, value: any, callback: any) {
|
function validateEnumValue(_rule: any, value: any) {
|
||||||
if (isEmpty(value)) {
|
if (isEmpty(value)) {
|
||||||
callback(new Error('枚举值不能为空'));
|
return Promise.reject(new Error('枚举值不能为空'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (Number.isNaN(Number(value))) {
|
if (Number.isNaN(Number(value))) {
|
||||||
callback(new Error('枚举值必须是数字'));
|
return Promise.reject(new Error('枚举值必须是数字'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const sameCount = dataSpecsList.value.filter(
|
const sameCount = dataSpecsList.value.filter(
|
||||||
(it) => it.value === value,
|
(it) => it.value === value,
|
||||||
).length;
|
).length;
|
||||||
if (sameCount > 1) {
|
if (sameCount > 1) {
|
||||||
callback(new Error('枚举值不能重复'));
|
return Promise.reject(new Error('枚举值不能重复'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 校验整个枚举列表:非空、无空项、无非法数字、无重复 */
|
/** 校验整个枚举列表:非空、无空项、无非法数字、无重复 */
|
||||||
function validateEnumList(_rule: any, _value: any, callback: any) {
|
function validateEnumList(_rule: any, _value: any) {
|
||||||
if (isEmpty(dataSpecsList.value)) {
|
if (isEmpty(dataSpecsList.value)) {
|
||||||
callback(new Error('请至少添加一个枚举项'));
|
return Promise.reject(new Error('请至少添加一个枚举项'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const hasEmpty = dataSpecsList.value.some(
|
const hasEmpty = dataSpecsList.value.some(
|
||||||
(item) => isEmpty(item.value) || isEmpty(item.name),
|
(item) => isEmpty(item.value) || isEmpty(item.name),
|
||||||
);
|
);
|
||||||
if (hasEmpty) {
|
if (hasEmpty) {
|
||||||
callback(new Error('存在未填写的枚举值或描述'));
|
return Promise.reject(new Error('存在未填写的枚举值或描述'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const hasInvalidNumber = dataSpecsList.value.some((item) =>
|
const hasInvalidNumber = dataSpecsList.value.some((item) =>
|
||||||
Number.isNaN(Number(item.value)),
|
Number.isNaN(Number(item.value)),
|
||||||
);
|
);
|
||||||
if (hasInvalidNumber) {
|
if (hasInvalidNumber) {
|
||||||
callback(new Error('存在非数字的枚举值'));
|
return Promise.reject(new Error('存在非数字的枚举值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const values = dataSpecsList.value.map((item) => item.value);
|
const values = dataSpecsList.value.map((item) => item.value);
|
||||||
if (new Set(values).size !== values.length) {
|
if (new Set(values).size !== values.length) {
|
||||||
callback(new Error('存在重复的枚举值'));
|
return Promise.reject(new Error('存在重复的枚举值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -36,53 +36,46 @@ function unitChange(unitSpecs: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 校验最小值 */
|
/** 校验最小值 */
|
||||||
function validateMin(_rule: any, _value: any, callback: any) {
|
function validateMin(_rule: any, _value: any) {
|
||||||
const min = Number(dataSpecs.value.min);
|
const min = Number(dataSpecs.value.min);
|
||||||
const max = Number(dataSpecs.value.max);
|
const max = Number(dataSpecs.value.max);
|
||||||
if (Number.isNaN(min)) {
|
if (Number.isNaN(min)) {
|
||||||
callback(new Error('请输入有效的数值'));
|
return Promise.reject(new Error('请输入有效的数值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!Number.isNaN(max) && min >= max) {
|
if (!Number.isNaN(max) && min >= max) {
|
||||||
callback(new Error('最小值必须小于最大值'));
|
return Promise.reject(new Error('最小值必须小于最大值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 校验最大值 */
|
/** 校验最大值 */
|
||||||
function validateMax(_rule: any, _value: any, callback: any) {
|
function validateMax(_rule: any, _value: any) {
|
||||||
const min = Number(dataSpecs.value.min);
|
const min = Number(dataSpecs.value.min);
|
||||||
const max = Number(dataSpecs.value.max);
|
const max = Number(dataSpecs.value.max);
|
||||||
if (Number.isNaN(max)) {
|
if (Number.isNaN(max)) {
|
||||||
callback(new Error('请输入有效的数值'));
|
return Promise.reject(new Error('请输入有效的数值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!Number.isNaN(min) && max <= min) {
|
if (!Number.isNaN(min) && max <= min) {
|
||||||
callback(new Error('最大值必须大于最小值'));
|
return Promise.reject(new Error('最大值必须大于最小值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 校验步长 */
|
/** 校验步长 */
|
||||||
function validateStep(_rule: any, _value: any, callback: any) {
|
function validateStep(_rule: any, _value: any) {
|
||||||
const step = Number(dataSpecs.value.step);
|
const step = Number(dataSpecs.value.step);
|
||||||
if (Number.isNaN(step)) {
|
if (Number.isNaN(step)) {
|
||||||
callback(new Error('请输入有效的数值'));
|
return Promise.reject(new Error('请输入有效的数值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (step <= 0) {
|
if (step <= 0) {
|
||||||
callback(new Error('步长必须大于 0'));
|
return Promise.reject(new Error('步长必须大于 0'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const min = Number(dataSpecs.value.min);
|
const min = Number(dataSpecs.value.min);
|
||||||
const max = Number(dataSpecs.value.max);
|
const max = Number(dataSpecs.value.max);
|
||||||
if (!Number.isNaN(min) && !Number.isNaN(max) && step > max - min) {
|
if (!Number.isNaN(min) && !Number.isNaN(max) && step > max - min) {
|
||||||
callback(new Error('步长不能大于最大值与最小值的差值'));
|
return Promise.reject(new Error('步长不能大于最大值与最小值的差值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -33,12 +33,11 @@ const structFormRef = ref();
|
|||||||
const formData = ref<any>(buildEmptyFormData());
|
const formData = ref<any>(buildEmptyFormData());
|
||||||
|
|
||||||
/** 校验结构体属性对象非空 */
|
/** 校验结构体属性对象非空 */
|
||||||
function validateStructSpecsList(_rule: any, _value: any, callback: any) {
|
function validateStructSpecsList(_rule: any, _value: any) {
|
||||||
if (isEmpty(dataSpecsList.value)) {
|
if (isEmpty(dataSpecsList.value)) {
|
||||||
callback(new Error('请至少添加一个结构体属性对象'));
|
return Promise.reject(new Error('请至少添加一个结构体属性对象'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
const [Modal, modalApi] = useVbenModal({
|
||||||
|
|||||||
@@ -114,41 +114,37 @@ export namespace ThingModelApi {
|
|||||||
|
|
||||||
/** 生成「必填 + 数字」类校验器:拼到 size / length / 枚举值上 */
|
/** 生成「必填 + 数字」类校验器:拼到 size / length / 枚举值上 */
|
||||||
function buildRequiredNumberValidator(label: string) {
|
function buildRequiredNumberValidator(label: string) {
|
||||||
return (_rule: any, value: any, callback: any) => {
|
return (_rule: any, value: any) => {
|
||||||
if (isEmpty(value)) {
|
if (isEmpty(value)) {
|
||||||
callback(new Error(`${label}不能为空`));
|
return Promise.reject(new Error(`${label}不能为空`));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (Number.isNaN(Number(value))) {
|
if (Number.isNaN(Number(value))) {
|
||||||
callback(new Error(`${label}必须是数字`));
|
return Promise.reject(new Error(`${label}必须是数字`));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 生成「标识符样式」名称校验器:开头需为中文 / 英文 / 数字,整体仅允许中文、英文、数字、下划线、短划线,长度 ≤ 20 */
|
/** 生成「标识符样式」名称校验器:开头需为中文 / 英文 / 数字,整体仅允许中文、英文、数字、下划线、短划线,长度 ≤ 20 */
|
||||||
export function buildIdentifierLikeNameValidator(label: string) {
|
export function buildIdentifierLikeNameValidator(label: string) {
|
||||||
return (_rule: any, value: string, callback: any) => {
|
return (_rule: any, value: string) => {
|
||||||
if (isEmpty(value)) {
|
if (isEmpty(value)) {
|
||||||
callback(new Error(`${label}不能为空`));
|
return Promise.reject(new Error(`${label}不能为空`));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!/^[一-龥A-Za-z0-9]/.test(value)) {
|
if (!/^[一-龥A-Za-z0-9]/.test(value)) {
|
||||||
callback(new Error(`${label}必须以中文、英文字母或数字开头`));
|
return Promise.reject(
|
||||||
return;
|
new Error(`${label}必须以中文、英文字母或数字开头`),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (!/^[一-龥A-Za-z0-9][\w一-龥-]*$/.test(value)) {
|
if (!/^[一-龥A-Za-z0-9][\w一-龥-]*$/.test(value)) {
|
||||||
callback(
|
return Promise.reject(
|
||||||
new Error(`${label}只能包含中文、英文字母、数字、下划线和短划线`),
|
new Error(`${label}只能包含中文、英文字母、数字、下划线和短划线`),
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (value.length > 20) {
|
if (value.length > 20) {
|
||||||
callback(new Error(`${label}长度不能超过 20 个字符`));
|
return Promise.reject(new Error(`${label}长度不能超过 20 个字符`));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +168,7 @@ export const ThingModelFormRules: Record<string, FormItemRule[]> = {
|
|||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
validator: (_rule: any, value: string, callback: any) => {
|
validator: (_rule: any, value: string) => {
|
||||||
const reservedKeywords = [
|
const reservedKeywords = [
|
||||||
'set',
|
'set',
|
||||||
'get',
|
'get',
|
||||||
@@ -183,18 +179,16 @@ export const ThingModelFormRules: Record<string, FormItemRule[]> = {
|
|||||||
'value',
|
'value',
|
||||||
];
|
];
|
||||||
if (reservedKeywords.includes(value)) {
|
if (reservedKeywords.includes(value)) {
|
||||||
callback(
|
return Promise.reject(
|
||||||
new Error(
|
new Error(
|
||||||
'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义',
|
'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (/^\d+$/.test(value)) {
|
if (/^\d+$/.test(value)) {
|
||||||
callback(new Error('标识符不能是纯数字'));
|
return Promise.reject(new Error('标识符不能是纯数字'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ import '../theme/index.scss';
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
xml: {
|
xml: {
|
||||||
|
default: '',
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
|
||||||
},
|
},
|
||||||
view: {
|
view: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -269,12 +269,12 @@ const onSelectElement = (element: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 初始化 BPMN 视图 */
|
/** 初始化 BPMN 视图 */
|
||||||
const importXML = async (xml: string) => {
|
const importXML = async (xml?: string) => {
|
||||||
// 清空流程图
|
// 清空流程图
|
||||||
clearViewer();
|
clearViewer();
|
||||||
|
|
||||||
// 初始化流程图
|
// 初始化流程图
|
||||||
if (xml !== null && xml !== '') {
|
if (xml) {
|
||||||
try {
|
try {
|
||||||
bpmnViewer.value = new BpmnViewer({
|
bpmnViewer.value = new BpmnViewer({
|
||||||
additionalModules: [MoveCanvasModule],
|
additionalModules: [MoveCanvasModule],
|
||||||
@@ -387,7 +387,7 @@ const setProcessStatus = (view: any) => {
|
|||||||
watch(
|
watch(
|
||||||
() => props.xml,
|
() => props.xml,
|
||||||
(newXml) => {
|
(newXml) => {
|
||||||
importXML(newXml);
|
importXML(newXml || '');
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
@@ -402,7 +402,7 @@ watch(
|
|||||||
|
|
||||||
/** mounted:初始化 */
|
/** mounted:初始化 */
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
importXML(props.xml);
|
importXML(props.xml || '');
|
||||||
setProcessStatus(props.view);
|
setProcessStatus(props.view);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ const startUserSelectTasks = ref<UserTask[]>([]);
|
|||||||
const startUserSelectAssignees = ref<Record<string, number[]>>({});
|
const startUserSelectAssignees = ref<Record<string, number[]>>({});
|
||||||
const tempStartUserSelectAssignees = ref<Record<string, number[]>>({});
|
const tempStartUserSelectAssignees = ref<Record<string, number[]>>({});
|
||||||
|
|
||||||
const bpmnXML = ref<string | undefined>(undefined);
|
const bpmnXML = ref('');
|
||||||
const simpleJson = ref<string | undefined>(undefined);
|
const simpleJson = ref<string | undefined>(undefined);
|
||||||
|
|
||||||
const activeTab = ref('form');
|
const activeTab = ref('form');
|
||||||
@@ -167,7 +167,7 @@ async function initProcessInfo(row: any, formVariables?: any) {
|
|||||||
const processDefinitionDetail: BpmProcessDefinitionApi.ProcessDefinition =
|
const processDefinitionDetail: BpmProcessDefinitionApi.ProcessDefinition =
|
||||||
await getProcessDefinition(row.id);
|
await getProcessDefinition(row.id);
|
||||||
if (processDefinitionDetail) {
|
if (processDefinitionDetail) {
|
||||||
bpmnXML.value = processDefinitionDetail.bpmnXml;
|
bpmnXML.value = processDefinitionDetail.bpmnXml || '';
|
||||||
simpleJson.value = processDefinitionDetail.simpleModel;
|
simpleJson.value = processDefinitionDetail.simpleModel;
|
||||||
}
|
}
|
||||||
// 情况二:业务表单
|
// 情况二:业务表单
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const props = withDefaults(
|
|||||||
defineProps<{
|
defineProps<{
|
||||||
bpmnXml?: string;
|
bpmnXml?: string;
|
||||||
loading?: boolean; // 是否加载中
|
loading?: boolean; // 是否加载中
|
||||||
modelView?: object;
|
modelView?: Record<string, any>;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -29,8 +29,10 @@ watch(
|
|||||||
async (newModelView) => {
|
async (newModelView) => {
|
||||||
// 加载最新
|
// 加载最新
|
||||||
if (newModelView) {
|
if (newModelView) {
|
||||||
// @ts-expect-error: viewer instance type is broader than local ref typing
|
view.value = {
|
||||||
view.value = newModelView;
|
...newModelView,
|
||||||
|
bpmnXml: newModelView.bpmnXml || '',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
@@ -40,7 +42,7 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
() => props.bpmnXml,
|
() => props.bpmnXml,
|
||||||
(value) => {
|
(value) => {
|
||||||
view.value.bpmnXml = value;
|
view.value.bpmnXml = value || '';
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
@@ -52,7 +54,7 @@ watch(
|
|||||||
>
|
>
|
||||||
<MyProcessViewer
|
<MyProcessViewer
|
||||||
key="processViewer"
|
key="processViewer"
|
||||||
:xml="view.bpmnXml"
|
:xml="view.bpmnXml || ''"
|
||||||
:view="view"
|
:view="view"
|
||||||
class="h-full min-h-[500px] w-full"
|
class="h-full min-h-[500px] w-full"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -26,57 +26,14 @@ const simpleModel = ref<any>({});
|
|||||||
const tasks = ref([]); // 用户任务
|
const tasks = ref([]); // 用户任务
|
||||||
const processInstance = ref(); // 流程实例
|
const processInstance = ref(); // 流程实例
|
||||||
|
|
||||||
/** 监控模型视图 包括任务列表、进行中的活动节点编号等 */
|
function setSimpleModelNodeTaskStatus(
|
||||||
watch(
|
|
||||||
() => props.modelView,
|
|
||||||
async (newModelView) => {
|
|
||||||
if (newModelView) {
|
|
||||||
tasks.value = newModelView.tasks;
|
|
||||||
processInstance.value = newModelView.processInstance;
|
|
||||||
// 已经拒绝的活动节点编号集合,只包括 UserTask
|
|
||||||
const rejectedTaskActivityIds: string[] =
|
|
||||||
newModelView.rejectedTaskActivityIds;
|
|
||||||
// 进行中的活动节点编号集合, 只包括 UserTask
|
|
||||||
const unfinishedTaskActivityIds: string[] =
|
|
||||||
newModelView.unfinishedTaskActivityIds;
|
|
||||||
// 已经完成的活动节点编号集合, 包括 UserTask、Gateway 等
|
|
||||||
const finishedActivityIds: string[] =
|
|
||||||
newModelView.finishedTaskActivityIds;
|
|
||||||
// 已经完成的连线节点编号集合,只包括 SequenceFlow
|
|
||||||
const finishedSequenceFlowActivityIds: string[] =
|
|
||||||
newModelView.finishedSequenceFlowActivityIds;
|
|
||||||
setSimpleModelNodeTaskStatus(
|
|
||||||
newModelView.simpleModel,
|
|
||||||
newModelView.processInstance?.status,
|
|
||||||
rejectedTaskActivityIds,
|
|
||||||
unfinishedTaskActivityIds,
|
|
||||||
finishedActivityIds,
|
|
||||||
finishedSequenceFlowActivityIds,
|
|
||||||
);
|
|
||||||
simpleModel.value = newModelView.simpleModel || {};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
);
|
|
||||||
|
|
||||||
/** 监控模型结构数据 */
|
|
||||||
watch(
|
|
||||||
() => props.simpleJson,
|
|
||||||
async (value) => {
|
|
||||||
if (value) {
|
|
||||||
simpleModel.value = JSON.parse(value);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const setSimpleModelNodeTaskStatus = (
|
|
||||||
simpleModel: SimpleFlowNode | undefined,
|
simpleModel: SimpleFlowNode | undefined,
|
||||||
processStatus: number,
|
processStatus: number,
|
||||||
rejectedTaskActivityIds: string[],
|
rejectedTaskActivityIds: string[],
|
||||||
unfinishedTaskActivityIds: string[],
|
unfinishedTaskActivityIds: string[],
|
||||||
finishedActivityIds: string[],
|
finishedActivityIds: string[],
|
||||||
finishedSequenceFlowActivityIds: string[],
|
finishedSequenceFlowActivityIds: string[],
|
||||||
) => {
|
) {
|
||||||
if (!simpleModel) {
|
if (!simpleModel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -166,7 +123,50 @@ const setSimpleModelNodeTaskStatus = (
|
|||||||
finishedActivityIds,
|
finishedActivityIds,
|
||||||
finishedSequenceFlowActivityIds,
|
finishedSequenceFlowActivityIds,
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/** 监控模型视图 包括任务列表、进行中的活动节点编号等 */
|
||||||
|
watch(
|
||||||
|
() => props.modelView,
|
||||||
|
async (newModelView) => {
|
||||||
|
if (newModelView) {
|
||||||
|
tasks.value = newModelView.tasks;
|
||||||
|
processInstance.value = newModelView.processInstance;
|
||||||
|
// 已经拒绝的活动节点编号集合,只包括 UserTask
|
||||||
|
const rejectedTaskActivityIds: string[] =
|
||||||
|
newModelView.rejectedTaskActivityIds;
|
||||||
|
// 进行中的活动节点编号集合, 只包括 UserTask
|
||||||
|
const unfinishedTaskActivityIds: string[] =
|
||||||
|
newModelView.unfinishedTaskActivityIds;
|
||||||
|
// 已经完成的活动节点编号集合, 包括 UserTask、Gateway 等
|
||||||
|
const finishedActivityIds: string[] =
|
||||||
|
newModelView.finishedTaskActivityIds;
|
||||||
|
// 已经完成的连线节点编号集合,只包括 SequenceFlow
|
||||||
|
const finishedSequenceFlowActivityIds: string[] =
|
||||||
|
newModelView.finishedSequenceFlowActivityIds;
|
||||||
|
setSimpleModelNodeTaskStatus(
|
||||||
|
newModelView.simpleModel,
|
||||||
|
newModelView.processInstance?.status,
|
||||||
|
rejectedTaskActivityIds,
|
||||||
|
unfinishedTaskActivityIds,
|
||||||
|
finishedActivityIds,
|
||||||
|
finishedSequenceFlowActivityIds,
|
||||||
|
);
|
||||||
|
simpleModel.value = newModelView.simpleModel || {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 监控模型结构数据 */
|
||||||
|
watch(
|
||||||
|
() => props.simpleJson,
|
||||||
|
async (value) => {
|
||||||
|
if (value) {
|
||||||
|
simpleModel.value = JSON.parse(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="loading">
|
<div v-loading="loading">
|
||||||
|
|||||||
@@ -14,13 +14,7 @@ import {
|
|||||||
import { IconifyIcon } from '@vben/icons';
|
import { IconifyIcon } from '@vben/icons';
|
||||||
import { formatDateTime, isEmpty } from '@vben/utils';
|
import { formatDateTime, isEmpty } from '@vben/utils';
|
||||||
|
|
||||||
import {
|
import { Avatar, Button, Timeline, TimelineItem, Tooltip } from 'antdv-next';
|
||||||
Avatar,
|
|
||||||
Button,
|
|
||||||
Timeline,
|
|
||||||
TimelineItem,
|
|
||||||
Tooltip,
|
|
||||||
} from 'antdv-next';
|
|
||||||
|
|
||||||
import { UserSelectModal } from '#/views/system/user/components';
|
import { UserSelectModal } from '#/views/system/user/components';
|
||||||
|
|
||||||
@@ -488,7 +482,6 @@ defineExpose({ setCustomApproveUsers, batchSetCustomApproveUsers });
|
|||||||
class="w-3/5"
|
class="w-3/5"
|
||||||
v-model:value="selectedUsers"
|
v-model:value="selectedUsers"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
title="选择用户"
|
|
||||||
@confirm="handleUserSelectConfirm"
|
@confirm="handleUserSelectConfirm"
|
||||||
@closed="handleUserSelectClosed"
|
@closed="handleUserSelectClosed"
|
||||||
@cancel="handleUserSelectCancel"
|
@cancel="handleUserSelectCancel"
|
||||||
|
|||||||
@@ -111,42 +111,38 @@ export namespace ThingModelApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 生成「必填 + 数字」类校验器:拼到 size / length / 枚举值上 */
|
/** 生成「必填 + 数字」类校验器:拼到 size / length / 枚举值上 */
|
||||||
function buildRequiredNumberValidator(label: string) {
|
function buildRequiredNumberValidator(label: string): any {
|
||||||
return (_rule: any, value: any, callback: any) => {
|
return (_rule: any, value: any) => {
|
||||||
if (isEmpty(value)) {
|
if (isEmpty(value)) {
|
||||||
callback(new Error(`${label}不能为空`));
|
return Promise.reject(new Error(`${label}不能为空`));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (Number.isNaN(Number(value))) {
|
if (Number.isNaN(Number(value))) {
|
||||||
callback(new Error(`${label}必须是数字`));
|
return Promise.reject(new Error(`${label}必须是数字`));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 生成「标识符样式」名称校验器:开头需为中文 / 英文 / 数字,整体仅允许中文、英文、数字、下划线、短划线,长度 ≤ 20 */
|
/** 生成「标识符样式」名称校验器:开头需为中文 / 英文 / 数字,整体仅允许中文、英文、数字、下划线、短划线,长度 ≤ 20 */
|
||||||
export function buildIdentifierLikeNameValidator(label: string) {
|
export function buildIdentifierLikeNameValidator(label: string): any {
|
||||||
return (_rule: any, value: string, callback: any) => {
|
return (_rule: any, value: string) => {
|
||||||
if (isEmpty(value)) {
|
if (isEmpty(value)) {
|
||||||
callback(new Error(`${label}不能为空`));
|
return Promise.reject(new Error(`${label}不能为空`));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!/^[一-龥A-Za-z0-9]/.test(value)) {
|
if (!/^[一-龥A-Za-z0-9]/.test(value)) {
|
||||||
callback(new Error(`${label}必须以中文、英文字母或数字开头`));
|
return Promise.reject(
|
||||||
return;
|
new Error(`${label}必须以中文、英文字母或数字开头`),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (!/^[一-龥A-Za-z0-9][\w一-龥-]*$/.test(value)) {
|
if (!/^[一-龥A-Za-z0-9][\w一-龥-]*$/.test(value)) {
|
||||||
callback(
|
return Promise.reject(
|
||||||
new Error(`${label}只能包含中文、英文字母、数字、下划线和短划线`),
|
new Error(`${label}只能包含中文、英文字母、数字、下划线和短划线`),
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (value.length > 20) {
|
if (value.length > 20) {
|
||||||
callback(new Error(`${label}长度不能超过 20 个字符`));
|
return Promise.reject(new Error(`${label}长度不能超过 20 个字符`));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +166,7 @@ export const ThingModelFormRules: Record<string, FormItemRule[]> = {
|
|||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
validator: (_rule: any, value: string, callback: any) => {
|
validator: ((_rule: any, value: string) => {
|
||||||
const reservedKeywords = [
|
const reservedKeywords = [
|
||||||
'set',
|
'set',
|
||||||
'get',
|
'get',
|
||||||
@@ -181,19 +177,17 @@ export const ThingModelFormRules: Record<string, FormItemRule[]> = {
|
|||||||
'value',
|
'value',
|
||||||
];
|
];
|
||||||
if (reservedKeywords.includes(value)) {
|
if (reservedKeywords.includes(value)) {
|
||||||
callback(
|
return Promise.reject(
|
||||||
new Error(
|
new Error(
|
||||||
'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义',
|
'set, get, post, property, event, time, value 是系统保留字段,不能用于标识符定义',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (/^\d+$/.test(value)) {
|
if (/^\d+$/.test(value)) {
|
||||||
callback(new Error('标识符不能是纯数字'));
|
return Promise.reject(new Error('标识符不能是纯数字'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
},
|
}) as any,
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ import '../theme/index.scss';
|
|||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
xml: {
|
xml: {
|
||||||
|
default: '',
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
|
||||||
},
|
},
|
||||||
view: {
|
view: {
|
||||||
type: Object,
|
type: Object,
|
||||||
@@ -192,12 +192,12 @@ const onSelectElement = (element: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** 初始化 BPMN 视图 */
|
/** 初始化 BPMN 视图 */
|
||||||
const importXML = async (xml: string) => {
|
const importXML = async (xml?: string) => {
|
||||||
// 清空流程图
|
// 清空流程图
|
||||||
clearViewer();
|
clearViewer();
|
||||||
|
|
||||||
// 初始化流程图
|
// 初始化流程图
|
||||||
if (xml !== null && xml !== '') {
|
if (xml) {
|
||||||
try {
|
try {
|
||||||
bpmnViewer.value = new BpmnViewer({
|
bpmnViewer.value = new BpmnViewer({
|
||||||
additionalModules: [MoveCanvasModule],
|
additionalModules: [MoveCanvasModule],
|
||||||
@@ -310,7 +310,7 @@ const setProcessStatus = (view: any) => {
|
|||||||
watch(
|
watch(
|
||||||
() => props.xml,
|
() => props.xml,
|
||||||
(newXml) => {
|
(newXml) => {
|
||||||
importXML(newXml);
|
importXML(newXml || '');
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
);
|
);
|
||||||
@@ -325,7 +325,7 @@ watch(
|
|||||||
|
|
||||||
/** mounted:初始化 */
|
/** mounted:初始化 */
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
importXML(props.xml);
|
importXML(props.xml || '');
|
||||||
setProcessStatus(props.view);
|
setProcessStatus(props.view);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -70,21 +70,19 @@ const rules: Record<string, FormItemRule[]> = {
|
|||||||
key: [
|
key: [
|
||||||
{ required: true, message: '流程标识不能为空', trigger: 'blur' },
|
{ required: true, message: '流程标识不能为空', trigger: 'blur' },
|
||||||
{
|
{
|
||||||
validator: (_rule: any, value: string, callback: any) => {
|
validator: ((_rule: any, value: string) => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
callback();
|
return Promise.resolve();
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!/^[a-z_][-\w.$]*$/i.test(value)) {
|
if (!/^[a-z_][-\w.$]*$/i.test(value)) {
|
||||||
callback(
|
return Promise.reject(
|
||||||
new Error(
|
new Error(
|
||||||
'只能包含字母、数字、下划线、连字符和点号,且必须以字母或下划线开头',
|
'只能包含字母、数字、下划线、连字符和点号,且必须以字母或下划线开头',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
},
|
}) as any,
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ const startUserSelectTasks = ref<UserTask[]>([]);
|
|||||||
const startUserSelectAssignees = ref<Record<string, number[]>>({});
|
const startUserSelectAssignees = ref<Record<string, number[]>>({});
|
||||||
const tempStartUserSelectAssignees = ref<Record<string, number[]>>({});
|
const tempStartUserSelectAssignees = ref<Record<string, number[]>>({});
|
||||||
|
|
||||||
const bpmnXML = ref<string | undefined>(undefined);
|
const bpmnXML = ref('');
|
||||||
const simpleJson = ref<string | undefined>(undefined);
|
const simpleJson = ref<string | undefined>(undefined);
|
||||||
|
|
||||||
// @ts-expect-error unused
|
// @ts-expect-error unused
|
||||||
@@ -168,7 +168,7 @@ async function initProcessInfo(row: any, formVariables?: any) {
|
|||||||
const processDefinitionDetail: BpmProcessDefinitionApi.ProcessDefinition =
|
const processDefinitionDetail: BpmProcessDefinitionApi.ProcessDefinition =
|
||||||
await getProcessDefinition(row.id);
|
await getProcessDefinition(row.id);
|
||||||
if (processDefinitionDetail) {
|
if (processDefinitionDetail) {
|
||||||
bpmnXML.value = processDefinitionDetail.bpmnXml;
|
bpmnXML.value = processDefinitionDetail.bpmnXml || '';
|
||||||
simpleJson.value = processDefinitionDetail.simpleModel;
|
simpleJson.value = processDefinitionDetail.simpleModel;
|
||||||
}
|
}
|
||||||
// 情况二:业务表单
|
// 情况二:业务表单
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ const props = withDefaults(
|
|||||||
defineProps<{
|
defineProps<{
|
||||||
bpmnXml?: string;
|
bpmnXml?: string;
|
||||||
loading?: boolean; // 是否加载中
|
loading?: boolean; // 是否加载中
|
||||||
modelView?: object;
|
modelView?: Record<string, any>;
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
loading: false,
|
loading: false,
|
||||||
@@ -29,8 +29,10 @@ watch(
|
|||||||
async (newModelView) => {
|
async (newModelView) => {
|
||||||
// 加载最新
|
// 加载最新
|
||||||
if (newModelView) {
|
if (newModelView) {
|
||||||
// @ts-expect-error: viewer instance type is broader than local ref typing
|
view.value = {
|
||||||
view.value = newModelView;
|
...newModelView,
|
||||||
|
bpmnXml: newModelView.bpmnXml || '',
|
||||||
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{ immediate: true },
|
{ immediate: true },
|
||||||
@@ -40,7 +42,7 @@ watch(
|
|||||||
watch(
|
watch(
|
||||||
() => props.bpmnXml,
|
() => props.bpmnXml,
|
||||||
(value) => {
|
(value) => {
|
||||||
view.value.bpmnXml = value;
|
view.value.bpmnXml = value || '';
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
@@ -52,7 +54,7 @@ watch(
|
|||||||
>
|
>
|
||||||
<MyProcessViewer
|
<MyProcessViewer
|
||||||
key="processViewer"
|
key="processViewer"
|
||||||
:xml="view.bpmnXml"
|
:xml="view.bpmnXml || ''"
|
||||||
:view="view"
|
:view="view"
|
||||||
class="h-full min-h-[500px] w-full"
|
class="h-full min-h-[500px] w-full"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -26,57 +26,14 @@ const simpleModel = ref<any>({});
|
|||||||
const tasks = ref([]); // 用户任务
|
const tasks = ref([]); // 用户任务
|
||||||
const processInstance = ref(); // 流程实例
|
const processInstance = ref(); // 流程实例
|
||||||
|
|
||||||
/** 监控模型视图 包括任务列表、进行中的活动节点编号等 */
|
function setSimpleModelNodeTaskStatus(
|
||||||
watch(
|
|
||||||
() => props.modelView,
|
|
||||||
async (newModelView) => {
|
|
||||||
if (newModelView) {
|
|
||||||
tasks.value = newModelView.tasks;
|
|
||||||
processInstance.value = newModelView.processInstance;
|
|
||||||
// 已经拒绝的活动节点编号集合,只包括 UserTask
|
|
||||||
const rejectedTaskActivityIds: string[] =
|
|
||||||
newModelView.rejectedTaskActivityIds;
|
|
||||||
// 进行中的活动节点编号集合, 只包括 UserTask
|
|
||||||
const unfinishedTaskActivityIds: string[] =
|
|
||||||
newModelView.unfinishedTaskActivityIds;
|
|
||||||
// 已经完成的活动节点编号集合, 包括 UserTask、Gateway 等
|
|
||||||
const finishedActivityIds: string[] =
|
|
||||||
newModelView.finishedTaskActivityIds;
|
|
||||||
// 已经完成的连线节点编号集合,只包括 SequenceFlow
|
|
||||||
const finishedSequenceFlowActivityIds: string[] =
|
|
||||||
newModelView.finishedSequenceFlowActivityIds;
|
|
||||||
setSimpleModelNodeTaskStatus(
|
|
||||||
newModelView.simpleModel,
|
|
||||||
newModelView.processInstance?.status,
|
|
||||||
rejectedTaskActivityIds,
|
|
||||||
unfinishedTaskActivityIds,
|
|
||||||
finishedActivityIds,
|
|
||||||
finishedSequenceFlowActivityIds,
|
|
||||||
);
|
|
||||||
simpleModel.value = newModelView.simpleModel || {};
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
);
|
|
||||||
|
|
||||||
/** 监控模型结构数据 */
|
|
||||||
watch(
|
|
||||||
() => props.simpleJson,
|
|
||||||
async (value) => {
|
|
||||||
if (value) {
|
|
||||||
simpleModel.value = JSON.parse(value);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const setSimpleModelNodeTaskStatus = (
|
|
||||||
simpleModel: SimpleFlowNode | undefined,
|
simpleModel: SimpleFlowNode | undefined,
|
||||||
processStatus: number,
|
processStatus: number,
|
||||||
rejectedTaskActivityIds: string[],
|
rejectedTaskActivityIds: string[],
|
||||||
unfinishedTaskActivityIds: string[],
|
unfinishedTaskActivityIds: string[],
|
||||||
finishedActivityIds: string[],
|
finishedActivityIds: string[],
|
||||||
finishedSequenceFlowActivityIds: string[],
|
finishedSequenceFlowActivityIds: string[],
|
||||||
) => {
|
) {
|
||||||
if (!simpleModel) {
|
if (!simpleModel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -166,7 +123,50 @@ const setSimpleModelNodeTaskStatus = (
|
|||||||
finishedActivityIds,
|
finishedActivityIds,
|
||||||
finishedSequenceFlowActivityIds,
|
finishedSequenceFlowActivityIds,
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
|
/** 监控模型视图 包括任务列表、进行中的活动节点编号等 */
|
||||||
|
watch(
|
||||||
|
() => props.modelView,
|
||||||
|
async (newModelView) => {
|
||||||
|
if (newModelView) {
|
||||||
|
tasks.value = newModelView.tasks;
|
||||||
|
processInstance.value = newModelView.processInstance;
|
||||||
|
// 已经拒绝的活动节点编号集合,只包括 UserTask
|
||||||
|
const rejectedTaskActivityIds: string[] =
|
||||||
|
newModelView.rejectedTaskActivityIds;
|
||||||
|
// 进行中的活动节点编号集合, 只包括 UserTask
|
||||||
|
const unfinishedTaskActivityIds: string[] =
|
||||||
|
newModelView.unfinishedTaskActivityIds;
|
||||||
|
// 已经完成的活动节点编号集合, 包括 UserTask、Gateway 等
|
||||||
|
const finishedActivityIds: string[] =
|
||||||
|
newModelView.finishedTaskActivityIds;
|
||||||
|
// 已经完成的连线节点编号集合,只包括 SequenceFlow
|
||||||
|
const finishedSequenceFlowActivityIds: string[] =
|
||||||
|
newModelView.finishedSequenceFlowActivityIds;
|
||||||
|
setSimpleModelNodeTaskStatus(
|
||||||
|
newModelView.simpleModel,
|
||||||
|
newModelView.processInstance?.status,
|
||||||
|
rejectedTaskActivityIds,
|
||||||
|
unfinishedTaskActivityIds,
|
||||||
|
finishedActivityIds,
|
||||||
|
finishedSequenceFlowActivityIds,
|
||||||
|
);
|
||||||
|
simpleModel.value = newModelView.simpleModel || {};
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ immediate: true },
|
||||||
|
);
|
||||||
|
|
||||||
|
/** 监控模型结构数据 */
|
||||||
|
watch(
|
||||||
|
() => props.simpleJson,
|
||||||
|
async (value) => {
|
||||||
|
if (value) {
|
||||||
|
simpleModel.value = JSON.parse(value);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div v-loading="loading">
|
<div v-loading="loading">
|
||||||
|
|||||||
@@ -486,7 +486,6 @@ defineExpose({ setCustomApproveUsers, batchSetCustomApproveUsers });
|
|||||||
class="w-3/5"
|
class="w-3/5"
|
||||||
v-model="selectedUsers"
|
v-model="selectedUsers"
|
||||||
:multiple="true"
|
:multiple="true"
|
||||||
title="选择用户"
|
|
||||||
@confirm="handleUserSelectConfirm"
|
@confirm="handleUserSelectConfirm"
|
||||||
@closed="handleUserSelectClosed"
|
@closed="handleUserSelectClosed"
|
||||||
@cancel="handleUserSelectCancel"
|
@cancel="handleUserSelectCancel"
|
||||||
|
|||||||
@@ -122,23 +122,21 @@ function normalizeFormData(result: any): RuleSceneApi.SceneRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 触发器校验 */
|
/** 触发器校验 */
|
||||||
function validateTriggers(_rule: any, value: any, callback: any) {
|
function validateTriggers(_rule: any, value: any) {
|
||||||
const error = validateSceneRuleTriggers(value);
|
const error = validateSceneRuleTriggers(value);
|
||||||
if (error) {
|
if (error) {
|
||||||
callback(new Error(error));
|
return Promise.reject(new Error(error));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 执行器校验 */
|
/** 执行器校验 */
|
||||||
function validateActions(_rule: any, value: any, callback: any) {
|
function validateActions(_rule: any, value: any) {
|
||||||
const error = validateSceneRuleActions(value);
|
const error = validateSceneRuleActions(value);
|
||||||
if (error) {
|
if (error) {
|
||||||
callback(new Error(error));
|
return Promise.reject(new Error(error));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
}
|
||||||
|
|
||||||
const formRules = reactive({
|
const formRules = reactive({
|
||||||
|
|||||||
@@ -35,52 +35,45 @@ function deleteEnum(index: number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 校验单项枚举值:必填、数字、不重复 */
|
/** 校验单项枚举值:必填、数字、不重复 */
|
||||||
function validateEnumValue(_rule: any, value: any, callback: any) {
|
const validateEnumValue: any = (_rule: any, value: any) => {
|
||||||
if (isEmpty(value)) {
|
if (isEmpty(value)) {
|
||||||
callback(new Error('枚举值不能为空'));
|
return Promise.reject(new Error('枚举值不能为空'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (Number.isNaN(Number(value))) {
|
if (Number.isNaN(Number(value))) {
|
||||||
callback(new Error('枚举值必须是数字'));
|
return Promise.reject(new Error('枚举值必须是数字'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const sameCount = dataSpecsList.value.filter(
|
const sameCount = dataSpecsList.value.filter(
|
||||||
(it) => it.value === value,
|
(it) => it.value === value,
|
||||||
).length;
|
).length;
|
||||||
if (sameCount > 1) {
|
if (sameCount > 1) {
|
||||||
callback(new Error('枚举值不能重复'));
|
return Promise.reject(new Error('枚举值不能重复'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 校验整个枚举列表:非空、无空项、无非法数字、无重复 */
|
/** 校验整个枚举列表:非空、无空项、无非法数字、无重复 */
|
||||||
function validateEnumList(_rule: any, _value: any, callback: any) {
|
const validateEnumList: any = (_rule: any, _value: any) => {
|
||||||
if (isEmpty(dataSpecsList.value)) {
|
if (isEmpty(dataSpecsList.value)) {
|
||||||
callback(new Error('请至少添加一个枚举项'));
|
return Promise.reject(new Error('请至少添加一个枚举项'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const hasEmpty = dataSpecsList.value.some(
|
const hasEmpty = dataSpecsList.value.some(
|
||||||
(item) => isEmpty(item.value) || isEmpty(item.name),
|
(item) => isEmpty(item.value) || isEmpty(item.name),
|
||||||
);
|
);
|
||||||
if (hasEmpty) {
|
if (hasEmpty) {
|
||||||
callback(new Error('存在未填写的枚举值或描述'));
|
return Promise.reject(new Error('存在未填写的枚举值或描述'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const hasInvalidNumber = dataSpecsList.value.some((item) =>
|
const hasInvalidNumber = dataSpecsList.value.some((item) =>
|
||||||
Number.isNaN(Number(item.value)),
|
Number.isNaN(Number(item.value)),
|
||||||
);
|
);
|
||||||
if (hasInvalidNumber) {
|
if (hasInvalidNumber) {
|
||||||
callback(new Error('存在非数字的枚举值'));
|
return Promise.reject(new Error('存在非数字的枚举值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const values = dataSpecsList.value.map((item) => item.value);
|
const values = dataSpecsList.value.map((item) => item.value);
|
||||||
if (new Set(values).size !== values.length) {
|
if (new Set(values).size !== values.length) {
|
||||||
callback(new Error('存在重复的枚举值'));
|
return Promise.reject(new Error('存在重复的枚举值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -29,54 +29,47 @@ function unitChange(unitSpecs: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 校验最小值 */
|
/** 校验最小值 */
|
||||||
function validateMin(_rule: any, _value: any, callback: any) {
|
const validateMin: any = (_rule: any, _value: any) => {
|
||||||
const min = Number(dataSpecs.value.min);
|
const min = Number(dataSpecs.value.min);
|
||||||
const max = Number(dataSpecs.value.max);
|
const max = Number(dataSpecs.value.max);
|
||||||
if (Number.isNaN(min)) {
|
if (Number.isNaN(min)) {
|
||||||
callback(new Error('请输入有效的数值'));
|
return Promise.reject(new Error('请输入有效的数值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!Number.isNaN(max) && min >= max) {
|
if (!Number.isNaN(max) && min >= max) {
|
||||||
callback(new Error('最小值必须小于最大值'));
|
return Promise.reject(new Error('最小值必须小于最大值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 校验最大值 */
|
/** 校验最大值 */
|
||||||
function validateMax(_rule: any, _value: any, callback: any) {
|
const validateMax: any = (_rule: any, _value: any) => {
|
||||||
const min = Number(dataSpecs.value.min);
|
const min = Number(dataSpecs.value.min);
|
||||||
const max = Number(dataSpecs.value.max);
|
const max = Number(dataSpecs.value.max);
|
||||||
if (Number.isNaN(max)) {
|
if (Number.isNaN(max)) {
|
||||||
callback(new Error('请输入有效的数值'));
|
return Promise.reject(new Error('请输入有效的数值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (!Number.isNaN(min) && max <= min) {
|
if (!Number.isNaN(min) && max <= min) {
|
||||||
callback(new Error('最大值必须大于最小值'));
|
return Promise.reject(new Error('最大值必须大于最小值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
};
|
||||||
|
|
||||||
/** 校验步长 */
|
/** 校验步长 */
|
||||||
function validateStep(_rule: any, _value: any, callback: any) {
|
const validateStep: any = (_rule: any, _value: any) => {
|
||||||
const step = Number(dataSpecs.value.step);
|
const step = Number(dataSpecs.value.step);
|
||||||
if (Number.isNaN(step)) {
|
if (Number.isNaN(step)) {
|
||||||
callback(new Error('请输入有效的数值'));
|
return Promise.reject(new Error('请输入有效的数值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if (step <= 0) {
|
if (step <= 0) {
|
||||||
callback(new Error('步长必须大于 0'));
|
return Promise.reject(new Error('步长必须大于 0'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
const min = Number(dataSpecs.value.min);
|
const min = Number(dataSpecs.value.min);
|
||||||
const max = Number(dataSpecs.value.max);
|
const max = Number(dataSpecs.value.max);
|
||||||
if (!Number.isNaN(min) && !Number.isNaN(max) && step > max - min) {
|
if (!Number.isNaN(min) && !Number.isNaN(max) && step > max - min) {
|
||||||
callback(new Error('步长不能大于最大值与最小值的差值'));
|
return Promise.reject(new Error('步长不能大于最大值与最小值的差值'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|||||||
@@ -33,13 +33,12 @@ const structFormRef = ref();
|
|||||||
const formData = ref<any>(buildEmptyFormData());
|
const formData = ref<any>(buildEmptyFormData());
|
||||||
|
|
||||||
/** 校验结构体属性对象非空 */
|
/** 校验结构体属性对象非空 */
|
||||||
function validateStructSpecsList(_rule: any, _value: any, callback: any) {
|
const validateStructSpecsList: any = (_rule: any, _value: any) => {
|
||||||
if (isEmpty(dataSpecsList.value)) {
|
if (isEmpty(dataSpecsList.value)) {
|
||||||
callback(new Error('请至少添加一个结构体属性对象'));
|
return Promise.reject(new Error('请至少添加一个结构体属性对象'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
callback();
|
return Promise.resolve();
|
||||||
}
|
};
|
||||||
|
|
||||||
const [Modal, modalApi] = useVbenModal({
|
const [Modal, modalApi] = useVbenModal({
|
||||||
async onConfirm() {
|
async onConfirm() {
|
||||||
|
|||||||
Reference in New Issue
Block a user