基于Spring+SpringMvc+Hibernate的医院门诊在线挂号系统

通过需求分析和为系统实现而需要添加的功能,将系统分解成合适的功能模块层次图,使用系统的用户分为三种:管理员、患者和医生。管理员具有最高的使用权限,可以使用全部功能;患者可以注册、自助挂号、修改个人信息、查询系统提供的各种信息等。医生只是对患者的挂号信息进行审批和修改个人信息。
本系统的功能结构图所示。
 
图3.1医院在线挂号系统总体功能模块图
 
图3.2管理员子系统功能模块图
 
图3.3医生子系统功能模块图
 
图3.4患者子系统功能模块图
3.2.2 系统模块描述 
系统模块的描述主要是通过使用文字去描述系统模块的功能和处理,而不是用图形描述。
1.管理员子系统
管理员主要是对系统中的数据进行管理:科室管理、医生管理、患者信息管理、挂号管理、医院信息管理、管理员管理。
(1)科室管理
管理员查询管理医院的科室信息。
(2)医生管理
管理员查询管理医生的信息。
(3)患者信息管理
管理员对患者信息进行管理。
(4)管理员管理
系统管理员对软件操作人员进行管理。
(5)医院信息管理
管理员对医院信息进行管理。
(6)挂号管理
管理员对患者的自助挂号信息进行管理。
2.患者子系统
患者子系统主要完成患者注册、自助挂号、预约信息查询、修改个人信息等。
(1)患者注册
新患者注册成为系统的用户方可进入系统挂号。
(2)自助挂号
患者通过挂号机自助完成挂号操作。
(3)预约信息查询
患者查询自己的预约挂号审批信息。
(4)修改个人信息
登录系统的患者修改个人的信息。
3.医生子系统
医生子系统的功能:挂号审批、审批记录查询、修改个人信息。
(1)挂号审批
医生对患者的挂号信息进行审批。
(2)审批记录查询
医生查询已经审批的挂号记录信息。
(3)修改个人信息
登录系统的医生修改个人信息。
4.3管理员子系统的设计和实现
4.3.1 系统登录页面
为了保证系统的安全,系统对登录用户进行身份验证,用户需要输入用户和密码,同时选择相应的身份类型。只有正确的用户和密码的用户才能进入系统。
 登录页面对应的磁盘文件为index.jsp,页面设计如图4.4所示:

 
图4.4系统登录页面
4.3.2 管理员子系统主页面
管理员子系统主要负责对医院门诊在线挂号系统中的医院信息、科室信息、医生信息、患者信息、挂号信息等的全面管理,如:添加修改删除各种数据信息,根据医院的实际情况对人员按所属的部门进行管理。共包括六个子功能模块:科室管理,医生管理,医院信息管理,挂号信息管理,患者信息管理,管理员管理。
 
图4.5管理员子系统主页面
4.3.3 医院管理页面
管理员对医院的信息进行添加修改删除管理。
 1.医院管理主页面,在主页面中显示全部的医院信息,对应的磁盘文件为servlet/HospitalServlet?method=findAllhospotal&flag=1,页面设计如图4.6所示:
 
图4.6医院管理主页面
 2.在主页面中点击添加按钮进入添加医院信息页面,对应的磁盘文件为servlet/HospitalServlet?method=addHospital,页面设计如图4.7所示:
 
图4.7添加医院信息页面
4.3.4 科室管理页面
管理员对医院的科室信息进行添加修改删除管理。
 1.科室管理主页面,在主页面中显示全部的科室信息,对应的磁盘文件为servlet/DeskServlet?method=findAllDesk,页面设计如图4.8所示:
 
图4.8科室管理主页面
 2.在主页面中点击添加按钮进入添加科室信息页面,对应的磁盘文件为servlet/DeskServlet?method=addDesk,页面设计如图4.9所示:
 
图4.9添加科室信息页面
4.3.5 医生管理页面
管理员对医生信息进行添加修改删除管理。
 1.医生管理主页面,在主页面中显示全部的医生信息,对应的磁盘文件为servlet/DoctorServlet?method=findAllDoctor&flag=1,页面设计如图4.10所示:
 
图4.10医生管理主页面
 2.在主页面中点击添加按钮进入添加医生信息页面,对应的磁盘文件为servlet/DoctorServlet?method=addDoctor,页面设计如图4.11所示:
 
