课程链接:尚医通项目
开始时间:2022-07-09

项目总结

尚医通业务流程

在这里插入图片描述

项目功能总结(后台管理系统)

本地访问地址
http://localhost:9528/

医院设置管理

(1)医院设置列表、添加、锁定、删除
(2)医院列表、详情、排班、下线
这个列表是一个平台系统,医院系统的实际路径就是下图9998的地址
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
查看详情
在这里插入图片描述
查看排班
在这里插入图片描述
这个医院列表的数据来自MongoDB,要保证里面有数据才能拿出来

数据管理

(1)数据字典树形显示、导入、导出
数据字典:把所有固定值,放到数据字典,项目需要的时候从里面取
在这里插入图片描述
导入导出都是Excel文件

用户管理

(1)用户列表、查看、锁定
在这里插入图片描述查看详情
在这里插入图片描述

一个用户下面可以添加多个就诊人
(2)认证用户审批
在这里插入图片描述
在注册用户时的实名认证

项目功能总结(前台用户系统)

本地访问地址
http://localhost:3000/

首页数据显示

(1)医院列表
在这里插入图片描述

医院详情显示

(1)医院科室显示
点进医院里面
在这里插入图片描述
选择某个科室,会提醒你先登录才能挂号

3、用户登录功能
(1)邮箱账号登录(邮箱验证码发送)
(2)微信扫描登录
从LoginVO中拿邮箱号和验证码,如果邮箱为空或者验证码为空,则报异常
如果验证码和redis里面拿到的验证码不同,也报异常
然后再判断是否有该邮箱地址的用户,如果没有则新建一个并save
不是第一次,直接登录,返回用户名和token信息

生成微信二维码
确认后再后台配置回调地址
回调域名地址,跳转到本地接口方法里面,编写回调方法
获取扫码人的信息添加到数据库里面

绑定微信
拿到传过来的VO类的Openid
如果能查到有该Openid的userinfo,则设置当前userinfo的email为VO的email
建一个Map存放name和token
token通过userinfo的id和name进行生成
调用的JwtHelper的工具类

获取扫描人信息过程

  • 第一步 获取回调返回code值 临时票据
  • 第二步 拿着code值,请求微信提供的地址,得到地址返回两个值 access_token openid
  • 第三步 拿着access_token openid 再去请求微信提供地址,请求地址返回扫描人信息
  • 第四部 绑定手机号,把手机号和微信扫描人信息添加到数据库中
    4、用户实名认证
    在这里插入图片描述
    这里上传了会交给后台管理系统进行审批
    调整user的auth_status字段即可

要预约挂号,我们必须要认证通过后才可以,所以我们在预约挂号前要做认证判断,如果没有认证通过,则跳转到认证页面
这里是前端代码进行判断,判断auth_status

在这里插入图片描述

5、就诊人管理
(1)列表、添加、详情、删除
就诊人列表
在这里插入图片描述
就诊人详情
在这里插入图片描述
新增就诊人
在这里插入图片描述
就诊人管理其实就是要实现一个完整的增删改查

预约挂号功能

(1)排班和挂号详情信息
在这里插入图片描述
放号倒计时
在这里插入图片描述

(2)确认挂号信息
在这里插入图片描述

(3)生成预约挂号订单
在这里插入图片描述
这里我做有点bug,每次都要点预约三次才能进去,实际也会消耗3个号

(4)挂号订单支付(微信)
在这里插入图片描述
支付成功后状态变更
在这里插入图片描述
此时会有邮件提醒挂号成功

(5)取消预约订单
在这里插入图片描述

项目技术点总结(后端技术)

SpringBoot

Nginx

实现负载均衡,后面用springcloud做了替代
在这里插入图片描述

SpringCloud

(1)Nacos注册中心(不同微服务间的调用)
(2)Feign(发现服务并实现调用)
(3)GateWay(Nginx的升级,通过网关转发到对应服务)

Redis

(1)使用Redis作为缓存(数据字典里面的数据放在Redis里面了)
(2)验证码有效时间、支付二维码有效时间

MongoDB

(1)使用MongoDB存储 医院相关数据(医院、科室、排班信息都放这里面了)
MongoTemplate(条件查询、聚合查询)
引入依赖-配置MongoDB地址-创建对应实体类-创建对应Repository接口,继承MongoRepository<>
再在serviceImpl自动注入后,即可调用接口方法
如果要条件查询,则需要编写Criteria 对象,封装条件

EasyExcel

(1)操作excel表格,进行读和写操作
引入依赖-》创建实体类(添加注解@ExcelProperty)-》实现写操作(EasyExcel.write())
读操作(ExcelListener)

MyBatisPlus

对Mybatis做了增强
service里面继承IService<>
Mapper里面继承BaseMapper<>

  • MyBatisPlus是什么
  • MyBatisPlus如何实现CRUD
  • MyBatisPlus自动填充(创建时间和新建时间,让每个具体的类继承BaseEntity,需要自动填充的字段添加注解TableField)
  • MyBatisPlus中如果不需要自定义新的BaseMapper以外的数据库操作,那么只需要Mapper接口继承BaseMapper即可,如果需要自己再写这以外的SQL语句,那么就需要额外编写Mapper.xml文件
  • 乐观锁(比较版本库,更新版本库 CAS) 在表添加字段作为版本号,对应实体类的字段,比如取名version,在version上加注解@Version
  • MyBatisPlus实现逻辑删除(添加字段作为逻辑删除标志,实体类中根据id删除)
  • MyBatisPlus实现分页查询(配置分页插件PaginationInterceptor,创建分页page格式,然后调用mapper.selectPage传入格式和封装查询条件的VO,得到的结果进行返回 )
  • 创建条件构造器QueryWrapper<>,实现条件查询

