import type { CreateStudioUploadCredentialDto, StudioAssetType, StudioUploadCredential, } from '@mp-pilates/shared' import type { useAdminStore } from '../stores/admin' type AdminStore = ReturnType function inferContentType(fileName: string): string | undefined { const extension = fileName.split('.').pop()?.toLowerCase() if (extension === 'jpg' || extension === 'jpeg') { return 'image/jpeg' } if (extension === 'png') { return 'image/png' } if (extension === 'webp') { return 'image/webp' } if (extension === 'heic') { return 'image/heic' } if (extension === 'heif') { return 'image/heif' } return undefined } function uploadToCos(filePath: string, credential: StudioUploadCredential): Promise { return new Promise((resolve, reject) => { uni.uploadFile({ url: credential.uploadUrl, filePath, name: 'file', formData: credential.formData as unknown as Record, success: (result) => { if (result.statusCode >= 200 && result.statusCode < 300) { resolve() return } const body = typeof result.data === 'string' ? result.data : JSON.stringify(result.data) const code = body.match(/([^<]+)<\/Code>/)?.[1] const message = body.match(/([^<]+)<\/Message>/)?.[1] const detail = code || message ? `${code ?? 'COS'}: ${message ?? body}` : body reject(new Error(`COS 上传失败 (${result.statusCode}) ${detail}`)) }, fail: (error) => { reject(new Error(error.errMsg || 'COS 上传失败')) }, }) }) } export async function uploadStudioAsset(params: { adminStore: AdminStore filePath: string fileName: string assetType: StudioAssetType }): Promise { const payload: CreateStudioUploadCredentialDto = { fileName: params.fileName, contentType: inferContentType(params.fileName), assetType: params.assetType, } const credential = await params.adminStore.createStudioUploadCredential(payload) await uploadToCos(params.filePath, credential) return credential.fileUrl }