图4.11添加医生信息页面
4.3.6 患者管理页面
管理员对注册的患者信息进行查看和删除管理。在页面中显示全部的患者信息,对应的磁盘文件为servlet/PatientServlet?method=findAllPatient&flag=1,页面设计如图4.12所示:
 
图4.12患者管理页面
4.3.7 挂号管理页面
管理员对患者的挂号信息进行查看和删除管理。在页面中显示全部的患者挂号信息,对应的磁盘文件为servlet/BespeakServlet?method=findAllBespeak&flag=1,页面设计如图4.13所示:
 
图4.13挂号管理页面


4.3.8 管理员管理页面
管理员对使用系统的管理员信息进行添加修改删除管理。
 1.管理员管理主页面,在主页面中显示全部的管理员信息,对应的磁盘文件为servlet/UsersServlet?method=findAllUsers&flag=,页面设计如图4.14所示:
 
图4.14管理员管理主页面
 2.在主页面中点击添加按钮进入添加管理员信息页面,对应的磁盘文件为servlet/UsersServlet?method=addUsers,页面设计如图4.15所示:
 
图4.15添加管理员信息页面
4.4患者子系统的设计和实现
4.4.1 患者注册
新患者只有通过注册获得用户名和密码,才可以登陆系统。在系统的登陆页面中点击注册按钮,进入患者注册页面。在注册页面中输入患者的相应信息,用户名和密码用于登陆系统。对应的磁盘文件为servlet/PatientServlet?method=add Patient&flag=2,页面设计如图4.16所示:
 
图4.16患者注册页面
4.4.2 患者子系统主页面
患者输入注册的用户名和密码登陆系统。在子系统主页中显示患者子系统的功能模块。对应的磁盘文件为pages/sy.jsp,页面设计如图4.17所示:
 
图4.17患者子系统主页面
4.4.3 预约挂号页面
患者在主页面中点击预约挂号菜单,进入预约挂号页面。在医生列表中根据主治范围和科室等信息选择相应的医生信息,输入预约日期和时间。对应的磁盘文件为servlet/BespeakServlet?method=addBespeak&flag=3,页面设计如图4.18所示:
 
图4.18预约挂号页面
4.4.4 预约信息页面
患者在主页面中点击预约信息菜单,进入预约信息页面。
1.在预约信息页面中显示全部的预约信息。对应的磁盘文件为servlet/BespeakServlet?method=findAllBespeak& flag=3,页面设计如图4.19所示:
 
图4.19预约信息页面
2.在预约信息页面中点击某个预约详细信息的查看按钮,进入该预约挂号的详细信息页面中。对应的磁盘文件为servlet/BespeakServlet?method=findAllB espeak& besid=38& a=1&flag=3,页面设计如图4.20所示:
 
图4.20预约详细信息页面
4.4.5 修改患者个人信息页面
患者在主页面中点击修改个人信息菜单,进入修改患者个人信息页面。在页面中输入相应的修改信息,对应的磁盘文件为servlet/PatientServlet?method= updatePage&pid=38& flag=3,页面设计如图4.21所示:
 
图4.21修改个人信息页面
4.5医生子系统的设计和实现


4.5.1 医生子系统主页面
医生子系统主要对患者的预约信息进行审核、查询已审核记录和修改个人信息。在子系统主页中显示医生子系统的功能模块。对应的磁盘文件为pages/sy.jsp,页面设计如图4.22所示:
 
图4.22医生子系统主页面
4.5.2 挂号审批页面
挂号审批页面是医生对患者的预约挂号信息进行审批,即对患者的预约信息进行认可,可以按期进行就诊。对应的磁盘文件为servlet/BespeakServlet?method= findAll Bespeak& flag=2,页面设计如图4.23所示:
 
图4.23挂号审批页面
4.5.3 已审批记录页面
医生查询已经通过审批的预约信息,也可以对已经审批的预约信息进行未通过审核操作。对应的磁盘文件为servlet/BespeakServlet?method=findAll Bespeak&flag=2&b=1,页面设计如图4.24所示:
 
图4.24已审批记录页面
4.5.4 修改个人信息页面
登陆系统的医生可以修改个人信息。对应的磁盘文件为servlet/ DoctorServlet ?method=updateMyPage&did=25,页面设计如图4.25所示:
 
图4.25修改个人信息页面

package com.lyh.flowers.controller;


