基于SpringBoot+VUE的宠物医院后台管理系统【源码开源】【建议收藏】
基于SpringBoot+VUE的宠物医院后台管理系统【源码开源】【建议收藏】
今天给大家开源一个基于SpringBoot+VUE的宠物医院后台管理系统,系统基于脚手架工程,花了大概1周时间做出来的。
该系统完全开源。
系统完美运行,无任何的bug,技术较多,可以当做
面试的项目或者作为毕设的项目。
通过本项目你可以学到:
- 项目是怎样前后端分离的
- vue 是如何用于后台管理的
- 如何用MyBaitsPlus 代码生成器生成代码的
- 单表增删改查(包括分页模糊查询)
- 批量删除
- 基于RBAC的权限管理是如何设计的
- 菜单管理又是如何实现的
- 文件上传的实现
- 导入导出
- 主从表的数据是如何在前端呈现的
- …
获取源码的方式见文章底部。
为防止刷着刷着找不到,大家点赞、收藏文章。
具体的介绍如下所示。
1.技术介绍
核心技术:SpringBoot+MyBatis-Plus;
前端:vue+elementui;
开发工具:Idea,VS Code, Git;
数据库:mysql5.7;
2.系统设计
本系统考虑的应用场景是在宠物店或宠物医院里, 主要有预约管理、药品管理、订单管理、充值管理等功能。
主要分了用户、医生和管理员三个角色。每个角色登录系统会有不同的菜单功能呈现,页面中不同的角色有不同的权限。各角色可访问的菜单都由管理员进行配置。
2.1系统功能设计
2.2预约流程
2.3就诊流程
2.4商品流程
2.5充值流程
3.功能介绍
3.1登录或注册
没有账号可以注册账号,当前只开放 普通用户的注册。对于医生和管理员的注册,由系统管理员在管理段注册。(默认管理员的账号和密码都是 admin)
登录之后,后台会菜单和权限的配置生成相应数据告知前端,前端进入相应的模块。
4.用户端
4.1就诊预约
用户可以查看所有医生信息,并根据宠物病情选择预约对应的医生预约排队(即添加预约信息)。
4.2预约管理
用户查看自己的预约信息,查看预约审核状态;并实现预约信息的添加,修改,删除,查询功能。
4.3药品管理
用户可以查询治疗宠物需要用到的所有药品或食品,针对自己宠物需要用到的商品可以进行订购(不能对商品实现添加,修改,删除功能)。
4.4订单管理
用户可以查看自己的所有商品订单,并实现修改,删除,查询功能,针未支付的订单可以进行支付,收到商品以后进行确认收货。
4.5充值中心
用户针对自己的账户进行余额充值。每笔充值记录及消费记录都可查询到。
4.6个人中心
用户可以查看自己的个人信息,并实现修改功能(例如:修改账号,密码等)。
5.医生端
医生的注册目前只能由管理员在管理员端进行注册,暂不开放自己注册。
5.1预约管理
医生可以查询预约了自己的所有预约信息,实现预约信息的添加,修改,删除,查询功能。
5.2诊断管理
针对每一个自己诊断的宠物进行记录,方便下次诊断时查询,实现就诊记录的添加,修改,删除,查询功能。
5.3.个人中心
医生可以查看自己的个人信息,并实现修改功能(例如:修改账号,密码等)。
(截图可参见前面用户端的)
6.管理员端
6.1.用户管理
查询所有普通用户信息,实现普通用户的添加,修改,删除,查询功能。
6.2.医生管理
查询所有医生信息,实现医生的添加,修改,删除,查询功能。
6.3.药品管理
查询所有治疗宠物的药品或食品信息,实现商品的添加,修改,删除,查询功能。
6.4.订单管理
查询用户的所有订单,针对已经付款的订单进行发货处理,针对已经完成的订单,以及未支付的订单可以进行删除处理,不能修改用户订单。
6.5.科室管理
查询科室信息,实现科室的添加,修改,删除,查询功能。
6.6.宠物种类管理
查询宠物种类信息,实现科室的添加,修改,删除,查询功能。
6.7.个人中心
管理员查询自己的个人信息,并可以实现修改功能(例如:修改账号,密码等)。
(截图可参见前面用户端的)
7.核心代码
/*** <p>* 订单管理控制器* </p>** @author * @since 2023-04-24*/
@RestController
@RequestMapping("/order")
public class OrderController {@Resourceprivate IOrderBaseService orderBaseService;@Resourceprivate IOrderItemService orderItemService;@Resourceprivate IDrugService drugService;@Resourceprivate IUserService userService;private final String now = DateUtil.now();// 新增或者更新@PostMappingpublic Result save(@RequestBody OrderDTO orderDTO) {if (orderDTO.getItems() == null || orderDTO.getItems().size()<1) {return Result.error(Constants.CODE_400, "参数错误.订单缺少项目信息");}if (StringUtils.isEmpty(orderDTO.getReceiverPhone())) {return Result.error(Constants.CODE_400, "参数错误.请提供收货人电话");}if (StringUtils.isEmpty(orderDTO.getReceiverAddress())) {return Result.error(Constants.CODE_400, "参数错误.请提供收货人地址");}//判断用户是否存在QueryWrapper<User> queryWrapperCustom = new QueryWrapper<>();queryWrapperCustom.eq("username", orderDTO.getUserName());queryWrapperCustom.eq("role", RoleEnum.ROLE_USER.toString());User findUser = userService.getOne(queryWrapperCustom);if (null == findUser) {return Result.error(Constants.CODE_404, "用户不存在");}if (orderDTO.getRemark() == null) {orderDTO.setRemark("");}BigDecimal totalAmount = new BigDecimal(0);OrderBase orderBase = new OrderBase();orderBase.setStatus(OrderBase.OrderStatus.UN_PAY);orderBase.setPayMode(OrderBase.PayMode.UNKNOWN);orderBase.setPayVoucherNo("");orderBase.setUserId(findUser.getId());orderBase.setUserName(findUser.getUsername());orderBase.setReceiverPhone(orderDTO.getReceiverPhone());orderBase.setReceiverAddress(orderDTO.getReceiverAddress());orderBase.setRemark(orderDTO.getRemark());long oid = 0;if (orderDTO.getId() == null) {//添加操作OrderIdGenerator orderIdGenerator = new OrderIdGenerator();oid = orderIdGenerator.nextId(this);orderDTO.setId(oid);User currentUser = TokenUtils.getCurrentUser();orderBase.setCreateName(currentUser.getUsername());orderBase.setCreateBy(String.valueOf(currentUser.getId()));orderBase.setCreateRole(currentUser.getRole());orderBase.setCreateTime(new Date());}else {//更新操作oid = orderDTO.getId();//找出原订单信息OrderBase oldOrder = orderBaseService.getById(oid);if (null == oldOrder) {return Result.error(Constants.CODE_404, "订单记录不存在.id=" + oid);}//只有待支付状态的订单才 可以 修改if (oldOrder.getStatus() != OrderBase.OrderStatus.UN_PAY) {return Result.error(Constants.CODE_600, "只有待支付状态的订单才可以修改 .id=" + oid);}orderBase.setCreateName(oldOrder.getCreateName());orderBase.setCreateBy(oldOrder.getCreateBy());orderBase.setCreateRole(oldOrder.getCreateRole());orderBase.setCreateTime(oldOrder.getCreateTime());//删除原来项目 表的内容orderItemService.delByOrderId(oid);}//先保存项目表int seq = 0;String orderOverview = "" ; // 订单项目简要for (OrderItem orderItem: orderDTO.getItems() ) {orderItem.setOrderId(oid);//处理 序号seq++;orderItem.setSeq(seq);if (orderItem.getItemId() == null ) {return Result.error(Constants.CODE_400, "参数错误. 订单项目id为Null");};if (orderItem.getQty() == null ) {return Result.error(Constants.CODE_400, "参数错误. 订单项目数量为Null");}if (orderItem.getQty() <= 0 ) {return Result.error(Constants.CODE_400, "参数错误. 订单项目数量必须大于0");}//数据库中查找商品是否存在Drug drug = drugService.getById(orderItem.getItemId());if (null == drug) {return Result.error(Constants.CODE_400, "参数错误. 商品不存在. 项目id=" + orderItem.getItemId());}orderItem.setPrice(drug.getRetailPrice());orderItem.setName(drug.getName() + " " + drug.getProductName());orderItem.setUnit(drug.getUnit());orderOverview += "|";orderOverview += orderItem.getName();//计算合计totalAmount = totalAmount.add(orderItem.getPrice().multiply(new BigDecimal(orderItem.getQty())));if (!orderItemService.save(orderItem)) {return Result.error(Constants.CODE_600, "业务异常.无法保存某订单的项目.项目id=" + orderItem.getItemId());};}orderOverview += "|";if (orderOverview.length()>128) {orderOverview = orderOverview.substring(0,127);}orderBase.setId(oid);orderBase.setOverview(orderOverview);orderBase.setAmount(totalAmount);//再保存主表的if (orderBaseService.saveOrUpdate(orderBase)) {return Result.success();}else {return Result.error(Constants.CODE_600, "业务异常.保存订单主表失败" );}}@DeleteMapping("/{id}")public Result delete(@PathVariable Long id) {OrderBase orderBase = orderBaseService.getById(id);if (null == orderBase ){return Result.error(Constants.CODE_404, "订单不存在. 订单id=" + id );}//只能删除未支付或已签收的订单if (orderBase.getStatus()==OrderBase.OrderStatus.UN_PAY ||orderBase.getStatus()==OrderBase.OrderStatus.SIGN ) {;}else {return Result.error(Constants.CODE_600, "无效订单状态.只能删除未支付或已签收的订单");}//先删除项目表的记录orderItemService.delByOrderId(id);orderBaseService.removeById(id);return Result.success();}@PostMapping("/del/batch")public Result deleteBatch(@RequestBody List<Long> ids) {//先删除项目表的记录for (Long id: ids) {orderItemService.delByOrderId(id);}orderBaseService.removeByIds(ids);return Result.success();}@GetMappingpublic Result findAll() {return Result.success(orderBaseService.list());}@GetMapping("/{id}")public Result findOne(@PathVariable Long id) {return Result.success(orderBaseService.getById(id));}@GetMapping("/page")public Result findPage(@RequestParam(defaultValue = "") String userName,@RequestParam Integer pageNum,@RequestParam Integer pageSize) {QueryWrapper<OrderBase> queryWrapper = new QueryWrapper<>();queryWrapper.orderByDesc("create_time");if (!"".equals(userName)) {queryWrapper.like("user_name", userName);}User currentUser = TokenUtils.getCurrentUser();if (currentUser.getRole().equals(RoleEnum.ROLE_USER.toString())) {//普通用户只能查看自己的预约记录queryWrapper.eq("user_id", currentUser.getId());}Object object = orderBaseService.page(new Page<>(pageNum, pageSize), queryWrapper);return Result.success(object);//return Result.success(orderBaseService.page(new Page<>(pageNum, pageSize), queryWrapper));}@GetMapping("/items/{id}")public Result findOrderItems(@PathVariable Long id) {//查找订单项目列表QueryWrapper<OrderItem> queryWrapper = new QueryWrapper<>();queryWrapper.orderByDesc("seq");queryWrapper.eq("order_id", id);return Result.success(orderItemService.list(queryWrapper));}/*** 导出接口*/@GetMapping("/export")public void export(HttpServletResponse response) throws Exception {// 从数据库查询出所有的数据List<OrderBase> list = orderBaseService.list();// 在内存操作,写出到浏览器ExcelWriter writer = ExcelUtil.getWriter(true);// 一次性写出list内的对象到excel,使用默认样式,强制输出标题writer.write(list, true);// 设置浏览器响应的格式response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");String fileName = URLEncoder.encode("OrderBase信息表", "UTF-8");response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");ServletOutputStream out = response.getOutputStream();writer.flush(out, true);out.close();writer.close();}/*** excel 导入* @param file* @throws Exception*/@PostMapping("/import")public Result imp(MultipartFile file) throws Exception {InputStream inputStream = file.getInputStream();ExcelReader reader = ExcelUtil.getReader(inputStream);// 通过 javabean的方式读取Excel内的对象,但是要求表头必须是英文,跟javabean的属性要对应起来List<OrderBase> list = reader.readAll(OrderBase.class);orderBaseService.saveBatch(list);return Result.success();}@PostMapping("/delivery/{id}")public Result delivery(@PathVariable Long id) {//发货//判断订单是否存在OrderBase orderBase = orderBaseService.getById(id);if (null == orderBase) {return Result.error(Constants.CODE_404, "订单不存在.订单id=" + id);}//判断订单是否已经支付if (orderBase.getStatus() == OrderBase.OrderStatus.PAYED){}else {return Result.error(Constants.CODE_600, "订单不是已支付状态, 不允许发货.");}if (orderBaseService.updateDeliveryInfo(id, OrderBase.OrderStatus.DELIVERED, new Date()) >0) {return Result.success(orderBaseService.getById(id));}else {return Result.error(Constants.CODE_600, "业务异常.更新订单发货信息失败" );}}@PostMapping("/sign/{id}")public Result sign(@PathVariable Long id) {//签收,//判断订单是否存在OrderBase orderBase = orderBaseService.getById(id);if (null == orderBase) {return Result.error(Constants.CODE_404, "订单不存在.订单id=" + id);}//判断订单是否已经支付if (orderBase.getStatus() == OrderBase.OrderStatus.DELIVERED){;}else {return Result.error(Constants.CODE_600, "订单不是已发货状态, 不允许签收.");}if (orderBaseService.updateSignInfo(id, OrderBase.OrderStatus.SIGN, new Date())>0) {return Result.success(orderBaseService.getById(id));}else {return Result.error(Constants.CODE_600, "业务异常.更新订单签收信息失败" );}}private User getUser() {return TokenUtils.getCurrentUser();}}
/*** <p>* 预约管理控制器* </p>** @author * @since 2023-04-23*/
@RestController
@RequestMapping("/appointment")
public class AppointmentController {@Resourceprivate IAppointmentService appointmentService;@Resourceprivate IUserService userService;@Resourceprivate IDoctorService doctorService;private final String now = DateUtil.now();// 新增或者更新@PostMappingpublic Result save(@RequestBody Appointment appointment) {if (appointment.getAppointmentTime() == null) {return Result.error(Constants.CODE_400, "参数错误:请提供预约时间");}//查找顾客信息QueryWrapper<User> queryWrapperCustom = new QueryWrapper<>();queryWrapperCustom.eq("username", appointment.getCustomName());queryWrapperCustom.eq("role", RoleEnum.ROLE_USER.toString());User findCustom = userService.getOne(queryWrapperCustom);if (null == findCustom) {return Result.error(Constants.CODE_404, "顾客不存在");}appointment.setCustomId(findCustom.getId());appointment.setCustomName(findCustom.getUsername());appointment.setCustomPhone(findCustom.getPhone());//查找医生信息QueryWrapper<User> queryWrapperDoctor = new QueryWrapper<>();queryWrapperDoctor.eq("username", appointment.getDoctorName());queryWrapperDoctor.eq("role", RoleEnum.ROLE_DOCTOR.toString());User findDoctor = userService.getOne(queryWrapperDoctor);if (null == findDoctor) {return Result.error(Constants.CODE_404, "医生不存在");}appointment.setDoctorId(findDoctor.getId());appointment.setDoctorName(findDoctor.getUsername());appointment.setDoctorPhone(findDoctor.getPhone());if (appointment.getRemark() == null) {appointment.setRemark("");}if (appointment.getId() == null) {//添加操作appointment.setStatus(Appointment.AppointmentStatus.WAIT_AUDIT);User currentUser = TokenUtils.getCurrentUser();appointment.setCreateName(currentUser.getUsername());appointment.setCreateBy(String.valueOf(currentUser.getId()));appointment.setCreateRole(currentUser.getRole());appointment.setCreateTime(new Date());}else {//更新操作if (appointment.getStatus() == null) {return Result.error(Constants.CODE_400, "参数错误:请提供预约状态");}//不更新原 创建人信息Appointment oldAppointment = appointmentService.getById(appointment.getId());if (null==oldAppointment) {return Result.error(Constants.CODE_404, "预约记录不存在");}appointment.setCreateName(oldAppointment.getCreateName());appointment.setCreateBy(oldAppointment.getCreateBy());appointment.setCreateRole(oldAppointment.getCreateRole());appointment.setCreateTime(oldAppointment.getCreateTime());}appointmentService.saveOrUpdate(appointment);return Result.success();}@DeleteMapping("/{id}")public Result delete(@PathVariable Long id) {appointmentService.removeById(id);return Result.success();}@PostMapping("/del/batch")public Result deleteBatch(@RequestBody List<Long> ids) {appointmentService.removeByIds(ids);return Result.success();}// @GetMapping
// public Result findAll() {// return Result.success(appointmentService.list());
// }@GetMapping("/{id}")public Result findOne(@PathVariable Long id) {return Result.success(appointmentService.getById(id));}@GetMapping("/page")public Result findPage(@RequestParam Integer pageNum,@RequestParam Integer pageSize,@RequestParam(defaultValue = "") String customName,@RequestParam(defaultValue = "") String doctorName) {QueryWrapper<Appointment> queryWrapper = new QueryWrapper<>();queryWrapper.orderByDesc("id");if (!"".equals(customName)) {queryWrapper.like("custom_name", customName);}if (!"".equals(doctorName)) {queryWrapper.like("doctor_name", doctorName);}User currentUser = TokenUtils.getCurrentUser();if (currentUser.getRole().equals(RoleEnum.ROLE_USER.toString())) {//普通用户只能查看自己的预约记录queryWrapper.eq("create_by", currentUser.getId());}else if (currentUser.getRole().equals(RoleEnum.ROLE_DOCTOR.toString())) {//医生可以查看自己的记录和 别人约自己的queryWrapper.eq("create_by", currentUser.getId()).or().eq("doctor_id", currentUser.getId());}return Result.success(appointmentService.page(new Page<>(pageNum, pageSize), queryWrapper));}/*** 导出接口*/@GetMapping("/export")public void export(HttpServletResponse response) throws Exception {// 从数据库查询出所有的数据List<Appointment> list = appointmentService.list();// 在内存操作,写出到浏览器ExcelWriter writer = ExcelUtil.getWriter(true);// 一次性写出list内的对象到excel,使用默认样式,强制输出标题writer.write(list, true);// 设置浏览器响应的格式response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");String fileName = URLEncoder.encode("Appointment信息表", "UTF-8");response.setHeader("Content-Disposition", "attachment;filename=" + fileName + ".xlsx");ServletOutputStream out = response.getOutputStream();writer.flush(out, true);out.close();writer.close();}/*** excel 导入* @param file* @throws Exception*/@PostMapping("/import")public Result imp(MultipartFile file) throws Exception {InputStream inputStream = file.getInputStream();ExcelReader reader = ExcelUtil.getReader(inputStream);// 通过 javabean的方式读取Excel内的对象,但是要求表头必须是英文,跟javabean的属性要对应起来List<Appointment> list = reader.readAll(Appointment.class);appointmentService.saveBatch(list);return Result.success();}private User getUser() {return TokenUtils.getCurrentUser();}}
8.设计文档
提供需求说明和关键的业务数据库表字典,很难得喔。
9.源码获取
如果你喜欢这个项目的话, 给个一键三连,点赞越多,往后提高更多的开源项目, 谢谢大家,gitee链接附上。
后端:https://gitee.com/madifu/petHis-backend
前端:https://gitee.com/madifu/petHis-fontend-admin
10.后记
在开发这个系统时,遇到过几个坑,包括 VUE的,还有js 的,它们是怎么绕过去的,将另行文章做相关介绍。
基于SpringBoot+VUE的宠物医院后台管理系统【源码开源】【建议收藏】相关推荐
- java计算机毕业设计Vue框架电商后台管理系统源码+mysql数据库+系统+lw文档+部署
java计算机毕业设计Vue框架电商后台管理系统源码+mysql数据库+系统+lw文档+部署 java计算机毕业设计Vue框架电商后台管理系统源码+mysql数据库+系统+lw文档+部署 本源码技术栈 ...
- java计算机毕业设计Vue框架电商后台管理系统源码+数据库+系统+lw文档
java计算机毕业设计Vue框架电商后台管理系统源码+数据库+系统+lw文档 java计算机毕业设计Vue框架电商后台管理系统源码+数据库+系统+lw文档 本源码技术栈: 项目架构:B/S架构 开发语 ...
- springboot+vue+mysql外卖点餐管理系统源码(包安装+讲解)
博主介绍:✌在职Java研发工程师.专注于程序设计.源码分享.技术交流.专注于Java技术领域和毕业设计✌ 项目名称 springboot+vue+mysql外卖点餐管理系统源码(包安装+讲解) 视 ...
- 【毕业设计专栏】基于SpringBoot+Vue学生综合测评系统【源码+论文+演示PPT视频】
目录 1.效果演示 2.系统介绍 3. 系统的详细设计与展示 3.1 学生后台管理模块 3.2管理员功能模块 4.系统分析与设计 4.1可行性分析 4.1.1 技术可行性分析 4.1.2 经济可行性分 ...
- 计算机毕业设计Springboot+vue的宠物销售商城网站(源码+系统+mysql数据库+Lw文档)
一.项目运行 开发语言:Java 开发工具:IDEA /Eclipse 数据库:MYSQL5.7 应用服务:Tomcat7/Tomcat8 使用框架:springboot+vue 宠物是人类最好的伙伴 ...
- [JAVA毕业设计]Vue框架电商后台管理系统源码获取和系统演示
项目运行 环境配置: Jdk1.8 + Tomcat8.5 + Mysql + HBuilderX(Webstorm也行)+ Eclispe(IntelliJ IDEA,Eclispe,MyEclis ...
- springboot+vue宠物医院诊所管理系统源码
开发环境及工具: 大等于jdk1.8,大于mysql5.5,idea(eclipse),nodejs,vscode(webstorm) 技术说明: springboot mybatis vue ele ...
- 基于springboot vue elementui的物品租赁系统源码
开发环境及工具: 大等于jdk1.8,大于mysql5.5,idea(eclipse),vscode(webstorm) 技术说明: springboot mybatis vue elementui ...
- 基于SpringBoot+Vue 实现准妈妈孕期交流平台【源码+论文+演示视频+包运行成功】
您好,我是码农飞哥(wei158556),感谢您阅读本文,欢迎一键三连哦.
最新文章
- DateGridView列的输出顺序反了
- 自学大数据需要从哪里入手 收藏了一份详细的学习路线图
- 数据库操作(使用FMDB)
- 线转hdmi为什么检测不到_为什么苹果MacBook这么保值?
- python网络通信的几种方式_python网络-计算机网络基础(23)
- 面试再也不怕问到HashMap(二)
- 优酷开放SDK之setOnTimeOutListener
- how is opportunity detail page display first item by default
- 【概率论】3-4:二维分布(Bivariate Distribution)
- Python脚本生成单个EXE文件
- ffmpeg处理RTMP流媒体的命令大全
- ElasticSearch分词近义词
- 服务器无线存储器,教你把无线路由器打造成网络存储器
- 第二关练习讲解(下部)
- 深入浅出 Docker
- iPhone 界面尺寸以及各种图表尺寸
- 第二章 预习导图 部署DNS服务
- shellcode转换
- 教务管理系统数据表关系图_浙江工商大学教务处
- thunderbird 登录网易邮箱