尚医通项目81-100:医院管理

开始时间:2022-05-27
课程链接:课程链接:【尚医通】

注册中心与服务调用

目前在医院列表中需要医院的信息和等级信息,而两段信息属于不同的的模块,service-hosp和service-cmn,所以我们需要使用到远程调用。
参考Dubbo入门
本项目使用Nacos

配置nacos
下载的是nacos-server-1.1.4版本
在这里插入图片描述
启动startup.cmd
在这里插入图片描述
启动后不要关闭,关了就会运行不了

在service的pom中添加

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

然后配置我们的两个微服务
将他们的application.properties分别设置一下

# nacos服务地址
spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

并在他们的主启动类上都加

@EnableDiscoveryClient

注解
此时打开网站
localhost:8848/nacos
默认登录名和密码都是nacos
进来之后
可以看到我们已经添加了两个服务
在这里插入图片描述

医院列表接口

目前我们把医院、科室和排班都上传到了平台,那么管理平台就应该把他们管理起来,在我们的管理平台能够直观的查看这些信息。
在这里插入图片描述
在这里插入图片描述

医院列表api接口

hosp微服务

写接口

package com.bupt.yygh.hosp.service;

import com.bupt.yygh.model.hosp.Hospital;
import com.bupt.yygh.vo.hosp.HospitalQueryVo;
import org.springframework.data.domain.Page;

import java.util.Map;

public interface HospitalService {
    //上传医院接口
    void save(Map<String, Object> paramMap);
    //实现根据医院编号查询
    Hospital getByHoscode(String hoscode);
    //医院列表(条件查询带分页)
    Page<Hospital> selectHospPage(Integer page, Integer limit, HospitalQueryVo hospitalQueryVo);

    void updateStatus(String id, Integer status);

    Map<String, Object> getHospById(String id);
}

在HospitalServiceImpl类实现接口

package com.bupt.yygh.hosp.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.bupt.yygh.cmn.client.DictFeignClient;
import com.bupt.yygh.hosp.repository.HospitalRepository;
import com.bupt.yygh.hosp.service.HospitalService;
import com.bupt.yygh.model.hosp.Hospital;
import com.bupt.yygh.vo.hosp.HospitalQueryVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Service
public class HospitalServiceImpl implements HospitalService {
    @Autowired
    private HospitalRepository hospitalRepository;

    @Autowired
    private DictFeignClient dictFeignClient;

    @Override
    public void save(Map<String, Object> paramMap) {
        //把参数map集合转换成字符串再转为对象 Hospital
        String mapString = JSONObject.toJSONString(paramMap);
        Hospital hospital = JSONObject.parseObject(mapString, Hospital.class);

        //判断是否存在数据
        String hoscode = hospital.getHoscode();
        Hospital hospitalExist = hospitalRepository.getHospitalByHoscode(hoscode);

        //如果存在,进行修改
        if (hospitalExist != null) {
            hospital.setStatus(hospitalExist.getStatus());
            hospital.setCreateTime(hospitalExist.getCreateTime());
            hospital.setUpdateTime(new Date());
            hospital.setIsDeleted(0);
            hospitalRepository.save(hospital);
        } else {//如果不存在,进行添加
            //判断项目是否上线
            hospital.setStatus(0);
            hospital.setCreateTime(new Date());
            hospital.setUpdateTime(new Date());
            hospital.setIsDeleted(0);
            hospitalRepository.save(hospital);
        }
    }

    @Override
    public Hospital getByHoscode(String hoscode) {
        Hospital hospital = hospitalRepository.getHospitalByHoscode(hoscode);
        return hospital;
    }

    //医院列表(条件查询分页)
    @Override
    public Page<Hospital> selectHospPage(Integer page, Integer limit, HospitalQueryVo hospitalQueryVo) {
        //创建pageable对象
        Pageable pageable = PageRequest.of(page - 1, limit);
        //创建条件匹配器
        ExampleMatcher matcher = ExampleMatcher.matching()
                .withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
                .withIgnoreCase(true);
        //hospitalQueryVo转换Hospital对象
        Hospital hospital = new Hospital();
        BeanUtils.copyProperties(hospitalQueryVo, hospital);
        //创建对象
        Example<Hospital> example = Example.of(hospital, matcher);
        //调用方法实现查询
        Page<Hospital> pages = hospitalRepository.findAll(example, pageable);

//        //获取查询list集合,遍历进行医院等级封装
        pages.getContent().stream().forEach(item -> {
            this.setHospitalHosType(item);
        });

        return pages;
    }

