23 KiB
23 KiB
景区排队叫号系统:规划与首个可运行纵向切片
Goal
在已确认的产品、技术与设计基线上,交付可运行的景区排队叫号系统纵向切片,并以自动化测试验证多项目隔离、幂等叫号与隐私边界。
Current Phase
Phase 27(生产后端与数据库基础交接)
Phases
Phase 27: 生产后端与数据库基础交接
- 确认独立 PostgreSQL、Kubernetes 业务服务、全景区上线和 3000 峰值在线用户边界
- 修复真实 PostgreSQL 烟测、管理员/手动叫号/项目筛选契约
- 新增个人数据清理迁移、维护事务、迁移幂等和临时 PostgreSQL 集成测试
- 增加生产配置校验、独立迁移命令和受保护管理员密码轮换命令
- 形成 Redis/Kubernetes/Secret/备份恢复的后端交接说明
- 完成前后端全量测试、构建和最终交接核对
- Status: complete
Phase 26: 员工端末号预计时长与轮询闪屏修复
- 定位员工队列 ETA 数据断点与闪屏触发条件
- 让员工队列返回按项目配置计算的末号预计时长
- 前端消费统一 ETA 并避免首次数据到达时整页重播入场动画
- 补充接口与页面回归测试并完成构建验证
- Status: complete
Phase 25: 大屏全屏纵向布局
- 确认全屏改为时间标题、当前叫号、轮播列表的上下架构
- 将当前叫号改为全宽主信息区
- 将轮播列表移到下方并改名为“最新取号码”
- 在列表标题区显示总计等待号数
- 完成回归、类型检查与生产构建
- Status: complete
Phase 24: 大屏顶部信息优化
- 根据截图定位管理端项目全屏大屏组件
- 左上角增加实时日期时间
- 优化项目名称的层级与对齐
- 删除大屏项目状态
- 完成测试、构建与真实页面验证
- Status: complete
Phase 23: 后台维护草稿与管理员防锁死
- 确认 admin 因角色点击即保存被改为 STAFF,恢复 ADMIN 角色与管理端登录
- 将账号角色、启停状态和项目权限合并为本地草稿
- 新增保存修改、放弃修改和未保存状态反馈
- 后端禁止降级或停用最后一个启用的管理员
- 核对其他后台维护表单已使用明确保存操作
- 完成前后端回归、静态检查和构建
- Status: complete
Phase 22: 管理端列表与账号维护布局
- 定位项目列表操作列未靠右对齐、账号角色原生下拉弹层样式失控问题
- 重新分配项目列表列宽和对齐方式
- 将角色改为可访问的分段选择,优化基础设置与项目权限布局
- 完成回归、构建与真实页面验证
- Status: complete
Phase 21: 页头完整 Logo 与去重
- 按用户反馈恢复完整品牌 Logo
- 删除无项目场景下右侧重复的品牌名称
- 完成前端回归和构建验证
- Status: complete
Phase 20: 页头 Logo 修正
- 确认方形完整品牌图被当作横向图标展示,导致内嵌文字与页头文字重复
- 将页头图片稳定裁切为纯图形标识,并调整默认系统名称
- 完成自动化与真实页面验证
- Status: complete
Phase 19: 维护账号 UI 优化
- 定位“所属项目”原生 fieldset 在宽屏下边框突兀、留白过大的问题
- 将账号状态与所属项目改为统一的表单分组和项目选择卡
- 补充回归测试并完成类型、构建和页面验证
- Status: complete
Phase 18: 项目管理与项目级规则维护
- 定位现有“项目管理”仅编辑规则、无项目创建/基础信息维护能力的偏差
- 新增项目创建与基础信息维护 API
- 将规则配置归入每个项目的维护页,不设独立导航
- 项目表单移除时区字段,票号格式改为仅可选
00000 - 补齐前后端回归测试并完成构建验证
- Status: complete
Phase 17: 员工 H5 与管理端登录隔离
- 定位共用登录入口、角色分流与单 Cookie 串端根因
- 拆分员工端/管理端登录、当前用户与退出 API
- 后端使用独立 Cookie 并严格校验端角色
- 更新前后端回归测试并完成构建验证
- Status: complete
Phase 16: 以员工端新逻辑统一其他端
- 审计后台、大屏、游客端遗留的批次/固定数量/硬编码状态假设
- 统一后台和大屏的当前叫号与号段语义
- 游客端改为真实排队位置与号码语义
- 将后台固定批量改为仅用于预计算法的“预计每次叫号数”
- 更新跨端回归测试并完成全量验证
- Status: complete
Phase 15: 游客公屏信息层级与分项目全屏
- 公屏以当前叫号为主信息,后续号码区间与预计时间为次信息
- 等待人数降为辅助信息,删除大屏中心设备状态
- 管理端改为每个项目独立进入全屏展示
- 修正公屏硬编码日期并完成前端回归验证
- Status: complete
Phase 14: 账号/项目归属与无批次叫号改造
- 管理端增加账号及账号所属项目管理
- 员工端支持快速叫下一个号与手动数量批量叫号
- 对外移除批次号概念和批次文案
- 每个项目每天从
00001开始生成纯数字号码 - 更新自动化测试与产品记录
- Status: complete
Phase 1: 需求盘点与案例调研
- 记录用户已给需求与约束
- 调研景区虚拟排队成熟案例
- 调研通用排队产品、批量叫号与硬件集成模式
- 提炼可借鉴能力和不宜照搬之处
- Status: complete
Phase 2: 领域模型与业务规则
- 梳理角色、项目、队列、号码、批次、服务窗口与状态机
- 设计批量叫号、过号、回呼、取消、暂停和闭园规则
- 设计预估等待时间模型及预测区间/降级策略
- 明确手机号、姓氏、性别的隐私与展示规则
- Status: complete
Phase 3: 产品范围与体验规划
- 规划员工 H5、游客 H5、大屏 Web、管理 Web
- 定义 MVP、后续版本与明确不做项
- 提供关键流程、页面清单、权限矩阵和验收标准
- Status: complete
Phase 4: 技术与集成规划
- 规划总体架构、实时通信、数据模型与接口边界
- 规划员工端/大屏硬件适配层和设备协议
- 规划可靠性、安全、审计、监控、容量与部署
- Status: complete
Phase 5: 交付与确认门槛
- 形成完整规划文档和决策台账
- 复核来源、假设、风险和待确认问题
- 纳入轻量架构、简单操作、管理端内置看板和多项目边界
- 向用户逐项确认关键决策
- 收到明确“确认,可以执行”或“开始执行”后才进入开发
- Status: complete
Phase 6: UI/UX 设计范式调研与定稿
- 读取 Product Design、taste、UI/UX 设计库与 GSAP 规范
- 调研排队/公共服务/交通导视/大屏的成熟设计模式
- 提炼四端共同品牌骨架与差异化密度/交互原则
- 定义色彩、字体、间距、组件、状态、图表、响应式和无障碍 tokens
- 定义 GSAP/CSS 动效边界、时长、降级和禁止模式
- 形成并交叉审查 Design Paradigm 文档
- 将设计关键决策纳入实施前确认门槛
- Status: complete
Phase 7: 首个可运行纵向切片
- 将最终决策同步到产品/设计文档
- 初始化 Git、Go/React 单仓库与可复现开发环境
- 建立 PostgreSQL 版本化迁移、GORM 模型与种子数据
- 实现内置账号登录、RBAC 与
project_id授权 - 实现员工取号、固定 N 连续叫号、过号与审计核心 API
- 实现游客私密状态、公示屏公开投影与 SSE/轮询降级
- 实现 React 员工端/游客端/公示屏/管理端基础路由与核心界面
- 实现设备成功/失败模拟器
- 通过 Go、前端与端到端自动化测试并完成浏览器验证
- Status: complete
Phase 8: 真实手机号对应与跨端实库验收
- 员工队列与当前批次返回并展示授权范围内的完整手机号、姓名/称谓对应关系
- 管理端返回并展示各项目活动号码与完整手机号对应关系
- 游客私密状态接口与页面展示联系手机号尾四位
- 公示屏继续保持票号白名单,不返回任何手机号字段
- 用真实 PostgreSQL 写入、真实 Go API、真实 React 页面完成跨端验收,不使用 mock 响应
- 补齐自动化契约、隐私回归、构建与浏览器控制台检查
- Status: complete
Phase 9: 手机端固定 390px 设计宽度
- 员工 H5 使用 390px 固定设计宽度,窄于 390px 时自适应至 100%
- 游客 H5 使用同一 390px 设计宽度,保持高度自适应和页面滚动
- 员工固定底部叫号栏与手机画布同宽且居中
- 管理端和公示屏保持桌面/大屏宽度,不受手机端规则影响
- 通过前端测试、生产构建、320/375/390/414px 与桌面浏览器视觉验收
- Status: complete
Phase 10: 管理端与大屏整合、员工 H5 场景化重构
- 确认管理端与大屏归入同一 PC 管理端,大屏保留全屏展示能力
- 确认员工 H5 以“叫号、取号、核验”三个场景组织
- 确认本轮仅重构已有前端能力,不新增账户、审计或真实硬件配置范围
- 重构路由、管理端导航与大屏中心
- 将员工 H5 拆分为场景入口,保留既有写入与隐私边界
- 补齐回归测试并完成桌面与 390px 视觉验收
- Status: complete
Phase 11: 全平台功能文案极简化
- 审计员工、管理、游客、公示屏与登录页全部可见文案
- 删除重复标题、eyebrow、副标题、说明句、帮助备注与设计约束表达
- 保留按钮、字段、关键业务数据、必要状态、反馈、空态与无障碍名称
- 收紧删除文案后遗留的空白和冗余容器
- 更新前端测试并通过类型检查、测试和生产构建
- 使用真实数据完成所有平台浏览器与控制台回归
- Status: complete
Phase 12: 移除核验流程并自动轮换叫号批次
- 删除员工端核验导航、页面和
/staff/verify业务路由(旧地址仅重定向) - 删除员工端到场、完成、过号和重新取号交互
- 调整 Go 叫号事务:新叫号时自动结束上一活动批次及其未结束号码
- 保持固定 N、FIFO、幂等、revision、审计和设备模拟边界
- 更新 API 烟测、Go/React 测试与产品文档
- 使用真实 PostgreSQL 验证连续两次叫号无需人工核验
- 完成员工端真实浏览器、管理/游客/公屏契约回归
- Status: complete
Phase 13: 小七孔品牌化四端重绘
- 完成现有四端、路由、状态与品牌资产审计
- 完成需求确认门槛并记录用户明确执行授权
- 建立可追溯产品契约与三个视觉方向
- 用户选定确切视觉候选图
- 提取设计、交互、动效与实施契约
- 实现员工 H5、游客 H5、PC 管理端与公示大屏
- 完成自动化、浏览器、响应式、可访问性与视觉 QA
- Status: in_progress
Key Questions
- 取号主体是“一位游客一个号”还是“一个同行团体一个号”?
- 现场是否允许游客自助取号,还是仅员工代取?
- “批量叫号”是一次叫多个连续号码、一个团体多成员,还是多窗口并发叫号?
- 号码迟到、过号、回呼、优先级和跨项目排队的业务规则是什么?
- 预估时间的承诺口径、刷新频率和误差容忍度是什么?
- 硬件范围是否包括打印机、功放/语音、LED/电视、扫码器、身份证读卡器等?
- “看板并入管理端”当前按运营数据看板处理;原需求中的游客公示大屏是否仍保持独立只读页面?
Decisions Made
| Decision | Rationale |
|---|---|
| 规划阶段先不实现产品代码 | 用户当时要求“形成完整的规划我们再动手”;现已完成确认门槛并收到执行授权 |
| 将事实、行业惯例与建议方案分开标注 | 避免把厂商营销材料误当成已验证结论 |
| 实现前启用需求确认门槛 | 该系统涉及现场运营、隐私、硬件与实时一致性,关键歧义会改变架构 |
| MVP 采用一个模块化单体应用 + PostgreSQL + 内置 SSE/轮询 + 同库待发送记录 | 保留队列事务正确性,同时按用户要求减少部署单元;本地设备网关只在真实硬件需要时增加 |
| 大屏/广播默认只使用每日可读票号,私密查询使用高熵 token | 合规研究表明三项身份字段公开的必要性不足;公开票号也不能成为个人详情查询凭证 |
| 设计语言优先“可信、清晰、耐候、低焦虑” | 四端属于公共服务与现场运营系统,强光、远距、弱网、高压操作和无障碍约束高于潮流风格 |
| MVP 保持轻量模块化单体,拒绝微服务/工作流引擎/复杂规则 DSL | 用户明确要求操作简单、逻辑不过度复杂、系统不笨重 |
| 运营数据看板并入管理端 | 复用管理端账号、权限、项目筛选和部署,不增加独立系统 |
一个系统支持多个项目,以 project_id 隔离 |
每个项目独立队列、规则、号段、设备、员工授权和统计,但不为每个项目重复部署 |
| 用户界面写“预计等待时间/预计叫号时间”,不写 ETA | 避免让游客和一线员工理解英文缩写 |
| 员工端与管理端看板必须账号登录 | 所有内部操作和数据看板均按账号、角色、项目范围授权;游客状态页与公示屏保持受控无账号访问 |
| 中心服务是 MVP 唯一写入权威 | 完全断网时停止数字化取号/叫号并切换人工预案,不建设边缘写入节点 |
| 一人一号;同手机号可持有多个活动号 | 支持儿童、老人和同行家人共用联系人手机号;重复取号必须提示并审计 |
| 批量叫号固定为队首连续 N 个号码 | 每项目配置 N,严格 FIFO;不足 N 时叫出全部剩余号码,不手选、不跳号 |
| 过号后重新取新号排到队尾 | 原号码失效但保留审计,避免旧号码重新插入打乱连续号段 |
| 手机号必填、姓氏/称谓选填且不收集法定性别 | 满足联系与查重,同时按最小必要原则降低个人信息风险;大屏只显示票号 |
| 首期同时支持固定批次与连续放行预计时间模板 | 每个项目二选一配置,仍不建设通用公式或预测平台 |
| 内置账号密码 + RBAC + 项目范围 | 先形成独立闭环,预留未来 SSO/OIDC 扩展边界 |
| 前端 React,后端 Go + GORM + PostgreSQL | 用户明确指定;核心叫号仍使用显式事务、行锁、幂等与数据库约束 |
| 首期硬件只做统一接口与成功/失败模拟器 | 真实设备待型号、协议、网络和回执能力确认后单独接入 |
| 采用已确认的分层留存策略 | 个人关联 30 天、业务事件 90 天后匿名化、安全日志至少 6 个月、后台审计 1 年 |
| 内部授权页面显示完整手机号,游客私密页只显示尾四位 | 用户要求号码与手机号能够对应;员工/管理员受账号和项目范围保护,游客链接仅提供本人核对所需的最少信息,公屏仍不含个人信息 |
| 员工 H5 与游客 H5 采用 390px 设计宽度 | 用户要求固定手机端尺寸;390px 是当前验收设备宽度,窄屏仍降为 100%,高度不锁死以避免内容截断 |
Errors Encountered
| Error | Attempt | Resolution |
|---|---|---|
| 维护账号 UI 新增测试使用了截图中的项目名,与测试夹具不一致 | 1 | 按测试夹具的真实项目名“东门观光车”修正断言 |
| 真实页面全页截图超时 | 1 | 不重复截图,改用 DOM 实际尺寸、计算样式、溢出检查和控制台日志完成验收 |
真实账号页验收脚本在 Node 上下文误用页面 location |
1 | 改用明确的 localhost 基础地址拼接维护页路径 |
账号草稿 dirty 判断使用 Boolean(user) 后 TypeScript 未收窄类型 |
1 | 改为 user ? ... : false 显式条件表达式 |
新增 Go 测试误用了旧模块路径 queue-system/internal/model |
1 | 按 go.mod 修正为 calllinesystem/server/internal/model |
Phase 17 首次 Go 构建缺少 server.go 的 model import;同一命令从 server/ 误读 web/src/api.ts |
1 | 补入 import,前端文件改从仓库根目录读取后继续验证 |
| 仓库当前为空,未发现现有项目资料 | 1 | 按绿地项目开展调研,并把待确认项显式记录 |
| 一次组合补丁因目标上下文已变化而未应用 | 1 | 重新读取精确片段,拆分为更小补丁后成功应用;未丢失内容 |
git status 无法执行:目录不是 Git 仓库 |
1 | 以文件清单和内容检查完成交付核验;不初始化仓库,以免扩大用户未授权范围 |
| in-app Browser 打开 Waitwhile 视觉参考连续超时 | 2 | 停止重复同一失败;改用已核验的官方帮助文档、其他官方设计系统资料与并行调研,不把未看到的截图当事实 |
| 组合补丁上下文与文件原文不一致 | 3 | 重新读取精确段落并拆成小补丁成功修改;未影响最终文档 |
| 轻量化改写 ETA 大段补丁因来源 URL 上下文录入不一致未应用 | 1 | 不重复大补丁;改为读取精确段落并按小节拆分修改 |
后端草稿 .env.example 的两把示例密钥解码为 34 字节,与 32 字节校验冲突 |
1 | 已通知后端工作流修正示例并补配置长度测试;本地运行使用新生成的 32 字节密钥 |
前端草稿 DTO 残留 party_size、组数/人数语义且未发送幂等键 |
1 | 已通知前端工作流改为一人一号/号码数,并为取号与叫号补 Idempotency-Key 和 expected_revision |
前端开发代理指向 :3000,与 Go API :8080 不一致,并生成了不应提交的 TypeScript 构建产物 |
1 | 已通知前端工作流改为 :8080 并清理/忽略 vite.config.js、声明文件和 *.tsbuildinfo |
后端 projectsForUser 将切片与 Find 写在同一 return 表达式,可能先复制空切片 |
1 | 已通知后端拆成显式查询与 return,并巡视同类 GORM 返回写法;同时对齐 display_name DTO |
Go API 草稿未校验 expected_revision、未阻止并行活动批次,且多处 DTO 字段与 React 不一致 |
1 | 已列出 P1 修正清单:revision 冲突、活动批次门槛、项目/队列/票号/批次/设备响应别名与私密链接位置 |
| React 项目切换时短暂保留旧队列,且重复手机号冲突没有明确二次确认流程 | 1 | 已分派前端修复:resourceKey 变化清空旧数据/取消旧请求,解析错误码并以第二次明确点击发送 allow_duplicate=true |
重复执行种子命令时 GORM FirstOrCreate 因预置主键未命中已有队列并触发唯一键冲突 |
1 | 改为按 project_id + business_date 显式查询,仅在 record not found 时创建,随后重跑真实数据库验证 |
| 独立审查发现公示 DTO 复用内部票字段、缺少可追溯重发新号、管理项目行零值、客户端重试未复用幂等键 | 1 | 已分别分派 Go/React 修复:公开白名单 DTO、唯一 reissue 关系/接口、真实项目投影、按提交意图复用幂等键 |
组合补丁因 progress.md 的章节顺序与预期不一致而未应用 |
1 | 通过 rg 获取精确行号,拆分为按文件小补丁后继续;没有代码丢失 |
| 公屏按业务记录更新时间判断连接新鲜度,空闲队列被误报为延迟 | 1 | 改为使用最近一次成功轮询时间;游客页和管理概览同步统一此口径 |
| 公屏最近批次没有公开内部批次 ID,React 产生列表键告警 | 1 | 使用批次号与叫号时间构造稳定公开键,并新增组件回归测试;浏览器控制台复验为零告警 |
queue 开发角色无 PostgreSQL CREATEDB 权限,无法创建隔离烟测数据库 |
1 | 不扩大应用角色权限;改由本机数据库所有者创建并把测试库 owner 指定为 queue |
| 独立审查发现状态迁移在事务提交后才解密手机号响应,坏密文会造成“已提交却返回 500” | 1 | 将授权 DTO 解密/组装移入事务,失败即整体回滚,并补回归测试 |
第二次 smoke-real 随机 display token 以 - 开头,被 argparse 当成选项 |
1 | 将参数改为 --display-token=<value> 单参数形式,并再次连续运行验证 |
| 四个 in-app Browser 标签并行 reload 时 webview attach 超时 | 1 | 不重复并行方案;读取浏览器故障指引后改为逐标签验证,避免多个可见页面同时争用 webview |
smoke-real 关闭 go run 后数据库连接释放稍晚,临时 smoke 数据库未被删除 |
1 | 改为先构建并运行单一临时 API 二进制,cleanup 使用 dropdb --force,并清理全部遗留测试库后复跑 |
| 浏览器 viewport reset 后旧 deliverable tab 句柄失效,首次 finalize 报 unknown tab | 1 | 不复用失效句柄;在现有 browser binding 中重新创建四个最终页面后一次性 finalize |
| 在创建新标签前设置 390×844 viewport 未传播到新标签,仍为 1280×720 | 1 | 标签创建后再次对当前浏览器设置 viewport,再在同一标签复验实际尺寸 |
| 固定宽度独立审查发现顶部安全区、底栏动态高度预留和 414px 登录卡宽度缺口 | 1 | 增加 safe-area top/左右规则、统一并扩大底栏 reserve 且限制文案单行、重算 auth-page 横向留白 |
内置浏览器技能缓存从 26.707.31428 切换,旧 SKILL.md 路径不存在 |
1 | 使用 rg --files 定位当前 26.707.41301 版本后继续,未重复访问失效路径 |
登录按钮点击后等待精确 /staff URL 超时 |
1 | 不重复点击;先读取新 DOM/当前 URL 判断是否已登录或发生角色重定向,再按实际页面继续 |
| 项目管理页截图 CDP 超时 | 1 | 不重复同一截图;已用完整可访问 DOM 验证选择器、六个设置字段和保存按钮,继续下一页面 |
zsh 展开不存在的根级 .env* 导致 token 搜索命令失败 |
1 | 移除未引用的 glob,改为只搜索已存在的 README/scripts/server/web 路径 |
首次从 server/ 目录运行 gofmt 时仍使用 server/... 相对路径 |
1 | 改用 internal/httpapi/... 后 Go 全量测试通过 |
| Phase 12 首次追加 findings/progress 时补丁标题或空 hunk 不匹配 | 2 | 读取文件尾部后按现有章节精确追加;代码未受影响 |
前端生产构建发现 BatchCard 测试仍传入已删除的 readOnly 属性 |
1 | 删除两个遗留测试属性后类型检查和生产构建通过 |
Notes
- 所有网络资料保留来源链接和访问时间(2026-07-10)。
- 关键架构决策前重读本计划与 findings.md。
- taste 只用于反模板化与视觉纪律,不直接主导后台仪表盘;GSAP 只用于有明确状态/层级目的的编排。