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