基于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";
}
}