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

5.4 KiB
Raw Blame History

医生排班管理 - 后端实现说明

文件结构

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

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

返回示例:

{
  "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

请求参数:

{
  "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

请求参数:

{
  "id": 1
}

4. 排班详情

URL: GET /adminapi/doctor.roster/detail

请求参数:

  • id: 排班ID

5. 批量保存排班

URL: POST /adminapi/doctor.roster/batchSave

请求参数:

{
  "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

请求参数:

{
  "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_timeupdate_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. 测试日期范围查询