    //更新医院上线状态
    @Override
    public void updateStatus(String id, Integer status) {
        //根据id查询医院信息
        Hospital hospital = hospitalRepository.findById(id).get();
        //设置修改的值
        hospital.setStatus(status);
        hospital.setUpdateTime(new Date());
        hospitalRepository.save(hospital);
    }

    @Override
    public Map<String, Object> getHospById(String id) {
        Map<String, Object> result = new HashMap<>();
        Hospital hospital = this.setHospitalHosType(hospitalRepository.findById(id).get());
        //医院基本信息(包含医院等级)
        result.put("hospital",hospital);
        //单独处理更直观
        result.put("bookingRule", hospital.getBookingRule());
        //不需要重复返回
        hospital.setBookingRule(null);
        return result;
    }

    //获取查询list集合,遍历进行医院等级封装
    private Hospital setHospitalHosType(Hospital hospital) {
        //根据dictCode和value获取医院等级名称
        //这里算多表查询,一个mysql一个MongoDB
        String hostypeString = dictFeignClient.getName("Hostype", hospital.getHostype());
        //查询省 市  地区
        String provinceString = dictFeignClient.getName(hospital.getProvinceCode());
        String cityString = dictFeignClient.getName(hospital.getCityCode());
        String districtString = dictFeignClient.getName(hospital.getDistrictCode());

        hospital.getParam().put("fullAddress", provinceString + cityString + districtString);
        hospital.getParam().put("hostypeString", hostypeString);
        return hospital;
    }
}

添加controller方法

package com.bupt.yygh.hosp.controller;

import com.bupt.yygh.common.result.Result;
import com.bupt.yygh.hosp.service.HospitalService;
import com.bupt.yygh.model.hosp.Hospital;
import com.bupt.yygh.vo.hosp.HospitalQueryVo;

import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/admin/hosp/hospital")
//@CrossOrigin
public class HospitalController {

    @Autowired
    private HospitalService hospitalService;

    //医院列表(条件查询分页)
    @GetMapping("list/{page}/{limit}")
    public Result listHosp(@PathVariable Integer page,
                           @PathVariable Integer limit,
                           HospitalQueryVo hospitalQueryVo) {
        //MongoDB返回对象
        Page<Hospital> pageModel = hospitalService.selectHospPage(page, limit, hospitalQueryVo);
        List<Hospital> content = pageModel.getContent();
        long totalElements = pageModel.getTotalElements();

        return Result.ok(pageModel);
    }

    //更新医院上线状态
    @ApiOperation(value = "更新医院上线状态")
    @GetMapping("updateHospStatus/{id}/{status}")
    public Result updateHospStatus(@PathVariable String id, @PathVariable Integer status) {
        hospitalService.updateStatus(id, status);
        return Result.ok();
    }

    //医院详情信息
    @ApiOperation(value = "医院详情信息")
    @GetMapping("showHospDetail/{id}")
    public Result showHospDetail(@PathVariable String id) {
        Map<String, Object> map = hospitalService.getHospById(id);
        return Result.ok(map);
    }
}

cmn微服务

由于我们的医院等级、省市区地址都是取的数据字典value值,因此我们在列表显示医院等级与医院地址时要根据数据字典value值获取数据字典名称
接口

package com.bupt.yygh.cmn.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.bupt.yygh.model.cmn.Dict;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.List;


public interface DictService extends IService<Dict> {
    //@Autowired不用写了,已经通过MP帮忙注册了
    List<Dict> findChlidData(Long id);

    void exportData(HttpServletResponse response);

    void importData(MultipartFile file);

    String getDictName(String dictCode, String value);

    //根据dictCode获取下级节点
    List<Dict> findByDictCode(String dictCode);
}

实现类

package com.bupt.yygh.cmn.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bupt.yygh.cmn.listener.DictListener;
import com.bupt.yygh.cmn.mapper.DictMapper;
import com.bupt.yygh.cmn.service.DictService;
import com.bupt.yygh.model.cmn.Dict;
import com.bupt.yygh.vo.cmn.DictEeVo;
import org.springframework.beans.BeanUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;

