import { getRuntimePlatform } from './env'; import { ensureJssdkReady } from './jssdk'; import type { WeixinSdkConfig } from './types'; export type ChooseWechatImageOptions = { count?: number; sourceType?: Array<'album' | 'camera'>; }; function base64ToFile(base64: string, fileName: string): File { const normalized = base64.startsWith('data:') ? base64 : `data:image/jpeg;base64,${base64.replace(/\s/g, '')}`; const [header, body] = normalized.split(','); const mime = header.match(/:(.*?);/)?.[1] ?? 'image/jpeg'; const binary = atob(body); const bytes = new Uint8Array(binary.length); for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i); return new File([bytes], fileName, { type: mime }); } function localIdToFile(localId: string): Promise { return new Promise((resolve, reject) => { if (!window.wx?.getLocalImgData) { reject(new Error('微信 getLocalImgData 不可用')); return; } window.wx.getLocalImgData({ localId, success: (res) => { try { resolve(base64ToFile(res.localData, `wx-${Date.now()}.jpg`)); } catch (e) { reject(e instanceof Error ? e : new Error('图片解析失败')); } }, fail: (err) => reject(new Error(err.errMsg || '读取图片失败')), }); }); } /** 微信内选图(相册/拍照),返回 File 列表;非微信环境返回 null */ export async function chooseWechatImages( config: WeixinSdkConfig, options: ChooseWechatImageOptions = {}, ): Promise { const platform = getRuntimePlatform(); if (platform === 'browser') return null; const count = options.count ?? 1; const sourceType = options.sourceType ?? ['album', 'camera']; if (platform === 'wechat-h5') { const pageUrl = typeof window !== 'undefined' ? window.location.href.split('#')[0] : ''; await ensureJssdkReady({ apiBase: config.apiBase ?? '/api/v1', clientApp: config.clientApp, getAccessToken: config.getAccessToken, url: pageUrl, jsApiList: ['chooseImage', 'getLocalImgData'], }); if (!window.wx?.chooseImage) { throw new Error('微信选图接口不可用,请刷新页面后重试'); } const localIds = await new Promise((resolve, reject) => { window.wx!.chooseImage!({ count, sizeType: ['compressed'], sourceType, success: (res) => resolve(res.localIds ?? []), fail: (err) => reject(new Error(err.errMsg || '无法打开相册')), }); }); const files: File[] = []; for (const localId of localIds) { files.push(await localIdToFile(localId)); } return files; } return null; } export function canUseWechatChooseImage(): boolean { return getRuntimePlatform() !== 'browser'; }