1. 需求分析

前面我们已经完成了检查项管理、检查组管理、套餐管理等。接下来我们需要进行预约设置,其实就是设置每一天的体检预约最大数量。客户可以通过微信端在线预约,在线预约时需要选择体检的时间,如果客户选择的时间已经预约满则无法进行预约。

2. 批量导入预约设置信息

预约设置信息对应的数据表为t_ordersetting,预约设置操作对应的页面为ordersetting.html
t_ordersetting表结构:

orderDate:预约日期

number:可预约人数

reservations:已预约人数

批量导入预约设置信息操作过程:

  1. 点击模板下载按钮下载Excel模板文件
  2. 将预约设置信息录入到模板文件中
  3. 点击上传文件按钮将录入完信息的模板文件上传到服务器
  4. 通过POI读取上传文件的数据并保存到数据库

本章解析Excel文件使用的技术为 Apache POI

2.1 完善页面

2.1.1 提供模板文件

资料中已经提供了Excel模板文件ordersetting_template.xlsx,将文件放在health_backend工程的template目录

2.1.2 实现模板文件下载

为模板下载按钮绑定事件实现模板文件下载

<el-button style="margin-bottom: 20px;margin-right: 20px" type="primary"
@click="downloadTemplate()">模板下载</el-button>
//模板文件下载
downloadTemplate(){window.location.href="../../template/ordersetting_template.xlsx";
}

2.1.3 文件上传

使用ElementUI的上传组件实现文件上传并绑定相关事件

<el-upload action="/ordersetting/upload.do"
name="excelFile"
:show-file-list="false"
:on-success="handleSuccess"
:before-upload="beforeUpload">
<el-button type="primary">上传文件</el-button>
</el-upload>
handleSuccess(response, file) {if(response.flag){this.$message({message: response.message,type: 'success'
});
}else{this.$message.error(response.message);
}
}
beforeUpload(file){const isXLS = file.type === 'application/vnd.ms-excel';if(isXLS){return true;}const isXLSX = file.type === 'application/vnd.openxmlformatsofficedocument.spreadsheetml.sheet';if (isXLSX) {return true;}this.$message.error('上传文件只能是xls或者xlsx格式!');return false;
}

2.2 后台代码

2.2.1 Controller

将资料中的POIUtils工具类复制到health_common工程
在health_backend工程创建OrderSettingController并提供upload方法

