工作流管理相关
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
// ===== 叶子值(兼容字符串/布尔/数字) =====
|
||||
|
||||
Reference in New Issue
Block a user