【排班管理详细步骤】(内附源码)

页面预览

医院详情

image-20230217040332183

排班管理

image-20230217051939537

第01章-医院详情

1、后端

1.1、Controller

AdminHospitalController

@ApiOperation(value = "获取医院详情")
@ApiImplicitParam(name = "hoscode",value = "医院编码", required = true)
@GetMapping("/show/{hoscode}")
public Result<Hospital> show(@PathVariable String hoscode) {
    Hospital hospital = hospitalService.show(hoscode);
    return Result.ok(hospital);
}

1.2、Service

接口:HospitalService

/**
     * 根据医院编码获取医院详情
     * @param hoscode
     * @return
     */
Hospital show(String hoscode);

实现:HospitalServiceImpl

@Override
public Hospital show(String hoscode) {
    Hospital hospital = hospitalRepository.findByHoscode(hoscode);
    return this.packHospital(hospital);
}

2、前端

2.1、添加路由

静态路由:

src/router/index.js:在“医院管理”下添加子节点

{
  path: 'hosp/show/:hoscode',
  name: 'hospShow',
  component: () => import('@/views/syt/hosp/show'),
  meta: { title: '查看', noCache: true },
  hidden: true
}

动态路由:

医院列表下添加按钮

image-20230317104455506

2.2、api

src/api/syt/hosp.js

//查看医院详情
getHospByCode(hoscode){
  return request ({
    url: `${apiName}/show/${hoscode}`,
    method: 'get'
  })
},

2.3、组件渲染

创建 src/views/syt/hosp/show.vue

<template>
  <div class="app-container">
    <h4>基本信息</h4>
    <table
      class="table table-striped table-condenseda table-bordered"
      width="100%"
    >
      <tbody>
        <tr>
          <th width="15%">医院名称</th>
          <td width="35%">
            <b style="font-size: 14px">{{ hospital.hosname }}</b> |
            {{ hospital.param.hostypeString }}
          </td>
          <th width="15%"></th>
          <td width="35%">
            <img
              :src="'data:image/jpeg;base64,' + hospital.logoData"
              width="80"
            />
          </td>
        </tr>
        <tr>
          <th>医院编码</th>
          <td>{{ hospital.hoscode }}</td>
          <th>地址</th>
          <td>{{ hospital.param.fullAddress }}</td>
        </tr>
        <tr>
          <th>坐车路线</th>
          <td colspan="3">{{ hospital.route }}</td>
        </tr>
        <tr>
          <th>医院简介</th>
          <td colspan="3">{{ hospital.intro }}</td>
        </tr>
      </tbody>
    </table>
    <h4>预约规则信息</h4>
    <table
      class="table table-striped table-condenseda table-bordered"
      width="100%"
    >
      <tbody>
        <tr>
          <th width="15%">预约周期</th>
          <td width="35%">{{ hospital.bookingRule.cycle }}天</td>
          <th width="15%">放号时间</th>
          <td width="35%">{{ hospital.bookingRule.releaseTime }}</td>
        </tr>
        <tr>
          <th>停挂时间</th>
          <td>{{ hospital.bookingRule.stopTime }}</td>
          <th>退号时间</th>
          <td>
            {{ hospital.bookingRule.quitDay == -1 ? '就诊前一工作日' : '就诊当日'
            }}{{ hospital.bookingRule.quitTime }} 前取消
          </td>
        </tr>
        <tr>
          <th>预约规则</th>
          <td colspan="3">
            <ol>
              <li v-for="item in hospital.bookingRule.rule" :key="item">{{ item }}</li>
            </ol>
          </td>
        </tr>
      </tbody>
    </table>
    <p style="text-align:center;"><el-button @click="back">返回</el-button></p>
    
  </div>
</template>

<script>
import hospApi from '@/api/syt/hosp'
import '@/styles/show.css'

export default {
  data() {
    return {
      hospital: null, //医院信息
    }
  },

  created () {
    
    this.fetchHospByHoscode(this.$route.params.hoscode)

  },

  methods: {
    //获取医院详情
    fetchHospByHoscode(hoscode){
      hospApi.getHospByCode(hoscode).then(response => {
        this.hospital = response.data
      })
    },

    //返回到医院列表
    back(){
        this.$router.push({path: '/syt/hospset/hosp/list'})
    }
  }
}
</script>

