excel 导入导出和 登录登出接口优化

segment2.0
linrf 2 years ago
parent 1cdbe44852
commit 1a3a6e73d6

@ -6,17 +6,23 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
@RestController
@RequestMapping("/common/")
@Api(value = "通用控制层", tags = "通用控制层")
@Api(value = "通用接口", tags = "通用接口")
@IgnoreValidate
public class CommonController {
@Value("${mybatis-plus.type-enums-package:#{nu11}}")
@ -25,7 +31,6 @@ public class CommonController {
private String appName;
//返回数据库枚举定义的value和display枚举需实现IIntegerEnum接口
@IgnoreValidate
@GetMapping("enum/{enumName}")
@ApiOperation("按枚举名称获取枚举列表值")
public List<EnumItemView> getEnum(@PathVariable String enumName) throws ClassNotFoundException {
@ -47,4 +52,22 @@ public class CommonController {
}
return null;
}
@GetMapping("excelTemplate/download/{fileName}/{filePath}")
@ApiOperation("下载excel")
public void downloadExcelTemplate(HttpServletResponse response, @PathVariable("fileName") String fileName, @PathVariable("filePath") String filePath) throws Exception {
//得到该文件
ClassPathResource classPathResource = new ClassPathResource(String.format("/%s/%s", filePath, fileName));
InputStream fileInputStream = classPathResource.getInputStream();
response.setHeader("Content-Disposition", "attachment;Filename=" + URLEncoder.encode(fileName, "UTF-8"));
OutputStream outputStream = response.getOutputStream();
byte[] bytes = new byte[2048];
int len = 0;
while ((len = fileInputStream.read(bytes)) > 0) {
outputStream.write(bytes, 0, len);
}
outputStream.flush();
fileInputStream.close();
outputStream.close();
}
}

@ -17,7 +17,6 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
@ -216,7 +215,4 @@ public interface RcvBasicApi {
*/
@GetMapping("/findByIdAndName")
int findByIdAndName(@RequestParam("id") Serializable id, @RequestParam("name") String name);
@GetMapping("/excelTemplate/download")
void excelTemplateDownload(HttpServletResponse response) throws Exception;
}

@ -42,9 +42,10 @@ public interface RcvSysUserApi {
/**
* 退
* @return
*/
@GetMapping("/logout")
void logout();
boolean logout();
/**
*

@ -0,0 +1,43 @@
package com.docus.server.dto.recovery.rcvbasic;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.metadata.BaseRowModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @ClassName BookInfoExcelModel
* @Description
* @Author ALW
* @Date 2023/3/1 11:25
* @Version 1.0
*/
@Data
@EqualsAndHashCode
public class MedicalInfoExcelModel extends BaseRowModel {
@ExcelProperty(value = "住院号", index = 0)
private String admissId;
@ExcelProperty(value = "住院次数", index = 1)
private Integer admissTimes;
@ExcelProperty(value = "流水号", index = 2)
private String serialNumber;
@ExcelProperty(value = "患者姓名", index = 3)
private String name;
@ExcelProperty(value = "住院医师", index = 4)
private String attendingName;
@ExcelProperty(value = "出院日期", index = 5)
private String disDate;
@ExcelProperty(value = "出院科室编码", index = 6)
private String disDept;
@ExcelProperty(value = "出院科室名称", index = 7)
private String disDeptName;
}

@ -0,0 +1,45 @@
package com.docus.server.dto.recovery.rcvbasic;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.metadata.BaseRowModel;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
* @ClassName BookInfoExcelModel
* @Description
* @Author ALW
* @Date 2023/3/1 11:25
* @Version 1.0
*/
@Data
@EqualsAndHashCode
public class MedicalInfoExcelModelDTO extends BaseRowModel {
private Long id;
@ExcelProperty(value = "住院号", index = 0)
private String admissId;
@ExcelProperty(value = "住院次数", index = 1)
private Integer admissTimes;
@ExcelProperty(value = "流水号", index = 2)
private String serialNumber;
@ExcelProperty(value = "患者姓名", index = 3)
private String name;
@ExcelProperty(value = "住院医师", index = 4)
private String attendingName;
@ExcelProperty(value = "出院日期", index = 5)
private String disDate;
@ExcelProperty(value = "出院科室编码", index = 6)
private String disDept;
@ExcelProperty(value = "出院科室名称", index = 7)
private String disDeptName;
}

@ -1,6 +1,7 @@
package com.docus.server.common.auth;
import com.alibaba.fastjson.JSON;
import com.docus.infrastructure.web.ControllerHelper;
import com.docus.infrastructure.web.exception.ApiException;
import com.docus.infrastructure.web.exception.ExceptionCode;
import com.docus.server.common.IgnoreValidate;
@ -62,8 +63,12 @@ public class TokenInterceptor extends HandlerInterceptorAdapter {
}
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Class<?> controller = handlerMethod.getMethod().getDeclaringClass();
if (handlerMethod.hasMethodAnnotation(IgnoreValidate.class) || controller.getAnnotation(IgnoreValidate.class) != null) {
// Class<?> controller = handlerMethod.getMethod().getDeclaringClass();
// if (handlerMethod.hasMethodAnnotation(IgnoreValidate.class) || controller.getAnnotation(IgnoreValidate.class) != null) {
// //忽略验证
// return super.preHandle(request, response, handler);
// }
if (ControllerHelper.findMethodOrClassLevelAnnotation(handler, IgnoreValidate.class) != null) {
//忽略验证
return super.preHandle(request, response, handler);
}

@ -1,26 +1,33 @@
package com.docus.server.controller;
import com.docus.infrastructure.util.easyexcel.ExcelUtil;
import com.docus.infrastructure.web.exception.ApiException;
import com.docus.infrastructure.web.exception.ExceptionCode;
import com.docus.infrastructure.web.request.SearchDTO;
import com.docus.infrastructure.web.response.PageResult;
import com.docus.server.api.recovery.RcvBasicApi;
import com.docus.server.common.IgnoreValidate;
import com.docus.server.convert.RcvBasicConvert;
import com.docus.server.dto.recovery.rcvbasic.AddRcvBasicDTO;
import com.docus.server.dto.recovery.rcvbasic.DeleteRcvBasicDTO;
import com.docus.server.dto.recovery.rcvbasic.EditRcvBasicDTO;
import com.docus.server.dto.recovery.rcvbasic.MedicalInfoExcelModel;
import com.docus.server.service.IRcvBasicService;
import com.docus.server.validate.MedicalImportExcelValidator;
import com.docus.server.vo.recovery.rcvbasic.RcvBasicVO;
import com.docus.server.vo.recovery.rcvbasic.SearchRcvBasicVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.io.OutputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.List;
@ -35,6 +42,8 @@ import java.util.List;
public class RcvBasicController implements RcvBasicApi {
@Resource
private IRcvBasicService iRcvBasicService;
@Resource
private MedicalImportExcelValidator medicalImportExcelValidator;
/**
*
@ -284,26 +293,28 @@ public class RcvBasicController implements RcvBasicApi {
return iRcvBasicService.findByIdAndName(id, name);
}
// @IgnoreValidate
// @Override
// @ApiOperation("下载病案回收导入基础数据excel模板")
// public void downloadExcelTemplate(HttpServletResponse response) throws Exception {
// super.downloadExcelTemplate(response, "病案回收导入基础数据模板.xlsx", "/tpl/");
// }
@IgnoreValidate
@ApiOperation("下载病案回收导入基础数据excel模板")
@Override
public void excelTemplateDownload(HttpServletResponse response) throws Exception {
// 取要下载的模板名称
String fileName = "病案回收导入基础数据模板.xlsx";
String address = "/tpl/病案回收导入基础数据模板.xlsx";
//得到该文件
ClassPathResource classPathResource = new ClassPathResource(address);
InputStream fileInputStream = classPathResource.getInputStream();
//设置Http响应头告诉浏览器下载这个附件,下载的文件名也是在这里设置的
response.setHeader("Content-Disposition", "attachment;Filename=" + URLEncoder.encode(fileName, "UTF-8"));
OutputStream outputStream = response.getOutputStream();
byte[] bytes = new byte[2048];
int len = 0;
while ((len = fileInputStream.read(bytes)) > 0) {
outputStream.write(bytes, 0, len);
@PostMapping("/importExcel")
@ApiOperation("病案回收基础数据导入模板")
@ApiImplicitParams({
@ApiImplicitParam(name = "file", value = "导入带数据的excel模板", required = true, dataTypeClass = MultipartFile.class)
})
public void importExcel(@RequestPart(value = "file") MultipartFile file, HttpServletRequest request) {
System.out.println("开始导入");
List<Object> excelData = ExcelUtil.readExcel(file, new MedicalInfoExcelModel(), 1, 2);
final int importMax = 100000;
if (excelData.size() > importMax) {
throw new ApiException(ExceptionCode.ParamIllegal.getCode(), "单次导入最多支持" + importMax + "条数据!");
}
outputStream.flush();
fileInputStream.close();
outputStream.close();
medicalImportExcelValidator.validate(excelData);
List<AddRcvBasicDTO> addRcvBasicDTOList = RcvBasicConvert.INSTANCE.convert(excelData);
iRcvBasicService.addRecord(addRcvBasicDTOList);
}
}

@ -44,8 +44,9 @@ public class RcvSysUserController implements RcvSysUserApi {
@ApiOperation("退出登录")
@Override
@IgnoreValidate
public void logout() {
public boolean logout() {
iRcvSysUserService.logout();
return true;
}
/**

@ -1,17 +1,23 @@
package com.docus.server.convert;
import com.docus.core.util.DateUtil;
import com.docus.infrastructure.web.response.PageResult;
import com.docus.server.dto.recovery.rcvbasic.AddRcvBasicDTO;
import com.docus.server.dto.recovery.rcvbasic.EditRcvBasicDTO;
import com.docus.server.dto.recovery.rcvbasic.MedicalInfoExcelModel;
import com.docus.server.entity.recovery.RcvBasic;
import com.docus.server.vo.recovery.rcvbasic.RcvBasicVO;
import com.docus.server.vo.recovery.rcvbasic.SearchRcvBasicVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
import static com.docus.core.util.DateUtil.PATTERN_DATETIME;
/**
*
*
@ -46,5 +52,25 @@ public interface RcvBasicConvert {
@Mappings({})
PageResult<SearchRcvBasicVO> convertPageVO(PageResult<RcvBasic> pageResult);
default List<AddRcvBasicDTO> convert(List<Object> excelData) {
List<AddRcvBasicDTO> list = new ArrayList<>();
MedicalInfoExcelModel medicalInfoExcelModel;
for (Object obj : excelData) {
// 使用的模板下载,可以强转
medicalInfoExcelModel = (MedicalInfoExcelModel) obj;
AddRcvBasicDTO excelModelDTO = convert(medicalInfoExcelModel);
list.add(excelModelDTO);
}
return list;
}
default AddRcvBasicDTO convert(MedicalInfoExcelModel medicalInfoExcelModel) {
AddRcvBasicDTO AddRcvBasicDTO = new AddRcvBasicDTO();
BeanUtils.copyProperties(medicalInfoExcelModel, AddRcvBasicDTO);
AddRcvBasicDTO.setDisDate(DateUtil.parse(medicalInfoExcelModel.getDisDate(), PATTERN_DATETIME));
return AddRcvBasicDTO;
}
}

@ -192,4 +192,7 @@ public interface IRcvBasicService {
* @return
*/
int findByIdAndName(Serializable id, String name);
void addRecord(List<AddRcvBasicDTO> medicalInfoExcelModelDtos);
}

@ -1,6 +1,7 @@
package com.docus.server.service.impl;
import com.docus.core.util.DateUtil;
import com.docus.core.util.ListUtils;
import com.docus.infrastructure.core.db.dao.IBaseDao;
import com.docus.infrastructure.redis.service.IdService;
import com.docus.infrastructure.web.request.SearchDTO;
@ -14,6 +15,7 @@ import com.docus.server.entity.recovery.RcvBasic;
import com.docus.server.enums.RecoveryStateEnum;
import com.docus.server.infrastructure.dao.IRcvBasicDao;
import com.docus.server.service.IRcvBasicService;
import com.docus.server.validate.MedicalImportExcelValidator;
import com.docus.server.vo.recovery.rcvbasic.RcvBasicVO;
import com.docus.server.vo.recovery.rcvbasic.SearchRcvBasicVO;
import org.springframework.stereotype.Service;
@ -21,8 +23,12 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
*
@ -36,6 +42,8 @@ public class RcvBasicServiceImpl implements IRcvBasicService {
private IRcvBasicDao iRcvBasicDao;
@Resource
private IdService idService;
@Resource
private MedicalImportExcelValidator medicalImportExcelValidator;
/**
*
@ -343,5 +351,57 @@ public class RcvBasicServiceImpl implements IRcvBasicService {
return iRcvBasicDao.findByIdAndName(id, name);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void addRecord(List<AddRcvBasicDTO> list) {
Map<String, List<AddRcvBasicDTO>> insertAndUpdateData = separateInsertAndUpdate(list);
List<AddRcvBasicDTO> insertDataList = insertAndUpdateData.get("insert");
List<AddRcvBasicDTO> updateDataList = insertAndUpdateData.get("update");
List<RcvBasic> insert = RcvBasicConvert.INSTANCE.convertAddDOList(insertDataList);
insert.forEach(p -> p.setId(idService.getDateSeq()));
List<RcvBasic> update = RcvBasicConvert.INSTANCE.convertAddDOList(updateDataList);
iRcvBasicDao.saveBatch(insert, IBaseDao.DEFAULT_BATCH_SIZE);
iRcvBasicDao.updateBatchById(update, IBaseDao.DEFAULT_BATCH_SIZE);
}
/**
* @@@ yyyy-MM-dd
*
* @param list
* @return insertupdate
*/
private Map<String, List<AddRcvBasicDTO>> separateInsertAndUpdate(List<AddRcvBasicDTO> list) {
// 定义更新和新增对象容器
List<AddRcvBasicDTO> insertDataList = new ArrayList<>();
List<AddRcvBasicDTO> updateDataList = new ArrayList<>();
// 根据病案号和来源查询所有的数据库病案,进行分离出更新和新增数据
List<String> snList = list.stream()
.map(AddRcvBasicDTO::getSerialNumber)
.distinct().collect(Collectors.toList());
List<RcvBasic> rcvBasicList = iRcvBasicDao.findBy("serialNumber", snList);
Map<String, List<RcvBasic>> stringListMap = ListUtils.groupBy(rcvBasicList, RcvBasic::getSerialNumber);
for (AddRcvBasicDTO modelDto : list) {
// 存在,进行更新
if (medicalImportExcelValidator.isDataBaseExistsAndChangePatientId(modelDto, stringListMap)) {
updateDataList.add(modelDto);
} else {
// 不存在,进行新增
insertDataList.add(modelDto);
}
}
// 将新增和更新数据按照对应key返回
Map<String, List<AddRcvBasicDTO>> separateInsertAndUpdateMap = new HashMap<>();
separateInsertAndUpdateMap.put("insert", insertDataList);
separateInsertAndUpdateMap.put("update", updateDataList);
return separateInsertAndUpdateMap;
}
}

@ -0,0 +1,160 @@
package com.docus.server.validate;
import com.docus.core.util.Func;
import com.docus.infrastructure.core.exception.BaseException;
import com.docus.server.dto.recovery.rcvbasic.AddRcvBasicDTO;
import com.docus.server.dto.recovery.rcvbasic.MedicalInfoExcelModel;
import com.docus.server.entity.recovery.RcvBasic;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@Component
@Slf4j
public class MedicalImportExcelValidator {
public void validate(List<Object> excelData) {
if (Func.isEmpty(excelData)) {
throw new BaseException("导如数据不能为空!");
}
MedicalInfoExcelModel medicalInfoExcelModel;
// 验证重复的病案信息 住院号@住院次数@患者姓名@出院时间 yyyy-MM-dd 组合
Set<String> patientInfos = new HashSet<>();
final String patientInfoTemplate = "%s@%s@%s@%s@%s";
for (Object obj : excelData) {
if (Func.isNull(obj)) {
throw new BaseException("中间行数据不能为空");
}
// 使用的模板下载,可以强转
medicalInfoExcelModel = (MedicalInfoExcelModel) obj;
if (Func.isBlank(medicalInfoExcelModel.getAdmissId())) {
throw new BaseException("住院号不能为空");
}
if (Func.isEmpty(medicalInfoExcelModel.getAdmissTimes())) {
throw new BaseException("住院次数不能为空");
}
if (Func.isNull(medicalInfoExcelModel.getSerialNumber())) {
throw new BaseException("流水号不能为空");
}
if (Func.isBlank(medicalInfoExcelModel.getName())) {
throw new BaseException("患者姓名不能为空");
}
if (Func.isBlank(medicalInfoExcelModel.getAttendingName())) {
throw new BaseException("住院医师不能为空");
}
String excelModelDisDate = medicalInfoExcelModel.getDisDate();
if (Func.isBlank(excelModelDisDate)) {
throw new BaseException("出院日期不能为空!");
}
if (Func.isBlank(medicalInfoExcelModel.getDisDept())) {
throw new BaseException("出院科室编码不能为空");
}
if (Func.isBlank(medicalInfoExcelModel.getDisDeptName())) {
throw new BaseException("出院科室名称不能为空");
}
// 有 / 分隔年月日的,转为 - 进行验证和转换
String transDisDateStr = excelModelDisDate.replace("/", "-");
Date disDate = parseDate(transDisDateStr);
if (Func.isNull(disDate)) {
throw new BaseException("出院日期格式解析错误!" + excelModelDisDate);
}
medicalInfoExcelModel.setDisDate(Func.formatDateTime(disDate));
String disDateStr = Func.formatDate(disDate);
// 住院号@住院次数@患者姓名@出院时间 yyyy-MM-dd 组合
String patientInfo = String.format(patientInfoTemplate,
medicalInfoExcelModel.getAdmissId(),
medicalInfoExcelModel.getAdmissTimes(),
medicalInfoExcelModel.getSerialNumber(),
medicalInfoExcelModel.getName(),
disDateStr);
if (patientInfos.contains(patientInfo)) {
throw new BaseException("本次导入有重复数据,请检查!住院号:"
+ medicalInfoExcelModel.getAdmissId()
+ " 住院次数:" + medicalInfoExcelModel.getAdmissTimes()
+ " 流水号:" + medicalInfoExcelModel.getSerialNumber()
+ " 患者姓名:" + medicalInfoExcelModel.getName()
+ " 出院日期:" + disDateStr);
}
patientInfos.add(patientInfo);
}
}
/**
* Date yyyy-MM-ddyyyy-MM-dd HHyyyy-MM-dd HH:mmyyyy-MM-dd HH:mm:ss
*
* @param dateStr
* @return , null
*/
public static Date parseDate(String dateStr) {
final String dateTimeStr = dateStr.trim();
final String example1 = "yyyy-MM-dd";
final String example2 = "yyyy-MM-dd HH";
final String example3 = "yyyy-MM-dd HH:mm";
final String example4 = "yyyy-MM-dd HH:mm:ss";
try {
if (dateTimeStr.length() == example1.length()) {
return Func.parseDate(dateTimeStr, example1);
}
if (dateTimeStr.length() == example2.length()) {
return Func.parseDate(dateTimeStr, example2);
}
if (dateTimeStr.length() == example3.length()) {
return Func.parseDate(dateTimeStr, example3);
}
return Func.parseDate(dateTimeStr, example4);
} catch (Exception ex) {
log.error(ex.getMessage(), ex);
return null;
}
}
public boolean isDataBaseExistsAndChangePatientId(AddRcvBasicDTO importExcelModelDto, Map<String, List<RcvBasic>> stringListMap) {
if (Func.isNull(stringListMap)) {
return false;
}
String serialNumber = importExcelModelDto.getSerialNumber();
List<RcvBasic> rcvBasics = stringListMap.get(serialNumber);
if (Func.isNotEmpty(rcvBasics)) {
for (RcvBasic basic : rcvBasics) {
if (Func.isNull(basic.getDisDate())) {
continue;
}
if (Func.isNull(basic.getAdmissTimes())) {
continue;
}
if (Func.isBlank(basic.getName())) {
continue;
}
String databaseDisDate = Func.formatDateTime(basic.getDisDate());
String importDataDisDate = Func.formatDateTime(importExcelModelDto.getDisDate());
// 住院次数、患者姓名、出院时间 yyyy-MM-dd 组合,如果存在修改对象的patientId 且返回 true
if (basic.getAdmissTimes().equals(importExcelModelDto.getAdmissTimes())
&& databaseDisDate.equals(importDataDisDate)
&& basic.getName().equals(importExcelModelDto.getName())) {
importExcelModelDto.setId(basic.getId());
return true;
}
}
}
return false;
}
}

@ -13,8 +13,8 @@
<packaging>pom</packaging>
<modules>
<!-- <module>docus-collector-update</module>-->
<module>docus-segmentation</module>
<!-- <module>docus-recovery</module>-->
<!-- <module>docus-segmentation</module>-->
<module>docus-recovery</module>
<module>docus-api-common</module>
<module>docus-client-interface</module>
</modules>
@ -280,4 +280,18 @@
</profiles>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>xlsx</nonFilteredFileExtension>
<nonFilteredFileExtension>xls</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
</plugins>
</build>
</project>

Loading…
Cancel
Save