1.验证码补全
                    //发送验证码
                    sendValidateCode() {
                        /**
                         * 1.手机号不能为空
                         * 2.手机号符合规范
                         * 3.发送一分钟后才可再次发送
                         */
                        //获取手机号
                        let telephone = this.orderInfo.telephone;
                        //验证手机号不能空
                        if (telephone == undefined){
                            this.$message.error("请输入手机号");
                            return null;
                        }
                        //验证手机号格式正确
                        //第一位为1,第二位为3-9,第三位往后九位都为0-9
                        let ref=/^1[3-9][0-9]{9}$/
                        if(!ref.test(telephone)){
                            this.$message.error("手机号格式错误!")
                            return null;
                        }
                        let number = 10;//倒计时的变量
                        let  btn = $("#validateCodeButton");
                        let id = setInterval(function (){
                            //屏蔽按钮,在按钮显示时间的倒计时
                            number --;
                            //jQuery设置标签的属性
                            btn.attr("disabled",true);
                            //修改按钮上的文字
                            btn.val(number+"秒后重新发送");
                            if (number == 0){
                                //终止定时器,按钮还原
                                btn.val("发送验证码");
                                btn.attr("disabled",false);
                                //清空定时器的执行 传递参数id值
                                clearInterval(id)
                            }
                        },1000);
                        axios.get("/SetMealController/sendCode.do?telephone="+telephone).then(response=>{
                            if (response.data.flag){
                                this.code=response.data.data
                                console.log(response.data.data)
                            }
                        })
                },发送验证码需要验证手机号格式是否正确,使用正则表达式
let ref=/^1[3-9][0-9]{9}$/ 
实现手机号规则判断
并实现了验证码隔时发送,使用JS的
setInterval
计时器,循环减少设置的倒计时,并在期间屏蔽发送按钮
btn.attr("disabled",true); 
通过更改其"disabled"属性的值实现;
使用JQuery的ID选择器
let  btn = $("#validateCodeButton"); 
实现对按钮的选择
后端如下:
   /**
     * 接收手机号,发送验证码
     * @param telephone
     * @return
     * 调用工具类发送验证码
     * 产生4位随机数
     * 发送成功,在Redis中存储一份验证码,设置5分钟过期(校验验证是否正确)
     */
    @GetMapping("/sendCode")
    public Result sendCode(String telephone){
        Integer capstr= ValidateCodeUtils.generateValidateCode(4);
        try {
            SMSUtils.sendShortMessage(SMSUtils.VALIDATE_CODE,telephone, String.valueOf(capstr));
            Jedis jedis=jedisPool.getResource();
            jedis.setex(telephone+ RedisConstant.SENDTYPE_ORDER,60*5,capstr+"");
            jedis.close();
            return new Result(true, MessageConstant.SEND_VALIDATECODE_SUCCESS);
        } catch (ClientException e) {
            e.printStackTrace();
            return new Result(false, MessageConstant.SEND_VALIDATECODE_FAIL);
        }
    }
}通过telephone拼接键,作为Key,将Redis中的键值对做对比,返回正确的信息;
2.预约套餐逻辑实现
1.前端验证表单数据的完整和正确性
                    //提交预约
                    submitOrder(){
                        /**
                         * 校验表单数据
                         * 1.姓名不能为空且大于一个字符
                         * 2.手机号不能为空且符合规范
                         * 3.身份证位数合适且符合规范
                         * 4.验证码不能为空
                         */
                     if (this.orderInfo.name===undefined){
                         this.$message.error("请填写姓名");
                         return ;
                     }
                     if (this.orderInfo.name.length<2){
                         this.$message.error("姓名不能少于2个字");
                         return ;
                     }
                        // let reg = /^[\u4E00-\u9FA5]+$/;
                        // if (!reg.test(name)){
                        //     this.$message.error("姓名必须是汉字");
                        //     return ;
                        // }
                        //手机号和验证码,写了就行
                        let telephone = this.orderInfo.telephone;
                        if (telephone == undefined){
                            this.$message.error("请输入手机号");
                            return ;
                        }
                        reg = /^1[3-9][0-9]{9}$/;
                        //正则表达式方法,test(被检测字符串),正则匹配成功返回true
                        if( ! reg.test(telephone)){
                            this.$message.error("手机号格式错误");
                            return ;
                        }
                        if (this.orderInfo.validateCode == undefined){
                            this.$message.error("请填写验证码");
                            return ;
                        }
                        let idCard = this.orderInfo.idCard;
                        if (idCard == undefined){
                            this.$message.error("请填写身份证号");
                            return ;
                        }
                        //验证身份证号
                        reg=/^[1-6][0-9]{16}[0-9X]$/
                        if (!reg.test(idCard)){
                            this.$message.error("身份证号格式错误");
                            return ;
                        }
                        //验证预约日期,JS的日历,用户只能选择,不能修改
                        if (this.orderInfo.orderDate == undefined){
                            this.$message.error("请选择预约日期");
                            return ;
                        }
                        axios.post("/OrderController/submitOrder.do",this.orderInfo).then(res=>{
                            if (res.data.flag){
                                this.$message.success(res.data.message);
                                location.href="orderSuccess.html"
                            }else {
                                this.$message.error(res.data.message);
                            }}
                        )
                    },复杂判断基本使用正则表达式,大X为身份证的10,拼接到9后
