小程序(mobile client)三项改进: 一、配置持久化(分发前置) - 运行时配置(relay 地址/设备 ID/token/心跳间隔)接入 storage - 懒加载:首次读取从 storage 恢复,合并默认值兼容旧字段 - 新增重置函数:清除 storage + 回到默认占位值 - 读写失败降级不崩溃 二、心跳 pong 闭环(移动网络可靠性) - 中继服务识别小程序心跳 ping,直接回 pong(不经桌面端透传) - 小程序收到 pong 更新入站时间,半连接看门狗据此判活 - 治移动网络 TCP 半连接挂死(socket 仍开但无响应) 三、文档同步关闭已完成项 - 条件表达式引擎:求值器+执行器+前端编辑入口+翻译均已落地 - 流式状态按会话隔离:accessor 委派 per-conv Map 已落地 - 灵感录入增强:表单已含来源/标签/优先级字段
113 lines
3.7 KiB
TypeScript
113 lines
3.7 KiB
TypeScript
/**
|
|
* miniapp 运行时配置(host/device_id/token 占位,由用户在设置页或 build env 填)
|
|
*
|
|
* 这些值在真实部署前是占位:
|
|
* - RELAY_HOST:ws/wss 地址,需替换为实际部署的 df-relay 地址
|
|
* - DEVICE_ID:用户首次配置桌面端时生成的设备 ID
|
|
* - TOKEN:对齐 df-relay 的 DF_RELAY_TOKEN(生产建议每 device 独立 token)
|
|
*/
|
|
|
|
export interface MiniappConfig {
|
|
/** relay WS 地址(含协议),如 'ws://192.168.1.100:8080/ws/miniapp' 或 'wss://relay.example.com/ws/miniapp' */
|
|
relayHost: string
|
|
/** 配对绑定的设备 ID */
|
|
deviceId: string
|
|
/** 配对 token(对齐 df-relay DF_RELAY_TOKEN) */
|
|
token: string
|
|
/** 心跳间隔(ms) */
|
|
heartbeatInterval: number
|
|
/** 重连初始间隔(ms,指数退避) */
|
|
reconnectBaseDelay: number
|
|
/** 重连最大间隔(ms) */
|
|
reconnectMaxDelay: number
|
|
}
|
|
|
|
/**
|
|
* 默认配置(占位值,需替换)
|
|
*
|
|
* 真实部署:用户在设置页填 relayHost/deviceId/token,或通过 build-time env 注入。
|
|
* MVP 阶段留占位让类型自洽,实际连接会失败(token 校验不通过 → relay 关连接,
|
|
* 这符合预期,提示用户配置)。
|
|
*/
|
|
export const defaultConfig: MiniappConfig = {
|
|
// 测试服 wss(u-work.1216.top → nginx 终止 TLS → df-relay :9180 明文 ws)
|
|
// 微信小程序真机要求 wss + socket 合法域名白名单(微信公众平台→开发设置→服务器域名)
|
|
relayHost: 'wss://u-work.1216.top/ws/miniapp',
|
|
// 配对桌面端 device_id(查桌面端 KV app_settings:device_id;填错则握手过但路由无对端)
|
|
// 当前填本机桌面端 device_id(联调期硬编码,后续做配对绑定流程)
|
|
deviceId: '1b92cbbd-d03e-4a0c-b226-9fadf8dcf0f0',
|
|
token: 'devflow-relay-default-token',
|
|
heartbeatInterval: 30000,
|
|
reconnectBaseDelay: 1000,
|
|
reconnectMaxDelay: 30000,
|
|
}
|
|
|
|
/** 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)
|
|
}
|
|
}
|