增加单个上传和多个上传
This commit is contained in:
@@ -95,6 +95,64 @@
|
||||
/>
|
||||
<!-- 开关 -->
|
||||
<el-switch v-else-if="fieldItem.type === 'switch'" v-model="dynamicFormValues[fieldItem.field]" />
|
||||
<!-- 单个文件上传 -->
|
||||
<div v-else-if="fieldItem.type === 'upload'" class="field-upload-wrapper">
|
||||
<el-upload
|
||||
:key="`field-upload-${fieldItem.field}-${getFieldUploadKey(fieldItem.field)}`"
|
||||
:auto-upload="false"
|
||||
:on-change="(file: any) => handleFieldUpload(fieldItem.field, file, 'upload')"
|
||||
:file-list="[]"
|
||||
:limit="1"
|
||||
:show-file-list="false"
|
||||
class="field-upload"
|
||||
>
|
||||
<el-button size="small" type="primary" :disabled="getFieldFileList(fieldItem.field).length >= 1">
|
||||
选择文件
|
||||
</el-button>
|
||||
</el-upload>
|
||||
<!-- 手动显示已上传成功的文件列表 -->
|
||||
<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">
|
||||
<span class="file-name">{{ uploadedFile.name }}</span>
|
||||
<el-button
|
||||
type="danger"
|
||||
link
|
||||
size="small"
|
||||
@click="removeFieldFile(fieldItem.field, fileIdx, 'upload')"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 多个文件上传 -->
|
||||
<div v-else-if="fieldItem.type === 'uploadMultiple'" class="field-upload-wrapper">
|
||||
<el-upload
|
||||
:key="`field-upload-${fieldItem.field}-${getFieldUploadKey(fieldItem.field)}`"
|
||||
:auto-upload="false"
|
||||
:multiple="true"
|
||||
:on-change="(file: any) => handleFieldUpload(fieldItem.field, file, 'uploadMultiple')"
|
||||
:file-list="[]"
|
||||
:show-file-list="false"
|
||||
class="field-upload"
|
||||
>
|
||||
<el-button size="small" type="primary">选择文件</el-button>
|
||||
</el-upload>
|
||||
<!-- 手动显示已上传成功的文件列表 -->
|
||||
<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">
|
||||
<span class="file-name">{{ uploadedFile.name }}</span>
|
||||
<el-button
|
||||
type="danger"
|
||||
link
|
||||
size="small"
|
||||
@click="removeFieldFile(fieldItem.field, fileIdx, 'uploadMultiple')"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 键值对输入(HTTP节点的headers和body) -->
|
||||
<div v-else-if="fieldItem.type === 'keyValue'" class="key-value-input-wrapper">
|
||||
<div
|
||||
@@ -199,11 +257,50 @@
|
||||
<el-option label="数字" value="number" />
|
||||
<el-option label="多行文本" value="textarea" />
|
||||
<el-option label="开关" value="switch" />
|
||||
<el-option label="单个上传" value="upload" />
|
||||
<el-option label="多个上传" value="uploadMultiple" />
|
||||
</el-select>
|
||||
<el-checkbox v-model="customField.required" class="custom-field-required">必填</el-checkbox>
|
||||
<el-button type="danger" link @click="removeCustomField(index)">删除</el-button>
|
||||
</div>
|
||||
<el-input v-model="customField.value" placeholder="默认值" class="custom-field-value-full" />
|
||||
<!-- 文件上传类型显示上传组件 -->
|
||||
<div v-if="customField.type === 'upload' || customField.type === 'uploadMultiple'" class="custom-field-upload-wrapper">
|
||||
<el-upload
|
||||
:key="`custom-upload-${index}-${customField.uploadKey || 0}`"
|
||||
:auto-upload="false"
|
||||
:multiple="customField.type === 'uploadMultiple'"
|
||||
:on-change="(file: any) => handleCustomFieldUpload(index, file, customField.type)"
|
||||
:file-list="[]"
|
||||
:limit="customField.type === 'upload' ? 1 : undefined"
|
||||
:show-file-list="false"
|
||||
class="custom-field-upload"
|
||||
>
|
||||
<el-button size="small" type="primary" :disabled="customField.type === 'upload' && getCustomFieldFileList(index).length >= 1">
|
||||
选择文件
|
||||
</el-button>
|
||||
</el-upload>
|
||||
<!-- 手动显示已上传成功的文件列表 -->
|
||||
<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">
|
||||
<span class="file-name">{{ uploadedFile.name }}</span>
|
||||
<el-button
|
||||
type="danger"
|
||||
link
|
||||
size="small"
|
||||
@click="removeCustomFieldFile(index, fileIdx, customField.type)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 非文件上传类型显示默认值输入框 -->
|
||||
<el-input
|
||||
v-else
|
||||
v-model="customField.value"
|
||||
placeholder="默认值"
|
||||
class="custom-field-value-full"
|
||||
/>
|
||||
</div>
|
||||
<el-button type="primary" link class="w100" @click="addCustomField">+ 添加自定义字段</el-button>
|
||||
</template>
|
||||
@@ -1718,12 +1815,108 @@ const getSelectOptions = (fieldItem: NodeLibraryFormItem) => {
|
||||
};
|
||||
// 添加自定义字段
|
||||
const addCustomField = () => {
|
||||
customFields.value.push({ label: '', value: '', type: 'input', required: false });
|
||||
customFields.value.push({ label: '', value: '', type: 'input', required: false, fileList: [], uploadKey: 0 });
|
||||
};
|
||||
// 删除自定义字段
|
||||
const removeCustomField = (index: number) => {
|
||||
customFields.value.splice(index, 1);
|
||||
};
|
||||
// 获取自定义字段的文件列表
|
||||
const getCustomFieldFileList = (index: number) => {
|
||||
const field = customFields.value[index];
|
||||
if (!field || !field.fileList) return [];
|
||||
return field.fileList;
|
||||
};
|
||||
// 处理自定义字段文件上传
|
||||
const handleCustomFieldUpload = async (index: number, file: any, type: string) => {
|
||||
const field = customFields.value[index];
|
||||
if (!field) return;
|
||||
|
||||
try {
|
||||
// 上传文件到OSS
|
||||
const uploadRes = await uploadFile(file.raw);
|
||||
|
||||
// 检查上传是否成功
|
||||
if (!uploadRes || !uploadRes.data || !uploadRes.data.fileURL) {
|
||||
throw new Error('上传失败:未返回文件URL');
|
||||
}
|
||||
|
||||
const fileUrl = uploadRes.data.fileAddressPrefix
|
||||
? `${uploadRes.data.fileAddressPrefix}${uploadRes.data.fileURL}`
|
||||
: uploadRes.data.fileURL;
|
||||
|
||||
// 初始化 fileList
|
||||
if (!field.fileList) {
|
||||
field.fileList = [];
|
||||
}
|
||||
|
||||
// 根据类型处理
|
||||
if (type === 'upload') {
|
||||
// 单个上传:替换现有文件
|
||||
field.fileList = [{ name: file.name, url: fileUrl }];
|
||||
field.value = fileUrl;
|
||||
} else if (type === 'uploadMultiple') {
|
||||
// 多个上传:添加到数组
|
||||
field.fileList.push({ name: file.name, url: fileUrl });
|
||||
|
||||
// 解析现有的 value
|
||||
let urls: string[] = [];
|
||||
if (field.value) {
|
||||
try {
|
||||
urls = JSON.parse(field.value);
|
||||
if (!Array.isArray(urls)) {
|
||||
urls = [field.value];
|
||||
}
|
||||
} catch (e) {
|
||||
urls = field.value ? [field.value] : [];
|
||||
}
|
||||
}
|
||||
|
||||
// 添加新的 URL
|
||||
urls.push(fileUrl);
|
||||
field.value = JSON.stringify(urls);
|
||||
}
|
||||
|
||||
ElMessage.success('文件上传成功');
|
||||
} catch (error: any) {
|
||||
ElMessage.error(error?.message || '文件上传失败');
|
||||
console.error('Upload error:', error);
|
||||
// 上传失败时,递增 uploadKey 来重置上传组件
|
||||
field.uploadKey = (field.uploadKey || 0) + 1;
|
||||
}
|
||||
};
|
||||
// 删除自定义字段的文件
|
||||
const removeCustomFieldFile = (index: number, fileIdx: number, type: string) => {
|
||||
const field = customFields.value[index];
|
||||
if (!field || !field.fileList) return;
|
||||
|
||||
// 删除文件
|
||||
field.fileList.splice(fileIdx, 1);
|
||||
|
||||
// 更新 value
|
||||
if (type === 'upload') {
|
||||
// 单个上传:清空 value
|
||||
field.value = '';
|
||||
} else if (type === 'uploadMultiple') {
|
||||
// 多个上传:从数组中删除对应的 URL
|
||||
try {
|
||||
let urls: string[] = [];
|
||||
if (field.value) {
|
||||
urls = JSON.parse(field.value);
|
||||
if (!Array.isArray(urls)) {
|
||||
urls = [];
|
||||
}
|
||||
}
|
||||
urls.splice(fileIdx, 1);
|
||||
field.value = urls.length > 0 ? JSON.stringify(urls) : '';
|
||||
} catch (e) {
|
||||
field.value = '';
|
||||
}
|
||||
}
|
||||
|
||||
// 递增 uploadKey 来重置上传组件
|
||||
field.uploadKey = (field.uploadKey || 0) + 1;
|
||||
};
|
||||
// 获取键值对数组
|
||||
const getKeyValuePairs = (field: string) => {
|
||||
const value = dynamicFormValues[field];
|
||||
@@ -1789,6 +1982,104 @@ const updateKeyValueFieldFromPairs = (field: string, pairs: Array<{ key: string;
|
||||
// 保存为JSON字符串
|
||||
dynamicFormValues[field] = Object.keys(obj).length > 0 ? JSON.stringify(obj) : '';
|
||||
};
|
||||
// 存储字段的文件列表
|
||||
const fieldFileLists = reactive<Record<string, any[]>>({});
|
||||
// 存储字段的上传key(用于重置上传组件)
|
||||
const fieldUploadKeys = reactive<Record<string, number>>({});
|
||||
// 获取字段的文件列表
|
||||
const getFieldFileList = (field: string) => {
|
||||
return fieldFileLists[field] || [];
|
||||
};
|
||||
// 获取字段的上传key
|
||||
const getFieldUploadKey = (field: string) => {
|
||||
return fieldUploadKeys[field] || 0;
|
||||
};
|
||||
// 处理字段文件上传
|
||||
const handleFieldUpload = async (field: string, file: any, type: string) => {
|
||||
try {
|
||||
// 上传文件到OSS
|
||||
const uploadRes = await uploadFile(file.raw);
|
||||
|
||||
// 检查上传是否成功
|
||||
if (!uploadRes || !uploadRes.data || !uploadRes.data.fileURL) {
|
||||
throw new Error('上传失败:未返回文件URL');
|
||||
}
|
||||
|
||||
const fileUrl = uploadRes.data.fileAddressPrefix
|
||||
? `${uploadRes.data.fileAddressPrefix}${uploadRes.data.fileURL}`
|
||||
: uploadRes.data.fileURL;
|
||||
|
||||
// 初始化文件列表
|
||||
if (!fieldFileLists[field]) {
|
||||
fieldFileLists[field] = [];
|
||||
}
|
||||
|
||||
// 根据类型处理
|
||||
if (type === 'upload') {
|
||||
// 单个上传:替换现有文件
|
||||
fieldFileLists[field] = [{ name: file.name, url: fileUrl }];
|
||||
dynamicFormValues[field] = fileUrl;
|
||||
} else if (type === 'uploadMultiple') {
|
||||
// 多个上传:添加到数组
|
||||
fieldFileLists[field].push({ name: file.name, url: fileUrl });
|
||||
|
||||
// 解析现有的 value
|
||||
let urls: string[] = [];
|
||||
if (dynamicFormValues[field]) {
|
||||
try {
|
||||
urls = JSON.parse(dynamicFormValues[field]);
|
||||
if (!Array.isArray(urls)) {
|
||||
urls = [dynamicFormValues[field]];
|
||||
}
|
||||
} catch (e) {
|
||||
urls = dynamicFormValues[field] ? [dynamicFormValues[field]] : [];
|
||||
}
|
||||
}
|
||||
|
||||
// 添加新的 URL
|
||||
urls.push(fileUrl);
|
||||
dynamicFormValues[field] = JSON.stringify(urls);
|
||||
}
|
||||
|
||||
ElMessage.success('文件上传成功');
|
||||
} catch (error: any) {
|
||||
ElMessage.error(error?.message || '文件上传失败');
|
||||
console.error('Upload error:', error);
|
||||
// 上传失败时,递增 uploadKey 来重置上传组件
|
||||
fieldUploadKeys[field] = (fieldUploadKeys[field] || 0) + 1;
|
||||
}
|
||||
};
|
||||
// 删除字段的文件
|
||||
const removeFieldFile = (field: string, fileIdx: number, type: string) => {
|
||||
if (!fieldFileLists[field]) return;
|
||||
|
||||
// 删除文件
|
||||
fieldFileLists[field].splice(fileIdx, 1);
|
||||
|
||||
// 更新 value
|
||||
if (type === 'upload') {
|
||||
// 单个上传:清空 value
|
||||
dynamicFormValues[field] = '';
|
||||
} else if (type === 'uploadMultiple') {
|
||||
// 多个上传:从数组中删除对应的 URL
|
||||
try {
|
||||
let urls: string[] = [];
|
||||
if (dynamicFormValues[field]) {
|
||||
urls = JSON.parse(dynamicFormValues[field]);
|
||||
if (!Array.isArray(urls)) {
|
||||
urls = [];
|
||||
}
|
||||
}
|
||||
urls.splice(fileIdx, 1);
|
||||
dynamicFormValues[field] = urls.length > 0 ? JSON.stringify(urls) : '';
|
||||
} catch (e) {
|
||||
dynamicFormValues[field] = '';
|
||||
}
|
||||
}
|
||||
|
||||
// 递增 uploadKey 来重置上传组件
|
||||
fieldUploadKeys[field] = (fieldUploadKeys[field] || 0) + 1;
|
||||
};
|
||||
// 判断是否可以添加自定义字段(排除判断节点、开始节点、HTTP节点等)
|
||||
const canAddCustomFields = (element: SelectedState | null) => {
|
||||
if (!element || element.kind !== 'node') return false;
|
||||
@@ -3149,6 +3440,44 @@ onBeforeUnmount(() => {
|
||||
align-self: flex-start;
|
||||
margin-top: 4px;
|
||||
}
|
||||
.custom-field-upload-wrapper,
|
||||
.field-upload-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
.uploaded-files-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
padding: 8px;
|
||||
background: #f9fafb;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 6px;
|
||||
}
|
||||
.uploaded-file-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 6px 10px;
|
||||
background: #fff;
|
||||
border: 1px solid #e5e7eb;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.uploaded-file-item:hover {
|
||||
border-color: #cbd5e1;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.uploaded-file-item .file-name {
|
||||
flex: 1;
|
||||
font-size: 13px;
|
||||
color: #374151;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
margin-right: 12px;
|
||||
}
|
||||
.input-source-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
Reference in New Issue
Block a user