import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Properties;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.lyh.flowers.pojo.CartItem;
import com.lyh.flowers.pojo.Flower;
import com.lyh.flowers.pojo.Order;
import com.lyh.flowers.pojo.OrderItem;
import com.lyh.flowers.pojo.PageBean;
import com.lyh.flowers.pojo.User;
import com.lyh.flowers.service.impl.AddressServiceImpl;
import com.lyh.flowers.service.impl.CartServiceImpl;
import com.lyh.flowers.service.impl.FlowerServiceImpl;
import com.lyh.flowers.service.impl.OrderServiceImpl;
import com.lyh.flowers.util.tools;

@Controller
@RequestMapping("/order")
public class OrderController {
    
    @Resource
    private OrderServiceImpl orderService;
    @Resource
    private CartServiceImpl cartService;
    @Resource
    private FlowerServiceImpl flowerService;
    @Resource
    private AddressServiceImpl addressService;
    
//    /**
//     * 返回一个不重复的字符串
//     * @return
//     */
//    public static String uuid() {
//        return UUID.randomUUID().toString().replace("-", "").toUpperCase();
//    }
    
    /**
     * 获取当前页码
     */
    private int getPc(HttpServletRequest req) {
        int pc = 1;
        String param = req.getParameter("pc");
        if(param != null && !param.trim().isEmpty()) {
            try {
                pc = Integer.parseInt(param);
            } catch(RuntimeException e) {}
        }
        return pc;
    }
    
    /**
     * 截取url,页面中的分页导航中需要使用它做为超链接的目标!
     */
    private String getUrl(HttpServletRequest req) {
        String url = req.getRequestURI() + "?" + req.getQueryString();
        /*
         * 如果url中存在pc参数,截取掉,如果不存在那就不用截取。
         */
        int index = url.lastIndexOf("&pc=");
        if(index != -1) {
            url = url.substring(0, index);
        }
        return url;
    }
    
    @RequestMapping(value="/orderlist",method={RequestMethod.GET})
    public String orderList(HttpServletRequest request,Model model){
        int pc = getPc(request);
        
        String url = getUrl(request);
        
        User user = (User)request.getSession().getAttribute("sessionUser");
        
        PageBean<Order> pb = orderService.myOrders(user.getUid(), pc);
        
        pb.setUrl(url);
        model.addAttribute("pb", pb);
        
        return "order/list";
    }
    
    @RequestMapping(value="/createOrder/{cartItemIds}",method={RequestMethod.POST})
    public String createOrder(@PathVariable String cartItemIds,HttpServletRequest request,Model model){
        /*
         * 1. 获取所有购物车条目的id,查询之
         */
        List<CartItem> cartItemList=new ArrayList<CartItem>();
        
        String[] cartItemIdArray = cartItemIds.split(",");
        String addressId = request.getParameter("addressId");
//        System.out.println("addressId:"+addressId);
        
        for(String cItemId:cartItemIdArray){
            CartItem cartItem=cartService.loadCartItem(cItemId);
            Flower flower=flowerService.findByFid(cartItem.getFid());
            cartItem.setFlower(flower);
            cartItemList.add(cartItem);
        }
        if(cartItemList.size() == 0) {
            model.addAttribute("code", "error");
            model.addAttribute("msg", "您没有选择要购买的鲜花,不能下单!");
            return "mainFrame/msg";
        }
        /*
         * 2. 创建Order
         */
        Order order = new Order();
        order.setOid(tools.uuid());//设置主键
        order.setOrdertime(String.format("%tF %<tT", new Date()));//下单时间
        order.setStatus(1);//设置状态,1表示未付款
        order.setAdid(addressId);
        order.setAddress(addressService.findByAdid(addressId));
//        order.setAddress(request.getParameter("address"));//设置收货地址
//        order.setName(request.getParameter("name"));
//        order.setPhone(request.getParameter("phone"));
        
        User owner = (User)request.getSession().getAttribute("sessionUser");
        
        order.setOwner(owner);//设置订单所有者
        order.setUid(owner.getUid());
        
        BigDecimal total = new BigDecimal("0");
        for(CartItem cartItem : cartItemList) {
            total = total.add(new BigDecimal(cartItem.getSubtotal() + ""));
        }
        order.setTotal(total.doubleValue());//设置总计
        
        /*
         * 3. 创建List<OrderItem>
         * 一个CartItem对应一个OrderItem
         */
        List<OrderItem> orderItemList = new ArrayList<OrderItem>();
        for(CartItem cartItem : cartItemList) {
            OrderItem orderItem = new OrderItem();
            orderItem.setOrderItemId(tools.uuid());//设置主键
            orderItem.setQuantity(cartItem.getQuantity());
            orderItem.setSubtotal(cartItem.getSubtotal());
            orderItem.setFlower(cartItem.getFlower());
            orderItem.setOrder(order);
            orderItemList.add(orderItem);
        }
        order.setOrderItemList(orderItemList);
        
        /*
         * 4. 调用service完成添加
         */
        orderService.createOrder(order);
        orderService.addOrderItem(orderItemList);
        // 删除购物车条目
        for(String cItemId:cartItemIdArray){
            cartService.delete(cItemId);
        }
        request.setAttribute("order", order);
        return "order/ordersucc";
    }
    
