405 lines
61 KiB
Markdown
405 lines
61 KiB
Markdown
# 景区排队叫号系统:调研发现与决策台账
|
||
|
||
## 员工端末号预计时长与闪屏(2026-07-12)
|
||
- `queueSnapshot` 当前把 `metrics.estimated_wait` 固定写成 `nil`,等待票的 `staffTicketView` 也未见按位置注入 ETA;员工前端却只读取最后一张等待票的 `estimated_wait`,因此稳定落入“暂不可估算”。
|
||
- 后台、公屏和游客接口已经统一调用 `domain.CalculateETA`;员工快照应按 `waiting_count - 1` 作为末号前方人数,并传入项目级 `ETAIntervalSeconds` 与当前运行状态。
|
||
- 员工页场景入场动画依赖 `[scene, Boolean(queue)]`。初始渲染 `queue=false`,首个轮询响应后变为 `true`,整块页面会再次淡入/位移,视觉上表现为刷新闪屏;该动画应只随场景切换,不随轮询数据挂载重播。
|
||
- 修复后首次队列数据挂载只设置稳定终态;只有 `scene` 真正变化时才播放场景切换动画。五秒轮询仍保留,且沿用旧数据刷新,不卸载叫号主内容。
|
||
- `formatEstimatedWait` 现在优先识别服务端标准字段 `estimate_minutes`,单点预测展示为“约 N 分钟”,避免同值上下界显示成“N-N 分钟”。
|
||
- 用户刷新后仍见“暂不可估算”的原因是开发 API 于 14:23 启动,早于后端修复且不支持热更新;Vite 前端已热更新,形成新前端配旧接口的状态,并非算法再次失效。
|
||
- 重启 API 后真实员工接口确认:云栖观光车项目/会话均为 `RUNNING`,配置每号 96 秒,等待 279 号,末号估算返回 `available=true, estimate_minutes=450`。
|
||
- 继续排查周期性闪屏发现:`FreshnessBanner` 在每次五秒轮询开始时插入“更新中”段落,完成时删除,导致员工页主体随 DOM 高度变化上下跳动。健康的后台刷新不应占据布局;游客端已有顶部实时状态,管理端已有刷新按钮状态,删除该临时段落不损失必要反馈。
|
||
- 游客端另有两个直接消费 `resource.refreshing` 的可见状态:页头每三秒在“实时更新/更新中”之间切换,刷新按钮同步启用/禁用并改变样式。它们虽然不卸载主卡片,但会造成周期性色彩和透明度闪动;健康自动轮询应保持“实时更新”和按钮外观稳定,只在离线或陈旧时改变界面。
|
||
|
||
## 大屏全屏纵向布局(2026-07-12)
|
||
- 全屏信息顺序调整为:日期时间与项目名标题栏 -> 当前叫号 -> 自动轮播列表。
|
||
- 现有轮播分页和六秒切换逻辑可直接保留,只调整全屏结构与标题信息。
|
||
- “总计等待号数”与“最新取号码”同置于列表标题栏,删除底部重复等待统计。
|
||
|
||
## 大屏顶部信息优化(2026-07-12)
|
||
- 用户截图对应管理端 `ProjectScreenTile` 的单项目全屏状态,不是独立公示屏 `DisplayPage`。
|
||
- 当前全屏顶部只有超大项目名和状态徽标,日期时间缺失,项目名称与主叫号数字竞争视觉注意力。
|
||
- 调整边界:日期时间仅在单项目全屏时显示在左上角;项目名称作为右侧上下文;项目状态从该大屏组件删除。
|
||
|
||
## 项目管理/规则配置拆分(2026-07-11)
|
||
- 当前 `/admin/projects` 只渲染 `ProjectSettingsForm`,内容是项目状态、叫号估算数、预计等待方式与参数,本质上是规则配置。
|
||
- 后端只有 `PUT /api/admin/projects/{id}/settings`,没有创建项目或维护项目基础信息的管理 API。
|
||
- `projects` 已包含可作为项目档案的 `name`/`code`/`timezone`/`ticket_prefix`,规则参数也已天然按项目行隔离,无需新建规则表。
|
||
- 最终交互边界:只保留“项目管理”导航;列表负责创建和进入维护,单个项目维护页同时包含基础信息与当前项目的规则配置。
|
||
- 时区不向管理员暴露,底层继续使用现有默认值保持数据兼容;票号不再手填前缀,界面仅提供 `00000` 格式选项。
|
||
- 项目名称/编码与运行状态/预计等待参数在管理交互中都是“项目维护字段”,不再使用基础信息和规则配置的视觉分区。
|
||
|
||
## 员工端 H5 GSAP 交互审计(2026-07-11)
|
||
- 员工端当前以 `/staff`、`/staff/tickets`、`/staff/me` 三个场景组织,核心动作是快速叫号、批量叫号、创建排队号码和切换项目。
|
||
- 当前已具备 busy、成功/警告/失败、轮询、离线/陈旧提示、幂等键等业务反馈;GSAP 必须消费这些状态,不建立第二套状态。
|
||
- 最适合 GSAP 的位置是组合状态时间线:叫号结果与队列重排、取号指标更新、项目切换弹层、场景内容切换。按钮 hover/focus/press 继续使用 CSS。
|
||
- 批量叫号必须作为原子事件整体进入;禁止逐号 stagger、老虎机数字、弹跳、闪烁以及依赖动画回调执行业务。
|
||
- 轮询每 5 秒更新,不能每次都播放动画;只强调当前前台操作导致且 revision 前进的变化。页面恢复前台后直接展示权威快照,不补播旧动画。
|
||
- 所有动画应通过 `useGSAP` 限定作用域并清理,使用 `gsap.matchMedia()` 为 reduced motion 提供直接终态。
|
||
- 详细方案见 `docs/staff-h5-gsap-ux-plan.md`。
|
||
- 实施采用单一 `motion/gsap.ts` 入口注册 `useGSAP` 与 Flip,避免各组件重复注册插件。
|
||
- 场景动画依赖 `Boolean(queue)`,确保初始加载态结束、真实场景挂载后才播放;无授权项目时不再对空 selector 调用 GSAP。
|
||
- 测试环境固定匹配 reduced-motion 分支,使可访问性查询不会在动画中间态把内容判定为隐藏,同时保留业务和焦点行为测试。
|
||
|
||
## Phase 16 跨端对齐审计(2026-07-11)
|
||
- 员工端已以“单号快速叫号 + 1-100 手动数量叫号”为权威交互,后台仍暴露 `call_batch_size` 配置,会让运营人员误以为叫号数量由项目固定。
|
||
- 管理端仍有 `第 N 批` 兼容显示分支;新业务界面应始终展示实际号码/号段,内部 call batch 仅作事务和审计容器。
|
||
- 游客端存在硬编码“第 33 位 / 共 65 位”、`10:30` 和“每 30 秒”,与 API 真实 `people_ahead` 及 5 秒轮询逻辑冲突,必须改为真实投影。
|
||
- 大屏号段预测已从当前叫号尾号推导,可兼容每日五位数字号;用户语义应统一为“本次叫号/最近叫号”。
|
||
|
||
## 用户已确认的需求
|
||
- 员工端:H5,可取号、叫号。
|
||
- 游客端:H5,可查看排队情况和预估等待时间。
|
||
- 大屏端:Web,公示最新排队情况。
|
||
- 管理端:Web,管理预估规则、数据日志、账号等。
|
||
- 取号标识包含手机号、姓氏、性别。
|
||
- 支持批量叫号。
|
||
- 员工端与大屏可能外接硬件,必须预留接口。
|
||
- 先调研成熟案例并形成完整规划,确认后再实施。
|
||
- 一个系统需要支持多个景区游玩项目,排队、规则、员工权限、设备和数据均按项目区分。
|
||
- 系统应优先简单操作和轻量实现,避免复杂工作流、过度配置与笨重架构。
|
||
- 运营数据看板并入管理端开发,不单独建设一套看板系统。
|
||
- 面向用户的文案使用“预计等待时间/预计叫号时间”,不直接显示英文缩写 ETA。
|
||
- 员工端与管理端(含运营数据看板)均必须通过账号登录后访问;不提供匿名入口。
|
||
|
||
## 当前假设(尚未确认)
|
||
- 这是从零开始的绿地项目;仓库当前无业务代码或既有架构约束。
|
||
- 当前按“一个景区/运营主体下包含多个游玩项目”规划,不在 MVP 引入多租户或多景区集团层级。
|
||
- 游客 H5 的“查看”入口可能通过号码查询链接、二维码或手机号验证访问。
|
||
- 首期不直接承诺与特定品牌硬件绑定,而以设备适配层隔离。
|
||
|
||
## 未决决策
|
||
- 取号粒度:个人或同行团体。
|
||
- 游客能否自助取号、是否需要短信验证码、是否允许远程取号。
|
||
- 批量叫号的精确定义与操作上限。
|
||
- 过号、回呼、取消、迟到、优先队列、闭园和故障降级规则。
|
||
- 硬件类型、品牌、协议、部署网络及现场控制要求。
|
||
- 短信/公众号/小程序通知是否属于范围。
|
||
- 多景区/多运营主体、多租户、票务/闸机/CRM 集成是否属于后续范围;MVP 只确认同一系统内的多项目。
|
||
- “看板并入管理端”当前解释为运营数据看板并入管理端,原需求中的游客公示大屏仍保留为只读页面;若用户所说“看板”即指公示大屏,需重新确认页面归属。
|
||
|
||
## Design Brief
|
||
- 模式:绿地产品,不是现有界面重设计。
|
||
- 设计目标:降低游客等待焦虑,提高员工高压操作正确率,让大屏在远距/强光下快速扫读,让管理端可审计且信息密度可控。
|
||
- 共同语言:可信、清晰、耐候、低焦虑;克制的景区品牌感建立在公共服务可读性之上。
|
||
- 四端差异:员工端高密度操作;游客端单任务引导;大屏远距信息;管理端数据/审计。
|
||
- 反方向:AI 紫渐变、全面玻璃拟态、娱乐化霓虹、三等分通用卡片、无意义循环动画、用颜色作为唯一状态信号。
|
||
- Product Design 未发现已保存的用户设计上下文或品牌资产;本轮从当前需求与公开参考出发,品牌色/Logo 作为后续可替换层。
|
||
|
||
## Design Research Findings
|
||
- UI/UX 设计库的首轮综合检索返回了 `Accessible & Ethical` 风格和高对比深蓝/蓝色板,这与公共服务场景吻合;但同时误匹配了 App Store 落地页、Cinzel/Josefin Sans 等奢华地产表达,已明确排除。数据库推荐只能作为候选,不可替代场景判断。
|
||
- 针对性风格检索最符合的是 `Swiss Modernism 2.0 + Accessible & Ethical + Inclusive Design`:严格网格、数学间距、非装饰性层级、单一品牌强调色、高对比、清晰焦点与 reduced motion。
|
||
- 产品类型检索把本项目识别为 `Government/Public Service` 与 `Real-Time Monitoring/Analytics Dashboard` 的组合。推荐底座是 accessible minimalism;实时监控只用于员工/管理端的信息组织,不采用 IoT 常见的全暗色玻璃拟态。
|
||
- 色彩候选中,公共服务深蓝方案和公共交通“蓝 + 橙”方案最相关。设计范式应把品牌主色与语义状态色分开:蓝色可承担品牌/交互,橙色只承担提醒或景区品牌点缀,红/绿/黄不可作为唯一状态编码。
|
||
- 简体中文字体检索明确支持 Noto Sans SC 单字体体系;首轮综合检索推荐的 Cinzel/Josefin Sans 缺少中文与公共服务适配性,排除。最终字体应优先系统中文字体栈或可自托管的 Noto Sans SC/思源黑体,数字可使用 tabular numerals。
|
||
- UX 检索强调:44×44px 以上触控目标、3-4px 可见焦点、动画只作用于每屏 1-2 个关键元素、完整 loading/success/error 反馈、320/375/414/768/1024/1440 多断点验证。
|
||
- 图表检索建议:等待趋势用折线图;ETA 预测与实际用实线/虚线加预测带;项目比较用条形图;目标达成用 bullet chart;时段拥挤用热力图但必须提供数值/表格替代。实时流图只在 ≥1Hz 且确有监控价值时使用,并提供暂停。
|
||
- GOV.UK 的官方设计原则与本项目高度一致:从用户需要开始、把复杂工作留给系统、为所有人设计、理解真实使用环境、建设完整服务而非孤立网页、保持一致但不强求四端完全相同。这支持“共享 token/语言,但按终端任务差异化”的设计范式。
|
||
- 中国侧可访问性底线可锚定现行 `GB/T 37668-2019`《信息技术 互联网内容无障碍可访问性技术要求与测试方法》。工信部适老化与无障碍改造通知进一步强调界面元素简化、信息扁平化、功能标识统一和操作流程一致;这些原则适用于游客 H5 的低认知负担设计,也适用于员工端在高压现场减少误操作。
|
||
- W3C《中文排版需求》最新工作草案(2026-05-03)提醒:中文并非把西文字号规则机械替换即可,设计需验证汉字字面、字重、行距、断行以及汉字与拉丁字母/数字/票号混排。项目因此统一采用清晰的中文无衬线字体,并将号码、ETA、时间戳的等宽数字和中西文混排列入真机测试。
|
||
- 成熟公共服务/交通系统共同指向“公共服务导视式界面(Public-service Wayfinding UI)”:事务层使用 GOV.UK/NHS 的清晰、可恢复和低负担模式,状态与组件采用 USWDS 一类语义 token,远距信息借鉴机场/公共交通导视。景区品牌只作为可替换的识别层,不侵入号码、ETA、状态和关键操作区。
|
||
- 官方导视标准支持以下可落地约束:无衬线、开放字腔、稳定笔画;正文左对齐、不两端对齐、不压在复杂图片上;长行控制在约 60–70 个西文字符等效范围。大屏字号不能只按 CSS px 验收,应按最远观看距离和屏幕实物字符高度做上午/正午/傍晚与斜视角测试。
|
||
- 动效原则收敛为“克制、快速、状态优先”:普通交互首选 CSS,React 条件面板才使用 Motion,GSAP 只允许进入大屏多区域同步换批等真正需要可中断时间线的少量场景。批量叫号必须作为一个原子批次同时出现,禁止逐号 stagger、老虎机数字、弹跳、闪烁、跑马灯和恢复前台后补播旧动画。
|
||
- 建议动效 token:按压 100ms、快速状态 150ms、标准面板 200ms、员工批次更新 300ms、大屏整体换批不超过 400ms;低动效仅保留不超过 100–150ms 的透明度/高亮,无动效为 0ms。业务提交、硬件命令、语音与动画并行响应同一事件,任何业务逻辑不得依赖动画完成回调。
|
||
- Page Visibility 与浏览器节流意味着 ETA、过号、叫号宽限和硬件执行都不能依赖前端计时器。标签页恢复时应先拉取服务端权威快照和 revision,直接显示最新状态,不重放隐藏期间的动画、提示音或语音。
|
||
- 排队产品 UI 专项核验收敛出 7 个成熟模式:Visitor Status Ticket、Operational Call Card、Batch Action Bar、Call Takeover、Live Ops Strip、Offline Trust Banner、Hardware Receipt Tray。前四项在 Qmatic/Waitwhile 公开资料中有直接界面或帮助文档证据;离线/硬件闭环可从 Wavetec/Qmatic 核验能力,但“多通道 ACK + 局部重试”并无成熟公开 UI,仍需本项目自定义。
|
||
- 厂商公开证据边界:Waitwhile 能证明批量 Serve/Alert/No Show 等操作,不能证明容量自动选组、原子事务、并发冲突和硬件 ACK;Qmatic 能证明单票叫号/转移/过号和多硬件,未证明多人原子批量叫号;因此不能从营销截图推断这些关键交互已经成熟。
|
||
- USWDS 使用语义颜色 token,而非在组件里硬编码;其官方可访问性指南强调颜色不能成为唯一含义。对本项目意味着品牌色、交互色、状态色和图表色必须分层,状态还需文字、图标和形状。
|
||
- WCAG 2.2 官方标准确认:普通文本至少 4.5:1、大字 3:1;支持 200% 文本缩放;焦点不可被遮挡;状态消息应能被辅助技术读取而不强制抢焦点;动画与闪烁需有暂停/停止/隐藏或 reduced motion 方案。
|
||
- TfL 的官方标准把一致的品牌、字体、颜色与安全/信心直接关联,并要求根据交通模式与环境选择正确标准。其导视强调清晰视线、图文结合、环境适配,而不是把一套 Web 卡片放大到屏幕。
|
||
- GOV.UK 错误消息规范要求错误具体、可修复、与字段标签语言一致,避免“发生错误”“必填”等泛化文案。这应作为员工取号表单和管理配置表单的文案标准。
|
||
|
||
## Research Findings
|
||
- 浏览器硬件 API 不能作为唯一的生产级硬件方案:截至 2026-07,WebUSB、Web Serial、WebHID 仍是“Limited availability”,且通常要求 HTTPS、安全上下文、用户授权/手势及特定浏览器支持。
|
||
- Web Serial 可连接物理串口以及通过 USB/Bluetooth 模拟串口的设备;首次授权需用户主动选择端口。它适合受控 Chromium 终端上的可选直连模式,不适合作为任意游客手机/任意浏览器的必备能力。
|
||
- 公网页面访问本地网络设备正在受到更严格的权限控制。Chrome 142 起推出 Local Network Access 权限提示;本地设备的 HTTP/HTTPS、CORS、证书及浏览器策略都会影响直连可靠性。
|
||
- 初步架构推论:硬件集成应有独立的“设备网关/本地代理”作为主路径,以云端下发设备命令、本地驱动适配、回传执行回执;WebUSB/Web Serial/WebHID 仅作为受控终端的可选适配器。所有设备命令都需幂等键、超时、重试、状态回执和手动降级。
|
||
- Waitwhile 的公开 API/帮助资料提供了一套可借鉴的领域拆分:Location/Queue、Service、Resource(窗口/通道/员工)、Customer、Visit。Visit 的主状态包含 WAITING、SERVING、COMPLETE,另有取消、到达、优先等标签/状态;事件以 visit.created/updated/removed、location-status.updated、message.created/updated 等 webhook 对外分发。
|
||
- Waitwhile 的 Visit 示例同时包含 `partySize`、票号、队列位置、原始/当前预估等待时长等字段,说明成熟产品通常把“访客资料”和“一次排队访问”分开,并显式支持同行人数。
|
||
- 成熟产品把游客个人状态页与公共大屏分开:个人页可展示实时位置、ETA,并允许到达/延迟/退出;公共屏可只显示票号/脱敏标识、正在服务及窗口/资源,且可播放声音。
|
||
- Waitwhile 的 API 允许一次创建或更新多个 Visit,但其“批量消息”不等于“批量叫号”。这进一步说明本项目必须定义批量叫号的原子语义,而不能把多选 UI 当作完整业务规则。
|
||
- 成熟系统记录账号、访客、队列访问、消息和配置变更等审计条目;并公开 409 并发冲突与 429 限流行为。对本项目的启示是叫号写操作需要乐观并发/串行化、幂等、重试边界和完整审计。
|
||
- 国内景区已有与本项目高度相似且可核验的成熟实操:
|
||
- 梵净山红云金顶采用扫码预约叫号,小程序展示预约号/当前叫号并在接近时提醒;现场广播和电子屏按连续号段(示例为 1736—1835)批量播报,引导游客在等待时游览其他点位。这直接证明“批量叫号”应支持按容量叫连续号段,并把 H5、提醒、广播、大屏统一在同一批次事件下。
|
||
- 长江索道通过售票窗口、自助机、微信公众号、OTA 等多入口实名购票取号,按号段、分时段乘坐;游客可在线查看排队进程并离开现场等候。其经验表明取号来源要统一归一化,队列票应可关联外部票务凭证,但不应把票务系统直接耦合进核心状态机。
|
||
- 陶然亭公园游船把云上排队、叫号登船、游船启航控制、广播、收银、定位和统计结合。其经验表明叫号系统可能最终进入“运营控制”边界,硬件命令与安全关键的启航控制必须分级授权、独立审计,不能由普通大屏页面直接触发。
|
||
- 国内案例还显示两种常见容量模型:红云金顶/长江索道属于按号段或批次放行,游船属于资源/船次容量调度。因此 ETA 不能只有“每人平均服务分钟数”一种公式,至少需支持连续服务与批次/班次两类规则。
|
||
- 国际主题乐园的官方资料进一步验证了几个共性:
|
||
- Disney、Universal、Europa-Park、USJ 普遍将门票/账户/同行组作为核销与排队主体,一人可为全组操作;成熟系统不会把姓名等弱标识当数据库主键。
|
||
- 主流体验通常使用 boarding group、return window 或系统分配时段,并明确名额有限、可能停发/暂停,且不承诺静态精确分钟数。
|
||
- 过号策略差异很大:Disney 表述为迟到可能不予接待;Europa-Park 明确迟到失去位置并需重新排队;这证明宽限、重排和重叫必须是项目级可配置规则。
|
||
- Volcano Bay 的 TapuTapu 用射频腕带、reader、振动提醒并支持遗失挂起/解绑;Disney/Universal 也使用 QR/NFC/实体票。这些案例支持“身份/核销凭证抽象 + 设备适配器”,而非绑定手机号或某一硬件协议。
|
||
- 多数官方游客材料不披露员工批量叫号 UI 和内部算法。可以确认 boarding group/号段/容量配额具备批量放行语义,但不能声称已核验某家具体的员工端按钮设计。
|
||
- 同行组应当成为一等业务对象:一个排队单需记录 `party_size` 及成员/外部票凭证(可选);按容量批量叫号默认不得无提示拆组,拆组或跳过大组必须授权并留痕。
|
||
- 通用厂商对照补充:
|
||
- Waitwhile 是公开资料中对批量操作证据最明确的产品,可多选 Visit/活动参与者执行 Alert、Serve 等操作,并公开 REST、Webhook、认证、限流和重试文档;但官方明确核心产品没有正式离线模式。
|
||
- Qmatic 公开能力主要是 Call next、指定号码、Recall/Recycle/No-show;优势是本地 Orchestra/Queue Agent 与打印、屏幕、语音硬件体系。其 Data Connect 是只读且非实时,不能被误用为叫号接口。
|
||
- Wavetec 公开案例展示本地 Controller、打印/语音/屏幕、双向 REST 与恢复后云同步,硬件/边缘模式成熟;但没有核验到一次叫多条独立票的公开证据。
|
||
- Qtrac、QLess 偏云端/浏览器和多渠道通知;公开材料不足以证明真正的批量多人叫号或断网自治。
|
||
- 行业结论是“批量叫号并非通用标配”。本项目的按人数/设备容量批量放行是核心差异,必须自建明确原子语义,而不是假定现成产品天然具备。
|
||
- Waitwhile 的 SUMMIT One Vanderbilt 案例按设施吞吐管理游客组:游客扫码/员工平板登记、填写同行人数,在场馆内活动,到时系统召集下一组。这是“同行组 + 设施容量 + 运营批次”的直接参考;页面所列效果与流量数字属于厂商案例自报。
|
||
- 合规核验结论:
|
||
- 手机号、姓氏、性别与游客关联后均属于个人信息;处理需目的明确、最小必要、事前告知并采用最短必要保存期限。
|
||
- 2025 年专项治理明确点名线下消费场景强制收集非必要手机号、生日、性别;仅写“用于取号标识”不足以自动证明三项均必要。
|
||
- 上述字段本身不在《个人信息保护法》第28条明确列举的敏感个人信息类别中,但聚合风险可能改变保护等级;不满14周岁未成年人的个人信息属于敏感个人信息。
|
||
- 大屏/广播若仍能对应具体游客,属于公开个人信息,应单独评估合法性/同意与保护影响;仅做手机号星号掩码并不自动等于匿名化。
|
||
- 网络运行/安全日志依法至少保留6个月;普通排队身份映射没有全国统一天数,应按最短必要;个人信息保护影响评估和委托/提供处理记录至少保留3年。
|
||
- 合规产品建议:公开屏和广播默认只使用随机票号;提供不依赖手机号的现场二维码/纸质号替代;儿童随监护人同行组处理;手机号只在短信/OTP/找回确有需要时收集;性别改为可选称谓或取消。
|
||
- ETA 研究结论:Little's Law `L=λW` 适合长期/稳定窗口的平均校验,不等于实时个人 ETA;景区午高峰、停机和增减资源是非平稳场景,直接用“人数÷到达率”会误导。
|
||
- ETA 应使用完成/放行吞吐而非游客到达率。批次项目基础公式可写为:`距下一批时间 + (ceil((前方有效人数 + 本组人数) / 预计实际批容量) - 1) × 预计批次间隔`;实际容量应来自近期真实入场而非名义容量。
|
||
- 游客展示应称“预测区间”而不是统计学上的置信区间;建议四舍五入到5分钟,显示高/中/低可信度、更新时间,并分别定义“预计叫到号”和“预计开始体验”两个可能的终点。
|
||
|
||
## 技术/产品决策
|
||
| Decision | Rationale |
|
||
|----------|-----------|
|
||
| 硬件采用抽象设备命令 + 本地设备网关,浏览器直连只作为可选方案 | 浏览器硬件 API 兼容性、授权和本地网络策略无法满足多硬件/多终端的稳定生产要求 |
|
||
| 大屏终端需支持保活、断线缓存和连接健康上报 | 大屏属于长时间运行终端;浏览器虽有 Screen Wake Lock,但旧设备兼容和权限仍需降级策略 |
|
||
| 客户(Visitor)与一次排队单(Queue Ticket/Visit)分表 | 同一游客可多次排队;排队状态、ETA 与审计属于一次访问而非永久身份资料 |
|
||
| 将批量叫号建模为独立 Call Batch,而非循环调用单号接口 | 需要原子选择、部分失败规则、统一回执、撤销边界和硬件播报一致性 |
|
||
| 游客个人状态页与公共大屏使用不同数据投影 | 权限、隐私、交互和刷新粒度不同,不能复用同一返回模型 |
|
||
| 大屏/广播默认只使用随机票号 | 手机号/姓氏/性别的公开必要性不足,且现场组合信息可能重新识别游客 |
|
||
| ETA 使用完成吞吐、批次容量和区间预测,不用到达率直接相除 | Little's Law 的稳定平均前提不适合非平稳实时队列;批次设施还受周期和实际载客量影响 |
|
||
| 先锁定队列修订行/CAS,再比较客户端修订号 | 避免两个并发叫号请求先同时通过版本校验,后到者等锁后仍沿用旧候选集 |
|
||
| 严格 FIFO 且不拆组时,ETA 复用逐组装箱算法 | `总人数÷容量` 忽略批次容量碎片,只能作为允许拆组时的近似下界 |
|
||
| MVP 的 `CallBatch` 只保留 ACTIVE/PARTIALLY_RESOLVED/RESOLVED | 覆盖叫号、部分到场/过号和结束;WITHDRAWN 撤回属于 P1,避免首期复杂逆向状态 |
|
||
|
||
## Phase 10:端结构重构发现
|
||
|
||
- 当前管理端只有 `/admin` 概览,后端已经提供项目参数更新接口;本轮可补齐项目管理表单,而不需要扩展服务端。
|
||
- 公示屏的公开令牌只保存哈希,管理概览不能重建现有 `/display/:token` 地址。因此大屏中心应以内置、受管理员保护的实时监控墙为主,物理公示屏继续沿用原有绑定 URL。
|
||
- 当前员工页把取号、批次核验、队首预览和叫号堆在一屏。重构为 `/staff`、`/staff/tickets`、`/staff/verify` 三个 H5 场景入口,可复用全部既有 API、幂等和项目授权逻辑。
|
||
- 设计采用公共服务导视式运营界面:桌面端左侧任务导航与高密度表格,H5 仅在当前场景呈现必要信息;不采用营销页面式视觉、装饰动效或新组件依赖。
|
||
| 硬件确认后再拆分下行 DeviceCommand 与上行 DeviceEvent | MVP 只保留统一接口和模拟成功/失败;扫码/按钮/完整 ACK 在具体硬件型号确认后实现 |
|
||
| taste 的建议只作用于品牌表达和反模板化检查 | 该 skill 明确不适合仪表盘、数据表与多步骤产品 UI;后台基础应选择成熟可访问组件模式 |
|
||
| GSAP 不作为全局默认动画库 | 简单状态反馈用 CSS/框架原生轻量过渡;只有大屏确有可中断多区域时间线需求时才评估 GSAP,并强制 reduced motion/清理 |
|
||
| 设计范式采用“公共服务导视型 Calm Utility” | 公共服务事务清晰度、交通导视和现场运营稳定性比旅游营销或科技大屏风格更适合四端场景 |
|
||
| 四端共享语义 token,但采用不同密度/信息层级 | 游客需要单主状态,员工需要高压操作,大屏需要远距扫读,管理端需要高密度审计;一致不等于相同 |
|
||
| 临时使用高对比蓝 + 暖橙品牌层,VI 到位后通过 alias 替换 | 当前没有既有品牌资产;语义状态、对比度、焦点和关键布局不能被品牌替换改变 |
|
||
| MVP 动效以 CSS/框架原生轻量过渡为主 | GSAP 只有大屏出现确切的可中断多区域时间线需求时才评估,且不能进入业务提交或设备控制链路 |
|
||
| 公共使用每日可读票号,私密查询使用高熵 token | 兼顾远距可读性与抗枚举;公开票号本身不能成为个人状态查询凭证 |
|
||
| WCAG 2.2 AA 与 GB/T 37668-2019 基线随 MVP 交付 | 无障碍不是后补功能;P1 只承载多语言、AAA 或专项辅助设备增强 |
|
||
| MVP 采用轻量模块化单体,不引入微服务、工作流引擎、规则 DSL 或事件溯源 | 用户明确要求系统不笨重;队列正确性保留在清晰的数据库事务中,其余能力按真实需求逐步增加 |
|
||
| 运营数据看板作为管理端模块 | 共用账号、权限、项目筛选和数据接口,避免多建一个前端应用与部署单元 |
|
||
| 以 `project_id` 作为核心业务边界 | 一个系统支持多个项目,但共用同一数据库和代码;项目分别拥有队列、规则、号段、设备、人员权限与统计 |
|
||
| 用户界面不用 ETA 缩写 | 对游客和现场员工统一写“预计等待时间”或“预计叫号时间”,降低理解成本 |
|
||
| 员工端与管理端看板均采用账号登录 + 项目授权 | 员工和管理员身份、可见项目与操作范围需要可追溯;游客状态页和公示屏仍使用受控无账号访问 |
|
||
|
||
## 风险与边界
|
||
- 手机号、姓氏、性别均涉及个人信息处理,大屏必须脱敏,日志需最小化留存与受控访问。
|
||
- 等待时间是动态估计,不宜呈现为确定承诺;需要区间、更新时间与异常降级。
|
||
- 叫号是高并发实时操作,必须防止重复叫号、跳号和多员工竞争导致的不一致。
|
||
- 浏览器直连本地硬件能力有限且兼容性不一,硬件接口不能只定义成前端 JavaScript API。
|
||
|
||
## 轻量化复核(2026-07-10 用户补充后)
|
||
- 原规划中的三类预计时间模型、完整规则版本审批、独立实时/设备工作进程等内容适合作为能力上限,但若整体进入 MVP 会违背“操作简单、系统不笨重”的新约束。
|
||
- MVP 应只实现首批项目实际需要的一种预计等待计算方式;同一项目只保存容量、批次间隔/平均处理时长、人工暂停等少量参数,高级回放、权重融合、复杂规则版本和机器学习后移。
|
||
- 管理端的运营数据看板与规则管理共用一个 Web 应用;游客公示大屏保留只读路由,不另建管理看板应用。
|
||
- 技术实现进一步收敛为一个后端应用、一个 PostgreSQL、同一代码库中的 H5/管理/公示页面;Redis、独立消息中间件、微服务和通用工作流引擎均不是 MVP 前提。
|
||
- 多项目采用同库同表 `project_id` 隔离,不做每项目一套部署/数据库,也不先建设组织—租户—景区—项目的多级继承。账号通过项目授权表访问一个或多个项目。
|
||
- 多项目下必须独立的最小范围:队列状态、票号前缀/序列、容量/预计时间参数、员工权限、设备绑定、营业状态和报表筛选;跨项目总览只放在管理端。
|
||
- 文档一致性复核发现旧版高级内容仍散落在领域对象、指标、测试和默认架构中(预计规则版本/逐次快照、复杂误差指标、定时发布回放、事务 Outbox/独立网关默认值);这些需要同步降级为简单配置、关键节点记录、基础误差统计和数据库待发送表/可选设备网关。
|
||
- 二次复核还发现硬件章节、管理接口和设计验收仍默认完整设备网关/规则发布流程。轻量版应把网关标为“真实硬件需要时选配”,管理接口改为项目预计时间设置,设计验收改为当前值/上一版/审计,而不是版本 diff 与发布流程。
|
||
- 最终轻量 MVP 已冻结为:四种项目状态(未开放/运行/暂停/结束)、唯一 `CALL_NEXT`、严格 FIFO、不拆组、不跳组、装不下即欠载;员工主界面没有手选、预叫、撤回或复杂规则。
|
||
- 硬件 MVP 只保留统一适配接口、模拟成功/失败和测试记录;注册配对、心跳、完整 ACK、扫码/按钮上行与本地网关均以具体硬件型号确认为前提。
|
||
- `project_id` 已形成闭环契约:覆盖所有项目级记录、唯一键、查询更新、统计审计、SSE 频道、设备命令和接口授权;项目范围由服务端从账号、查询令牌或设备绑定确定。
|
||
- 独立复核确认上述轻量化、多项目、看板归属和中文预计时间术语均无剩余 P1 问题。
|
||
|
||
## Resources
|
||
- MDN WebUSB API: https://developer.mozilla.org/en-US/docs/Web/API/WebUSB_API
|
||
- MDN Web Serial API: https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API
|
||
- web.dev Accessing hardware devices on the web: https://web.dev/articles/devices-introduction
|
||
- Chrome Web Serial guide: https://developer.chrome.com/docs/capabilities/serial
|
||
- Chrome Local Network Access update: https://developer.chrome.com/blog/local-network-access
|
||
- MDN Screen Wake Lock API: https://developer.mozilla.org/en-US/docs/Web/API/Screen_Wake_Lock_API
|
||
- Waitwhile API - List visits: https://developers.waitwhile.com/reference/listvisits
|
||
- Waitwhile API - Webhooks: https://developers.waitwhile.com/reference/webhooks-2
|
||
- Waitwhile webhook examples: https://developers.waitwhile.com/docs/webhook-response-examples
|
||
- Waitwhile audit entries: https://developers.waitwhile.com/docs/tracking-changes-with-audit-entries
|
||
- Waitwhile customer status page: https://help.waitwhile.com/en/articles/9949637-the-customer-status-page-real-time-updates-for-your-customers
|
||
- Waitwhile public/serving display: https://help.waitwhile.com/en/articles/11370712-how-to-use-the-waitlist-display-to-direct-customers-to-a-counter
|
||
- 梵净山扫码预约、当前叫号、号段广播(贵州省人大转载贵州日报): https://www.gzrd.gov.cn/gzwh/202505/t20250530_87945751.html
|
||
- 长江索道智能分流、按号段分时乘坐(重庆市政府): https://www.cq.gov.cn/ywdt/bmts/201809/t20180921_8655058.html
|
||
- 长江索道在线查看排队进程(重庆市政府,2025): https://www.cq.gov.cn/zwgk/zfxxgkml/zdlyxxgk/ggwh/ly/zxdt/202503/t20250311_14394287.html
|
||
- 陶然亭公园云排队、叫号、广播与启航控制(北京市公园管理中心): https://gygl.beijing.gov.cn/xxgk/xxgk_gyxx/202203/t20220321_2635717.html
|
||
- Disney World Virtual Queue: https://disneyworld.disney.go.com/en_CA/guest-services/virtual-queue/
|
||
- Universal Studios Hollywood Virtual Line: https://www.universalstudioshollywood.com/web/en/us/plan-your-visit/virtual-line
|
||
- Universal Orlando Virtual Line: https://www.universalorlando.com/web/en/us/plan-your-visit/virtual-line
|
||
- Europa-Park VirtualLine: https://www.europapark.de/en/theme-park/info/plan-your-visit/virtualline-europa-park
|
||
- Universal Studios Japan 预约乘坐: https://www.usj.co.jp/web/zh/cn/enjoy/numbered-ticket/yoyakunori
|
||
- Universal Volcano Bay TapuTapu FAQ: https://www.universalorlando.com/web/en/us/plan-your-visit/taputapu-faq
|
||
- Waitwhile 批量操作: https://help.waitwhile.com/en/articles/8061037-navigating-the-visits-page
|
||
- Waitwhile SUMMIT One Vanderbilt: https://waitwhile.com/case-studies/summit-one-vanderbilt/
|
||
- Waitwhile 离线能力说明: https://help.waitwhile.com/en/articles/11603596-does-waitwhile-work-without-internet
|
||
- Qmatic Serve View: https://docs.qmatic.io/en/staff-user-guides/user-guide--serve-view.html
|
||
- Qmatic Queue Agent: https://docs.qmatic.io/en/service-and-branch-configuration/branch-configuration/about-branches.html
|
||
- Qmatic Data Connect 限制: https://data-connect.docs.qmatic.io/developerguide.html
|
||
- Wavetec Wasl 本地分支与云同步案例: https://www.wavetec.com/es/case-studies/wasl-properties-customer-experience-transformation/
|
||
- Qtrac Virtual Queuing: https://qtrac.com/virtual-queuing/
|
||
- QLess Products: https://www.qless.com/products/
|
||
- 《个人信息保护法》: https://www.cac.gov.cn/2021-08/20/c_1631050028355286.htm
|
||
- 2025 年个人信息保护专项行动: https://www.cac.gov.cn/2025-03/28/c_1744867353112759.htm
|
||
- 《网络数据安全管理条例》: https://app.www.gov.cn/govdata/gov/202409/30/520076/article.html
|
||
- GB/T 45574-2025 敏感个人信息处理安全要求: https://openstd.samr.gov.cn/bzgk/std/newGbInfo?hcno=F9F3A2EBF49E9B4D73AD8C8912986D5A
|
||
- Little's Law 原始论文: https://pubsonline.informs.org/doi/10.1287/opre.9.3.383
|
||
- Time-Varying Little's Law: https://www.cambridge.org/core/journals/probability-in-the-engineering-and-informational-sciences/article/abs/estimating-waiting-times-with-the-timevarying-littles-law/18BF94EF65D06A5E52B72D1F81F3BFE0
|
||
|
||
## Browser Findings
|
||
- MDN 将 WebUSB(页面更新 2025-07-12)和 Web Serial(页面更新 2026-05-26)标注为非 Baseline/有限可用,并说明仅安全上下文可用。
|
||
- Chrome 文档说明 Web Serial/WebUSB 的设备选择必须由用户手势触发,且单设备权限由用户显式授予。
|
||
- Chrome Local Network Access 文档(更新说明覆盖至 2025-09-29)显示 Chrome 142 推出访问局域网设备的权限提示;这会影响公网页面直连本地打印机、控制器或网关。
|
||
- Waitwhile API 状态与 webhook 示例显示,成熟排队产品使用明确 Visit 状态、位置/ETA 字段和前后快照事件;其帮助中心将个人状态页面与 TV/Serving Display 拆分配置。
|
||
- 梵净山资料给出了完整现场链路:手机实时队列 → 接近提醒 → 广播/电子屏按号段叫号 → 闸机入场;这是当前最贴近用户需求的国内参考案例。
|
||
- 国际案例中同行组、门票凭证、return window、容量限额、迟到处理和多通道核销是反复出现的成熟模式;应吸收其领域模型,不照搬依赖原生 App 或自有腕带的交互前提。
|
||
- 五家通用厂商的公开资料证明游客状态页、ETA、大屏、短信、硬件代理和审计已成熟,但真正的多人批量叫号与断网自治不能靠营销词推断,均需明确合同/POC。
|
||
|
||
## 实施冻结决策(2026-07-10)
|
||
- 用户已在最新完整摘要后明确回复“确认,可以执行”,需求确认门槛已打开。
|
||
- MVP 采用中心服务唯一写入;完全断网时停止数字化取号/叫号并切换人工预案。
|
||
- 取号为一人一号;同一手机号允许在同一项目持有多个活动号码,员工确认重复提示后继续并留审计。
|
||
- 取号字段为手机号必填、姓氏和称谓选填,称谓默认“游客”,不采集法定性别;大屏只显示票号。
|
||
- 批量叫号为每项目固定 N、严格 FIFO 的连续号码;不足 N 时叫剩余号码,不手选、不跳号。
|
||
- 过号后原号码失效,若继续排队则由员工重新取新号进入队尾。
|
||
- 预计等待时间首期支持固定批次与连续放行两种简单模板,每项目二选一。
|
||
- 认证首期为内置账号密码、RBAC 和项目范围,预留 SSO/OIDC。
|
||
- 技术栈冻结为 React + TypeScript + Vite 前端,Go + GORM + PostgreSQL 后端;核心叫号事务显式使用锁、幂等和约束。
|
||
- 硬件首期只交付统一接口、成功/失败模拟器和测试日志。
|
||
- 留存默认值:个人关联 30 天、原始业务事件 90 天后匿名化、安全日志至少 6 个月、后台审计 1 年、影响评估记录 3 年。
|
||
- 当前本机已发现 Node.js 22.22.3、pnpm 10.33.2、npm 10.9.8;未发现 Go、Docker 或 psql,需要在实现阶段建立可复现运行环境。
|
||
|
||
## Phase 7 实施发现
|
||
- 已安装 Go 1.26.5 与 PostgreSQL 17.10;本地开发数据库使用角色/库 `queue`。
|
||
- 初版迁移从数据库层落实项目级外键、项目/营业日票号唯一、公开 token 哈希唯一、手机号 HMAC 活动索引、审计留存时间、幂等键唯一和设备模拟结果约束。
|
||
- GORM 仅承担模型与常规查询;固定 N 叫号仍需在同一显式事务中锁定 `queue_sessions`、读取 FIFO 票号、创建批次、推进票状态、增加 revision 并写审计/幂等响应。
|
||
- 独立契约审查证明“可编译/可构建”不足以替代端到端响应核验:公示投影必须使用独立白名单 DTO,管理项目行必须返回真实指标,客户端同一提交意图必须复用幂等键。
|
||
- “过号后重新取号”需要一等业务动作而非仅靠普通取号表单:原票与新票应有唯一关联、服务端锁/revision/幂等保护和显式审计。
|
||
- 连接新鲜度必须按最近一次成功请求判断,不能用最后一次业务状态变化时间代替;空闲但健康的队列不会持续产生 `updated_at`。
|
||
- 公示屏的公开 DTO 刻意不暴露内部主键,因此前端列表稳定键应由公开且会话内唯一的批次号/叫号时间组成,不能假定内部 DTO 字段存在。
|
||
- 最终纵向切片已通过真实 PostgreSQL、增强 API 烟测、Go 竞态测试、13 项前端测试、生产构建和四端浏览器验收;当前可作为真实硬件接入与现场试点的开发基线。
|
||
|
||
## Phase 8 变更边界(2026-07-10)
|
||
- 员工端与管理端需要在已登录且通过 `project_id` 授权的上下文中,显示票号、完整手机号、姓氏/称谓和状态之间的对应关系。
|
||
- 游客状态页由高熵私密 token 授权,只增加联系手机号尾四位用于自我核对,不返回完整手机号。
|
||
- 公示屏的公开白名单契约保持不变,任何序列化结果均不得出现 `phone` 字段。
|
||
- “真实测试”定义为:数据写入本机 PostgreSQL,经过正在运行的 Go API 读写,并由 React 页面实际渲染和浏览器操作验证;测试手机号是明确的受控测试值,不使用组件 mock 或静态假响应冒充联调结果。
|
||
- 现有手机号和姓氏已经使用 AES-GCM 加密存储,附加认证数据分别是 `phone:{project_id}` 与 `last_name:{project_id}`;无需也不应新增数据库明文字段。
|
||
- 当前 `ticketView` 是不持有 cipher 的包级函数,且只返回 honorific;内部 DTO 若要返回完整手机号/姓氏,需要改为经过 `Server` 解密的授权投影,解密失败必须让请求失败而不是静默返回错误对应关系。
|
||
- 管理概览路由已有 ADMIN 门槛;员工队列路由已有账号项目授权。新增完整手机号只能落在这两类现有鉴权路由,不能复用到公示 DTO。
|
||
- 当前真实 PostgreSQL 中已有多条 AES-GCM 密文记录:手机号密文 27 字节、nonce 12 字节、HMAC 64 字符,证明页面此前缺少对应关系是读模型/展示问题,不是数据未落库。
|
||
- 员工端需要同时覆盖“等待队列表”和“当前批次卡片”;只在等待表加手机号会导致叫到后立刻失去号码与联系方式对应关系。
|
||
- 管理端目前只有项目汇总,新增活动号码表应限制为 WAITING/CALLED/ARRIVED 等仍需现场处理的状态,避免运营首页默认展开历史个人信息。
|
||
- 后端已将员工票号投影改为经 `Server` cipher 解密的授权 DTO,覆盖等待队列、当前批次、创建、叫号、状态迁移和重新取号响应;任一密文认证失败会让请求失败,不会产生错配的空手机号。
|
||
- 管理端 `active_tickets` 只选择 WAITING/CALLED/ARRIVED,游客响应只增加 `phone_last4`;公示 DTO 仍是独立结构,未复用内部票号视图。
|
||
- 前端员工端同时覆盖队首预览、等待表和当前批次,管理端新增活动号码表;公屏 `BatchCard` 默认 `showContactDetails=false`,只有员工端显式开启。
|
||
- 真实浏览器/实库记录 A0009 验证通过:员工端将 A0009、受控完整手机号与“实测女士”对应;游客私密页只显示尾号 8042;管理端活动号码表显示同一完整对应关系;公屏 DOM 不含完整测试手机号或“手机号”标签。
|
||
- 独立审查发现事务边界细节:状态迁移若在提交后才解密并组装响应,密文损坏会让数据库已变更但客户端收到 500。个人字段授权投影属于事务成功条件,必须在 commit 前构造。
|
||
- 真实烟测不能只验证静态 waiting/admin 投影;创建、叫号/current batch、状态动作和重新取号都各自序列化票号,必须逐路径验证手机号/姓氏连续性,并在结束时清理活动批次以支持重复执行。
|
||
- 最终桌面视觉复核中,员工端把手机号作为队首预览的次级信息且保留固定底部叫号动作;管理端活动号码表在首屏内清晰对应项目、票号、完整手机号、姓氏/称谓、状态和时间,没有挤压原项目总览。
|
||
- 四个新鲜标签页的浏览器控制台均无 error/warn。
|
||
- 390×844 真实员工页面包含 A0009 和完整测试手机号,document scrollWidth 375 小于 innerWidth 390;新增手机号列仍被表格自己的横向滚动容器约束,没有造成整页横向溢出。
|
||
- `go run` 作为后台烟测进程时,父进程退出与编译后二进制释放数据库连接之间存在竞态;临时数据库清理应运行可直接控制 PID 的构建产物,并用 PostgreSQL `dropdb --force` 收口残余连接。
|
||
- 最终 `make smoke-real` 改为构建单一临时 API 二进制;连续两次运行均完成真实迁移/写入/全路径断言,且每次结束后临时数据库计数都回到 0。
|
||
|
||
## Phase 9 尺寸边界(2026-07-10)
|
||
- 员工端与游客端按手机 H5 处理,固定参考宽度为 390px;实际设备视口小于 390px 时必须使用 100% 宽度,不能产生整页横向滚动。
|
||
- “固定尺寸”只固定设计宽度,不固定页面高度;员工表格和长内容仍在页面/局部容器内正常滚动。
|
||
- 管理端和公示屏分别面向桌面运营与远距大屏,不能被手机端 max-width 规则误伤。
|
||
- 当前员工与管理端共用无变体的 `AppShell`,因此不能直接给 `.app-shell` 限宽;需要增加仅 StaffPage 使用的 mobile variant,避免管理端一起变成 390px。
|
||
- 现有员工单列布局主要由 viewport `@media (max-width: 767px)` 触发;固定 390px 容器在桌面 viewport 下仍会命中桌面双列规则,因此 mobile variant 还必须显式覆盖 header、main、staff-layout、project picker 和固定底栏布局。
|
||
- 实现采用 `AppShell variant="mobile"`,只由 StaffPage 启用;选择器以 `.app-shell--mobile ...` 提高作用域,因此后续通用 media query 不会把管理端限宽。
|
||
- 员工固定操作栏使用 `left: 50% + translateX(-50%) + width: min(100%, 390px)` 与手机画布同宽;游客页和登录卡同样收敛到 390px,宽表格仍由 `.table-scroll` 局部滚动。
|
||
- 1280px 桌面窗口实测:员工 shell=390px、底部叫号栏=390px,游客页=390px;管理端和公屏均为 1265px,证明手机规则未污染桌面路由。
|
||
- 桌面截图确认员工 H5 以居中手机画布呈现,header、单列内容和固定叫号栏对齐同一宽度。
|
||
- 390×844 实际视口复验:员工 shell=390px、固定叫号栏=390px、document scrollWidth=390px;游客页=390px、scrollWidth=390px,并继续显示真实尾号 8042。
|
||
- 独立尺寸审查指出 `viewport-fit=cover` 下顶部还需 safe-area inset;固定栏的主内容预留不能小于文本放大后的栏高;登录页父级 16px padding 会让 414px 视口中的 390px 卡片缩水到 382px。
|
||
- 上述三项已修复:员工、游客与登录页覆盖四向安全区;员工主内容和固定栏共用 `180px + safe-bottom` 预留,项目/状态长文本单行省略;登录页用动态左右留白确保 414px 视口中的卡片为 390px。
|
||
- 四档真实浏览器回归通过:员工 shell/底栏在 320、375、390、414px 视口分别为 320、375、390、390px;登录卡同样分别为 320、375、390、390px,均无整页横向溢出。
|
||
- 游客页四档回归均无横向溢出且继续显示真实手机号尾号;1280px 桌面复核中员工/游客保持 390px,管理端/公屏保持约 1265px,四端控制台无 error/warn。
|
||
- 为避免只在空列表上验收,通过真实员工页面向开发 PostgreSQL 创建 A0010:员工端与管理端显示 `A0010 / 13800138042 / 尺寸实测女士`,游客私密页只显示 A0010 与尾号 8042。
|
||
- A0010 存在时的 390px 员工页 document scrollWidth=390px;760px 宽的号码表被 322px 的局部 `.table-scroll` 正确约束,没有把整页撑宽。
|
||
|
||
## Phase 11 全平台功能文案极简化(2026-07-11)
|
||
- 用户要求所有平台删除非必要标题、说明、备注、副标题、设计思考和约束表达,只保留直接完成任务所需的按钮、字段、数据与状态。
|
||
- 采用公共服务产品界面的保守边界:不删除表单标签、表头、按钮名称、票号/手机号/人数/时间、成功/错误反馈、必要空态、隐私最小披露和辅助技术名称。
|
||
- 本轮只改前端内容层级与相应间距,不改变路由、业务接口、权限、字段顺序、状态机或隐私投影。
|
||
- 设计方向读取为:面向现场员工、管理员和游客的高密度公共服务产品界面,低变化、低动效、高信息密度;`DESIGN_VARIANCE=3`、`MOTION_INTENSITY=2`、`VISUAL_DENSITY=8`,沿用现有原生 CSS 设计系统。
|
||
- 初步字符串扫描显示冗余主要集中在 `page-heading` 的 eyebrow+H1+说明三层、panel 的 eyebrow+标题、项目上下文备注、Freshness 常态时间、EmptyState 描述和卡片总结句;按钮、表单标签、表头、票号、手机号和关键状态无需改名。
|
||
- 员工 H5 当前每个场景同时出现顶级场景标题、场景导航、面板标题,语义重复。应保留“叫号/取号/核验”导航与面板内直接操作,删除“员工工作台”eyebrow、顶级 H1 说明和面板 eyebrow。
|
||
- 员工叫号页的“当前叫号/当前批次/队首预览/固定容量/底栏本次将叫”存在多次重复;保留批次本体、等待数、队首号码和唯一底部叫号按钮即可。
|
||
- 法定/隐私留存说明虽然属于必要合规信息,但不必常驻占据主流程;本轮保留字段用途的最小辅助技术描述与错误反馈,删除长留存备注的可见常驻行,不改变数据处理规则。
|
||
- 管理端冗余集中在侧栏三行介绍与隐私注释、各页“eyebrow + H1 + 说明”、运行规则说明和大屏中心底部注释;导航、汇总指标、表单字段、表头、票号与全屏按钮是硬功能,应保留。
|
||
- 游客端可删除品牌副标题、私密链接标签、重复状态徽标、通用 guidance 与“需要帮助”长说明;必须保留项目、文字状态、票号、尾号、预计等待、前方人数、叫号入口/时间、服务端消息和刷新按钮。
|
||
- 公示屏可删除“现场叫号”眉题、重复批次元信息、健康状态下的数据更新时间、设备文案和“以工作人员指引为准”;项目、运行状态、当前票号、最近叫号、等待量、预计等待及异常连接提示必须保留。
|
||
- 登录页只需品牌名、账号、密码、登录按钮和错误反馈;宣传副标题、内部账号 eyebrow、重复登录标题、权限说明与账号约束帮助文字均可删除。
|
||
- 删除可见标题时必须把 `aria-labelledby` 改成稳定 `aria-label` 或保留屏幕阅读器标题;重点包括员工四个区块、BatchCard、Visitor help、Login、Display current 和 Admin 两张表。删除手机号留存提示时必须同步清理 `aria-describedby`,避免悬空引用。
|
||
- 测试应从页标题断言转向硬功能断言:按钮、表单控件、表头、票号、手机号、文字状态、操作结果、离线/错误/空态和隐私不泄露;另加反回归断言确保被点名的解释性文案不再出现。
|
||
- CSS 需要同步收口:员工底栏删去两行状态后,`--staff-primary-bar-reserve` 可由 180px 下调到约 100px;删去页标题后以紧凑工具栏承载项目选择/刷新/全屏,不保留空的 `.page-heading` 间距。
|
||
- 侧栏只剩三项导航后应删除 intro/note 样式并缩窄栏宽与内间距;登录卡删除介绍区后降低纵向 gap;游客帮助区改成单按钮操作区;公示屏删除 footer 后同步调整 grid rows,避免底部空行。
|
||
- 设计技能的营销布局规则不适用于本项目的高密度后台/数据表;本轮只采用复制审计、无障碍、对比度、按钮不换行、主题/颜色/圆角一致性和空/错/加载状态等通用预检项,不引入新设计系统依赖。
|
||
- 页面层精简已落地:员工三场景删除页级标题/说明和面板眉题,底栏只剩主按钮;管理三页删除介绍层与备注;游客删除重复状态/帮助说明;登录只剩品牌与控件;公示屏删除眉题、设备说明与重复元信息。
|
||
- 第一轮字符串复扫仍发现少量需总线收口的内容:游客 `privacy-label`、项目名仍使用 eyebrow 样式、公示屏健康 footer、UI 中的 `—/–` 占位或范围符号,以及员工项目状态被单独包装成一张过重的 context 卡片。
|
||
- 管理端只剩导航后,1023px 媒体规则仍会把单一 nav 放入双列侧栏;需要改为单列。单按钮/单选择器的 `.admin-page-heading` 需要右对齐并缩小底部间距,避免删除标题后留下大片空白。
|
||
- 首个真实浏览器页面确认登录卡只剩品牌、账号、密码和登录按钮,已删除内部账号、登录工作台、宣传说明与帮助备注;访问员工端时未登录会正确回到该精简登录页。
|
||
- 管理员登录实际落到 `/admin`;精简后 DOM 只保留三项导航、刷新按钮、四项汇总、两张业务表及真实 A0010/完整手机号/姓名状态对应,已无页级 eyebrow、H1 说明或侧栏注释。
|
||
- 管理概览截图确认左侧导航已缩为紧凑卡片,刷新按钮右对齐,汇总与表格连续排列;删除标题后没有空白容器、断裂边框或按钮漂浮问题。
|
||
- 员工叫号页真实 DOM 已压缩为项目选择/运行状态、叫号/取号/核验导航、等待数、下一批真实号码及唯一叫号按钮;用户点名的“员工工作台”“当前批次与下一批”“严格按队首自动选号”等说明均不存在。
|
||
- 390×844 实测宽度与固定栏正确:shell=390px、底栏=390px/86px、document scrollWidth=390px,A0010 仍可见且旧说明为零。
|
||
- 视觉截图发现“暂无当前批次”仍继承通用 180px 空态高度,虽然文字已删但留下过量空白;需对叫号面板空态压缩到约 88px 后复验。
|
||
- 叫号空态已压缩并实测为 88px,390px 页面仍无横向溢出。
|
||
- 员工取号页真实 DOM 只保留项目/状态、三任务导航、手机号/姓氏/称谓、创建按钮、等待队列/刷新和业务表;手机号用途、留存说明、可选备注与“代游客创建/实时列表”均已删除,A0010 对应关系未丢失。
|
||
- 390px 取号页截图确认表单直接进入字段/按钮,等待队列紧接其后,无空标题块;宽表仍仅在局部容器内滚动。
|
||
- 核验页空状态只保留项目、任务导航、刷新和“暂无需要核验的批次”,未保留“当前批次/到场与完成核验/叫号后会显示”等说明。
|
||
- 游客 A0010 页只保留品牌、项目、文字状态、票号、尾号 8042、预计等待、前方号码和刷新按钮;“个人状态页/私密链接/需要帮助/通用 guidance”均已删除,完整手机号仍未泄露。
|
||
- 390px 游客截图确认内容在单张票卡内完成,刷新按钮紧随其后,无帮助说明卡、空白页脚或横向溢出。
|
||
- 项目管理页真实 DOM 只剩项目选择器、项目状态/批量数/宽限/预计方式/间隔/缓冲字段和保存按钮;页级标题、说明和“运行规则”说明均不存在。
|
||
- 管理端大屏中心只保留全屏按钮、项目名/状态、当前票号、等待量、预计等待和设备状态;已无“全项目实时监控”说明、公开投影备注或 tile 眉题。
|
||
- 旧公示屏 token 当前返回“尚未绑定项目”,需要从本地种子/配置定位当前可用只读地址后再验公示内容;错误态本身已精简为错误、原因和重连按钮。
|
||
- 使用项目幂等 seed 生成新公示 token 后,真实公示页正常返回;页面只保留项目/时钟/运行状态、当前叫号、最近叫号和队列概况,健康 footer、设备文案和现场说明均已删除。
|
||
- 公示屏桌面截图确认四个硬信息区占满画布且无底部空行;当前新营业日暂无叫号,正确显示“暂无待到场号码/暂无最近叫号/等待 0”。
|
||
- 最终静态扫描中用户点名的旧文案、纸号/广播预案、帮助说明和可见长破折号均为零;所有页面控制台 error/warn 为零。
|
||
- 最终前端基线为 11 个 Vitest 文件、26 项测试;TypeScript、Vite 生产构建和 Go API 健康检查全部通过。
|
||
|
||
## Phase 12 移除核验流程(2026-07-11)
|
||
- 用户确认不需要核验逻辑,并批准推荐方案:员工端只保留叫号/取号;每次叫下一批时自动结束上一批,不再提供到场、完成、过号或重新取号操作。
|
||
- 不能只删除前端入口:当前 Go 事务会在活动批次存在时拒绝再次叫号;必须在同一显式事务内结束上一批与其未结束号码,再锁定 FIFO 下一批。
|
||
- 保留边界:固定 N、严格 FIFO、幂等键、`expected_revision`、项目授权、审计记录、设备模拟和公开隐私投影均不改变。
|
||
- 当前 `callNext` 在 revision 校验后统计项目级 `CALLED` 批次并返回 `ACTIVE_BATCH_EXISTS`;替代实现应在同一事务中锁定所有活动批次,将其仍为 `CALLED/ARRIVED` 的票标为 `COMPLETED`,写入 `completed_at`,再选取本营业日队首 WAITING 号码。
|
||
- 自动轮换只在新批次确实创建成功时提交;若 revision 冲突、队列为空、设备记录或响应投影失败,事务回滚,上一批不能被单独结束。
|
||
- revision 仍只增加 1 次,幂等重放仍在轮换之前返回保存响应;`CALL_NEXT` 审计应补充自动结束的批次/票数,便于追溯系统而非人工完成。
|
||
- 旧状态列和迁移需保留以兼容历史数据,但应移除 HTTP 路由与前端 API 入口,使到场/完成/过号/重新取号在产品运行面不可访问。
|
||
- 代码核查确认:核验能力由两个 Go 路由(状态迁移、重新取号)、React `/staff/verify` 页面及 `BatchCard` 行操作共同暴露;三处必须一起移除,避免残留入口。
|
||
- 当前员工端在存在 `current_batch` 时同时拦截函数和禁用按钮;改造后只按等待人数、项目状态和数据新鲜度决定能否叫下一批。
|
||
- 工具记录:首次追加本节时匹配了错误的标题上下文,补读文件尾部后按现有 Phase 12 段落重新定位。
|
||
# 2026-07-11 新增确认:无批次叫号与账号归属
|
||
|
||
- 后台必须提供账号管理,并能维护每个账号所属项目。
|
||
- 员工叫号包含两个入口:快速叫下一个号;批量叫号可手动输入本次数量。
|
||
- “批次”只可作为后端事务分组实现细节,不再作为用户可见业务概念或编号。
|
||
- 票号按项目、按营业日独立递增,展示固定五位纯数字,从 `00001` 开始,不含 A/B/C/D 等前缀。
|
||
# Phase 17 登录隔离发现(2026-07-11)
|
||
|
||
- 当前 React 只有 `/login`,`LoginPage.destinationFor` 按角色把 `ADMIN` 导向 `/admin`,其他导向 `/staff`。
|
||
- 当前 Go API 只有 `/api/auth/login|me|logout`,全站共用 `SessionCookieName` 一枚 Cookie,员工 H5 与管理 Web 无法在同一浏览器保持独立会话。
|
||
- 员工 API 当前只要登录即可访问,管理员也会被当作员工使用;需要将入口、Cookie 和后端角色校验三层同时隔离。
|
||
# 2026-07-11 维护账号 UI 审计
|
||
|
||
- 截图中“所属项目”直接使用浏览器原生 `fieldset/legend`,在宽屏容器中产生突兀的灰色边框、过多空白与松散纵向排列。
|
||
- 维护页当前是单项即时保存;本次仅调整视觉结构,不改变角色、状态和项目归属的 API 行为。
|
||
- 改造方向:使用无边框语义分组、紧凑的说明文案、自适应项目卡片网格和整卡可点击状态,与现有公共服务导视风格保持一致。
|
||
# 2026-07-11 页头 Logo 审计
|
||
|
||
- `xiaoqikong-logo.jpg` 是 640×640 方形完整品牌图,内含绿色山水图形、“小七孔文旅集团”与英文名,不是可直接作为横向页头图标的素材。
|
||
- 截图中的重复文字由“图片内嵌公司名 + `AppShell` 默认公司名”叠加造成;多段后置 CSS 覆盖还使原有裁切几何失效。
|
||
- 不修改原始品牌资产,通过固定视窗和绝对定位只展示图片上半部的绿色图形,避免各端继续显示内嵌文字。
|
||
# 2026-07-11 管理端列表与账号维护 UI 审计
|
||
|
||
- 项目列表当前使用 5 个弹性列,“操作”列占用宽度后内容仍左对齐,视觉上像表格只使用了左侧区域。
|
||
- 角色字段使用原生 `<select>`,macOS 弹层无法与页面设计系统保持一致,且弹出后遮挡账号状态。
|
||
- 角色仅有“员工 / 管理员”两个互斥值,适合改为带 radio 语义的分段选择;项目权限列表适合使用 `auto-fit + minmax` 充分利用宽屏。
|
||
# 2026-07-11 后台维护草稿与管理员防锁死
|
||
|
||
- 数据库核查确认 `admin` 账号已被即时交互改为 `STAFF`,密码未变;管理端按角色严格拒绝员工账号,因此表现为“账号密码登录不上”。
|
||
- 已将 `admin` 恢复为 `ADMIN`,并用管理端登录端点实测返回 HTTP 200。
|
||
- 项目创建、项目基础信息与运行规则已经使用 form submit 和明确保存按钮;后台唯一的点击即提交维护项是账号维护。
|
||
- 账号维护现在本地组合角色、状态和项目权限草稿,仅在用户点击“保存修改”后调用一次更新 API。
|
||
- 服务端对最后一个启用管理员的降级或停用返回 `409 LAST_ACTIVE_ADMIN`,不再仅依赖前端防误触。
|