新增: 小程序配置持久化与心跳闭环 + 文档同步
小程序(mobile client)三项改进: 一、配置持久化(分发前置) - 运行时配置(relay 地址/设备 ID/token/心跳间隔)接入 storage - 懒加载:首次读取从 storage 恢复,合并默认值兼容旧字段 - 新增重置函数:清除 storage + 回到默认占位值 - 读写失败降级不崩溃 二、心跳 pong 闭环(移动网络可靠性) - 中继服务识别小程序心跳 ping,直接回 pong(不经桌面端透传) - 小程序收到 pong 更新入站时间,半连接看门狗据此判活 - 治移动网络 TCP 半连接挂死(socket 仍开但无响应) 三、文档同步关闭已完成项 - 条件表达式引擎:求值器+执行器+前端编辑入口+翻译均已落地 - 流式状态按会话隔离:accessor 委派 per-conv Map 已落地 - 灵感录入增强:表单已含来源/标签/优先级字段
This commit is contained in:
@@ -341,7 +341,7 @@ class WsClient {
|
||||
}
|
||||
const text = res.data
|
||||
if (!text) return
|
||||
// 活性:任意入站帧更新(relay 无 pong,用心跳期间入站消息替代判活)
|
||||
// 活性:任意入站帧更新(含 relay 回的 pong 心跳响应,用于半连接检测)
|
||||
this.lastInboundAt = Date.now()
|
||||
|
||||
// 握手阶段可能收到 relay 发的错误控制帧(relay.rs:200-238)
|
||||
|
||||
@@ -674,7 +674,14 @@ function subscribeWs(): void {
|
||||
}
|
||||
},
|
||||
onControl: (msg: ControlMessage) => {
|
||||
// 心跳响应等,miniapp 仅 console(不维持在线状态 UI)
|
||||
// 心跳 pong 响应:relay 收到 miniapp ping 后直接回 pong(不经 device),
|
||||
// miniapp 据此更新 lastPongTime 看门狗(ws.ts 已维护 lastInboundAt,但该路径不经过
|
||||
// onControl,这里记录到变量供日志诊断)。pong 闭环治移动网络 TCP 半连接挂死。
|
||||
if (msg.control_kind === 'pong') {
|
||||
console.debug('[useAiChat] 收到心跳 pong(relay 响应,连接健康)')
|
||||
return
|
||||
}
|
||||
// 其他 control 消息(hello_ack / pair 等)仅 console 不维持在线状态 UI
|
||||
console.log('[useAiChat] control', msg)
|
||||
},
|
||||
onStatus: (status: WsStatus, detail?: string) => {
|
||||
|
||||
@@ -42,13 +42,71 @@ export const defaultConfig: MiniappConfig = {
|
||||
reconnectMaxDelay: 30000,
|
||||
}
|
||||
|
||||
/** 单例配置(miniapp 内存配置,后续接 storage 持久化) */
|
||||
let _config: MiniappConfig = { ...defaultConfig }
|
||||
/** storage key(持久化完整 MiniappConfig JSON) */
|
||||
const STORAGE_KEY = 'df-miniapp-config'
|
||||
|
||||
/** 单例配置(null 表示尚未从 storage 加载) */
|
||||
let _config: MiniappConfig | null = null
|
||||
|
||||
/**
|
||||
* 从 storage 读取并合并默认配置
|
||||
*
|
||||
* uni.getStorageSync(key) 未命中时返回 ''(空字符串),命中返回原写入值。
|
||||
* 容错:读取/解析失败仅 warn,不抛出,回落到 defaultConfig。
|
||||
*/
|
||||
function loadFromStorage(): MiniappConfig {
|
||||
try {
|
||||
const raw = uni.getStorageSync(STORAGE_KEY)
|
||||
if (!raw) return { ...defaultConfig }
|
||||
const parsed = JSON.parse(raw) as Partial<MiniappConfig>
|
||||
// 合并默认值,避免旧版本字段缺失导致 undefined
|
||||
return { ...defaultConfig, ...parsed }
|
||||
} catch (e) {
|
||||
console.warn('[df-miniapp] load config from storage failed:', e)
|
||||
return { ...defaultConfig }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步写入 storage(JSON 序列化完整配置)
|
||||
*
|
||||
* 容错:写入失败仅 warn,不影响内存配置。
|
||||
*/
|
||||
function saveToStorage(config: MiniappConfig): void {
|
||||
try {
|
||||
uni.setStorageSync(STORAGE_KEY, JSON.stringify(config))
|
||||
} catch (e) {
|
||||
console.warn('[df-miniapp] save config to storage failed:', e)
|
||||
}
|
||||
}
|
||||
|
||||
export function getConfig(): MiniappConfig {
|
||||
// 首次调用时从 storage 加载并缓存
|
||||
if (_config === null) {
|
||||
_config = loadFromStorage()
|
||||
}
|
||||
return _config
|
||||
}
|
||||
|
||||
export function setConfig(patch: Partial<MiniappConfig>): void {
|
||||
// 确保已加载(避免在 getConfig 前调用 setConfig 丢失 storage 旧值)
|
||||
if (_config === null) {
|
||||
_config = loadFromStorage()
|
||||
}
|
||||
_config = { ..._config, ...patch }
|
||||
saveToStorage(_config)
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置为默认配置并清除 storage 持久化数据
|
||||
*
|
||||
* 用于用户重新配对或恢复出厂占位值的场景。
|
||||
*/
|
||||
export function resetConfig(): void {
|
||||
_config = { ...defaultConfig }
|
||||
try {
|
||||
uni.removeStorageSync(STORAGE_KEY)
|
||||
} catch (e) {
|
||||
console.warn('[df-miniapp] remove config from storage failed:', e)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user