第02章-科室列表

1、后端

1.1、Controller

创建 AdminDepartmentController

package com.atguigu.syt.hosp.controller.admin;

@Api(tags = "科室管理")
@RestController
@RequestMapping("/admin/hosp/department")
public class AdminDepartmentController {

    @Resource
    private DepartmentService departmentService;

    @ApiOperation(value = "查询医院所有科室列表")
    @ApiImplicitParam(name = "hoscode",value = "医院编码", required = true)
    @GetMapping("/getDeptList/{hoscode}")
    public Result<List<DepartmentVo>> getDeptList(@PathVariable String hoscode) {
        List<DepartmentVo> list = departmentService.findDeptTree(hoscode);
        return Result.ok(list);
    }
}

1.2、Service

接口:DepartmentService

/**
     * 根据医院编码获取部门嵌套列表
     * @param hoscode
     * @return
     */
List<DepartmentVo> findDeptTree(String hoscode);

实现:DepartmentServiceImpl

@Override
public List<DepartmentVo> findDeptTree(String hoscode) {

    //创建list集合,用于最终数据封装
    List<DepartmentVo> result = new ArrayList<>();
    //根据医院编号,查询医院所有科室信息
    List<Department> departmentList = departmentRepository.findByHoscode(hoscode);
    //根据大科室编号  bigcode 分组,获取每个大科室里面下级子科室
    //collect:将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法
    Map<String, List<Department>> deparmentMap =
        departmentList.stream().collect(Collectors.groupingBy(Department::getBigcode));
    //遍历map集合 deparmentMap   (iter)
    for(Map.Entry<String,List<Department>> entry : deparmentMap.entrySet()) {
        //大科室编号
        String bigcode = entry.getKey();
        //大科室编号对应的全部数据
        List<Department> subList = entry.getValue();
        //封装大科室
        DepartmentVo departmentVo = new DepartmentVo();
        departmentVo.setDepcode(bigcode);
        departmentVo.setDepname(subList.get(0).getBigname());
        //封装小科室
        List<DepartmentVo> children = new ArrayList<>();
        for(Department subDepartment: subList) {
            DepartmentVo subDepartmentVo =  new DepartmentVo();
            subDepartmentVo.setDepcode(subDepartment.getDepcode());
            subDepartmentVo.setDepname(subDepartment.getDepname());
            //封装到list集合
            children.add(subDepartmentVo);
        }
        //把小科室list集合放到大科室children里面
        departmentVo.setChildren(children);
        //放到最终result里面
        result.add(departmentVo);
    }
    //返回
    return result;
}

1.3、Repository

/**
 * 根据医院编号查询科室列表
 * @param hoscode
 * @return
 */
List<Department> findByHoscode(String hoscode);

2、前端

2.1、添加路由

静态路由:

src/router/index.js:在“医院管理”下添加子节点

{
  path: 'hosp/schedule/:hoscode',
  name: 'hospSchedule',
  component: () => import('@/views/syt/hosp/schedule'),
  meta: { title: '排班', noCache: true },
  hidden: true
} 

动态路由:

医院列表下添加按钮

image-20230611004523358

image-20230317105009222

2.2、api

创建src/api/syt/dept.js

import request from '@/utils/request'
const apiName = '/admin/hosp/department'
export default {
  //查看医院科室
  getDeptByHoscode(hoscode) {
    return request ({
        url: `${apiName}/getDeptList/${hoscode}`,
        method: 'get'
    })
  },
}

2.3、组件渲染

src/views/syt/hosp/schedule.vue

<template>
  <div class="app-container">
    <div style="margin-bottom: 10px; font-size: 10px">选择:</div>
    <el-container style="height: 100%">
      <el-aside width="200px" style="border: 1px silver solid">
        <!-- 部门 -->
        <el-tree
          :data="data"
          :props="defaultProps"
          @node-click="selectDept"
        >
        </el-tree>
      </el-aside>
      <el-main style="padding: 0 0 0 20px">
        <el-row style="width: 100%">
          <!-- 排班日期 分页 -->
        </el-row>
        <el-row style="margin-top: 20px">
          <!-- 排班日期对应的排班医生 -->
        </el-row>
      </el-main>
    </el-container>
  </div>
</template>
<script>
import deptApi from '@/api/syt/dept'
export default {
  data() {
    return {
      data: [], //部门列表
      defaultProps: {
        children: 'children',
        label: 'depname',
      },
      
      hoscode: null, //医院编号
      depcode: null, //科室编号
      workDate: null, //选中的排班日期
      activeIndex: -1, //选中的排班日期的索引

      bookingScheduleList: [], //当前选中的科室下所显示的排班日期数据
      page: 1, // 当前页
      limit: 6, // 每页个数
      total: 0, // 总页码

      scheduleDetailList:[] //某一个日期下排班详情列表
    }
  },

  created() {
    this.hoscode = this.$route.params.hoscode
    this.fetchData()
  },

  methods: {
    fetchData() {
      deptApi.getDeptByHoscode(this.hoscode).then((response) => {
        this.data = response.data
      })
    },

        //选择部门
    selectDept(data) {
      // 科室大类直接返回,
      if (data.children != null) return

      this.depcode = data.depcode
      this.getScheduleRule()
    },
  },
}
</script>

第03章-日期统计列表

1、后端

1.1、引入工具类

在service-hosp中引入joda-time依赖

<!--时间日期工具-->
<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
</dependency>

资料:资料>DateUtil工具

将DateUtil复制到service-hosp的utils包

1.2、Controller

创建AdminScheduleController

package com.atguigu.syt.hosp.controller.admin;

@Api(tags = "排班接口")
@RestController
@RequestMapping("/admin/hosp/schedule")
public class AdminScheduleController {

    @Resource
    private ScheduleService scheduleService;

    @ApiOperation(value ="查询排班规则数据")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page",value = "页码",required = true),
            @ApiImplicitParam(name = "limit",value = "每页记录数",required = true),
            @ApiImplicitParam(name = "hoscode",value = "医院编码",required = true),
            @ApiImplicitParam(name = "depcode",value = "部门编码",required = true)
    })
    @GetMapping("/getScheduleRule/{page}/{limit}/{hoscode}/{depcode}")
    public Result<Map<String, Object>> getScheduleRule(@PathVariable Long page,
                                                       @PathVariable Long limit,
                                                       @PathVariable String hoscode,
                                                       @PathVariable String depcode) {
        Map<String,Object> map = scheduleService.getScheduleRule(page,limit,hoscode,depcode);
        return Result.ok(map);
    }
}

1.3、Service

接口:ScheduleService

/**
     * 根据医院编号 和 科室编号 ,查询排班规则(按日期展示)
     * @param page
     * @param limit
     * @param hoscode
     * @param depcode
     * @return
     */
Map<String, Object> getScheduleRule(Long page, Long limit, String hoscode, String depcode);

实现:ScheduleServiceImpl

@Resource
private MongoTemplate mongoTemplate;

