import { apiBase, request } from './api'; import { compressImageFileIfNeeded, DEFAULT_OSS_MAX_UPLOAD_BYTES, formatOssMaxSizeMb, } from '@dukang/shared-ui/compressImage'; const UPLOAD_TIMEOUT_MS = 120_000; export type OssMediaType = 'IMAGE' | 'VIDEO' | 'FILE'; export type UploadFileResult = { url: string; ossKey: string; bucket: string; mock: boolean; }; async function prepareUploadFile(file: File, mediaType: OssMediaType): Promise { if (mediaType !== 'IMAGE') return file; const compressed = await compressImageFileIfNeeded(file); if (compressed.size > DEFAULT_OSS_MAX_UPLOAD_BYTES) { throw new Error(`图片压缩后仍超过 ${formatOssMaxSizeMb()}MB,请换一张较小的图片`); } return compressed; } async function uploadFileToOssInner( file: File, options: { bizType: string; mediaType?: OssMediaType }, ): Promise { const mediaType = options.mediaType ?? (file.type.startsWith('video/') ? 'VIDEO' : 'IMAGE'); const prepared = await prepareUploadFile(file, mediaType); const formData = new FormData(); formData.append('file', prepared); formData.append('bizType', options.bizType); formData.append('mediaType', mediaType); const token = localStorage.getItem('accessToken'); const headers: Record = { 'X-Client-App': 'PARTNER_H5' }; if (token) headers.Authorization = `Bearer ${token}`; const controller = new AbortController(); const timeoutId = window.setTimeout(() => controller.abort(), UPLOAD_TIMEOUT_MS); try { const res = await fetch(`${apiBase}/common/resources/upload`, { method: 'POST', headers, body: formData, signal: controller.signal, }); const json = await res.json(); if (json.code === 401) { localStorage.removeItem('accessToken'); throw new Error('未登录'); } if (json.code !== 0) { throw new Error(json.message || '上传失败'); } const data = json.data as UploadFileResult; return { url: data.url, ossKey: data.ossKey, bucket: data.bucket, mock: data.mock, }; } catch (e) { if (e instanceof DOMException && e.name === 'AbortError') { throw new Error('上传超时,请检查网络后重试'); } throw e; } finally { window.clearTimeout(timeoutId); } } /** 经 API 服务端转存 OSS,避免浏览器直传跨域 */ export function uploadFileToOss( file: File, options: { bizType: string; mediaType?: OssMediaType }, ): Promise { return uploadFileToOssInner(file, options); } export type OpenCityOption = { id: string; name: string; code: string; province: string; }; export async function fetchPartnerCities(): Promise { return request('PARTNER_H5', '/partner/stores/cities'); }