feat 打印storage

This commit is contained in:
Ironsp
2026-09-27 09:55:18 +08:00
parent 5a7d56265c
commit 7a24c6bfd0
5 changed files with 172 additions and 2 deletions

1
.gitignore vendored
View File

@@ -20,6 +20,7 @@ CLAUDE.md
.vscode .vscode
.claude .claude
.rtk .rtk
.workbuddy
# Editor directories and files # Editor directories and files
.idea .idea

View File

@@ -1,9 +1,19 @@
<script setup lang="ts"> <script setup lang="ts">
import { useDeviceAuth } from '@/composables/useDeviceAuth' import { useDeviceAuth } from '@/composables/useDeviceAuth'
import { initTables } from '@/service' import { initTables } from '@/service'
import storage from '@/utils/storage'
const { initAuth } = useDeviceAuth() const { initAuth } = useDeviceAuth()
// 开发环境把 storage 调试方法挂到全局,控制台可直接调用
// 用法:storagePrint() / storageAll()
if (import.meta.env.DEV) {
;(globalThis as any).storagePrint = () => storage.print()
;(globalThis as any).storageAll = () => storage.all()
// 启动时自动打印一次,不想看就把这行注释掉
storage.print()
}
onLaunch(async () => { onLaunch(async () => {
try { try {
await initTables() await initTables()

View File

@@ -23,6 +23,12 @@
* *
* // 获取所有key * // 获取所有key
* storage.keys() * storage.keys()
*
* // 打印全部数据(key: value 形式)
* storage.print()
*
* // 打印全部数据并返回对象
* const all = storage.all()
*/ */
interface StorageItem<T = any> { interface StorageItem<T = any> {
@@ -120,7 +126,86 @@ const storage = {
* @returns key数组 * @returns key数组
*/ */
keys(): string[] { keys(): string[] {
return Object.keys(uni.getStorageInfoSync().keys) return uni.getStorageInfoSync().keys || []
},
/**
* 获取全部数据(key: value 形式的普通对象)
* 会自动过滤已过期的 key
* @returns 键值对对象
*/
all(): Record<string, any> {
const result: Record<string, any> = {}
for (const key of this.keys()) {
const raw = uni.getStorageSync(key)
if (!raw)
continue
try {
const item: StorageItem = JSON.parse(raw)
// 已过期则顺手清掉,不放进结果
if (item.expire && item.expire < Date.now()) {
this.remove(key)
continue
}
result[key] = item.value
}
catch {
// 非法 JSON(早期版本或其它代码直接写的裸数据)原样返回
result[key] = raw
}
}
return result
},
/**
* 打印全部数据到控制台(key: value 形式)
* H5 直接看浏览器控制台,App / 小程序看 HBuilderX 的控制台
*
* 注意:App 端真机的 console 会过滤多参数、合并日志,
* 所以这里用「一条完整字符串」输出,保证一定能看到。
*
* @returns 键值对对象,便于链式调试
*/
print(): Record<string, any> {
const data = this.all()
const keys = Object.keys(data)
if (!keys.length) {
console.log('[storage] 空')
return data
}
// 拼成单条字符串,避免 App 端多参数日志被截断或吞掉
const lines = [`[storage] 共 ${keys.length} 项`]
keys.forEach((key) => {
lines.push(` ${key}: ${this.format(data[key])}`)
})
lines.push(`[storage] 完整对象: ${JSON.stringify(data)}`)
console.log(lines.join('\n'))
return data
},
/**
* 把值格式化成单行字符串,避免对象打印成 [object Object]
*/
format(value: any): string {
if (value === null)
return 'null'
if (value === undefined)
return 'undefined'
if (typeof value === 'string')
return value
if (typeof value === 'object') {
try {
return JSON.stringify(value)
}
catch {
return String(value)
}
}
return String(value)
}, },
} }

View File

@@ -9,6 +9,78 @@ import AutoImport from 'unplugin-auto-import/vite'
import { defineConfig } from 'vite' import { defineConfig } from 'vite'
import UniPolyfill from 'vite-plugin-uni-polyfill' import UniPolyfill from 'vite-plugin-uni-polyfill'
/**
* 兜底处理 uni:json 插件对 pages.json 的解析失败
*
* 背景:vite-plugin-uni-pages 会用 comment-json 往 pages.json 里写入
* `// GENERATED BY UNI-PAGES...` 注释。uni-app 的 uni:json 插件本应用
* jsonc-parser 吃掉注释,但当它拿到半截文件内容(HBuilderX 写入与读取竞态)
* 时 parse 会返回 undefined,导致插件没产出 code,随后 Vite 内置 vite:json
* 用严格 JSON.parse 接手,撞上注释直接报错:
* Failed to parse JSON file, invalid JSON syntax found at position -1
*
* 这个插件挂在最前面(enforce: 'pre'),保证 vite:json 拿到的一定是无注释的
* 合法 JSON,从而绕开该问题。
*/
function stripJsonComments() {
return {
name: 'strip-json-comments',
enforce: 'pre' as const,
transform(code: string, id: string) {
// 只处理 src 下的 pages.json / manifest.json
if (!/[\\/](?:pages|manifest)\.json(?:\?.*)?$/.test(id))
return null
// 本身就不含注释,交回后续插件处理
if (!code.includes('//'))
return null
let inString = false
let escaped = false
let result = ''
for (let i = 0; i < code.length; i++) {
const ch = code[i]
if (inString) {
result += ch
if (escaped)
escaped = false
else if (ch === '\\')
escaped = true
else if (ch === '"')
inString = false
continue
}
if (ch === '"') {
inString = true
result += ch
continue
}
// 行注释:跳到行尾
if (ch === '/' && code[i + 1] === '/') {
while (i < code.length && code[i] !== '\n') i++
result += '\n'
continue
}
// 块注释:跳到结束
if (ch === '/' && code[i + 1] === '*') {
i += 2
while (i < code.length && !(code[i] === '*' && code[i + 1] === '/')) i++
i++
continue
}
result += ch
}
return { code: result, map: null }
},
}
}
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
css: { css: {
@@ -20,6 +92,8 @@ export default defineConfig({
}, },
}, },
plugins: [ plugins: [
// 必须放最前:在 uni:json / vite:json 之前剥掉 pages.json 里的注释
stripJsonComments(),
// https://uni-helper.js.org/vite-plugin-uni-manifest // https://uni-helper.js.org/vite-plugin-uni-manifest
UniHelperManifest(), UniHelperManifest(),
// https://uni-helper.js.org/vite-plugin-uni-pages // https://uni-helper.js.org/vite-plugin-uni-pages