云健康项目之预约管理后端和页面

举报
tea_year 发表于 2025/10/28 10:47:27 2025/10/28
【摘要】 体检预约流程 用户可以通过如下操作流程进行体检预约: 1、在移动端首页点击体检预约,页面跳转到套餐列表页面 2、在套餐列表页面点击要预约的套餐,页面跳转到套餐详情页面 3、在套餐详情页面点击立即预约,页面跳转到预约页面 4、在预约页面录入体检人信息,包括手机号,点击发送验证码 5、在预约页面录入收到的手机短信验证码,点击提交预约,完成体检预约后台代码1 Controller在health_m...

体检预约流程 用户可以通过如下操作流程进行体检预约:

1、在移动端首页点击体检预约,页面跳转到套餐列表页面

2、在套餐列表页面点击要预约的套餐,页面跳转到套餐详情页面

3、在套餐详情页面点击立即预约,页面跳转到预约页面

4、在预约页面录入体检人信息,包括手机号,点击发送验证码

5、在预约页面录入收到的手机短信验证码,点击提交预约,完成体检预约

后台代码

1 Controller

在health_mobile工程中创建OrderController并提供submitOrder方法


/**
 * 体检预约
 */
@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;
    }
}

2 服务接口

在health_interface工程中创建体检预约服务接口OrderService并提供预约方法

/**
 * 体检预约服务接口
 */
public interface OrderService {
    //体检预约
    public Result order(Map map) throws Exception;
}

3 服务实现类

在health_service_provider工程中创建体检预约服务实现类OrderServiceImpl并实现体检预约方法。

体检预约方法处理逻辑比较复杂,需要进行如下业务处理:

1、检查用户所选择的预约日期是否已经提前进行了预约设置,如果没有设置则无法进行预约

2、检查用户所选择的预约日期是否已经约满,如果已经约满则无法预约

3、检查用户是否重复预约(同一个用户在同一天预约了同一个套餐),如果是重复预约则无法完成再次预约

4、检查当前用户是否为会员,如果是会员则直接完成预约,如果不是会员则自动完成注册并进行预约

5、预约成功,更新当日的已预约人数

实现代码如下:


/**
 * 体检预约服务
 */
@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());
    }
}

4 Dao接口

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);
}
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();
}
public interface OrderDao {
    public void add(Order order);
    public List<Order> findByCondition(Order order);
}

5 Mapper映射文件

OrderSettingDao.xml

<!--根据日期查询预约设置信息-->
<select id="findByOrderDate" parameterType="date" resultType="com.yunhe.pojo.OrderSetting">
  select * from t_ordersetting where orderDate = #{orderDate}
</select>
<!--更新已预约人数-->
<update id="editReservationsByOrderDate" parameterType="com.yunhe.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.yunhe.dao.MemberDao" >
    <select id="findAll" resultType="com.yunhe.pojo.Member">
        select * from t_member
    </select>

    <!--根据条件查询-->
    <select id="selectByCondition" 
            parameterType="string" resultType="com.yunhe.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.yunhe.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.yunhe.pojo.Member">
        select * from t_member where id = #{id}
    </select>

    <!--根据id查询会员-->
    <select id="findByTelephone" 
            parameterType="string" resultType="com.yunhe.pojo.Member">
        select * from t_member where phoneNumber = #{phoneNumber}
    </select>

    <!--编辑会员-->
    <update id="edit" parameterType="com.yunhe.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>

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.yunhe.dao.OrderDao" >
    <resultMap id="baseResultMap" type="com.yunhe.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.yunhe.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.yunhe.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>

3. 预约成功页面展示

前面已经完成了体检预约,预约成功后页面会跳转到成功提示页面(orderSuccess.html)并展示预约的相关信息(体检人、体检套餐、体检时间等)。

3.1 页面调整

提供orderSuccess.html页面,展示预约成功后相关信息

<div class="info-title">
  <span class="name">体检预约成功</span>
</div>
<div class="notice-item">
  <div class="item-title">预约信息</div>
  <div class="item-content">
    <p>体检人:{{orderInfo.member}}</p>
    <p>体检套餐:{{orderInfo.setmeal}}</p>
    <p>体检日期:{{orderInfo.orderDate}}</p>
    <p>预约类型:{{orderInfo.orderType}}</p>
  </div>
</div>
<script>
  //从请求URL根据参数名获取对应值,orderId为预约id
  var id = getUrlParam("orderId");
</script>
<script>
  var vue = new Vue({
    el:'#app',
    data:{
      orderInfo:{}
    },
    mounted(){
      axios.post("/order/findById.do?id=" + id).then((response) => {
        this.orderInfo = response.data.data;
      });
    }
  });
</script>

3.2 后台代码

3.2.1 Controller

在OrderController中提供findById方法,根据预约id查询预约相关信息

/**
 * 根据id查询预约信息,包括套餐信息和会员信息
 * @param id
 * @return
*/
@RequestMapping("/findById")
public Result findById(Integer id){
  try{
    Map map = orderService.findById(id);
    //查询预约信息成功
    return new Result(true,MessageConstant.QUERY_ORDER_SUCCESS,map);
  }catch (Exception e){
    e.printStackTrace();
    //查询预约信息失败
    return new Result(false,MessageConstant.QUERY_ORDER_FAIL);
  }
}

3.2.2 服务接口

在OrderService服务接口中扩展findById方法

//根据id查询预约信息,包括体检人信息、套餐信息
public Map findById(Integer id) throws Exception;

3.2.3 服务实现类

在OrderServiceImpl服务实现类中实现findById方法

//根据id查询预约信息,包括体检人信息、套餐信息
public Map findById(Integer id) throws Exception {
  Map map = orderDao.findById4Detail(id);
  if(map != null){
    //处理日期格式
    Date orderDate = (Date) map.get("orderDate");
    map.put("orderDate",DateUtils.parseDate2String(orderDate));
  }
  return map;
}

3.2.4 Dao接口

在OrderDao接口中扩展findById4Detail方法

public Map findById4Detail(Integer id);

3.2.5 Mapper映射文件

在OrderDao.xml映射文件中提供SQL语句

<!--根据预约id查询预约信息,包括体检人信息、套餐信息-->
<select id="findById4Detail" parameterType="int" resultType="map">
  select m.name member ,s.name setmeal,o.orderDate orderDate,o.orderType orderType
  from
  t_order o,
  t_member m,
  t_setmeal s
  where o.member_id=m.id and o.setmeal_id=s.id and o.id=#{id}
</select>

小结

体检预约功能实现 “五步法” 前端流程(首页→套餐列表→详情→预约页→提交),后端以分层架构支撑核心逻辑。​
后端核心为 OrderController,submitOrder 方法先从 Redis 校验验证码,再调用 OrderService;服务层通过五层校验(日期设置、预约满额、重复预约、会员判断、人数更新)处理业务,非会员自动注册,最后保存预约记录;Dao 层借助 MyBatis 映射文件,实现 Order、Member、OrderSetting 表的 CRUD,如 OrderDao.xml 的多表联查。​
预约成功后,前端 orderSuccess.html 通过 Vue+Axios 获取订单 ID,请求 /findById 接口;后端 OrderService.findById 方法联表查询预约、会员、套餐信息,处理日期格式后返回,实现信息展示。整体技术栈融合 SpringMVC、MyBatis、Redis,保障流程闭环与数据安全。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。