Kaynağa Gözat

fix: 修改上传图片参数

sgc 1 gün önce
ebeveyn
işleme
50c4bb7506

+ 121 - 3
src/api/upload.js

@@ -175,6 +175,40 @@ function deepFindHttpUrl(val, depth = 0, maxDepth = 8) {
 }
 
 /**
+ * 递归查找上传接口返回的 `download_url` / `downloadUrl`(后台保存相册等常以该字段为 imgUrl)
+ * @param {unknown} val
+ * @param {number} depth
+ * @param {number} maxDepth
+ * @returns {string}
+ */
+function preferDownloadUrlFromBody(val, depth = 0, maxDepth = 10) {
+  if (depth > maxDepth || val == null) return "";
+  if (Array.isArray(val)) {
+    for (const item of val) {
+      const u = preferDownloadUrlFromBody(item, depth + 1, maxDepth);
+      if (u) return u;
+    }
+    return "";
+  }
+  if (typeof val !== "object") return "";
+  const o = /** @type {Record<string, unknown>} */ (val);
+  for (const k of ["download_url", "downloadUrl"]) {
+    const v = o[k];
+    if (typeof v === "string" && v.trim()) {
+      const t = v.trim();
+      const abs = normalizeToFileUrl(t);
+      if (abs) return abs;
+      if (/^https?:\/\//i.test(t)) return t;
+    }
+  }
+  for (const v of Object.values(o)) {
+    const u = preferDownloadUrlFromBody(v, depth + 1, maxDepth);
+    if (u) return u;
+  }
+  return "";
+}
+
+/**
  * 从 JSON 体中解析文件访问地址(兼容多种后端约定)
  * @param {unknown} body
  * @returns {string}
@@ -186,6 +220,17 @@ function pickUrlFromJsonBody(body) {
     return normalizeToFileUrl(body) || (body.trim().startsWith("http") ? body.trim() : "");
   }
 
+  if (typeof body === "object" && !Array.isArray(body)) {
+    const dUrl = preferDownloadUrlFromBody(body);
+    if (dUrl) return dUrl;
+  }
+
+  if (Array.isArray(body)) {
+    const dUrl = preferDownloadUrlFromBody(body);
+    if (dUrl) return dUrl;
+    return deepFindHttpUrl(body);
+  }
+
   if (typeof body !== "object" || Array.isArray(body)) {
     return deepFindHttpUrl(body);
   }
@@ -338,12 +383,12 @@ function assertSimpleUploadBusinessOk(parsed) {
 }
 
 /**
- * POST multipart:字段 file;可选 filename(此处不传则服务端用原名)
+ * POST multipart:字段 file;解析展示用地址与业务保存用的 download_url
  * @param {File} file
  * @param {{ signal?: AbortSignal }} [fetchOptions]
- * @returns {Promise<string>} 文件访问 URL
+ * @returns {Promise<{ url: string; downloadUrl: string; parsed: unknown }>}
  */
-async function postFileToSimpleUpload(file, fetchOptions = {}) {
+async function postFileToSimpleUploadDetailed(file, fetchOptions = {}) {
   const base = String(BASE_AI_URL || "").replace(/\/$/, "");
   if (!base) {
     throw new Error("未配置上传服务地址(VITE_AI_UPLOAD_BASE 或默认 /ai-upload)");
@@ -416,6 +461,8 @@ async function postFileToSimpleUpload(file, fetchOptions = {}) {
     throw new Error(moderationUserTip);
   }
 
+  const downloadUrl = (preferDownloadUrlFromBody(parsed) || "").trim();
+
   let url = pickUrlFromJsonBody(parsed);
   if (!url && trimmed.startsWith("http")) {
     url = trimmed;
@@ -442,6 +489,17 @@ async function postFileToSimpleUpload(file, fetchOptions = {}) {
     console.error("[upload/simple] 无法解析文件地址,响应片段:", trimmed.slice(0, 800));
     throw new Error("上传失败,未返回文件地址");
   }
+  return { url, downloadUrl, parsed };
+}
+
+/**
+ * POST multipart:字段 file;可选 filename(此处不传则服务端用原名)
+ * @param {File} file
+ * @param {{ signal?: AbortSignal }} [fetchOptions]
+ * @returns {Promise<string>} 文件访问 URL
+ */
+async function postFileToSimpleUpload(file, fetchOptions = {}) {
+  const { url } = await postFileToSimpleUploadDetailed(file, fetchOptions);
   return url;
 }
 
@@ -516,6 +574,66 @@ export async function uploadFilesToOss(files, _fileType, options = {}) {
 }
 
 /**
+ * 单文件上传:返回列表展示用地址与业务保存用的 `download_url`(响应中无则为空字符串)
+ * @param {File} file
+ * @param {{ showLoading?: boolean; skipSimpleUploadOverlay?: boolean; uploadSuccessMessage?: string | null; uploadOverlayTitle?: string }} [options]
+ * @returns {Promise<{ fileUrl: string; downloadUrl: string }>}
+ */
+export async function uploadFileToOssWithDownloadMeta(file, options = {}) {
+  const { showLoading = false, skipSimpleUploadOverlay = false, uploadSuccessMessage, uploadOverlayTitle } = options;
+  if (!(file instanceof File)) {
+    throw new Error("请选择要上传的文件");
+  }
+
+  let closeLoading = () => {};
+  if (showLoading && skipSimpleUploadOverlay) {
+    const loading = ElMessage({ message: "上传中...", type: "info", duration: 0, showClose: false });
+    closeLoading = () => loading.close();
+  }
+
+  try {
+    const runUpload = async signal => {
+      const { url, downloadUrl } = await postFileToSimpleUploadDetailed(file, signal ? { signal } : {});
+      return { fileUrl: url, downloadUrl };
+    };
+
+    let result;
+    if (skipSimpleUploadOverlay) {
+      const overlaySignal = useSimpleUploadOverlayStore().getActiveAbortSignal?.();
+      result = await runUpload(overlaySignal ?? null);
+    } else {
+      const overlayOpts =
+        uploadSuccessMessage !== undefined || uploadOverlayTitle
+          ? {
+              title: uploadOverlayTitle,
+              successMessage: uploadSuccessMessage
+            }
+          : undefined;
+      result = await withSimpleUploadOverlay(signal => runUpload(signal), overlayOpts);
+    }
+
+    closeLoading();
+    return result;
+  } catch (e) {
+    closeLoading();
+    console.error("上传失败", e);
+    if (isUploadUserCancelledError(e)) {
+      throw e;
+    }
+    const msg = e?.message || "上传失败";
+    ElMessage.error(msg);
+    try {
+      if (e && typeof e === "object") {
+        Object.defineProperty(e, "__uploadMessageShown", { value: true, enumerable: false, configurable: true });
+      }
+    } catch (_) {
+      /* ignore */
+    }
+    throw e;
+  }
+}
+
+/**
  * 上传单个文件,返回 URL 字符串
  * @param {File} file
  * @param {string} [fileType]

+ 2 - 2
src/components/Upload/Imgs.vue

@@ -83,7 +83,7 @@ interface UploadFileProps {
   height?: string; // 组件高度 ==> 非必传(默认为 150px)
   width?: string; // 组件宽度 ==> 非必传(默认为 150px)
   borderRadius?: string; // 组件边框圆角 ==> 非必传(默认为 8px)
-  onSuccess?: (url: string) => void;
+  onSuccess?: (url: string, response?: unknown, file?: UploadFile) => void;
   onVideoPreview?: (url: string) => void; // 点击视频「查看」时的回调,用于父级弹窗放大预览(不传则新标签页打开)
   showSuccessNotification?: boolean; // 是否显示上传成功通知 ==> 非必传(默认为 true)
   hideUploadTrigger?: boolean; // 是否隐藏上传入口(达限或自定义隐藏时使用)==> 非必传(默认为 false)
@@ -276,7 +276,7 @@ const handleHttpUpload = (options: UploadRequestOptions): Promise<unknown> => {
       emit("update:fileList", _fileList.value);
       if (props.onSuccess) {
         try {
-          const result = props.onSuccess(fileUrl);
+          const result = props.onSuccess(fileUrl, response, options.file as UploadFile);
           if (
             result !== undefined &&
             result !== null &&

Dosya farkı çok büyük olduğundan ihmal edildi
+ 68 - 700
src/views/storeDecoration/officialPhotoAlbum/index.vue


Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor