跳转至

[ISSUE-0054] 第 10 轮 agent — A2 hybrid 6 处真 bug

v0.10.73 A2 上线后立即第 10 轮独立 agent 审查。Agent 找到 6 个真 bug + 5 个边缘 case + 1 个元洞察

6 个真 bug(v0.10.74 全部修复)

🔴 修 #1 数据安全 — client mode 删/导"选全部"误删 22w 全表

saveParams 不含 quickFilter / filterTaskId / hasEmailOnlyapiLocalDataDeleteselectOption='all' 时直接 deleteByQuery(exViewFilterToQuery(filters,keyword,logic)) — 空 filters 即全表 query。

场景:用户 client mode 用 quickFilter='has-email' + filterTaskId='X' 看 10 行 → 点"选全部 10 项"→ selectOption='all' → server 用空 filter 删全表 22w → 数据灾难。

短期修(v0.10.74):client mode 下拦截 selectOption !== 'current',toast 提示用户先切完整模式。 长期重构(待做):saveParams 加 quickFilter/taskId/hasEmailOnly,server 端 search.ts 接受全套参数。

🔴 修 #2 删除后 UI ≤ 30s 不刷

deleteRun.onSuccessdataRefresh()(apiLocalDataList.refresh)。client mode 下 dataRun 从未跑过 → refresh 是 no-op。rowsSnapshot 由 DataView 顶层 30s polling + maps-data-updated event 驱动,子组件无主动触发权

:LocalDataView Props 加 onRequestRefreshSnapshot?: () => void,DataView 传 refreshRows。delete/export onSuccess 调它。

🔴 修 #3 空 DB 时 "去创建任务" CTA 失效

state.allCount 只在 dataRun.onSuccess(server)里设置。client mode 下永远是 -1 → 空状态 CTA 永不显示,新用户看 MUI 默认 "No rows" 干瘪文案。

:判定条件改为 state.allCount === 0 || (mode === 'client' && merchantStats.total === 0)

🔴 修 #4 client mode page reset 缺失

getTableData(1) reset page 的逻辑只在 mode === 'server' 跑。client mode 下 quickFilter / keyword / filterTaskId 变化时 page 不重置。

场景:page=5 + 切 has-email chip(结果只 30 行=2 页)→ slice(80,100) 返空 → 用户看空白。

:加独立 useEffect([mode, quickFilter, keyword, filterTaskId], () => { if (mode === 'client') setState({ page: 1 }) })

🔴 修 #5 mode 切换不重置 page / selectKeys

setMode('server') 直接换 mode,但 state.page=5 在新数据集可能不存在 → 显示空页;selectKeys 跨 mode 不清空 → checkbox 错位。

setMode 改 wrapper,内部同时 setState({ page: 1, selectKeys: [], selectTotal: 0, selectOption: 'current' })

🔴 修 #6 flushData 刷新按钮 client mode 无效

flushData={dataRefresh} — client mode 下 dataRun 没跑过 → refresh 无意义。用户点"刷新"无反应。

flushData wrap 成 mode-aware:client mode 调 onRequestRefreshSnapshot();server mode 走原 dataRefresh()

5 个边缘 case(部分修,部分待做)

🟡 修 #8 banner 文案 filterTaskId 时误导

旧文案"还有 X 条老数据 — 可按'任务筛选'查看" — 当 filterTaskId 已设时这话不通(已经在筛选了)。

filterTaskId 存在时换文案"该任务还有 X 条老数据,切完整模式查看"。

🟡 修 #10 client mode 50k cap banner 缺失

state.truncated 仅 server onSuccess 写,client mode 永远不报"50k 截断"。

:(未做,留下轮)client mode 加 rowsSnapshot.length >= 50000 && quickFilter === 'has-email' 同款 banner。本轮先让 #1 拦截兜底。

🟢 #7 / #9 / #11

未修 — 优先级低。

元洞察(agent 直击要害)

"A2 = 数据派生路径换分支,但 mutation/refresh/CTA/banner 路径全都还指向旧 server-mode 单源。"

三个 tab "架构对齐"只对 read path 成立,write path(delete/export/refresh/empty-state)依旧是 server-mode 独苗。每加一个 mode 分支就要把 4 条写路径全都判断分支,否则就是"读快了写乱了"。

真正的修法不是补丁式各加 if (mode === 'client'),而是把 saveParams / dataRefresh / allCount 这些跨路径状态抽成单一信号源(如 useDataSource hook 暴露 { data, total, refresh, mutate }),让 mode 切换只换 hook 实现。否则未来还会出 ISSUE-0055/0056(删错、刷不到、CTA 不见)。

本轮先按补丁式修 6 个真 bug,长期需重构。

audit_grep

- pattern: "selectOption.*['\"]all['\"][\\s\\S]{0,200}filters\\s*[,}]"
  description: "client mode  selectOption='all' +  filters 全表删  必须有拦截"

相关

  • [[0053-a2-merchant-client-server-hybrid|0053-A2商家列表client-server-hybrid]] — 上一轮(带入这 6 个 bug)
  • 修bug全字典扫描 — 元洞察:"每加一个 mode 分支要把所有跨路径状态都改"
  • 独立agent审查 — 第 10 轮 agent 一针见血