體檢預約


體檢預約流程

用戶可以通過如下操作流程進行體檢預約:

1、在移動端首頁點擊體檢預約,頁面跳轉到套餐列表頁面

2、在套餐列表頁面點擊要預約的套餐,頁面跳轉到套餐詳情頁面

3、在套餐詳情頁面點擊立即預約,頁面跳轉到預約頁面

4、在預約頁面錄入體檢人信息,包括手機號,點擊發送驗證碼

5、在預約頁面錄入收到的手機短信驗證碼,點擊提交預約,完成體檢預約

體檢預約

頁面調整

在預約頁面(/pages/orderInfo.html)進行調整

展示預約的套餐信息

第一步:從請求路徑中獲取當前套餐的id

<script>
  var id = getUrlParam("id");//套餐id
</script>

第二步:定義模型數據setmeal,用於套餐數據展示

var vue = new Vue({
  el:'#app',
  data:{
    setmeal:{},//套餐信息
    orderInfo:{
      setmealId:id,
      sex:'1'
    }//預約信息
  }
});
View Code
<div class="card">
  <div class="">
    <img :src="'http://pqjroc654.bkt.clouddn.com/'+setmeal.img" width="100%" height="100%" />
  </div>
  <div class="project-text">
    <h4 class="tit">{{setmeal.name}}</h4>
    <p class="subtit">{{setmeal.remark}}</p>
    <p class="keywords">
        <span>{{setmeal.sex == '0' ? '性別不限' : setmeal.sex == '1' ? '男':'女'}}</span>
        <span>{{setmeal.age}}</span>
    </p>
  </div>
  <div class="project-know">
    <a href="orderNotice.html" class="link-page">
      <i class="icon-ask-circle"><span class="path1"></span><span class="path2"></span></i>
      <span class="word">預約須知</span>
      <span class="arrow"><i class="icon-rit-arrow"></i></span>
    </a>
  </div>
</div>
View Code

第三步:在VUE的鈎子函數中發送ajax請求,根據id查詢套餐信息

mounted(){
  axios.post("/setmeal/findById.do?id=" + id).then((response) => {
    this.setmeal = response.data.data;
  });
}

手機號校驗

第一步:在頁面導入的healthmobile.js文件中已經定義了校驗手機號的方法

/**
 * 手機號校驗
 1--以1為開頭;
 2--第二位可為3,4,5,7,8,中的任意一位;
 3--最后以0-9的9個整數結尾。
 */
function checkTelephone(telephone) {
    var reg=/^[1][3,4,5,7,8][0-9]{9}$/;
    if (!reg.test(telephone)) {
        return false;
    } else {
        return true;
    }
}
View Code

第二步:為發送驗證碼按鈕綁定事件sendValidateCode

<div class="input-row">
  <label>手機號</label>
  <input v-model="orderInfo.telephone" 
         type="text" class="input-clear" placeholder="請輸入手機號">
  <input style="font-size: x-small;" 
         id="validateCodeButton" @click="sendValidateCode()" type="button" value="發送驗證碼">
</div>
//發送驗證碼
sendValidateCode(){
  //獲取用戶輸入的手機號
  var telephone = this.orderInfo.telephone;
  //校驗手機號輸入是否正確
  if (!checkTelephone(telephone)) {
    this.$message.error('請輸入正確的手機號');
    return false;
  }
}

30秒倒計時效果

前面在sendValidateCode方法中進行了手機號校驗,如果校驗通過,需要顯示30秒倒計時效果

//發送驗證碼
sendValidateCode(){
  //獲取用戶輸入的手機號
  var telephone = this.orderInfo.telephone;
  //校驗手機號輸入是否正確
  if (!checkTelephone(telephone)) {
    this.$message.error('請輸入正確的手機號');
    return false;
  }
  validateCodeButton = $("#validateCodeButton")[0];
  clock = window.setInterval(doLoop, 1000); //一秒執行一次
}

其中,validateCodeButton和clock是在healthmobile.js文件中定義的變量,doLoop是在healthmobile.js文件中定義的方法

var clock = '';//定時器對象,用於頁面30秒倒計時效果
var nums = 30;
var validateCodeButton;
//基於定時器實現30秒倒計時效果
function doLoop() {
    validateCodeButton.disabled = true;//將按鈕置為不可點擊
    nums--;
    if (nums > 0) {
        validateCodeButton.value = nums + '秒后重新獲取';
    } else {
        clearInterval(clock); //清除js定時器
        validateCodeButton.disabled = false;
        validateCodeButton.value = '重新獲取驗證碼';
        nums = 30; //重置時間
    }
}
View Code

