Seetong · Report

🎯 Seetong 问题雷达 第258期

时间窗口:2026-10-26 17:00:00~2026-10-27 17:00:00

📌TL;DR 核心要点

  • 🔴 iOS 8.4.1.6 长连接一夜重建 37 次、每 6 分钟切一次接入节点,报警推送与设备在线态因此丢包(严重度 76,置信度 中)
  • 🟠 iOS 8.4.1.6 报警页首次进入要卡十几秒,通知权限查询与列表重建都在主线程上(严重度 68,置信度 中)
  • 反馈 259780:2026-10-26 23:48:36,iOS 8.4.1.6,iPhone 26.6,山东(账号尾号 4123),原文“报警很卡”,随附 Logan(8 129 行,覆盖 2026-10-26 00:16~23:47)。

🔥最近一个月 Top 问题

按严重度与复发期数排序,已把跨期同类反馈归集;负责人由问题代码锚点对应的 Git 提交历史(blame / 近期主要提交者)反查;数据窗口:最近 30 天(截至 2026-10-27)。

#问题(严重度降序)严重度平台版本负责人问题原因
1HarmonyOS `1.1.2.3` 多用户离线与核心视频链路失效
20 期 · 170 条反馈
100Android · HarmonyOS1.1.1.11 / 8.4.1.6 / 1.1.2.3陈宝旺、唐胜、冉博麟、谭伟HarmonyOS 客户端把 P2P 瞬时离线写成本地持久状态,并在后续在线判断中优先使用这个旧值,可能导致设备已恢复在线却仍显示离线;回放离线态和播放错误透传不足则放大了用户的“看不到画面”体验。
2Android `8.4.1.6` HEVC 预览以零宽高启动解码器
1 期 · 3 条反馈
90Android8.4.1.6张威、唐胜、谭伟Android 8.4.1.6 在首次 TPS_AddWachtRsp 尚未提供有效 HEVC 宽高时,仍立即调用 OpenStreamAgent 创建 MediaCodec,系统以 BAD_VALUE 拒绝零宽高配置,而客户端没有等待后续媒体参数或建立明确失败终态。
3Android 与 iOS 8.4.1.6 报警功能突然失效与通知不达
1 期 · 3 条反馈
90Android · iOS8.4.1.6唐胜、许源现有客户端样本表明 Android 通知权限与 token 注册均成功,故障更接近“服务端未生成报警或推送任务未送达”,但神策缺少报警生成与推送到达事件,iOS 样本又混合了通知权限关闭,当前不能完成单点定因。
4HarmonyOS 画中画状态导致切换设备后仍显示前一路画面
1 期 · 3 条反馈
90HarmonyOS1.1.1.11 / 1.1.2.3张跃译多个 HarmonyOS 画面共享一个无代次、无串行化、无旧控制器清理的 PipManager,切换设备时旧创建任务和新选择竞争,最终把第一路 XComponent、savId 或恢复状态保留下来。
5升级后回放体验整体退化
5 期 · 20 条反馈
85Android · HarmonyOS · iOS8.4.1.6 / 1.1.2.3 / 8.3.14.2唐胜、许源、欧阳荣、谭伟8.4.1.6 对回放链路做了多处改动(时间条 UI、通道切换进度对齐、报警-录像联动),导致回放体验多点退化;Logan 显示取流层无崩溃,问题在"UI/状态对齐 + 报警录像关联"而非连接失败。
6KMP 回放页未申请屏幕常亮,回放中手机自动息屏
11 期 · 27 条反馈
84Android · HarmonyOS8.4.1.6 / 8.4.1 / 8.4.2唐胜、陈宝旺、谭伟、许源KMP 回放页的屏幕常亮能力已在代码中完整实现(KMP 公共层 → 桥接层 → Android 宿主层齐备),但承载该实现的提交只落在 feature_v8.4.2 一条分支上,feature_v8.4.4、master、hotfix_v1.1.1 全部不含,因此所有已发布版本(Android 8.4.1.6 / HarmonyOS 1.1.1.11)在运行时都走不到 FLAG_KEEP_SCREEN_ON,回放过程中发生系统级息屏。
7Android 实时预览无首帧却被标记为“视频播放中”,并无限重试
7 期 · 22 条反馈
80Android · iOS8.4.1.6 / 1.1.2.3 / 8.1.1.11唐胜、陈宝旺、欧阳荣、谭伟预览页把“取流请求已提交”或“设备在线状态消息”误当成播放成功,而没有把首帧到达作为唯一成功门禁;add_watch_result=-1 后仍持续 10 秒重试并显示“视频播放中”,导致用户长时间等待且无法获得明确失败反馈。
8SD 卡跌至不可读写或反复未初始化,录像回放被直接阻断
3 期 · 9 条反馈
80Android · HarmonyOS · iOS8.4.1.6 / 1.1.1.11唐胜、张威、陈宝旺设备上报的 SD 卡状态在 258245 中持续处于未初始化/格式化中,在 258173 中由正常可读写跌至不可读写;App 按协议正确展示异常,根因更可能在 SD 卡、卡槽/供电、设备存储控制器或固件挂载逻辑,而不是 KMP 页面误报。
9iOS `8.4.1.6` 云回放卡顿,首帧与失败状态可能被提前结算
2 期 · 8 条反馈
80Android · iOS8.4.1.6 / 8.3.11.3 / 8.4.106陈宝旺、欧阳荣、谭伟iOS 云回放容器允许解析完成后在 1.2 秒无首帧时提前向 KMP 返回成功,同时把 IJK 播放错误与正常结束合并处理,导致页面对真实卡顿、缓冲超时或解码失败缺少准确状态和可回溯证据;这是高度可疑的共同客户端缺陷,但仍需复现确认其是否为 3 名用户的直接主因。
10iOS 8.1.2.4 微信登录授权码重复提交触发 30100225
1 期 · 3 条反馈
80iOS8.1.2.4 / 8.1.204 / 8.4.106待定微信回调与恢复登录没有一次性 state、幂等锁和授权码消费机制,重复回跳或重试会把同一个单次授权码再次发给服务端,服务端以 30100225 拒绝后客户端仍保留旧状态。

🔴 问题 1:iOS 8.4.1.6 长连接反复重建,报警推送与设备在线态被拖垮 | 负责人:欧阳荣、位冬、唐胜、许源

1. 现象与覆盖范围

  • 反馈 259780:2026-10-26 23:48:36,iOS 8.4.1.6,iPhone 26.6,山东(账号尾号 4123),原文“报警很卡”,随附 Logan(8 129 行,覆盖 2026-10-26 00:16~23:47)。
  • 该用户在近 24 小时内共提交 2 条同族反馈:259780(“报警很卡”)与 259617(2026-10-26 00:38,“报警信息经常短缺”)。两条出自同一账号、同一机型,指向的是同一件事的两个侧面——列表卡,以及消息本身不全。
  • 同期还有 iOS 8.4.1.6 的两条卡顿反馈:259896(2026-10-27 16:28,iPhone 17.5.1,广东,“更新后 APP 出现严重卡顿现象,卡回放无法播放,进入 APP 后卡顿得无法操作,偶尔还会闪退出”)、259911(2026-10-27 17:38,iPhone 26.3,江苏连云港,“卡顿”)。两条都带 Logan。
  • 另有 259824(2026-10-27 10:47,iPhone 27.0,内蒙古,“下面栏里,报警那里一进去就特别卡”),其症状更接近本期问题 2,单独在第 2 节展开。
  • 严重度评分:76 / 100。反馈量 20(本窗口 4 条直接反馈、3 条带 Logan,其中 1 名用户在 23 小时内重复提交);共性广度 30(iOS 单一端,但覆盖 8.4.1.6 一个版本、iPhone 17.5.1/17.6.1/26.3/26.6/27.0 五个 iOS 版本、山东/广东/江苏/内蒙古四个省级地区);业务关键度 30(报警推送与设备在线态,是消息主链路;未达设备掉线的 40 分档)。
  • 与第 257 期(今日 09:00)的关系:09:00 那期的窗口是 2026-10-26 17:00:54~2026-10-27 09:00,259780 与 259617 都落在该窗口内,当期把它归入「app 卡死 / 报警很卡 🟡 单点」而未展开。本期拿到了同账号的 8 129 行完整日志,把「卡」拆成了可验证的长连接重建问题,因此不属于重复占用,而是对同一现象补上了此前缺失的证据。

2. 神策证据

  • 事件总量基线(2026-10-27 截至查询时):
  • DeviceConnectResult 16 201 468 次/5 285 091 人
  • MonitorFrameResult 39 603 822 次
  • DeviceVideoPlayback 15 557 262 次
  • SiotDevConnectResult 3 709 046 次
  • AppSwitchStatusValue 3 137 335 次
  • 参考上一条:DeviceConnectResult 是客户端主动发起的设备连接频次事件,量级远大于 SiotDevConnectResult(后者每设备仅埋一次)。长连接反复重建会连带触发设备状态重新拉取与连接重试,因此这两个事件的比值可以作为「客户端侧连接动作是否异常放大」的旁证,但不能单独证明长连接重建。
  • 口径限制(必须说明):当前事件清单中不存在长连接建立、断开、心跳超时或接入节点切换的专用事件。Login(2026-10-27 为 565 980 次)只覆盖账号登录,不覆盖 ws 会话;AppSwitchStatusValue 只反映前后台切换。因此神策只能提供「消息与连接规模」的背景,无法量化 ws 重建次数,本问题的量化证据全部来自 Logan。
  • 已核对 2026-10-27 全量事件名清单(前 30 个),确认 AlarmMessage、WsManager 等历史文档中出现的事件名在当前环境中不存在,本期不使用这些事件做任何推断。

3. Logan 关键日志

反馈 259780,Logan 8 129 行,覆盖 2026-10-26 00:16:24~23:47:38,运行环境 st_run_env_pro,version: 8.4.1.6,clientId: 913386C3-3847-403F-B7DA-CC55125A658D。

  • 冷启动次数:初始化SDK日志信息 共出现 6 次(00:16:24、02:20:43、09:12:00、11:02:13、18:54:45、23:47:38)。间隔分别为 124.3、411.3、110.2、472.5、292.9 分钟,属于用户主动杀进程重启的形态,不是系统连续崩溃重启。
  • 长连接重建次数:开始初始化长连接 共出现 37 次。也就是说,除了这 6 次冷启动,还有 31 次是在 App 存活期间重建的 ws 会话。
  • 接入节点反复轮换:37 次初始化命中的 ws 地址至少包括 122.9.8.100、114.116.213.86、114.116.196.16、114.116.220.7、122.9.40.201、122.9.45.119、114.116.196.211、114.116.222.246、122.9.14.70 等 9 个不同节点。每次重连都重新走 /seetong-netty-manager/netty/manager/get/available/netty/server 重新分配节点,说明客户端没有做节点粘滞。
  • 60 秒内再次重建:5 次。09:52:57→09:53:45(47.8 秒)、15:26:26→15:27:18(52.0 秒)、17:33:38→17:34:37(59.6 秒)、17:48:28→17:49:06(38.8 秒)、23:46:44→23:47:38(54.1 秒)。另有多次 2~5 分钟量级的重建(15:27:18→15:29:07 109 秒、15:29:07→15:33:23 257 秒、16:24:35→16:28:36 241 秒)。合起来看,15:21~17:49 两个半小时内重建 12 次,平均 12 分钟一次。
  • 断开的形态:主动断开长连接日志信息 - code: 1001 - reason: Stream end encountered 反复出现,日志里记为「主动断开」,即客户端侧调用关闭,而不是服务端 1011/1006 之类的异常掉线。
  • 重连标志恒为 1:websocketUploadLoginInfo 里 reconn 取值来自 self.reconnection,而 self.reconnection 在首次登录成功后即被置为 YES(WebSocketManager.m:562),在 RMWebSocketClose(:378-403)与 didClose 路径中都没有复位,只在 :762 一处出现 self.reconnection = NO。反馈日志对应的会话在重建后仍以 reconn=1 上报,与「客户端把每一次重连都当成首次重连」的形态一致。
  • 心跳与重建的关系:initHeartBeat(WebSocketManager.m:249-259)先判 heartBeatTimer 是否存在,若不存在则先调 destoryHeartBeat 再 dispatch_async 到主线程创建 10 秒周期定时器;destoryHeartBeat(:378-389)本身也是 dispatch_async(main_queue) 里 invalidate + 置 nil。两个异步块都在主队列,顺序上 destory 的 block 可能排在新 initHeartBeat 之后执行,把刚建的 timer 置成 nil。反馈日志中每一次 长连接连接成功 后都没有稳定的 10 秒心跳节奏(日志只记录 --- 取消心跳 destoryHeartBeat ---,没有对应的 senderheartBeat 记录),与「心跳被自己取消」的推演一致,但当前 Logan 未打印 senderheartBeat 内容,此点尚未闭环。
  • 对业务的影响面:用户因「报警很卡」「报警信息经常短缺」两次提反馈,而报警列表的实时增量依赖 ws 推送(kSocketGetDeviceAlarmList 走 WebSocketManager)。每次重建都会形成 1~5 秒的空窗,叠加 getNetty 的节点重新分配,足以让这段时间内的报警推送丢失或延迟,随后由下一次全量拉取补齐——这正是「消息短缺」与「进来就卡(触发重拉)」的典型形态。
  • 反馈 259896 的 Logan(3 922 行,覆盖 10:00:22~16:27:04)同样在 15:13:39 出现一次完整的 SDK 重新初始化,说明长连接重建不是单账号孤例。

4. 代码定位

  • 涉及模块:Seetong-App-iOS/Seetong5.0_ios/Seetong_tps/Tools/Scoket/WebSocketManager.m(iOS 长连接管理,当前分支 feature_v8.4.2)。
  • 关键类与文件:WebSocketManager(WebSocketManager.m,属性 heartBeatTimer 在 :35、reconnection 在 :42)。
  • 心跳生命周期调用链:connect(:60、:130)→ initHeartBeat(:249)→ destoryHeartBeat(:378)→ [timer invalidate]。
  • 关键分支:initHeartBeat 第 251 行的 if(self.heartBeatTimer) { return; } 与紧随其后的 [self destoryHeartBeat] 相互矛盾——既然已经确认 timer 为空,紧接着的销毁就是把「待创建的 timer」置于异步销毁风险中。
  • 重连链路:reConnectServer(:310 起)→ performReconnect(:333)→ [WebSocketManager getNetty]。
  • 关键分支:reConnectServer 只在 readyState == SR_OPEN || SR_CONNECTING 时提前返回;reConnectCount >= 5 时停止重连。反馈日志中重建次数远超 5,说明有某个路径在每次连接成功后重置了计数,或绕过了 reConnectServer 直接走 getNetty。
  • 重连标志:websocketUploadLoginInfo(:545-563)读 self.reconnection;self.reconnection = YES 在 :562;self.reconnection = NO 仅出现在 :762。RMWebSocketClose(:378 段)未复位该标志。
  • 关闭路径:RMWebSocketClose(WebSocketManager.m:389-407)→ [self.webSocket close] + _webSocket = nil + destoryHeartBeat + destoryNetWorkStartTesting,同时把 isAppStartWakeup 置 NO。
  • 修复方向锚点(按优先级):
  1. WebSocketManager.m:249-259:把 initHeartBeat 的「判空 → 销毁 → 异步创建」改为同一次主队列同步执行,或去掉判空后的 destoryHeartBeat 调用,消除「异步销毁覆盖新建」的竞态。
  2. WebSocketManager.m:389-407 / :762:在 RMWebSocketClose 与 didClose 中统一把 reConnectCount 复位,并让 reconnection 只在首次登录成功时置 YES、在每次断开时置 NO。
  3. getNetty 调用点:增加 ws 会话单飞——同一 clientId 在 connecting 或 open 状态下拒绝再次发起 getNetty,并打点记录调用方。
  4. 接入节点:在 getNetty 返回的节点可用时优先复用上一次节点,避免每次重建都切换。

5. 根因结论

  • 置信度:🟡 中。
  • 一句话根因:iOS 长连接的心跳与关闭路径存在「异步销毁覆盖新建定时器」与「重连计数/重连标志不复位」两处状态机缺陷,使连接在无服务端主动断开的情况下被客户端反复重建,每次重建都形成推送空窗。
  • 关键证据链:
  • Logan 侧:37 次 ws 重建 vs 6 次冷启动(31 次非用户触发);5 次在 60 秒内重建;断开 reason 恒为 Stream end encountered(客户端侧发起);9 个接入节点轮换。
  • 代码侧:initHeartBeat 判空后仍调用 destoryHeartBeat,两者均 dispatch_async(main_queue);RMWebSocketClose 复位了 isAppWakeup 但未复位 reConnectCount / reconnection。
  • 用户侧:同账号 23 小时内两次提交「报警很卡」「报警信息经常短缺」。
  • 未闭环处:本期没有拿到 senderheartBeat 的实际发送记录,也没有服务端侧的 ws 会话时长统计,因此「心跳被取消」这一环仍是推演,不是实测。

6. 建议下一步

  • 分配给:iOS 基础组件负责人(长连接 / WebSocketManager),由欧阳荣跟进复核。
  • 优先处理项:
  1. 在 initHeartBeat、destoryHeartBeat、RMWebSocketClose、websocketDidOpen、websocketUploadLoginInfo 五处补打 reConnectCount、reconnection、heartBeatTimer 是否为空、以及调用方堆栈,一次灰度即可判断是「谁在 open 后立即关」。
  2. 修掉 initHeartBeat 的异步销毁时序问题,把 reConnectCount / reconnection 的复位下沉到 RMWebSocketClose 与 didClose。
  • 验证方法:
  • 真机(iPhone 26.x、27.0 各一台)后台驻留 2 小时,统计 开始初始化长连接 次数应 ≤ 冷启动次数 + 3;reconn 在重建首次之后应为 1 且不入库为新会话。
  • 报警推送回归:服务端在 ws 重建窗口内下发报警,验证 30 次下发无丢失。
  • 心跳:抓包确认 10 秒周期心跳持续存在,且 destoryHeartBeat 与新 initHeartBeat 不交叉。
  • 任务账本:沿用 T-20261027-171012-c2c8(P1,captured),本期已更新其 next_action 补入 259780 的 37 次重建与节点轮换证据。

🟠 问题 2:iOS 8.4.1.6 报警页首次进入卡十几秒,主线程同时扛权限查询与列表重建 | 负责人:欧阳荣、Not Committed Yet、谭伟、唐胜

1. 现象与覆盖范围

  • 反馈 259824:2026-10-27 10:47:48,iOS 8.4.1.6,iPhone 27.0,内蒙古(账号 W_LP84UmIedZ),原文“下面栏里,报警那里一进去就特别卡”,随附 Logan(3 178 行,覆盖 08:17:05~10:47 前后)。
  • 同族旁证:259780(“报警很卡”)、259769(2026-10-26 22:21,iOS 8.4.1.6,iPhone 18.6.2,安徽,“经常 app 卡死”)、259896(“进入 APP 后卡顿得无法操作,偶尔还会闪退出”)。
  • 严重度评分:68 / 100。反馈量 20(4 条直接反馈、3 条带 Logan、跨越 4 个 iOS 系统版本);共性广度 30(iOS 单端,覆盖 8.4.1.6 与 17.5.1/18.6.2/26.3/26.6/27.0 五个系统版本、安徽/广东/江苏/内蒙古四个省级地区、4 个不同机型);业务关键度 25(报警入口可用性,属关键交互但非完全不可用)。
  • 与上一条的关系:长连接重建(问题 1)会让报警页每次进入都触发一次全量重拉,是「卡」的放大器;本条关注的是页面自身的首屏路径——即使连接正常,首次进入也存在主线程阻塞。

2. 神策证据

  • 神策侧没有报警页首屏耗时、主线程卡顿或页面渲染耗时的埋点。已核对 2026-10-27 事件清单:与页面相关的只有 $AppViewScreen(404 407 284 次)、$AppClick(266 940 102 次)、$pageview(940 665 次),均无耗时字段。
  • 唯一可用的规模参照:AppSwitchStatusValue 2026-10-27 为 3 137 335 次/648 590 人,其中 8.4.1.6 占 2 139 162 次;用户在这台 iPhone 26.6 上单日 37 次 ws 重建、6 次冷启动,说明前后台切换频繁。每次回前台都会触发 KMP 报警页的 pageDidAppear 刷新路径(见第 4 节),这是「一进去就卡」的触发条件之一。
  • 结论口径:神策在本问题中只能做背景,不能做量化,主证据来自 Logan 与代码。

3. Logan 关键日志

反馈 259824,Logan 3 178 行,覆盖 2026-10-27 08:17:05 起,os: ios、version: 8.4.1.6、clientId: 66CD0A06-F637-4C6C-A023-45907A542755,type: 27.0。

  • 08:17:05.434 当前APP使用的语言: 中文 (中国),08:17:05.584 初始化SDK日志信息 … version: 8.4.1.6,08:17:05.665 获取到设备列表后,唤醒低功耗设备日志信息 - 低功耗设备数量: 0 - 是否为工程商: 0 - 长连接状态: 0。这是冷启动后进入首屏的完整序列。
  • 日志首行 2026-10-27 08:17:05.441 EXCEPTION 1 --- [clogan] clogan header,说明该份日志的头部被截断,08:17 之前的内容没有采集到。因此本期无法从该条反馈直接看到报警页的进入时刻与卡顿时长,只能拿到条目提交(10:47:48)前的会话片段。
  • 上一条反馈 259780 中同类页面的日志显示,报警页的数据来源是 ws 接口 kSocketGetDeviceAlarmList,并伴随 /seetong-member-device/device/list、/seetong-member-device/device/group/list、/seetong-sms/member-message/unread/count、/seetong-mall/device/va_service 等 20 个接口在页面进入后集中请求(该份日志中 device/list 与 device/group/list 各被请求 46 次)。
  • 反馈 259780 中同一账号在 23:48:36 提交「报警很卡」,其日志末段 23:47:38 的 初始化SDK 之后紧接 ws 重建,说明用户是在重启 App 后立刻进入报警页并感知到卡顿。
  • 客观限制:本期两份 iOS 报警页 Logan 都没有打印主线程耗时、页面生命周期耗时或 UI 卡顿日志(AlarmMsgViewController 只打 NSLog 业务流水,KMP 侧 AlarmMessagePage 只打 LogUtils.i 状态串)。因此「卡了多久」目前只能由用户描述给出,无法从日志侧量化。

