160 lines
3.9 KiB
JavaScript
160 lines
3.9 KiB
JavaScript
/** 头像等媒体:真机选图后须 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)
|
||
}
|