246 lines
5.4 KiB
Markdown
246 lines
5.4 KiB
Markdown
# 医生排班管理 - 后端实现说明
|
||
|
||
## 文件结构
|
||
|
||
```
|
||
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. 测试日期范围查询
|