|
|
@@ -1,6 +1,57 @@
|
|
|
/**
|
|
|
* URL处理工具函数
|
|
|
*/
|
|
|
+import { Local } from './storage';
|
|
|
+
|
|
|
+/**
|
|
|
+ * 给文件地址拼接登录用户 token 参数
|
|
|
+ * 用于 <a href> / window.open / van-image :src / showImagePreview 等无法携带 Authorization 头的直链访问
|
|
|
+ * @param url 原始文件地址
|
|
|
+ * @returns 拼接 token 后的地址(非 http(s) / 空 / data: / blob: 直接原样返回,避免本地静态资源被污染)
|
|
|
+ */
|
|
|
+export function withToken(url?: string | null): string {
|
|
|
+ if (url === null || url === undefined) return '';
|
|
|
+ const str = String(url).trim();
|
|
|
+ if (!str) return str;
|
|
|
+ if (str.startsWith('data:') || str.startsWith('blob:') || str.startsWith('about:') || str.startsWith('#')) return str;
|
|
|
+ // 仅 http(s) 文件直链需要鉴权,本地静态资源直接返回
|
|
|
+ if (!/^https?:\/\//i.test(str)) return str;
|
|
|
+ let token = '';
|
|
|
+ try {
|
|
|
+ token = Local.get('token') || '';
|
|
|
+ } catch (e) {
|
|
|
+ token = '';
|
|
|
+ }
|
|
|
+ if (!token) return str;
|
|
|
+ // 已带 token 则不再重复拼接
|
|
|
+ if (/[?&]token=/.test(str)) return str;
|
|
|
+ const sep = str.includes('?') ? '&' : '?';
|
|
|
+ return `${str}${sep}token=${encodeURIComponent(token)}`;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 文件地址统一入口(withToken 别名,语义更明确)
|
|
|
+ */
|
|
|
+export function getFileUrl(url?: string | null): string {
|
|
|
+ return withToken(url);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * 去掉地址中的 token 参数
|
|
|
+ * 上传回显用 withToken 做展示时,提交给后端前需调用此方法还原为原始地址,避免把 token 持久化存储
|
|
|
+ */
|
|
|
+export function stripToken(url?: string | null): string {
|
|
|
+ if (url === null || url === undefined) return '';
|
|
|
+ const str = String(url);
|
|
|
+ if (!str || !/[?&]token=/.test(str)) return str;
|
|
|
+ // 去掉 ?token=xxx 或 &token=xxx,并清理多余的 ? & 符号
|
|
|
+ let cleaned = str.replace(/([?&])token=[^&]*/g, (match, sep) => (sep === '?' ? '?' : ''));
|
|
|
+ cleaned = cleaned.replace(/\?&/, '?').replace(/&&+/g, '&');
|
|
|
+ cleaned = cleaned.replace(/[?&]$/, '');
|
|
|
+ // ? 后第一个是 & 的情况:? &a=1 => ?a=1
|
|
|
+ cleaned = cleaned.replace(/\?&/, '?');
|
|
|
+ return cleaned;
|
|
|
+}
|
|
|
|
|
|
/**
|
|
|
* 获取完整的图片URL
|
|
|
@@ -8,8 +59,8 @@
|
|
|
* @returns 完整的图片URL
|
|
|
*/
|
|
|
export function getImageUrl(url: string): string {
|
|
|
- // 图片是相对路径不需要拼
|
|
|
- return url
|
|
|
+ // 图片是相对路径不需要拼,但文件直链需要拼接登录 token 鉴权
|
|
|
+ return withToken(url);
|
|
|
// if (!url) return ''
|
|
|
|
|
|
// // 如果已经包含http或https协议,直接返回
|
|
|
@@ -36,9 +87,9 @@ export function getImageUrl(url: string): string {
|
|
|
export function getResourceUrl(url: string, baseUrlKey: string = 'VITE_IMAGE_BASE_URL'): string {
|
|
|
if (!url) return ''
|
|
|
|
|
|
- // 如果已经包含http或https协议,直接返回
|
|
|
+ // 如果已经包含http或https协议,直接拼接 token 后返回
|
|
|
if (url.startsWith('http://') || url.startsWith('https://')) {
|
|
|
- return url
|
|
|
+ return withToken(url)
|
|
|
}
|
|
|
|
|
|
// 获取环境变量中的基础URL
|