163 lines
5.2 KiB
JavaScript
163 lines
5.2 KiB
JavaScript
// frontend/utils/handlers/draftHandler.js
|
||
// 创作草稿 handler(分组型,按 uid 分组;草稿 key 已通过 M0 改造为 *_${uid} 形式)
|
||
|
||
import { getCurrentUid, getAllBaseKeys } from '@/utils/draftStorage'
|
||
|
||
function bytesOf(keys) {
|
||
let total = 0
|
||
for (const k of keys) {
|
||
try { const v = uni.getStorageSync(k); if (v != null) total += JSON.stringify(v).length } catch (e) {}
|
||
}
|
||
return total
|
||
}
|
||
|
||
function listAllDraftLikeKeys() {
|
||
try {
|
||
const info = uni.getStorageInfoSync()
|
||
const all = info.keys || []
|
||
const baseKeys = getAllBaseKeys()
|
||
return all.filter((k) => baseKeys.some((base) => k === base || k.startsWith(`${base}_`)))
|
||
} catch (e) { return [] }
|
||
}
|
||
|
||
function extractUidFromDraftKey(key, baseKey) {
|
||
const prefix = `${baseKey}_`
|
||
if (!key.startsWith(prefix)) return null
|
||
return key.slice(prefix.length)
|
||
}
|
||
|
||
/**
|
||
* Remove the listed storage keys, counting only successful removals.
|
||
* Reads each value first to capture accurate freedBytes before deletion.
|
||
* @param {string[]} targets
|
||
* @returns {{freedBytes: number, keyCount: number}}
|
||
*/
|
||
function removeAndCount(targets) {
|
||
let freed = 0
|
||
let count = 0
|
||
for (const k of targets) {
|
||
try {
|
||
let bytes = 0
|
||
try { const v = uni.getStorageSync(k); if (v != null) bytes = JSON.stringify(v).length } catch (e) {}
|
||
uni.removeStorageSync(k)
|
||
freed += bytes
|
||
count++
|
||
} catch (e) {
|
||
console.warn('[draftHandler] remove failed:', k, e.message)
|
||
}
|
||
}
|
||
return { freedBytes: freed, keyCount: count }
|
||
}
|
||
|
||
export default {
|
||
id: 'draft',
|
||
label: '创作中的草稿',
|
||
description: '未提交的创作表单/生成结果',
|
||
warning: true,
|
||
warningText: '将清空你未提交的创作草稿,是否继续?',
|
||
strongWarningText: '将清空该账号的草稿,对方下次登录不会看到。是否继续?',
|
||
|
||
async computeSize() {
|
||
const keys = listAllDraftLikeKeys()
|
||
return { sizeBytes: bytesOf(keys), keyCount: keys.length }
|
||
},
|
||
|
||
async computeBreakdown() {
|
||
const currentUid = getCurrentUid()
|
||
const allKeys = listAllDraftLikeKeys()
|
||
const groups = []
|
||
const baseKeys = getAllBaseKeys()
|
||
const isLoggedIn = !!currentUid
|
||
|
||
// 按 uid 聚合
|
||
const byUid = new Map()
|
||
for (const k of allKeys) {
|
||
const matchedBase = baseKeys.find((b) => k === b || k.startsWith(`${b}_`))
|
||
if (!matchedBase) continue
|
||
const uid = extractUidFromDraftKey(k, matchedBase)
|
||
const groupUid = uid || '__legacy__'
|
||
if (!byUid.has(groupUid)) byUid.set(groupUid, [])
|
||
byUid.get(groupUid).push(k)
|
||
}
|
||
|
||
for (const [uid, keys] of byUid) {
|
||
const isCurrent = uid === currentUid
|
||
const isLegacy = uid === '__legacy__'
|
||
let canClean, disabledReason
|
||
if (!isLoggedIn) {
|
||
canClean = false
|
||
disabledReason = 'logged-out'
|
||
} else if (isLegacy) {
|
||
// 老无 uid 后缀 key 单独分组(不与他人草稿混合)
|
||
canClean = keys.length > 0
|
||
disabledReason = keys.length === 0 ? 'empty' : null
|
||
} else {
|
||
canClean = keys.length > 0
|
||
disabledReason = keys.length === 0 ? 'empty' : null
|
||
}
|
||
groups.push({
|
||
uid,
|
||
displayUid: isLegacy ? '老版本数据' : (isCurrent ? `我的 (${uid})` : `其他用户 (${uid})`),
|
||
isCurrent,
|
||
sizeBytes: bytesOf(keys),
|
||
keyCount: keys.length,
|
||
canClean,
|
||
disabledReason,
|
||
})
|
||
}
|
||
|
||
return groups.sort((a, b) => b.sizeBytes - a.sizeBytes)
|
||
},
|
||
|
||
async cleanGroup({ uid }) {
|
||
const currentUid = getCurrentUid()
|
||
const allKeys = listAllDraftLikeKeys()
|
||
const baseKeys = getAllBaseKeys()
|
||
|
||
const reserved = new Set()
|
||
if (currentUid) {
|
||
// 保留当前 uid 的 keys
|
||
for (const k of allKeys) {
|
||
const base = baseKeys.find((b) => k === b || k.startsWith(`${b}_`))
|
||
if (!base) continue
|
||
if (extractUidFromDraftKey(k, base) === currentUid) reserved.add(k)
|
||
}
|
||
}
|
||
|
||
if (uid === 'self') {
|
||
const targets = allKeys.filter((k) => {
|
||
const base = baseKeys.find((b) => k === b || k.startsWith(`${b}_`))
|
||
if (!base) return false
|
||
return extractUidFromDraftKey(k, base) === currentUid
|
||
})
|
||
return removeAndCount(targets)
|
||
} else if (uid === '__legacy__') {
|
||
// 单独清老无 uid 后缀 key(不删其他用户的!)
|
||
const targets = allKeys.filter((k) => {
|
||
const base = baseKeys.find((b) => k === b || k.startsWith(`${b}_`))
|
||
if (!base) return false
|
||
return k === base
|
||
})
|
||
return removeAndCount(targets)
|
||
} else if (uid === 'others') {
|
||
// 其他用户聚合(不含 legacy)
|
||
const targets = allKeys.filter((k) => {
|
||
const base = baseKeys.find((b) => k === b || k.startsWith(`${b}_`))
|
||
if (!base) return false
|
||
const u = extractUidFromDraftKey(k, base)
|
||
return u && u !== currentUid
|
||
})
|
||
return removeAndCount(targets)
|
||
} else {
|
||
// 具体其他 uid
|
||
const targets = allKeys.filter((k) => {
|
||
const base = baseKeys.find((b) => k === b || k.startsWith(`${b}_`))
|
||
if (!base) return false
|
||
if (reserved.has(k)) return false // defensive
|
||
return extractUidFromDraftKey(k, base) === uid
|
||
})
|
||
return removeAndCount(targets)
|
||
}
|
||
},
|
||
}
|