2.后端逻辑实现代码:
 /**
     *    {"setmealId":"13","sex":"1","name":"石松","telephone":"13800138000",
     *  "validateCode":"1234","idCard":"123456789012345678","orderDate":"2024-10-25"}
     *  保存预约数据
     *  体检预约方法处理逻辑比较复杂,需要进行如下业务处理:
     *
     * 1、检查用户所选择的预约日期是否已经提前进行了预约设置,如果没有设置则无法进行预约  t_ordersetting
     *
     * 2、检查用户所选择的预约日期是否已经约满,如果已经约满则无法预约 t_ordersetting
     *
     * 3、检查当前用户是否为会员,如果是会员则直接完成预约,如果不是会员则自动完成注册并进行预约 t_member
     * 4、检查用户是否重复预约(同一个用户在同一天预约了同一个套餐),如果是重复预约则无法完成再次预约  t_order
     *
     * 5、预约成功,更新当日的已预约人数 t_ordersetting
     */1、检查用户所选择的预约日期是否已经提前进行了预约设置,如果没有设置则无法进行预约 t_ordersetting
OrderSetting orderSetting =orderSettingMapper.queryOrderSettingByOrderDate(map.get("orderDate"));<select id="queryOrderSettingByOrderDate" parameterType="String" resultType="orderSetting">
    select id,orderDate,number,reservations from t_ordersetting
    where orderDate = #{orderDate}
</select>  //预约日期查询结果是 null
        if(orderSetting == null){
            return new Result(false, MessageConstant.SELECTED_DATE_CANNOT_ORDER);
        }
        //2、检查用户所选择的预约日期是否已经约满,如果已经约满则无法预约 t_ordersetting
        //orderSetting对象中的 number值大于reservations值,就可以预约
        if (orderSetting.getReservations() >= orderSetting.getNumber()) {
            return new Result(false, MessageConstant.ORDER_FULL);
        }预设为空则不能预约
预设的预约值大于等于全部值,预约已满
2、检查当前用户是否为会员,如果是会员则直接完成预约,如果不是会员则自动完成注册并进行预约 t_member
Member member =memberMapper.ifMember(map.get("telephone"));
        if (member!=null){//是会员,查看是否约过
            try {
                Order order = new Order();
                order.setSetmealId(Integer.parseInt(map.get("setmealId")));//存储套餐ID
                order.setOrderDate(Date2Utils.parseString2Date(map.get("orderDate")));//存储预约的日期
                order.setMemberId(member.getId());//存储用户的ID
                int count  = orderMapper.queryOrderByMember(order);
                if (count!=0){
                    return new Result(false,MessageConstant.HAS_ORDERED);
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
        if (member==null){//不是会员,肯定没约过,直接帮他注册帮他约
            //mapper成注册会员
            member=new Member();
            member.setName(map.get("name"));
            member.setSex(map.get("sex"));
            member.setIdCard(map.get("idCard"));
            member.setPhoneNumber(map.get("telephone"));
            member.setRegTime(new Date());
            //mapper层,会员的数据写入到会员表
            memberMapper.addMember(member);
        }若是会员,则查看会员当天是否约过此类型的套餐,SQL语句
 @Select("select count(0) from t_order " +
            "where member_id = #{memberId}  " +
            "and orderDate=#{orderDate}  " +
            "and setmeal_id = #{setmealId} ")
    int queryOrderByMember(Order order);需要会员id,当天日期和套餐id
若不是会员,则直接注册会员
 if (member==null){//不是会员,肯定没约过,直接帮他注册帮他约
            //mapper成注册会员
            member=new Member();
            member.setName(map.get("name"));
            member.setSex(map.get("sex"));
            member.setIdCard(map.get("idCard"));
            member.setPhoneNumber(map.get("telephone"));
            member.setRegTime(new Date());
            //mapper层,会员的数据写入到会员表
            memberMapper.addMember(member);
        }3、预约成功,更新当日的已预约人数 t_ordersetting
 orderSettingMapper.updatareservations(map.get("orderDate"));
        Order order = new Order();
        try {
            order.setOrderDate(Date2Utils.parseString2Date(map.get("orderDate")));//设置预约日期
            order.setSetmealId(Integer.parseInt(map.get("setmealId")));//设置套餐ID
            order.setOrderStatus(Order.ORDERSTATUS_NO);
            order.setOrderType(Order.ORDERTYPE_WEIXIN);
            //设置会员的Id
            order.setMemberId(member.getId());
            orderMapper.addOrder(order);
            return new Result(true,MessageConstant.ORDER_SUCCESS,order.getId());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }补上其他大佬发现的问题及解决办法




















