feat(mp): AES-256-GCM 加密存储 + 安全日志 + ErrorBoundary 升级 + BLE 并发修复

- secure-storage-aes: AES-256-GCM 替代 XOR,保留 XOR 迁移读取
- crypto-polyfill: wx.getRandomValuesSync → crypto.getRandomValues
- logger.ts: dev/prod 区分日志级别,生产不输出详情
- ErrorBoundary: 错误分类(network/render/unknown) + 结构化日志
- DataSyncScheduler: isSyncing 互斥防并发重复同步
- app.tsx 首行导入 crypto-polyfill
This commit is contained in:
iven
2026-05-22 00:13:37 +08:00
parent 29543ef0e7
commit 21f8040994
7 changed files with 329 additions and 115 deletions

View File

@@ -26,6 +26,7 @@ export interface SyncResult {
export class DataSyncScheduler {
private config: Required<SyncSchedulerConfig>;
private timerId: ReturnType<typeof setInterval> | null = null;
private isSyncing = false;
constructor(config?: SyncSchedulerConfig) {
this.config = { ...DEFAULT_CONFIG, ...config };
@@ -40,14 +41,21 @@ export class DataSyncScheduler {
/** 执行同步并记录时间戳 */
async recordSync(syncFn: () => Promise<SyncResult>): Promise<SyncResult> {
if (this.isSyncing) {
return { success: false, uploadedCount: 0, error: '同步进行中' };
}
this.isSyncing = true;
try {
const result = await syncFn();
if (result.success) {
this.saveRecord({ lastSyncAt: Date.now() });
}
return result;
} catch (e: any) {
return { success: false, uploadedCount: 0, error: e.message || '同步失败' };
} catch (e: unknown) {
const message = e instanceof Error ? e.message : '同步失败';
return { success: false, uploadedCount: 0, error: message };
} finally {
this.isSyncing = false;
}
}
@@ -96,7 +104,6 @@ export class DataSyncScheduler {
Taro.setStorageSync(this.config.storageKey, JSON.stringify(record));
} catch (err) {
console.warn('[ble-sync] Storage 操作失败:', err);
// Storage 写入失败不影响主流程
}
}
}