概述
尚医通(二)
一、数据字典系统
何为数据字典?数据字典就是管理系统常用的分类数据或者一些固定数据,例如:省市区三级联动数据、民族数据、行业数据、学历数据等,由于该系统大量使用这种数据,所以我们要做一个数据管理方便管理系统数据,一般系统基本都会做数据管理。
service下创建service_cmn模块,将dict表逆向工程,配置分页以及swagger
数据库字典分析
parent_id:
上级id,通过id与parent_id构建上下级关系,例如:我们要获取所有行业数据,那么只需要查询parent_id=20000的数据
name:名称,例如:填写用户信息,我们要select标签选择民族,“汉族”就是数据字典的名称
value:值,例如:填写用户信息,我们要select标签选择民族,“1”(汉族的标识)就是数据字典的值
dict_code:编码,编码是我们自定义的,全局唯一,例如:我们要获取行业数据,我们可以通过parent_id获取,但是parent_id是不确定的,所以我们可以根据编码来获取行业数据
假如要获取民族的数据,dict_code = “民族”
element ui 树形表格数据
二、数据字典
这里只写service 实现类
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {
@Autowired
private DictMapper dictMapper;
//根据数据id查询子数据列表
@Override
@Cacheable(value = "dict",keyGenerator = "keyGenerator") //添加缓存
public List<Dict> findChildData(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);
return count > 0;
}
//导出数据字典接口
@Override
public void exportDictData(HttpServletResponse response) {
//设置下载信息
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
String fileName = "dict";
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
//查询数据库
List<Dict> dictList = baseMapper.selectList(null);
//把Dict对象转换成DictEeVo对象
List<DictEeVo> dictVoList = new ArrayList<>(dictList.size());
for(Dict dict :dictList){
DictEeVo dictEeVo = new DictEeVo();
BeanUtils.copyProperties(dict,dictEeVo);
dictVoList.add(dictEeVo);
}
//调用方法进行写操作
try {
EasyExcel.write(response.getOutputStream(), DictEeVo.class)
.sheet("dict")
.doWrite(dictVoList);
} catch (IOException e) {
e.printStackTrace();
}
}
//导入数据字典
@Override
@CacheEvict(value = "dict", allEntries=true) //表示清空缓存中的所有内容
public void importDictData(MultipartFile file) {
try {
EasyExcel.read(file.getInputStream(),DictEeVo.class,new DictListener(dictMapper))
.sheet().doRead();
} catch (IOException e) {
e.printStackTrace();
}
}
//查询名称
@Override
public String getDictName(String dictCode, String value) {
//如果dictCode为空,直接根据value查询
if(StringUtils.isEmpty(dictCode)){
QueryWrapper queryWrapper = new QueryWrapper();
queryWrapper.eq("value",value);
Dict dict = dictMapper.selectOne(queryWrapper);
return dict.getName();
}else{//如果dictCode不为空,根据dictCode和value查询
//根据dictcode查询dict对象,目的是得到dict的id值,在根据此id值查询此id下的子id
QueryWrapper<Dict> queryWrapper1 = new QueryWrapper();
queryWrapper1.eq("dict_code",dictCode);
Dict codeDict = dictMapper.selectOne(queryWrapper1);
Long parent_id = codeDict.getId();
//根据parentId和value值进行查询
QueryWrapper<Dict> queryWrapper2 = new QueryWrapper();
queryWrapper2.eq("parent_id",parent_id).eq("value",value);
Dict finalDict = baseMapper.selectOne(queryWrapper2);
return finalDict.getName();
}
}
//根据dictcode查询查询子节点
@Override
public List<Dict> findByDictCode(String dictCode) {
//根据dictcode获取对应的id
QueryWrapper<Dict> queryWrapper1 = new QueryWrapper();
queryWrapper1.eq("dict_code",dictCode);
Dict codeDict = dictMapper.selectOne(queryWrapper1);
//根据id获取子节点
List<Dict> childData = this.findChildData(codeDict.getId());
return childData;
}
二、Spring Cache Redis
Spring Cache 是一个非常优秀的缓存组件。自Spring 3.1起,提供了类似于@Transactional注解事务的注解Cache支持,且提供了Cache抽象,方便切换各种底层Cache(如:redis)
使用Spring Cache的好处:
1,提供基本的Cache抽象,方便切换各种底层Cache;
2,通过注解Cache可以实现类似于事务一样,缓存逻辑透明的应用到我们的业务代码上,且只需要更少的代码就可以完成;
3,提供事务回滚时也自动回滚缓存;
4,支持比较复杂的缓存逻辑;
service_util配置redis
package com.atguigu.yygh.common.config;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.lang.reflect.Method;
import java.time.Duration;
/**
* @author wangyihui
* @create 2021-04-25 15:40
*/
@Configuration
@EnableCaching // 开启缓存处理
public class RedisConfig {
private RedisCacheManager build;
/**
* 自定义key规则
*
* @return
*/
@Bean
public KeyGenerator keyGenerator() {
return new KeyGenerator() {
@Override
public Object generate(Object target, Method method, Object... params) {
StringBuilder sb = new StringBuilder();
sb.append(target.getClass().getName());
sb.append(method.getName());
for (Object obj : params) {
sb.append(obj.toString());
}
return sb.toString();
}
};
}
/**
* 设置RedisTemplate规则
*
* @param redisConnectionFactory
* @return
*/
@Bean
public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<Object, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
// 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
// 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
//序列号key value
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.setHashKeySerializer(new StringRedisSerializer());
redisTemplate.setHashValueSerializer(jackson2JsonRedisSerializer);
redisTemplate.afterPropertiesSet();
return redisTemplate;
}
/**
* 设置CacheManager缓存规则
*
* @param factory
* @return
*/
@Bean
public CacheManager cacheManager(RedisConnectionFactory factory) {
RedisSerializer<String> redisSerializer = new StringRedisSerializer();
Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
//解决查询缓存转换异常的问题
ObjectMapper om = new ObjectMapper();
om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
jackson2JsonRedisSerializer.setObjectMapper(om);
// 配置序列化(解决乱码的问题),过期时间600秒
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
.entryTtl(Duration.ofSeconds(600))
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jackson2JsonRedisSerializer))
.disableCachingNullValues();
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(config)
.build();
return cacheManager;
}
}
Spring Cache相当于自动缓存,对于redis需要用RedisTemplate不需要手动set,get
常用注解
@Cacheable
根据方法对其返回结果进行缓存,下次请求时,如果缓存存在,则直接读取缓存数据返回;如果缓存不存在,则执行方法,并把返回的结果存入缓存中。一般用在查询方法上。
@CachePut
使用该注解标志的方法,每次都会执行,并将结果存入指定的缓存中。其他方法可以直接从响应的缓存中读取缓存数据,而不需要再去查询数据库。一般用在新增方法上。
@CacheEvict
使用该注解标志的方法,会清空指定的缓存。
spring cache 与redis的区别
1、对于redis的缓存,springcache只支持String,其它的Hash、List、Set、Zset都不支持,所以对于Hash、List、Set、Zset只能用RedisTemplate
2、Spring cache 只支持单表的数据缓存,Redis支持多表的数据缓存
三、整合MongoDB数据库
docker安装mongodb 这里不要配置用用户密码使用mongo
直接原生启动容器
docker run -d --restart=always -p 27017:27017 --name mymongo -v /data/db:/data/db -d mongo
配置mongodb连接,你的mongodb数据库没有yygh_hosp也可以配置连接
#mongodb
spring.data.mongodb.uri=mongodb://47.108.170.87:27017/yygh_hosp
**注意:**这里尽量别使用需要密码验证才能使用mongoDb数据库,不然你远程配置连接贼鸡儿烦
mongodb用来存储医院相关的数据信息
这里要自定义三个MongoDb的dao层,分别对应医院、科室、排版
@Repository
public interface HospitalRepository extends MongoRepository<Hospital,String> {
//判断是否存在数据
Hospital getHospitalByHoscode(String hoscode); //MongoRepository有一套规范,直接按照规范命名,会直接调用写好的方法
//根据医院名称查询
List<Hospital> findHospitalByHosnameLike(String hosname);
}
import com.wang.yygh.model.hosp.Department;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
/**
* @author wangyihui
* @create 2021-11-11 10:03
*/
@Repository
public interface DepartmentRepository extends MongoRepository<Department,String> {
Department getDepartmentByHoscodeAndDepcode(String hoscode, String depcode);
}
import com.wang.yygh.model.hosp.Schedule;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.stereotype.Repository;
import java.util.Date;
import java.util.List;
/**
* @author wangyihui
* @create 2021-11-11 15:51
*/
@Repository
public interface ScheduleRepository extends MongoRepository<Schedule,String> {
//根据医院编号和排班编号进行查询
Schedule getScheduleByHoscodeAndHosScheduleId(String hoscode, String hosScheduleId);
//根据医院编号、科室编号和工作日期,查询排班详情信息
List<Schedule> findScheduleByHoscodeAndDepcodeAndWorkDate(String hoscode, String depcode, Date toDate);
}
service impl
@Service
public class HospitalSevriceImpl implements HospitalService {
@Autowired
private HospitalRepository hospitalRepository;
@Autowired
private DictFeignClient dictFeignClient;
@Override
public void save(Map<String, Object> parapMap) {
//把参数的map集合转换成对象Hospital,方便操作
String mapString = JSONObject.toJSONString(parapMap); //先把map转换成字符串
Hospital hospital = JSONObject.parseObject(mapString, Hospital.class); // 把字符串转换成Hospital对象
//判断是否存在相同数据
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);
//hospitalSetQueryVo转换成hospital对象
Hospital hospital = new Hospital();
BeanUtils.copyProperties(hospitalQueryVo,hospital);
//创建Example对象
Example<Hospital> example = Example.of(hospital,matcher);
//调用方法实现查询
Page<Hospital> pages = hospitalRepository.findAll(example, pageable);
//查询到所有医院集合并遍历,然后获取到医院等级信息
//采用流的方式
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<>();
//根据id查询医院信息并将等级信息也封装进去
Hospital hospital = this.setHospitalHosType(hospitalRepository.findById(id).get());
result.put("hospital",hospital);
//单独处理更直观
result.put("bookingRule", hospital.getBookingRule());
//不需要重复返回
hospital.setBookingRule(null);
return result;
}
//获取医院名称
@Override
public String getHospName(String hoscode) {
Hospital hospital = hospitalRepository.getHospitalByHoscode(hoscode);
if(hospital != null){
return hospital.getHosname();
}
return null;
}
//根据医院名称查询
@Override
public List<Hospital> findByHosname(String hosname) {
List<Hospital> list = hospitalRepository.findHospitalByHosnameLike(hosname);
return list;
}
//根据医院编号获取预约挂号详情
@Override
public Map<String, Object> item(String hoscode) {
Map<String, Object> result = new HashMap<>();
//医院详情
Hospital hospital = this.setHospitalHosType(this.getByHoscode(hoscode));
result.put("hospital", hospital);
//预约规则
result.put("bookingRule", hospital.getBookingRule());
//不需要重复返回
hospital.setBookingRule(null);
return result;
}
//获取查询到的医院集合,遍历进行医院等级封装
private Hospital setHospitalHosType(Hospital hospital) {
//根据dictCode和value获取医院等级名称
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("hostypeString",hostypeString);
hospital.getParam().put("fullAddress",provinceString + cityString + districtString);
return hospital;
}
}
@Service
public class DepartmentServiceImpl implements DepartmentService {
@Autowired
private DepartmentRepository departmentRepository;
//上传科室接口
@Override
public void save(Map<String, Object> parampMap) {
//parampMap转换成Department对象
String parampMapString = JSONObject.toJSONString(parampMap);
Department department = JSONObject.parseObject(parampMapString, Department.class);
//根据医院编号和科室信息进行查询
Department departmentExist = departmentRepository
.getDepartmentByHoscodeAndDepcode(department.getHoscode(),department.getDepcode()); //取名采取spring DATA规范
//判断科室是否存在
if(departmentExist != null){
//如果存在,做更改
departmentExist.setUpdateTime(new Date());
departmentExist.setIsDeleted(0);
departmentRepository.save(departmentExist);
}else{
department.setCreateTime(new Date());
department.setUpdateTime(new Date());
department.setIsDeleted(0);
departmentRepository.save(department);
}
}
//查询科室
@Override
public Page<Department> finPageDepartment(int page, int limit, DepartmentQueryVo departmentQueryVo) {
//MongoRepository开发CRUD
//创建Pageble对象,里面设置当前页和每页记录数
Pageable pageable = PageRequest.of(page - 1,limit); // 当前页从0开始,但是我们从1开始传的
//将departmentQueryVo对象转换为department对象
Department department = new Department();
BeanUtils.copyProperties(departmentQueryVo,department);
department.setIsDeleted(0);
//创建Example对象
ExampleMatcher matcher = ExampleMatcher.matching()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
.withIgnoreCase(true);
Example<Department> example = Example.of(department,matcher);
Page<Department> all = departmentRepository.findAll(example,pageable);
return all;
}
//删除科室
@Override
public void remove(String hoscode, String depcode) {
//根据医院编号和科室编号查询科室信息
Department department = departmentRepository.getDepartmentByHoscodeAndDepcode(hoscode, depcode);
if(depcode != null){
//删除
departmentRepository.deleteById(department.getId());
}
}
//根据医院编号,查询所有科室列表
@Override
public List<DepartmentVo> findDepTree(String hoscode) {
//创建List集合,用于最终数据封装
List<DepartmentVo> result = new ArrayList<>();
//根据医院编号,查询所有科室信息
Department departmentQuery = new Department();
departmentQuery.setHoscode(hoscode);
Example<Department> example = Example.of(departmentQuery);
//所有科室列表信息
List<Department> departmentList = departmentRepository.findAll(example);
//根据大科室编号bigcode进行分组,获取每个大科室里面的下级子科室
Map<String, List<Department>> departmentMap =
departmentList.stream().collect(Collectors.groupingBy(Department::getBigcode));
//遍历map集合
for(Map.Entry<String,List<Department>> entry : departmentMap.entrySet()){
//大科室编号
String bigcode = entry.getKey();
//大科室编号对应的全部数据
List<Department> department1List = entry.getValue();
//封装大科室
DepartmentVo departmentVo1 = new DepartmentVo();
departmentVo1.setDepcode(bigcode);
departmentVo1.setDepname(department1List.get(0).getBigname());
//封装小科室
List<DepartmentVo> children = new ArrayList<>();
for(Department department : department1List){
DepartmentVo departmentVo2 = new DepartmentVo();
departmentVo2.setDepcode(department.getDepcode());
departmentVo2.setDepname(department.getDepname());
//封装到List集合
children.add(departmentVo2);
}
//把小科室list集合放到大科室children里面
departmentVo1.setChildren(children);
//放到最终result里面
result.add(departmentVo1);
}
return result;
}
//根据医院编号和科室编号查询科室名称
@Override
public String getDepName(String hoscode, String depcode) {
Department department = departmentRepository.getDepartmentByHoscodeAndDepcode(hoscode, depcode);
if(department != null){
return department.getDepname();
}
return null;
}
//根据医院编号和科室编号查询科室
@Override
public Department getDepartment(String hoscode, String depcode) {
return departmentRepository.getDepartmentByHoscodeAndDepcode(hoscode, depcode);
}
}
@Service
public class ScheduleServiceImpl extends ServiceImpl<ScheduleMapper,Schedule> implements ScheduleService {
@Autowired
private ScheduleRepository scheduleRepository;
@Autowired
private MongoTemplate mongoTemplate;
@Autowired
private HospitalService hospitalService;
@Autowired
private DepartmentService departmentService;
//上传排班
@Override
public void save(Map<String, Object> parampMap) {
//parampMap转换成Department对象
String parampMapString = JSONObject.toJSONString(parampMap);
Schedule schedule = JSONObject.parseObject(parampMapString, Schedule.class);
//根据医院编号和排班编号进行查询
Schedule scheduleExist = scheduleRepository
.getScheduleByHoscodeAndHosScheduleId(schedule.getHoscode(),schedule.getHosScheduleId()); //取名采取spring DATA规范
//判断排班是否存在
if(scheduleExist != null){
//如果存在,做更改
scheduleExist.setUpdateTime(new Date());
scheduleExist.setIsDeleted(0);
scheduleExist.setStatus(1);
scheduleRepository.save(scheduleExist);
}else{
schedule.setCreateTime(new Date());
schedule.setUpdateTime(new Date());
schedule.setIsDeleted(0);
schedule.setStatus(1);
scheduleRepository.save(schedule);
}
}
//查询科室
@Override
public Page<Schedule> finPageSchedule(int page, int limit, ScheduleQueryVo scheduleQueryVo) {
//MongoRepository开发CRUD
//创建Pageble对象,里面设置当前页和每页记录数
Pageable pageable = PageRequest.of(page - 1,limit); // 当前页从0开始,但是我们从1开始传的
//将departmentQueryVo对象转换为department对象
Schedule schedule = new Schedule();
BeanUtils.copyProperties(scheduleQueryVo,schedule);
schedule.setIsDeleted(0);
schedule.setStatus(1);
//创建Example对象
ExampleMatcher matcher = ExampleMatcher.matching()
.withStringMatcher(ExampleMatcher.StringMatcher.CONTAINING)
.withIgnoreCase(true);
Example<Schedule> example = Example.of(schedule,matcher);
Page<Schedule> all = scheduleRepository.findAll(example,pageable);
return all;
}
//删除排班
@Override
public void remove(String hoscode, String hosScheduleId) {
//根据医院编号和排班编号查询相关信息
Schedule schedule = scheduleRepository.getScheduleByHoscodeAndHosScheduleId(hoscode, hosScheduleId);
if(schedule != null){
scheduleRepository.deleteById(schedule.getId());
}
}
//根据医院编号和科室编号,查询排班规则数据
@Override
public Map<String, Object> getReleSchedule(Long page, Long limit, String hoscode, String depcode) {
//根据医院编号和科室编号查询
Criteria criteria = Criteria.where("hoscode").is(hoscode).and("depcode").is(depcode);
//根据工作日期workdate进行分组 采用MongoTemplate方式
Aggregation agg = Aggregation.newAggregation(
Aggregation.match(criteria), //匹配条件
Aggregation.group("workDate") //分组字段
.first("workDate").as("workDate")
//统计号源数量
.count().as("docCount")
.sum("reservedNumber").as("reservedNumber") //科室可预约数
.sum("availableNumber").as("availableNumber"), //科室剩余预约数
Aggregation.sort(Sort.Direction.DESC,"workDate"),
//实现分页
Aggregation.skip((page - 1) * limit),
Aggregation.limit(limit)
);
//调用方法,最终执行
//BookingScheduleRuleVo封装返回数据
AggregationResults<BookingScheduleRuleVo> aggResults = mongoTemplate.aggregate(agg, Schedule.class, BookingScheduleRuleVo.class);
List<BookingScheduleRuleVo> bookingScheduleRuleVoList = aggResults.getMappedResults();
//分组查询的总记录数
Aggregation totalAgg = Aggregation.newAggregation(
Aggregation.match(criteria),
Aggregation.group("workDate")
);
AggregationResults<BookingScheduleRuleVo> totalAggResultS = mongoTemplate.aggregate(totalAgg, Schedule.class, BookingScheduleRuleVo.class);
int total = totalAggResultS.getMappedResults().size();
//把workDate日期对应的星期获取
for(BookingScheduleRuleVo bookingScheduleRuleVo : bookingScheduleRuleVoList){
Date workDate = bookingScheduleRuleVo.getWorkDate();
String dayOfWeek = this.getDayOfWeek(new DateTime(workDate));
bookingScheduleRuleVo.setDayOfWeek(dayOfWeek);
}
//设置最终数据进行返回
Map<String,Object> result = new HashMap<>();
result.put("bookingScheduleRuleList",bookingScheduleRuleVoList);
result.put("total",total);
//获取医院名称
String hosName = hospitalService.getHospName(hoscode);
//其他基础数据(医院名称)
Map<String, String> baseMap = new HashMap<>();
baseMap.put("hosname",hosName);
result.put("baseMap",baseMap);
return result;
}
//根据医院编号、科室编号和工作日期,查询排班详情信息
@Override
public List<Schedule> getDetailSchedule(String hoscode, String depcode, String workDate) {
//根据参数查询mongodb,得到数据
List<Schedule> scheduleList =
scheduleRepository.findScheduleByHoscodeAndDepcodeAndWorkDate(hoscode,depcode,new DateTime(workDate).toDate());
//把得到的list遍历,向其中添加医院名称、科室名称、日期对应的星期
scheduleList.stream().forEach(item -> {
this.packageSchedule(item);
});
return scheduleList;
}
//获取可预约排班数据
@Override
public Map<String,Object> getBookingScheduleRule(Integer page, Integer limit, String hoscode, String depcode) {
Map<String,Object> result = new HashMap<>();
//根据医院编号获取预约规则
Hospital hospital = hospitalService.getByHoscode(hoscode);
if(hospital == null){
throw new YyghException(ResultCodeEnum.DATA_ERROR);
}
BookingRule bookingRule = hospital.getBookingRule();
//根据预约规则获取可预约数据(分页)
IPage iPage = this.getListData(page,limit,bookingRule);
//获取当前可预约日期
List<Date> dateList = iPage.getRecords();
//获取可预约日期里面科室的剩余数据
Criteria criteria = Criteria.where("hoscode").is(hoscode).and("depcode").is(depcode).and("workDate").in(dateList);
Aggregation agg = Aggregation.newAggregation(
Aggregation.match(criteria),
Aggregation.group("workDate").first("workDate").as("workDate")
.count().as("docCount")
.sum("availableNumber").as("availableNumber")
.sum("reservedNumber").as("reservedNumber")
);
AggregationResults<BookingScheduleRuleVo> aggregateResult = mongoTemplate.aggregate(agg, Schedule.class, BookingScheduleRuleVo.class);
List<BookingScheduleRuleVo> scheduleVoList = aggregateResult.getMappedResults();
//合并数据 map集合 key:日期 value:预约规则和剩余数量等
Map<Date, BookingScheduleRuleVo> scheduleVoMap = new HashMap<>();
if(!CollectionUtils.isEmpty(scheduleVoList)) {
scheduleVoMap = scheduleVoList.stream().collect(Collectors.toMap(BookingScheduleRuleVo::getWorkDate, BookingScheduleRuleVo -> BookingScheduleRuleVo));
}
//获取可预约排版规则
List<BookingScheduleRuleVo> bookingScheduleRuleVoList = new ArrayList<>();
for(int i=0, len=dateList.size(); i<len; i++) {
Date date = dateList.get(i);
//从map集合中根据key日期获取value值
BookingScheduleRuleVo bookingScheduleRuleVo = scheduleVoMap.get(date);
if(bookingScheduleRuleVo == null){
bookingScheduleRuleVo = new BookingScheduleRuleVo();
//就诊医生人数
bookingScheduleRuleVo.setDocCount(0);
//科室剩余预约数 -1表示无号
bookingScheduleRuleVo.setAvailableNumber(-1);
}
bookingScheduleRuleVo.setWorkDate(date);
bookingScheduleRuleVo.setWorkDateMd(date);
//计算当前预约日期对应的星期
String dayOfWeek = this.getDayOfWeek(new DateTime(date));
bookingScheduleRuleVo.setDayOfWeek(dayOfWeek);
//最后一页最后一条记录为即将预约 状态 0:正常 1:即将放号 -1:当天已停止挂号
if(i == len-1 && page == iPage.getPages()) {
bookingScheduleRuleVo.setStatus(1);
} else {
bookingScheduleRuleVo.setStatus(0);
}
//当天预约如果过了停号时间, 不能预约
if(i == 0 && page == 1) {
DateTime stopTime = this.getDateTime(new Date(), bookingRule.getStopTime());
if(stopTime.isBeforeNow()) {
//停止预约
bookingScheduleRuleVo.setStatus(-1);
}
}
bookingScheduleRuleVoList.add(bookingScheduleRuleVo);
}
//可预约日期规则数据
result.put("bookingScheduleList", bookingScheduleRuleVoList);
result.put("total", iPage.getTotal());
//其他基础数据
Map<String, String> baseMap = new HashMap<>();
//医院名称
baseMap.put("hosname", hospitalService.getHospName(hoscode));
//科室
Department department =departmentService.getDepartment(hoscode, depcode);
//大科室名称
baseMap.put("bigname", department.getBigname());
//科室名称
baseMap.put("depname", department.getDepname());
//月
baseMap.put("workDateString", new DateTime().toString("yyyy年MM月"));
//放号时间
baseMap.put("releaseTime", bookingRule.getReleaseTime());
//停号时间
baseMap.put("stopTime", bookingRule.getStopTime());
result.put("baseMap", baseMap);
return result;
}
//根据排班id获取排班数据
@Override
public Schedule getScheduleId(String scheduleId) {
Optional<Schedule> optional = scheduleRepository.findById(scheduleId);
Schedule schedule = optional.get();
return this.packageSchedule(schedule);
}
//根据排班id获取预约下单数据
@Override
public ScheduleOrderVo getScheduleOrderVo(String scheduleId) {
ScheduleOrderVo scheduleOrderVo = new ScheduleOrderVo();
Schedule schedule = this.getScheduleId(scheduleId);
// Schedule schedule = baseMapper.selectById(scheduleId);
if(schedule == null){
throw new YyghException(ResultCodeEnum.PARAM_ERROR);
}
//获取预约规则信息,从hospital中获取
Hospital hospital = hospitalService.getByHoscode(schedule.getHoscode());
if(hospital == null){
throw new YyghException(ResultCodeEnum.PARAM_ERROR);
}
BookingRule bookingRule = hospital.getBookingRule();
if(bookingRule == null){
throw new YyghException(ResultCodeEnum.PARAM_ERROR);
}
//把获取的数据设置到scheduleOrderVo中
scheduleOrderVo.setHoscode(schedule.getHoscode());
scheduleOrderVo.setHosname(hospitalService.getHospName(schedule.getHoscode()));
scheduleOrderVo.setDepcode(schedule.getDepcode());
scheduleOrderVo.setDepname(departmentService.getDepName(schedule.getHoscode(), schedule.getDepcode()));
scheduleOrderVo.setHosScheduleId(schedule.getHosScheduleId());
scheduleOrderVo.setAvailableNumber(schedule.getAvailableNumber());
scheduleOrderVo.setTitle(schedule.getTitle());
scheduleOrderVo.setReserveDate(schedule.getWorkDate());
scheduleOrderVo.setReserveTime(schedule.getWorkTime());
scheduleOrderVo.setAmount(schedule.getAmount());
//退号截止天数(如:就诊前一天为-1,当天为0)
int quitDay = bookingRule.getQuitDay();
DateTime quitTime = this.getDateTime(new DateTime(schedule.getWorkDate()).plusDays(quitDay).toDate(), bookingRule.getQuitTime());
scheduleOrderVo.setQuitTime(quitTime.toDate());
//预约开始时间
DateTime startTime = this.getDateTime(new Date(), bookingRule.getReleaseTime());
scheduleOrderVo.setStartTime(startTime.toDate());
//预约截止时间
DateTime endTime = this.getDateTime(new DateTime().plusDays(bookingRule.getCycle()).toDate(), bookingRule.getStopTime());
scheduleOrderVo.setEndTime(endTime.toDate());
//当天停止挂号时间
DateTime stopTime = this.getDateTime(new Date(), bookingRule.getStopTime());
scheduleOrderVo.setStartTime(stopTime.toDate());
return scheduleOrderVo;
}
//更新排班,用于mq
@Override
public void update(Schedule schedule) {
schedule.setUpdateTime(new Date());
scheduleRepository.save(schedule);
}
//根据预约规则获取可预约数据(分页)
private IPage getListData(Integer page, Integer limit, BookingRule bookingRule) {
//获取当天放号时间 yyyy-MM-dd HH:mm
DateTime releaseTime = this.getDateTime(new Date(), bookingRule.getReleaseTime());
//获取预约周期
Integer cycle = bookingRule.getCycle();
//如果当天放号时间已过,预约周期从后一天开始计算,周期+1
if(releaseTime.isBeforeNow()){
cycle += 1;
}
//获取可预约所有日期,最后一天显示即将放号
List<Date> dateList = new ArrayList<>();
for(int i = 0;i < cycle;i++){
DateTime curDateTime = new DateTime().plusDays(i);
String dateString = curDateTime.toString("yyyy-MM-dd");
dateList.add(new DateTime(dateString).toDate());
}
//因为预约周期不同,每页最多显示7天,预约周期大于7天的要进行分页
List<Date> pageDateList = new ArrayList<>();
int start = (page-1) * limit;
int end = (page -1) * limit + limit;
//如果预约周期<=7,直接显示
if(dateList.size() < end){
end = dateList.size();
}
for(int i = start;i < end;i++){
pageDateList.add(dateList.get(i));
}
//如果>7,则进行分页
IPage<Date> iPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(page,7,dateList.size());
iPage.setRecords(pageDateList);
return iPage;
}
/**
* 将Date日期(yyyy-MM-dd HH:mm)转换为DateTime
*/
private DateTime getDateTime(Date date, String timeString) {
String dateTimeString = new DateTime(date).toString("yyyy-MM-dd") + " "+ timeString;
DateTime dateTime = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm").parseDateTime(dateTimeString);
return dateTime;
}
//把医院名称、科室名称、日期对应的星期封装到排班详情
private Schedule packageSchedule(Schedule schedule) {
//设置医院名称
schedule.getParam().put("hosname",hospitalService.getHospName(schedule.getHoscode()));
//设置科室名称
schedule.getParam().put("depname",departmentService.getDepName(schedule.getHoscode(),schedule.getDepcode()));
//设置日期对应星期
schedule.getParam().put("dayOfWeek",this.getDayOfWeek(new DateTime(schedule.getWorkDate())));
return schedule;
}
/**
* 根据日期获取周几数据
* @param dateTime
* @return
*/
private String getDayOfWeek(DateTime dateTime) {
String dayOfWeek = "";
switch (dateTime.getDayOfWeek()) {
case DateTimeConstants.SUNDAY:
dayOfWeek = "周日";
break;
case DateTimeConstants.MONDAY:
dayOfWeek = "周一";
break;
case DateTimeConstants.TUESDAY:
dayOfWeek = "周二";
break;
case DateTimeConstants.WEDNESDAY:
dayOfWeek = "周三";
break;
case DateTimeConstants.THURSDAY:
dayOfWeek = "周四";
break;
case DateTimeConstants.FRIDAY:
dayOfWeek = "周五";
break;
case DateTimeConstants.SATURDAY:
dayOfWeek = "周六";
default:
break;
}
return dayOfWeek;
}
}
controller:由于统一预约平台要提供接口给外面数据上传形象所以这里弄个api供给外部使用
@RestController
@RequestMapping("/api/hosp")
public class ApiController {
@Autowired
private HospitalService hospitalService;
@Autowired
private HospitalSetService hospitalSetService;
@Autowired
private DepartmentService departmentService;
@Autowired
private ScheduleService scheduleService;
//上传医院接口
@PostMapping("saveHospital")
public Result saveHosp(HttpServletRequest request){
//获取医院传递过来的信息
Map<String, String[]> parameterMap = request.getParameterMap();
//为避免后面遍历,将map中的String[]转换成Object
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//核验签名是否一致
//1.获取医院系统传递过来的签名
String hospSign = (String) parampMap.get("sign");
//2.根据传递过来的医院编码,查询数据库,查询签名
String hoscode = (String) parampMap.get("hoscode");
String signKey = hospitalSetService.getSignKey(hoscode);
//3.把查询出来的签名进行MD5加密
String signKeyMD5 = MD5.encrypt(signKey);
//4.判断签名是否一致
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//图片数据采取base64工具类传输,在传输过程中“+”转换为了“ ”,因此我们要转换回来
String logoData = (String) parampMap.get("logoData");
logoData = logoData.replace(" ","+");
parampMap.put("logoData",logoData);
//调用service的方法
hospitalService.save(parampMap);
return Result.ok();
}
//查询医院接口
@PostMapping("hospital/show")
public Result getHospital(HttpServletRequest request){
//获取医院传递过来的信息
Map<String, String[]> parameterMap = request.getParameterMap();
//为避免后面遍历,将map中的String[]转换成Object
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//获取传递过来的医院编号
String hoscode = (String) parampMap.get("hoscode");
//签名校验
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//调用service方法
Hospital hospital = hospitalService.getByHoscode(hoscode);
return Result.ok(hospital);
}
//上传科室接口
@PostMapping("saveDepartment")
public Result saveDepartment(HttpServletRequest request){
//获取传递过来的科室信息
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//核验签名是否一致
String hospSign = (String) parampMap.get("sign");
String hoscode = (String) parampMap.get("hoscode");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//调用service方法
departmentService.save(parampMap);
return Result.ok();
}
//科室查询接口
@PostMapping("department/list")
public Result findDepartment(HttpServletRequest request){
//获取传递过来的科室信息
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//医院编号
String hoscode = (String) parampMap.get("hoscode");
//当前页
int page = Integer.parseInt((String) parampMap.get("page"));
if(StringUtils.isEmpty(page)){
page = 1;
}
//每页显示记录数
int limit = Integer.parseInt((String) parampMap.get("limit"));
if(StringUtils.isEmpty(limit)){
limit = 1;
}
//签名校验
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//调用service查询
//查询条件的值封装到departmentQueryVo中
DepartmentQueryVo departmentQueryVo = new DepartmentQueryVo();
departmentQueryVo.setHoscode(hoscode);
Page<Department> pageModel = departmentService.finPageDepartment(page,limit,departmentQueryVo);
return Result.ok(pageModel);
}
//删除科室接口
@PostMapping("department/remove")
public Result removeDepartment(HttpServletRequest request){
//获取传递过来的科室信息
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//获取医院编号和科室编号
String hoscode = (String) parampMap.get("hoscode");
String depcode = (String) parampMap.get("depcode");
//签名校验
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
departmentService.remove(hoscode,depcode);
return Result.ok();
}
//上传排班
@PostMapping("saveSchedule")
public Result saveSchedule(HttpServletRequest request){
//获取传递过来的科室信息
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//签名校验
String hospSign = (String) parampMap.get("sign");
String hoscode = (String) parampMap.get("hoscode");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//调用service方法
scheduleService.save(parampMap);
return Result.ok();
}
//查询排班
@PostMapping("schedule/list")
public Result findSchedule(HttpServletRequest request) {
//获取传递过来的科室信息
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//医院编号
String hoscode = (String) parampMap.get("hoscode");
//科室编号
String depcode = (String) parampMap.get("depcode");
//当前页
int page = Integer.parseInt((String) parampMap.get("page"));
if (StringUtils.isEmpty(page)) {
page = 1;
}
//每页显示记录数
int limit = Integer.parseInt((String) parampMap.get("limit"));
if (StringUtils.isEmpty(limit)) {
limit = 1;
}
//签名校验
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if (!hospSign.equals(signKeyMD5)) {
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//调用service查询
//查询条件的值封装到departmentQueryVo中
ScheduleQueryVo scheduleQueryVo = new ScheduleQueryVo();
scheduleQueryVo.setHoscode(hoscode);
scheduleQueryVo.setDepcode(depcode);
Page<Schedule> pageModel = scheduleService.finPageSchedule(page, limit, scheduleQueryVo);
return Result.ok(pageModel);
}
//删除排班
@PostMapping("schedule/remove")
public Result remove(HttpServletRequest request){
//获取传递过来的科室信息
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//获取医院编号和排班编号
String hoscode = (String) parampMap.get("hoscode");
String hosScheduleId = (String) parampMap.get("hosScheduleId");
//签名校验
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
scheduleService.remove(hoscode,hosScheduleId);
return Result.ok();
}
}
@Api("医院管理接口")
@RestController
@RequestMapping("/api/hosp/hospital")
public class HospitalApiController {
@Autowired
private HospitalService hospitalService;
@Autowired
private DepartmentService departmentService;
@Autowired
private ScheduleService scheduleService;
@Autowired
private HospitalSetService hospitalSetService;
//查询医院列表
@ApiOperation("查询医院列表")
@GetMapping("findHospList/{page}/{limit}")
public Result findHospList(@PathVariable("page") Integer page,
@PathVariable("limit") Integer limit,
HospitalQueryVo hospitalQueryVo){
Page<Hospital> hospitals = hospitalService.selectHospPage(page, limit, hospitalQueryVo);
List<Hospital> content = hospitals.getContent(); //供前端调用
int totalPages = hospitals.getTotalPages(); //供前端调用
return Result.ok(hospitals);
}
//根据医院名称查询
@ApiOperation("根据医院名称查询")
@GetMapping("findByHosname/{hosname}")
public Result findHospList(@PathVariable("hosname") String hosname){
List<Hospital> list = hospitalService.findByHosname(hosname); //模糊查询 可能返回多个,用list接收
return Result.ok(list);
}
//根据医院编号获取科室列表
@ApiOperation("根据医院编号获取科室列表")
@GetMapping("department/{hoscode}")
public Result index(@PathVariable("hoscode") String hoscode){
List<DepartmentVo> list = departmentService.findDepTree(hoscode);
return Result.ok(list);
}
//根据医院编号获取预约挂号详情
@ApiOperation(value = "根据医院编号获取预约挂号详情")
@GetMapping("findHospDetail/{hoscode}")
public Result item(@PathVariable("hoscode") String hoscode){
Map<String,Object> map = hospitalService.item(hoscode);
return Result.ok(map);
}
//获取可预约排班数据
@ApiOperation(value = "获取可预约排班数据")
@GetMapping("auth/getBookingScheduleRule/{page}/{limit}/{hoscode}/{depcode}")
public Result getBookingSchedule(
@ApiParam(name = "page", value = "当前页码", required = true)
@PathVariable Integer page,
@ApiParam(name = "limit", value = "每页记录数", required = true)
@PathVariable Integer limit,
@ApiParam(name = "hoscode", value = "医院code", required = true)
@PathVariable String hoscode,
@ApiParam(name = "depcode", value = "科室code", required = true)
@PathVariable String depcode) {
return Result.ok(scheduleService.getBookingScheduleRule(page, limit, hoscode, depcode));
}
//获取排班具体数据
@ApiOperation(value = "获取排班具体数据")
@GetMapping("auth/findScheduleList/{hoscode}/{depcode}/{workDate}")
public Result findScheduleList(
@ApiParam(name = "hoscode", value = "医院code", required = true)
@PathVariable String hoscode,
@ApiParam(name = "depcode", value = "科室code", required = true)
@PathVariable String depcode,
@ApiParam(name = "workDate", value = "排班日期", required = true)
@PathVariable String workDate) {
return Result.ok(scheduleService.getDetailSchedule(hoscode, depcode, workDate));
}
//根据排班id获取排班数据
@ApiOperation(value = "根据排班id获取排班数据")
@GetMapping("getSchedule/{scheduleId}")
public Result getSchedule(@PathVariable("scheduleId") String scheduleId){
Schedule schedule = scheduleService.getScheduleId(scheduleId);
return Result.ok(schedule);
}
//根据排班id获取预约下单数据
@ApiOperation(value = "根据排班id获取预约下单数据")
@GetMapping("inner/getScheduleOrderVo/{scheduleId}")
public ScheduleOrderVo getScheduleOrderVo(@PathVariable("scheduleId") String scheduleId) {
return scheduleService.getScheduleOrderVo(scheduleId);
}
//获取医院签名信息
@ApiOperation(value = "获取医院签名信息")
@GetMapping("inner/getSignInfoVo/{hoscode}")
public SignInfoVo getSignInfoVo(@PathVariable("hoscode") String hoscode) {
return hospitalSetService.getSignInfoVo(hoscode);
}
}
四、上传医院
上传医院、上传科室,上传排班的信息是在预约统一平台实现的接口,然后由每个医院来调用预约统一平台的接口,上床自己医院的相关信息
这里用hosp_manager来模拟医院上传医院信息
这里有个bug 你的hospital_set表必须有一条id为1的数据
上传医院信息是吧医院的json字符串解析为map 对象然后通过地址保存在mongodb 数据库中
JSONObject respone = HttpRequestHelper.sendRequest(paramMap,this.getApiUrl()+"/api/hosp/saveHospital")
注意这里api 地址是service_hosp里面的端口然后service_hosp实现这里controller 的/api/hosp/saveHospital
service
import com.wang.yygh.model.hosp.Hospital;
import com.wang.yygh.vo.hosp.HospitalQueryVo;
import org.springframework.data.domain.Page;
import java.util.List;
import java.util.Map;
/**
* @author wangyihui
* @create 2021-11-11 18:16
*/
public interface HospitalService {
//上传医院接口
void save(Map<String, Object> parapMap);
//实现根据医院编号查询
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);
//获取医院名称
String getHospName(String hoscode);
//根据医院名称查询
List<Hospital> findByHosname(String hosname);
//根据医院编号获取预约挂号详情
Map<String, Object> item(String hoscode);
}
service impl
@Service
public class HospitalSevriceImpl implements HospitalService {
@Autowired
private HospitalRepository hospitalRepository;
@Autowired
private DictFeignClient dictFeignClient;
@Override
public void save(Map<String, Object> parapMap) {
//把参数的map集合转换成对象Hospital,方便操作
String mapString = JSONObject.toJSONString(parapMap); //先把map转换成字符串
Hospital hospital = JSONObject.parseObject(mapString, Hospital.class); // 把字符串转换成Hospital对象
//判断是否存在相同数据
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);
//hospitalSetQueryVo转换成hospital对象
Hospital hospital = new Hospital();
BeanUtils.copyProperties(hospitalQueryVo,hospital);
//创建Example对象
Example<Hospital> example = Example.of(hospital,matcher);
//调用方法实现查询
Page<Hospital> pages = hospitalRepository.findAll(example, pageable);
//查询到所有医院集合并遍历,然后获取到医院等级信息
//采用流的方式
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<>();
//根据id查询医院信息并将等级信息也封装进去
Hospital hospital = this.setHospitalHosType(hospitalRepository.findById(id).get());
result.put("hospital",hospital);
//单独处理更直观
result.put("bookingRule", hospital.getBookingRule());
//不需要重复返回
hospital.setBookingRule(null);
return result;
}
//获取医院名称
@Override
public String getHospName(String hoscode) {
Hospital hospital = hospitalRepository.getHospitalByHoscode(hoscode);
if(hospital != null){
return hospital.getHosname();
}
return null;
}
//根据医院名称查询
@Override
public List<Hospital> findByHosname(String hosname) {
List<Hospital> list = hospitalRepository.findHospitalByHosnameLike(hosname);
return list;
}
//根据医院编号获取预约挂号详情
@Override
public Map<String, Object> item(String hoscode) {
Map<String, Object> result = new HashMap<>();
//医院详情
Hospital hospital = this.setHospitalHosType(this.getByHoscode(hoscode));
result.put("hospital", hospital);
//预约规则
result.put("bookingRule", hospital.getBookingRule());
//不需要重复返回
hospital.setBookingRule(null);
return result;
}
//获取查询到的医院集合,遍历进行医院等级封装
private Hospital setHospitalHosType(Hospital hospital) {
//根据dictCode和value获取医院等级名称
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("hostypeString",hostypeString);
hospital.getParam().put("fullAddress",provinceString + cityString + districtString);
return hospital;
}
}
controller
@RestController
@RequestMapping("/api/hosp")
public class ApiController {
@Autowired
private HospitalService hospitalService;
@Autowired
private HospitalSetService hospitalSetService;
@Autowired
private DepartmentService departmentService;
@Autowired
private ScheduleService scheduleService;
//上传医院接口
@PostMapping("saveHospital")
public Result saveHosp(HttpServletRequest request){
//获取医院传递过来的信息
Map<String, String[]> parameterMap = request.getParameterMap();
//为避免后面遍历,将map中的String[]转换成Object
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//核验签名是否一致
//1.获取医院系统传递过来的签名
String hospSign = (String) parampMap.get("sign");
//2.根据传递过来的医院编码,查询数据库,查询签名
String hoscode = (String) parampMap.get("hoscode");
String signKey = hospitalSetService.getSignKey(hoscode);
//3.把查询出来的签名进行MD5加密
String signKeyMD5 = MD5.encrypt(signKey);
//4.判断签名是否一致
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//图片数据采取base64工具类传输,在传输过程中“+”转换为了“ ”,因此我们要转换回来
String logoData = (String) parampMap.get("logoData");
logoData = logoData.replace(" ","+");
parampMap.put("logoData",logoData);
//调用service的方法
hospitalService.save(parampMap);
return Result.ok();
}
//查询医院接口
@PostMapping("hospital/show")
public Result getHospital(HttpServletRequest request){
//获取医院传递过来的信息
Map<String, String[]> parameterMap = request.getParameterMap();
//为避免后面遍历,将map中的String[]转换成Object
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//获取传递过来的医院编号
String hoscode = (String) parampMap.get("hoscode");
//签名校验
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//调用service方法
Hospital hospital = hospitalService.getByHoscode(hoscode);
return Result.ok(hospital);
}
//上传科室接口
@PostMapping("saveDepartment")
public Result saveDepartment(HttpServletRequest request){
//获取传递过来的科室信息
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//核验签名是否一致
String hospSign = (String) parampMap.get("sign");
String hoscode = (String) parampMap.get("hoscode");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//调用service方法
departmentService.save(parampMap);
return Result.ok();
}
//科室查询接口
@PostMapping("department/list")
public Result findDepartment(HttpServletRequest request){
//获取传递过来的科室信息
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//医院编号
String hoscode = (String) parampMap.get("hoscode");
//当前页
int page = Integer.parseInt((String) parampMap.get("page"));
if(StringUtils.isEmpty(page)){
page = 1;
}
//每页显示记录数
int limit = Integer.parseInt((String) parampMap.get("limit"));
if(StringUtils.isEmpty(limit)){
limit = 1;
}
//签名校验
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//调用service查询
//查询条件的值封装到departmentQueryVo中
DepartmentQueryVo departmentQueryVo = new DepartmentQueryVo();
departmentQueryVo.setHoscode(hoscode);
Page<Department> pageModel = departmentService.finPageDepartment(page,limit,departmentQueryVo);
return Result.ok(pageModel);
}
//删除科室接口
@PostMapping("department/remove")
public Result removeDepartment(HttpServletRequest request){
//获取传递过来的科室信息
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//获取医院编号和科室编号
String hoscode = (String) parampMap.get("hoscode");
String depcode = (String) parampMap.get("depcode");
//签名校验
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
departmentService.remove(hoscode,depcode);
return Result.ok();
}
//上传排班
@PostMapping("saveSchedule")
public Result saveSchedule(HttpServletRequest request){
//获取传递过来的科室信息
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//签名校验
String hospSign = (String) parampMap.get("sign");
String hoscode = (String) parampMap.get("hoscode");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//调用service方法
scheduleService.save(parampMap);
return Result.ok();
}
//查询排班
@PostMapping("schedule/list")
public Result findSchedule(HttpServletRequest request) {
//获取传递过来的科室信息
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//医院编号
String hoscode = (String) parampMap.get("hoscode");
//科室编号
String depcode = (String) parampMap.get("depcode");
//当前页
int page = Integer.parseInt((String) parampMap.get("page"));
if (StringUtils.isEmpty(page)) {
page = 1;
}
//每页显示记录数
int limit = Integer.parseInt((String) parampMap.get("limit"));
if (StringUtils.isEmpty(limit)) {
limit = 1;
}
//签名校验
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if (!hospSign.equals(signKeyMD5)) {
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
//调用service查询
//查询条件的值封装到departmentQueryVo中
ScheduleQueryVo scheduleQueryVo = new ScheduleQueryVo();
scheduleQueryVo.setHoscode(hoscode);
scheduleQueryVo.setDepcode(depcode);
Page<Schedule> pageModel = scheduleService.finPageSchedule(page, limit, scheduleQueryVo);
return Result.ok(pageModel);
}
//删除排班
@PostMapping("schedule/remove")
public Result remove(HttpServletRequest request){
//获取传递过来的科室信息
Map<String, String[]> parameterMap = request.getParameterMap();
Map<String, Object> parampMap = HttpRequestHelper.switchMap(parameterMap);
//获取医院编号和排班编号
String hoscode = (String) parampMap.get("hoscode");
String hosScheduleId = (String) parampMap.get("hosScheduleId");
//签名校验
String hospSign = (String) parampMap.get("sign");
String signKey = hospitalSetService.getSignKey(hoscode);
String signKeyMD5 = MD5.encrypt(signKey);
if(!hospSign.equals(signKeyMD5)){
throw new YyghException(ResultCodeEnum.SIGN_ERROR);
}
scheduleService.remove(hoscode,hosScheduleId);
return Result.ok();
}
}
医院接口模拟系统 测试数据
{
"hoscode": "1000_0",
"hosname": "北京协和医院",
"hostype": "1",
"provinceCode": "110000",
"cityCode": "110100",
"districtCode": "110102",
"address": "大望路",
"intro": "北京协和医院是集医疗、教学、科研于一体的大型三级甲等综合医院,是国家卫生计生委指定的全国疑难重症诊治指导中心,也是最早承担高干保健和外宾医疗任务的医院之一,以学科齐全、技术力量雄厚、特色专科突出、多学科综合优势强大享誉海内外。在2010、2011、2012、2013、2014年复旦大学医院管理研究所公布的“中国最佳医院排行榜”中连续五年名列榜首。nn医院建成于1921年,由洛克菲勒基金会创办。建院之初,就志在“建成亚洲最好的医学中心”。90余年来,医院形成了“严谨、求精、勤奋、奉献”的协和精神和兼容并蓄的特色文化风格,创立了“三基”、“三严”的现代医学教育理念,形成了以“教授、病案、图书馆”著称的协和“三宝”,培养造就了张孝骞、林巧稚等一代医学大师和多位中国现代医学的领军人物,并向全国输送了大批的医学管理人才,创建了当今知名的10余家大型综合及专科医院。2011年在总结90年发展经验的基础上,创新性提出了“待病人如亲人,提高病人满意度;待同事如家人,提高员工幸福感”新办院理念。nn目前,医院共有2个院区、总建筑面积53万平方米,在职职工4000余名、两院院士5人、临床和医技科室53个、国家级重点学科20个、国家临床重点专科29个、博士点16个、硕士点29个、国家级继续医学教育基地6个、二级学科住院医师培养基地18个、三级学科专科医师培养基地15个。开放住院床位2000余张,单日最高门诊量约1.5万人次、年出院病人约8万余人次。被评为“全国文明单位”、“全国创先争优先进基层党组织”、“全国卫生系统先进集体”、“首都卫生系统文明单位”、“最受欢迎三甲医院”,荣获全国五一劳动奖章。同时,医院还承担着支援老少边穷地区、国家重要活动和突发事件主力医疗队的重任,在2008年北京奥运工作中荣获“特别贡献奖”。nn90多年来,协和人以执着的医志、高尚的医德、精湛的医术和严谨的学风书写了辉煌的历史,今天的协和人正为打造“国际知名、国内一流”医院的目标而继续努力。",
"route": "东院区乘车路线:106、108、110、111、116、684、685路到东单路口北;41、104快、814路到东单路口南;1、52、802路到东单路口西;20、25、37、39路到东单路口东;103、104、420、803路到新东安市场;地铁1、5号线到东单。n西院区乘车路线:68路到辟才胡同东口;更多乘车路线详见须知。",
"logoData": "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",
"bookingRule": {
"cycle": "10",
"releaseTime": "08:30",
"stopTime": "11:30",
"quitDay": "-1",
"quitTime": "15:30",
"rule": [
"西院区预约号取号地点:西院区门诊楼一层大厅挂号窗口取号",
"东院区预约号取号地点:东院区老门诊楼一层大厅挂号窗口或新门诊楼各楼层挂号/收费窗口取号"
]
}
}
注意这里上传的医院信息以及模拟系统和统一挂号的医院信息一致
上传科室与上传医院信息一样,先本地处理然后交割统一预约平台进行保存
@Override
public boolean saveDepartment(String data) {
JSONArray jsonArray = new JSONArray();
if(!data.startsWith("[")) {
JSONObject jsonObject = JSONObject.parseObject(data);
jsonArray.add(jsonObject);
} else {
jsonArray = JSONArray.parseArray(data);
}
for(int i=0, len=jsonArray.size(); i<len; i++) {
JSONObject jsonObject = jsonArray.getJSONObject(i);
Map<String, Object> paramMap = new HashMap<>();
paramMap.put("hoscode",this.getHoscode());
paramMap.put("depcode",jsonObject.getString("depcode"));
paramMap.put("depname",jsonObject.getString("depname"));
paramMap.put("intro",jsonObject.getString("intro"));
paramMap.put("bigcode", jsonObject.getString("bigcode"));
paramMap.put("bigname",jsonObject.getString("bigname"));
paramMap.put("timestamp", HttpRequestHelper.getTimestamp());
paramMap.put("sign",MD5.encrypt(this.getSignKey()));
JSONObject respone = HttpRequestHelper.sendRequest(paramMap,this.getApiUrl()+"/api/hosp/saveDepartment");
System.out.println(respone.toJSONString());
if(null == respone || 200 != respone.getIntValue("code")) {
throw new YyghException(respone.getString("message"), 201);
}
}
return true;
}
发送过去之前进行自定义MD5加密,预约统一挂号平台接受之后又拿出签名进行解密,然后从数据库里面进行比对如果有,则将科室保存在mongodb数据库中
map转换为科室对象,添加之前根据医院编号和科室编号查询,有就更新,没有就添加
医院的排班信息,一个科室里面有很多医生,每个医生的出诊时间都是不一样,
最后
以上就是笑点低雪糕为你收集整理的尚医通(二)尚医通(二)的全部内容,希望文章能够帮你解决尚医通(二)尚医通(二)所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复