@Override
public Map<String, Object> getScheduleRule(Long page, Long limit, String hoscode, String depcode) {

    //获取查询结果
    //List<Schedule> list = mongoTemplate.findAll(Schedule.class);
    //查询条件:根据医院编号和科室编号查询
    Criteria criteria = Criteria.where("hoscode").is(hoscode).and("depcode").is(depcode);
    //根据工作日workDate期进行分组
    Aggregation agg = Aggregation.newAggregation(
        //1 查询条件
        Aggregation.match(criteria),
        Aggregation
        //2 按照日期分组 select workDate as workDate from schedule group by workDate
        .group("workDate").first("workDate").as("workDate")
        //3 可预约数
        .sum("reservedNumber").as("reservedNumber")
        //4 剩余预约数
        .sum("availableNumber").as("availableNumber"),
        //5 排序
        Aggregation.sort(Sort.Direction.ASC,"workDate"),
        //6 分页
        Aggregation.skip((page-1)*limit),
        Aggregation.limit(limit)
    );
    //执行查询,查询Schedule集合,将文档中的同名字段数据存入BookingScheduleRuleVo类
    AggregationResults<ScheduleRuleVo> aggResults = mongoTemplate.aggregate(agg, Schedule.class, ScheduleRuleVo.class);
    //获取查询结果
    List<ScheduleRuleVo> list = aggResults.getMappedResults();


    //分组查询后的总记录数
    Aggregation totalAgg = Aggregation.newAggregation(
        Aggregation.match(criteria),
        Aggregation.group("workDate")
    );
    AggregationResults<ScheduleRuleVo> totalAggResults = mongoTemplate.aggregate(totalAgg, Schedule.class, ScheduleRuleVo.class);
    int total = totalAggResults.getMappedResults().size();
    //根据日期计算对应星期获取 (iter)
    for (ScheduleRuleVo scheduleRuleVo : list) {
        Date workDate = scheduleRuleVo.getWorkDate();
        String dayOfWeek = DateUtil.getDayOfWeek(new DateTime(workDate));
        scheduleRuleVo.setDayOfWeek(dayOfWeek);
    }
    //设置最终数据,进行返回
    Map<String, Object> result = new HashMap<>();
    result.put("list",list);
    result.put("total",total);
    return result;
}

2、前端

2.1、api

创建src/api/syt/schedule.js

import request from '@/utils/request'
const apiName = '/admin/hosp/schedule'
export default {
  //查看排班
  getScheduleRule(page, limit, hoscode, depcode) {
    return request ({
        url: `${apiName}/getScheduleRule/${page}/${limit}/${hoscode}/${depcode}`,
        method: 'get'
    })
  },
}

2.2、组件渲染

完善src/views/syt/hosp/schedule.vue

html:

<!-- 排班日期 -->
<el-tag
        v-for="(item, index) in bookingScheduleList"
        :key="item.id"
        @click="selectDate(item.workDate, index)"
        :type="index == activeIndex ? '' : 'info'"
        style="height: 60px; margin-right: 15px; cursor: pointer"
        >
    {{ item.workDate }} {{ item.dayOfWeek }}<br />
    余号{{ item.availableNumber }} / 共{{ item.reservedNumber }}
</el-tag>
<!-- 分页 -->
<el-pagination
               v-if="total > 0"
               :current-page="page"
               :total="total"
               :page-size="limit"
               class="pagination"
               layout="prev, pager, next"
               align="center"
               style="margin-top: 20px"
               @current-change="changePage"
               >
</el-pagination>

js

import scheduleApi from '@/api/syt/schedule'

methods

 fetchData() {
      deptApi.getDeptByHoscode(this.hoscode).then(response => {
        this.data = response.data;
        //默认加载日期统计列表
        //如果this.data有数据,默认选中第一个
        if (this.data.length > 0) {
          this.depcode = this.data[0].children[0].depcode;
          this.getScheduleRule();
        }
      });
    },
//获取排班日期列表
getScheduleRule() {
  this.workDate = null
  this.activeIndex = -1
  this.scheduleDetailList = []
    
  //调用api查询
  scheduleApi
    .getScheduleRule(this.page, this.limit, this.hoscode, this.depcode)
    .then((response) => {
      this.bookingScheduleList = response.data.list
      this.total = response.data.total
    })
},

//日期翻页
changePage(page) {
  this.page = page
  this.getScheduleRule()
},
//选择日期
selectDate(workDate, index) {
  this.workDate = workDate
  this.activeIndex = index
},

第04章-排班详情

1、后端

1.1、Controller

在AdminScheduleController中添加方法

@ApiOperation(value = "查询排班详细信息")
@ApiImplicitParams({
    @ApiImplicitParam(name = "hoscode",value = "医院编码",required = true),
    @ApiImplicitParam(name = "depcode",value = "部门编码",required = true),
    @ApiImplicitParam(name = "workDate",value = "选择日期",required = true)
})
@GetMapping("/getScheduleDetail/{hoscode}/{depcode}/{workDate}")
public Result<List<Schedule>> getScheduleDetail( @PathVariable String hoscode,
                                                @PathVariable String depcode,
                                                @PathVariable String workDate) {
    List<Schedule> list = scheduleService.getScheduleList(hoscode,depcode,workDate);
    return Result.ok(list);
}

1.2、service

接口:ScheduleService

/**
     * 据医院编号 、科室编号和工作日期,查询排班详细信息
     * @param hoscode
     * @param depcode
     * @param workDate
     * @return
     */
List<Schedule> getScheduleList(String hoscode, String depcode, String workDate);

实现:ScheduleServiceImpl

@Override
public List<Schedule> getScheduleList(String hoscode, String depcode, String workDate) {

    //注意:最后一个参数需要进行数据类型的转换
    return scheduleRepository.findByHoscodeAndDepcodeAndWorkDate(
        hoscode,
        depcode,
        new DateTime(workDate).toDate());  //数据类型的转换
}

1.3、Repository

在ScheduleRepository中添加接口方法

/**
     * 据医院编号 、科室编号和工作日期,查询排班详细信息
     * @param hoscode
     * @param depcode
     * @param date
     * @return
     */
List<Schedule> findByHoscodeAndDepcodeAndWorkDate(String hoscode, String depcode, Date date);

2、前端

2.1、api

src/api/syt/schedule.js添加方法

//查询排班详情
getScheduleDetail(hoscode, depcode, workDate) {
    return request({
        url: `${apiName}/getScheduleDetail/${hoscode}/${depcode}/${workDate}`,
        method: 'get'
    })
}

2.2、组件渲染

src/views/yygh/hosp/schedule.vue

html:

<!-- 排班日期对应的排班医生 -->
<el-table
          v-if="scheduleDetailList.length > 0"
          :data="scheduleDetailList"
          border
          fit
          highlight-current-row
          >
    <el-table-column label="序号" width="60" align="center">
        <template slot-scope="scope">
            {{ scope.$index + 1 }}
        </template>
    </el-table-column>
    <el-table-column label="职称" width="150">
        <template slot-scope="scope">
            {{ scope.row.title }} | {{ scope.row.docname }}
        </template>
    </el-table-column>
    <el-table-column label="号源时间" width="80">
        <template slot-scope="scope">
            {{ scope.row.workTime == 0 ? '上午' : '下午' }}
        </template>
    </el-table-column>
    <el-table-column
                     prop="reservedNumber"
                     label="可预约数"
                     width="80"
                     />
    <el-table-column
                     prop="availableNumber"
                     label="剩余预约数"
                     width="100"
                     />
    <el-table-column prop="amount" label="挂号费(元)" width="90" />
    <el-table-column prop="skill" label="擅长技能" />
</el-table>

methods:完善之前的selectDate()方法,添加getDetailSchedule()方法


//查询日期统计数据
    getScheduleRule() {
      //数据初始化
      this.workDate = null;
      this.activeIndex = -1;
      this.scheduleDetailList = [];
      //调用接口获取数据
      scheduleApi
        .getScheduleRule(this.page, this.limit, this.hoscode, this.depcode)
        .then(response => {
          this.bookingScheduleList = response.data.list;
          this.total = response.data.total;
          //默认选中workdate、activeIndex赋值,调用方法加载排班数据
          this.workDate = this.bookingScheduleList[0].workDate;
          this.activeIndex = 0;
          this.getDetailSchedule();
        });
    },

//选择日期(完善此方法,添加最后一行代码)
selectDate(workDate, index) {
  this.workDate = workDate
  this.activeIndex = index
  this.getDetailSchedule()
},

//查询排班详情
getDetailSchedule() {
  scheduleApi
    .getScheduleDetail(this.hoscode, this.depcode, this.workDate)
    .then((response) => {
      this.scheduleDetailList = response.data
    })
},

源码:https://gitee.com/dengyaojava/guigu-syt-parent

posted @ 2023-06-12 19:19  自律即自由-  阅读(217)  评论(0编辑  收藏  举报