工作流管理相关

This commit is contained in:
2026-08-13 09:36:46 +08:00
parent 0e6381d2b3
commit 2ae59c9252
3 changed files with 52 additions and 52 deletions
@@ -36,10 +36,10 @@
</div>
</el-form-item>
<el-form-item v-if="jsonTypeIsScalar" label="默认值">
<template v-if="hasReference">
<div class="fcd-ref-bound" :class="{ 'is-invalid': referenceInvalid }">
<span class="fcd-ref-bound-text">已引用{{ referenceLabel }}</span>
<el-button size="small" text type="danger" @click="clearReference">清除</el-button>
<template v-if="hasValueSource">
<div class="fcd-ref-bound" :class="{ 'is-invalid': valueSourceInvalid }">
<span class="fcd-ref-bound-text">已引用{{ valueSourceLabel }}</span>
<el-button size="small" text type="danger" @click="clearValueSource">清除</el-button>
</div>
</template>
<template v-else>
@@ -64,7 +64,7 @@
<el-tag size="small" type="info">{{ node.nodeCode }}</el-tag>
</div>
<div v-if="node.outputFields.length === 0" class="fcd-ref-node-empty">该节点无输出字段</div>
<div v-for="of in node.outputFields" :key="of.field" class="fcd-ref-field" @click="setReference(node, of)">
<div v-for="of in node.outputFields" :key="of.field" class="fcd-ref-field" @click="setValueSource(node, of)">
{{ of.label || of.field }}
</div>
</div>
@@ -177,10 +177,10 @@
</div>
</el-form-item>
<el-form-item v-if="jsonTypeIsScalar" label="默认值">
<template v-if="hasReference">
<div class="fcd-ref-bound" :class="{ 'is-invalid': referenceInvalid }">
<span class="fcd-ref-bound-text">已引用{{ referenceLabel }}</span>
<el-button size="small" text type="danger" @click="clearReference">清除</el-button>
<template v-if="hasValueSource">
<div class="fcd-ref-bound" :class="{ 'is-invalid': valueSourceInvalid }">
<span class="fcd-ref-bound-text">已引用{{ valueSourceLabel }}</span>
<el-button size="small" text type="danger" @click="clearValueSource">清除</el-button>
</div>
</template>
<template v-else>
@@ -205,7 +205,7 @@
<el-tag size="small" type="info">{{ node.nodeCode }}</el-tag>
</div>
<div v-if="node.outputFields.length === 0" class="fcd-ref-node-empty">该节点无输出字段</div>
<div v-for="of in node.outputFields" :key="of.field" class="fcd-ref-field" @click="setReference(node, of)">
<div v-for="of in node.outputFields" :key="of.field" class="fcd-ref-field" @click="setValueSource(node, of)">
{{ of.label || of.field }}
</div>
</div>
@@ -319,7 +319,7 @@ interface FieldFormData {
accept?: string; maxSize?: number; maxCount?: number;
uploadRules?: UploadRule[]; uploadTotalMaxCount?: number; uploadTotalMaxSize?: number;
};
reference?: { nodeId: string; field: string };
valueSource?: { nodeId: string; field: string };
_createParentId?: string; _isArrayParent?: boolean; _childrenCount?: number;
}
@@ -344,7 +344,7 @@ const form = reactive<FieldFormData>({
label: '', description: '', role: '',
isForm: true, required: false, defaultValue: '', options: [], constraint: {},
enumValues: [],
reference: undefined,
valueSource: undefined,
});
const uploadRules = ref<UploadRule[]>([]);
@@ -367,7 +367,7 @@ function resetForm() {
form.isForm = true; form.required = false; form.defaultValue = '';
form.options = []; form.constraint = {};
form.enumValues = [];
form.reference = undefined;
form.valueSource = undefined;
// @ts-ignore
form._createParentId = undefined; form._isArrayParent = false;
uploadRules.value = [];
@@ -389,7 +389,7 @@ function loadForm(data: FieldFormData | null) {
}
form.constraint = data.constraint ? { ...data.constraint } : {};
form.enumValues = data.enumValues ? JSON.parse(JSON.stringify(data.enumValues)) : [];
form.reference = data.reference ? { ...data.reference } : undefined;
form.valueSource = data.valueSource ? { ...data.valueSource } : undefined;
// @ts-ignore
form._createParentId = data._createParentId; form._isArrayParent = data._isArrayParent ?? false;
// @ts-ignore
@@ -448,9 +448,9 @@ watch(() => props.visible, (val) => { if (val) loadForm(props.formData); }, { im
// ===== 默认值引用上级节点输出 =====
const hasUpstream = computed(() => (props.upstreamNodes?.length ?? 0) > 0);
const hasReference = computed(() => !!form.reference);
const referenceLabel = computed(() => {
const ref = form.reference;
const hasValueSource = computed(() => !!form.valueSource);
const valueSourceLabel = computed(() => {
const ref = form.valueSource;
if (!ref) return '';
const node = props.upstreamNodes?.find((n) => n.id === ref.nodeId);
const nodeName = node?.label || ref.nodeId;
@@ -458,23 +458,23 @@ const referenceLabel = computed(() => {
return `${nodeName}.${fieldLabel}`;
});
// 引用是否已失效:上游节点被删除,或其输出字段已不存在
const referenceInvalid = computed(() => {
const ref = form.reference;
const valueSourceInvalid = computed(() => {
const ref = form.valueSource;
if (!ref) return false;
const node = props.upstreamNodes?.find((n) => n.id === ref.nodeId);
if (!node) return true;
return !node.outputFields.some((f) => f.field === ref.field);
});
watch(referenceInvalid, (invalid) => {
if (invalid && form.reference) { form.reference = undefined; }
watch(valueSourceInvalid, (invalid) => {
if (invalid && form.valueSource) { form.valueSource = undefined; }
}, { immediate: true });
const setReference = (node: UpstreamNodeInfo, of: { field: string; label: string }) => {
form.reference = { nodeId: node.id, field: of.field };
const setValueSource = (node: UpstreamNodeInfo, of: { field: string; label: string }) => {
form.valueSource = { nodeId: node.id, field: of.field };
// 有引用时默认值无意义,清空避免两者并存导致歧义
form.defaultValue = '';
};
const clearReference = () => {
form.reference = undefined;
const clearValueSource = () => {
form.valueSource = undefined;
};
function handleSave() {
+6 -6
View File
@@ -84,7 +84,7 @@ interface FieldConfig {
defaultValue?: string | number;
options?: Array<{ label: string; value: string }>;
enumValues?: any[];
reference?: { nodeId: string; field: string };
valueSource?: { nodeId: string; field: string };
constraint?: {
minLength?: number; maxLength?: number; pattern?: string;
min?: number; max?: number; numberType?: string;
@@ -130,7 +130,7 @@ interface FieldFormData {
_createParentId?: string;
_isArrayParent?: boolean;
_childrenCount?: number;
reference?: { nodeId: string; field: string };
valueSource?: { nodeId: string; field: string };
}
// --- helpers ---
@@ -314,7 +314,7 @@ function formToConfig(form: FieldFormData): FieldConfig {
if (form.defaultValue) cfg.defaultValue = form.jsonType === 'number' ? Number(form.defaultValue) : form.defaultValue;
if (form.options?.length > 0) cfg.options = [...form.options];
if (form.enumValues?.length > 0) cfg.enumValues = JSON.parse(JSON.stringify(form.enumValues));
if (form.reference) cfg.reference = { ...form.reference };
if (form.valueSource) cfg.valueSource = { ...form.valueSource };
const hasC = Object.values(form.constraint).some((v: any) => {
if (Array.isArray(v)) return v.length > 0;
return v !== undefined && v !== null && v !== '';
@@ -335,7 +335,7 @@ function hasAnyConfig(node: JsonNodeData): boolean {
if (c.label || c.description || c.role || c.defaultValue) return true;
if (c.options?.length) return true;
if (c.enumValues?.length) return true;
if (c.reference) return true;
if (c.valueSource) return true;
if (c.required) return true;
if (c.isForm === false) return true;
if (c.constraint && Object.keys(c.constraint).length > 0) return true;
@@ -366,7 +366,7 @@ function openFieldDialog(nodeId: string) {
options: cfg.options || [],
constraint: cfg.constraint ? { ...cfg.constraint } : {},
enumValues: cfg.enumValues ? JSON.parse(JSON.stringify(cfg.enumValues)) : [],
reference: cfg.reference ? { ...cfg.reference } : undefined,
valueSource: cfg.valueSource ? { ...cfg.valueSource } : undefined,
_childrenCount: node.children.length,
},
};
@@ -399,7 +399,7 @@ function openAddChildDialog(parentNodeId: string) {
options: [],
constraint: {},
enumValues: [],
reference: undefined,
valueSource: undefined,
_createParentId: parentNodeId,
_isArrayParent: isArray,
_childrenCount: 0,
@@ -82,13 +82,13 @@
<el-checkbox
size="small"
:model-value="def.runtimeShow ?? false"
:disabled="hasReference"
:disabled="hasValueSource"
@change="toggleExpose"
class="mf-leaf-expose"
>表单展示</el-checkbox>
</el-tooltip>
<el-popover
v-if="canReference"
v-if="canValueSource"
placement="bottom"
:width="260"
trigger="click"
@@ -119,7 +119,7 @@
v-for="of in node.outputFields"
:key="of.field"
class="mf-ref-field"
@click="setReference(node, of)"
@click="setValueSource(node, of)"
>
{{ of.label || of.field }}
</div>
@@ -128,9 +128,9 @@
</div>
</el-popover>
</div>
<div v-if="hasReference" class="mf-ref-bound" :class="{ 'is-invalid': referenceInvalid }">
<span class="mf-ref-bound-text">已引用{{ referenceLabel }}</span>
<el-button size="small" text type="danger" @click="clearReference">清除</el-button>
<div v-if="hasValueSource" class="mf-ref-bound" :class="{ 'is-invalid': valueSourceInvalid }">
<span class="mf-ref-bound-text">已引用{{ valueSourceLabel }}</span>
<el-button size="small" text type="danger" @click="clearValueSource">清除</el-button>
</div>
<div v-else-if="!isUpload" class="mf-leaf-ctrl">
<el-input-number
@@ -220,13 +220,13 @@ const isTextarea = computed(() => isLeaf.value && fieldType.value === 'textarea'
const isUpload = computed(() => isLeaf.value && fieldType.value === 'upload');
// ===== 引用上级节点输出 =====
// 可引用:叶子 + 非开关 + 非固定选项下拉 + 非上传(开关/下拉值来自模型;上传类型不提供引用
const canReference = computed(() => isLeaf.value && !isSwitch.value && !isSelect.value && !isUpload.value);
// 可引用:叶子 + 非开关 + 非固定选项下拉(开关/下拉值来自模型;上传类型同样支持引用上级输出
const canValueSource = computed(() => isLeaf.value && !isSwitch.value && !isSelect.value);
const hasUpstream = computed(() => (props.upstreamNodes?.length ?? 0) > 0);
const hasReference = computed(() => !!def.value?.reference);
const hasValueSource = computed(() => !!def.value?.valueSource);
// 已引用时的展示文案:{节点label}.{字段label}
const referenceLabel = computed(() => {
const ref = def.value?.reference;
const valueSourceLabel = computed(() => {
const ref = def.value?.valueSource;
if (!ref) return '';
const node = props.upstreamNodes?.find((n) => n.id === ref.nodeId);
const nodeName = node?.label || ref.nodeId;
@@ -235,34 +235,34 @@ const referenceLabel = computed(() => {
});
// 引用是否已失效:上游节点被删除,或其输出字段已不存在(换模型/换配置导致 schema 变化)
const referenceInvalid = computed(() => {
const ref = def.value?.reference;
const valueSourceInvalid = computed(() => {
const ref = def.value?.valueSource;
if (!ref) return false;
const node = props.upstreamNodes?.find((n) => n.id === ref.nodeId);
if (!node) return true;
return !node.outputFields.some((f) => f.field === ref.field);
});
// 失效引用自动清理,避免保存脏数据(就地删除 reference,复用深 watch 上传链路)
// 失效引用自动清理,避免保存脏数据(就地删除 valueSource,复用深 watch 上传链路)
watch(
referenceInvalid,
valueSourceInvalid,
(invalid) => {
if (invalid && def.value) {
delete def.value.reference;
delete def.value.valueSource;
}
},
{ immediate: true }
);
// 选中前驱节点输出字段:就地写 def.reference,复用深 watch 上传链路
const setReference = (node: UpstreamNodeInfo, of: { field: string; label: string }) => {
// 选中前驱节点输出字段:就地写 def.valueSource,复用深 watch 上传链路
const setValueSource = (node: UpstreamNodeInfo, of: { field: string; label: string }) => {
if (!def.value) return;
def.value.reference = { nodeId: node.id, field: of.field };
def.value.valueSource = { nodeId: node.id, field: of.field };
};
const clearReference = () => {
const clearValueSource = () => {
if (!def.value) return;
delete def.value.reference;
delete def.value.valueSource;
};
// ===== 叶子值(兼容字符串/布尔/数字) =====