4. 代码定位

  • iOS 原生侧(报警页宿主):
  • Seetong-App-iOS/Seetong5.0_ios/Seetong_tps/Classes/TPS/UIVC/VCMessage/AlarmMsgViewController.m(2 011 行)
  • viewWillAppear:(:138-151)在每次进入时同步执行 getDeviceIds、getDeviceUids,设备为 0 直接 updateNoDataView,否则 startRefreshTableHeader → loadData(:432)。
  • checkNotification(:786-806)调用 [[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:],回调内 dispatch_async(main_queue) 再更新提示条。权限查询本身在系统进程侧,首次 NotDetermined 时会弹出授权对话,是首屏主线程可感知停顿的候选来源。
  • refreshLatestAlarmListDataIsRefresh:(:596-651)先 queryAlarmTimelineFromDBWithDate:(STAlarmTimelineCacheTool.m:37-60,FMDatabaseQueue inDatabase 内 SELECT * FROM alarmtimeline where user_id=? AND alarm_date=? ORDER BY last_timestamp 全量读当天时间轴),回调里再 queryAlarmDataFromDBWithDate: 全量读当天报警,两段 DB 读取都发生在回调链上。
  • removeDuplicatesFromDeviceAlarmList:usingMessageModeArray:(:1844-1876)对每条新报警在 messageModeArray 上做一次 indexOfObjectPassingTest,复杂度 O(n×m)。这段在 :1832 的 for (NSInteger i = 0; i < 15; i++) 日期循环内被反复调用,报警条数越多退化越明显。
  • KMP 侧(Android / HarmonyOS 共用,iOS 也走同名页面):
  • seetong-kmp/moduleMessage/src/commonMain/kotlin/com/seetong/modulemessage/page/AlarmMessagePage.kt(2 540 行,分支 feature_v8.4.2)
  • pageDidAppear(:320-341):非首次加载时依次 refreshDeviceOptions(reason = "page_did_appear")、resumeHeaderRefreshIndicatorIfNeeded()、refreshAlarmHistoryAfterPageAppears(reason = "page_did_appear")、syncPendingOnlineAlarmMessages(trigger = "page_did_appear")。
  • observeForegroundEvent(:826-838):EVENT_APP_FOREGROUND 时同样执行上述四步,reason 换成 app_foreground。
  • refreshAlarmHistoryAfterPageAppears(:977-1018):仅对 iOS 生效(if (!pagerData.isIOS ...) return),置 isRefreshing = true 后 lifecycleScope.launch 调 vm.refreshHistoryAfterPageAppear。
  • AlarmMessagePageViewModel.refreshCurrentHistoryUiState(:857-914):resetPaging → loadedDateKeys.clear() → loadedTimelineWindows.clear() → primeLatestTimelineWindowFromCache → syncLoadedMessagesFromCache → rebuildFilterOptions → buildSuccessUiState → requestFirstPage(forceRemote = true)。也就是说每次回前台都要重建整个列表状态并强制远程重拉第一页。
  • 修复方向锚点:
  1. AlarmMsgViewController.m:786:把首次通知权限「询问」从页面加载路径剥离,页面只读 getNotificationSettingsWithCompletionHandler 结果,授权询问改到启动后空闲或用户主动触发;并对该调用加耗时日志。
  2. AlarmMsgViewController.m:1844:把 msgId 去重改成用 NSDictionary/NSMutableSet 建索引,把 O(n×m) 降到 O(n+m)。
  3. AlarmMessagePage.kt:826-838:回前台刷新加节流(例如距上次成功刷新 < 30 秒直接跳过),避免 ws 反复重建时每次回前台都触发一次全量重拉。
  4. AlarmMessagePageViewModel.kt:899:requestFirstPage 改为可取消 + 首屏优先,先用缓存 cachedState 上屏,远程结果到达后局部 diff 更新,不要整表重建。

5. 根因结论

  • 置信度:🟡 中。
  • 一句话根因:iOS 报警页把「通知权限查询、当天报警全量 DB 读取、O(n×m) 去重、KMP 强制远程重拉第一页」四件事压在同一次页面进入的主线程路径上,任何一项变慢都会被人感知为「一进去就卡」。
  • 关键证据链:
  • 用户侧:4 条不同 iOS 版本、不同机型的独立反馈都指向报警页或 App 级卡顿。
  • 代码侧:viewWillAppear → loadData → DB 全量读 → O(n×m) 去重的同步链,叠加 KMP pageDidAppear 的强制远程重拉。
  • 日志侧:259780 单日 37 次 ws 重建 + 46 次 device/list 请求,说明页面进入会被反复触发重拉。
  • 未闭环处:本期两份 Logan 都没有卡顿时长数据,259824 的日志头部被截断(clogan header 处即开始),因此「十几秒」这一数字来自用户描述,不是日志实测;通知权限阻塞也尚未通过 Instruments 证实。

6. 建议下一步

  • 分配给:iOS 报警模块负责人 + KMP moduleMessage 负责人。
  • 优先处理项:
  1. 按反馈 259824 的机型(iPhone 27.0 / iOS 26)真机复现:清空通知权限后首次进入报警 Tab,抓 Instruments Time Profiler 与 Main Thread Checker,确认 getNotificationSettingsWithCompletionHandler 回调前主线程是否被阻塞。
  2. 在 AlarmMsgViewController.m:138、:432、:596、:1844 与 AlarmMessagePage.kt:977 五处加耗时打点,先量化再优化。
  • 验证方法:
  • 100 条 / 500 条 / 1 000 条报警三档数据量下,首次进入报警页可见首帧 ≤ 500 ms。
  • 前后台切换 20 次,报警页每次回前台不出现整表重建(可用 refreshCurrentHistoryUiState reason=page_return 日志计数验证节流生效)。
  • 通知权限 NotDetermined、Denied、Authorized 三态各验证一次首屏时间,确认权限查询不再进入关键路径。
  • 任务账本:沿用 T-20261027-171006-ff51(P1,captured)。

本期扫描全量(全部沉淀到知识库)

#关键词反馈数分类处置
1长连接重建 / 报警卡 / 报警信息短缺5🔴 进雷达详细分析见问题 1(259780、259617、259896、259911、259769)
2报警页进入卡顿4🟠 进雷达详细分析见问题 2(259824 及同族)
4设备离线 / 老显示离线11🟡 单点或重复与第 257 期同族;259893、259865、259832 已并入任务 T-20261027-171012-5d00
5回放 / 录像 / 回看不可用14🟡 单点或重复iOS 与 Android 部分已在第 255~257 期覆盖;HarmonyOS 6 条无 Logan,待补证
6移动侦测 / 人形不显示或不报警2🟤 产品建议259922、259923(同账号重复提交),与任务 T-20261018-090818-00a1 同族
7添加设备 / 配网 / 绑定冲突3🟡 单点259909(录像机二维码已被他人绑定,属业务规则咨询)、259914、259760
8画面看不到 / 只有图片2🟡 单点或重复259902、259771;与任务 T-20261021-170533-1339、T-20261024-170603-cfd1 同族
9声音 / 对讲1🟡 单点259906,无 Logan
10客服 / 流量卡 / 无效内容13🟢 咨询或无效259892、259915、259725、259735、259875、259867 等,无技术信息量
已折叠 1 条普遍性网络问题(含 -102/-101/-1002 与中/英/俄/法/西/葡/土/阿/日多语言网络提示模板,如 Проверьте телефонную сеть、Please check your mobile network);全量明细见同名 Markdown 知识库。
说明:同一反馈可能同时落入「进雷达」与某一排除栏(例如 259824 既算报警页卡顿,也出现在其他关键词统计中),因此上表各栏之和大于去重后的 185 条。

应用市场反馈(2026-10-27 00:00–23:59)

商店评论数差评数主要问题分类处置
App Store00无无评论
华为应用市场00无无评论
应用宝00无无评论
Google Play——采集失败未配置代理,本期无法采集
荣耀 / vivo / OPPO / 小米——待导入需人工后台导出评论文件

差评原文摘录:本窗口没有采集到应用市场评论。

采集状态:App Store 0 条、华为应用市场 0 条、应用宝 0 条;Google Play 失败(未配置代理);荣耀应用市场、vivo 应用商店、OPPO 软件商店、小米应用商店待导入。原始数据:knowledge/appstore-feedback/raw/2026-10-27.json。

注意:以上「0 条」是采集成功但确实无评论;Google Play 与四个手商店是采集未完成,属于数据盲区,不能等同于「用户没有意见」。本期进雷达的两个问题均来自自有反馈平台,未获得应用市场侧交叉印证。

数据源状态

数据源状态说明
自有反馈接口✅ 正常total=207 / fetched=207 / complete=true / pages=5;窗口 2026-10-26 17:00:00~2026-10-27 17:00:00 内 185 条,其余 22 条为 17:00 之后新提交
应用市场(App Store / 华为 / 应用宝)✅ 正常三家均返回 0 条
应用市场(Google Play)❌ 失败未配置代理,本期无法采集
应用市场(荣耀 / vivo / OPPO / 小米)⏸️ 待导入需人工后台导出评论文件
神策⚠️ 部分降级query_sql 可用;SiotDevConnectResult 无 result 列(只有 error_code,且本期该列为空),AlarmMessage 事件名不存在,均已在正文标注口径限制,未用替代事件硬凑
Logan✅ 可读下载 3 份:259780(8 129 行)、259824(3 178 行)、259896(3 922 行);259824 头部为 clogan header,08:17 之前内容缺失
友盟⏭️ 未查本期无崩溃、ANR 类主诉;用户提到「偶尔闪退」但无崩溃栈,不满足触发条件
TAPD⏭️ 未查已用 Logan + 代码链路定位,不以历史 Bug 搜索替代现场证据
代码仓✅ 已核对Seetong-App-iOS 分支 feature_v8.4.2;seetong-kmp 分支 feature_v8.4.2;Seetong-App-Android 分支 feature_v8.4.2
任务账本✅ 已登记T-20261027-171012-c2c8、T-20261027-171006-ff51,均 P1 / captured;本期已更新 c2c8 的 next_action

待补证

  • 补采 259824(iPhone 27.0)的完整 Logan 前段:当前文件从 08:17:05 的 clogan header 开始,缺失进入报警页的实际时刻,无法给出卡顿时长。
  • 在 WebSocketManager 五处关键节点补打 reConnectCount / reconnection / 心跳状态与调用方堆栈后,灰度一批 iOS 8.4.1.6 用户,拿到「谁在 open 后立即 close」的直接证据。
  • 取服务端侧 ws 会话时长与会话数统计,与客户端 37 次重建对齐,确认服务端是否也在同一时刻判定断开。
  • 对 259896(iPhone 17.5.1,广东,卡回放无法播放 + 闪退)补采崩溃栈或 Log0/Log1 附件;本期该条只拿到 15:13 一次 SDK 初始化,不足以判断其闪退与长连接重建是否相关。
  • HarmonyOS 1.1.2.3 本期 6 条回放或离线反馈仍无 Logan,需在下期前补采至少 2 份。
  • Google Play 与荣耀/vivo/OPPO/小米四个商店的采集缺口需补齐,否则应用市场侧长期是盲区。

下一期 = 第259期 = 2026-10-28-H17.md(明天下午 17:00;窗口 2026-10-27 17:00~2026-10-28 17:00)

🗂️历史期次

查看全部历史期次(近 90 天)→