From e96cc2fbb5506cdce82bf47377635e55ad4995c0 Mon Sep 17 00:00:00 2001 From: QiuSW <105186638@qq.com> Date: Tue, 4 Aug 2026 11:49:18 +0800 Subject: [PATCH] docs(design): close Bell prototype review gaps --- docs/02-requirements.md | 2 + docs/07-user-stories.md | 20 +- docs/08-interaction-checklist.md | 14 +- docs/design/bell/index.html | 451 ++++++++++++++++++++++++++----- docs/raw/14-Bell原型评审.md | 45 +++ docs/routes.md | 13 +- docs/tasks/T-004.md | 26 +- 7 files changed, 484 insertions(+), 87 deletions(-) create mode 100644 docs/raw/14-Bell原型评审.md diff --git a/docs/02-requirements.md b/docs/02-requirements.md index d1629d5..f0b67e5 100644 --- a/docs/02-requirements.md +++ b/docs/02-requirements.md @@ -56,6 +56,8 @@ - 升级链、超时、联系人和时段可按租户/站点配置。 - 至少两条独立投递路径,其中一条可绕过互联网。 - 区分已发出、已送达、已看到;没有回执不能当成功。 +- Alert 与 Event 保持可导航的多对多关系;被规则抑制且没有创建 Alert 的 Event 不伪装为已投递。 +- 班次交接覆盖未 ack、处置中与升级中的 Alert;接班确认留痕,交接过程不暂停或重置升级链。 - 静默必须限时且自动恢复,单次不超过 4 小时,无永久静默。 - 业务预警与运维告警使用不同通道和值班配置。 diff --git a/docs/07-user-stories.md b/docs/07-user-stories.md index c434663..a3c2827 100644 --- a/docs/07-user-stories.md +++ b/docs/07-user-stories.md @@ -23,7 +23,7 @@ - 角色:家属/值班员。 - 目标:收到异常后查看关联证据、确认接手并记录处置结果。 - 价值:把“发出通知”变成“有人负责”。 -- 验收:首次投递、送达、看到、ack、升级分别可追溯;无 ack 自动升级;进程重启不丢失升级链。 +- 验收:通道的已发出、已送达、已看到,与 Alert 的 ack、升级分别可追溯;无回执、通道不支持、可重试失败和最终失败不伪装成功;Alert 可查看聚合的 Event,Event 可查看触发的 Alert;并发 ack 时后到者看到真实处置人且不能覆盖;无 ack 自动升级,进程重启不丢失升级链。 - 关联:RQ-C-17~RQ-C-30,IX-005~IX-008。 ## US-004 标记误报 @@ -39,7 +39,7 @@ - 角色:租户管理员/站点管理员。 - 目标:按站点和设备覆盖场景模板,配置区域、时段、持续时间和联系人升级链。 - 价值:同一通用底座适配不同场景。 -- 验收:继承来源清楚、变更可试运行/回滚、静默不超过 4 小时且自动恢复。 +- 验收:继承来源清楚、变更可试运行;回滚先展示版本差异与影响,并创建新的不可变版本,不改写历史;静默不超过 4 小时且自动恢复。 - 关联:RQ-C-11~RQ-C-15、RQ-C-23~RQ-C-28,IX-010~IX-012。 ## US-006 事件最小权限查看 @@ -82,6 +82,22 @@ - 验收:Bell 是 Site/Area/配额/策略真相源;策略变更影响已有成像设备时必须显式选择迁移或取消,不自动停用;Sense 展示策略版本与同步状态,投影不可用时仅拒绝相关新写入。 - 关联:RQ-S1-05、NFR-CMP-05,IX-016、IX-020。 +## US-011 完成值班交接 + +- 角色:交班值班员/接班值班员。 +- 目标:在班次结束前把所有未 ack、处置中和升级中的 Alert 连同备注交给下一班,并得到明确接手确认。 +- 价值:保证“有人负责”不在班次边界中断。 +- 验收:交接清单显示当前状态、处置人与下一次升级时间;接班人确认后写审计;交接过程不暂停、不重置升级链,未确认交接时原责任关系保持不变。 +- 关联:RQ-C-17~RQ-C-30,IX-021。 + +## US-012 导出规则验收效果 + +- 角色:项目负责人/租户管理员/验收人员。 +- 目标:按规则版本和冻结样本窗口查看可复核的召回率与每路每天误报数。 +- 价值:让站点验收使用场景相关、可追溯的效果口径,避免跨场景“准确率”误导。 +- 验收:报表展示规则版本、样本时间窗、正样本/漏检样本、通道天数、召回率和每路每天误报数;明确不提供跨场景统一准确率;导出保留筛选与口径说明。 +- 关联:RQ-C-22、`02-requirements` §8,IX-022。 + ## 追溯规则 新增 P0 UI 任务必须引用至少一个 US 和一个 IX;若没有 UI,任务文件明确写“不适用”。需求变化先更新用户故事和交互清单,再改页面。 diff --git a/docs/08-interaction-checklist.md b/docs/08-interaction-checklist.md index af17a63..480282d 100644 --- a/docs/08-interaction-checklist.md +++ b/docs/08-interaction-checklist.md @@ -8,13 +8,13 @@ | IX-002 | 配额与批量结果 | 显示已用/上限;超 16 不等于非法,按站点配置校验;部分成功可重试;配额不可读取时只禁用新增/启用并保留已有列表与流 | US-001 | M2 | | IX-003 | 设备列表 | 分页/筛选/批量选择;128 路不一次加载所有视频和详情 | US-001 | M2/M4 | | IX-004 | 设备健康 | 期望态、媒体/推理/存储实际态、认证失败、最后在线完整时间与站点时区、时间漂移、分片、重试进度;运维告警独立,凭据更新只允许写入新值且旧值永不回显 | US-002 | M2/M4 | -| IX-005 | 预警到达 | 明确严重度、站点、时间、证据可用性;重复投递不产生重复处置 | US-003 | M3 | -| IX-006 | ack | 一次点击可确认,显示确认人/时间;并发 ack 有清晰结果 | US-003 | M3 | -| IX-007 | 升级 | 显示当前层级、下一次升级时间、每次投递状态;失败不能伪装成功 | US-003 | M3 | -| IX-008 | 事件详情 | 结构化事实、抓拍、视频、时间线、处置;证据加载失败可重试且不丢元数据 | US-003 | M3/M4 | +| IX-005 | 预警到达 | 明确严重度、站点、时间、证据可用性与关联事件数;重复投递不产生重复处置 | US-003 | M3 | +| IX-006 | ack | 一次点击可确认,显示确认人/时间;服务端首个成功者成为处置人,并发后到者看到当前处置人和冲突结果,不静默覆盖或显示双成功 | US-003 | M3 | +| IX-007 | 升级与投递 | 显示当前层级、下一次升级时间;每个通道分别展示已发出、已送达、已看到,Alert ack 单独展示;无回执/不支持/未知、可重试失败及最终失败不得伪装成功 | US-003 | M3 | +| IX-008 | 事件详情 | 结构化事实、抓拍、视频、时间线、处置;证据加载失败可重试且不丢元数据;Alert 展示关联 Event 与聚合原因,Event 展示触发的 Alert 与最终状态,两边可深链;被抑制且未创建 Alert 的事件明确标为未触发 | US-003 | M3/M4 | | IX-009 | 误报反馈 | 确认动作、可选原因、提交成功反馈;只改变 outcome,不改原始事件 | US-004 | M3 | | IX-010 | 规则编辑 | 显示租户/站点/设备继承来源,支持区域/警戒线/时段/持续时间 | US-005 | M3/M4 | -| IX-011 | 规则试运行 | 明确“未正式生效”,展示命中样本与影响范围,支持取消/回滚 | US-005 | M4 | +| IX-011 | 规则试运行与回滚 | 明确“未正式生效”,展示命中样本与影响范围,支持取消;回滚前展示目标版本差异与影响,确认后创建并发布等价的新版本,历史版本保持不可变;版本冲突时阻止覆盖并提供刷新/另存路径 | US-005 | M4 | | IX-012 | 升级链/静默 | 联系人顺序、超时、双通道;静默最长 4h、显示自动恢复时间、无永久选项 | US-005 | M3/M4 | | IX-013 | 权限与隐私 | 越权统一处理;无授权租户不展示人脸入口;不泄露流 URL/凭据 | US-006 | M3/M4 | | IX-014 | 设备模态与能力 | 一级入口为“设备”;列表可按 `modality` 筛选,添加时先选模态,详情按 `capabilities` 渐进展示;能力同时显示厂商/型号/固件/认证、探测来源与时间、探测值和生效值差异;视频设备显示画面/媒体/检测区域,未交付的非视频适配器显示 `adapter_not_ready`,不用虚构遥测或禁用的视频页签占位 | US-008 | M2/M6 | @@ -23,7 +23,9 @@ | IX-017 | 检测区域几何编辑 | 多边形和方向警戒线支持绘制、显式完成、撤销、清空、顶点编辑;警戒线在草稿/已保存态均显示方向箭头并可反转;鼠标与键盘坐标操作等效;画面参数变化后标记待校准且不自动改坐标;区域版本与规则版本独立 | US-005 | M3 | | IX-018 | 草稿与跨系统上下文 | 几何草稿自动保存并可恢复;只有持久化失败或切换空间类型等会破坏草稿的动作才拦截确认;Sense↔Bell 双向携带并消费 `camera + zone + return_to` 上下文;返回后恢复草稿,版本已被他人更新时提示冲突且不覆盖 | US-005 | M3 | | IX-019 | 运维中心与写入降级 | Sense 用一个一级“运维中心”聚合对账差异/退避/下次重试/孤儿安全闸、媒体与推理分片、边缘节点/隧道/补传、运维告警和系统状态;配额或 Area 策略不可读取时页面继续可读且已有链路不受影响,只禁用相关写操作;不得混入 Bell 业务预警 | US-002、US-008 | M2/M4/M6 | -| IX-020 | 管理上下文、RBAC 与审计归属 | 全局头部显示租户、站点、账号和角色;只读角色隐藏写操作,深链越权统一拒绝且不泄露资源是否存在;Tenant/Site/Area/RBAC/配额/全局审计由 Bell 管理,Sense 只呈现消费上下文和设备操作入口,携带 tenant/site/device/return_to 深链到 Bell 审计 | US-006、US-009、US-010 | M2/M4 | +| IX-020 | 管理上下文、RBAC 与审计归属 | 全局头部显示租户、站点、账号和角色;只读角色隐藏写操作,深链越权统一拒绝且不泄露资源是否存在;Tenant/Site/Area/RBAC/配额/全局审计由 Bell 管理,Sense 只呈现消费上下文和设备操作入口,携带 tenant/site/device/return_to 深链到 Bell 审计;Bell 移动端底部导航不超过 5 项,并通过可发现的“管理”入口访问 Site/Area 与审计 | US-006、US-009、US-010 | M2/M4 | +| IX-021 | 值班交接 | 清单覆盖未 ack、处置中和升级中的 Alert,显示交班人、接班人、备注及下一次升级时间;接班确认写审计,交接期间不暂停或重置升级链,未确认时不转移责任 | US-011 | M3 | +| IX-022 | 规则验收报表 | 按规则版本与冻结样本窗口展示召回率、每路每天误报数和计算样本量;支持保留口径的导出;不提供跨场景统一准确率 | US-012 | M4 | ## 全局状态 diff --git a/docs/design/bell/index.html b/docs/design/bell/index.html index 34f1d63..75ef0ef 100644 --- a/docs/design/bell/index.html +++ b/docs/design/bell/index.html @@ -79,6 +79,7 @@ .btn-danger { background: rgba(251,113,133,.1); border-color: rgba(251,113,133,.38); color: #ffb4c2; } .btn-quiet { border-color: transparent; background: transparent; color: var(--muted); } .icon-btn { width: 42px; padding: 0; } + .text-button { min-height: 32px; padding: 2px 6px; border: 0; background: transparent; color: #b8e5ff; text-decoration: underline; text-underline-offset: 3px; } .select, .field, .textarea { width: 100%; min-height: 40px; padding: 8px 11px; border: 1px solid var(--line); border-radius: 9px; background: var(--surface-2); color: var(--text); } .textarea { min-height: 80px; resize: vertical; } .top-actions .select { width: auto; min-width: 150px; } @@ -132,10 +133,18 @@ .fact span { display: block; color: var(--muted); font-size: 11px; } .fact strong { display: block; margin-top: 3px; font-size: 13px; font-variant-numeric: tabular-nums; } .privacy-note { margin: 0 12px 12px; padding: 9px 10px; display: flex; gap: 8px; border-left: 3px solid var(--cyan); background: rgba(56,189,248,.08); color: var(--muted); font-size: 12px; } + .relation-panel { margin: 0 12px 12px; padding: 11px; border: 1px solid var(--line); border-radius: 10px; background: var(--surface-2); } + .relation-panel h3 { margin: 0 0 8px; font-size: 13px; } + .relation-list { display: grid; gap: 7px; } + .relation-item { min-height: 40px; padding: 8px 10px; border: 1px solid var(--line); border-radius: 8px; background: var(--surface); color: var(--text); display: flex; align-items: center; justify-content: space-between; gap: 10px; text-align: left; } + .relation-item span { color: var(--muted); font-size: 12px; } .action-scroll { max-height: calc(100dvh - 210px); overflow-y: auto; } .ack-box { padding: 14px; border-bottom: 1px solid var(--line); } .ack-box .btn { width: 100%; min-height: 48px; } .ack-box p { margin: 9px 0 0; color: var(--muted); font-size: 12px; } + .ack-tools { margin-top: 8px; display: flex; justify-content: flex-end; } + .inline-alert { margin-top: 9px; padding: 9px 10px; border: 1px solid rgba(251,191,36,.4); border-radius: 8px; background: rgba(251,191,36,.09); color: #ffe8a8; font-size: 12px; } + .inline-alert.danger { border-color: rgba(251,113,133,.42); background: rgba(251,113,133,.09); color: #ffc3ce; } .countdown { display: grid; grid-template-columns: auto 1fr; gap: 10px; align-items: center; padding: 12px; margin: 12px; border: 1px solid rgba(251,191,36,.28); border-radius: 10px; background: rgba(251,191,36,.07); } .countdown strong { display: block; font-size: 20px; color: #ffe18a; font-variant-numeric: tabular-nums; } .countdown span { color: var(--muted); font-size: 12px; } @@ -149,6 +158,8 @@ .step.current .step-dot { background: var(--warning); } .step strong { display: block; } .step span { color: var(--muted); font-size: 12px; } + .delivery-facts { margin-top: 4px; display: grid; gap: 2px; } + .delivery-facts span { display: block; } .disposition { padding: 14px; border-top: 1px solid var(--line); display: grid; gap: 9px; } .disposition label { color: var(--muted); font-size: 12px; font-weight: 700; } .disposition-actions { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; } @@ -167,6 +178,8 @@ td { font-variant-numeric: tabular-nums; } tr:last-child td { border-bottom: 0; } tr:hover td { background: color-mix(in srgb, var(--primary-soft) 50%, transparent); } + .pager { min-height: 58px; padding: 10px 14px; border-top: 1px solid var(--line); display: flex; align-items: center; justify-content: space-between; gap: 12px; } + .pager-actions { display: flex; gap: 7px; } .rule-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); } .rule-card { padding: 15px; } .rule-card-top { display: flex; align-items: center; justify-content: space-between; gap: 8px; } @@ -190,6 +203,9 @@ .linked-zone strong, .linked-zone small { display: block; } .linked-zone small { color: var(--muted); } .workflow-note { grid-column: 1/-1; margin: 0; padding: 10px 11px; border-left: 3px solid var(--primary); background: var(--primary-soft); color: var(--muted); font-size: 12px; } + .version-diff { display: grid; gap: 8px; } + .version-diff article { padding: 10px 12px; border: 1px solid var(--line); border-radius: 9px; background: var(--surface-2); } + .version-diff article strong { display: block; } .chain-grid { grid-template-columns: minmax(0, 1.4fr) minmax(300px, .8fr); } .chain-row { padding: 13px 14px; display: grid; grid-template-columns: 40px 1fr auto; gap: 11px; align-items: center; border-bottom: 1px solid var(--line); } .chain-row:last-child { border-bottom: 0; } @@ -206,6 +222,7 @@ .donut::after { content: "83%\A 24h 内闭环"; white-space: pre; position: absolute; inset: 27px; border-radius: 50%; display: grid; place-items: center; text-align: center; background: var(--surface); color: var(--text); font-weight: 800; } .legend { display: flex; flex-wrap: wrap; gap: 10px; color: var(--muted); font-size: 12px; } .legend i { display: inline-block; width: 9px; height: 9px; margin-right: 5px; border-radius: 2px; } + .metric-note { margin: 12px 0 0; padding: 10px 12px; border-left: 3px solid var(--cyan); background: rgba(56,189,248,.08); color: var(--muted); } .state-layer { display: none; min-height: 420px; place-items: center; padding: 24px; border: 1px dashed var(--line); border-radius: var(--radius); background: var(--surface); text-align: center; } .state-layer.show { display: grid; } .state-layer .icon { width: 40px; height: 40px; color: var(--primary); } @@ -216,7 +233,7 @@ .skeleton i:nth-child(2) { width: 72%; } @keyframes shimmer { to { background-position: -200% 0; } } dialog { width: min(610px, calc(100% - 28px)); max-height: 88dvh; padding: 0; border: 1px solid var(--line); border-radius: 16px; background: var(--surface); color: var(--text); box-shadow: 0 24px 80px rgba(0,0,0,.5); } - #ruleDialog { width: min(760px, calc(100% - 28px)); } + #ruleDialog, #eventDialog, #handoverDialog, #rollbackDialog { width: min(760px, calc(100% - 28px)); } dialog::backdrop { background: rgba(4,7,15,.68); backdrop-filter: blur(4px); } .dialog-head, .dialog-foot { padding: 14px 18px; border-bottom: 1px solid var(--line); display: flex; align-items: center; justify-content: space-between; gap: 10px; } .dialog-head h2 { margin: 0; font-size: 17px; } @@ -232,6 +249,7 @@ .muted { color: var(--muted); } .mono { font-family: ui-monospace, SFMono-Regular, Consolas, monospace; font-variant-numeric: tabular-nums; } .mobile-nav { display: none; } + .mobile-manage { display: none; } @media (max-width: 1240px) { :root { --sidebar: 78px; } .brand-copy, .nav span:not(.count), .nav-label, .shift-card { display: none; } @@ -249,6 +267,7 @@ .sidebar { display: none; } .topbar { padding: 8px 12px; } .site span, .top-actions .select { display: none; } + .mobile-manage { display: inline-flex; min-width: 44px; } .content { padding: 12px; } .btn, .select, .field, .textarea { min-height: 44px; } .icon-btn { min-width: 44px; } @@ -260,6 +279,7 @@ .site-grid { grid-template-columns: 1fr; } .rule-grid { grid-template-columns: 1fr 1fr; } .fact-grid { grid-template-columns: repeat(2, 1fr); } + .pager { align-items: flex-start; flex-direction: column; } .mobile-nav { position: fixed; z-index: 50; left: 8px; right: 8px; bottom: 8px; display: grid; grid-template-columns: repeat(5, 1fr); padding: 5px; border: 1px solid var(--line); border-radius: 14px; background: var(--surface); box-shadow: var(--shadow); } .mobile-nav button { min-height: 48px; border: 0; border-radius: 9px; background: transparent; color: var(--muted); display: grid; place-items: center; font-size: 11px; } .mobile-nav button.active { color: #c9c1ff; background: var(--primary-soft); } @@ -302,13 +322,16 @@
@@ -435,8 +455,9 @@
+

