8.9 KiB
值班排班(日历 + 公开链接抢班)— 设计文档
日期: 2026-08-14
状态: 待实现
仓库: shanxia2.0(backend/+web-admin/)
方案: 方案 1 —「日排班 + 班次名额 + 公开 Token 链接」
UI 原型:docs/demos/duty-schedule-v1-demo.html(管理端)、docs/demos/duty-h5-grab-demo.html(公开 H5)
权威对照: Fresh Mint(docs/web-admin-ui-spec-fresh-mint.md)、公开页可参考运输计划司机免登录(/#/public/pl/transport/{token})
背景
总经理需要按日历安排值班(早班 / 晚班 / 值班等),可设定各班次人数,并可直接指定系统用户;同时生成按日的公开链接,员工免登录填写姓名抢班,满员不可再抢。总经理在日历中可查看历史排班。
参考截图(仅视觉参考):值班系统截图/。第一版不做统计页。
已确认决策
| # | 决策 |
|---|---|
| D1 | 管理端在 web-admin 排班;员工通过 公开 H5 链接抢班 |
| D2 | 一天一个链接(如「8 月 20 日值班」),每次配置某日即对应一条 token 链接 |
| D3 | H5 上将当日多个班次独立罗列,不做筛选,方便直接抢 |
| D4 | 抢班只填姓名;同名不拦截,靠总经理事后核对 |
| D5 | 总经理「直接安排」从系统用户选择 |
| D6 | 员工不能自己取消;总经理可删人、改名额/班次、关链接 |
| D7 | 有人报名后总经理仍可改(不整日锁定) |
| D8 | V1 只要日历 + 历史排班;统计页以后再说 |
| D9 | 班次类型系统预置(早班 / 晚班 / 值班),暂不可自定义 |
| D10 | 只能按天建:点日历某日 → 配置 → 生成该日链接(不做批量日期范围) |
| D11 | 同一天同一人可以占多个班次(早班 + 晚班互不影响) |
| D12 | 关链后重开仍用原 token(V1 不做「重置链接」) |
| D13 | 将 capacity 调到小于当前报名人数时禁止保存,须先删人 |
| D14 | 过往日期仍允许总经理修改(不做历史冻结) |
| D15 | 权限按菜单权限控制,不单独硬编码「总经理」角色名 |
方案选择
采用方案 1(已确认):duty_day + duty_slot + duty_assignment,公开 token 对齐现有免登录链接模式。
未采用:扁平日历事件(名额与关链难控);纯列表无月历(不符合「按日历排班/看历史」)。
架构与边界
| 端 | 职责 |
|---|---|
| web-admin | 月历、按日配置、指定用户、复制/关闭链接、删人改班、历史翻月 |
公开页(web-admin #/public/...) |
token 打开当日抢班页;免登录;只填姓名提交 |
| backend | 租户隔离管理 API + 公开抢班 API;名额并发控制;路径加入加密排除列表 |
公开页落地建议:与司机免登录一致,挂在 web-admin hash 路由,例如 /#/public/duty/{token};链接 Origin 使用现有 PUBLIC_WEB_ORIGIN(或等价配置)拼接。
duty_day (一天 = 一个 access_token)
└── duty_slot × N(morning / evening / duty,各有 capacity)
└── duty_assignment × M(source = assign | grab)
数据模型
表名前缀建议 duty_;均含门户公共字段(id, tenant_no, order_num, remark, create_by, create_dept_id, create_time, update_by, update_time, del_flag)。字段顺序:id → 业务字段 → 公共字段。软删。
duty_day(值班日)
| 字段 | 说明 |
|---|---|
duty_date |
值班日期;同一 tenant_no 下唯一(未删除) |
access_token |
公开访问令牌;足够长、不可猜;租户内唯一 |
link_status |
open / closed |
duty_slot(班次名额)
| 字段 | 说明 |
|---|---|
duty_day_id |
所属值班日 |
shift_type |
预置:morning(早班)/ evening(晚班)/ duty(值班) |
capacity |
名额,≥ 1 |
约束:同一 duty_day_id + shift_type 唯一(未删除)。
duty_assignment(占位)
| 字段 | 说明 |
|---|---|
duty_slot_id |
所属班次 |
source |
assign(管理端指定)/ grab(H5 抢班) |
user_id |
指定时必填;抢班为空 |
person_name |
展示名(用户姓名或手填姓名) |
满员规则:该 slot 下未删除 assignment 数 < capacity 才可新增。
SQL 变更须同步维护 docs/sql/(与 database-conventions 一致)。
Web 管理端
入口与权限
- 新菜单「值班排班」(具体挂载位置实现时定),按钮级权限可拆:查看 / 编辑 / 关链(最小也可合并为菜单权限,能进即可改)。
- UI:Fresh Mint;主色
#10b981;label-position="top";弹窗无背景模糊。 - 模式:月历主视图;不做统计页(D8)。
月历
- 月切换 +「今天」。
- 日格摘要:班次 chip(类型 + 人名或
已占/名额);未配置显示未排班。 - 点击日期 → 配置弹窗(与 Demo 一致)。
配置某日
- 配置预置班次及
capacity(可只启用部分班次)。 - 从系统用户选择直接安排 →
source=assign,写入user_id+person_name;指定人数不得超过该班次剩余名额。 - 列表展示已报名,区分指定 / 抢班;支持删除 assignment。
- 复制链接:
{PUBLIC_WEB_ORIGIN}/#/public/duty/{access_token}。 - 关闭 / 打开链接:改
link_status;关链后 H5 展示关闭态;日历仍可见数据。 - 缩容校验(D13):
capacity不得小于当前有效报名数。 - 去掉某班次(不再启用):若该 slot 仍有有效报名,禁止删除/停用,须先清空报名。
- 首次保存某日:创建
duty_day+ slots,生成access_token;再次保存更新 slots/安排,token 不变(D12)。
历史
- 翻月查看过往排班;过往日仍可编辑(D14)。
公开 H5
对齐原型 docs/demos/duty-h5-grab-demo.html;视觉用三墙 Token(#0a9f6d),与管理端色值不混用。
状态
| 状态 | 表现 |
|---|---|
| 可抢 | 班次卡片独立罗列;可填姓名提交;满员卡片禁用 |
| 提交成功 | 展示日期 / 班次 / 姓名摘要 |
| 链接关闭 | 「报名已关闭」 |
| token 无效 | 「链接无效或已失效」 |
规则
- 免登录;只填姓名(D4)。
- 不可自助取消(D6)。
- 同天可抢多个班次(D11)。
- 展示已报名姓名列表(便于员工感知剩余名额;同名风险已知晓)。
API
管理端(登录 + 租户 + 数据权限按现有约定)
| 能力 | 说明 |
|---|---|
| 月历查询 | 按年月返回每日摘要(slots + assignments 精简) |
| 日详情 | 含链接状态、token/完整 URL、slots、assignments |
| 保存日配置 | 创建或更新 day/slots;校验缩容;可选写入 assign |
| 删除 assignment | 释放名额 |
| 开关链接 | open / closed |
用户选择器复用现有系统用户列表接口。
公开(免登录)
| 接口 | 说明 |
|---|---|
GET /api/public/duty/{token} |
当日只读:日期、状态、各 slot 与已报名姓名 |
POST /api/public/duty/{token}/grab |
body: { shiftType, personName };personName 去首尾空格后非空且长度受限(建议 ≤20);校验开链与名额 |
须:
- 注册路由于
app/api/__init__.py与app/main.py。 - 公开路径加入
API_ENCRYPT_EXCLUDE_PATHS(及前端等价排除,若有)。 - 抢班在事务内检查人数后再插入,防止超卖。
- 错误:满员 / 已关闭 / token 无效 — 明确文案。
- V1:按 IP 或 token 做基础限流(实现时可用现有中间件或轻量计数)。
公开响应不返回其他日期或其他租户数据。
错误处理
| 场景 | 行为 |
|---|---|
| 抢班时刚好满员 | 返回失败,H5 提示名额已满并刷新人数 |
| 关链后提交 | 拒绝,展示关闭态 |
| 管理端缩容过大 | 保存失败,提示先删除多余人员 |
| 删除不存在的 assignment | 幂等或明确 404 |
测试要点(验收)
- 按日配置早/晚/值班名额并复制链接,H5 可打开且班次独立展示。
- 指定系统用户占名额;H5 抢班占名额;满员后不可再抢。
- 关链后 H5 不可抢;打开后可继续抢(同 token)。
- 管理端删人后名额释放;缩容小于当前人数被拒。
- 同姓名可重复报名;同人同日可抢多个班次。
- 翻月可看历史排班。
- 租户隔离:A 租户链接不可看到 B 租户数据。
明确不做(V1)
- 统计页 / 按人汇总卡片
- 批量按日期范围建排班
- 自定义班次类型
- H5 登录、手机号、验证码
- 员工自助取消
- 重置 token
- 历史日期自动冻结
原型索引
- 管理端月历 + 配置:
docs/demos/duty-schedule-v1-demo.html - 公开 H5 多状态:
docs/demos/duty-h5-grab-demo.html