Files
qiji/docs/superpowers/specs/2026-07-12-leave-management-design.md
T
2026-07-12 12:48:19 +08:00

350 lines
11 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 客户经理请假功能 — 设计文档
> 日期: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. 历史周翻看时,请假数据对应当时的日期区间