import com.alibaba.dubbo.config.annotation.Reference;
import com.itheima.constant.MessageConstant;
import com.itheima.entity.Result;
import com.itheima.pojo.OrderSetting;
import com.itheima.service.OrderSettingService;
import com.itheima.utils.POIUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;import javax.xml.ws.handler.MessageContext;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;/*** @author 嘿嘿嘿1212* @version 1.0* @date 2019/10/18 19:39*/
@RestController
@RequestMapping("ordersetting")
public class OrderSettingController {@Referenceprivate OrderSettingService orderSettingService;/*** 文件上传,实现预约设置数据批量导入** @param excelFile* @return*/@RequestMapping("upload")public Result upload(@RequestParam("excelFile") MultipartFile excelFile) {try {//使用POI解析Excel表格List<String[]> excel = POIUtils.readExcel(excelFile);//转换数据类型List<OrderSetting> list = new LinkedList<OrderSetting>();for (String[] strings : excel) {String orderDate = strings[0];String number = strings[1];OrderSetting orderSetting = new OrderSetting(new Date(orderDate), Integer.parseInt(number));list.add(orderSetting);}orderSettingService.add(list);} catch (Exception e) {e.printStackTrace();return new Result(false, MessageConstant.IMPORT_ORDERSETTING_FAIL);}return new Result(true, MessageConstant.IMPORT_ORDERSETTING_SUCCESS);}}
  • POIUtils
package com.itheima.utils;import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;public class POIUtils {private final static String xls = "xls";private final static String xlsx = "xlsx";private final static String DATE_FORMAT = "yyyy/MM/dd";/*** 读入excel文件,解析后返回* @param file* @throws IOException*/public static List<String[]> readExcel(MultipartFile file) throws IOException {//检查文件checkFile(file);//获得Workbook工作薄对象Workbook workbook = getWorkBook(file);//创建返回对象,把每行中的值作为一个数组,所有行作为一个集合返回List<String[]> list = new ArrayList<String[]>();if(workbook != null){for(int sheetNum = 0;sheetNum < workbook.getNumberOfSheets();sheetNum++){//获得当前sheet工作表Sheet sheet = workbook.getSheetAt(sheetNum);if(sheet == null){continue;}//获得当前sheet的开始行int firstRowNum  = sheet.getFirstRowNum();//获得当前sheet的结束行int lastRowNum = sheet.getLastRowNum();//循环除了第一行的所有行for(int rowNum = firstRowNum+1;rowNum <= lastRowNum;rowNum++){//获得当前行Row row = sheet.getRow(rowNum);if(row == null){continue;}//获得当前行的开始列int firstCellNum = row.getFirstCellNum();//获得当前行的列数int lastCellNum = row.getPhysicalNumberOfCells();String[] cells = new String[row.getPhysicalNumberOfCells()];//循环当前行for(int cellNum = firstCellNum; cellNum < lastCellNum;cellNum++){Cell cell = row.getCell(cellNum);cells[cellNum] = getCellValue(cell);}list.add(cells);}}workbook.close();}return list;}//校验文件是否合法public static void checkFile(MultipartFile file) throws IOException{//判断文件是否存在if(null == file){throw new FileNotFoundException("文件不存在!");}//获得文件名String fileName = file.getOriginalFilename();//判断文件是否是excel文件if(!fileName.endsWith(xls) && !fileName.endsWith(xlsx)){throw new IOException(fileName + "不是excel文件");}}public static Workbook getWorkBook(MultipartFile file) {//获得文件名String fileName = file.getOriginalFilename();//创建Workbook工作薄对象,表示整个excelWorkbook workbook = null;try {//获取excel文件的io流InputStream is = file.getInputStream();//根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象if(fileName.endsWith(xls)){//2003workbook = new HSSFWorkbook(is);}else if(fileName.endsWith(xlsx)){//2007workbook = new XSSFWorkbook(is);}} catch (IOException e) {e.printStackTrace();}return workbook;}public static String getCellValue(Cell cell){String cellValue = "";if(cell == null){return cellValue;}//如果当前单元格内容为日期类型,需要特殊处理String dataFormatString = cell.getCellStyle().getDataFormatString();if(dataFormatString.equals("m/d/yy")){cellValue = new SimpleDateFormat(DATE_FORMAT).format(cell.getDateCellValue());return cellValue;}//把数字当成String来读,避免出现1读成1.0的情况if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){cell.setCellType(Cell.CELL_TYPE_STRING);}//判断数据的类型switch (cell.getCellType()){case Cell.CELL_TYPE_NUMERIC: //数字cellValue = String.valueOf(cell.getNumericCellValue());break;case Cell.CELL_TYPE_STRING: //字符串cellValue = String.valueOf(cell.getStringCellValue());break;case Cell.CELL_TYPE_BOOLEAN: //BooleancellValue = String.valueOf(cell.getBooleanCellValue());break;case Cell.CELL_TYPE_FORMULA: //公式cellValue = String.valueOf(cell.getCellFormula());break;case Cell.CELL_TYPE_BLANK: //空值cellValue = "";break;case Cell.CELL_TYPE_ERROR: //故障cellValue = "非法字符";break;default:cellValue = "未知类型";break;}return cellValue;}
}

2.2.2 服务接口

创建OrderSettingService服务接口并提供新增方法

package com.itheima.service;
import com.itheima.pojo.OrderSetting;
import java.util.List;public interface OrderSettingService {public void add(List<OrderSetting> list) throws Exception;}

2.2.3 服务实现类

创建服务实现类OrderSettingServiceImpl并实现新增方法

package com.itheima.service.impl;import com.alibaba.dubbo.config.annotation.Service;
import com.itheima.dao.OrderSettingDao;
import com.itheima.pojo.OrderSetting;
import com.itheima.service.OrderSettingService;
import org.springframework.beans.factory.annotation.Autowired;import java.util.List;/*** @author 嘿嘿嘿1212* @version 1.0* @date 2019/10/18 20:09*/
@Service(interfaceClass = OrderSettingService.class)
public class OrderSettingServiceImpl implements OrderSettingService {@Autowiredprivate OrderSettingDao orderSettingDao;@Overridepublic void add(List<OrderSetting> list) throws Exception {//批量导入预约人数if (list != null && list.size() > 0) {for (OrderSetting orderSetting : list) {//判断当前日期是否已经进行了预约设置long countByOrderDate = orderSettingDao.findCountByOrderDate(orderSetting.getOrderDate());if (countByOrderDate > 0) {//已经进行了预约设置,执行更新操作orderSettingDao.editNumberByOrderDate(orderSetting);} else {//没有进行预约设置,执行插入操作orderSettingDao.add(orderSetting);}}}}
}

2.2.4 Dao接口

创建Dao接口OrderSettingDao并提供更新和新增方法与查询

package com.itheima.dao;import com.itheima.pojo.OrderSetting;import java.util.Date;/*** @author 嘿嘿嘿1212* @version 1.0* @date 2019/10/18 20:17*/
public interface OrderSettingDao {/*** 根据预约时间查询是否存在预约* @param orderDate* @return*/public long findCountByOrderDate(Date orderDate);/*** 添加预约* @param orderSetting*/public void add(OrderSetting orderSetting);/*** 根据预约时间修改预约人数* @param orderSetting*/public void editNumberByOrderDate(OrderSetting orderSetting);
}

2.2.5 Mapper映射文件

创建Mapper映射文件OrderSettingDao.xml并提供相关SQL

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.itheima.dao.OrderSettingDao"><!--根据预约时间查询--><select id="findCountByOrderDate" resultType="long" parameterType="date">select count(*)from t_ordersettingwhere orderDate = #{orderDate}</select><!--添加预约数据--><insert id="add" parameterType="com.itheima.pojo.OrderSetting">insert intot_ordersetting (orderDate, number, reservations)values(#{orderDate}, #{number}, #{reservations})</insert><!--根据预约时间修改可预约人数--><update id="editNumberByOrderDate" parameterType="com.itheima.pojo.OrderSetting">update t_ordersettingset number = #{number}where orderDate = #{orderDate}</update></mapper>

3. 日历展示预约设置信息

前面已经完成了预约设置功能,现在就需要通过日历的方式展示出来每天设置的预约人数。
在页面中已经完成了日历的动态展示,我们只需要查询当前月份的预约设置信息并展示到日历中即可,同时在日历中还需要展示已经预约的人数,效果如下:

3.1 完善页面

3.1.1 使用静态数据调试

为了能够快速看到效果,我们可以先使用静态数据模拟,然后再改为发送ajax请求查询数据库。
实现步骤:
(1)预约设置数据对应的模型数据为leftobj,在initData方法最后为leftobj模型数据赋值:

this.leftobj = [
{ date: 1, number: 120, reservations: 1 },
{ date: 3, number: 120, reservations: 1 },
{ date: 4, number: 120, reservations: 120 },
{ date: 6, number: 120, reservations: 1 },
{ date: 8, number: 120, reservations: 1 }
];

其中date表示日期,number表示可预约人数,reservations表示已预约人数
(2)使用VUE的v-for标签遍历上面的leftobj模型数据,展示到日历上:

<template>
<template v-for="obj in leftobj"><template v-if="obj.date == dayobject.day.getDate()"><template v-if="obj.number > obj.reservations"><div class="usual"><p>可预约{{obj.number}}人</p><p>已预约{{obj.reservations}}人</p></div></template><template v-else><div class="fulled"><p>可预约{{obj.number}}人</p><p>已预约{{obj.reservations}}人</p><p>已满</p></div></template></template>
</template>
<button v-if="dayobject.day > today" @click="handleOrderSet(dayobject.day)"class="orderbtn">设置
</button>
</template></div>
</template>

3.1.2 发送ajax获取动态数据

将上面的静态模拟数据去掉,改为发送ajax请求,根据当前页面对应的月份查询数据库获取预约设置信息,将查询结果赋值给leftobj模型数据

//发送ajax请求,根据当前页面对应的月份查询预约设置信息
axios.post("/ordersetting/getOrderSettingByMonth.do?date="+this.currentYear+'-'+this.currentMonth
).then((response)=>{if(response.data.flag){//为模型数据赋值,通过双向绑定展示到日历中this.leftobj = response.data.data;}else{this.$message.error(response.data.message);}
});

3.2 后台代码

3.2.1 Controller

在OrderSettingController中提供getOrderSettingByMonth方法,根据月份查询预约设置信息

/**
* 根据日期查询预约设置数据(获取指定日期所在月份的预约设置数据)
* @param date
* @return
*/
@RequestMapping("/getOrderSettingByMonth")
public Result getOrderSettingByMonth(String date){//参数格式为:2019-03try{List<Map> list = orderSettingService.getOrderSettingByMonth(date);//获取预约设置数据成功return new Result(true,MessageConstant.GET_ORDERSETTING_SUCCESS,list);}catch (Exception e){e.printStackTrace();//获取预约设置数据失败return new Result(false,MessageConstant.GET_ORDERSETTING_FAIL);}
}

注意:List<Map>Map是为灵活的进行返回数据绑定,指定属性名称,减少封装实体类

3.2.2 服务接口

在OrderSettingService服务接口中扩展方法getOrderSettingByMonth

public List<Map> getOrderSettingByMonth(String date);//参数格式为:2019-03

3.2.3 服务实现类

在OrderSettingServiceImpl服务实现类中实现方法getOrderSettingByMonth

//根据日期查询预约设置数据
public List<Map> getOrderSettingByMonth(String date) {//2019-3
String begin = date + "-1";//无论是哪个月份都是小于31号的String end = date + "-31";//进行封装查询数据Map<String, String> map = new HashMap<String, String>(2);map.put("begin", begin);map.put("end", end);//调用orderSettingDao进行查询List<OrderSetting> list = orderSettingDao.getOrderSettingByMonth(map);//进行封装数据List<Map<String, Integer>> result = new ArrayList<Map<String, Integer>>();if (list != null && list.size() > 0) {for (OrderSetting orderSetting : list) {Map<String, Integer> left = new HashMap<String, Integer>();//获取需要的数据int day = orderSetting.getOrderDate().getDate();int number = orderSetting.getNumber();int reservations = orderSetting.getReservations();//封装到指定属性名中left.put("date", date);left.put("number", number);left.put("reservations", reservations);result.add(left);}}return result
}

3.2.4 Dao接口

在OrderSettingDao接口中扩展方法getOrderSettingByMonth

public List<OrderSetting> getOrderSettingByMonth(Map date);

3.2.5 Mapper映射文件

在OrderSettingDao.xml文件中扩展SQL

<!--根据月份查询预约设置信息-->
<select id="getOrderSettingByMonth"
parameterType="map"
resultType="com.itheima.pojo.OrderSetting">select * from t_ordersetting where orderDate between #{dateBegin} and #{dateEnd}
</select>

4. 基于日历实现预约设置

本章节要完成的功能为通过点击日历中的设置按钮来设置对应日期的可预约人数。效果如下:

4.1 完善页面

4.1.1 为设置按钮绑定事件

为日历中的设置按钮绑定单击事件,当前日期作为参数

<button v-if="dayobject.day > today"
@click="handleOrderSet(dayobject.day)" class="orderbtn">设置</button>
//预约设置
handleOrderSet(day){alert(day);
}

4.1.2 弹出预约设置窗口并发送ajax请求

完善handleOrderSet方法,弹出预约设置窗口,用户点击确定按钮则发送ajax请求

//预约设置
handleOrderSet(day) {this.$prompt('请输入可预约人数', '预约设置', {confirmButtonText: '确定',cancelButtonText: '取消',inputPattern: /^[0-9]*[1-9][0-9]*$/,inputErrorMessage: '只能输入正整数'
}).then(({value}) => {//发送ajax请求根据日期修改可预约人数axios.post("/ordersetting/editNumberByDate.do", {orderDate: this.formatDate(day.getFullYear(), day.getMonth() + 1, day.getDate()), //日期number: value //可预约人数}).then((response) => {if (response.data.flag) {this.initData(this.formatDate(day.getFullYear(), day.getMonth() + 1,1));this.$message({type: 'success',message: response.data.message});} else {this.$message.error(response.data.message);}});
}).catch(() => {this.$message({type: 'info',message: '已取消'});
});

4.2 后台代码

4.2.1 Controller

在OrderSettingController中提供方法editNumberByDate

/**
* 根据指定日期修改可预约人数
* @param orderSetting
* @return
*/
@RequestMapping("editNumberByDate")
public Result editNumberByDate(@RequestBody OrderSetting orderSetting) {try {orderSettingService.editNumberByDate(orderSetting);return new Result(true, MessageConstant.ORDERSETTING_SUCCESS);} catch (Exception e) {e.printStackTrace();return new Result(false, MessageConstant.ORDERSETTING_FAIL);}
}

4.2.2 服务接口

在OrderSettingService服务接口中提供方法editNumberByDate

public void editNumberByDate(OrderSetting orderSetting);

4.2.3 服务实现类

在OrderSettingServiceImpl服务实现类中实现editNumberByDate

//根据日期修改可预约人数
@Override
public void editNumberByDate(OrderSetting orderSetting) {//查询当前日期是否进行了预约设置long count = orderSettingDao.findCountByOrderDate(orderSetting.getOrderDate());if (count > 0) {//当前日期已经进行了预约设置,需要进行修改操作orderSettingDao.editNumberByOrderDate(orderSetting);} else {//当前日期未进行预约设置,需要进行插入操作orderSettingDao.add(orderSetting);}}

4.2.4 Dao接口

在OrderSettingDao接口中提供方法

public void editNumberByOrderDate(OrderSetting orderSetting);
public long findCountByOrderDate(Date orderDate);
public void add(OrderSetting orderSetting);

4.2.5 Mapper映射文件

在OrderSettingDao.xml映射文件中提供SQL

<!--根据日期更新可预约人数-->
<update id="editNumberByOrderDate" parameterType="com.itheima.pojo.OrderSetting">update t_ordersetting set number = #{number} where orderDate = #{orderDate}
</update>
<!--根据预约日期查询-->
<select id="findCountByOrderDate" parameterType="java.util.Date" resultType="long">select count(*) from t_ordersetting where orderDate = #{orderDate}
</select>

XX健康:预约管理-预约设置日历插件文件简单下载Excel文件解析Excel表数据批量导入相关推荐

  1. Day_05 传智健康项目-预约管理-预约设置

    第5章 预约管理-预约设置 1. 需求分析 前面我们已经完成了检查项管理.检查组管理.套餐管理等.接下来我们需要进行预约设置,其实就是设置每一天的体检预约最大数量.客户可以通过微信端在线预约,在线预约 ...

  2. .NET开源工作流驰ccflow从表数据数据源导入设置

    2019独角兽企业重金招聘Python工程师标准>>> 驰骋工作流从表数据数据源导入设置 关键字 驰骋工作流引擎 流程快速开发平台 workflow ccflow jflow  .n ...

  3. Java版开源工作流Jflow从表数据数据源导入设置

    驰骋工作流从表数据数据源导入设置 关键字 驰骋工作流引擎 流程快速开发平台 workflow ccflow jflow  .net开源工作流 从表数据导入设置             概要说明 在从表 ...

  4. 传智健康day05 预约管理-预约设置

    1. 需求分析 前面我们已经完成了检查项管理.检查组管理.套餐管理等.接下来我们需要进行预约设置,其实就是设置每一天的体检预约最大数量.客户可以通过微信端在线预约,在线预约时需要选择体检的时间,如果客 ...

  5. FullCalendar日历插件的简单使用(版本4.2.0)

    最近开的一个项目,涉及到了日历日程安排的功能,所以选用了一个免费的日历插件:FullCalendar 1.首先去官网将官方的demo下载下来,通过官方的demo进行一个初步的了解,下面正式开始 PS: ...

  6. excel亮灯怎么设置_Excel这些超简单的聚光灯制作方法,核对数据再也不用愁!...

    原标题:Excel这些超简单的聚光灯制作方法,核对数据再也不用愁! 最近一直问小编Excel的聚光灯效果怎么做?今天小编就教大家快速制作聚光灯效果,核对数据再也不用怕看花眼啦! 一.聚光灯效果制作 步 ...

  7. java版开源工作流引擎ccflow从表数据数据源导入设置

    为什么80%的码农都做不了架构师?>>>    关键字 驰骋工作流引擎 流程快速开发平台 workflow ccflow jflow  .net开源工作流 从表数据导入设置 概要说明 ...

  8. 小技巧—设置IIS禁止网站放下载电影文件

    有台托管的服务器,共享100M电信机房光纤,近来发现网速度爆慢,登陆上去检查发现很CPU占用正常,都在20%以内,检查想了想,莫非有人放了大量软件或电影.MP3提供下载? 动动手,改了一下IIS设置, ...

  9. JQUERY插件JqueryAjaxFileUplaoder----更简单的异步文件上传

    异步上传相信大家都做过类似的功能,JqueryAjaxFileUploader为我们提供了更简单的实现和使用方式.不过既然是JQUERY的插件那么它所依赖的环境大家都懂得.JqueryAjaxFile ...

最新文章

  1. 【牛客每日一题】4.15 Treepath 题解(树上dfs/树形DP)
  2. 使用Mybatis的Generator可能导致的一个错误
  3. java中class_Java中Class对象详解
  4. android打包成apk会屏蔽注解,Android解决混淆打包之后注解被去掉的问题-Go语言中文社区...
  5. linux系统中删除一次性任务流程,Linux系统中的计划任务
  6. 《Essential C++》笔记之return;分析
  7. 2018大盘点 | R语言中文社区十大火爆文章
  8. 二级c语言 文件题,二级C语言题库文件.doc
  9. 解析身份证号码(附加Java代码)
  10. 领域自适应论文(六十八):Implicit Class-Conditioned Domain Alignment for Unsupervised Domain Adaptation论文原理
  11. php课程banner,5种关于banner图的实例代码
  12. 华为电脑Linux进pe,华为 PE-TLOOM 开启USB调试模式
  13. oracle odt.net,ODT .NET 详解之 SqlDataSource 访问 Oracle
  14. 博云与智领云达成战略合作,携手共研云原生大数据领域
  15. 看到校友录一位同学的留言,想起来一首诗
  16. 学习笔记:C语言简介
  17. 电脑会员管理系统怎么弄,电脑会员卡管理系统怎么弄
  18. Spoken English Practice(I won't succumb to you, not ever again)
  19. 7-7 字符串中的大写字母改成小写字母 (10 分)
  20. python基于PHP+MySQL的药店药品进销存管理系统

热门文章

  1. 【洛谷P1970】花匠【贪心】
  2. 物理实验室改造前搬迁注意事项有哪些TENAISU
  3. zabbix迁移部署注意事项
  4. tradingview 修改K线的颜色,边框色,线条色
  5. 数据加载、存储与文件格式(python)
  6. java中static的用法_Java类中static的用法
  7. 事业上如何运用“长尾理论”?
  8. 钉钉、微信抢占移动OA入口,其他OA厂商何去何从?
  9. 外泌体的三种分离方法及其临床意义
  10. Vue-router 使用编程式导航多次执行会报错NavigationDuplicated的解决方法