發送ajax請求

在按鈕上顯示30秒倒計時效果的同時,需要發送ajax請求,在后台給用戶發送手機驗證碼

//發送驗證碼
sendValidateCode(){
  //獲取用戶輸入的手機號
  var telephone = this.orderInfo.telephone;
  //校驗手機號輸入是否正確
  if (!checkTelephone(telephone)) {
    this.$message.error('請輸入正確的手機號');
    return false;
  }
  validateCodeButton = $("#validateCodeButton")[0];
  clock = window.setInterval(doLoop, 1000); //一秒執行一次
  axios.post("/validateCode/send4Order.do?telephone=" + telephone).then((response) => {
    if(!response.data.flag){
      //驗證碼發送失敗
      this.$message.error('驗證碼發送失敗,請檢查手機號輸入是否正確');
    }
  });
}
View Code

創建ValidateCodeController,提供方法發送短信驗證碼,並將驗證碼保存到redis

package com.itheima.controller;
​
import com.aliyuncs.exceptions.ClientException;
import com.itheima.constant.MessageConstant;
import com.itheima.constant.RedisConstant;
import com.itheima.constant.RedisMessageConstant;
import com.itheima.entity.Result;
import com.itheima.utils.JedisUtils;
import com.itheima.utils.SMSUtils;
import com.itheima.utils.ValidateCodeUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.util.Random;
​
/**
 * 短信驗證碼
 */
@RestController
@RequestMapping("/validateCode")
public class ValidateCodeController {
    @Autowired
    private JedisPool jedisPool;
  
    //體檢預約時發送手機驗證碼
    @RequestMapping("/send4Order")
    public Result send4Order(String telephone){
        Integer code = ValidateCodeUtils.generateValidateCode(4);//生成4位數字驗證碼
        try {
            //發送短信
            SMSUtils.sendShortMessage(SMSUtils.VALIDATE_CODE,telephone,code.toString());
        } catch (ClientException e) {
            e.printStackTrace();
            //驗證碼發送失敗
            return new Result(false, MessageConstant.SEND_VALIDATECODE_FAIL);
        }
        System.out.println("發送的手機驗證碼為:" + code);
        //將生成的驗證碼緩存到redis
        jedisPool.getResource().setex(
          telephone + RedisMessageConstant.SENDTYPE_ORDER,5 * 60,code.toString());
        //驗證碼發送成功
        return new Result(true,MessageConstant.SEND_VALIDATECODE_SUCCESS);
    }
}
View Code

頁面中使用DatePicker控件來展示日歷。根據需求,最多可以提前一個月進行體檢預約,所以日歷控件只展示未來一個月的日期

<div class="date">
  <label>體檢日期</label>
  <i class="icon-date" class="picktime"></i>
  <input v-model="orderInfo.orderDate" type="text" class="picktime" readonly>
</div>
<script>
  //日期控件
  var calendar = new datePicker();
  calendar.init({
    'trigger': '.picktime',/*按鈕選擇器,用於觸發彈出插件*/
    'type': 'date',/*模式:date日期;datetime日期時間;time時間;ym年月;*/
    'minDate': getSpecifiedDate(new Date(),1),/*最小日期*/
    'maxDate': getSpecifiedDate(new Date(),30),/*最大日期*/
    'onSubmit': function() { /*確認時觸發事件*/},
    'onClose': function() { /*取消時觸發事件*/ }
  });
</script>
View Code

其中getSpecifiedDate方法定義在healthmobile.js文件中

//獲得指定日期后指定天數的日期
function getSpecifiedDate(date,days) {
    date.setDate(date.getDate() + days);//獲取指定天之后的日期
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    var day = date.getDate();
    return (year + "-" + month + "-" + day);
}

提交預約請求

為提交預約按鈕綁定事件

<div class="box-button">
  <button @click="submitOrder()" type="button" class="btn order-btn">提交預約</button>
</div>
//提交預約
submitOrder(){
  //校驗身份證號格式
  if(!checkIdCard(this.orderInfo.idCard)){
    this.$message.error('身份證號碼輸入錯誤,請重新輸入');
    return ;
  }
  axios.post("/order/submit.do",this.orderInfo).then((response) => {
    if(response.data.flag){
      //預約成功,跳轉到預約成功頁面
      window.location.href="orderSuccess.html?orderId=" + response.data.data;
    }else{
      //預約失敗,提示預約失敗信息
      this.$message.error(response.data.message);
    }
  });
}
View Code

