• Day116.尚医通:预约挂号详情 ※


    目录

    一、预约挂号详情 ※

    1、接口实现 

    2、前端实现

    二、预约确认

    1、接口实现

    2、前端实现


    一、预约挂号详情 ※

    1、需求分析 

    (1) 根据page、limit、hoscode、depcode,带分页带条件查询信息

    (2) 根据hoscode、depcode、workDate 查询排班明细数据

    (3) 根据医院预约周期展现号源信息(失效)

    (4) 如果当天已过开始挂号时间,预约周期+1

    (5) 如果没有医生出诊的日期(放假),也需要展示出来

    (6) 根据开始、停止挂号时间,判断状态

    2、接口分析

    1. 带分页带条件统计号源信息

    *参数:page、limit、hoscode、depcode

    *返回值:map

    2. 查询排班明细数据

    *参数:hoscode、depcode、workDate

    *返回值:list

    1、接口实现 

    1. controller

    HospitalApiController下新增方法

    1. @ApiOperation(value = "获取可预约排班数据")
    2. @GetMapping("auth/getBookingScheduleRule/{page}/{limit}/{hoscode}/{depcode}")
    3. public R getBookingSchedule(
    4. @PathVariable Integer page,
    5. @PathVariable Integer limit,
    6. @PathVariable String hoscode,
    7. @PathVariable String depcode) {
    8. Map map = scheduleService.getBookingSchedule(page, limit, hoscode, depcode);
    9. return R.ok().data(map);
    10. }
    11. @ApiOperation(value = "获取排班数据")
    12. @GetMapping("auth/findScheduleList/{hoscode}/{depcode}/{workDate}")
    13. public R findScheduleList(
    14. @PathVariable String hoscode,
    15. @PathVariable String depcode,
    16. @PathVariable String workDate) {
    17. //方法复用
    18. List scheduleList = scheduleService.getScheduleDetail(hoscode,depcode,workDate);
    19. return R.ok().data("scheduleList",scheduleList);
    20. }

    2. Service

    IPage:多传入一个总记录数,就可以算出总页数

    1. //获取可预约排班数据
    2. @Override
    3. public Map getBookingSchedule(
    4. Integer page, Integer limit, String hoscode, String depcode) {
    5. //1.根据hoscode 查询医院信息,获取预约规则
    6. //2.根据预约规则,分页信息,查询可预约日期的集合分页对象 (不受数据库影响,Ipage苞米豆)
    7. //3.参考后台接口实现聚合查询 (List)
    8. //4.合并 步骤2和步骤3的数据
    9. //5.封装数据并返回
    10. return null;
    11. }
    1. //获取可预约排班数据
    2. @Override
    3. public Map getBookingSchedule(
    4. Integer page, Integer limit, String hoscode, String depcode) {
    5. Map result = new HashMap<>();
    6. //1、根据hoscode 查询医院信息,获取预约规则
    7. Hospital hospital = hospitalService.getHospital(hoscode);
    8. if(hospital==null){
    9. throw new YyghException(20001,"医院信息有误");
    10. }
    11. BookingRule bookingRule = hospital.getBookingRule();
    12. //2、根据预约规则,分页信息,查询可预约日期的集合分页对象 (不受数据库影响,Ipage苞米豆)
    13. IPage iPage = this.getDateListPage(page,limit,bookingRule);
    14. List datePageList = iPage.getRecords();
    15. //3、参考后台接口实现聚合查询 (List),获取可预约日期科室剩余预约数
    16. //3.1准备筛选条件
    17. Criteria criteria = Criteria
    18. .where("hoscode").is(hoscode)
    19. .and("depcode").is(depcode)
    20. .and("workDate").in(datePageList);
    21. //3.2创建聚合查询对象
    22. Aggregation agg = Aggregation.newAggregation(
    23. //3.2.1设置查询条件
    24. Aggregation.match(criteria),
    25. //3.2.2设置聚合参数 + 聚合查询字段 (分组)
    26. Aggregation.group("workDate")
    27. .first("workDate").as("workDate")
    28. .count().as("docCount")
    29. .sum("reservedNumber").as("reservedNumber")
    30. .sum("availableNumber").as("availableNumber")
    31. );
    32. //3.3执行聚合查询List
    33. AggregationResults aggregate =
    34. mongoTemplate.aggregate(agg, Schedule.class, BookingScheduleRuleVo.class);
    35. List scheduleVoList =
    36. aggregate.getMappedResults();
    37. //3.4转化查询结果的类型,List=>Map k:workDate v:BookingScheduleRuleVo
    38. Map scheduleVoMap = new HashMap<>();
    39. if(!CollectionUtils.isEmpty(scheduleVoList)){
    40. scheduleVoMap = scheduleVoList.stream().collect(Collectors.toMap(
    41. BookingScheduleRuleVo::getWorkDate,
    42. BookingScheduleRuleVo->BookingScheduleRuleVo
    43. ));
    44. }
    45. //4、合并 步骤2(datePageList)和步骤3(scheduleVoMap)的数据
    46. List bookingScheduleRuleVoList = new ArrayList<>();
    47. for (int i = 0, let = datePageList.size(); i < let; i++) {
    48. //4.1 遍历 datePageList,取出每一天日期
    49. Date date = datePageList.get(i);
    50. //4.2 根据日期,查询scheduleVoMap,获取排班聚合的记录信息
    51. BookingScheduleRuleVo bookingScheduleRuleVo = scheduleVoMap.get(date);
    52. //4.3 排班聚合的记录是空的,需要初始化
    53. if(bookingScheduleRuleVo==null){
    54. bookingScheduleRuleVo = new BookingScheduleRuleVo();
    55. bookingScheduleRuleVo.setDocCount(0);//当前预约数
    56. bookingScheduleRuleVo.setAvailableNumber(-1);//
    57. }
    58. //4.4 设置排班日期
    59. bookingScheduleRuleVo.setWorkDate(date);
    60. bookingScheduleRuleVo.setWorkDateMd(date);
    61. //4.5 根据日期换算周几
    62. String dayOfWeek = this.getDayOfWeek(new DateTime(date));
    63. bookingScheduleRuleVo.setDayOfWeek(dayOfWeek);
    64. //4.6 根据时间进行状态判断 (状态 0:正常 1:即将放号 -1:当天已停止挂号)
    65. //最后一页,最后一条记录,状态为即将放号
    66. if(i==let-1 && page==iPage.getPages()){
    67. bookingScheduleRuleVo.setStatus(1);
    68. }else{
    69. bookingScheduleRuleVo.setStatus(0);
    70. }
    71. //第一页,第一条记录,如果已过停止挂号时间,状态为-1,当天停止挂号
    72. if(i==0&&page==1){
    73. DateTime stopDateTime = this.getDateTime(new Date(), bookingRule.getStopTime());
    74. if(stopDateTime.isBeforeNow()){
    75. bookingScheduleRuleVo.setStatus(-1);
    76. }
    77. }
    78. bookingScheduleRuleVoList.add(bookingScheduleRuleVo);
    79. }
    80. //5、封装数据并返回
    81. //可预约日期规则数据
    82. result.put("bookingScheduleList", bookingScheduleRuleVoList);
    83. result.put("total", iPage.getTotal());
    84. //其他基础数据
    85. Map baseMap = new HashMap<>();
    86. //医院名称
    87. baseMap.put("hosname", hospitalService.getHospName(hoscode));
    88. //科室
    89. Department department =departmentService.getDepartment(hoscode, depcode);
    90. //大科室名称
    91. baseMap.put("bigname", department.getBigname());
    92. //科室名称
    93. baseMap.put("depname", department.getDepname());
    94. //月
    95. baseMap.put("workDateString", new DateTime().toString("yyyy年MM月"));
    96. //放号时间
    97. baseMap.put("releaseTime", bookingRule.getReleaseTime());
    98. //停号时间
    99. baseMap.put("stopTime", bookingRule.getStopTime());
    100. result.put("baseMap", baseMap);
    101. return result;
    102. }
    1. //分支2 :根据预约规则,分页信息,查询可预约日期的集合分页对象
    2. private IPage getDateListPage(
    3. Integer page, Integer limit, BookingRule bookingRule) {
    4. //1.从预约规则中获取开始挂号的时间(当前系统日期+开始时间)
    5. DateTime releaseDateTime =
    6. this.getDateTime(new Date(),bookingRule.getReleaseTime());
    7. // 2.从预约规则中获取周期,判断周期是否需要+1 如果当天放号时间已过,则预约周期后一天为即将放号时间,周期加1
    8. Integer cycle = bookingRule.getCycle();
    9. if(releaseDateTime.isBeforeNow()) cycle +=1;
    10. //3.根据周期推算出可以挂号的日期,存入集合(list)
    11. List dateList = new ArrayList<>();
    12. for (int i = 0; i < cycle; i++) {
    13. //当前日期向后i天
    14. DateTime plusDays = new DateTime().plusDays(i);
    15. String plusDaysString = plusDays.toString("yyyy-MM-dd");
    16. dateList.add(new DateTime(plusDaysString).toDate());
    17. }
    18. //4.准备分页参数 日期分页,由于预约周期不一样,页面一排最多显示7天数据,多了就要分页显示
    19. int start = (page-1)*limit;
    20. int end = (page-1)*limit+limit;
    21. if(end>dateList.size()) end = dateList.size();
    22. //5.根据分页参数,获取分页后日期集合
    23. List datePageList = new ArrayList<>();
    24. for (int i = start; i < end; i++) {
    25. datePageList.add(dateList.get(i));
    26. }
    27. //6.封装数据到IPage对象,返回
    28. IPage iPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(page,limit,dateList.size());
    29. iPage.setRecords(datePageList);
    30. return iPage;
    31. }
    32. //日期+开始时间
    33. private DateTime getDateTime(Date date, String timeString) {
    34. String dateTimeString = new DateTime(date)
    35. .toString("yyyy-MM-dd") + " "+ timeString;
    36. DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm").parseDateTime(dateTimeString);
    37. return dateTime;
    38. }

    3. 更新排班数据,测试:

    2、前端实现

    1. 页面分析创建页面入口

    2. 添加API

    1. //获取可预约排班数据
    2. getBookingScheduleList(page, limit, hoscode, depcode) {
    3. return request({
    4. url: `${api_name}/auth/getBookingScheduleRule/${page}/${limit}/${hoscode}/${depcode}`,
    5. method: 'get'
    6. })
    7. },
    8. //获取排班数据
    9. findScheduleList(hoscode, depcode, workDate) {
    10. return request({
    11. url: `${api_name}/auth/findScheduleList/${hoscode}/${depcode}/${workDate}`,
    12. method: 'get'
    13. })
    14. },

    3. 添加页面元素

    1. <template>
    2. <div class="nav-container page-component">
    3. <div class="nav left-nav">
    4. <div class="nav-item selected">
    5. <span class="v-link selected dark" :onclick="'javascript:window.location=\'/hosp/'+hoscode+'\''">预约挂号
    6. span>
    7. div>
    8. <div class="nav-item ">
    9. <span class="v-link clickable dark"
    10. :onclick="'javascript:window.location=\'/hosp/detail/'+hoscode+'\''"> 医院详情 span>
    11. div>
    12. <div class="nav-item">
    13. <span class="v-link clickable dark"
    14. :onclick="'javascript:window.location=\'/hosp/notice/'+hoscode+'\''"> 预约须知 span>
    15. div>
    16. <div class="nav-item "><span class="v-link clickable dark"> 停诊信息 span>
    17. div>
    18. <div class="nav-item "><span class="v-link clickable dark"> 查询/取消 span>
    19. div>
    20. div>
    21. <div class="page-container">
    22. <div class="hospital-source-list">
    23. <div class="header-wrapper" style="justify-content:normal">
    24. <span class="v-link clickable" @click="show()">{{ baseMap.hosname}}span>
    25. <div class="split">div>
    26. <div>{{ baseMap.bigname }}div>
    27. div>
    28. <div class="title mt20"> {{ baseMap.depname }}div>
    29. <div class="mt60">
    30. <div class="title-wrapper">{{ baseMap.workDateString }}div>
    31. <div class="calendar-list-wrapper">
    32. <div :class="'calendar-item '+item.curClass" style="width: 124px;"
    33. v-for="(item, index) in bookingScheduleList" :key="item.id"
    34. @click="selectDate(item, index)">
    35. <div class="date-wrapper"><span>{{ item.workDate }}span><span class="week">{{
    36. item.dayOfWeek }}span>div>
    37. <div class="status-wrapper" v-if="item.status == 0">{{ item.availableNumber == -1 ? '无号' :
    38. item.availableNumber == 0 ? '约满' : '有号' }}div>
    39. <div class="status-wrapper" v-if="item.status == 1">即将放号div>
    40. <div class="status-wrapper" v-if="item.status == -1">停止挂号div>
    41. div>
    42. div>
    43. <el-pagination class="pagination" layout="prev, pager, next" :current-page="page" :total="total"
    44. :page-size="limit" @current-change="getPage">
    45. el-pagination>
    46. div>
    47. <div class="countdown-wrapper mt60" v-if="!tabShow">
    48. <div class="countdonw-title"> {{ time }}<span class="v-link selected">{{ baseMap.releaseTime }}
    49. span>放号div>
    50. <div class="countdown-text"> 倒 计 时
    51. <div>
    52. <span class="number">{{ timeString }}span>
    53. div>
    54. div>
    55. div>
    56. <div class="mt60" v-if="tabShow">
    57. <div class="">
    58. <div class="list-title">
    59. <div class="block">div>
    60. 上午号源
    61. div>
    62. <div v-for="item in scheduleList" :key="item.id">
    63. <div class="list-item" v-if="item.workTime == 0">
    64. <div class="item-wrapper">
    65. <div class="title-wrapper">
    66. <div class="title">{{ item.title }}div>
    67. <div class="split">div>
    68. <div class="name"> {{ item.docname }}div>
    69. div>
    70. <div class="special-wrapper">{{ item.skill }}div>
    71. div>
    72. <div class="right-wrapper">
    73. <div class="fee"> ¥{{ item.amount }}
    74. div>
    75. <div class="button-wrapper">
    76. <div class="v-button" @click="booking(item.id, item.availableNumber)"
    77. :style="item.availableNumber == 0 || pageFirstStatus == -1 ? 'background-color: #7f828b;' : ''">
    78. <span>剩余<span class="number">{{ item.availableNumber }}span>span>
    79. div>
    80. div>
    81. div>
    82. div>
    83. div>
    84. div>
    85. div>
    86. <div class="mt60" v-if="tabShow">
    87. <div class="">
    88. <div class="list-title">
    89. <div class="block">div>
    90. 下午号源
    91. div>
    92. <div v-for="item in scheduleList" :key="item.id">
    93. <div class="list-item" v-if="item.workTime == 1">
    94. <div class="item-wrapper">
    95. <div class="title-wrapper">
    96. <div class="title">{{ item.title }}div>
    97. <div class="split">div>
    98. <div class="name"> {{ item.docname }}div>
    99. div>
    100. <div class="special-wrapper">{{ item.skill }}div>
    101. div>
    102. <div class="right-wrapper">
    103. <div class="fee"> ¥{{ item.amount }}
    104. div>
    105. <div class="button-wrapper">
    106. <div class="v-button" @click="booking(item.id, item.availableNumber)"
    107. :style="item.availableNumber == 0 || pageFirstStatus == -1 ? 'background-color: #7f828b;' : ''">
    108. <span>剩余<span class="number">{{ item.availableNumber }}span>span>
    109. div>
    110. div>
    111. div>
    112. div>
    113. div>
    114. div>
    115. div>
    116. div>
    117. div>
    118. div>
    119. template>

    4. 添加JS方法

    5. 测试: 

    二、预约确认

    需求分析:

    (1)根据预约周期,展示可预约日期数据,按分页展示

    (2)选择日期展示当天可预约列表(该接口后台已经实现过)

    1、接口实现

    (1). 查询排班详情接口

    *参数:scheduleId

    *返回值:schedule

    (2). 登录用户,查询就诊人集合信息

    2. controller 

    ​​​​​​​HospitalApiController

    1. @ApiOperation(value = "根据排班id获取排班数据")
    2. @GetMapping("getSchedule/{id}")
    3. public R getSchedule(@PathVariable String id) {
    4. Schedule schedule = scheduleService.findScheduleById(id);
    5. return R.ok().data("schedule",schedule);
    6. }

    3. service 

    1. //根据排班id获取排班数据
    2. @Override
    3. public Schedule findScheduleById(String id) {
    4. Schedule schedule = scheduleRepository.findById(id).get();
    5. return this.packageSchedule(schedule);//翻译字段返回
    6. }

    2、前端实现

    1. 确认入口,创建页面

    2. hospital 添加API

    1. //根据排班id获取排班数据
    2. getSchedule(id) {
    3. return request({
    4. url: `${api_name}/getSchedule/${id}`,
    5. method: 'get'
    6. })
    7. }

     3. 添加页面

    1. <template>
    2. <div class="nav-container page-component">
    3. <div class="nav left-nav">
    4. <div class="nav-item selected">
    5. <span class="v-link selected dark"
    6. :onclick="'javascript:window.location=\'/hospital/'+schedule.hoscode+'\''">预约挂号 span>
    7. div>
    8. <div class="nav-item ">
    9. <span class="v-link clickable dark"
    10. :onclick="'javascript:window.location=\'/hospital/detail/'+schedule.hoscode+'\''"> 医院详情 span>
    11. div>
    12. <div class="nav-item">
    13. <span class="v-link clickable dark"
    14. :onclick="'javascript:window.location=\'/hospital/notice/'+schedule.hoscode+'\''"> 预约须知 span>
    15. div>
    16. <div class="nav-item "><span class="v-link clickable dark"> 停诊信息 span>
    17. div>
    18. <div class="nav-item "><span class="v-link clickable dark"> 查询/取消 span>
    19. div>
    20. div>
    21. <div class="page-container">
    22. <div class="hospital-order">
    23. <div class="header-wrapper">
    24. <div class="title mt20"> 确认挂号信息div>
    25. <div>
    26. <div class="sub-title">
    27. <div class="block">div>
    28. 选择就诊人:
    29. div>
    30. <div class="patient-wrapper">
    31. <div>
    32. <div class="v-card clickable item ">
    33. <div class="inline" v-for="(item,index) in patientList" :key="item.id"
    34. @click="selectPatient(index)" style="margin-right: 10px;">
    35. <div :class="activeIndex == index ? 'item-wrapper selected' : 'item-wrapper'">
    36. <div>
    37. <div class="item-title">{{ item.name }}div>
    38. <div>{{ item.param.certificatesTypeString }}div>
    39. <div>{{ item.certificatesNo }}div>
    40. div>
    41. <img src="//img.114yygh.com/static/web/checked.png" class="checked">
    42. div>
    43. div>
    44. div>
    45. div>
    46. <div class="item space add-patient v-card clickable">
    47. <div class="">
    48. <div class="item-add-wrapper" @click="addPatient()"> +
    49. 添加就诊人
    50. div>
    51. div>
    52. div>
    53. <div class="el-loading-mask" style="display: none;">
    54. <div class="el-loading-spinner">
    55. <svg viewBox="25 25 50 50" class="circular">
    56. <circle cx="50" cy="50" r="20" fill="none" class="path">circle>
    57. svg>
    58. div>
    59. div>
    60. div>
    61. <div class="sub-title" v-if="patientList.length > 0">
    62. <div class="block">div>
    63. 选择就诊卡: <span class="card-tips"><span class="iconfont">span>
    64. 如您持社保卡就诊,请务必选择医保预约挂号,以保证正常医保报销span>
    65. div>
    66. <el-card class="patient-card" shadow="always" v-if="patientList.length > 0">
    67. <div slot="header" class="clearfix">
    68. <div><span class="name"> {{ patient.name }} {{ patient.certificatesNo }} 居民身份证span>
    69. div>
    70. div>
    71. <div class="card SELF_PAY_CARD">
    72. <div class="info"><span class="type">{{ patient.isInsure == 0 ? '自费' :
    73. '医保'}}span><span class="card-no">{{ patient.certificatesNo }}span><span
    74. class="card-view">居民身份证span>div>
    75. <span class="operate">span>
    76. div>
    77. <div class="card">
    78. <div class="text bind-card">div>
    79. div>
    80. el-card>
    81. <div class="sub-title">
    82. <div class="block">div>
    83. 挂号信息
    84. div>
    85. <div class="content-wrapper">
    86. <el-form ref="form">
    87. <el-form-item label="就诊日期:">
    88. <div class="content"><span>{{ schedule.workDate }} {{ schedule.param.dayOfWeek }} {{
    89. schedule.workTime == 0 ? '上午' : '下午' }}span>div>
    90. el-form-item>
    91. <el-form-item label="就诊医院:">
    92. <div class="content"><span>{{ schedule.param.hosname }} span>div>
    93. el-form-item>
    94. <el-form-item label="就诊科室:">
    95. <div class="content"><span>{{ schedule.param.depname }} span>div>
    96. el-form-item>
    97. <el-form-item label="医生姓名:">
    98. <div class="content"><span>{{ schedule.docname }} span>div>
    99. el-form-item>
    100. <el-form-item label="医生职称:">
    101. <div class="content"><span>{{ schedule.title }} span>div>
    102. el-form-item>
    103. <el-form-item label="医生专长:">
    104. <div class="content"><span>{{ schedule.skill }}span>div>
    105. el-form-item>
    106. <el-form-item label="医事服务费:">
    107. <div class="content">
    108. <div class="fee">{{ schedule.amount }}元div>
    109. div>
    110. el-form-item>
    111. el-form>
    112. div>
    113. <div>
    114. <div class="sub-title">
    115. <div class="block">div>
    116. 用户信息
    117. div>
    118. <div class="content-wrapper">
    119. <el-form ref="form" :model="form">
    120. <el-form-item class="form-item" label="就诊人手机号:">
    121. {{ patient.phone }}
    122. el-form-item>
    123. el-form>
    124. div>
    125. div>
    126. <div class="bottom-wrapper">
    127. <div class="button-wrapper">
    128. <div class="v-button" @click="submitOrder()">{{ submitBnt }}div>
    129. div>
    130. div>
    131. div>
    132. div>
    133. div>
    134. div>
    135. div>
    136. template>

    4. JS实现,CSS样式

    1. <style>
    2. .hospital-order .header-wrapper {
    3. display: -webkit-box;
    4. display: -ms-flexbox;
    5. display: block !important;
    6. -webkit-box-align: center;
    7. -ms-flex-align: center;
    8. align-items: center;
    9. }
    10. .hospital-order .sub-title {
    11. letter-spacing: 1px;
    12. color: #999;
    13. margin-top: 60px;
    14. display: -webkit-box;
    15. display: -ms-flexbox;
    16. display: flex;
    17. -webkit-box-align: center;
    18. -ms-flex-align: center;
    19. align-items: center;
    20. }
    21. .hospital-order .content-wrapper .content {
    22. color: #333;
    23. }
    24. .el-form-item {
    25. margin-bottom: 5px;
    26. }
    27. .hospital-order .content-wrapper {
    28. margin-left: 140px;
    29. margin-top: 20px;
    30. }
    31. style>

    5. 测试

  • 相关阅读:
    IDEA绿色版本重装系统之后git远程仓出现的问题
    图像畸变与去畸变
    GB/T 29734.3-2020 塑钢复合门窗检测
    关于使用腾讯云HiFlow场景连接器每天提醒签到打卡
    【奇思妙想】【节省磁盘空间】我有一些文件,我不想移动它们,但又想节省磁盘空间,该怎么做呢?
    Java如何遍历HashSet呢?
    第9章_瑞萨MCU零基础入门系列教程之SCI I2C
    LINQ详解二(C#)
    内网IP端口提供外网连接访问?快解析动态域名与内网映射P2P穿透方案
    面试中常问到的C++11的题目和答案
  • 原文地址:https://blog.csdn.net/a111042555/article/details/126101414