目录
- 1. 前言
- 2. 数据库设计:库存模型
- 3. 后端逻辑:批量生成算法
- 4. 页面搭建:排班管理台
- 4.1 列表展示区
- 4.2 批量排班弹窗 (核心交互)
- 4.3 重设提交方法
- 5. 最终效果
- 6. 总结
1. 前言
在前几篇教程中,我们完成了科室、人员、角色和菜单的建设。这些都是静态的资源,如果不把它们“运转”起来,医院就无法接诊。
排班的本质,就是将**“医生资源”与“时间片段”结合,生成可供患者购买的“库存服务”**。
对于医院管理者来说,排班最大的痛点在于重复性:一个医生的出诊规律通常是固定的(例如:每周一上午、周三下午)。如果让管理员每天手动去创建一条排班记录,那简直是灾难。
因此,本篇我们的核心目标是:
- 定义排班模型:设计一张能够承载“库存”的数据库表。
- 实现批量排班:通过一个低代码表单,一次性生成某位医生未来一个月的排班数据(即“预先生成号源”)。
2. 数据库设计:库存模型
我们需要创建一个模型来存储“谁、在哪天、哪个时段、有多少个号”。
请登录云开发平台 -> 数据模型,新建t_schedule表。
| 字段名称 | 字段标识 | 数据类型 | 必填 | 说明 |
|---|---|---|---|---|
| 排班日期 | work_date | 日期/文本 | 是 | 格式建议YYYY-MM-DD,便于查询 |
| 关联医生 | doctor_id | 关联关系 | 是 | 关联t_personnel |
| 关联科室 | dept_id | 关联关系 | 是 | 关联t_department(冗余字段,方便查询) |
| 时段 | work_type | 枚举 | 是 | 选项:1(上午), 2(下午), 3(夜诊) |
| 总号源数 | total_count | 数字 | 是 | 该班次最多放多少个号,如 30 |
| 剩余号源 | surplus_count | 数字 | 是 | 初始值等于总号源数,随预约递减 |
| 挂号费 | reg_fee | 数字 | 是 | 单位:元 |
| 状态 | status | 枚举 | 是 | 1(正常), 0(停诊) |
设计小贴士:
为什么要有dept_id?虽然doctor_id里已经包含了部门信息,但在患者端查询“心内科有哪些排班”时,直接查t_schedule的dept_id索引,比“查排班 -> 关联医生 -> 关联部门”的跨表查询效率高得多。这叫空间换时间。
3. 后端逻辑:批量生成算法
管理员的操作场景通常是:“给张三医生排下个月每周一上午的班,每次30个号”。
我们需要编写一个自定义 API 来处理这个循环生成的逻辑。
在APIs 连接器 -> 自定义代码中新建 API。
入参设计 (Params):
doctorId: 医生IDdeptId: 科室IDstartDate: 开始日期 (YYYY-MM-DD)endDate: 结束日期 (YYYY-MM-DD)weekDays: 数组,包含需要排班的周几 (如[1, 3]代表周一和周三)workType: 时段 (1=上午)totalCount: 号源数fee: 费用
代码实现:
/** * API: batchCreateSchedule * 功能: 批量生成排班号源 */module.exports=asyncfunction(params,context){const{doctorId,deptId,startDate,endDate,weekDays,workType,totalCount,fee}=params;constresults=[];// 1. 初始化日期:注意时区处理,避免因为 0 点偏差导致日期跨越letcurrent=newDate(startDate);constend=newDate(endDate);// 确保结束日期能被包含在循环内(设置时间为 23:59:59)end.setHours(23,59,59,999);// 循环日期while(current<=end){// getDay(): 0是周日, 1-6是周一到周六constdayNum=current.getDay();// 转换为你的格式:"1"-"6" 代表周一到周六, "7" 代表周日constcurrentDayStr=dayNum===0?7:dayNum;// 2. 判断是否在选中的星期几中 (此时都是字符串,可以正确匹配)if(weekDays.includes(currentDayStr)){// 格式化为 YYYY-MM-DDconstdateStr=current.toISOString().split('T')[0];// 3. 查重:防止同一天同一时段重复排班constexist=awaitcontext.callModel({dataSourceName:'t_schedule',methodName:'wedaGetRecords',params:{where:[{key:'doctor_id',rel:'eq',val:doctorId},{key:'work_date',rel:'eq',val:dateStr},{key:'work_type',rel:'eq',val:workType}]}});if(exist.records&&exist.records.length>0){console.log(`跳过已存在排班:${dateStr}`);}else{// 4. 组装数据results.push({doctor_id:{_id:doctorId},dept_id:{_id:deptId},work_date:newDate(dateStr).getTime(),work_type:workType,total_count:Number(totalCount),surplus_count:Number(totalCount),reg_fee:Number(fee),status:"1"});}}// 移动到下一天current.setDate(current.getDate()+1);}// 5. 批量写入if(results.length>0){awaitcontext.callModel({dataSourceName:'t_schedule',methodName:'wedaBatchCreateV2',params:{data:results}});return{success:true,createdCount:results.length,message:"排班生成成功"};}else{return{success:false,message:"未生成任何新排班,可能日期范围内已存在或未匹配到星期"};}};4. 页面搭建:排班管理台
我们需要一个页面来查看排班,并提供一个按钮唤起“批量排班”的弹窗。
4.1 列表展示区
点击创建页面的图标,创建排班管理页面
删除网格布局,添加布局组件
添加数据表格组件
勾选排班表,选择场景
添加必要的筛选条件
4.2 批量排班弹窗 (核心交互)
在全局按钮里添加一个批量排班按钮
然后添加一个弹窗组件
在弹窗内容里添加一个表单容器
数据模型选择排班表
把排班日期改为日期区间选择
添加一个下拉多选组件,设置为每周出诊时段
4.3 重设提交方法
因为我们批量排班是要调用API,需要改一下表单容器的提交方法。选中表单容器,点击事件
将调用数据源方法改为我们的API
修改入参
({"doctorId":$w.form3.submitParams.data.doctor_id?._id||"","deptId":$w.form3.submitParams.data.dept_id?._id||"","startDate":$w.form3.submitParams.data.work_date?.[0]||0,"endDate":$w.form3.submitParams.data.work_date?.[1]||0,"weekDays":$w.form3.submitParams.data.weekDays?.map(item=>Number(item))||[],"workType":$w.form3.submitParams.data.work_type||"","totalCount":$w.form3.submitParams.data.total_count!==null ? Number($w.form3.submitParams.data.total_count):0, // null兜底0"fee":$w.form3.submitParams.data.reg_fee!==null ? Number($w.form3.submitParams.data.reg_fee):0})5. 最终效果
打开排版管理可以看到排班的记录
点击批量排班可以进行按照时间范围排班
6. 总结
本篇我们抛弃了复杂的 C 端高并发逻辑,回归到B 端管理系统的本质——高效的数据生产。
通过一个自定义 API 和一个简单的表单,我们将管理员从繁琐的“每天排班”中解放出来,实现了“一次配置,整月生效”。现在,我们的数据库里已经躺好了未来一个月的号源数据。
下一步预告:
号源有了,患者就可以在小程序上看到了。下一篇,我们将进入小程序端开发,实现首页金刚区跳转与科室-医生-排班的联动查询。
关注我,手把手教你开发互联网医院!