# 景区排队叫号系统:规划与首个可运行纵向切片 ## Goal 在已确认的产品、技术与设计基线上,交付可运行的景区排队叫号系统纵向切片,并以自动化测试验证多项目隔离、幂等叫号与隐私边界。 ## Current Phase Phase 46(单项目大屏支持项目编码路由) ## Phases ### Phase 39: 运营统计经营复盘看板优化 - [x] 扩展运营统计数据接口,支持趋势、项目对比、峰值时段和异常摘要 - [x] 将运营统计页重构为指标层、趋势层、项目对比层和异常下钻层 - [x] 补充筛选、空态、错误态、响应式布局和回归测试 - [x] 完成全量测试、类型检查、生产构建与运行态验收 - **Status:** complete #### Confirmed Decisions | Decision | Result | Why it matters | |---|---|---| | 运营统计看板服务场景 | 经营复盘:按日期/项目查看总量、趋势、效率、异常并支持下钻 | 与实时运营概览分工,避免把历史分析和当前值班监控混在一起 | #### Errors Encountered | Error | Attempt | Resolution | |---|---|---| | 在 `server` 工作目录执行时仍使用了包含 `server/` 前缀的格式化路径 | 1 | 改用 `internal/httpapi/...` 相对路径,后端定向测试通过 | | 历史页面回归测试仍断言旧版“取号人数”卡片 | 1 | 更新测试夹具和断言,覆盖经营复盘、每日趋势和项目对比 | | 看板新增“平均等待”在 KPI 与项目对比中各出现一次,旧测试使用唯一文本查询 | 1 | 改为断言匹配数量大于 0,测试通过 | | 小时统计集成夹具按 UTC 写入,测试错误期望为 9/10 点 | 1 | 结合 Asia/Shanghai 业务时区修正为 17/18 点,并验证取号与叫号分桶分离 | | 并行执行全量前端测试和静态检查时,员工页已有测试偶发超时 | 1 | 单独复跑员工页 8 项通过;随后串行执行 `make test`,15 个文件/53 项测试全部通过 | ### Phase 40: 运营统计看板布局与 UI/UX 收敛 - [x] 依据 UI/UX 规范复核看板层级、信息密度、趋势图可读性和响应式排版 - [x] 删除“需要关注”前端模块及相关引导文案,保留项目下钻能力 - [x] 将看板重排为 KPI、全宽趋势、全宽项目对比、状态与时段节奏四个层级 - [x] 修复项目对比在窄屏下的网格错位、间距和可访问性回归 - [x] 完成前端定向测试、类型检查、构建和工作态验证 - **Status:** complete #### Confirmed Decisions | Decision | Result | Why it matters | |---|---|---| | “需要关注”模块 | 删除前端展示,不再在经营复盘页渲染关注卡片或异常引导语 | 看板回到可验证的经营事实,避免把阈值推断当成首页主结论 | | 看板信息层级 | KPI → 每日趋势 → 项目对比 → 状态/峰值/小时节奏 | 减少并列卡片,先看总体,再定位项目,最后看运营节奏 | | 短日期范围趋势 | 少于 4 个营业日显示日卡片摘要,4 天及以上显示 SVG 折线图 | 避免单点/少点折线造成错误的趋势暗示,同时保留日级数据 | #### Errors Encountered | Error | Attempt | Resolution | |---|---|---| | 当前管理端路由需要管理员会话,无法直接用未认证浏览器做看板截图 | 1 | 不读取或写入密码/运行数据,改用 UI/UX 规范、源码审计、组件回归和运行态健康检查验证 | ### Phase 41: 运营统计页视觉层级与排版精修 - [x] 完成保留式视觉审计,明确筛选区、指标层、内容卡片和响应式的改版边界 - [x] 使用统一指标轨道、视图感知筛选网格和清晰的卡片层级,减少卡片碎片化 - [x] 修复历史页空值文案、小时条文字色和移动端间距等细节问题 - [x] 保留现有数据、路由、下钻、导出和权限契约,补充页面级 UI 回归断言 - [x] 完成定向测试、类型检查、构建和运行态验证 - **Status:** complete #### Confirmed Decisions | Decision | Result | Why it matters | |---|---|---| | 视觉方向 | 保留现有景区绿色品牌和原生 CSS,不引入新组件库、图片或营销型动效 | 管理端优先可信、可读和稳定,不牺牲信息密度换装饰 | | 指标容器 | 五个 KPI 合并为一张指标轨道,桌面用分隔线,移动端按两列自然折行 | 让指标成为一个整体,减少重复白卡和视觉噪音 | | 筛选布局 | 统计页只展示日期、项目和操作;记录页保留状态和关键词字段 | 消除统计页空列与无效留白,保持各视图控件语义一致 | | 动效 | 仅保留现有 hover/focus/press 反馈,不新增滚动或循环动画 | `MOTION_INTENSITY=2`,运营数据页需要稳定扫描和低干扰 | #### Errors Encountered | Error | Attempt | Resolution | |---|---|---| | `design-taste-frontend` 明确不以后台仪表盘为专用范围 | 1 | 采用其保留式重设计、形状一致性、文案自检和交互状态规则;数据图表与响应式细节以 `ui-ux-pro-max` 为主 | ### Phase 42: 运营统计模块标题区呼吸空间优化 - [x] 依据用户截图定位每日趋势、项目对比、状态分布和高峰时段的标题区拥挤问题 - [x] 统一增加卡片内边距、标题与副标题间距、标题区与数据区间距 - [x] 保留项目行、峰值列表、状态列表和趋势数据结构,不改变业务交互 - [x] 补充样式回归检查并完成前端测试、类型检查和构建验证 - **Status:** complete #### Confirmed Decisions | Decision | Result | Why it matters | |---|---|---| | 标题区处理 | 四个模块统一使用宽松的卡片内边距和独立标题区,不分别打补丁 | 保持同一页面的节奏一致,避免每张卡的标题位置不同 | | 内容区分隔 | 标题区下方增加明确留白,数据列表/趋势从标题区之后开始 | 让标题、副标题和数据各自形成可扫描的视觉层级 | | 响应式 | 桌面提升水平留白,移动端保留可用宽度并同步增加垂直间距 | 解决桌面拥挤的同时避免窄屏内容被压缩或横向溢出 | #### Evidence | Source | Finding | |---|---| | 用户提供的运营统计截图 | 每日趋势、项目对比、状态分布和高峰时段的标题/副标题贴近卡片边线,标题区与首个数据区缺少缓冲空间 | ### Phase 38: 后台历史数据管理功能实施 - [x] 实现历史数据后端接口、查询过滤、统计聚合、详情与 CSV 导出 - [x] 接入管理端历史数据入口与排队/叫号/统计三视图 - [x] 补充脱敏、审计、索引和 90 天匿名化策略验证 - [x] 运行 Go/前端测试、类型检查、构建与数据库烟测 - **Status:** complete #### Errors Encountered | Error | Attempt | Resolution | |---|---|---| | PostgreSQL 将匿名化维护条件 `$1 - interval '90 days'` 推断为 interval,导致 `timestamp with time zone <= interval` | 1 | 为参数增加 `::timestamptz` 显式转换,待重新运行真实数据库验证 | | PostgreSQL 历史接口集成夹具使用大写项目编码,触发项目编码校验 | 1 | 将测试夹具项目编码改为小写格式,重新验证通过 | | 直接调用详情 handler 的测试请求未设置 Go 1.22 `PathValue` | 1 | 在测试请求上显式设置 `id` 路径值,重新验证通过 | | 根目录执行 `pnpm typecheck` 找不到 `package.json` | 1 | 按项目脚本约定改用 `make` 或在 `web` 子目录执行,验证通过 | ### Phase 37: 后台历史数据管理功能规划 - [x] 核对现有管理端导航、权限、历史事实表和个人信息清理机制 - [x] 形成历史记录、叫号批次、运营统计、导出和治理边界 - [x] 形成页面、接口、索引、权限、隐私和验收建议 - [x] 确认“90 天后原始业务事件”保留匿名明细与统计、删除个人关联信息 - **Status:** complete #### Risks / Open Decisions | Decision | Current recommendation | Why it matters | |---|---|---| | 90 天后的历史明细 | 已确认:保留匿名明细与长期统计,删除个人关联信息且不可恢复 | 会决定清理任务、查询范围、导出字段和验收标准 | ### Phase 36: 员工端取号同行人数输入修复 - [x] 复现并定位同行人数输入框被 `1` 固定的状态更新原因 - [x] 允许用户正常清空后输入合法人数,同时保留项目人数上下限校验 - [x] 补充输入交互回归测试并完成页面验证 - **Status:** complete #### Errors Encountered | Error | Attempt | Resolution | |---|---|---| | 新增的“先清空再输入”回归断言在旧实现下收到值 `1` 而不是空值 | 1 | 作为缺陷复现基线保留;下一步修改表单草稿类型与 `onChange`,让编辑过程允许短暂空值 | | 代码和测试修复后,自动化直接 `fill("")` 首次仍显示 `1` | 1 | 确认 Vite 已加载新源码;改用用户真实操作的全选 + Backspace 后值稳定为空,再输入 `3` 成功,判定为数字输入框与自动化 `fill` 的行为差异 | ### Phase 35: 员工端队列按 10 个增量展开 - [x] 确认前端与 API 服务已启动并通过健康检查 - [x] 将“查看更多”从一次展开全部改为每次追加 10 个号码 - [x] 保留收起能力,并在项目/场景切换时恢复默认 10 个 - [x] 补充增量展开回归测试并完成全量验证 - **Status:** complete ### Phase 34: 员工端批量叫号按钮与指标分隔优化 - [x] 将两个批量操作统一为浅色风格,并改名为“批量叫号 / 批量叫人” - [x] 补回移动端“下一个号 / 下个号人数”之间的竖向分割线 - [x] 更新员工端回归测试,保持叫号模式、参数与禁用逻辑不变 - [x] 完成类型检查、全量测试、生产构建、真实页面和截图对照验收 - **Status:** complete #### Errors Encountered | Error | Attempt | Resolution | |---|---|---| | 已释放后重新接管的预览标签在 `fullPage` 截图中出现横向压缩,但 DOM 盒模型和普通视口截图均正常 | 1 | 不使用失真的全页图作为证据,改用同一 390×844 标签的普通视口截图并核对实际盒模型尺寸 | | 追加 Phase 34 验收记录时误用了 Phase 33 的二级标题上下文 | 1 | 读取当前计划后改用实际三级标题和更小补丁,未影响业务文件 | ### Phase 33: 项目新建/维护表单结构化 - [x] 将现有字段归纳为“基础信息 / 叫号规则 / 其他规则”三个语义分组 - [x] 优化默认值与单次上限的成对布局,保留现有提交契约 - [x] 确保新建和维护页面共享结构,并补充可访问语义回归测试 - [x] 完成类型检查、前端测试、生产构建与页面验收 - **Status:** complete #### Errors Encountered | Error | Attempt | Resolution | |---|---|---| | 带辅助文案的上限字段使成对输入框基线错位 | 1 | 将分组内 `.field` 设为顶部对齐,1440px 桌面与 390px 窄屏复验均通过 | ### Phase 32: 员工端叫号指标与队列展示优化 - [x] 删除统一叫号模块内部横向分隔线,并统一按号码/按人数按钮颜色 - [x] 将叫号指标调整为下个号人数、剩余未叫号、剩余未叫人数 - [x] 将队列行改为三列均匀对称布局,默认展示 10 个号码并支持展开/收起 - [x] 移除队列内部滚动容器,让展开内容随页面自然延展 - [x] 完成自动化、构建、真实页面和截图对照验收 - **Status:** complete #### Errors Encountered | Error | Attempt | Resolution | |---|---|---| | Product Design 用户上下文预检脚本按插件根目录推断路径时不存在 | 1 | 使用技能目录内实际脚本 `skills/user-context/scripts/user_context_preflight.py` 重新执行,确认无已保存用户上下文 | | 由手机视口切换到桌面视口后直接刷新,应用内预览页重新挂载超时 | 1 | 保留现有浏览器连接,按故障指引新建同浏览器标签后继续桌面验收 | ### Phase 28: 创建项目与项目维护表单统一 - [x] 让创建项目复用项目维护的完整字段与布局 - [x] 保证创建提交的项目配置与页面默认值一致 - [x] 修复 Alpine 运行环境缺少时区数据导致的合法时区校验失败 - [x] 补充前后端回归测试并完成类型检查、构建验证 - **Status:** complete ### Phase 29: 游客手机号运营测试查询 - [x] 新增非生产手机号查询 API,复用手机号 HMAC 索引和游客状态投影 - [x] 支持同一手机号返回多个项目的当前活动排队单,并增加基础限流 - [x] 新增 `/visitor` 游客手机号查询页面,保留原有 `/visitor/:token` 私密状态页 - [x] 补充前后端单元测试、真实 PostgreSQL/API 烟测和构建验证 - **Status:** complete #### Errors Encountered | Error | Attempt | Resolution | |---|---|---| | 前端查询页面测试把同一项目/号码在列表和详情中的重复文本当成唯一元素 | 1 | 将断言改为允许列表与详情卡同时出现 | | 在 `server` 工作目录下使用了带 `server/` 前缀的 gofmt 路径 | 1 | 改用 `internal/httpapi/...` 相对路径后通过 | ### Phase 27: 生产后端与数据库基础交接 - [x] 确认独立 PostgreSQL、Kubernetes 业务服务、全景区上线和 3000 峰值在线用户边界 - [x] 修复真实 PostgreSQL 烟测、管理员/手动叫号/项目筛选契约 - [x] 新增个人数据清理迁移、维护事务、迁移幂等和临时 PostgreSQL 集成测试 - [x] 增加生产配置校验、独立迁移命令和受保护管理员密码轮换命令 - [x] 形成 Redis/Kubernetes/Secret/备份恢复的后端交接说明 - [x] 完成前后端全量测试、构建和最终交接核对 - **Status:** complete ### Phase 26: 员工端末号预计时长与轮询闪屏修复 - [x] 定位员工队列 ETA 数据断点与闪屏触发条件 - [x] 让员工队列返回按项目配置计算的末号预计时长 - [x] 前端消费统一 ETA 并避免首次数据到达时整页重播入场动画 - [x] 补充接口与页面回归测试并完成构建验证 - **Status:** complete ### Phase 25: 大屏全屏纵向布局 - [x] 确认全屏改为时间标题、当前叫号、轮播列表的上下架构 - [x] 将当前叫号改为全宽主信息区 - [x] 将轮播列表移到下方并改名为“最新取号码” - [x] 在列表标题区显示总计等待号数 - [x] 完成回归、类型检查与生产构建 - **Status:** complete ### Phase 24: 大屏顶部信息优化 - [x] 根据截图定位管理端项目全屏大屏组件 - [x] 左上角增加实时日期时间 - [x] 优化项目名称的层级与对齐 - [x] 删除大屏项目状态 - [x] 完成测试、构建与真实页面验证 - **Status:** complete ### Phase 23: 后台维护草稿与管理员防锁死 - [x] 确认 admin 因角色点击即保存被改为 STAFF,恢复 ADMIN 角色与管理端登录 - [x] 将账号角色、启停状态和项目权限合并为本地草稿 - [x] 新增保存修改、放弃修改和未保存状态反馈 - [x] 后端禁止降级或停用最后一个启用的管理员 - [x] 核对其他后台维护表单已使用明确保存操作 - [x] 完成前后端回归、静态检查和构建 - **Status:** complete ### Phase 22: 管理端列表与账号维护布局 - [x] 定位项目列表操作列未靠右对齐、账号角色原生下拉弹层样式失控问题 - [x] 重新分配项目列表列宽和对齐方式 - [x] 将角色改为可访问的分段选择,优化基础设置与项目权限布局 - [x] 完成回归、构建与真实页面验证 - **Status:** complete ### Phase 21: 页头完整 Logo 与去重 - [x] 按用户反馈恢复完整品牌 Logo - [x] 删除无项目场景下右侧重复的品牌名称 - [x] 完成前端回归和构建验证 - **Status:** complete ### Phase 20: 页头 Logo 修正 - [x] 确认方形完整品牌图被当作横向图标展示,导致内嵌文字与页头文字重复 - [x] 将页头图片稳定裁切为纯图形标识,并调整默认系统名称 - [x] 完成自动化与真实页面验证 - **Status:** complete ### Phase 19: 维护账号 UI 优化 - [x] 定位“所属项目”原生 fieldset 在宽屏下边框突兀、留白过大的问题 - [x] 将账号状态与所属项目改为统一的表单分组和项目选择卡 - [x] 补充回归测试并完成类型、构建和页面验证 - **Status:** complete ### Phase 18: 项目管理与项目级规则维护 - [x] 定位现有“项目管理”仅编辑规则、无项目创建/基础信息维护能力的偏差 - [x] 新增项目创建与基础信息维护 API - [x] 将规则配置归入每个项目的维护页,不设独立导航 - [x] 项目表单移除时区字段,票号格式改为仅可选 `00000` - [x] 补齐前后端回归测试并完成构建验证 - **Status:** complete ### Phase 17: 员工 H5 与管理端登录隔离 - [x] 定位共用登录入口、角色分流与单 Cookie 串端根因 - [x] 拆分员工端/管理端登录、当前用户与退出 API - [x] 后端使用独立 Cookie 并严格校验端角色 - [x] 更新前后端回归测试并完成构建验证 - **Status:** complete ### Phase 16: 以员工端新逻辑统一其他端 - [x] 审计后台、大屏、游客端遗留的批次/固定数量/硬编码状态假设 - [x] 统一后台和大屏的当前叫号与号段语义 - [x] 游客端改为真实排队位置与号码语义 - [x] 将后台固定批量改为仅用于预计算法的“预计每次叫号数” - [x] 更新跨端回归测试并完成全量验证 - **Status:** complete ### Phase 15: 游客公屏信息层级与分项目全屏 - [x] 公屏以当前叫号为主信息,后续号码区间与预计时间为次信息 - [x] 等待人数降为辅助信息,删除大屏中心设备状态 - [x] 管理端改为每个项目独立进入全屏展示 - [x] 修正公屏硬编码日期并完成前端回归验证 - **Status:** complete ### Phase 14: 账号/项目归属与无批次叫号改造 - [x] 管理端增加账号及账号所属项目管理 - [x] 员工端支持快速叫下一个号与手动数量批量叫号 - [x] 对外移除批次号概念和批次文案 - [x] 每个项目每天从 `00001` 开始生成纯数字号码 - [x] 更新自动化测试与产品记录 - **Status:** complete ### Phase 1: 需求盘点与案例调研 - [x] 记录用户已给需求与约束 - [x] 调研景区虚拟排队成熟案例 - [x] 调研通用排队产品、批量叫号与硬件集成模式 - [x] 提炼可借鉴能力和不宜照搬之处 - **Status:** complete ### Phase 2: 领域模型与业务规则 - [x] 梳理角色、项目、队列、号码、批次、服务窗口与状态机 - [x] 设计批量叫号、过号、回呼、取消、暂停和闭园规则 - [x] 设计预估等待时间模型及预测区间/降级策略 - [x] 明确手机号、姓氏、性别的隐私与展示规则 - **Status:** complete ### Phase 3: 产品范围与体验规划 - [x] 规划员工 H5、游客 H5、大屏 Web、管理 Web - [x] 定义 MVP、后续版本与明确不做项 - [x] 提供关键流程、页面清单、权限矩阵和验收标准 - **Status:** complete ### Phase 4: 技术与集成规划 - [x] 规划总体架构、实时通信、数据模型与接口边界 - [x] 规划员工端/大屏硬件适配层和设备协议 - [x] 规划可靠性、安全、审计、监控、容量与部署 - **Status:** complete ### Phase 5: 交付与确认门槛 - [x] 形成完整规划文档和决策台账 - [x] 复核来源、假设、风险和待确认问题 - [x] 纳入轻量架构、简单操作、管理端内置看板和多项目边界 - [x] 向用户逐项确认关键决策 - [x] 收到明确“确认,可以执行”或“开始执行”后才进入开发 - **Status:** complete ### Phase 6: UI/UX 设计范式调研与定稿 - [x] 读取 Product Design、taste、UI/UX 设计库与 GSAP 规范 - [x] 调研排队/公共服务/交通导视/大屏的成熟设计模式 - [x] 提炼四端共同品牌骨架与差异化密度/交互原则 - [x] 定义色彩、字体、间距、组件、状态、图表、响应式和无障碍 tokens - [x] 定义 GSAP/CSS 动效边界、时长、降级和禁止模式 - [x] 形成并交叉审查 Design Paradigm 文档 - [x] 将设计关键决策纳入实施前确认门槛 - **Status:** complete ### Phase 7: 首个可运行纵向切片 - [x] 将最终决策同步到产品/设计文档 - [x] 初始化 Git、Go/React 单仓库与可复现开发环境 - [x] 建立 PostgreSQL 版本化迁移、GORM 模型与种子数据 - [x] 实现内置账号登录、RBAC 与 `project_id` 授权 - [x] 实现员工取号、固定 N 连续叫号、过号与审计核心 API - [x] 实现游客私密状态、公示屏公开投影与 SSE/轮询降级 - [x] 实现 React 员工端/游客端/公示屏/管理端基础路由与核心界面 - [x] 实现设备成功/失败模拟器 - [x] 通过 Go、前端与端到端自动化测试并完成浏览器验证 - **Status:** complete ### Phase 8: 真实手机号对应与跨端实库验收 - [x] 员工队列与当前批次返回并展示授权范围内的完整手机号、姓名/称谓对应关系 - [x] 管理端返回并展示各项目活动号码与完整手机号对应关系 - [x] 游客私密状态接口与页面展示联系手机号尾四位 - [x] 公示屏继续保持票号白名单,不返回任何手机号字段 - [x] 用真实 PostgreSQL 写入、真实 Go API、真实 React 页面完成跨端验收,不使用 mock 响应 - [x] 补齐自动化契约、隐私回归、构建与浏览器控制台检查 - **Status:** complete ### Phase 9: 手机端固定 390px 设计宽度 - [x] 员工 H5 使用 390px 固定设计宽度,窄于 390px 时自适应至 100% - [x] 游客 H5 使用同一 390px 设计宽度,保持高度自适应和页面滚动 - [x] 员工固定底部叫号栏与手机画布同宽且居中 - [x] 管理端和公示屏保持桌面/大屏宽度,不受手机端规则影响 - [x] 通过前端测试、生产构建、320/375/390/414px 与桌面浏览器视觉验收 - **Status:** complete ### Phase 10: 管理端与大屏整合、员工 H5 场景化重构 - [x] 确认管理端与大屏归入同一 PC 管理端,大屏保留全屏展示能力 - [x] 确认员工 H5 以“叫号、取号、核验”三个场景组织 - [x] 确认本轮仅重构已有前端能力,不新增账户、审计或真实硬件配置范围 - [x] 重构路由、管理端导航与大屏中心 - [x] 将员工 H5 拆分为场景入口,保留既有写入与隐私边界 - [x] 补齐回归测试并完成桌面与 390px 视觉验收 - **Status:** complete ### Phase 11: 全平台功能文案极简化 - [x] 审计员工、管理、游客、公示屏与登录页全部可见文案 - [x] 删除重复标题、eyebrow、副标题、说明句、帮助备注与设计约束表达 - [x] 保留按钮、字段、关键业务数据、必要状态、反馈、空态与无障碍名称 - [x] 收紧删除文案后遗留的空白和冗余容器 - [x] 更新前端测试并通过类型检查、测试和生产构建 - [x] 使用真实数据完成所有平台浏览器与控制台回归 - **Status:** complete ### Phase 12: 移除核验流程并自动轮换叫号批次 - [x] 删除员工端核验导航、页面和 `/staff/verify` 业务路由(旧地址仅重定向) - [x] 删除员工端到场、完成、过号和重新取号交互 - [x] 调整 Go 叫号事务:新叫号时自动结束上一活动批次及其未结束号码 - [x] 保持固定 N、FIFO、幂等、revision、审计和设备模拟边界 - [x] 更新 API 烟测、Go/React 测试与产品文档 - [x] 使用真实 PostgreSQL 验证连续两次叫号无需人工核验 - [x] 完成员工端真实浏览器、管理/游客/公屏契约回归 - **Status:** complete ### Phase 13: 小七孔品牌化四端重绘 - [x] 完成现有四端、路由、状态与品牌资产审计 - [x] 完成需求确认门槛并记录用户明确执行授权 - [x] 建立可追溯产品契约与三个视觉方向 - [ ] 用户选定确切视觉候选图 - [ ] 提取设计、交互、动效与实施契约 - [ ] 实现员工 H5、游客 H5、PC 管理端与公示大屏 - [ ] 完成自动化、浏览器、响应式、可访问性与视觉 QA - **Status:** in_progress ## Key Questions 1. 取号主体是“一位游客一个号”还是“一个同行团体一个号”? 2. 现场是否允许游客自助取号,还是仅员工代取? 3. “批量叫号”是一次叫多个连续号码、一个团体多成员,还是多窗口并发叫号? 4. 号码迟到、过号、回呼、优先级和跨项目排队的业务规则是什么? 5. 预估时间的承诺口径、刷新频率和误差容忍度是什么? 6. 硬件范围是否包括打印机、功放/语音、LED/电视、扫码器、身份证读卡器等? 7. “看板并入管理端”当前按运营数据看板处理;原需求中的游客公示大屏是否仍保持独立只读页面? ## 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=` 单参数形式,并再次连续运行验证 | | 四个 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 | 删除两个遗留测试属性后类型检查和生产构建通过 | | 本轮首次连接本地浏览器时运行时尚未初始化 | 1 | 按浏览器技能规范初始化运行时后重新连接,未影响代码验证 | | 本轮一次 Go 回归从仓库根目录执行,未找到 `server/go.mod` | 1 | 改在 `server/` 模块目录执行,时区回归测试通过 | | Phase 31 初始化误将既有长期台账当作新文件 | 1 | 立即从 HEAD 精确恢复三份台账,确认无差异后改为只追加本轮记录;业务代码未受影响 | | Phase 31 首次追加台账时误判 `progress.md` 标题 | 1 | 读取真实标题 `# Progress Log` 后改用精确上下文,不重复原失败补丁 | | Phase 31 基线测试命令经 `pnpm` 透传后运行了全部前端测试,暴露 2 个既有游客查询测试失败 | 1 | 不修改无关游客功能;改用 `pnpm exec vitest run src/pages/StaffPage.test.tsx` 精确执行目标测试,并在最终全量验证中单独说明既有失败边界 | | Phase 31 更新验证进度的补丁包含空 hunk | 1 | 删除无效 hunk 并按两个文件的精确上下文重新追加,业务代码与验证结果不受影响 | | 浏览器连接在登录后打印 Statsig 外部初始化超时 | 1 | 页面导航、登录和 DOM 均正常完成;按应用自身控制台与页面状态继续验收,不把浏览器宿主统计请求误判为产品故障 | | 浏览器手动删除通知分成两个步骤后,通知已先达到 5 秒自动消失 | 1 | 该结果先证明自动清理生效;手动路径改为在同一次浏览器调用内触发新通知并立即删除,避免工具往返时间干扰 | ## Phase 30 — 手机号查询后进入独立号码页(2026-07-15) - 将 `/visitor` 收敛为手机号提交页,成功查询后使用 replace 导航到 `/visitor/phone`。 - 新增无输入框的号码状态页,复用游客状态卡片和实时轮询;同手机号多张活动号码仍支持选择。 - 保留“重新查询其他手机号”按钮,不在号码页内嵌手机号输入表单。 - 验证通过:前端 13 个测试文件共 43 项测试、TypeScript 检查、Vite 生产构建和 `git diff --check`。 ## Notes - 所有网络资料保留来源链接和访问时间(2026-07-10)。 - 关键架构决策前重读本计划与 findings.md。 - taste 只用于反模板化与视觉纪律,不直接主导后台仪表盘;GSAP 只用于有明确状态/层级目的的编排。 ### Phase 31: 员工端叫号模块合并、置顶与通知自动消失(2026-07-15) - [x] 审计员工端当前叫号状态、通知、布局和既有未提交改动 - [x] 叫号通知支持手动关闭,并在创建 5 秒后自动消失 - [x] 按号码数量和按人数叫号合并为一个顶部大模块 - [x] 删除两个模式小标题,只保留“按号数/人数叫号”主标题 - [x] 整个叫号模块在员工页滚动时保持置顶 - [x] 补齐定时、手动关闭、文案和滚动布局回归测试 - [x] 通过前端测试、类型检查、生产构建和视觉验收 - **Status:** complete ### Phase 43: 关键接口结构化出入参日志(2026-07-28) - [x] 盘点关键 API、既有访问日志与敏感字段 - [x] 为统一日志中间件补充请求/响应捕获回归测试 - [x] 实现 JSON 出入参、查询参数脱敏与日志大小限制 - [x] 排除流式事件、文件导出和健康检查等不适合记录正文的接口 - [x] 完成 Go 全量测试、静态检查与隐私泄漏扫描 - **Status:** complete #### Errors Encountered | Error | Attempt | Resolution | |---|---:|---| | PowerShell 中复杂 `rg` 正则的双引号终止符与字符类转义失败 | 2 | 拆成单引号、小范围查询后完成敏感字段盘点 | | 新增日志回归首次运行按预期失败:原始路径泄露、无正文、状态码被覆盖、panic 无访问日志 | 1 | 实现模板路径、旁路捕获、首次状态保护并调整中间件顺序,聚焦测试转绿 | | Windows Go 环境关闭 CGO,`go test -race` 无法启动 | 1 | 不重复同一失败;使用全量测试、聚焦并发安全审查、`go vet` 和构建完成本轮验证 | ### Phase 44: 手机号查询重复排队号码修复(2026-07-28) - [x] 构造同项目多活动场次下的确定性回归测试 - [x] 定位重复记录进入查询结果的根因 - [x] 以最小改动收敛手机号查询结果 - [x] 完成后端全量测试、静态检查与构建验证 - [x] 更新故障结论和部署说明 - **Status:** complete #### Confirmed Decisions | Decision | Result | Why it matters | |---|---|---| | 手机号查询的场次口径 | 每个项目只查询 `business_date` 最新的 `RUNNING/PAUSED` 场次 | 与员工队列、公屏快照的当前场次口径一致,排除旧场次残留同号 | | 同手机号多号处理 | 保留当前场次中号码不同的全部活动票 | 继续满足“一人一号、同手机号可持有多个活动号”的既有业务规则 | #### Errors Encountered | Error | Attempt | Resolution | |---|---:|---| | PowerShell 下向 `rg` 传入 Unix 风格 `*_test.go` 路径通配符失败 | 1 | 后续改由 `rg` 自身的 `-g` 过滤文件,不再让 Windows 解析目录通配符 | ### Phase 45: 管理端大屏中心免登录访问(2026-07-31) - [x] 核对 `/admin/display` 前端路由、页面依赖与后端鉴权边界 - [x] 新增仅包含公开大屏字段的免登录接口 - [x] 将 `/admin/display` 切换为无需管理员会话的独立页面 - [x] 补充路由、公开字段白名单与页面回归测试 - [x] 完成前后端测试、类型检查和生产构建验证 - **Status:** complete #### Confirmed Decisions | Decision | Result | Why it matters | |---|---|---| | 管理端总览接口 | `/api/admin/overview` 继续强制管理员登录 | 该接口含活动游客联系方式和后台配置,不能为大屏免登录而整体放开 | | 公开大屏数据 | 新增字段白名单接口,仅返回项目名、公开票号、等待量、预计等待与刷新时间 | 满足多项目大屏展示,同时维持隐私与后台权限边界 | | 前端入口 | `/admin/display` 使用独立公开页面,不挂载管理员鉴权 Provider | 未登录访问不产生登录跳转或无意义的管理员会话探测 | #### Errors Encountered | Error | Attempt | Resolution | |---|---:|---| | 首次组合补丁把内部网络路由误写为 `HandleFunc`,上下文未匹配 | 1 | 读取真实路由片段后按现有 `Handle` 行重新应用,未产生部分代码改动 | | 普通网页读取器因域名安全校验拒绝打开线上 URL | 1 | 改用只读应用内浏览器核对,不绕过安全校验 | | 应用内浏览器两次打开线上 URL 均超时 | 2 | 按有界重试停止继续访问;保留“代码已完成、线上尚未部署验证”的明确边界 | ### Phase 46: 单项目大屏支持项目编码路由(2026-07-31) - [x] 核对现有 `/display/:token` 路由与项目编码规则 - [x] 后端允许用项目编码读取公开单项目快照 - [x] 保留已有公示 Token 路由兼容 - [x] 补充编码规范化、API 路径与回归测试 - [x] 完成全量测试、类型检查和构建验证 - **Status:** complete #### Confirmed Decisions | Decision | Result | Why it matters | |---|---|---| | 单项目 URL | `/display/{项目编码}`,例如 `/display/RAFT` | 无需查找不可恢复的原始公示 Token,路径可直接配置到现场屏幕 | | 大小写 | 项目编码路由大小写不敏感,服务端统一转大写查询 | 降低手工录入错误 | | 兼容策略 | 40–128 位既有 Token 继续按哈希查询 | 不破坏已经部署的单项目公示链接 | #### Errors Encountered | Error | Attempt | Resolution | |---|---:|---| | 新增回归测试在旧实现下找不到 `normalizeDisplayProjectCode` | 1 | 作为项目编码解析缺口的失败基线,随后实现解析函数 | | 解析函数对非法编码返回了规范化文本和 `false`,与失败契约不一致 | 1 | 非法输入统一返回空字符串和 `false`,避免调用方误用无效编码 |