/** 头像等媒体:真机选图后须 saveFile,/static/ 须 getImageInfo */ function buildStaticPathCandidates(url) { const list = [url] if (url.startsWith('/')) { list.push(url.slice(1)) } else { list.push(`/${url}`) } return [...new Set(list.filter(Boolean))] } function isPackageStaticPath(url) { return /^(\/)?static\//i.test(url) } /** chooseImage / saveFile 产生的本地路径(含真机 temp、usr、store) */ export function isLocalFilePath(url) { if (!url) return false if (/^(wxfile:|file:|blob:|data:)/i.test(url)) return true if (/^https?:\/\/(tmp|usr|store)\//i.test(url)) return true if (/^https?:\/\//i.test(url) && !isPackageStaticPath(url)) return true return false } function showPreviewFail() { uni.showToast({ title: '无法预览头像', icon: 'none' }) } function openPreview(path, onFail) { if (!path) { ;(onFail || showPreviewFail)() return } uni.previewImage({ urls: [path], current: path, fail: () => (onFail ? onFail() : showPreviewFail()) }) } function previewLocalFile(url) { openPreview(url, () => { uni.getImageInfo({ src: url, success: (res) => { openPreview(res.path || url, showPreviewFail) }, fail: showPreviewFail }) }) } function tryGetImageInfo(candidates, index, onSuccess, onFail) { if (index >= candidates.length) { onFail() return } uni.getImageInfo({ src: candidates[index], success: (res) => onSuccess(res.path || candidates[index]), fail: () => tryGetImageInfo(candidates, index + 1, onSuccess, onFail) }) } function getMpUserDataPath() { // #ifdef MP-WEIXIN return wx.env.USER_DATA_PATH // #endif return '' } function tryCopyFile(candidates, index, onSuccess, onFail) { // #ifdef MP-WEIXIN const userPath = getMpUserDataPath() if (!userPath) { onFail() return } const fs = uni.getFileSystemManager() const extMatch = candidates[0]?.match(/\.(\w+)(?:\?|$)/) const ext = extMatch ? extMatch[1] : 'png' const dest = `${userPath}/avatar_preview_${Date.now()}.${ext}` if (index >= candidates.length) { onFail() return } fs.copyFile({ srcPath: candidates[index], destPath: dest, success: () => onSuccess(dest), fail: () => tryCopyFile(candidates, index + 1, onSuccess, onFail) }) // #endif // #ifndef MP-WEIXIN onFail() // #endif } function previewPackageStatic(url) { const candidates = buildStaticPathCandidates(url) tryGetImageInfo( candidates, 0, (path) => openPreview(path, showPreviewFail), () => { tryCopyFile( candidates, 0, (path) => openPreview(path, showPreviewFail), showPreviewFail ) } ) } /** 选图后将临时文件转为真机可预览、可持久化的本地路径 */ export function persistChosenImage(tempPath) { return new Promise((resolve) => { const path = String(tempPath || '').trim() if (!path) { resolve('') return } // #ifdef MP-WEIXIN uni.saveFile({ tempFilePath: path, success: (res) => resolve(res.savedFilePath || path), fail: () => resolve(path) }) // #endif // #ifndef MP-WEIXIN resolve(path) // #endif }) } export function previewImage(src, fallback = '') { const url = String(src || fallback || '').trim() if (!url) { uni.showToast({ title: '暂无头像', icon: 'none' }) return } if (isLocalFilePath(url)) { previewLocalFile(url) return } if (isPackageStaticPath(url)) { previewPackageStatic(url) return } previewLocalFile(url) }