xw před 1 měsícem
rodič
revize
05ae380de4
2 změnil soubory, kde provedl 78 přidání a 21 odebrání
  1. 22 21
      src/components/ImageUpload/index.vue
  2. 56 0
      src/utils/ossUrl.js

+ 22 - 21
src/components/ImageUpload/index.vue

@@ -42,6 +42,7 @@
 
 <script>
 import { getToken } from "@/utils/auth";
+import { resolveAccessUrl, stripSignedParams } from "@/utils/ossUrl";
 
 import { Loading } from 'element-ui';
 
@@ -86,24 +87,7 @@ export default {
   watch: {
     value: {
       handler(val) {
-        if (val) {
-          // 首先将值转为数组
-          const list = Array.isArray(val) ? val : this.value.split(',');
-          // 然后将数组转为对象数组
-          this.fileList = list.map(item => {
-            if (typeof item === "string") {
-              if (item.indexOf(this.baseUrl) === -1) {
-                  item = { name: item, url: item };
-              } else {
-                  item = { name: item, url: item };
-              }
-            }
-            return item;
-          });
-        } else {
-          this.fileList = [];
-          return [];
-        }
+        this.loadFileList(val);
       },
       deep: true,
       immediate: true
@@ -116,6 +100,22 @@ export default {
     },
   },
   methods: {
+    async loadFileList(val) {
+      if (!val) {
+        this.fileList = [];
+        return;
+      }
+      const list = Array.isArray(val) ? val : val.split(',');
+      const fileList = [];
+      for (const item of list) {
+        if (typeof item === 'string' && item) {
+          const storedUrl = stripSignedParams(item);
+          const accessUrl = await resolveAccessUrl(storedUrl);
+          fileList.push({ name: storedUrl, url: accessUrl });
+        }
+      }
+      this.fileList = fileList;
+    },
     // 删除图片
     handleRemove(file, fileList) {
       const findex = this.fileList.map(f => f.name).indexOf(file.name);
@@ -126,8 +126,9 @@ export default {
     },
     // 上传成功回调
     handleUploadSuccess(res) {
-      console.log(res)
-      this.fileList.push({ name: res.url, url: res.url });
+      const storedUrl = stripSignedParams(res.url);
+      const accessUrl = res.accessUrl || storedUrl;
+      this.fileList.push({ name: storedUrl, url: accessUrl });
       this.$emit("input", this.listToString(this.fileList));
       this.loading.close();
     },
@@ -272,7 +273,7 @@ export default {
       let strs = "";
       separator = separator || ",";
       for (let i in list) {
-        strs += list[i].url.replace(this.baseUrl, "") + separator;
+        strs += list[i].name.replace(this.baseUrl, "") + separator;
       }
       return strs != '' ? strs.substr(0, strs.length - 1) : '';
     }

+ 56 - 0
src/utils/ossUrl.js

@@ -0,0 +1,56 @@
+import request from '@/utils/request'
+
+const signedUrlCache = new Map()
+
+/**
+ * 判断是否为腾讯云COS私有存储预签名地址
+ */
+export function isCosUrl(url) {
+  if (!url || typeof url !== 'string') {
+    return false
+  }
+  return url.includes('.myqcloud.com/') || url.includes('.cos.')
+}
+
+/**
+ * 去除URL里预签名query参数,返回原始文件地址
+ */
+export function stripSignedParams(url) {
+  if (!url) {
+    return url
+  }
+  const index = url.indexOf('?')
+  return index > 0 ? url.substring(0, index) : url
+}
+
+/**
+ * 转换存储地址为可访问链接,私有文件自动获取预签名地址
+ */
+export function resolveAccessUrl(url) {
+  const storedUrl = stripSignedParams(url)
+  if (!storedUrl || !isCosUrl(storedUrl)) {
+    return Promise.resolve(url)
+  }
+  if (signedUrlCache.has(storedUrl)) {
+    return Promise.resolve(signedUrlCache.get(storedUrl))
+  }
+  return request({
+    url: '/common/getSignedUrl',
+    method: 'get',
+    params: { url: storedUrl }
+  }).then(res => {
+    const accessUrl = (res.accessUrl || res.url || storedUrl)
+    signedUrlCache.set(storedUrl, accessUrl)
+    return accessUrl
+  }).catch(() => storedUrl)
+}
+
+/**
+ * 批量转换COS文件访问URL
+ */
+export function resolveAccessUrls(urls) {
+  if (!urls || !urls.length) {
+    return Promise.resolve([])
+  }
+  return Promise.all(urls.map(url => resolveAccessUrl(url)))
+}