    //支付准备
    @RequestMapping("/paymentPre/{oid}")
    public String paymentPre(@PathVariable String oid,HttpServletRequest request,Model model){
        model.addAttribute("order", orderService.load(oid));
        return "order/pay";
    }
    
    //支付方法
    @RequestMapping("/payment/{oid}")
    public String payment(@PathVariable String oid,HttpServletRequest request,HttpServletResponse response,Model model) throws IOException{
        Properties props = new Properties();
        props.load(this.getClass().getClassLoader().getResourceAsStream("payment.properties"));
        /*
         * 1. 准备13个参数
         */
        String p0_Cmd = "Buy";//业务类型,固定值Buy
        String p1_MerId = props.getProperty("p1_MerId");//商号编码,在易宝的唯一标识
        String p2_Order = oid;//订单编码
        String p3_Amt = "0.01";//支付金额
        String p4_Cur = "CNY";//交易币种,固定值CNY
        String p5_Pid = "";//商品名称
        String p6_Pcat = "";//商品种类
        String p7_Pdesc = "";//商品描述
        String p8_Url = props.getProperty("p8_Url");//在支付成功后,易宝会访问这个地址。
        String p9_SAF = "";//送货地址
        String pa_MP = "";//扩展信息
        String pd_FrpId = request.getParameter("yh");//支付通道
        String pr_NeedResponse = "1";//应答机制,固定值1
        
        /*
         * 2. 计算hmac
         * 需要13个参数
         * 需要keyValue
         * 需要加密算法
         */
        String keyValue = props.getProperty("keyValue");
        String hmac = PaymentUtil.buildHmac(p0_Cmd, p1_MerId, p2_Order, p3_Amt,
                p4_Cur, p5_Pid, p6_Pcat, p7_Pdesc, p8_Url, p9_SAF, pa_MP,
                pd_FrpId, pr_NeedResponse, keyValue);
        
        /*
         * 3. 重定向到易宝的支付网关
         */
        StringBuilder sb = new StringBuilder("https://www.yeepay.com/app-merchant-proxy/node");
        sb.append("?").append("p0_Cmd=").append(p0_Cmd);
        sb.append("&").append("p1_MerId=").append(p1_MerId);
        sb.append("&").append("p2_Order=").append(p2_Order);
        sb.append("&").append("p3_Amt=").append(p3_Amt);
        sb.append("&").append("p4_Cur=").append(p4_Cur);
        sb.append("&").append("p5_Pid=").append(p5_Pid);
        sb.append("&").append("p6_Pcat=").append(p6_Pcat);
        sb.append("&").append("p7_Pdesc=").append(p7_Pdesc);
        sb.append("&").append("p8_Url=").append(p8_Url);
        sb.append("&").append("p9_SAF=").append(p9_SAF);
        sb.append("&").append("pa_MP=").append(pa_MP);
        sb.append("&").append("pd_FrpId=").append(pd_FrpId);
        sb.append("&").append("pr_NeedResponse=").append(pr_NeedResponse);
        sb.append("&").append("hmac=").append(hmac);
        
        response.sendRedirect(sb.toString());
        
        
        return null;
    }
    
    /**
     * 回馈方法
     * 当支付成功时,易宝会访问这里
     * 用两种方法访问:
     * 1. 引导用户的浏览器重定向(如果用户关闭了浏览器,就不能访问这里了)
     * 2. 易宝的服务器会使用点对点通讯的方法访问这个方法。(必须回馈success,不然易宝服务器会一直调用这个方法)
     */
    @RequestMapping("/back")
    public String back(HttpServletRequest request,HttpServletResponse response,Model model) throws IOException{
        /*
         * 1. 获取12个参数
         */
        String p1_MerId = request.getParameter("p1_MerId");
        String r0_Cmd = request.getParameter("r0_Cmd");
        String r1_Code = request.getParameter("r1_Code");
        String r2_TrxId = request.getParameter("r2_TrxId");
        String r3_Amt = request.getParameter("r3_Amt");
        String r4_Cur = request.getParameter("r4_Cur");
        String r5_Pid = request.getParameter("r5_Pid");
        String r6_Order = request.getParameter("r6_Order");
        String r7_Uid = request.getParameter("r7_Uid");
        String r8_MP = request.getParameter("r8_MP");
        String r9_BType = request.getParameter("r9_BType");
        String hmac = request.getParameter("hmac");
        /*
         * 2. 获取keyValue
         */
        Properties props = new Properties();
        props.load(this.getClass().getClassLoader().getResourceAsStream("payment.properties"));
        String keyValue = props.getProperty("keyValue");
        /*
         * 3. 调用PaymentUtil的校验方法来校验调用者的身份
         *   >如果校验失败:保存错误信息,转发到msg.jsp
         *   >如果校验通过:
         *     * 判断访问的方法是重定向还是点对点,如果要是重定向
         *     修改订单状态,保存成功信息,转发到msg.jsp
         *     * 如果是点对点:修改订单状态,返回success
         */
        boolean bool = PaymentUtil.verifyCallback(hmac, p1_MerId, r0_Cmd, r1_Code, r2_TrxId,
                r3_Amt, r4_Cur, r5_Pid, r6_Order, r7_Uid, r8_MP, r9_BType,
                keyValue);
        if(!bool) {
            request.setAttribute("code", "error");
            request.setAttribute("msg", "无效的签名,支付失败!");
            return "mainFrame/msg";
        }
        if(r1_Code.equals("1")) {
            orderService.updateStatus(r6_Order, 2);//修改订单状态
            if(r9_BType.equals("1")) {
                request.setAttribute("code", "success");
                request.setAttribute("msg", "恭喜您,支付成功!");
                return "mainFrame/msg";                
            } else if(r9_BType.equals("2")) {
                response.getWriter().print("success");
            }
        }
        return null;
    }
        
    
    //订单详情
    @RequestMapping("/desc/{oid}")
    public String desc(@PathVariable String oid,HttpServletRequest request,Model model){
        Order order = orderService.load(oid);
//        Address address=addressService.findByAdid(order.getAdid());
        
        order.setAddress(addressService.findByAdid(order.getAdid()));
        
        model.addAttribute("order", order);
        
//        System.out.println("address:"+address.getAdcity());
        
        String btn = request.getParameter("btn");//btn说明了用户点击哪个超链接来访问本方法的
        model.addAttribute("btn", btn);
        
        return "order/desc";
    }
    
    @RequestMapping("/cancle/{oid}")
    public String cancle(@PathVariable String oid,HttpServletRequest request,Model model){
        /*
         * 校验订单状态
         */
        int status = orderService.findStatus(oid);
        if(status != 1) {
            request.setAttribute("code", "error");
            request.setAttribute("msg", "状态不对,不能取消!");
            return "mainFrame/msg";
        }
        orderService.updateStatus(oid, 5);//设置状态为取消!
        request.setAttribute("code", "success");
        request.setAttribute("msg", "您的订单已取消");
        
        return "redirect:/order/orderlist";
//        return "mainFrame/msg";
    }
    
    @RequestMapping("/confirm/{oid}")
    public String confirm(@PathVariable String oid,HttpServletRequest request,Model model){
        /*
         * 校验订单状态
         */
        int status = orderService.findStatus(oid);
        if(status != 3) {
            request.setAttribute("code", "error");
            request.setAttribute("msg", "状态不对,不能确认收货!");
            return "mainFrame/msg";
        }
        orderService.updateStatus(oid, 4);//设置状态为取消!
        request.setAttribute("code", "success");
        request.setAttribute("msg", "恭喜,交易成功!");
        
        return "redirect:/order/orderlist";
//        return "mainFrame/msg";
    }
    
    
    
    @RequestMapping("/ordersucc")
    public String ordersucc(HttpServletRequest request,Model model){
        return "order/ordersucc";
    }
    

     }