2026-01-21 13:37:54 +08:00
|
|
|
|
const env = __VITE_ENV__;
|
|
|
|
|
|
|
2026-02-09 15:40:03 +08:00
|
|
|
|
function joinBaseAndPath(base, path) {
|
|
|
|
|
|
const b = String(base || '').replace(/\/+$/, '');
|
|
|
|
|
|
const p = String(path || '');
|
|
|
|
|
|
if (!p) return b;
|
|
|
|
|
|
if (/^https?:\/\//i.test(p)) return p;
|
|
|
|
|
|
return `${b}/${p.replace(/^\/+/, '')}`;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 兼容历史数据:某些链接缺少域名后的 /
|
|
|
|
|
|
export function normalizeFileUrl(url) {
|
|
|
|
|
|
const u = String(url || '').trim();
|
|
|
|
|
|
if (!u) return '';
|
|
|
|
|
|
if (/^https?:\/\//i.test(u)) {
|
|
|
|
|
|
const afterProtocolIndex = u.indexOf('://') + 3;
|
|
|
|
|
|
const firstSlashIndex = u.indexOf('/', afterProtocolIndex);
|
|
|
|
|
|
if (firstSlashIndex > 0) {
|
|
|
|
|
|
const prefix = u.slice(0, afterProtocolIndex);
|
|
|
|
|
|
const host = u.slice(afterProtocolIndex, firstSlashIndex);
|
|
|
|
|
|
const path = u.slice(firstSlashIndex);
|
|
|
|
|
|
if (host.toLowerCase().endsWith('uploads') && !path.toLowerCase().startsWith('/uploads/')) {
|
|
|
|
|
|
const fixedHost = host.slice(0, -'uploads'.length);
|
|
|
|
|
|
const normalizedPath = `/uploads${path.startsWith('/') ? '' : '/'}${path.replace(/^\/+/, '')}`;
|
|
|
|
|
|
return `${prefix}${fixedHost}${normalizedPath}`;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return u.replace(/^(https?:\/\/[^/]+)(uploads\/)/i, '$1/$2');
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-01-21 15:27:18 +08:00
|
|
|
|
export async function uploadFile(tempFilePath) {
|
2026-01-21 13:37:54 +08:00
|
|
|
|
try {
|
|
|
|
|
|
const res = await new Promise((resolve, reject) => {
|
|
|
|
|
|
uni.uploadFile({
|
2026-02-09 15:40:03 +08:00
|
|
|
|
url: joinBaseAndPath(env.MP_API_BASE_URL, 'upload'),
|
2026-01-21 13:37:54 +08:00
|
|
|
|
filePath: tempFilePath,
|
|
|
|
|
|
name: 'file',
|
|
|
|
|
|
success: (resp) => resolve(resp),
|
|
|
|
|
|
fail: (err) => reject(err),
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const data = typeof res.data === 'string' ? JSON.parse(res.data) : res.data;
|
2026-01-21 15:27:18 +08:00
|
|
|
|
if (data && data.success && data.filePath) {
|
2026-02-09 15:40:03 +08:00
|
|
|
|
return normalizeFileUrl(joinBaseAndPath(env.MP_API_BASE_URL, data.filePath));
|
2026-01-21 13:37:54 +08:00
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.log('upload file error:', e);
|
|
|
|
|
|
}
|
|
|
|
|
|
return undefined;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 选择单张图片并上传,成功返回上传结果(接口返回的 data.data)
|
|
|
|
|
|
* - 内部会处理 loading / toast
|
|
|
|
|
|
* - 失败或取消返回 null
|
|
|
|
|
|
*/
|
|
|
|
|
|
export async function chooseAndUploadImage(options = {}) {
|
|
|
|
|
|
const {
|
|
|
|
|
|
count = 1,
|
|
|
|
|
|
sizeType = ['compressed'],
|
2026-01-21 15:27:18 +08:00
|
|
|
|
sourceType = ['album', 'camera']
|
2026-01-21 13:37:54 +08:00
|
|
|
|
} = options;
|
|
|
|
|
|
|
|
|
|
|
|
const imageResult = await new Promise((resolve) => {
|
|
|
|
|
|
uni.chooseImage({
|
|
|
|
|
|
count,
|
|
|
|
|
|
sizeType,
|
|
|
|
|
|
sourceType,
|
|
|
|
|
|
success: (res) => resolve(res),
|
|
|
|
|
|
fail: () => resolve(null),
|
|
|
|
|
|
});
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
const tempFilePath = imageResult?.tempFilePaths?.[0];
|
|
|
|
|
|
if (!tempFilePath) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
try {
|
2026-01-21 15:27:18 +08:00
|
|
|
|
const uploadRes = await uploadFile(tempFilePath);
|
2026-01-21 13:37:54 +08:00
|
|
|
|
if (uploadRes) {
|
|
|
|
|
|
return uploadRes;
|
|
|
|
|
|
}
|
|
|
|
|
|
return null;
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|