RabbitMQ

(1)订单相关操作,发送mq消息
提升并发功能
封装了一个工具类
在这里插入图片描述
订单生成模块用了这个内容
发送mq消息,号源更新和邮件通知

//发送mq消息,号源更新和邮件通知
            OrderMqVo orderMqVo = new OrderMqVo();
            //三个参数的设置
            orderMqVo.setScheduleId(scheduleId);
            orderMqVo.setReservedNumber(reservedNumber);
            orderMqVo.setAvailableNumber(availableNumber);

            //邮件提示
            MsmVo msmVo = new MsmVo();
            msmVo.setEmail(orderInfo.getPatientEmail());

            String reserveDate =
                    new DateTime(orderInfo.getReserveDate()).toString("yyyy-MM-dd")
                            + (orderInfo.getReserveTime() == 0 ? "上午" : "下午");
            Map<String, Object> param = new HashMap<String, Object>() {{
                put("title", orderInfo.getHosname() + "|" + orderInfo.getDepname() + "|" + orderInfo.getTitle());
                put("amount", orderInfo.getAmount());
                put("reserveDate", reserveDate);
                put("name", orderInfo.getPatientName());
                put("quitTime", new DateTime(orderInfo.getQuitTime()).toString("yyyy-MM-dd HH:mm"));
            }};
            msmVo.setParam(param);

            orderMqVo.setMsmVo(msmVo);
            //发送
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_ORDER, MqConst.ROUTING_ORDER, orderMqVo);

然后在hosp模块做接收
order->携带路由和交换机到hosp进行库存, hosp里携带邮件的交换机和路由到msm模块进行邮件发送

@Component
public class HospitalReceiver {

    @Autowired
    private ScheduleService scheduleService;

    @Autowired
    private RabbitService rabbitService;

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_ORDER, durable = "true"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_ORDER),
            key = {MqConst.ROUTING_ORDER}
    ))

    //order->携带路由和交换机到hosp进行库存, hosp里携带邮件的交换机和路由到msm模块进行邮件发送
    public void receiver(OrderMqVo orderMqVo, Message message, Channel channel) throws IOException {
        //下单成功更新预约数
        Schedule schedule = scheduleService.getScheduleId(orderMqVo.getScheduleId());
        schedule.setReservedNumber(orderMqVo.getReservedNumber());
        schedule.setAvailableNumber(orderMqVo.getAvailableNumber());
        scheduleService.update(schedule);
        //发送邮件
        MsmVo msmVo = orderMqVo.getMsmVo();
        if (null != msmVo) {
            rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_MSM, MqConst.ROUTING_MSM_ITEM, msmVo);
        }
    }
}

Docker

(1)下载镜像 docker pull (MongoDB和RabbitMQ)
(2)创建容器 docker run

阿里云OSS(云端存放图片,数据库存地址)

文件存储服务器

阿里云短信服务(改为了邮箱服务了)

写了一个service_msm的微服务
其controller主要是这样一个流程
发送验证码前判断该邮箱是否能在redis里面获取到验证码,如果有,说明还没到过期时间,就用之前的验证码即可
如果没有,利用工具类生成6位验证码,放入到redis里面,并设置过期时间
然后执行编写的send方法,就是在网上找一个发邮件的Java模板就可以

微信登录/支付

生成二维码用于登录和支付
调用的微信的接口
微信返回xml数据
xml变成map集合进行操作

在这里插入图片描述

项目技术点总结(前端技术)

vue

(1)指令

Element-ui

nuxt

npm

模块化开发

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
跨域问题的解决

Spring提供了解决方案,在对应controller上添加一个标签就可以了(@CrossOrigin //跨域)。
跨域问题第二种解决方式
gateway模块中写配置类CorsConfig,有配置类就不能再加crossorigin了

挂号平台是一个整合,会去整理各个医院自己的系统的数据,医院系统数据传到MongoDB,然后挂号平台会读取,这里就是用的MongoDB中repository的部分
在这里插入图片描述
数据字典的使用
我们的hosp模块调用MongoDB数据库拿到的数据是这个形式
在这里插入图片描述
但要和具体的字段对应起来,需要去查dict
在这里插入图片描述

在这里插入图片描述
那么这里就涉及到了注册中心
我们在DictFeignClient接口里写需要调用的服务,这里是(service-cmn)

//需要调用服务的名称
@FeignClient(value = "service-cmn")
@Repository
public interface DictFeignClient {
    @GetMapping("/admin/cmn/dict/getName/{dictCode}/{value}")
    public String getName(@PathVariable("dictCode") String dictCode, @PathVariable("value") String value);

    //根据value查询
    @GetMapping("/admin/cmn/dict/getName/{value}")
    public String getName(@PathVariable("value") String value);
}

而这里面路径的写法和DictController基本一致
通过service-hosp调用service-cmn
结束时间:2022-07-09

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