将主图、图片列表和属性图片的上传方式从手动上传改为自动上传,使用http-request自定义上传处理

This commit is contained in:
WUSIJIAN
2025-12-25 17:55:52 +08:00
parent 73373ad7a1
commit 559bc4f6f1
2 changed files with 64 additions and 52 deletions

View File

@@ -76,7 +76,7 @@ export function uploadAssetImage(file: File) {
const formData = new FormData(); const formData = new FormData();
formData.append('file', file); formData.append('file', file);
return newService({ return newService({
url: '/assets/asset/Uploadimage', url: '/assets/asset/uploadImage',
method: 'post', method: 'post',
data: formData, data: formData,
headers: { headers: {

View File

@@ -135,9 +135,9 @@
<el-upload <el-upload
class="attr-image-uploader" class="attr-image-uploader"
:show-file-list="false" :show-file-list="false"
:auto-upload="false" :auto-upload="true"
accept="image/*" accept="image/*"
:on-change="onAttrImageChange(attr)" :http-request="onAttrImageUpload(attr)"
> >
<img <img
v-if="ruleForm.metadata[getAttrKey(attr)]" v-if="ruleForm.metadata[getAttrKey(attr)]"
@@ -172,8 +172,8 @@
<el-upload <el-upload
class="avatar-uploader" class="avatar-uploader"
:show-file-list="false" :show-file-list="false"
:auto-upload="false" :auto-upload="true"
:on-change="handleMainImageChange" :http-request="handleMainImageUpload"
accept="image/*" accept="image/*"
> >
<img v-if="mainImagePreview" :src="mainImagePreview" class="avatar" /> <img v-if="mainImagePreview" :src="mainImagePreview" class="avatar" />
@@ -191,7 +191,8 @@
<el-upload <el-upload
v-model:file-list="imageFileList" v-model:file-list="imageFileList"
list-type="picture-card" list-type="picture-card"
:auto-upload="false" :auto-upload="true"
:http-request="handleImageListUpload"
:on-preview="handlePictureCardPreview" :on-preview="handlePictureCardPreview"
:on-remove="handleRemove" :on-remove="handleRemove"
accept="image/*" accept="image/*"
@@ -445,7 +446,7 @@ import { Plus, Delete } from '@element-plus/icons-vue';
import { getAsset, createAsset, updateAsset, uploadAssetImage } from '/@/api/assets/asset'; import { getAsset, createAsset, updateAsset, uploadAssetImage } from '/@/api/assets/asset';
import { getCategoryTree, getCategory } from '/@/api/assets/category'; import { getCategoryTree, getCategory } from '/@/api/assets/category';
import Editor from '/@/components/editor/index.vue'; import Editor from '/@/components/editor/index.vue';
import type { UploadFile, UploadUserFile } from 'element-plus'; import type { UploadFile, UploadUserFile, UploadRequestOptions } from 'element-plus';
// 类型定义 // 类型定义
interface TimeSlot { interface TimeSlot {
@@ -547,10 +548,8 @@ const getAttrLabel = (attr: CategoryAttr): string => {
}; };
// 图片相关 // 图片相关
const mainImageFile = ref<File | null>(null);
const mainImagePreview = ref(''); const mainImagePreview = ref('');
const imageFileList = ref<UploadUserFile[]>([]); const imageFileList = ref<UploadUserFile[]>([]);
const attrImageFiles = ref<Record<string, File>>({}); // 暂存属性图片文件
const dialogVisible = ref(false); const dialogVisible = ref(false);
const dialogImageUrl = ref(''); const dialogImageUrl = ref('');
// 图片拼接 // 图片拼接
@@ -674,15 +673,56 @@ const rules: FormRules = {
}; };
// 主图上传处理 // 主图上传处理
const handleMainImageChange = (file: UploadFile) => { const handleMainImageUpload = async (options: UploadRequestOptions) => {
if (file.raw) { try {
mainImageFile.value = file.raw; const url = await uploadImage(options.file);
mainImagePreview.value = URL.createObjectURL(file.raw); if (url) {
ruleForm.mainImage = 'set'; // 标记已上传 ruleForm.mainImage = url;
formRef.value?.validateField('mainImage'); mainImagePreview.value = formatImageUrl(url);
formRef.value?.validateField('mainImage');
}
} catch (error) {
ElMessage.error('主图上传失败');
} }
}; };
// 图片列表上传处理
const handleImageListUpload = async (options: UploadRequestOptions) => {
try {
const url = await uploadImage(options.file);
if (url) {
const fileItem = imageFileList.value.find((f) => f.uid === options.file.uid);
if (fileItem) {
fileItem.url = formatImageUrl(url);
fileItem.status = 'success';
fileItem.response = url; // 存储原始 URL
}
}
} catch (error) {
ElMessage.error('上传失败');
const index = imageFileList.value.findIndex((f) => f.uid === options.file.uid);
if (index !== -1) {
imageFileList.value.splice(index, 1);
}
}
};
// 属性图片上传处理
const onAttrImageUpload = (attr: CategoryAttr) => {
return async (options: UploadRequestOptions) => {
try {
const url = await uploadImage(options.file);
if (url) {
const key = getAttrKey(attr);
ruleForm.metadata[key] = url;
formRef.value?.validateField(`metadata.${key}`);
}
} catch (error) {
ElMessage.error('图片上传失败');
}
};
};
// 主图预览 // 主图预览
const previewMainImage = () => { const previewMainImage = () => {
if (mainImagePreview.value) { if (mainImagePreview.value) {
@@ -693,7 +733,6 @@ const previewMainImage = () => {
// 主图删除 // 主图删除
const removeMainImage = () => { const removeMainImage = () => {
mainImageFile.value = null;
mainImagePreview.value = ''; mainImagePreview.value = '';
ruleForm.mainImage = ''; ruleForm.mainImage = '';
formRef.value?.validateField('mainImage'); formRef.value?.validateField('mainImage');
@@ -701,8 +740,6 @@ const removeMainImage = () => {
// 图片列表预览 // 图片列表预览
const handlePictureCardPreview = (file: UploadFile) => { const handlePictureCardPreview = (file: UploadFile) => {
console.log(file,'111');
dialogImageUrl.value = file.url || ''; dialogImageUrl.value = file.url || '';
dialogVisible.value = true; dialogVisible.value = true;
}; };
@@ -715,29 +752,10 @@ const handleRemove = (file: UploadFile) => {
} }
}; };
// 属性图片上传处理
const handleAttrImageChange = (file: UploadFile, attr: CategoryAttr) => {
if (file.raw) {
const key = getAttrKey(attr);
const url = URL.createObjectURL(file.raw);
ruleForm.metadata[key] = url;
attrImageFiles.value[key] = file.raw;
formRef.value?.validateField(`metadata.${key}`);
}
};
// 生成属性图片上传回调
const onAttrImageChange = (attr: CategoryAttr) => {
return (file: UploadFile) => handleAttrImageChange(file, attr);
};
// 移除属性图片 // 移除属性图片
const removeAttrImage = (attr: CategoryAttr) => { const removeAttrImage = (attr: CategoryAttr) => {
const key = getAttrKey(attr); const key = getAttrKey(attr);
ruleForm.metadata[key] = ''; ruleForm.metadata[key] = '';
if (attrImageFiles.value[key]) {
delete attrImageFiles.value[key];
}
formRef.value?.validateField(`metadata.${key}`); formRef.value?.validateField(`metadata.${key}`);
}; };
@@ -806,10 +824,8 @@ const removeKeyValuePair = (list: KeyValuePair[], index: number) => {
const resetForm = () => { const resetForm = () => {
const initial = getInitialForm(); const initial = getInitialForm();
Object.assign(ruleForm, initial); Object.assign(ruleForm, initial);
mainImageFile.value = null;
mainImagePreview.value = ''; mainImagePreview.value = '';
imageFileList.value = []; imageFileList.value = [];
attrImageFiles.value = {};
categoryAttrs.value = []; categoryAttrs.value = [];
imgAddressPrefix.value = ''; imgAddressPrefix.value = '';
}; };
@@ -1048,21 +1064,19 @@ const buildRequestBody = async (): Promise<any> => {
body.offlineTime = ruleForm.offlineTime; body.offlineTime = ruleForm.offlineTime;
} }
// 主图上传 // 主图 (已在上传时直接赋值给 ruleForm.mainImage)
if (mainImageFile.value) { if (ruleForm.mainImage) {
body.imageUrl = await uploadImage(mainImageFile.value);
} else if (ruleForm.mainImage && !ruleForm.mainImage.startsWith('blob:')) {
body.imageUrl = ruleForm.mainImage; body.imageUrl = ruleForm.mainImage;
} }
// 图片列表上传 // 图片列表
const imageUrls: string[] = []; const imageUrls: string[] = [];
for (const file of imageFileList.value) { for (const file of imageFileList.value) {
if (file.raw) { if (file.response) {
const url = await uploadImage(file.raw); // 新上传的图片使用原始 URL
if (url) imageUrls.push(url); imageUrls.push(file.response as string);
} else if (file.url && !file.url.startsWith('blob:')) { } else if (file.url && !file.url.startsWith('blob:')) {
// 已有图片保留原URL // 已有图片保留原 URL
imageUrls.push(file.url); imageUrls.push(file.url);
} }
} }
@@ -1108,10 +1122,8 @@ const buildRequestBody = async (): Promise<any> => {
const key = getAttrKey(attr); const key = getAttrKey(attr);
let value = ruleForm.metadata[key]; let value = ruleForm.metadata[key];
// 如果是图片类型且有文件需要上传 // 如果是图片类型,且值是 blob 开头(未上传成功的情况),置为空
if (attr.type === 'image' && attrImageFiles.value[key]) { if (attr.type === 'image' && typeof value === 'string' && value.startsWith('blob:')) {
value = await uploadImage(attrImageFiles.value[key]);
} else if (typeof value === 'string' && value.startsWith('blob:')) {
value = ''; value = '';
} }