其中checkIdCard方法是在healthmobile.js文件中定義的

/**
 * 身份證號碼校驗
 * 身份證號碼為15位或者18位,15位時全為數字,18位前17位為數字,最后一位是校驗位,可能為數字或字符X
 */
function checkIdCard(idCard){
    var reg = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/;
    if(reg.test(idCard)){
        return true;
    }else{
        return false;
    }
}
View Code

后台代碼

Controller

在health_mobile工程中創建OrderController並提供submitOrder方法

package com.itheima.controller;
​
import com.alibaba.dubbo.config.annotation.Reference;
import com.aliyuncs.exceptions.ClientException;
import com.itheima.constant.MessageConstant;
import com.itheima.constant.RedisConstant;
import com.itheima.constant.RedisMessageConstant;
import com.itheima.entity.Result;
import com.itheima.pojo.Member;
import com.itheima.pojo.Order;
import com.itheima.pojo.Setmeal;
import com.itheima.service.OrderService;
import com.itheima.utils.JedisUtils;
import com.itheima.utils.SMSUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.JedisPool;
import java.util.HashMap;
import java.util.Map;
​
/**
 * 體檢預約
 */
@RestController
@RequestMapping("/order")
public class OrderController {
    @Reference
    private OrderService orderService;
    @Autowired
    private JedisPool jedisPool;
​
    /**
     * 體檢預約
     * @param map
     * @return
     */
    @RequestMapping("/submit")
    public Result submitOrder(@RequestBody Map map){
        String telephone = (String) map.get("telephone");
        //從Redis中獲取緩存的驗證碼,key為手機號+RedisConstant.SENDTYPE_ORDER
        String codeInRedis = jedisPool.getResource().get(
          telephone + RedisMessageConstant.SENDTYPE_ORDER);
        String validateCode = (String) map.get("validateCode");
        //校驗手機驗證碼
        if(codeInRedis == null || !codeInRedis.equals(validateCode)){
            return new Result(false, MessageConstant.VALIDATECODE_ERROR);
        }
        Result result =null;
        //調用體檢預約服務
        try{
            map.put("orderType", Order.ORDERTYPE_WEIXIN);
            result = orderService.order(map);
        }catch (Exception e){
            e.printStackTrace();
            //預約失敗
            return result;
        }
        if(result.isFlag()){
            //預約成功,發送短信通知
            String orderDate = (String) map.get("orderDate");
            try {
                SMSUtils.sendShortMessage(SMSUtils.ORDER_NOTICE,telephone,orderDate);
            } catch (ClientException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
}
View Code

服務接口

在health_interface工程中創建體檢預約服務接口OrderService並提供預約方法

package com.itheima.service;
​
import com.itheima.entity.Result;
import java.util.Map;
/**
 * 體檢預約服務接口
 */
public interface OrderService {
    //體檢預約
    public Result order(Map map) throws Exception;
}

服務實現類

在health_service_provider工程中創建體檢預約服務實現類OrderServiceImpl並實現體檢預約方法。

體檢預約方法處理邏輯比較復雜,需要進行如下業務處理:

1、檢查用戶所選擇的預約日期是否已經提前進行了預約設置,如果沒有設置則無法進行預約

2、檢查用戶所選擇的預約日期是否已經約滿,如果已經約滿則無法預約

3、檢查用戶是否重復預約(同一個用戶在同一天預約了同一個套餐),如果是重復預約則無法完成再次預約

4、檢查當前用戶是否為會員,如果是會員則直接完成預約,如果不是會員則自動完成注冊並進行預約

5、預約成功,更新當日的已預約人數

實現代碼如下:

package com.itheima.service;
​
import com.alibaba.dubbo.config.annotation.Service;
import com.itheima.constant.MessageConstant;
import com.itheima.dao.MemberDao;
import com.itheima.dao.OrderDao;
import com.itheima.dao.OrderSettingDao;
import com.itheima.dao.SetmealDao;
import com.itheima.entity.Result;
import com.itheima.pojo.Member;
import com.itheima.pojo.Order;
import com.itheima.pojo.OrderSetting;
import com.itheima.pojo.Setmeal;
import com.itheima.utils.DateUtils;
import org.apache.poi.ss.usermodel.DateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
​
/**
 * 體檢預約服務
 */
@Service(interfaceClass = OrderService.class)
@Transactional
public class OrderServiceImpl implements OrderService{
    @Autowired
    private OrderSettingDao orderSettingDao;
    @Autowired
    private MemberDao memberDao;
    @Autowired
    private OrderDao orderDao;
  
    //體檢預約
    public Result order(Map map) throws Exception {
        //檢查當前日期是否進行了預約設置
        String orderDate = (String) map.get("orderDate");
        Date date = DateUtils.parseString2Date(orderDate);
        OrderSetting orderSetting = orderSettingDao.findByOrderDate(date);
        if(orderSetting == null){
            return new Result(false, MessageConstant.SELECTED_DATE_CANNOT_ORDER);
        }
      
        //檢查預約日期是否預約已滿
        int number = orderSetting.getNumber();//可預約人數
        int reservations = orderSetting.getReservations();//已預約人數
        if(reservations >= number){
            //預約已滿,不能預約
            return new Result(false,MessageConstant.ORDER_FULL);
        }
      
        //檢查當前用戶是否為會員,根據手機號判斷
        String telephone = (String) map.get("telephone");
        Member member = memberDao.findByTelephone(telephone);
        //防止重復預約
        if(member != null){
            Integer memberId = member.getId();
            int setmealId = Integer.parseInt((String) map.get("setmealId"));
            Order order = new Order(memberId,date,null,null,setmealId);
            List<Order> list = orderDao.findByCondition(order);
            if(list != null && list.size() > 0){
                //已經完成了預約,不能重復預約
                return new Result(false,MessageConstant.HAS_ORDERED);
            }
        }
        
        //可以預約,設置預約人數加一
        orderSetting.setReservations(orderSetting.getReservations()+1);
        orderSettingDao.editReservationsByOrderDate(orderSetting);
​
        if(member == null){
            //當前用戶不是會員,需要添加到會員表
            member = new Member();
            member.setName((String) map.get("name"));
            member.setPhoneNumber(telephone);
            member.setIdCard((String) map.get("idCard"));
            member.setSex((String) map.get("sex"));
            member.setRegTime(new Date());
            memberDao.add(member);
        }
      
        //保存預約信息到預約表
        Order order = new Order(member.getId(),
                                date,
                                (String)map.get("orderType"),
                                Order.ORDERSTATUS_NO,
                                Integer.parseInt((String) map.get("setmealId")));
        orderDao.add(order);
      
        return new Result(true,MessageConstant.ORDER_SUCCESS,order.getId());
    }
}
View Code

 Dao接口

package com.itheima.dao;
​
import com.itheima.pojo.OrderSetting;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
​
public interface OrderSettingDao {
    public void add(OrderSetting orderSetting);
    //更新可預約人數
    public void editNumberByOrderDate(OrderSetting orderSetting);
    //更新已預約人數
    public void editReservationsByOrderDate(OrderSetting orderSetting);
    public long findCountByOrderDate(Date orderDate);
    //根據日期范圍查詢預約設置信息
    public List<OrderSetting> getOrderSettingByMonth(Map date);
    //根據預約日期查詢預約設置信息
    public OrderSetting findByOrderDate(Date orderDate);
}
​
View Code
package com.itheima.dao;
​
import com.github.pagehelper.Page;
import com.itheima.pojo.Member;
import java.util.List;
​
public interface MemberDao {
    public List<Member> findAll();
    public Page<Member> selectByCondition(String queryString);
    public void add(Member member);
    public void deleteById(Integer id);
    public Member findById(Integer id);
    public Member findByTelephone(String telephone);
    public void edit(Member member);
    public Integer findMemberCountBeforeDate(String date);
    public Integer findMemberCountByDate(String date);
    public Integer findMemberCountAfterDate(String date);
    public Integer findMemberTotalCount();
}
View Code
package com.itheima.dao;
​
import com.itheima.pojo.Order;
import java.util.List;
import java.util.Map;
​
public interface OrderDao {
    public void add(Order order);
    public List<Order> findByCondition(Order order);
}
​
View Code

Mapper映射文件

OrderSettingDao.xml

<!--根據日期查詢預約設置信息-->
<select id="findByOrderDate" parameterType="date" resultType="com.itheima.pojo.OrderSetting">
  select * from t_ordersetting where orderDate = #{orderDate}
</select>
<!--更新已預約人數-->
<update id="editReservationsByOrderDate" parameterType="com.itheima.pojo.OrderSetting">
  update t_ordersetting set reservations = #{reservations} where orderDate = #{orderDate}
</update>

MemberDao.xml

<?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.MemberDao" >
    <select id="findAll" resultType="com.itheima.pojo.Member">
        select * from t_member
    </select><!--根據條件查詢-->
    <select id="selectByCondition" 
            parameterType="string" resultType="com.itheima.pojo.Member">
        select * from t_member
        <if test="value != null and value.length > 0">
            where fileNumber = #{value} or phoneNumber = #{value} or name = #{value}
        </if>
    </select><!--新增會員-->
    <insert id="add" parameterType="com.itheima.pojo.Member">
        <selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
            SELECT LAST_INSERT_ID()
        </selectKey>
        insert into 
            t_member
              (fileNumber,name,sex,idCard,phoneNumber,
               regTime,password,email,birthday,remark)
             values
              (#{fileNumber},#{name},#{sex},#{idCard},#{phoneNumber},
               #{regTime},#{password},#{email},#{birthday},#{remark})
    </insert><!--刪除會員-->
    <delete id="deleteById" parameterType="int">
        delete from t_member where id = #{id}
    </delete><!--根據id查詢會員-->
    <select id="findById" parameterType="int" resultType="com.itheima.pojo.Member">
        select * from t_member where id = #{id}
    </select><!--根據id查詢會員-->
    <select id="findByTelephone" 
            parameterType="string" resultType="com.itheima.pojo.Member">
        select * from t_member where phoneNumber = #{phoneNumber}
    </select><!--編輯會員-->
    <update id="edit" parameterType="com.itheima.pojo.Member">
        update t_member
        <set>
            <if test="fileNumber != null">
                fileNumber = #{fileNumber},
            </if>
            <if test="name != null">
                name = #{name},
            </if>
            <if test="sex != null">
                sex = #{sex},
            </if>
            <if test="idCard != null">
                idCard = #{idCard},
            </if>
            <if test="phoneNumber != null">
                phoneNumber = #{phoneNumber},
            </if>
            <if test="regTime != null">
                regTime = #{regTime},
            </if>
            <if test="password != null">
                password = #{password},
            </if>
            <if test="email != null">
                email = #{email},
            </if>
            <if test="birthday != null">
                birthday = #{birthday},
            </if>
            <if test="remark != null">
                remark = #{remark},
            </if>
        </set>
        where id = #{id}
    </update><!--根據日期統計會員數,統計指定日期之前的會員數-->
    <select id="findMemberCountBeforeDate" parameterType="string" resultType="int">
        select count(id) from t_member where regTime &lt;= #{value}
    </select><!--根據日期統計會員數-->
    <select id="findMemberCountByDate" parameterType="string" resultType="int">
        select count(id) from t_member where regTime = #{value}
    </select><!--根據日期統計會員數,統計指定日期之后的會員數-->
    <select id="findMemberCountAfterDate" parameterType="string" resultType="int">
        select count(id) from t_member where regTime &gt;= #{value}
    </select><!--總會員數-->
    <select id="findMemberTotalCount" resultType="int">
        select count(id) from t_member
    </select>
</mapper>
View Code

OrderDao.xml

<?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.OrderDao" >
    <resultMap id="baseResultMap" type="com.itheima.pojo.Order">
        <id column="id" property="id"/>
        <result column="member_id" property="memberId"/>
        <result column="orderDate" property="orderDate"/>
        <result column="orderType" property="orderType"/>
        <result column="orderStatus" property="orderStatus"/>
        <result column="setmeal_id" property="setmealId"/>
    </resultMap>
    <!--新增-->
    <insert id="add" parameterType="com.itheima.pojo.Order">
        <selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
            SELECT LAST_INSERT_ID()
        </selectKey>
        insert into 
            t_order
        (member_id,orderDate,orderType,orderStatus,setmeal_id)
            values 
        (#{memberId},#{orderDate},#{orderType},#{orderStatus},#{setmealId})
    </insert><!--動態條件查詢-->
    <select id="findByCondition" 
            parameterType="com.itheima.pojo.Order" 
            resultMap="baseResultMap">
        select * from t_order
        <where>
            <if test="id != null">
                and id = #{id}
            </if>
            <if test="memberId != null">
                and member_id = #{memberId}
            </if>
            <if test="orderDate != null">
                and orderDate = #{orderDate}
            </if>
            <if test="orderType != null">
                and orderType = #{orderType}
            </if>
            <if test="orderStatus != null">
                and orderStatus = #{orderStatus}
            </if>
            <if test="setmealId != null">
                and setmeal_id = #{setmealId}
            </if>
        </where>
    </select>
</mapper>
View Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM