feat(rectification): anonymous aggregate telemetry + admin summary page

One row per rectification Case, written once when the range card is first
delivered (GET /api/rectification/cases/[caseId], fire-and-forget after the
response is built). Numbers and closed enums only: no user / case / session
id, birth data, names, text or timestamps finer than the ISO week. Dedupe via
a separate case_id ledger that cascades with the Case (and account deletion).

Migration 20260926010000 is additive: two RLS tables with no runtime table
grants, SECURITY DEFINER write (service_role), purge (service_role) and
aggregate-only summary (admin_runtime) functions; 180-day retention.

Admin: 「校正统计」 page + GET /api/admin/rectification-telemetry
(admin.customers.read), aggregates only, no per-row view or export.

TASK-rectification-telemetry-20260926. test:db not run locally (no Docker).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
This commit is contained in:
Jesse_Chen
2026-09-26 15:36:29 +08:00
co-authored by Claude Opus 5.5
parent f74825a27c
commit d0bfc1fc3d
27 changed files with 2422 additions and 6 deletions
@@ -0,0 +1,51 @@
# 生时校正匿名统计:隐私说明
任务书:`docs/tasks/TASK-rectification-telemetry-20260926.md`。迁移:`frontend/supabase/migrations/20260926010000_rectification_telemetry.sql`。
## 存什么
每个校正会话第一次给出范围卡时记一行,只有下面这些字段(白名单写死在 `frontend/src/lib/rectification-agentic/v9/telemetry.ts` 的 `RECTIFICATION_TELEMETRY_FIELDS`,由 `frontend/tests/rectification-telemetry.test.ts` 钉住;加字段必须改测试):
| 字段 | 含义 | 类型 |
| --- | --- | --- |
| `recorded_week` | 记录所在 ISO 周的周一(UTC) | 日期,只到周 |
| `window_radius_minutes` | 出卡时搜索窗口的一半宽度 | 0–720 |
| `birth_time_source` | `hospital_record` / `approximate` / `period_only` / `unknown` | 枚举 |
| `questions_total` 及五个分类 | 定向 / 引导 / 带年月探针 / 性格 / 开放的提问数(总数含其他类) | 0–1000 |
| `experiences_added` | 用户讲过、仍有效的经历件数 | 0–1000 |
| `range_width_minutes` | 卡上范围宽度 | 0–1440 |
| `candidate_count` | 仍在比较的候选分钟数 | 0–1440 |
| `top_two_gap_points` | 第一名与第二名差几个百分点 | 0–100 |
| `stop_reason` | `converged` / `pool_exhausted` / `user_no_more` / `round_cap` / `user_stopped` / `error` | 枚举 |
| `precision_gate_met` | 精度门槛是否达标 | 布尔 |
| `duration_seconds` | 从第一轮到出卡的秒数 | 0–1 年 |
| `algorithm_version` / `policy_version` / `skill_version` | 版本号(只允许 `[A-Za-z0-9._:+-]`,不合规的记空) | 版本 id |
## 不存什么
- 不存用户、校正记录(Case)、会话编号;不存出生日期、时间、地点、姓名、邮箱;不存用户原话、证据摘要、模型输出;不存 IP;时间不细于周。
- 候选时刻、范围起止时刻(`HH:MM`)也不存,只存宽度。
- 写入失败的日志只有一行 `[rectification-telemetry] write skipped reason=<错误码>`,不带任何字段值、编号或错误原文。
## 去重与账户删除(任务书 D4 的落法)
- 任务书 D4 允许为去重和删除联动存用户 id。本实现更严:统计行里**不存**任何 id。
- 去重用另一张表 `rectification_telemetry_reported_cases`,只有一列 `case_id`,外键指向校正记录并 `on delete cascade`。账户删除 → 身份用户删除 → 校正记录级联删除 → 这张台账的行一并删除。
- 台账没有时间列,也没有指向统计行的列,统计行无法再关联回任何人;账户删除后留下的统计行本来就不含个人信息,所以不需要(也无法)按人删除。
- 同一个校正会话只记一次,以第一次出卡时的状态为准;之后继续补经历、采用、确认都不改这一行。
## 谁能读写
- 两张表都开启 RLS,且不给任何运行角色表权限(`anon` / `authenticated` / `app_runtime` / `admin_runtime` / `service_role` 全部 revoke)。
- 写:只能通过 `record_rectification_telemetry`(SECURITY DEFINER,只授权 `service_role`);函数先核对该 Case 属于该用户,再写台账和统计行,任一 CHECK 不过则整笔回滚。
- 读:只能通过 `rectification_telemetry_summary(weeks)`(SECURITY DEFINER,只授权 `admin_runtime`),返回中位数、分布、按周趋势和版本分布,不返回任何单行。后台接口 `GET /api/admin/rectification-telemetry` 需要 `admin.customers.read` 权限,没有逐条列表、没有导出。
## 保留期
- 180 天。每次写入先删除「所在周的周一早于今天 180 天」的行;汇总函数也不读 180 天以前的行;运维可调用 `purge_expired_rectification_telemetry()`(只授权 `service_role`)手动执行同一删除。
- 没有定时任务:长时间没有新写入时,过期行在库里但汇总看不到,下一次写入即删除。
## 写入时机与性能
- 写入点是 `GET /api/rectification/cases/[caseId]`(每轮结束后前端都会刷新它),只在当前决策为交付结果(`sessionOutcomeAllowsDelivery`)、卡片有候选列、且最近活动在 2 小时内时记录;翻看很久以前的历史不会补记。
- 复用这次响应已经算好的决策和卡片,不再重复计算;写库在响应构建完之后另起(`setImmediate`),不 await,失败吞掉。
@@ -0,0 +1,121 @@
# PROGRESS · 生时校正匿名聚合统计(2026-09-26)
- 任务书:`docs/tasks/TASK-rectification-telemetry-20260926.md`
- 分支:`codex/rectification-telemetry-20260926`,基线 `origin/staging` `7203d94e`(fewer-probes-card 合入之后);提交前变基到 `f74825a2`(其后只多了离线研究脚本与文档,不涉及本单文件)
- 执行:Claude 子代理(直接执行模式,产品授权)。未推送。
- 产品新增能力,任务书未要求 BUG 号,不开 BUG 号。Skill 不 bump(用户可见行为不变)。
## 结论先行
| 任务 | 做了什么 | 状态 |
| --- | --- | --- |
| T1 迁移 + RLS + 保留期 | `frontend/supabase/migrations/20260926010000_rectification_telemetry.sql`:两张新表(统计行 `rectification_telemetry`、去重台账 `rectification_telemetry_reported_cases`)、三个 SECURITY DEFINER 函数(写 / 清理 / 汇总)。只加不改 | 完成;**test:db 本机无 Docker 未跑**,以门禁 DB job 为准 |
| T2 写入点 + 纯函数 + 白名单测试 | `frontend/src/lib/rectification-agentic/v9/telemetry.ts`;挂在 `GET /api/rectification/cases/[caseId]`,复用这次响应已算好的决策与卡片;`setImmediate` 后写、不 await、吞错 | 完成 |
| T3 后台汇总页 | 「校正统计」`/admin/rectification-telemetry` + `GET /api/admin/rectification-telemetry`:宽度分布、提问数分布(含分类均值)、停止原因占比、门槛达标率、按周趋势、差距分布(=卡上是否显示百分比)、出生时间来源、版本 | 完成 |
| T4 记录 | CHANGELOG、DESIGN(后台节)、本文件、`docs/testing/rectification-telemetry-20260926.md`、`docs/operations/rectification-telemetry-privacy.md`、BLOCKED | 完成 |
## 字段表(行里只有这些,外加 `id` 随机 uuid 和 `recorded_week`)
| 字段 | 取值 / 口径 | 来源 |
| --- | --- | --- |
| `recorded_week` | 记录所在 ISO 周的周一(UTC),库里默认值生成 | DB default |
| `window_radius_minutes` | 出卡时搜索窗口宽度的一半,0–720 | `case.candidateRange` |
| `birth_time_source` | `hospital_record` / `approximate` / `period_only` / `unknown`(`block_scan` 阶段或来源为 unknown 记 unknown;family_exact、legacy_import、空都并入 approximate,与 `normalizeBirthTimeSource` 一致) | `case.birthTimeSource`、`case.stage` |
| `questions_total` | 已问过的问题数:焦点状态为 active / resolved / declined / skipped;`superseded`(未答就被换掉)不算 | 焦点列表 |
| `questions_targeted` | 问题 id 以 `collect:targeted:` 开头 | 同上 |
| `questions_guided` | 以 `collect:guided:` 开头(D1 之后每个校正最多 2 道,可直接看新流程是否生效) | 同上 |
| `questions_dated_probe` | schema 带 `probe_year` 的点选探针 | 同上 |
| `questions_personality` | `choice_kind = varga_style`、`tie_break_round`、D9/D10 风格题,以及不带年份的引擎探针(09-09 起按性格题处理) | 同上 |
| `questions_open` | 其余 `collect:*`(开放采集、邀请补经历、职业、其他) | 同上 |
| 其他类 | 不单独存;= 总数 − 五类之和(时段选择、扩窗等),汇总页显示 | 派生 |
| `experiences_added` | 仍有效的经历件数(confirmed / draft / pending_confirmation) | 证据台账 |
| `range_width_minutes` | 卡片范围宽度(卡片没有范围时用决策的可信范围),0–1440 | `range_delivery.range` |
| `candidate_count` | 仍在比较的候选分钟数 | `decision.separation.ranked` |
| `top_two_gap_points` | 卡片三列相对可能性第一与第二之差(百分点);只有一列记空 | `range_delivery.columns` |
| `stop_reason` | 见下 | 决策 + 焦点 + 推断回执 |
| `precision_gate_met` | 决策层本轮测得的 D1 门槛 | `decision.precisionGateMet` |
| `duration_seconds` | 从最早一轮到现在的秒数,封顶 1 年 | 轮次时间 |
| `algorithm_version` / `policy_version` / `skill_version` | 只允许 `[A-Za-z0-9._:+-]{1,64}`,否则记空 | 快照 / Case |
停止原因(先中先得):
1. `user_stopped`:`sessionOutcome = provisional_range_user_stopped`(Case 为 paused,点「停止」或说不想继续)。
2. `converged`:精度门槛达标。
3. `round_cap`:决策层自己的熔断 `budgetExhausted`(8 轮 / 有效答题上限 / 平台期),从推断回执算,和决策用的是同一个函数(本单只加了 `export`)。
4. `user_no_more`:`stopReason = user_uncertainty_too_high`(多半答「说不好」),或出卡前最后一道已关闭的采集题被用户答了「没有 / 记不清」。
5. `pool_exhausted`:其余(题源问空,包括 `probe_pool_exhausted`、`tied_first`、七条线问完就出卡)。
6. `error`:枚举保留,**当前没有任何路径会写**(产品里不存在「因错误结束一个校正」的事件)。
与新流程(fewer-probes-card,`7203d94e`)的对应:引导题数量(D1 上限 2)直接是 `questions_guided`;「卡上是否显示百分比」(D4,差距 ≥ 5)没有单独存,由 `top_two_gap_points` 派生——汇总页的差距分布按 0–2 / 3–4 / 5–9 / 10+ / 只有一列分桶,5–9 与 10+ 即显示了百分比。这样以后阈值变了,历史行仍能按新阈值重算,也没有在任务书字段表之外另加字段。
## 偏离任务书之处(请验收方裁决)
1. **不存用户 id(D4 更严)**。任务书 D4 允许为去重与删除联动存用户 id;协调方的硬红线是行里不存任何用户 / 案例 / 会话 id。落法:统计行没有任何 id;去重另用 `rectification_telemetry_reported_cases(case_id)`,外键 `on delete cascade` 到校正记录——账户删除 → 身份用户 → Case 级联 → 台账行删除。台账没有时间列也没有指向统计行的列,统计行无法关联回人;它本来就不含个人信息,所以账户删除后留下也不违反 D4 的目的。
2. **只在「第一次出卡」时写,不覆盖放弃 / 超时(D2 的后半句未做)**。产品里没有「放弃」或「超时结束」事件:Case 一直可续,`POST /api/rectification/cases/[caseId]/close` 前端没有调用方。没出卡就离开的会话目前不入统计。要覆盖需另开单(例如新开校正时把旧 Case 记为放弃,或定时扫描长时间无活动的 Case),届时可沿用 `error` / 新增 `abandoned` 枚举(加枚举要改 CHECK,属收紧/放宽约束,需按 §7.6 拆两轮)。
3. **时间只到周**。按周趋势只需要周;记录日期精确到天会让统计行能和 Case 的活动时间对上,所以只存周一日期。
4. **权限用 `admin.customers.read`**。现有权限里没有「只给产品负责人」的读权限;能看单个客户资料的角色看汇总不增加暴露面。若要只给 owner,需新增权限(动 RBAC 表),本单未做。
## 迁移(为什么向后兼容)
- 只有 `create table` ×2、`create index` ×1、`create or replace function` ×3(均为新函数名)、RLS 开启与 grant / revoke(只作用于新对象)。没有改任何旧表、旧函数、旧权限。
- 当前已部署的代码不引用这些对象;门禁「Migrate Staging Database」先迁移后部署,旧代码在迁移后照常运行;新代码若在迁移前运行,写入失败也只记一行日志(吞错),不影响用户。
- 表权限:两张表 RLS 开启,`anon` / `authenticated` / `app_runtime` / `admin_runtime` / `service_role` 全部 revoke,没有 policy;写只能走 `record_rectification_telemetry`(service_role),读只能走 `rectification_telemetry_summary`(admin_runtime),清理 `purge_expired_rectification_telemetry`(service_role)。
- 保留期 180 天:每次写入先删「周一早于今天 − 180 天」的行,汇总不读 180 天以前的行,另有手动清理函数。没有定时任务。
- 写入函数先核对 Case 属于该用户;任一 CHECK 不过(枚举、范围、版本格式、五类之和不超过总数)整笔回滚,去重标记不会残留。
## 测试
### 新增
| 文件 | 条数 | 内容 |
| --- | --- | --- |
| `frontend/tests/rectification-telemetry.test.ts` | 18 | 行键 = 白名单(新增字段必须改测试);写入参数 = 白名单 + 两个 id;行里只有整数 / 布尔 / 枚举 / 版本号,虚构姓名、生日、地点、原话、id、HH:MM 都不出现;各字段取值;非法版本与缺值;问题分类;来源分类;停止原因全分支(含 `budgetExhausted` 同源);资格(非交付、无卡、历史读、停止);调度:不在本 tick 写、同 Case 只写一次、只读 / 不合格不写、写失败 / 同步抛错 / build 抛错都不外抛且日志只有原因码;迁移源文本:表列 = 白名单、函数参数 = 白名单、只加不改、RLS、授权、180 天;GET 路由 `void` 调度不 await |
| `frontend/tests/admin-rectification-telemetry-contract.test.ts` | 5 | 后台接口只读、只调汇总函数、不直接查表、admin 无表权限;菜单与权限;无导出;解析器固定形状;周数只收 4 / 12 / 26;标签覆盖全部停止原因、差距分桶与卡片 5 个百分点规则对齐 |
| `frontend/tests/database-rectification-telemetry.test.ts` | 1(Docker) | 真实 PG17:列白名单、RLS、各角色零表权限、函数执行权限矩阵、admin 直接查表被拒、写入 / 重复写入 no-op、他人 Case 被拒、五种非法值整笔回滚后仍可写、180 天清理、admin 汇总内容且不含 id / 生日 / 地点、周数封顶 26、账户删除级联台账而统计行保留。**本机 docker unavailable 跳过** |
### 改动的既有断言(原值 / 新值 / 原因)
| 文件 | 原值 | 新值 | 原因 |
| --- | --- | --- | --- |
| `frontend/tests/database-local-business.test.ts`(public 表白名单) | `profiles` 后直接 `redemption_attempts` | 中间加 `rectification_telemetry`、`rectification_telemetry_reported_cases` | 本迁移新增两张表;该断言要求与 `pg_tables` 一致(Docker 测试,本机跳过) |
| `tests/test_api_server_security.py::test_capability_audit_scans_registry_and_local_sources` | `admin/products` 后直接 `admin/roles` | 中间加 `admin/rectification-telemetry` | 新后台页是新的 app 路由,能力审计扫描到 |
两处都在代码里写了三栏注释。未弱化任何断言。
### 前端全量(Node 22.14.0,`/exec-daemon/node`)
- 基线:`origin/staging` `7203d94e` 同代码日志 4012 条 / 24 失败(全部 Docker / DB)。
- 本分支:**4036 条 / pass 3984 / fail 24 / skipped 28**。失败名单与基线逐条 `diff` 为空(新增失败 0);测试名列表无消失,新增 24 个名字(18 + 5 + 1)。
- `tsc --noEmit` 0 错;`npm run lint` 0 error(126 warning,均为既有文件,本单改动文件单独 eslint 0 输出)。
### Python 门禁集合
- `python3 -m pytest $(cat gate-pytest-args.txt)`:**948 passed / 1 skipped**,与基线一致,0 失败。
### 构建
- `npm run build -- --webpack`:成功;`/` 仍 `○ Static`;新增 `ƒ /admin/rectification-telemetry`、`ƒ /api/admin/rectification-telemetry`。
- rootMainFiles gzip:zlib 默认级 131,255 B / 9 级 130,950 B;基线 130,933 B → **+0.25%(默认级)/ +0.01%(9 级)**,在 ±2% 内。增量来自 webpack runtime 里多了新后台页 chunk 的映射,首页代码未变。
- 构建产生的 `frontend/frontend/` 已删除,未提交。
### 截图(虚构汇总数据)
后台布局要求服务端管理员会话,本机没有;截图用一个**临时**页面(未提交,已删除)把同一个 `AdminApp` + `RectificationTelemetrySummaryView` 渲染出来,`next start` + Chrome 无头,CDP 拦截 `/api/admin/session` 与 `/api/admin/rectification-telemetry`,后者返回经真实 `parseRectificationTelemetrySummary` 处理过的虚构汇总。控制台 0 error。
- `docs/testing/rectification-telemetry-20260926/telemetry-data-1280.png`:桌面,98 个虚构会话
- `docs/testing/rectification-telemetry-20260926/telemetry-data-390.png`:手机宽度(按周趋势表横向滚动)
- `docs/testing/rectification-telemetry-20260926/telemetry-empty-1280.png`:无数据时
首轮截图后按手机宽度把分布表「占比」列从固定 200px 改为 36% 并重截,上面三张是改后版本。最终干净构建复测 gzip 不变(131,255 / 130,950 B)。
## 环境缺口
- 无 Docker:`npm run test:db` 未跑(`database-rectification-telemetry.test.ts` 与 `database-local-business.test.ts` 的新表白名单都待门禁 DB job;run 号推送后补记)。
- 无受控后台账号:登录态、真实数据按 `docs/testing/rectification-telemetry-20260926.md` 待产品走。
- 未部署。
## 没做的
- 放弃 / 超时结束的会话不入统计(见偏离 2)。
- `error` 停止原因无写入路径。
- 没有定时清理任务(写入时清理 + 汇总只读 180 天内)。
+1 -1
View File
@@ -36,7 +36,7 @@
| 任务书 | 进度 | 主题 | 状态 | 落点 |
| --- | --- | --- | --- | --- |
| `TASK-rectification-fewer-probes-card-20260926.md` | [PROGRESS](PROGRESS-rectification-fewer-probes-card-20260926.md) | **减少无效追问 + 卡片区间为主**:引导补件离线新增达标 0 → 上限 6→2、定向题问完门槛未达直接出卡;卡片区间为主标题、代表分钟副标题,第一二名差距 ≥5 个百分点才显示百分比,否则写「目前区分不开」。不放宽任何置信度。先做 | 已验收(真机清单欠) | `4e6e8d87` + 验收补改 `7203d94e`(区分不开时隐藏「最可能」),deploy-staging run 2933 已部署;回放真值 ±30/±60 19→20、宽度中位 ±1 分钟、提问 11.4→7.8;Skill 10.0.30;真机清单 `docs/testing/rectification-fewer-probes-card-20260926.md` 未走 |
| `TASK-rectification-telemetry-20260926.md` | — | **匿名聚合统计**:每会话一行只存数字 / 枚举(题数分类、宽度、差距、停止原因、门槛达标、耗时、版本),管理后台只看汇总、保留 180 天;动表须 test:db。排在 fewer-probes 后 | 待领取 | — |
| `TASK-rectification-telemetry-20260926.md` | [PROGRESS](PROGRESS-rectification-telemetry-20260926.md) | **匿名聚合统计**:每会话一行只存数字 / 枚举(题数分类、宽度、差距、停止原因、门槛达标、耗时、版本),管理后台只看汇总、保留 180 天;动表须 test:db。排在 fewer-probes 后 | 待验收 | `codex/rectification-telemetry-20260926`(未推送;迁移 `20260926010000` 加两表三函数;行里不存用户 / 案例 id,去重另走级联台账;本机无 Docker,test:db 以门禁为准) |
| `TASK-rectification-offline-research-20260926.md` | `PROGRESS-rectification-offline-research-20260926.md` | **三项离线研究**:答错 1–2 题的容错、V1/V2 分盘配权正确重跑、改正「1 分钟≈1.1 天」(实测中位 3.8 天)并核实 `_representative_pairs` 推断。不改线上。结论(`docs/research/rectification_offline_research_2026_09_26.md`):R1 答错 1 题真值在区间 98–100%、头名降三到四成,答错 2 题 ±30/±60 挤出 7–10%(两道反答=8 分=淘汰线);R2 权重生效,V1/V2 在 ±30/±60 按定义恒等、±10 六题后指标不变 → `no_benefit`(已实测);R3 3.8 天/分钟复现,45 天闸≈8–34 分钟,`_representative_pairs` 推断被推翻(全配对题数不变,卡在逐月评估),另记 BUG-1048 `investigating`(闸门跨年豁免 + zip 错位)。三项均不建议立实现单 | 已验收 | `0f5442ce`(纯研究,不改线上);三项均不立实现单:答错 2 题 ±30 真值入区间 0.93、V1/V2 no_benefit、每分钟边界位移中位 3.82 天(勘误 5 份文档);新发现 BUG-1048 出题闸门两处漏洞待产品决定 |
| `TASK-rectification-code-split-20260926.md` | — | **代码拆分(只搬不改)**:聊天组件 2043 行 / 35 useState、`POST` 926 行、`runV9AgentTurn` 1047 行,269 处切源码测试;拆分 + 增长合同 + 切片测试改调用函数。排在 fewer-probes、telemetry 之后 | 待领取 | — |
| `TASK-rectification-dup-question-20260926.md` | `PROGRESS-rectification-dup-question-20260926.md` | **同一轮问题出现两次(BUG-1045,复发自 BUG-585,BUG-969 拼回题干、去重只在刷新路径)+ 同一道选择题连画两张(BUG-1046:提交失败不回滚本地已答 + 兜底问题块条件过宽;H2 漏收回合)**。先于 latency 单 | 已验收(Claude 09-26 直接执行:子代理复现 A 与 B-H1(选择题提交 409 / 网络错误不回滚本地已答);Claude 变基到含 BUG-1043/1044 的 staging 后独立复验 tsc/lint 0、全量 3981 条失败名单与基线逐条一致、四路由 ○、gzip 不变) | `e4c1c7a3`(已部署 `f1d16405`,health 一致) |
@@ -0,0 +1,28 @@
# 生时校正匿名统计:真人验收清单(2026-09-26)
前提:staging 已部署含 `20260926010000_rectification_telemetry.sql` 的版本(门禁会先自动跑 Migrate Staging Database),并用有「查看客户基本资料」权限的后台账号登录 `https://admin.staging.jyotisha.chat`。
## A. 后台能看到汇总
1. 左侧菜单出现「校正统计」,点进去页面标题是「生时校正统计」。
2. 顶部说明写着匿名、只看汇总、不能逐条查看或导出、保留 180 天。
3. 右上角可以切「近 4 周 / 近 12 周 / 近 26 周」,切换后数字随之变化,不报错。
4. 还没有任何数据时:会话数为 0,各分布表占比为 0,页面不报错。
## B. 做一次校正后数字会增加
1. 用自己的测试账号(受控账号,不要用真实用户)在 staging 走一次生时校正,直到出现「目前范围」卡片。
2. 回到后台「校正统计」刷新:会话数 +1;「最终范围宽度分布」「提问数分布」「停止原因」各有一格 +1;按周趋势里本周 +1。
3. 在同一个校正里继续补一件经历、再出卡,或者点「更像这个」采用:会话数**不再**增加(每个校正只记一次)。
4. 点「停止」结束另一个校正并出现范围卡:停止原因「用户中止」+1。
## C. 看不到个人信息
1. 页面上没有任何用户邮箱、姓名、出生日期、地点、时间点(HH:MM)或对话内容。
2. 页面上没有下载、导出或逐条列表入口。
## D. 用户侧无感
1. 做校正的过程中,出卡那一轮的等待时间与以前一样,没有新的报错或提示。
发现问题请截图并记下操作时间(不要截到别人的资料)。
Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 207 KiB