diff --git a/docs/superpowers/specs/2026-07-12-leave-management-design.md b/docs/superpowers/specs/2026-07-12-leave-management-design.md new file mode 100644 index 0000000..73e9c90 --- /dev/null +++ b/docs/superpowers/specs/2026-07-12-leave-management-design.md @@ -0,0 +1,349 @@ +# 客户经理请假功能 — 设计文档 + +> 日期:2026-07-12 | 状态:已确认 + +## 一、需求概述 + +为政企周报管理系统添加客户经理请假功能。请假可由客户经理自己提交或支局长代为提交,提交即生效(无需审批)。请假期间免填报考核、免催办提醒,AI 周报摘要标注请假信息。 + +## 二、核心决策 + +| 决策项 | 结论 | +|--------|------| +| 粒度 | 按天(start_date ~ end_date) | +| 审批 | 无需审批,提交即生效 | +| 类型 | 年假 / 事假 / 病假 / 调休 / 其他 | +| 权限 | 经理看自己,支局长/领导看全员 | +| 入口 | PC 端仪表盘卡片 + 独立页面 + 移动端首页 + 表单页 | + +## 三、数据模型 + +### 新增表 `leaves` + +```sql +CREATE TABLE leaves ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + manager_id UUID NOT NULL REFERENCES users(id), + leave_type VARCHAR(20) NOT NULL DEFAULT '事假', -- 年假/事假/病假/调休/其他 + start_date DATE NOT NULL, + end_date DATE NOT NULL, + reason VARCHAR(500) DEFAULT '', + submitted_by UUID NOT NULL REFERENCES users(id), -- 提交人(本人或支局长) + created_at TIMESTAMPTZ DEFAULT now(), + updated_at TIMESTAMPTZ DEFAULT now() +); + +CREATE INDEX idx_leaves_manager_id ON leaves(manager_id); +CREATE INDEX idx_leaves_dates ON leaves(start_date, end_date); +``` + +### 设计要点 + +- `start_date <= end_date`,应用层校验 +- 判断"今天是否请假中":`start_date <= today <= end_date` +- 判断"本周是否有请假":`start_date <= sunday AND end_date >= monday` +- 无 edit_log 列(请假记录简单,不追变更历史) + +### SQLAlchemy 模型 + +```python +class Leave(Base): + __tablename__ = "leaves" + id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) + manager_id: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("users.id"), index=True) + leave_type: Mapped[str] = mapped_column(String(20), default="事假") + start_date: Mapped[date] = mapped_column(Date) + end_date: Mapped[date] = mapped_column(Date) + reason: Mapped[str] = mapped_column(String(500), default="") + submitted_by: Mapped[uuid.UUID] = mapped_column(UUID(as_uuid=True), ForeignKey("users.id")) + created_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now()) + updated_at: Mapped[datetime] = mapped_column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) +``` + +## 四、业务逻辑变更 + +### 4.1 填报进度判断 (`get_reporting_progress`) + +**文件:** `backend/app/services/dashboard.py` + +变更点: +1. 查询本周所有请假记录(`start_date <= sunday AND end_date >= monday`) +2. 对每个经理判断今日是否在请假区间内 +3. 新增第四种状态 `on_leave` + +```python +# 新增返回字段 +{ + "manager_id": "uuid", + "has_reported_today": bool, + "completed": bool, + "on_leave": bool, # ← 新增 + "leave_info": { # ← 新增(仅 on_leave=True 时有值) + "leave_type": "事假", + "start_date": "...", + "end_date": "..." + } | null +} +``` + +前端三色状态扩展为四色: + +| 状态 | 条件 | 颜色 | 印章 | +|------|------|------|------| +| `full` | 已填 + 完成 | 绿 (sage) | 满 | +| `catching` | 已填 + 追赶中 | 黄 (gold) | 追 | +| `missing` | 未填 | 红 (vermilion) | 未 | +| `on_leave` | 请假中 | 蓝灰 | 假 | + +### 4.2 催办提醒 (`check_daily_reporting`) + +**文件:** `backend/app/services/scheduler.py` + +变更点: +1. 查询当天请假中的经理(`start_date <= today <= end_date`) +2. 从催办列表中排除这些经理 +3. 汇总消息标注"X人请假,已豁免" + +### 4.3 仪表盘统计卡 + +**文件:** `backend/app/services/dashboard.py` + 前端 `Dashboard.vue` + +新增第五张统计卡「本周请假」: +- 数字:本周请假总人数 +- 数据来源:统计 `start_date <= sunday AND end_date >= monday` 的去重 manager 数 +- 点击跳转 `/leaves` +- 颜色:蓝灰调 + +### 4.4 AI 摘要提示词 + +**文件:** `backend/app/services/ai_summary.py` → `build_summary_prompt()` + +新增一节注入请假数据: + +```markdown +## 本周请假情况 +- 张三 (事假): 2026-07-13 ~ 2026-07-15 (3天) +- 李四 (年假): 2026-07-14 ~ 2026-07-17 (4天) +``` + +效果:LLM 生成的摘要会自然提及"本周张三请事假3天未参与拜访"等信息。 + +## 五、API 设计 + +所有接口挂载在 `/api/leaves`,需登录认证。 + +### 5.1 列表 + +``` +GET /api/leaves?manager_id=xxx&status=active&page=1&page_size=25 +``` + +权限:`director`/`leader` 看全员,`manager` 只返回自己的记录。 +`status` 筛选项:`active`(进行中)/ `upcoming`(未来)/ `past`(已结束)/ 不传全部。 +默认按 `start_date DESC` 排序。 + +### 5.2 新建 + +``` +POST /api/leaves +``` + +```json +{ + "manager_id": "uuid", + "leave_type": "年假", + "start_date": "2026-07-13", + "end_date": "2026-07-15", + "reason": "回老家" +} +``` + +权限:`manager` 只能给自己建(manager_id 必须等于自己),`director` 可以给任何人建。 +校验:`end_date >= start_date`。 + +### 5.3 编辑 + +``` +PUT /api/leaves/{id} +``` + +请求体同新建。权限:`director` 可编辑任意记录,`manager` 仅可编辑自己提交且尚未开始的记录。 + +### 5.4 删除 + +``` +DELETE /api/leaves/{id} +``` + +权限:同编辑。 + +### 5.5 概览(仪表盘用) + +``` +GET /api/leaves/overview?reference_date=2026-07-12 +``` + +```json +{ + "week_start": "2026-07-13", + "week_end": "2026-07-19", + "total_on_leave": 2, + "leave_list": [ + { + "manager_id": "uuid", + "manager_name": "张三", + "leave_type": "事假", + "start_date": "2026-07-13", + "end_date": "2026-07-15", + "days": 3 + } + ] +} +``` + +权限:`director`/`leader` 返回全员请假数据,`manager` 只返回自己。 + +## 六、前端设计 + +### 6.1 PC 端 — 仪表盘卡片 + +**文件:** `frontend/src/views/desktop/Dashboard.vue` + +- 新增第五张统计卡「本周请假」 +- 样式与现有四卡一致(stat-card + stat-glyph + 数字 + 标签) +- 颜色:蓝灰色调(`--slate` 系列 CSS 变量) +- 点击跳转 `/leaves` +- 数据来源:`GET /api/leaves/overview` + +### 6.2 PC 端 — 请假管理页 + +**文件:** 新增 `frontend/src/views/desktop/Leaves.vue` + +**路由:** `/leaves`,DesktopLayout 侧边栏「工作」分组下新增「请假管理」 + +**页面结构:** + +- 顶部汇总栏:按请假类型分组统计条数(年假X / 事假X / 病假X / 调休X / 其他X) +- 筛选栏:按经理筛选(支局长/领导可见)、按状态筛选(进行中 / 即将开始 / 已结束) +- 表格列:姓名 + 类型(彩色标签)+ 日期范围 + 天数 + 原因摘要 + 提交人 + 操作(编辑/删除) +- 进行中的行蓝色左边框高亮 +- 新增/编辑弹窗(el-dialog):选择经理(支局长代填时)、请假类型 chip 按钮组、日期范围选择器、原因 textarea + +**参考文件:** +- 汇总栏样式:参考 `WorkPlans.vue` / `KeyVisits.vue` 的顶部汇总栏 +- 表格模式:参考 `CustomerManage.vue` 的 el-table + 分页 +- 表单弹窗:参考各独立工作页的 CRUD 弹窗 + +### 6.3 PC 端 — 填报进度卡片 + +**文件:** `frontend/src/views/desktop/Dashboard.vue` + +- 请假中的经理卡片:蓝色「假」印章水印 + 灰色进度条 + "请假中"文案 +- 不计入未填报人数统计 + +### 6.4 PC 端 — 侧边栏 + +**文件:** `frontend/src/components/DesktopLayout.vue` + +侧边栏「工作」分组新增: + +``` +工作 + ├─ 工作计划 + ├─ 商机跟单 + ├─ 要客拜访 + └─ 请假管理 ← 新增,📋 icon +``` + +### 6.5 移动端 — 首页入口 + +**文件:** `frontend/src/views/mobile/Home.vue` + +- 在快捷按钮区域(现有「工作计划」「商机跟单」「要客拜访」旁)新增「请假」chip +- 如果当前有进行中的请假,chip 右上角显示蓝色小圆点 +- 点击跳转 `/m/leaves` + +### 6.6 移动端 — 请假列表页 + +**文件:** 新增 `frontend/src/views/mobile/LeavesList.vue` + +**路由:** `/m/leaves` + +- 卡片流式列表(参考 Home.vue 的记录卡片风格) +- 每条记录:类型彩色标签 + 日期范围 + 天数 + 原因 +- 进行中的卡片蓝色左边框 +- 顶部有「新建请假」按钮(ink 风格全宽按钮) + +### 6.7 移动端 — 请假表单页 + +**文件:** 新增 `frontend/src/views/mobile/LeaveForm.vue` + +**路由:** `/m/leave/new` + `/m/leave/:id/edit`(复用同一组件) + +- 沿用现有移动端表单模式(editorial header + 返回按钮 + 中文标题 + 英文副标题 + 金色装饰线) +- 请假类型:chip 按钮组(年假/事假/病假/调休/其他),参考 VisitForm 的拜访方式 chip +- 日期范围:开始日期 → 结束日期 +- 原因:textarea,选填 +- 提交按钮:全宽暗色按钮「提交请假」 +- 编辑模式下额外显示删除按钮(vermilion 描边) + +### 6.8 移动端 — 路由配置 + +**文件:** `frontend/src/router/index.ts` + +新增 3 条移动端路由: + +```typescript +{ path: 'leaves', component: LeavesList }, // /m/leaves +{ path: 'leave/new', component: LeaveForm }, // /m/leave/new +{ path: 'leave/:id/edit', component: LeaveForm }, // /m/leave/:id/edit +``` + +## 七、文件变更清单 + +### 后端新增 + +| 文件 | 说明 | +|------|------| +| `backend/app/models/leave.py` | Leave SQLAlchemy 模型 | +| `backend/app/schemas/leave.py` | Pydantic 请求/响应 schema | +| `backend/app/api/leaves.py` | REST API 路由 | +| `backend/app/services/leaves.py` | 业务逻辑层 | +| `backend/alembic/versions/xxxx_add_leaves_table.py` | 数据库迁移 | + +### 后端修改 + +| 文件 | 改动 | +|------|------| +| `backend/app/services/dashboard.py` | 填报进度 +`on_leave` 状态;统计卡 +请假数 | +| `backend/app/services/scheduler.py` | 催办过滤请假人员 | +| `backend/app/services/ai_summary.py` | `build_summary_prompt` 注入请假数据 | +| `backend/app/models/__init__.py` | 导入 Leave 模型 | +| `backend/app/main.py` | 注册 leaves 路由 + lifespan 自动建表 | + +### 前端新增 + +| 文件 | 说明 | +|------|------| +| `frontend/src/views/desktop/Leaves.vue` | PC 端请假管理页 | +| `frontend/src/views/mobile/LeavesList.vue` | 移动端请假列表页 | +| `frontend/src/views/mobile/LeaveForm.vue` | 移动端请假表单页 | +| `frontend/src/api/leaves.ts` | Axios API 模块 | + +### 前端修改 + +| 文件 | 改动 | +|------|------| +| `frontend/src/views/desktop/Dashboard.vue` | 新增请假统计卡 + 填报进度 on_leave 状态 | +| `frontend/src/components/DesktopLayout.vue` | 侧边栏新增请假管理入口 | +| `frontend/src/router/index.ts` | 新增 /leaves + /m/leaves 等路由 | +| `frontend/src/views/mobile/Home.vue` | 新增请假快捷入口 chip | + +## 八、验证要点 + +1. 经理提交请假后,当天仪表盘填报进度显示蓝「假」状态 +2. 请假中的经理不收到催办提醒 +3. 支局长可代任意经理提交请假 +4. AI 摘要中体现请假信息 +5. 移动端可完成请假提交→列表查看→编辑→删除全流程 +6. 历史周翻看时,请假数据对应当时的日期区间