https节点表单更改
This commit is contained in:
@@ -106,22 +106,13 @@
|
|||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
class="field-upload"
|
class="field-upload"
|
||||||
>
|
>
|
||||||
<el-button size="small" type="primary" :disabled="getFieldFileList(fieldItem.field).length >= 1">
|
<el-button size="small" type="primary" :disabled="getFieldFileList(fieldItem.field).length >= 1"> 选择文件 </el-button>
|
||||||
选择文件
|
|
||||||
</el-button>
|
|
||||||
</el-upload>
|
</el-upload>
|
||||||
<!-- 手动显示已上传成功的文件列表 -->
|
<!-- 手动显示已上传成功的文件列表 -->
|
||||||
<div v-if="getFieldFileList(fieldItem.field).length > 0" class="uploaded-files-list">
|
<div v-if="getFieldFileList(fieldItem.field).length > 0" class="uploaded-files-list">
|
||||||
<div v-for="(uploadedFile, fileIdx) in getFieldFileList(fieldItem.field)" :key="fileIdx" class="uploaded-file-item">
|
<div v-for="(uploadedFile, fileIdx) in getFieldFileList(fieldItem.field)" :key="fileIdx" class="uploaded-file-item">
|
||||||
<span class="file-name">{{ uploadedFile.name }}</span>
|
<span class="file-name">{{ uploadedFile.name }}</span>
|
||||||
<el-button
|
<el-button type="danger" link size="small" @click="removeFieldFile(fieldItem.field, fileIdx, 'upload')"> 删除 </el-button>
|
||||||
type="danger"
|
|
||||||
link
|
|
||||||
size="small"
|
|
||||||
@click="removeFieldFile(fieldItem.field, fileIdx, 'upload')"
|
|
||||||
>
|
|
||||||
删除
|
|
||||||
</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -142,12 +133,7 @@
|
|||||||
<div v-if="getFieldFileList(fieldItem.field).length > 0" class="uploaded-files-list">
|
<div v-if="getFieldFileList(fieldItem.field).length > 0" class="uploaded-files-list">
|
||||||
<div v-for="(uploadedFile, fileIdx) in getFieldFileList(fieldItem.field)" :key="fileIdx" class="uploaded-file-item">
|
<div v-for="(uploadedFile, fileIdx) in getFieldFileList(fieldItem.field)" :key="fileIdx" class="uploaded-file-item">
|
||||||
<span class="file-name">{{ uploadedFile.name }}</span>
|
<span class="file-name">{{ uploadedFile.name }}</span>
|
||||||
<el-button
|
<el-button type="danger" link size="small" @click="removeFieldFile(fieldItem.field, fileIdx, 'uploadMultiple')">
|
||||||
type="danger"
|
|
||||||
link
|
|
||||||
size="small"
|
|
||||||
@click="removeFieldFile(fieldItem.field, fileIdx, 'uploadMultiple')"
|
|
||||||
>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -155,38 +141,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 键值对输入(HTTP节点的headers和body) -->
|
<!-- 键值对输入(HTTP节点的headers和body) -->
|
||||||
<div v-else-if="fieldItem.type === 'keyValue'" class="key-value-input-wrapper">
|
<div v-else-if="fieldItem.type === 'keyValue'" class="key-value-input-wrapper">
|
||||||
<div
|
<div v-for="(pair, pairIndex) in getKeyValuePairs(fieldItem.field)" :key="pairIndex" class="key-value-pair">
|
||||||
v-for="(pair, pairIndex) in getKeyValuePairs(fieldItem.field)"
|
<el-input v-model="pair.key" placeholder="键" class="key-input" @input="updateKeyValueField(fieldItem.field)" />
|
||||||
:key="pairIndex"
|
<el-input v-model="pair.value" placeholder="值" class="value-input" @input="updateKeyValueField(fieldItem.field)" />
|
||||||
class="key-value-pair"
|
<el-button type="danger" :icon="Delete" circle size="small" @click="removeKeyValuePair(fieldItem.field, pairIndex)" />
|
||||||
>
|
|
||||||
<el-input
|
|
||||||
v-model="pair.key"
|
|
||||||
placeholder="键"
|
|
||||||
class="key-input"
|
|
||||||
@input="updateKeyValueField(fieldItem.field)"
|
|
||||||
/>
|
|
||||||
<el-input
|
|
||||||
v-model="pair.value"
|
|
||||||
placeholder="值"
|
|
||||||
class="value-input"
|
|
||||||
@input="updateKeyValueField(fieldItem.field)"
|
|
||||||
/>
|
|
||||||
<el-button
|
|
||||||
type="danger"
|
|
||||||
:icon="Delete"
|
|
||||||
circle
|
|
||||||
size="small"
|
|
||||||
@click="removeKeyValuePair(fieldItem.field, pairIndex)"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<el-button
|
<el-button type="primary" link :icon="Plus" @click="addKeyValuePair(fieldItem.field)" class="add-pair-btn">
|
||||||
type="primary"
|
|
||||||
link
|
|
||||||
:icon="Plus"
|
|
||||||
@click="addKeyValuePair(fieldItem.field)"
|
|
||||||
class="add-pair-btn"
|
|
||||||
>
|
|
||||||
添加键值对
|
添加键值对
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -275,7 +235,11 @@
|
|||||||
:show-file-list="false"
|
:show-file-list="false"
|
||||||
class="custom-field-upload"
|
class="custom-field-upload"
|
||||||
>
|
>
|
||||||
<el-button size="small" type="primary" :disabled="customField.type === 'upload' && getCustomFieldFileList(index).length >= 1">
|
<el-button
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
:disabled="customField.type === 'upload' && getCustomFieldFileList(index).length >= 1"
|
||||||
|
>
|
||||||
选择文件
|
选择文件
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
@@ -283,24 +247,14 @@
|
|||||||
<div v-if="getCustomFieldFileList(index).length > 0" class="uploaded-files-list">
|
<div v-if="getCustomFieldFileList(index).length > 0" class="uploaded-files-list">
|
||||||
<div v-for="(uploadedFile, fileIdx) in getCustomFieldFileList(index)" :key="fileIdx" class="uploaded-file-item">
|
<div v-for="(uploadedFile, fileIdx) in getCustomFieldFileList(index)" :key="fileIdx" class="uploaded-file-item">
|
||||||
<span class="file-name">{{ uploadedFile.name }}</span>
|
<span class="file-name">{{ uploadedFile.name }}</span>
|
||||||
<el-button
|
<el-button type="danger" link size="small" @click="removeCustomFieldFile(index, fileIdx, customField.type)">
|
||||||
type="danger"
|
|
||||||
link
|
|
||||||
size="small"
|
|
||||||
@click="removeCustomFieldFile(index, fileIdx, customField.type)"
|
|
||||||
>
|
|
||||||
删除
|
删除
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 非文件上传类型显示默认值输入框 -->
|
<!-- 非文件上传类型显示默认值输入框 -->
|
||||||
<el-input
|
<el-input v-else v-model="customField.value" placeholder="默认值" class="custom-field-value-full" />
|
||||||
v-else
|
|
||||||
v-model="customField.value"
|
|
||||||
placeholder="默认值"
|
|
||||||
class="custom-field-value-full"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<el-button type="primary" link class="w100" @click="addCustomField">+ 添加自定义字段</el-button>
|
<el-button type="primary" link class="w100" @click="addCustomField">+ 添加自定义字段</el-button>
|
||||||
</template>
|
</template>
|
||||||
@@ -1656,7 +1610,7 @@ const handleTreeNodeClick = async (data: TreeNode) => {
|
|||||||
// 后端错误会自动显示
|
// 后端错误会自动显示
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 处理结果节点(title)
|
// 处理结果节点(title)
|
||||||
if (data.nodeType === 'title' && data.workflowId && data.fileUrl) {
|
if (data.nodeType === 'title' && data.workflowId && data.fileUrl) {
|
||||||
// 管理员权限检查:管理员只能编辑,不能进入创作模式
|
// 管理员权限检查:管理员只能编辑,不能进入创作模式
|
||||||
@@ -1785,7 +1739,7 @@ const isJudgeNode = (node: Item) => {
|
|||||||
const isSelectField = (fieldItem: NodeLibraryFormItem) => {
|
const isSelectField = (fieldItem: NodeLibraryFormItem) => {
|
||||||
// 如果字段类型是 select,直接返回 true
|
// 如果字段类型是 select,直接返回 true
|
||||||
if (fieldItem.type === 'select') return true;
|
if (fieldItem.type === 'select') return true;
|
||||||
|
|
||||||
// 兼容旧的硬编码字段
|
// 兼容旧的硬编码字段
|
||||||
return fieldItem.field === 'size' || fieldItem.field === 'resolution';
|
return fieldItem.field === 'size' || fieldItem.field === 'resolution';
|
||||||
};
|
};
|
||||||
@@ -1795,7 +1749,7 @@ const getSelectOptions = (fieldItem: NodeLibraryFormItem) => {
|
|||||||
if (fieldItem.options && Array.isArray(fieldItem.options)) {
|
if (fieldItem.options && Array.isArray(fieldItem.options)) {
|
||||||
return fieldItem.options;
|
return fieldItem.options;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 兼容旧的硬编码选项
|
// 兼容旧的硬编码选项
|
||||||
if (fieldItem.field === 'size') {
|
if (fieldItem.field === 'size') {
|
||||||
return [
|
return [
|
||||||
@@ -1835,15 +1789,13 @@ const handleCustomFieldUpload = async (index: number, file: any, type: string) =
|
|||||||
try {
|
try {
|
||||||
// 上传文件到OSS
|
// 上传文件到OSS
|
||||||
const uploadRes = await uploadFile(file.raw);
|
const uploadRes = await uploadFile(file.raw);
|
||||||
|
|
||||||
// 检查上传是否成功
|
// 检查上传是否成功
|
||||||
if (!uploadRes || !uploadRes.data || !uploadRes.data.fileURL) {
|
if (!uploadRes || !uploadRes.data || !uploadRes.data.fileURL) {
|
||||||
throw new Error('上传失败:未返回文件URL');
|
throw new Error('上传失败:未返回文件URL');
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileUrl = uploadRes.data.fileAddressPrefix
|
const fileUrl = uploadRes.data.fileAddressPrefix ? `${uploadRes.data.fileAddressPrefix}${uploadRes.data.fileURL}` : uploadRes.data.fileURL;
|
||||||
? `${uploadRes.data.fileAddressPrefix}${uploadRes.data.fileURL}`
|
|
||||||
: uploadRes.data.fileURL;
|
|
||||||
|
|
||||||
// 初始化 fileList
|
// 初始化 fileList
|
||||||
if (!field.fileList) {
|
if (!field.fileList) {
|
||||||
@@ -1858,7 +1810,7 @@ const handleCustomFieldUpload = async (index: number, file: any, type: string) =
|
|||||||
} else if (type === 'uploadMultiple') {
|
} else if (type === 'uploadMultiple') {
|
||||||
// 多个上传:添加到数组
|
// 多个上传:添加到数组
|
||||||
field.fileList.push({ name: file.name, url: fileUrl });
|
field.fileList.push({ name: file.name, url: fileUrl });
|
||||||
|
|
||||||
// 解析现有的 value
|
// 解析现有的 value
|
||||||
let urls: string[] = [];
|
let urls: string[] = [];
|
||||||
if (field.value) {
|
if (field.value) {
|
||||||
@@ -1871,7 +1823,7 @@ const handleCustomFieldUpload = async (index: number, file: any, type: string) =
|
|||||||
urls = field.value ? [field.value] : [];
|
urls = field.value ? [field.value] : [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加新的 URL
|
// 添加新的 URL
|
||||||
urls.push(fileUrl);
|
urls.push(fileUrl);
|
||||||
field.value = JSON.stringify(urls);
|
field.value = JSON.stringify(urls);
|
||||||
@@ -1917,39 +1869,40 @@ const removeCustomFieldFile = (index: number, fileIdx: number, type: string) =>
|
|||||||
// 递增 uploadKey 来重置上传组件
|
// 递增 uploadKey 来重置上传组件
|
||||||
field.uploadKey = (field.uploadKey || 0) + 1;
|
field.uploadKey = (field.uploadKey || 0) + 1;
|
||||||
};
|
};
|
||||||
// 获取键值对数组
|
// 获取键值对数组(使用响应式存储)
|
||||||
const getKeyValuePairs = (field: string) => {
|
const getKeyValuePairs = (field: string) => {
|
||||||
const value = dynamicFormValues[field];
|
// 如果还没有初始化,从 dynamicFormValues 中加载
|
||||||
if (!value) {
|
if (!fieldKeyValuePairs[field]) {
|
||||||
return [{ key: '', value: '' }];
|
const value = dynamicFormValues[field];
|
||||||
}
|
|
||||||
|
if (!value) {
|
||||||
// 如果是字符串,尝试解析为JSON对象
|
fieldKeyValuePairs[field] = [{ key: '', value: '' }];
|
||||||
if (typeof value === 'string') {
|
} else if (typeof value === 'string') {
|
||||||
try {
|
try {
|
||||||
const parsed = JSON.parse(value);
|
const parsed = JSON.parse(value);
|
||||||
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
|
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
|
||||||
return Object.entries(parsed).map(([k, v]) => ({ key: k, value: String(v) }));
|
fieldKeyValuePairs[field] = Object.entries(parsed).map(([k, v]) => ({ key: k, value: String(v) }));
|
||||||
|
} else {
|
||||||
|
fieldKeyValuePairs[field] = [{ key: '', value: '' }];
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
fieldKeyValuePairs[field] = [{ key: '', value: '' }];
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} else if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
||||||
// 解析失败,返回空数组
|
const pairs = Object.entries(value).map(([k, v]) => ({ key: k, value: String(v) }));
|
||||||
|
fieldKeyValuePairs[field] = pairs.length > 0 ? pairs : [{ key: '', value: '' }];
|
||||||
|
} else {
|
||||||
|
fieldKeyValuePairs[field] = [{ key: '', value: '' }];
|
||||||
}
|
}
|
||||||
return [{ key: '', value: '' }];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果是对象,转换为键值对数组
|
return fieldKeyValuePairs[field];
|
||||||
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
|
|
||||||
const pairs = Object.entries(value).map(([k, v]) => ({ key: k, value: String(v) }));
|
|
||||||
return pairs.length > 0 ? pairs : [{ key: '', value: '' }];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [{ key: '', value: '' }];
|
|
||||||
};
|
};
|
||||||
// 添加键值对
|
// 添加键值对
|
||||||
const addKeyValuePair = (field: string) => {
|
const addKeyValuePair = (field: string) => {
|
||||||
const pairs = getKeyValuePairs(field);
|
const pairs = getKeyValuePairs(field);
|
||||||
pairs.push({ key: '', value: '' });
|
pairs.push({ key: '', value: '' });
|
||||||
updateKeyValueFieldFromPairs(field, pairs);
|
updateKeyValueFieldFromPairs(field);
|
||||||
};
|
};
|
||||||
// 删除键值对
|
// 删除键值对
|
||||||
const removeKeyValuePair = (field: string, index: number) => {
|
const removeKeyValuePair = (field: string, index: number) => {
|
||||||
@@ -1959,26 +1912,28 @@ const removeKeyValuePair = (field: string, index: number) => {
|
|||||||
if (pairs.length === 0) {
|
if (pairs.length === 0) {
|
||||||
pairs.push({ key: '', value: '' });
|
pairs.push({ key: '', value: '' });
|
||||||
}
|
}
|
||||||
updateKeyValueFieldFromPairs(field, pairs);
|
updateKeyValueFieldFromPairs(field);
|
||||||
};
|
};
|
||||||
// 更新键值对字段
|
// 更新键值对字段
|
||||||
const updateKeyValueField = (field: string) => {
|
const updateKeyValueField = (field: string) => {
|
||||||
const pairs = getKeyValuePairs(field);
|
updateKeyValueFieldFromPairs(field);
|
||||||
updateKeyValueFieldFromPairs(field, pairs);
|
|
||||||
};
|
};
|
||||||
// 从键值对数组更新字段值
|
// 从键值对数组更新字段值
|
||||||
const updateKeyValueFieldFromPairs = (field: string, pairs: Array<{ key: string; value: string }>) => {
|
const updateKeyValueFieldFromPairs = (field: string) => {
|
||||||
|
const pairs = fieldKeyValuePairs[field];
|
||||||
|
if (!pairs) return;
|
||||||
|
|
||||||
// 过滤掉空的键值对
|
// 过滤掉空的键值对
|
||||||
const validPairs = pairs.filter(p => p.key.trim() !== '');
|
const validPairs = pairs.filter((p) => p.key.trim() !== '');
|
||||||
|
|
||||||
// 转换为对象
|
// 转换为对象
|
||||||
const obj: Record<string, string> = {};
|
const obj: Record<string, string> = {};
|
||||||
validPairs.forEach(p => {
|
validPairs.forEach((p) => {
|
||||||
if (p.key.trim()) {
|
if (p.key.trim()) {
|
||||||
obj[p.key.trim()] = p.value;
|
obj[p.key.trim()] = p.value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// 保存为JSON字符串
|
// 保存为JSON字符串
|
||||||
dynamicFormValues[field] = Object.keys(obj).length > 0 ? JSON.stringify(obj) : '';
|
dynamicFormValues[field] = Object.keys(obj).length > 0 ? JSON.stringify(obj) : '';
|
||||||
};
|
};
|
||||||
@@ -1986,6 +1941,8 @@ const updateKeyValueFieldFromPairs = (field: string, pairs: Array<{ key: string;
|
|||||||
const fieldFileLists = reactive<Record<string, any[]>>({});
|
const fieldFileLists = reactive<Record<string, any[]>>({});
|
||||||
// 存储字段的上传key(用于重置上传组件)
|
// 存储字段的上传key(用于重置上传组件)
|
||||||
const fieldUploadKeys = reactive<Record<string, number>>({});
|
const fieldUploadKeys = reactive<Record<string, number>>({});
|
||||||
|
// 存储字段的键值对(用于响应式更新)
|
||||||
|
const fieldKeyValuePairs = reactive<Record<string, Array<{ key: string; value: string }>>>({});
|
||||||
// 获取字段的文件列表
|
// 获取字段的文件列表
|
||||||
const getFieldFileList = (field: string) => {
|
const getFieldFileList = (field: string) => {
|
||||||
return fieldFileLists[field] || [];
|
return fieldFileLists[field] || [];
|
||||||
@@ -1999,15 +1956,13 @@ const handleFieldUpload = async (field: string, file: any, type: string) => {
|
|||||||
try {
|
try {
|
||||||
// 上传文件到OSS
|
// 上传文件到OSS
|
||||||
const uploadRes = await uploadFile(file.raw);
|
const uploadRes = await uploadFile(file.raw);
|
||||||
|
|
||||||
// 检查上传是否成功
|
// 检查上传是否成功
|
||||||
if (!uploadRes || !uploadRes.data || !uploadRes.data.fileURL) {
|
if (!uploadRes || !uploadRes.data || !uploadRes.data.fileURL) {
|
||||||
throw new Error('上传失败:未返回文件URL');
|
throw new Error('上传失败:未返回文件URL');
|
||||||
}
|
}
|
||||||
|
|
||||||
const fileUrl = uploadRes.data.fileAddressPrefix
|
const fileUrl = uploadRes.data.fileAddressPrefix ? `${uploadRes.data.fileAddressPrefix}${uploadRes.data.fileURL}` : uploadRes.data.fileURL;
|
||||||
? `${uploadRes.data.fileAddressPrefix}${uploadRes.data.fileURL}`
|
|
||||||
: uploadRes.data.fileURL;
|
|
||||||
|
|
||||||
// 初始化文件列表
|
// 初始化文件列表
|
||||||
if (!fieldFileLists[field]) {
|
if (!fieldFileLists[field]) {
|
||||||
@@ -2022,7 +1977,7 @@ const handleFieldUpload = async (field: string, file: any, type: string) => {
|
|||||||
} else if (type === 'uploadMultiple') {
|
} else if (type === 'uploadMultiple') {
|
||||||
// 多个上传:添加到数组
|
// 多个上传:添加到数组
|
||||||
fieldFileLists[field].push({ name: file.name, url: fileUrl });
|
fieldFileLists[field].push({ name: file.name, url: fileUrl });
|
||||||
|
|
||||||
// 解析现有的 value
|
// 解析现有的 value
|
||||||
let urls: string[] = [];
|
let urls: string[] = [];
|
||||||
if (dynamicFormValues[field]) {
|
if (dynamicFormValues[field]) {
|
||||||
@@ -2035,7 +1990,7 @@ const handleFieldUpload = async (field: string, file: any, type: string) => {
|
|||||||
urls = dynamicFormValues[field] ? [dynamicFormValues[field]] : [];
|
urls = dynamicFormValues[field] ? [dynamicFormValues[field]] : [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 添加新的 URL
|
// 添加新的 URL
|
||||||
urls.push(fileUrl);
|
urls.push(fileUrl);
|
||||||
dynamicFormValues[field] = JSON.stringify(urls);
|
dynamicFormValues[field] = JSON.stringify(urls);
|
||||||
@@ -3007,7 +2962,7 @@ onBeforeUnmount(() => {
|
|||||||
.creation-page {
|
.creation-page {
|
||||||
height: calc(100vh - 100px);
|
height: calc(100vh - 100px);
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 320px minmax(0, 1fr) 340px;
|
grid-template-columns: 360px minmax(0, 1fr) 360px;
|
||||||
gap: 14px;
|
gap: 14px;
|
||||||
padding: 14px;
|
padding: 14px;
|
||||||
background: #f6f8fb;
|
background: #f6f8fb;
|
||||||
|
|||||||
Reference in New Issue
Block a user