产品流程:先确认摄像头和检测区域,再配置业务条件;试运行样本达到现场评审要求后,才允许正式发布。

-
+

标记为误报

这只会追加事件 outcome,不会修改原始事件事实和证据。

@@ -445,78 +466,374 @@

编辑 Area 准入策略

保存生成新策略版本;Sense 投影同步前会显示旧版本,不允许绕过后端准入检查。

策略与已有设备冲突

北围墙当前有 4 台成像设备。改为“仅非成像”前必须选择显式处置;系统不会自动停用、移动或保留违规设备。

+ +

管理

移动端保留 5 个主入口,低频管理能力从这里进入。
+ +

事件详情

不可变事实
事件编号—
点位—
规则—
证据—

触发的预警

+ +

值班交接

白班 · 林值班员 → 晚班
ALT-1842 · 未 ack下一次升级 01:42
ALT-1841 · 处置中王值班员现场核查
ALT-1839 · 升级中短信重试 2/3

交接期间升级链继续计时,不暂停、不重置。接班人确认前,当前责任关系保持不变。

+ +

版本历史与回滚

RULE-007 · 历史版本不可变
当前 v7 · 2026-08-01 正式发布持续 3 秒 · 全天 · 4 个点位 · 区域 v7
目标 v6 · 2026-07-18 历史版本持续 5 秒 · 夜间 22:00–06:00 · 3 个点位 · 区域 v6
影响评估将减少 1 个点位并收窄时段;预计每日预警 -18%。确认后创建并发布 v8,使其配置等价于 v6,v6/v7 均保持不变。