ddcfe3334e
部署到群晖 / deploy (push) Successful in 44s
- Phase 1: 添加纪念日合并人物创建流程(方案 B) - Phase 2: 农历提醒按 lunarMonth/Day 计算每年公历 - Phase 3: 人员数据同步到后端(新增 /api/person) - Phase 4: 新设备启动从云端恢复数据 - Phase 5: 工具函数收敛 utils/format.js - Phase 6: 同步失败入队 + 启动重试 - Phase 7: 闰月生日完整支持(含 isLeapMonth + UI 警示) - 修复 lunarInfo 数据表错位(替换为权威源 jjonline/calendar.js) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
68 lines
1.9 KiB
JavaScript
68 lines
1.9 KiB
JavaScript
/**
|
|
* 同步管理:失败入队,启动时重试
|
|
* Why:自建后端、HTTPS 链路、定时任务任一环节抖动都会导致单次写入丢失。本地队列兜底,保证最终一致。
|
|
*/
|
|
|
|
const api = require('./api')
|
|
|
|
const QUEUE_KEY = 'pending_sync_queue'
|
|
|
|
function loadQueue() {
|
|
try { return wx.getStorageSync(QUEUE_KEY) || [] } catch (e) { return [] }
|
|
}
|
|
|
|
function saveQueue(q) {
|
|
try { wx.setStorageSync(QUEUE_KEY, q) } catch (e) {}
|
|
}
|
|
|
|
function enqueue(item) {
|
|
const q = loadQueue()
|
|
q.push({ ...item, ts: Date.now() })
|
|
saveQueue(q)
|
|
}
|
|
|
|
async function dispatch(item) {
|
|
if (item.kind === 'person') return api.person(item.action, item.data)
|
|
if (item.kind === 'anniversary') return api.anniversary(item.action, item.data)
|
|
throw new Error('unknown sync kind: ' + item.kind)
|
|
}
|
|
|
|
// 立即尝试同步;失败入队
|
|
async function syncOrEnqueue(item) {
|
|
try {
|
|
const res = await dispatch(item)
|
|
if (res && res.success === false) throw new Error(res.error || 'server returned failure')
|
|
return true
|
|
} catch (err) {
|
|
console.warn('[sync] 失败已入队:', item.kind, item.action, err.message || err)
|
|
enqueue(item)
|
|
return false
|
|
}
|
|
}
|
|
|
|
// 尝试 flush 整个队列,失败的留下下次再试
|
|
async function flush() {
|
|
const q = loadQueue()
|
|
if (q.length === 0) return { flushed: 0, remaining: 0 }
|
|
const remaining = []
|
|
let flushed = 0
|
|
for (const item of q) {
|
|
try {
|
|
const res = await dispatch(item)
|
|
if (res && res.success === false) throw new Error(res.error || 'server returned failure')
|
|
flushed++
|
|
} catch (err) {
|
|
remaining.push(item)
|
|
}
|
|
}
|
|
saveQueue(remaining)
|
|
if (flushed > 0) console.log(`[sync] 队列 flush 完成:成功 ${flushed},剩余 ${remaining.length}`)
|
|
return { flushed, remaining: remaining.length }
|
|
}
|
|
|
|
function getPendingCount() {
|
|
return loadQueue().length
|
|
}
|
|
|
|
module.exports = { syncOrEnqueue, flush, getPendingCount }
|