Files
npm-tool/.qoder/repowiki/zh/content/核心模块/存储模块 (TsStorage).md

507 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 存储模块 (TsStorage)
<cite>
**本文引用的文件列表**
- [TsStorage.js](file://src/utils/TsStorage.js)
- [TsCrypto.js](file://src/utils/TsCrypto.js)
- [TsSM4.js](file://src/utils/TsSM4.js)
- [TsCommon.js](file://src/utils/TsCommon.js)
- [TsGlobalConfig.js](file://src/utils/TsGlobalConfig.js)
- [TsHttpUtil.js](file://src/https/TsHttpUtil.js)
- [index.js](file://index.js)
- [package.json](file://package.json)
- [README.md](file://README.md)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构总览](#架构总览)
5. [详细组件分析](#详细组件分析)
6. [依赖关系分析](#依赖关系分析)
7. [性能考量](#性能考量)
8. [故障排查指南](#故障排查指南)
9. [结论](#结论)
10. [附录](#附录)
## 简介
本文件为存储模块TsStorage的完整数据持久化文档聚焦于基于浏览器 localStorage 的数据存储机制,涵盖以下主题:
- 数据序列化与反序列化流程
- 用户 token 管理
- 加密开关控制与数据生命周期管理
- 与加密模块SM4/加密器)的集成关系
- 数据安全传输与存储最佳实践
- 完整 API 接口说明(保存、获取、删除等)
- 使用示例、数据迁移策略与备份恢复方案
- 浏览器兼容性与存储容量限制
## 项目结构
该工具包采用“按功能域分层”的组织方式,存储模块位于 utils 目录下,并通过 index.js 汇总导出,供上层业务统一调用。
```mermaid
graph TB
subgraph "工具包入口"
IDX["index.js"]
end
subgraph "存储层"
TS["TsStorage.js"]
TC["TsCommon.js"]
end
subgraph "加密层"
TG["TsGlobalConfig.js"]
TSM["TsSM4.js"]
TCR["TsCrypto.js"]
end
subgraph "网络层"
TH["TsHttpUtil.js"]
end
IDX --> TS
IDX --> TCR
IDX --> TSM
IDX --> TG
IDX --> TH
TH --> TS
TH --> TCR
TH --> TG
TS --> TC
TCR --> TSM
TCR --> TG
```
图表来源
- [index.js:1-16](file://index.js#L1-L16)
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
- [TsCommon.js:1-98](file://src/utils/TsCommon.js#L1-L98)
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
- [TsSM4.js:1-456](file://src/utils/TsSM4.js#L1-L456)
- [TsGlobalConfig.js:1-34](file://src/utils/TsGlobalConfig.js#L1-L34)
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
章节来源
- [index.js:1-16](file://index.js#L1-L16)
- [package.json:1-24](file://package.json#L1-L24)
## 核心组件
- 存储模块TsStorage封装 localStorage 的读写、token 管理、加密开关管理,提供统一的键值存取接口。
- 加密模块TsCrypto + TsSM4基于 SM4 算法的加解密实现,支持 ECB 模式与 Base64 输出。
- 全局配置TsGlobalConfig提供 base64Key、前缀、HTTP 参数注入与错误回调等全局配置。
- 通用工具TsCommon提供 JSON 解析、空值判断等基础能力。
- 网络工具TsHttpUtil在请求中自动注入 token 与加密开关,对响应进行解密与解析。
章节来源
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
- [TsSM4.js:1-456](file://src/utils/TsSM4.js#L1-L456)
- [TsGlobalConfig.js:1-34](file://src/utils/TsGlobalConfig.js#L1-L34)
- [TsCommon.js:1-98](file://src/utils/TsCommon.js#L1-L98)
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
## 架构总览
存储模块与加密模块的交互路径如下:网络层在发送请求时根据加密开关对请求体进行加密;接收响应时若标记为加密,则进行解密并解析 JSON存储层负责持久化 token 与加密开关状态。
```mermaid
sequenceDiagram
participant App as "应用"
participant Http as "TsHttpUtil"
participant Store as "TsStorage"
participant Crypto as "TsCrypto"
participant SM4 as "TsSM4"
participant Srv as "后端服务"
App->>Store : "saveUserToken(token)"
App->>Store : "saveEncryptBody(true/false)"
App->>Http : "post(url, data)"
Http->>Store : "getEncryptBody()"
alt "加密开启"
Http->>Crypto : "encrypt(JSON.stringify(data))"
Crypto->>SM4 : "encrypt(明文)"
SM4-->>Crypto : "密文(Base64)"
Crypto-->>Http : "密文"
Http->>Srv : "POST { encryptData : 密文 }"
else "加密关闭"
Http->>Srv : "POST 原始 JSON"
end
Srv-->>Http : "响应(可能含 encrypt 标记)"
alt "响应需解密"
Http->>Crypto : "decrypt(密文)"
Crypto->>SM4 : "decrypt(密文)"
SM4-->>Crypto : "明文"
Crypto-->>Http : "明文"
Http->>Http : "parseJSON(明文)"
end
Http-->>App : "{ data, recordsTotal }"
```
图表来源
- [TsHttpUtil.js:80-91](file://src/https/TsHttpUtil.js#L80-L91)
- [TsHttpUtil.js:117-123](file://src/https/TsHttpUtil.js#L117-L123)
- [TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23)
- [TsCrypto.js:19-30](file://src/utils/TsCrypto.js#L19-L30)
- [TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387)
## 详细组件分析
### 存储模块TsStorage
- 功能职责
- 统一的键值存取:将任意值序列化为 JSON 字符串后写入 localStorage。
- 用户 token 管理:提供保存与读取 token 的便捷方法。
- 加密开关管理:保存/读取“是否对请求体进行加密”的布尔标志。
- 安全反序列化:通过通用工具解析 JSON避免异常导致崩溃。
- 关键实现要点
- 写入:以 {data: value} 的结构写入 localStorage便于后续统一解析。
- 读取:从 localStorage 读取字符串,交由通用工具解析为对象,再取出 data 字段;未命中或解析失败时返回默认值。
- token 与加密开关:分别以固定键名保存,便于网络层直接读取。
- 错误处理
- 读取失败或 JSON 解析异常时,返回默认值,保证健壮性。
- 性能与复杂度
- 写入/读取均为 O(1),序列化/反序列化为 O(n)n 为字符串长度)。
- 使用建议
- 对大对象建议在上层进行拆分或压缩,避免 localStorage 膨胀。
- 避免存储敏感信息(如明文密码),优先使用加密开关与服务端保护。
```mermaid
flowchart TD
Start(["函数入口"]) --> SaveGet{"save 或 get?"}
SaveGet --> |save| Serialize["JSON.stringify({data: value})"]
Serialize --> Write["localStorage.setItem(key, 字符串)"]
SaveGet --> |get| Read["localStorage.getItem(key)"]
Read --> Parse["Common.parseJSON(字符串, {data: 默认值})"]
Parse --> Extract["取 data 字段"]
Extract --> End(["返回结果"])
```
图表来源
- [TsStorage.js:31-43](file://src/utils/TsStorage.js#L31-L43)
- [TsCommon.js:34-44](file://src/utils/TsCommon.js#L34-L44)
章节来源
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
- [TsCommon.js:34-44](file://src/utils/TsCommon.js#L34-L44)
### 加密模块TsCrypto + TsSM4
- 功能职责
- 提供 SM4 加密与解密能力,支持 ECB 模式与 Base64 输出。
- 通过全局配置注入密钥base64 编码),确保前后端一致。
- 关键实现要点
- 初始化:从全局配置读取 base64Key 并转换为字节数组作为密钥。
- 模式与输出:默认 ECB 模式与 Base64 输出,满足前端直传需求。
- 块处理:按 16 字节块进行填充、轮密钥变换与输出转换。
- 安全性
- ECB 模式适合小数据块加密,但不提供完整性校验;建议仅用于请求体加密场景。
- 密钥来源于全局配置,需确保其安全性与一致性。
- 性能与复杂度
- 单次加/解密为 O(n)n 为数据长度),块大小固定为 16 字节。
- 使用建议
- 对大文本建议分片处理,避免一次性内存压力。
- 与网络层配合使用,避免在本地重复加密。
```mermaid
classDiagram
class TsCrypto {
+constructor()
+encrypt(content) string
+decrypt(base64) string
-sm4 : TsSM4
}
class TsSM4 {
+constructor(config)
+encrypt(plaintext) string
+decrypt(ciphertext) string
-mode : string
-cipherType : string
-key : Uint8Array
-iv : Uint8Array
-encryptRoundKeys : Uint32Array
-decryptRoundKeys : Uint32Array
}
TsCrypto --> TsSM4 : "组合"
```
图表来源
- [TsCrypto.js:5-34](file://src/utils/TsCrypto.js#L5-L34)
- [TsSM4.js:96-156](file://src/utils/TsSM4.js#L96-L156)
章节来源
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
- [TsSM4.js:1-456](file://src/utils/TsSM4.js#L1-L456)
- [TsGlobalConfig.js:19-29](file://src/utils/TsGlobalConfig.js#L19-L29)
### 网络层与存储/加密集成TsHttpUtil
- 功能职责
- 在请求前根据加密开关对请求体进行加密,并替换为 { encryptData: 密文 }。
- 在响应后根据响应标记进行解密,并解析 JSON。
- 自动注入 token 到请求头。
- 关键流程
- 请求前处理:读取加密开关,若开启则对 data 进行加密;读取 token 注入到 headers。
- 响应后处理:若响应标记为加密,则解密并解析 JSON否则直接返回 data。
- 错误处理
- 统一错误处理器返回标准化错误对象。
- 性能与复杂度
- 主要开销在 JSON 序列化/反序列化与 SM4 加解密,整体为 O(n)。
- 使用建议
- 通过全局配置统一设置加密开关与密钥,避免分散配置。
```mermaid
sequenceDiagram
participant C as "调用方"
participant H as "TsHttpUtil"
participant S as "TsStorage"
participant E as "TsCrypto"
participant M as "TsSM4"
participant R as "后端"
C->>H : "post(url, {data})"
H->>S : "getEncryptBody()"
alt "加密开启"
H->>E : "encrypt(JSON.stringify(data))"
E->>M : "encrypt(明文)"
M-->>E : "密文"
E-->>H : "密文"
H->>R : "POST { encryptData : 密文 }"
else "加密关闭"
H->>R : "POST { data }"
end
R-->>H : "响应(可能含 encrypt 标记)"
alt "响应需解密"
H->>E : "decrypt(密文)"
E->>M : "decrypt(密文)"
M-->>E : "明文"
E-->>H : "明文"
H->>H : "parseJSON(明文)"
end
H-->>C : "{ data, recordsTotal }"
```
图表来源
- [TsHttpUtil.js:50-91](file://src/https/TsHttpUtil.js#L50-L91)
- [TsHttpUtil.js:117-123](file://src/https/TsHttpUtil.js#L117-L123)
- [TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23)
- [TsCrypto.js:19-30](file://src/utils/TsCrypto.js#L19-L30)
- [TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387)
章节来源
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
- [TsSM4.js:1-456](file://src/utils/TsSM4.js#L1-L456)
### API 接口文档(存储模块)
- 保存用户 token
- 方法saveUserToken(token)
- 作用:将 token 以固定键名保存至 localStorage
- 返回:无
- 参考:[TsStorage.js:9-11](file://src/utils/TsStorage.js#L9-L11)
- 获取用户 token
- 方法getUserToken()
- 作用:从 localStorage 读取 token未命中返回空字符串
- 返回:字符串
- 参考:[TsStorage.js:13-15](file://src/utils/TsStorage.js#L13-L15)
- 开启/关闭请求体加密
- 方法saveEncryptBody(bool)
- 作用:保存布尔值以控制请求体是否加密
- 返回:无
- 参考:[TsStorage.js:17-19](file://src/utils/TsStorage.js#L17-L19)
- 读取加密开关
- 方法getEncryptBody()
- 作用:读取加密开关,未命中返回默认 true
- 返回:布尔值
- 参考:[TsStorage.js:21-23](file://src/utils/TsStorage.js#L21-L23)
- 通用保存
- 方法save(key, value)
- 作用:将任意值序列化后保存至 localStorage
- 返回:无
- 参考:[TsStorage.js:31-33](file://src/utils/TsStorage.js#L31-L33)
- 通用获取
- 方法get(key, def)
- 作用:从 localStorage 读取并解析 JSON返回 data 字段
- 返回:任意类型(默认值为传入 def
- 参考:[TsStorage.js:41-43](file://src/utils/TsStorage.js#L41-L43)
章节来源
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
### 数据序列化与反序列化
- 序列化
- 将任意值包装为 {data: value},再通过 JSON.stringify 转为字符串,写入 localStorage。
- 优点:统一结构,便于后续解析;可扩展字段(如版本号)。
- 参考:[TsStorage.js:31-33](file://src/utils/TsStorage.js#L31-L33)
- 反序列化
- 从 localStorage 读取字符串,使用通用工具解析为对象,取 data 字段作为实际值。
- 若解析失败或未命中返回默认值def
- 参考:[TsStorage.js:41-43](file://src/utils/TsStorage.js#L41-L43), [TsCommon.js:34-44](file://src/utils/TsCommon.js#L34-L44)
章节来源
- [TsStorage.js:31-43](file://src/utils/TsStorage.js#L31-L43)
- [TsCommon.js:34-44](file://src/utils/TsCommon.js#L34-L44)
### 用户 token 管理
- 存储位置:固定键名为 token
- 读写接口saveUserToken/getUserToken
- 使用场景:网络层在请求头中注入 token实现鉴权
- 参考:[TsStorage.js:9-15](file://src/utils/TsStorage.js#L9-L15), [TsHttpUtil.js:109-111](file://src/https/TsHttpUtil.js#L109-L111)
章节来源
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
- [TsHttpUtil.js:109-111](file://src/https/TsHttpUtil.js#L109-L111)
### 加密开关控制与数据生命周期
- 加密开关
- 保存键名encrypt_body
- 默认值true开启加密
- 作用:控制网络层是否对请求体进行加密
- 参考:[TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23), [TsHttpUtil.js:82-86](file://src/https/TsHttpUtil.js#L82-L86)
- 生命周期
- 保存saveEncryptBody(bool)
- 读取getEncryptBody(),未命中返回 true
- 删除localStorage.removeItem("encrypt_body")
- 参考:[TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23)
章节来源
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
- [TsHttpUtil.js:80-91](file://src/https/TsHttpUtil.js#L80-L91)
### 存储模块与加密模块的集成关系
- 网络层在请求前读取加密开关,决定是否对 data 进行加密。
- 响应后若标记为加密,网络层进行解密并解析 JSON。
- 存储层负责持久化 token 与加密开关,形成闭环。
- 参考:[TsHttpUtil.js:80-91](file://src/https/TsHttpUtil.js#L80-L91), [TsHttpUtil.js:117-123](file://src/https/TsHttpUtil.js#L117-L123), [TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23)
章节来源
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
### 数据安全传输与存储最佳实践
- 传输安全
- 使用加密开关对请求体进行加密,避免明文在网络中传输。
- 仅对必要字段加密,避免过度加密影响性能。
- 参考:[TsHttpUtil.js:80-91](file://src/https/TsHttpUtil.js#L80-L91)
- 存储安全
- 不在 localStorage 中存储敏感明文(如密码、私钥)。
- 使用加密开关保护本地缓存的敏感数据。
- 参考:[TsStorage.js:31-43](file://src/utils/TsStorage.js#L31-L43)
- 配置安全
- 密钥来源于全局配置,需确保其保密性与一致性。
- 参考:[TsGlobalConfig.js:19-29](file://src/utils/TsGlobalConfig.js#L19-L29), [TsCrypto.js:7-13](file://src/utils/TsCrypto.js#L7-L13)
章节来源
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
- [TsGlobalConfig.js:1-34](file://src/utils/TsGlobalConfig.js#L1-L34)
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
### 使用示例
- 保存与读取普通数据
- 参考:[README.md:28-41](file://README.md#L28-L41)
- 设置加密开关
- 参考:[README.md:12-26](file://README.md#L12-L26)
- 保存用户 token
- 参考:[TsStorage.js:9-15](file://src/utils/TsStorage.js#L9-L15)
章节来源
- [README.md:1-43](file://README.md#L1-L43)
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
### 数据迁移策略与备份恢复
- 迁移策略
- 版本升级时,可在存储层增加版本字段,读取时进行兼容性处理。
- 对历史数据进行批量重写(如重新序列化),确保新结构可用。
- 参考:[TsStorage.js:31-43](file://src/utils/TsStorage.js#L31-L43)
- 备份与恢复
- 备份:读取所有键值并导出为 JSON 文件。
- 恢复:导入 JSON 后逐条写入 localStorage。
- 注意:避免在恢复过程中覆盖当前用户数据,建议先导入到临时键名,再合并。
- 参考:[TsStorage.js:31-43](file://src/utils/TsStorage.js#L31-L43)
章节来源
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
### 浏览器兼容性与存储容量限制
- 浏览器兼容性
- localStorage 在现代浏览器中广泛支持;在无痕模式或受限环境下可能不可用。
- 参考:[TsStorage.js:31-43](file://src/utils/TsStorage.js#L31-L43)
- 存储容量限制
- localStorage 通常为 510 MB因浏览器而异超出会抛出异常。
- 建议:对大对象进行分片或压缩,避免频繁写入导致溢出。
- 参考:[TsStorage.js:31-43](file://src/utils/TsStorage.js#L31-L43)
章节来源
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
## 依赖关系分析
- 模块耦合
- TsHttpUtil 依赖 TsStorage、TsCrypto、TsGlobalConfig形成“网络层-存储层-加密层-配置层”的链路。
- TsStorage 依赖 TsCommon用于安全解析 JSON。
- TsCrypto 依赖 TsSM4 与全局配置,提供加解密能力。
- 外部依赖
- base64-jsBase64 编解码与字节数组互转。
- umi-requestHTTP 请求封装与错误处理。
- 可能的循环依赖
- 当前模块间无循环依赖,结构清晰。
```mermaid
graph LR
Http["TsHttpUtil"] --> Store["TsStorage"]
Http --> Crypto["TsCrypto"]
Http --> Global["TsGlobalConfig"]
Store --> Common["TsCommon"]
Crypto --> SM4["TsSM4"]
Crypto --> Global
```
图表来源
- [index.js:1-16](file://index.js#L1-L16)
- [TsHttpUtil.js:1-6](file://src/https/TsHttpUtil.js#L1-L6)
- [TsStorage.js:1](file://src/utils/TsStorage.js#L1)
- [TsCrypto.js:1-3](file://src/utils/TsCrypto.js#L1-L3)
- [TsSM4.js:1](file://src/utils/TsSM4.js#L1)
- [TsGlobalConfig.js:1-3](file://src/utils/TsGlobalConfig.js#L1-L3)
- [TsCommon.js:1](file://src/utils/TsCommon.js#L1)
章节来源
- [index.js:1-16](file://index.js#L1-L16)
- [package.json:19-22](file://package.json#L19-L22)
## 性能考量
- 序列化/反序列化成本O(n)n 为字符串长度;建议对大对象进行分片或压缩。
- 加解密成本SM4 单次加/解密 O(n),注意避免对频繁小数据进行重复加密。
- I/O 成本localStorage 读写为 O(1),但频繁写入可能导致主线程阻塞,建议批量写入或延迟写入。
- 建议:在业务层对热点数据进行缓存,减少重复序列化与写入。
## 故障排查指南
- 读取不到数据
- 检查键名是否正确;确认是否被覆盖或删除。
- 参考:[TsStorage.js:41-43](file://src/utils/TsStorage.js#L41-L43)
- JSON 解析失败
- 检查存储内容是否为合法 JSON确认是否被其他模块篡改。
- 参考:[TsCommon.js:34-44](file://src/utils/TsCommon.js#L34-L44)
- 加密/解密异常
- 检查密钥是否正确;确认 ECB 模式与 Base64 输出是否匹配。
- 参考:[TsCrypto.js:7-13](file://src/utils/TsCrypto.js#L7-L13), [TsSM4.js:338-387](file://src/utils/TsSM4.js#L338-L387)
- 请求未加密
- 检查加密开关是否开启;确认网络层是否正确读取开关。
- 参考:[TsHttpUtil.js:80-91](file://src/https/TsHttpUtil.js#L80-L91), [TsStorage.js:17-23](file://src/utils/TsStorage.js#L17-L23)
章节来源
- [TsStorage.js:1-55](file://src/utils/TsStorage.js#L1-L55)
- [TsCommon.js:1-98](file://src/utils/TsCommon.js#L1-L98)
- [TsCrypto.js:1-34](file://src/utils/TsCrypto.js#L1-L34)
- [TsSM4.js:1-456](file://src/utils/TsSM4.js#L1-L456)
- [TsHttpUtil.js:1-171](file://src/https/TsHttpUtil.js#L1-L171)
## 结论
TsStorage 通过统一的序列化/反序列化与键值管理,为应用提供了简洁可靠的本地存储能力;结合加密模块与网络层,实现了从传输到存储的端到端安全方案。建议在生产环境中:
- 明确敏感数据边界,合理启用加密开关;
- 控制存储体积,避免 localStorage 溢出;
- 在升级时做好版本兼容与迁移策略;
- 严格管理密钥与配置,确保一致性与安全性。
## 附录
- 入口导出
- index.js 汇总导出各模块,便于统一引入。
- 参考:[index.js:8-15](file://index.js#L8-L15)
- 依赖清单
- base64-js、umi-request 等外部依赖。
- 参考:[package.json:19-22](file://package.json#L19-L22)
章节来源
- [index.js:1-16](file://index.js#L1-L16)
- [package.json:1-24](file://package.json#L1-L24)