@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {
    //@Autowired不用写了,已经通过MP帮忙注册了
    @Override
    @Cacheable(value = "dict", keyGenerator = "keyGenerator")
    public List<Dict> findChlidData(Long id) {
        //条件构造器
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", id);

        List<Dict> dictList = baseMapper.selectList(wrapper);
        //向list集合每个dict对象中设置hasChildren
        for (Dict dict : dictList) {
            Long dictId = dict.getId();
            boolean isChild = this.isChildren(dictId);
            dict.setHasChildren(isChild);
        }
        return dictList;
    }

    //判断id下面是否有子节点
    private boolean isChildren(Long id) {
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", id);
        Integer count = baseMapper.selectCount(wrapper);
        // 0>0    1>0
        return count > 0;
    }

    @Override
    public void exportData(HttpServletResponse response) {
        try {
            //设置下载信息,以下载方式打开
            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = "dict";
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");

            //查询数据库
            List<Dict> dictList = baseMapper.selectList(null);
//            这个dictList不能直接传,因为对应关系不匹配,我们要传的是DictEeVo对象
            List<DictEeVo> dictVoList = new ArrayList<>(dictList.size());
            for (Dict dict : dictList) {
                DictEeVo dictEeVo = new DictEeVo();
                BeanUtils.copyProperties(dict, dictEeVo);
                dictVoList.add(dictEeVo);
            }
            //刚刚是传的路径,这里传IO流了
            EasyExcel.write(response.getOutputStream(), DictEeVo.class).sheet("数据字典").doWrite(dictVoList);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    //清空缓存,装最新更新的数据
    @Override
    @CacheEvict(value = "dict", allEntries = true)
    public void importData(MultipartFile file) {
        //导入数据字典
        try {
            EasyExcel.read(file.getInputStream(), DictEeVo.class, new DictListener(baseMapper)).sheet().doRead();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String getDictName(String dictCode, String value) {
        //如果dictCode为空,直接根据value查询
        if (StringUtils.isEmpty(dictCode)) {
            //直接根据value查询
            QueryWrapper<Dict> wrapper = new QueryWrapper<>();
            wrapper.eq("value", value);
            Dict dict = baseMapper.selectOne(wrapper);
            return dict.getName();
        } else {//如果dictCode不为空,根据dictCode和value查询

            //根据dictcode查询dict对象,得到dict的id值(此时定位的就是诸如“医院等级”这种字段)
            Dict codeDict = this.getDictByDictCode(dictCode);
            Long parent_id = codeDict.getId();
            //然后根据刚刚dict的id值,去匹配看,谁的parent_id根据parent_id和value进行查询
            // 此时定位的就是医院等级下具体的数据
            Dict finalDict = baseMapper.selectOne(new QueryWrapper<Dict>()
                    .eq("parent_id", parent_id)
                    .eq("value", value));
            return finalDict.getName();
        }
    }

    //根据dictCode获取下级节点
    @Override
    public List<Dict> findByDictCode(String dictCode) {
        //根据dictCode获取对应id
        Dict dict = this.getDictByDictCode(dictCode);
        // 根据id获取子节点
        List<Dict> childData = this.findChlidData(dict.getId());
        return childData;
    }

    private Dict getDictByDictCode(String dictCode) {
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("dict_code", dictCode);
        Dict codeDict = baseMapper.selectOne(wrapper);
        return codeDict;
    }

}

添加controller

package com.bupt.yygh.cmn.controller;

import com.bupt.yygh.cmn.service.DictService;
import com.bupt.yygh.common.result.Result;
import com.bupt.yygh.model.cmn.Dict;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.List;

@Api("数据字典接口")
@RestController
@RequestMapping("/admin/cmn/dict")
//@CrossOrigin
public class DictController {
    @Autowired
    private DictService dictService;

    //根据数据id查询子数据列表
    @ApiOperation(value = "根据数据id查询子数据列表")
    @GetMapping("findChildData/{id}")
    public Result findChildData(@PathVariable Long id) {
        List<Dict> list = dictService.findChlidData(id);
        return Result.ok(list);
    }

    @ApiOperation(value = "导出")
    @GetMapping(value = "/exportData")
    public void exportData(HttpServletResponse response) {
        dictService.exportData(response);
    }

    @ApiOperation(value = "导入")
    @PostMapping("importData")
    public Result importData(MultipartFile file) {
        dictService.importData(file);
        return Result.ok();
    }

//    //导入数据字典
//    @PostMapping("importData")
//    public Result importDict(MultipartFile file) {
//        dictService.importDictData(file);
//        return Result.ok();
//    }
//
//    //导出数据字典接口
//    @GetMapping("exportData")
//    public void exportDict(HttpServletResponse response) {
//        dictService.exportDictData(response);
//    }

    //根据dictCode获取下级节点
    //比如查询到省份这个字段的节点,那么通过他对应的id,去找下面谁的父id为这个id
    //找到的就是其下的具体数据
    @ApiOperation(value = "根据dictCode获取下级节点")
    @GetMapping("findByDictCode/{dictCode}")
    public Result findByDictCode(@PathVariable String dictCode) {
        List<Dict> list = dictService.findByDictCode(dictCode);
        return Result.ok(list);
    }

    //根据dictcode和value查询
    @GetMapping("getName/{dictCode}/{value}")
    public String getName(@PathVariable String dictCode,
                          @PathVariable String value) {
        String dictName = dictService.getDictName(dictCode, value);
        return dictName;
    }

    //根据value查询
    @GetMapping("getName/{value}")
    public String getName(@PathVariable String value) {
        String dictName = dictService.getDictName("", value);
        return dictName;
    }
}

封装Feign服务调用

我们的cmn是服务提供者,hosp是消费者,那么还需要建立他俩以及注册中心的连接
搭建模块
在这里插入图片描述
添加Feign接口类

package com.bupt.yygh.cmn.client;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Repository;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

//需要调用服务的名称
@FeignClient("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);
}

报错
在这里插入图片描述
在service模块引入依赖

<!-- 服务调用feign -->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>

在service-hosp添加依赖

<dependency>
    <groupId>com.atguigu.yygh</groupId>
    <artifactId>service-cmn-client</artifactId>
    <version>1.0</version>
</dependency>

启动类开启服务调用

@SpringBootApplication
@ComponentScan(basePackages = "com.bupt")
@EnableDiscoveryClient
//下面这个注解是为了找到微服务的提供者
@EnableFeignClients(basePackages = "com.bupt")
public class ServiceHospApplication {
    public static void main(String[] args) {
        SpringApplication.run(ServiceHospApplication.class, args);
    }
}

前端代码略

此时测试一下
发现报错

在这里插入图片描述

在这里插入图片描述

后端部分是可以启动的
在这里插入图片描述
我怀疑是跨域问题,于是考虑配置网关

配置网关

之前用nginx不能解决跨域
每次都要在controller上加crossorigin注解
用spring cloud gateway来解决会更好
算是技术使用的一种升级

启动报错
在这里插入图片描述
是因为我的80端口被占用,需要把nginx关掉
配置了网关,还在报这个错误
在这里插入图片描述
但另外的服务都是正常的
并且转发的URL也是localhost而不是localhost:9001了

问题解决:注意观察
我们上面的报错信息
是list/1/10/一大堆东西
但是我们后端传参只传了

@GetMapping("list/{page}/{limit}")

也就是有一个参数我们是没有的,我就去看前端代码
在src\api\hosp.js下
我们写了一个获取医院列表的方法
应该是

  getHospList(page, limit, searchObj) {
    return request({
      url: `/admin/hosp/hospital/list/${page}/${limit}`,
      method: 'get',
      params: searchObj
    })

我写成了

      url: `/admin/hosp/hospital/list/${page}/${limit}/${searchObj}`,

诶唷,找了半天
看看效果

使用idea配置前端代码(抛弃掉VSCODE)

因为我目前用idea上传代码到码云上很容易,VSCODE不太行
所以我尝试在idea上配置前端代码,然后上传到gitee很方便
参考博客
在这里插入图片描述
启动
正常运行
然后上传代码到gitee里面,
在这里插入图片描述

从gitee里下载代码到本地

平时都是用工位电脑做开发的,现在需要用自己的电脑做开发,于是把gitee上代码得克隆下来,在这里走一遍流程。
参考博客

下载到本地后导入idea,参考博客

我自己的电脑要使用前端代码,还得先下载node.js
最好把VSCODE那一套走一遍,把环境配置好
再用idea打开正常使用
当然也可以直接在idea中打开终端

在这里插入图片描述
选中terminal
再通过cd命令切换到对应目录即可

实现医院列表功能

具体代码略,参考码云仓库尚医通后端代码第八次提交

查看医院详情
请添加图片描述
上线下线
请添加图片描述
排班列表
请添加图片描述
结束时间:2022-05-29

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值