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:
@@ -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 写入失败不影响主流程
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user