# 接口加密与本地数据缓存模块文档
## 目录
- [一、接口加密模块](#一接口加密模块)
- [二、本地数据缓存模块](#二本地数据缓存模块)
- [三、快速集成指南](#三快速集成指南)
- [四、常见问题与解决方案](#四常见问题与解决方案)
---
## 一、接口加密模块
### 1.1 加密原理
- **加密算法**: XOR 加密 + Base64 编码
- **签名验证**: 基于时间戳的哈希签名
- **编码方式**: 自定义 UTF-8 编码/解码(兼容 APP 环境)
### 1.2 前端实现
#### 1.2.1 核心文件:`common/crypto-utils.js`
```javascript
import config from '@/config/config'
class CryptoUtils {
constructor() {
this.key = config.cryptoKey || 'ykzs2024'
this.enabled = config.cryptoEnabled !== undefined ? config.cryptoEnabled : false
}
// UTF-8 编码(兼容 TextEncoder)
stringToBytes(str) {
const bytes = []
for (let i = 0; i < str.length; i++) {
const charCode = str.charCodeAt(i)
if (charCode < 128) {
bytes.push(charCode)
} else if (charCode < 2048) {
bytes.push((charCode >> 6) | 192)
bytes.push((charCode & 63) | 128)
} else if (charCode < 65536) {
bytes.push((charCode >> 12) | 224)
bytes.push(((charCode >> 6) & 63) | 128)
bytes.push((charCode & 63) | 128)
} else {
bytes.push((charCode >> 18) | 240)
bytes.push(((charCode >> 12) & 63) | 128)
bytes.push(((charCode >> 6) & 63) | 128)
bytes.push((charCode & 63) | 128)
}
}
return new Uint8Array(bytes)
}
// UTF-8 解码(兼容 TextDecoder)
bytesToString(bytes) {
let str = ''
let i = 0
while (i < bytes.length) {
const byte = bytes[i]
if (byte < 128) {
str += String.fromCharCode(byte)
i++
} else if (byte < 224) {
str += String.fromCharCode(((byte & 31) << 6) | (bytes[i + 1] & 63))
i += 2
} else if (byte < 240) {
str += String.fromCharCode(((byte & 15) << 12) | ((bytes[i + 1] & 63) << 6) | (bytes[i + 2] & 63))
i += 3
} else {
str += String.fromCharCode(((byte & 7) << 18) | ((bytes[i + 1] & 63) << 12) | ((bytes[i + 2] & 63) << 6) | (bytes[i + 3] & 63))
i += 4
}
}
return str
}
// XOR 加密
xorEncrypt(bytes, keyBytes) {
const result = new Uint8Array(bytes.length)
for (let i = 0; i < bytes.length; i++) {
result[i] = bytes[i] ^ keyBytes[i % keyBytes.length]
}
return result
}
// 加密数据
encrypt(data) {
if (!this.enabled) return data
try {
const jsonStr = JSON.stringify(data)
const dataBytes = this.stringToBytes(jsonStr)
const keyBytes = this.stringToBytes(this.key)
const xorBytes = this.xorEncrypt(dataBytes, keyBytes)
let binary = ''
for (let i = 0; i < xorBytes.length; i++) {
binary += String.fromCharCode(xorBytes[i])
}
return btoa(binary)
} catch (e) {
console.error('加密失败:', e)
return data
}
}
// 解密数据
decrypt(encryptedData) {
if (!this.enabled) return encryptedData
try {
const binary = atob(encryptedData)
const bytes = new Uint8Array(binary.length)
for (let i = 0; i < binary.length; i++) {
bytes[i] = binary.charCodeAt(i)
}
const keyBytes = this.stringToBytes(this.key)
const xorBytes = this.xorEncrypt(bytes, keyBytes)
const jsonStr = this.bytesToString(xorBytes)
return JSON.parse(jsonStr)
} catch (e) {
console.error('解密失败:', e)
return encryptedData
}
}
// 生成签名
generateSign(timestamp) {
const input = timestamp + this.key
const sign = this.simpleHash(input)
return sign
}
// 简单哈希算法
simpleHash(str) {
let hash = 0
if (str.length === 0) return '0'
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i)
hash = ((hash << 5) - hash) + char
hash = hash & 0x7FFFFFFF
}
return hash.toString(16)
}
}
export default new CryptoUtils()
```
#### 1.2.2 HTTP 拦截器:`common/http.interceptor.js`
```javascript
import config from '@/config/config';
import cryptoUtils from '@/common/crypto-utils.js';
// 请求拦截器
Vue.prototype.$u.http.interceptor.request = (config) => {
// 添加 token
if (vm.token) {
config.header['token'] = vm.token;
}
// 添加时间戳和签名
const timestamp = Math.floor(Date.now() / 1000);
const sign = cryptoUtils.generateSign(timestamp);
// 加密数据
if (cryptoUtils.enabled) {
if (config.data && typeof config.data === 'object') {
config.data = {
encrypted: cryptoUtils.encrypt(config.data),
timestamp: timestamp,
sign: sign
};
}
if (config.params && typeof config.params === 'object') {
config.params = {
encrypted: cryptoUtils.encrypt(config.params),
timestamp: timestamp,
sign: sign
};
}
} else {
// 不加密时直接添加时间戳和签名
if (config.data && typeof config.data === 'object') {
config.data = {
...config.data,
timestamp: timestamp,
sign: sign
};
}
if (config.params && typeof config.params === 'object') {
config.params = {
...config.params,
timestamp: timestamp,
sign: sign
};
}
}
return config;
}
// 响应拦截器
Vue.prototype.$u.http.interceptor.response = (response) => {
let res = response.data;
// 解密响应数据
if (cryptoUtils.enabled && res && res.encrypted) {
res = cryptoUtils.decrypt(res.encrypted);
}
return res;
}
```
#### 1.2.3 配置文件:`config/config.js`
```javascript
export default {
// 加密配置
cryptoKey: 'ykzs2024', // 加密密钥
cryptoEnabled: true, // 是否启用加密
}
```
### 1.3 后端实现(ThinkPHP)
#### 1.3.1 中间件:`application/api/middleware/Api.php`
```php
<?php
namespace appapimiddleware;
use thinkRequest;
use thinkResponse;
class Api
{
public function handle(Request $request, Closure $next)
{
$cryptoEnabled = config('crypto.enabled');
if ($cryptoEnabled) {
// 获取加密参数
$encrypted = $request->param('encrypted');
$timestamp = $request->param('timestamp');
$sign = $request->param('sign');
if ($encrypted) {
// 验证签名
$expectedSign = $this->generateSign($timestamp);
if ($sign !== $expectedSign) {
return json(['code' => 0, 'msg' => '签名验证失败']);
}
// 解密数据
$decryptedData = $this->decrypt($encrypted);
if ($decryptedData) {
// 使用反射修改请求对象
$reflection = new ReflectionClass($request);
$property = $reflection->getProperty('param');
$property->setAccessible(true);
$property->setValue($request, $decryptedData);
// 同时修改 $_GET、$_POST、$_REQUEST
$_GET = array_merge($_GET, $decryptedData);
$_POST = array_merge($_POST, $decryptedData);
$_REQUEST = array_merge($_REQUEST, $decryptedData);
}
}
}
$response = $next($request);
// 清理加密相关字段
if ($cryptoEnabled) {
$data = $response->getData();
if (is_array($data)) {
unset($data['encrypted'], $data['timestamp'], $data['sign']);
$response->data($data);
}
}
return $response;
}
private function generateSign($timestamp)
{
$key = config('crypto.key');
$input = $timestamp . $key;
return $this->simpleHash($input);
}
private function simpleHash($str)
{
$hash = 0;
if (strlen($str) === 0) return '0';
for ($i = 0; $i < strlen($str); $i++) {
$char = ord($str[$i]);
$hash = (($hash << 5) - $hash) + $char;
$hash = $hash & 0x7FFFFFFF;
}
return dechex($hash);
}
private function decrypt($encryptedData)
{
$key = config('crypto.key');
try {
// Base64 解码
$binary = base64_decode($encryptedData);
// XOR 解密
$keyBytes = $this->stringToBytes($key);
$dataBytes = $this->stringToBytes($binary);
$xorBytes = $this->xorEncrypt($dataBytes, $keyBytes);
// 转换为字符串
$jsonStr = $this->bytesToString($xorBytes);
return json_decode($jsonStr, true);
} catch (Exception $e) {
return null;
}
}
private function stringToBytes($str)
{
$bytes = [];
$len = strlen($str);
for ($i = 0; $i < $len; $i++) {
$bytes[] = ord($str[$i]);
}
return $bytes;
}
private function bytesToString($bytes)
{
$str = '';
foreach ($bytes as $byte) {
$str .= chr($byte);
}
return $str;
}
private function xorEncrypt($bytes, $keyBytes)
{
$result = [];
$keyLen = count($keyBytes);
for ($i = 0; $i < count($bytes); $i++) {
$result[] = $bytes[$i] ^ $keyBytes[$i % $keyLen];
}
return $result;
}
}
```
#### 1.3.2 配置文件:`config/crypto.php`
```php
<?php
return [
'enabled' => true,
'key' => 'ykzs2024',
];
```
### 1.4 使用注意事项
1. **密钥安全**: 前后端必须使用相同的密钥
2. **签名验证**: 确保时间戳和签名正确,防止重放攻击
3. **错误处理**: 加密/解密失败时要有降级方案
4. **性能考虑**: 加密会增加 CPU 开销,根据实际需求选择是否启用
5. **兼容性**: 自定义 UTF-8 编码确保在 APP 环境中也能正常工作
---
## 二、本地数据缓存模块
### 2.1 缓存架构
```
DataCache (数据缓存管理器)
├── cacheMap (缓存键映射)
├── cacheTime (默认缓存时间: 30分钟)
├── indexCacheTime (首页缓存时间: 1分钟)
├── apiInstance (API 实例)
└── syncService (同步服务)
```
### 2.2 核心文件:`common/data-cache.js`
#### 2.2.1 缓存配置
```javascript
this.cacheMap = {
'customer': 'customers',
'reservation': 'reservations',
'treatment': 'treatments',
'bill': 'bills',
'message': 'messages',
'category_pay': 'categories_pay',
'category_income': 'categories_income',
'anli': 'anlis',
'index': 'indexData',
'user': 'user_info'
}
this.cacheTime = 30 * 60 * 1000 // 默认缓存时间:30分钟
this.indexCacheTime = 1 * 60 * 1000 // 首页和用户信息缓存时间:1分钟
```
#### 2.2.2 API 方法映射
```javascript
getApiMethod(type) {
const apiMap = {
'customer': (params) => this.apiInstance.getCustomerList({ ...params, local: 1 }),
'reservation': (params) => this.apiInstance.getReservationList({ ...params, local: 1 }),
'treatment': (params) => this.apiInstance.getTreatmentList({ ...params, local: 1 }),
'bill': (params) => this.apiInstance.getIncomeDetails({ ...params, local: 1 }),
'message': (params) => this.apiInstance.getNoticeList({ ...params, local: 1 }),
'category_pay': (params) => this.apiInstance.getTypeInfo({ ...params, type: 'pay' }),
'category_income': (params) => this.apiInstance.getTypeInfo({ ...params, type: 'income' }),
'anli': (params) => this.apiInstance.getAnliList({ ...params, local: 1 }),
'index': (params) => this.apiInstance.getCustomerIndexData(params),
'user': (params) => this.apiInstance.getInfo(params)
}
return apiMap[type]
}
```
#### 2.2.3 获取数据
```javascript
async getData(type, params = {}) {
const cacheKey = this.cacheMap[type]
const useLocalData = uni.getStorageSync('useLocalData') !== false
let data = storage.get(cacheKey)
// 1. 优先使用本地缓存
if (useLocalData && data && this.isValid(data, type)) {
const result = this.formatResponse(type, data, params)
return result
}
// 2. 从服务器获取
if (this.apiInstance) {
try {
const apiMethod = this.getApiMethod(type)
const res = await apiMethod(params)
if (res && res.code === 1) {
let cacheData
if (type === 'message') {
cacheData = Array.isArray(res.data) ? res.data : (res.data.list?.data || res.data.list || [])
} else if (type === 'user') {
cacheData = res.data
} else {
cacheData = Array.isArray(res.data) ? res.data : (res.data.list || [])
}
cacheData.cacheTime = Date.now()
storage.set(cacheKey, cacheData)
return this.formatResponse(type, cacheData, params)
}
} catch (e) {
console.error('从服务器获取数据失败', e)
}
}
// 3. 返回缓存或默认数据
if (data) {
return this.formatResponse(type, data, params)
}
return this.getDefaultData(type)
}
```
#### 2.2.4 保存数据
```javascript
async saveData(type, data, action = 'add') {
const cacheKey = this.cacheMap[type]
let list = storage.get(cacheKey) || []
if (action === 'add') {
data.id = data.id || Date.now()
data.createTime = new Date().toISOString()
list.unshift(data)
} else if (action === 'update') {
const index = list.findIndex(item => String(item.id) === String(data.id))
if (index !== -1) {
list[index] = { ...list[index], ...data, updateTime: new Date().toISOString() }
}
} else if (action === 'delete') {
list = list.filter(item => String(item.id) !== String(data.id))
// 删除相关数据
if (type === 'customer') {
this.deleteRelatedData(data.id)
}
}
list.cacheTime = Date.now()
storage.set(cacheKey, list)
syncService.addToQueue(action, type, data)
return { code: 1, msg: '操作成功', data: data }
}
```
#### 2.2.5 数据过滤
```javascript
filterData(data, params) {
if (!Array.isArray(data)) return data
let result = [...data]
// 关键词搜索
if (params.keyword) {
const keyword = params.keyword.toLowerCase()
result = result.filter(item => {
const searchFields = [
item.name, item.phone, item.project,
item.employee, item.content,
item.customer_info?.name,
item.customer_info?.phone
]
const fieldMatch = searchFields.some(val =>
val && String(val).toLowerCase().includes(keyword)
)
if (fieldMatch) return true
return Object.values(item).some(val =>
String(val).toLowerCase().includes(keyword)
)
})
}
// 状态过滤
if (params.status && params.status !== '待跟进' && params.status !== '已跟进') {
result = result.filter(item => item.status === params.status)
}
// 待跟进/已跟进
if (params.status === '待跟进') {
result = result.filter(item => !item.result || item.result === '')
} else if (params.status === '已跟进') {
result = result.filter(item => item.result && item.result !== '')
}
// 日期过滤
if (params.current_date) {
result = result.filter(item => {
let timeField = item.treatment_time || item.reserve_time
if (!timeField) return false
let itemDate
if (typeof timeField === 'number' || (!isNaN(timeField) && timeField.length <= 10)) {
const date = new Date(Number(timeField) * 1000)
itemDate = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`
} else {
itemDate = String(timeField).split(' ')[0]
}
return itemDate === params.current_date
})
}
// 分页
if (params.page && params.limit) {
const start = (params.page - 1) * params.limit
const end = start + params.limit
result = result.slice(start, end)
}
return result
}
```
### 2.3 使用示例
#### 2.3.1 在 local-api.js 中使用
```javascript
import dataCache from './data-cache.js'
class LocalApi {
// 获取顾客列表
async getCustomerList(params) {
return dataCache.getData('customer', params)
}
// 添加顾客
async addCustomer(data) {
return dataCache.saveData('customer', data, 'add')
}
// 更新顾客
async updateCustomer(data) {
return dataCache.saveData('customer', data, 'update')
}
// 删除顾客
async deleteCustomer(data) {
return dataCache.saveData('customer', data, 'delete')
}
// 获取用户信息
async getInfo(params) {
const res = await dataCache.getData('user', params)
if (res && res.code === 1) {
return res
}
return { code: 1, data: { user: {}, list: [], banner: { list: [], type: '' } } }
}
// 清除缓存
async clearAllCache() {
dataCache.clearAllCache()
return { code: 1, msg: '缓存已清除' }
}
}
```
#### 2.3.2 在页面中使用
```javascript
import localApi from '@/common/local-api.js'
export default {
data() {
return {
customerList: []
}
},
methods: {
async loadCustomers() {
const res = await localApi.getCustomerList({
page: 1,
limit: 20,
keyword: '张三'
})
if (res && res.code === 1) {
this.customerList = res.data.list
}
},
async addCustomer() {
const res = await localApi.addCustomer({
name: '李四',
phone: '13800138000'
})
if (res && res.code === 1) {
uni.showToast({ title: '添加成功' })
}
}
}
}
```
### 2.4 数据类型处理
#### 2.4.1 列表类型数据(customer、reservation、treatment、bill)
- 缓存结构:`{ list: [...], cacheTime: timestamp }`
- 返回格式:`{ code: 1, data: { list: [...], total: number } }`
#### 2.4.2 用户信息类型(user)
- 缓存结构:`{ user: {}, list: [], banner: {}, cacheTime: timestamp }`
- 返回格式:`{ code: 1, data: { user: {}, list: [], banner: {} } }`
#### 2.4.3 首页数据类型(index)
- 缓存结构:`{ ...data, cacheTime: timestamp }`
- 返回格式:`{ code: 1, data: { ...data } }`
#### 2.4.4 分类数据类型(category_pay、category_income)
- 缓存结构:`[...items, cacheTime: timestamp]`
- 返回格式:`{ code: 1, data: [...items] }`
### 2.5 注意事项
1. **缓存时间**: 根据数据更新频率设置合理的缓存时间
2. **数据同步**: 修改数据后自动添加到同步队列
3. **关联数据**: 删除顾客时自动删除相关预约、治疗、账单数据
4. **数据过滤**: 支持关键词搜索、状态过滤、日期过滤、分页
5. **错误处理**: 服务器请求失败时返回缓存数据或默认数据
6. **数据结构**: 不同类型的数据结构不同,需要在 `formatResponse` 中正确处理
---
## 三、快速集成指南
### 3.1 文件清单
#### 前端文件
```
jz_uniapp/
├── common/
│ ├── config.js # 配置文件
│ ├── crypto-utils.js # 加密工具类
│ ├── http.interceptor.js # HTTP 拦截器
│ ├── data-cache.js # 数据缓存管理器
│ ├── local-storage.js # 本地存储封装
│ ├── sync-service.js # 同步服务
│ └── local-api.js # 本地 API 封装
```
#### 后端文件
```
backend/
├── config/
│ └── crypto.php # 加密配置
└── application/api/middleware/
└── Api.php # API 中间件
```
### 3.2 集成步骤
#### 步骤 1:复制前端文件
1. 复制 `common/config.js` 到新项目
2. 复制 `common/crypto-utils.js` 到新项目
3. 复制 `common/http.interceptor.js` 到新项目
4. 复制 `common/data-cache.js` 到新项目
5. 复制 `common/local-storage.js` 到新项目
6. 复制 `common/sync-service.js` 到新项目
7. 复制 `common/local-api.js` 到新项目
#### 步骤 2:配置加密
1. 修改 `config/config.js` 中的加密配置:
```javascript
export default {
cryptoKey: 'your-secret-key', // 修改为你的密钥
cryptoEnabled: true, // 是否启用加密
}
```
2. 在 `main.js` 中初始化 HTTP 拦截器:
```javascript
import httpInterceptor from '@/common/http.interceptor.js'
Vue.prototype.$u.http.interceptor.request = httpInterceptor.request
Vue.prototype.$u.http.interceptor.response = httpInterceptor.response
```
#### 步骤 3:配置数据缓存
1. 在 `data-cache.js` 中添加你的数据类型:
```javascript
this.cacheMap = {
'your_type': 'your_cache_key',
// ... 其他类型
}
```
2. 在 `getApiMethod` 中添加 API 方法映射:
```javascript
getApiMethod(type) {
const apiMap = {
'your_type': (params) => this.apiInstance.getYourData(params),
// ... 其他类型
}
return apiMap[type]
}
```
3. 在 `local-api.js` 中添加 API 方法:
```javascript
async getYourData(params) {
return dataCache.getData('your_type', params)
}
async addYourData(data) {
return dataCache.saveData('your_type', data, 'add')
}
```
#### 步骤 4:复制后端文件
1. 复制 `config/crypto.php` 到新项目
2. 复制 `application/api/middleware/Api.php` 到新项目
3. 修改加密配置:
```php
<?php
return [
'enabled' => true,
'key' => 'your-secret-key', // 与前端保持一致
];
```
4. 在路由配置中应用中间件:
```php
Route::group(function () {
Route::rule('api/your-endpoint', 'api/YourController/method')
// ... 其他路由
})->middleware(appapimiddlewareApi::class);
```
#### 步骤 5:测试验证
1. 测试加密功能:
- 启用加密后,检查请求是否包含 `encrypted`、`timestamp`、`sign`
- 检查后端是否能正确解密数据
2. 测试缓存功能:
- 首次请求数据,检查是否从服务器获取
- 再次请求数据,检查是否使用缓存
- 修改数据后,检查缓存是否更新
3. 测试同步功能:
- 在离线状态下添加数据
- 恢复网络连接,检查数据是否同步到服务器
### 3.3 配置说明
#### 前端配置项
| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| cryptoKey | String | 'ykzs2024' | 加密密钥 |
| cryptoEnabled | Boolean | false | 是否启用加密 |
| useLocalData | Boolean | true | 是否使用本地数据 |
#### 后端配置项
| 配置项 | 类型 | 默认值 | 说明 |
|--------|------|--------|------|
| enabled | Boolean | true | 是否启用加密 |
| key | String | 'ykzs2024' | 加密密钥 |
---
## 四、常见问题与解决方案
### 4.1 加密相关问题
#### 问题 1:TextEncoder is not defined
**原因**: APP 环境不支持 TextEncoder/TextDecoder
**解决**: 使用自定义的 `stringToBytes` 和 `bytesToString` 方法
#### 问题 2:签名验证失败
**原因**: 前后端密钥不一致或时间戳计算错误
**解决**:
1. 确保前后端使用相同的密钥
2. 检查时间戳是否为秒级时间戳
3. 检查签名算法是否一致
#### 问题 3:解密失败
**原因**: 数据格式错误或编码问题
**解决**:
1. 确保加密数据是有效的 Base64 字符串
2. 检查 UTF-8 编码/解码是否正确
3. 添加错误处理和日志
### 4.2 缓存相关问题
#### 问题 1:缓存数据不更新
**原因**: 缓存时间未过期或未清除缓存
**解决**:
1. 修改数据后调用 `dataCache.clearCache(type)` 清除缓存
2. 调整缓存时间设置
3. 使用 `dataCache.refreshData(type, params)` 强制刷新
#### 问题 2:数据结构不匹配
**原因**: 不同类型的数据结构不同,未正确处理
**解决**:
1. 在 `formatResponse` 中为每种类型添加正确的处理逻辑
2. 在 `getData` 中为每种类型设置正确的缓存数据结构
3. 参考文档中的"数据类型处理"部分
#### 问题 3:数据同步失败
**原因**: 同步队列中缺少对应类型的处理逻辑
**解决**:
1. 在 `sync-service.js` 的 `syncItem` 方法中添加对应的 case
2. 确保同步时包含必要的参数(如 token)
3. 检查后端 API 是否正确处理同步请求
### 4.3 性能优化建议
1. **合理设置缓存时间**: 根据数据更新频率设置不同的缓存时间
2. **使用分页加载**: 大数据量时使用分页,避免一次性加载过多数据
3. **懒加载**: 非关键数据延迟加载
4. **压缩数据**: 对缓存数据进行压缩,减少存储空间
5. **定期清理**: 定期清理过期缓存,释放存储空间
### 4.4 安全建议
1. **密钥管理**: 不要将密钥硬编码在代码中,使用环境变量
2. **HTTPS**: 生产环境必须使用 HTTPS
3. **签名验证**: 严格验证签名,防止重放攻击
4. **数据脱敏**: 敏感数据在传输前进行脱敏处理
5. **日志记录**: 记录加密/解密操作,便于问题排查
---
## 附录
### A. 完整示例代码
参见项目中的以下文件:
- `jz_uniapp/common/crypto-utils.js`
- `jz_uniapp/common/http.interceptor.js`
- `jz_uniapp/common/data-cache.js`
- `backend/application/api/middleware/Api.php`
### B. API 参考
#### CryptoUtils
| 方法 | 参数 | 返回值 | 说明 |
|------|------|--------|------|
| encrypt(data) | Object/String | String | 加密数据 |
| decrypt(encryptedData) | String | Object/String | 解密数据 |
| generateSign(timestamp) | Number | String | 生成签名 |
#### DataCache
| 方法 | 参数 | 返回值 | 说明 |
|------|------|--------|------|
| getData(type, params) | String, Object | Promise | 获取数据 |
| saveData(type, data, action) | String, Object, String | Promise | 保存数据 |
| clearCache(type) | String | void | 清除缓存 |
| clearAllCache() | - | void | 清除所有缓存 |
| refreshData(type, params) | String, Object | Promise | 刷新数据 |
### C. 更新日志
- 2026-03-04: 初始版本
- 实现接口加密模块
- 实现本地数据缓存模块
- 添加快速集成指南
- 添加常见问题与解决方案
---
**文档版本**: 1.0.0
**最后更新**: 2026-03-04
**维护者**: AI Assistant