feat 打印storage
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -20,6 +20,7 @@ CLAUDE.md
|
|||||||
.vscode
|
.vscode
|
||||||
.claude
|
.claude
|
||||||
.rtk
|
.rtk
|
||||||
|
.workbuddy
|
||||||
|
|
||||||
# Editor directories and files
|
# Editor directories and files
|
||||||
.idea
|
.idea
|
||||||
|
|||||||
10
src/App.vue
10
src/App.vue
@@ -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()
|
||||||
|
|||||||
@@ -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)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user