/**
* 应用版本:与 manifest 发版时尽量保持 versionName/versionCode 一致(非 App 端会回退到默认值)。
*
* 本地待更新信息:写入 uni.setStorageSync(APP_PENDING_UPDATE_STORAGE_KEY, 对象或 JSON 字符串)
* 形状:{ versionName, versionCode?, changelog?, downloadUrl?, packageSize? }
* packageSize 示例:「128 MB」「7.13 GB」,展示在标题下灰色副标题
* 与 getCurrentAppVersionInfo() 比较,若本地版本更新则展示「可更新」界面。
*/
export const APP_PENDING_UPDATE_STORAGE_KEY = 'APP_PENDING_UPDATE'
export function readPendingUpdateFromStorage() {
try {
const raw = uni.getStorageSync(APP_PENDING_UPDATE_STORAGE_KEY)
if (raw == null || raw === '') return null
if (typeof raw === 'object' && raw !== null && !Array.isArray(raw)) return raw
if (typeof raw === 'string') {
const o = JSON.parse(raw)
return o && typeof o === 'object' && !Array.isArray(o) ? o : null
}
} catch (e) {}
return null
}
function parseVersionNameToComparable(name) {
if (!name || typeof name !== 'string') return 0
const m = name.trim().match(/^(\d+)\.(\d+)\.(\d+)/)
if (!m) return 0
const a = parseInt(m[1], 10) || 0
const b = parseInt(m[2], 10) || 0
const c = parseInt(m[3], 10) || 0
return a * 10000 + b * 100 + c
}
export function effectiveVersionComparable(info) {
if (!info) return 0
const n = Number(info.versionCode)
if (!Number.isNaN(n) && n > 0) return n
const fromName = parseVersionNameToComparable(info.versionName)
return fromName > 0 ? fromName : 0
}
/** 版本号字符串规范化后比较(与接口 `version`、本地存储一致) */
export function normalizeVersionString(s) {
if (s == null) return ''
return String(s).trim()
}
function stripHtmlToPlain(html) {
if (!html || typeof html !== 'string') return ''
return html
.replace(/<\/p>/gi, '\n')
.replace(/
/gi, '\n')
.replace(/<[^>]+>/g, '')
.replace(/\r\n/g, '\n')
.replace(/\n{3,}/g, '\n\n')
.trim()
}
/** 当前运行包版本(App 读 runtime,小程序读账号信息,其余与 manifest 默认一致) */
export function getCurrentAppVersionInfo() {
let versionName = '1.0.2'
let versionCode = 102
// #ifdef APP-PLUS
try {
if (typeof plus !== 'undefined' && plus.runtime) {
versionName = plus.runtime.version || versionName
const vc = plus.runtime.versionCode
if (vc != null && vc !== '') {
const parsed = parseInt(String(vc), 10)
if (!Number.isNaN(parsed)) versionCode = parsed
}
}
} catch (e) {}
// #endif
// #ifdef MP-WEIXIN
try {
const acc = uni.getAccountInfoSync && uni.getAccountInfoSync()
if (acc && acc.miniProgram && acc.miniProgram.version) {
versionName = acc.miniProgram.version
const parsed = parseVersionNameToComparable(versionName)
if (parsed > 0) versionCode = parsed
}
} catch (e) {}
// #endif
return {
versionName: String(versionName),
versionCode: Number(versionCode) || 0
}
}
/** 与当前包比较:pending 是否为更高版本(本地存储或任意来源的待更新描述对象) */
export function remoteHasNewerVersion(currentInfo, pending) {
if (!pending || typeof pending !== 'object') return false
const c = effectiveVersionComparable(currentInfo)
const r = effectiveVersionComparable({
versionName: pending.versionName,
versionCode: pending.versionCode
})
if (r <= 0) return false
return r > c
}
function isTrivialEmptyHtml(html) {
if (!html || typeof html !== 'string') return true
const t = html.replace(/\s/g, '').toLowerCase()
return (
t === '' ||
t === '