Files
zyt/server/DOCTOR_ROSTER_BACKEND.md
T
2026-03-04 15:32:30 +08:00

246 lines
5.4 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.
# 医生排班管理 - 后端实现说明
## 文件结构
```
server/app/
├── adminapi/
│ ├── controller/doctor/
│ │ └── RosterController.php # 排班控制器
│ ├── lists/doctor/
│ │ └── RosterLists.php # 排班列表
│ ├── logic/doctor/
│ │ └── RosterLogic.php # 排班逻辑
│ └── validate/doctor/
│ └── RosterValidate.php # 排班验证器
└── common/
└── model/doctor/
└── Roster.php # 排班模型
```
## 数据库表
表名:`la_doctor_roster`
```sql
CREATE TABLE `la_doctor_roster` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`doctor_id` int(11) NOT NULL COMMENT '医生ID(对应 zyt_admin.id',
`date` date NOT NULL COMMENT '日期',
`period` varchar(20) NOT NULL COMMENT '时段 morning/afternoon',
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1-出诊 2-停诊 3-休息 4-请假',
`quota` int(11) DEFAULT '0' COMMENT '号源数',
`max_patients` int(11) DEFAULT '0' COMMENT '最大接诊数',
`booked_count` int(11) DEFAULT '0' COMMENT '已预约数',
`remark` varchar(500) DEFAULT '',
`create_time` int(11) NOT NULL,
`update_time` int(11) NOT NULL,
`delete_time` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_doctor_date_period` (`doctor_id`,`date`,`period`,`delete_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
```
## API 接口
### 1. 获取排班列表
**URL**: `GET /adminapi/doctor.roster/lists`
**请求参数**:
- `start_date`: 开始日期(必填)
- `end_date`: 结束日期(必填)
- `doctor_id`: 医生ID(可选)
- `period`: 时段(可选,morning/afternoon
- `status`: 状态(可选,1/2/3/4
**返回示例**:
```json
{
"code": 1,
"msg": "success",
"data": {
"lists": [
{
"id": 1,
"doctor_id": 1,
"date": "2026-03-02",
"period": "morning",
"status": 1,
"quota": 20,
"max_patients": 30,
"booked_count": 5,
"remark": "",
"create_time": 1709366400,
"update_time": 1709366400
}
],
"count": 1,
"page_no": 1,
"page_size": 15
}
}
```
### 2. 保存排班
**URL**: `POST /adminapi/doctor.roster/save`
**请求参数**:
```json
{
"id": 1,
"doctor_id": 1,
"date": "2026-03-02",
"period": "morning",
"status": 1,
"quota": 20,
"max_patients": 30,
"remark": ""
}
```
**说明**:
- `id` 存在时为更新,不存在时为新增
- `status`: 1-出诊 2-停诊 3-休息 4-请假
- `period`: morning-上午 afternoon-下午
### 3. 删除排班
**URL**: `POST /adminapi/doctor.roster/delete`
**请求参数**:
```json
{
"id": 1
}
```
### 4. 排班详情
**URL**: `GET /adminapi/doctor.roster/detail`
**请求参数**:
- `id`: 排班ID
### 5. 批量保存排班
**URL**: `POST /adminapi/doctor.roster/batchSave`
**请求参数**:
```json
{
"rosters": [
{
"doctor_id": 1,
"date": "2026-03-02",
"period": "morning",
"status": 1,
"quota": 20,
"max_patients": 30
},
{
"doctor_id": 1,
"date": "2026-03-02",
"period": "afternoon",
"status": 1,
"quota": 20,
"max_patients": 30
}
]
}
```
### 6. 复制排班
**URL**: `POST /adminapi/doctor.roster/copy`
**请求参数**:
```json
{
"source_start_date": "2026-03-02",
"source_end_date": "2026-03-08",
"target_start_date": "2026-03-09",
"doctor_id": 1
}
```
**说明**:
- 将源日期范围的排班复制到目标日期
- `doctor_id` 可选,不传则复制所有医生的排班
## 核心逻辑
### RosterLogic::save()
保存排班逻辑:
1. 检查是否有 `id` 参数
2.`id` 则更新,无 `id` 则新增
3. 自动设置 `create_time``update_time`
### RosterLogic::batchSave()
批量保存逻辑:
1. 开启事务
2. 遍历排班数组
3. 检查是否已存在(根据 doctor_id + date + period
4. 存在则更新,不存在则新增
5. 提交事务
### RosterLogic::copy()
复制排班逻辑:
1. 获取源日期范围的排班数据
2. 计算日期差
3. 为每条排班创建新记录,日期加上日期差
4. 检查目标日期是否已存在排班,避免重复
## 数据验证
### RosterValidate
验证规则:
- `doctor_id`: 必填
- `date`: 必填,日期格式
- `period`: 必填,只能是 morning 或 afternoon
- `status`: 必填,只能是 1/2/3/4
- `quota`: 数字
- `max_patients`: 数字
## 模型特性
### Roster Model
自动属性:
- `status_desc`: 状态描述(出诊/停诊/休息/请假)
- `period_desc`: 时段描述(上午/下午)
- `date_text`: 日期文本
软删除:
- 使用 `delete_time` 字段
- 删除时不会真正删除记录,只是设置删除时间
## 注意事项
1. **唯一索引**: `doctor_id + date + period + delete_time` 确保同一医生同一天同一时段只有一条有效排班
2. **医生数据来源**: 医生数据来自 `zyt_admin` 表,`role_id=1`
3. **时间格式**:
- 数据库存储使用整型时间戳
- 日期字段使用 DATE 类型
4. **事务处理**: 批量操作和复制操作使用事务确保数据一致性
5. **错误处理**: 所有 Logic 方法都有异常捕获,失败时返回 false 并设置错误信息
## 测试建议
1. 测试新增排班
2. 测试更新排班
3. 测试删除排班
4. 测试同一时段重复排班(应该失败)
5. 测试批量保存
6. 测试复制排班
7. 测试日期范围查询