Browse Source

Merge branch 'sd' of dd.tall.wiki:ccsens_wiki/ccsenscloud into sd

sd
zy_Java 4 years ago
parent
commit
05a6978dcb
  1. 19
      ht/src/main/java/com/ccsens/ht/api/PatientReportExportController.java
  2. 14
      ht/src/main/java/com/ccsens/ht/api/QuestionController.java
  3. 16
      ht/src/main/java/com/ccsens/ht/bean/dto/PatientReportDto.java
  4. 25
      ht/src/main/java/com/ccsens/ht/bean/dto/QuestionDto.java
  5. 109
      ht/src/main/java/com/ccsens/ht/bean/vo/PatientReportVo.java
  6. 15
      ht/src/main/java/com/ccsens/ht/bean/vo/QuestionVo.java
  7. 54
      ht/src/main/java/com/ccsens/ht/persist/dao/HtPatientReportDao.java
  8. 18
      ht/src/main/java/com/ccsens/ht/persist/dao/HtPatientReportRecordDescDao.java
  9. 5
      ht/src/main/java/com/ccsens/ht/service/IPatientReportService.java
  10. 33
      ht/src/main/java/com/ccsens/ht/service/IQuestionService.java
  11. 407
      ht/src/main/java/com/ccsens/ht/service/PatientReportService.java
  12. 44
      ht/src/main/java/com/ccsens/ht/service/QuestionService.java
  13. 49
      ht/src/main/java/com/ccsens/ht/uitl/Constant.java
  14. 4
      ht/src/main/resources/application.yml
  15. 150
      ht/src/main/resources/mapper_dao/HtPatientReportDao.xml
  16. 12
      ht/src/main/resources/mapper_dao/HtPatientReportRecordDescDao.xml
  17. 10
      ht/src/main/resources/mapper_dao/HtQuestionDao.xml
  18. 2
      pom.xml
  19. 14
      question/src/main/java/com/ccsens/question/api/PatientReportController.java
  20. 12
      question/src/main/java/com/ccsens/question/bean/dto/PatientReportDto.java
  21. 18
      question/src/main/java/com/ccsens/question/bean/vo/PatientReportVo.java
  22. 8
      question/src/main/java/com/ccsens/question/persist/dao/HtPatientReportDao.java
  23. 8
      question/src/main/java/com/ccsens/question/service/IPatientReportService.java
  24. 28
      question/src/main/java/com/ccsens/question/service/PatientReportService.java
  25. 2
      question/src/main/java/com/ccsens/question/uitl/Constant.java
  26. 6
      question/src/main/resources/mapper_dao/HtPatientReportDao.xml
  27. 4
      tall/src/main/resources/application.yml
  28. 10
      util/src/main/java/com/ccsens/util/PdfUtil.java
  29. 516
      util/src/main/java/com/ccsens/util/PoiUtil.java
  30. 3
      util/src/main/java/com/ccsens/util/WebConstant.java

19
ht/src/main/java/com/ccsens/ht/api/PatientReportExportController.java

@ -11,10 +11,7 @@ import com.ccsens.util.bean.dto.QueryDto;
import io.swagger.annotations.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
@ -70,19 +67,19 @@ public class PatientReportExportController {
return JsonResponse.newInstance().ok(export);
}
@MustLogin
@DoctorAudit
// @MustLogin
// @DoctorAudit
@ApiOperation(value = "导出指定id的报告单分析",notes = "导出指定id的报告单分析")
@ApiImplicitParams({
@ApiImplicitParam(name = "json", value = "导出指定id的报告单分析", required = true)
})
@RequestMapping(value="/exportAnalyse", method = RequestMethod.POST)
public void exportAnalyse(@RequestBody @ApiParam @Valid QueryDto<List<PatientReportDto.ExportSpecial>> param, HttpServletResponse response) throws IOException {
@RequestMapping(value="/exportAnalyse", method = RequestMethod.GET)
public void exportAnalyse(@RequestParam(value = "ids")@ApiParam @Valid List<Long> ids, HttpServletResponse response) throws IOException {
//查询报告单信息
log.info("导出指定报告单分析:{}", param);
Workbook workbook = patientReportService.exportAnalyse(param.getParam(), param.getUserId());
log.info("导出指定报告单分析:{}", ids);
Workbook workbook = patientReportService.exportAnalyse(ids);
log.info("导出报告单分析结束");
String fileName = "报告单信息";
String fileName = "报告单信息.xlsx";
response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, CharsetUtil.UTF_8));
workbook.write(response.getOutputStream());
}

14
ht/src/main/java/com/ccsens/ht/api/QuestionController.java

@ -91,6 +91,19 @@ public class QuestionController {
return JsonResponse.newInstance().ok(patientCanvas);
}
@MustLogin
@DoctorAudit
@ApiOperation(value = "保存题目的其他记录",notes = "whj:保存题目的其他记录")
@ApiImplicitParams({
})
@RequestMapping(value="/saveRecord", method = RequestMethod.POST)
public JsonResponse saveRecord(@RequestBody @ApiParam @Valid QueryDto<QuestionDto.Record> queryDto) {
log.info("保存题目的其他记录:{}", queryDto);
questionService.saveRecord(queryDto.getParam(), queryDto.getUserId());
log.info("保存题目的其他记录成功");
return JsonResponse.newInstance().ok();
}
@MustLogin
@DoctorAudit
@ApiOperation(value = "查看用户画图信息",notes = "zy:查看画板信息画图轨迹等")
@ -116,4 +129,5 @@ public class QuestionController {
log.info("删除画图轨迹成功");
return JsonResponse.newInstance().ok();
}
}

16
ht/src/main/java/com/ccsens/ht/bean/dto/PatientReportDto.java

@ -99,8 +99,18 @@ public class PatientReportDto {
}
@ApiModel("导出报告单分析-请求")
@Data
public static class ExportSpecial{
@ApiModelProperty("报告单ID")
private Long id;
// public ExportSpecial() {
// }
//
// public ExportSpecial(Long id) {
// this.id = id;
// }
}
/**医生对报告单权限*/
@ -131,6 +141,8 @@ public class PatientReportDto {
@ApiModel("查询报告单")
@Data
public static class AdminQueryReport {
@ApiModelProperty("病人名字")
private String patientName;
@ApiModelProperty("病人年龄-开始")
private Byte startAge;
@ApiModelProperty("病人年龄-结束")
@ -168,9 +180,9 @@ public class PatientReportDto {
@ApiModelProperty("量表类型")
private String code;
@ApiModelProperty("开始")
private Integer start;
private Double start;
@ApiModelProperty("结束")
private Integer end;
private Double end;
}
@ApiModel("临床诊断统计请求")

25
ht/src/main/java/com/ccsens/ht/bean/dto/QuestionDto.java

@ -5,6 +5,7 @@ import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.servlet.http.Part;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.io.File;
import java.math.BigDecimal;
@ -76,6 +77,30 @@ public class QuestionDto {
@ApiModelProperty("超出占比")
private String beyondProportion;
}
@Data
@ApiModel("其他记录-request")
public static class Record{
@NotNull
@ApiModelProperty("病人报告单ID")
private Long patientReportId;
@NotNull
@ApiModelProperty("其他记录答案")
private List<RecordDetail> details;
}
@Data
@ApiModel("其他记录答案-request")
public static class RecordDetail{
@ApiModelProperty("试题ID")
@NotNull(message = "试题ID不能为空")
private Long recordId;
@NotEmpty
@ApiModelProperty("答案")
private List<String> answers;
}
@Data
@ApiModel("画板信息")
public static class Canvas{

109
ht/src/main/java/com/ccsens/ht/bean/vo/PatientReportVo.java

@ -14,9 +14,9 @@ import java.math.BigDecimal;
import java.util.*;
/**
* @program: ptpro
* @program: ht
* @description:
* @author: wu huijuan
* @author: whj
* @create: 2019/10/31 10:28
*/
public class PatientReportVo {
@ -150,7 +150,7 @@ public class PatientReportVo {
}
PdfUtil.Row fourRow = new PdfUtil.Row();
PdfUtil.Cell cell = new PdfUtil.Cell();
cell.setContent("临床诊断:" );
cell.setContent("临床诊断:" + (StrUtil.isEmpty(this.clinicalDiagnosis) ? "" : this.clinicalDiagnosis) );
cell.setCenter(false);
cell.setColSpan(2);
cell.setBorderLeft(0);
@ -190,15 +190,15 @@ public class PatientReportVo {
rows.add(
fillRow(
"文化程度:" + this.educationalStatusUnit + "年",
"编号:" + this.serialNumber,
"编号:" + (StrUtil.isEmpty(this.serialNumber) ? "" : this.serialNumber),
"职业:" + careerMap.get(this.career))
);
//第三栏
rows.add(
fillRow(
"科别:" + this.department,
"床号:" + this.bedNumber,
"病案号:" + this.hospitalNumber)
"科别:" + (StrUtil.isEmpty(this.department) ? "" : this.department),
"床号:" + (StrUtil.isEmpty(this.bedNumber) ? "" : this.bedNumber),
"病案号:" + (StrUtil.isEmpty(this.hospitalNumber) ? "" : this.hospitalNumber))
);
return rows;
}
@ -345,7 +345,7 @@ public class PatientReportVo {
fillMmseOrNpi(headNum, rows, mmse, npi);
break;
case Constant.Ht.Report.MOCA:
fillMoca(rows);
fillSingleMoca(rows);
break;
default:
fillCommon(rows);
@ -363,6 +363,16 @@ public class PatientReportVo {
private void fillMMSE(List<PdfUtil.Row> rows) {
List<ReportScore> mmseList = new ArrayList<>();
dealMMSE(this, mmseList);
PdfUtil.Row row = new PdfUtil.Row();
PdfUtil.Cell purposeCell = new PdfUtil.Cell(Constant.Export.MMSE_PURPOSE);
purposeCell.setColSpan(8);
purposeCell.setBorderRight(1);
purposeCell.setCenter(false);
purposeCell.setHeight(36);
row.addCell(purposeCell);
rows.add(row);
PdfUtil.Row titleRow = new PdfUtil.Row();
PdfUtil.Row scoreRow = new PdfUtil.Row();
for (int i = 0; i < mmseList.size() ; i++) {
@ -486,8 +496,29 @@ public class PatientReportVo {
rows.add(row2);
}
private void fillMoca(List<PdfUtil.Row> rows) {
fillMocaScore(rows);
}
private void fillSingleMoca(List<PdfUtil.Row> rows) {
//moca
PdfUtil.Row row = new PdfUtil.Row();
PdfUtil.Cell purposeCell = new PdfUtil.Cell(Constant.Export.MOCA_PURPOSE);
purposeCell.setColSpan(8);
purposeCell.setCenter(false);
purposeCell.setBorderRight(1);
purposeCell.setHeight(36);
row.addCell(purposeCell);
rows.add(row);
fillMocaScore(rows);
}
private void fillMocaScore(List<PdfUtil.Row> rows) {
int firstIndex = 5;
PdfUtil.Row row1 = new PdfUtil.Row();
PdfUtil.Cell cell = new PdfUtil.Cell();
@ -604,8 +635,7 @@ public class PatientReportVo {
}
}
/**医生对报告单权限*/
@ApiModel("PatientReportVoAuthority")
@ApiModel("医生对报告单权限")
@Data
public static class Authority{
@ApiModelProperty("对报告单的操作权限 0:仅查看 1: 可修改 2:可审查")
@ -735,4 +765,63 @@ public class PatientReportVo {
@ApiModelProperty("答案")
private String answer;
}
@ApiModel("报告单分析导出-vo")
@Data
public static class Analyse{
@ApiModelProperty("报告单ID")
private Long id;
@ApiModelProperty("测评日期")
private Long reportTime;
@ApiModelProperty("患者名字")
private String patientName;
@ApiModelProperty("性别")
private Byte sex;
@ApiModelProperty("年龄")
private Byte patientAge;
@ApiModelProperty("文化程度")
private Byte educationalStatus;
@ApiModelProperty("职业")
private Byte career;
@ApiModelProperty("临床诊断")
private String clinicalDiagnosis;
@ApiModelProperty("严重程度")
private Byte pasi;
@ApiModelProperty("mmse分数")
private List<MMSEScore> mmseScores;
@ApiModelProperty("moca分数")
private List<MoCAScore> mocaScores;
@ApiModelProperty("总分")
private List<TotalScore> totalScores;
}
@ApiModel("mmse分数-导出分析")
@Data
public static class MMSEScore{
@ApiModelProperty("code")
private String code;
@ApiModelProperty("分数")
private BigDecimal score;
}
@ApiModel("moca分数-导出分析")
@Data
public static class MoCAScore{
@ApiModelProperty("题目排序")
private int sort;
@ApiModelProperty("分数")
private BigDecimal score;
}
@ApiModel("量表总分数-导出分析")
@Data
public static class TotalScore{
@ApiModelProperty("量表类型")
private String evaluationCode;
@ApiModelProperty("总评分")
private BigDecimal totalScore;
}
}

15
ht/src/main/java/com/ccsens/ht/bean/vo/QuestionVo.java

@ -204,6 +204,19 @@ public class QuestionVo {
private List<String> answers;
@ApiModelProperty("选项")
private List<RecordOption> options;
public List<RecordOption> getOptions() {
if (CollectionUtil.isNotEmpty(answers) && CollectionUtil.isNotEmpty(options)) {
for (RecordOption option: options) {
for (String answer: answers) {
if (option.getDataKey().equals(answer)) {
option.choose = 1;
}
}
}
}
return options;
}
}
@Data
@ApiModel("record的选项")
@ -214,6 +227,8 @@ public class QuestionVo {
private String dataKey;
@ApiModelProperty("显示值")
private String dataValue;
@ApiModelProperty("是否选中 0:否 1:是")
private byte choose = 0;
}
@Data

54
ht/src/main/java/com/ccsens/ht/persist/dao/HtPatientReportDao.java

@ -18,40 +18,41 @@ public interface HtPatientReportDao extends HtPatientReportMapper {
/**
*根据病人报告单ID查询报告单结果
* @param id
*@return: com.ccsens.ht.bean.vo.PatientReportVo.ReprotPatient
*@Author: wuHuiJuan
* @param id 报告单ID
*@return com.ccsens.ht.bean.vo.PatientReportVo.ReprotPatient
*@author wuHuiJuan
*@date: 2019/11/19 11:08
*/
PatientReportVo.ReprotPatient queryReportResult(@Param("id") Long id);
/**
* 根据病人报告单ID查询报告单各项相关分数
* @param id 报告单ID
* @param rey 是否查询rey
* @param report 报告单类型
*@return: com.ccsens.ht.bean.vo.PatientReportVo.ReportScore
*@Author: wuHuiJuan
*@return com.ccsens.ht.bean.vo.PatientReportVo.ReportScore
*@author wuHuiJuan
*@date: 2019/11/19 11:46
*/
List<PatientReportVo.ReportScore> queryReportScore(@Param("id") Long id,@Param("rey") int rey, @Param("report") String report);
/**
* 查询NPI的分数
* @param id
* @return
* @param id 报告单ID
* @return npi分数
*/
List<Map<String, Object>> queryNPIScore(@Param("id") Long id);
List<Map<String, Object>> queryNpiScore(@Param("id") Long id);
/**
* 检查未完成的报告单
* @param userId
* @return
* @param userId 医生ID
* @return 报告单
*/
PatientReportVo.Complete checkComplete(@Param("userId") Long userId);
/**
* 忽略报告单
* @param id
* @param userId
* @param id 报告单ID
* @param userId 用户ID
*/
void ignoreComplete(@Param("id") Long id, @Param("userId") Long userId);
@ -59,35 +60,35 @@ public interface HtPatientReportDao extends HtPatientReportMapper {
* 查询报告单名字ID名字导出路径
* @param doctorId 医生ID
* @param patientId 病人ID
* @return
* @return 报告单id,名字和pdf路径
*/
List<PatientReportVo.ReportName> queryReportName(@Param("doctorId")Long doctorId, @Param("patientId") Long patientId);
/**
* 管理员查询报告单
* @param adminQueryReport
* @return
* @param adminQueryReport 搜索条件
* @return 报告单
*/
List<PatientReportVo.ReportName> queryAllReports(PatientReportDto.AdminQueryReport adminQueryReport);
/**
* 根据临床诊断统计
* @param param
* @return
* @param param 统计条件
* @return 临床诊断统计
*/
List<PatientReportVo.ClinicalDiagnosis> countByClinicalDiagnosis(PatientReportDto.ClinicalDiagnosis param);
/**
* 根据年龄性别统计
* @param param
* @return
* @param param 年龄性别
* @return 年龄性别统计
*/
List<PatientReportVo.AgeAndSex> countBySexAndAge(PatientReportDto.AgeAndSex param);
/**
* 根据日期统计
* @param param
* @return
* @param param 日期
* @return 统计
*/
List<PatientReportVo.Day> countByDay(PatientReportDto.Day param);
@ -95,7 +96,7 @@ public interface HtPatientReportDao extends HtPatientReportMapper {
* 查询报告单的详细答题洗洗
* @param id 报告单id
* @param evaluationCode 测试类型
* @return
* @return 报告单的详细答题明细
*/
List<PatientReportVo.ReportDetailAnswer> queryReportAnswer(@Param("id")Long id, @Param("evaluationCode")String evaluationCode);
@ -110,7 +111,7 @@ public interface HtPatientReportDao extends HtPatientReportMapper {
* 根据病人报告单ID查询报告单各项相关分数
* @param id 报告单ID
* @param code 量表类型
* @return
* @return 报告单分数
*/
List<PatientReportVo.ReportScore> queryReportScore2(@Param("id") Long id, @Param("code") String code);
@ -121,4 +122,11 @@ public interface HtPatientReportDao extends HtPatientReportMapper {
* @return 题目
*/
List<PatientReportVo.QuestionAndAnswer> queryQuestionAndScore(@Param("id") Long id, @Param("code") String code);
/**
*
* @param ids 指定报告单ID
* @return 报告单分数 mmse 分类 moca 试题和分数 其他总分
*/
List<PatientReportVo.Analyse> queryReportAnalyseScore(@Param("ids") List<Long> ids);
}

18
ht/src/main/java/com/ccsens/ht/persist/dao/HtPatientReportRecordDescDao.java

@ -0,0 +1,18 @@
package com.ccsens.ht.persist.dao;
import com.ccsens.ht.bean.po.HtPatientReportRecordDesc;
import com.ccsens.ht.persist.mapper.HtPatientReportRecordDescMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author whj
*/
public interface HtPatientReportRecordDescDao extends HtPatientReportRecordDescMapper {
/**
* 批量保存答案
* @param records 保存答案
*/
void batchSave(@Param("list") List<HtPatientReportRecordDesc> records);
}

5
ht/src/main/java/com/ccsens/ht/service/IPatientReportService.java

@ -168,9 +168,8 @@ public interface IPatientReportService {
/**
* 导出指定报告单分析
* @param param 报告单ID列表
* @param userId 用户ID
* @param ids 报告单ID列表
* @return workbook
*/
Workbook exportAnalyse(List<PatientReportDto.ExportSpecial> param, Long userId);
Workbook exportAnalyse(List<Long> ids);
}

33
ht/src/main/java/com/ccsens/ht/service/IQuestionService.java

@ -17,33 +17,33 @@ public interface IQuestionService {
/**
* 根据类型和题号查询试题
* @param query
* @param userId
* @return
* @param query 类型和题号
* @param userId userId
* @return 试题及相关
*/
QuestionVo.Query queryQuestion(QuestionDto.Query query, Long userId);
/**
* 保存试题得分
* @param score
* @param userId
* @return
* @param score 分数
* @param userId userId
* @return 成功与否
*/
CodeEnum saveScore(QuestionDto.Score score, Long userId) throws IOException, NotSupportedFileTypeException;
CodeEnum saveScore(QuestionDto.Score score, Long userId);
/**
* 保存画图轨迹信息
* @param param
* @param userId
* @return
* @param param 画图
* @param userId userId
* @return 轨迹
*/
List<QuestionVo.PatientCanvas> saveCanvas(QuestionDto.SavePatientCanvas param, Long userId);
/**
* 查看用户画图信息
* @param param
* @param userId
* @return
* @param param 报告单+试题
* @param userId userId
* @return 画图及分析
*/
List<QuestionVo.PatientCanvas> getCanvas(QuestionDto.QueryPatientCanvas param, Long userId);
@ -61,4 +61,11 @@ public interface IQuestionService {
* @param userId userId
*/
void delCanvas(QuestionDto.DelPatientCanvas param, Long userId);
/**
* 保存题目的其他记录
* @param records 记录
* @param userId 用户ID
*/
void saveRecord(QuestionDto.Record records, Long userId);
}

407
ht/src/main/java/com/ccsens/ht/service/PatientReportService.java

@ -8,13 +8,12 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ccsens.ht.bean.dto.PatientReportDto;
import com.ccsens.ht.bean.dto.PatientReportSearchDto;
import com.ccsens.ht.bean.dto.QuestionDto;
import com.ccsens.ht.bean.po.*;
import com.ccsens.ht.bean.vo.PatientReportSearchVo;
import com.ccsens.ht.bean.vo.PatientReportVo;
import com.ccsens.ht.persist.dao.HtDoctorDao;
import com.ccsens.ht.persist.dao.HtPatientReportDao;
import com.ccsens.ht.persist.dao.HtPositionDao;
import com.ccsens.ht.persist.dao.HtReportDao;
import com.ccsens.ht.bean.vo.QuestionVo;
import com.ccsens.ht.persist.dao.*;
import com.ccsens.ht.persist.mapper.HtPatientFollowUpMapper;
import com.ccsens.ht.persist.mapper.HtPatientMapper;
import com.ccsens.ht.persist.mapper.HtPatientReportRecordMapper;
@ -26,6 +25,7 @@ import com.github.pagehelper.PageInfo;
import com.github.pagehelper.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@ -65,6 +65,12 @@ public class PatientReportService implements IPatientReportService {
private HtPatientFollowUpMapper htPatientFollowUpMapper;
@Resource
private HtReportDao htReportDao;
@Resource
private RedisUtil redisUtil;
@Resource
private HtQuestionDao htQuestionDao;
@Resource
private IQuestionService questionService;
@Override
public JsonResponse<PatientReportVo.Generate> generatePatientReport(PatientReportDto.Generate generate, Long userId) {
@ -235,7 +241,7 @@ public class PatientReportService implements IPatientReportService {
}
private void initNPI(long id, PatientReportVo.ReportScore score) {
List<Map<String, Object>> list = htPatientReportDao.queryNPIScore(id);
List<Map<String, Object>> list = htPatientReportDao.queryNpiScore(id);
Map<String,Object> npiScore = new HashMap<>();
list.forEach(map -> npiScore.put((String)map.get("optionName"), map.get("score")));
PatientReportVo.ReportScore carer = new PatientReportVo.ReportScore();
@ -367,7 +373,9 @@ public class PatientReportService implements IPatientReportService {
content.add(row);
initLast(content, 8);
String path = PropUtil.imgDomain + "/" + PdfUtil.createPdf(PropUtil.path, detail.getPatient().getHospital(), Constant.Ht.Report.PARENT_NAME, new PdfUtil.Margin(), detail.getPatient().toPdfRow(), content);
String[] split = detail.getPatient().getHospital().split("");
String title = String.join(" ", split);
String path = PropUtil.imgDomain + "/" + PdfUtil.createPdf(PropUtil.path, title, Constant.Ht.Report.PARENT_NAME, new PdfUtil.Margin(), detail.getPatient().toPdfRow(), content);
report.setUrl(path);
htPatientReportDao.updateByPrimaryKeySelective(report);
log.info("生成文件路径:{}", path);
@ -457,6 +465,19 @@ public class PatientReportService implements IPatientReportService {
@Override
public PageInfo<PatientReportVo.ReportName> queryAllReports(PatientReportDto.AdminQueryReport adminQueryReport, Long userId) {
PageHelper.startPage(adminQueryReport.getPageNum(), adminQueryReport.getPageSize());
List<PatientReportDto.Score> scores = adminQueryReport.getScores();
if (CollectionUtil.isNotEmpty(scores)) {
Iterator<PatientReportDto.Score> iterator = scores.iterator();
while (iterator.hasNext()) {
PatientReportDto.Score next = iterator.next();
if (next.getStart() == null && next.getEnd() == null) {
iterator.remove();
}
}
}
List<PatientReportVo.ReportName> reportNames = htPatientReportDao.queryAllReports(adminQueryReport);
return new PageInfo<>(reportNames);
}
@ -624,33 +645,379 @@ public class PatientReportService implements IPatientReportService {
//查询报告单信息和病人信息
PatientReportVo.ReprotPatient reportPatient = htPatientReportDao.queryReportResult(param.getId());
if (reportPatient == null) {
throw new BaseException(CodeEnum.PARAM_ERROR);
}
//查询报告单分数
List<PatientReportVo.ReportScore> reportScores = htPatientReportDao.queryReportScore2(param.getId(),param.getCode());
if (!Constant.Ht.Report.ADL.equals(param.getCode())) {
getReportScores(param, content, reportScores);
getReportScores(param, content, reportScores, reportPatient);
}
String subHead = CollectionUtil.isEmpty(reportScores) ? "" : reportScores.get(0).getName() + "(" + reportScores.get(0).getCode() + ")报告单";
PdfUtil.Margin margin = new PdfUtil.Margin();
margin.setTop(12);
margin.setBottom(12);
margin.setLeft(36);
String path = PropUtil.imgDomain + "/" + PdfUtil.createPdf(PropUtil.path, reportPatient.getHospital(), subHead, margin , reportPatient.toPdfSimpleCodeRow(),questionTable, content);
margin.setTop(24);
margin.setBottom(24);
margin.setLeft(64);
margin.setRight(64);
String[] split = reportPatient.getHospital().split("");
String title = String.join(" ", split);
String path = PropUtil.imgDomain + "/" + PdfUtil.createPdf(PropUtil.path, title, subHead, margin , reportPatient.toPdfSimpleCodeRow(),questionTable, content);
log.info("{}报告单导出路径:{}", param, path);
return path;
}
@Override
public Workbook exportAnalyse(List<PatientReportDto.ExportSpecial> param, Long userId) {
public Workbook exportAnalyse(List<Long> ids) {
List<PatientReportVo.Analyse> analyses = htPatientReportDao.queryReportAnalyseScore(ids);
int total = 124;
List<List< PoiUtil.PoiUtilCell >> rows = new ArrayList<>();
// 标题 表头
initAnalyseTitle(rows, total);
if (CollectionUtil.isEmpty(analyses)) {
Workbook workbook = new XSSFWorkbook();;
PoiUtil.exportWB("报告单详情", rows, workbook);
return workbook;
}
// 填充数据
for (int i = 0; i < analyses.size(); i++) {
List<PoiUtil.PoiUtilCell> row = new ArrayList<>();
row.add(new PoiUtil.PoiUtilCell(String.valueOf(i+1),1,1));
for (int j = 1; j < total; j++) {
row.add(new PoiUtil.PoiUtilCell("",1,1));
}
fillAnalyse(row, analyses.get(i));
rows.add(row);
}
// PoiUtil.
return null;
Workbook workbook = new XSSFWorkbook();;
PoiUtil.exportWB("报告单详情", rows, workbook);
return workbook;
}
private List<PatientReportVo.ReportScore> getReportScores(PatientReportDto.ExportCode param, List<PdfUtil.Row> content, List<PatientReportVo.ReportScore> reportScores) {
private Long getQuestionId(String code, int sort) {
String key = "ht_question_" + code + "_" + sort;
Object value = redisUtil.get(key);
if (value != null) {
return (Long) value;
}
HtQuestionExample questionExample = new HtQuestionExample();
questionExample.createCriteria().andParentCodeEqualTo(code).andSortEqualTo(sort);
List<HtQuestion> htQuestions = htQuestionDao.selectByExample(questionExample);
if (CollectionUtil.isEmpty(htQuestions)) {
return null;
}
Long id = htQuestions.get(0).getId();
redisUtil.set(key, id);
return id;
}
/**
* 填充导出分析
* @param row 表格
* @param analyse 分析
*/
private void fillAnalyse(List<PoiUtil.PoiUtilCell> row, PatientReportVo.Analyse analyse) {
row.get(1).setValue(DateUtil.format(new Date(analyse.getReportTime()), "yyyy.MM.dd"));
row.get(2).setValue(analyse.getPatientName());
row.get(3).setValue(analyse.getSex() == 0 ? "男" : "女");
row.get(4).setValue(String.valueOf(analyse.getPatientAge()));
row.get(5).setValue(Constant.Ht.getEducational(analyse.getEducationalStatus()));
row.get(6).setValue(Constant.Ht.getCareer(analyse.getCareer()));
row.get(7).setValue(analyse.getClinicalDiagnosis());
row.get(8).setValue(Constant.Ht.getPasi(analyse.getPasi()));
// MMSE分数
if (CollectionUtil.isNotEmpty(analyse.getMmseScores())) {
analyse.getMmseScores().forEach(score->{
switch (score.getCode()) {
case "DXL" : row.get(9).setValue(score.getScore().intValue() + "");break;
case "JYL" : row.get(10).setValue(score.getScore().intValue() + "");break;
case "ZYLHJSL" : row.get(11).setValue(score.getScore().intValue() + "");break;
case "HYNL" : row.get(12).setValue(score.getScore().intValue() + "");break;
case "YYNL" : row.get(13).setValue(score.getScore().intValue() + "");break;
case "JGNL" : row.get(14).setValue(score.getScore().intValue() + "");break;
}
});
}
// MOCA匹配
if (CollectionUtil.isNotEmpty(analyse.getMocaScores())) {
for (int i = 0; i < analyse.getMocaScores().size(); i++) {
PatientReportVo.MoCAScore score = analyse.getMocaScores().get(i);
if (score.getSort() <= 3) {
row.get(15+score.getSort()).setValue(score.getScore().intValue() + "");
} else if (score.getSort() == 4 || score.getSort() == 5 || score.getSort() == 6) {
String value = row.get(19).getValue();
int s = StrUtil.isEmpty(value) ? 0 : Integer.parseInt(value);
row.get(19).setValue(String.valueOf(s + score.getScore().intValue()));
} else if (score.getSort() >= 7 && score.getSort() <= 12) {
row.get(13+score.getSort()).setValue(score.getScore().intValue() + "");
} else if (score.getSort() == 13 || score.getSort() == 14) {
String value = row.get(26).getValue();
int s = StrUtil.isEmpty(value) ? 0 : Integer.parseInt(value);
row.get(26).setValue(String.valueOf(s + score.getScore().intValue()));
} else if (score.getSort() >= 15 && score.getSort() <= 17) {
row.get(12+score.getSort()).setValue(score.getScore().intValue() + "");
} else if (score.getSort()== 20 || score.getSort() == 21) {
row.get(10+score.getSort()).setValue(score.getScore().intValue() + "");
} else if (score.getSort() == 18) {
row.get(32).setValue(score.getScore().intValue() + "");
}
}
}
// 报告单一总成绩
if (CollectionUtil.isNotEmpty(analyse.getTotalScores())) {
analyse.getTotalScores().forEach(totalScore -> {
switch (totalScore.getEvaluationCode()) {
case "MMSE": row.get(15).setValue(totalScore.getTotalScore().intValue() + "");break;
case "MoCA": row.get(33).setValue(totalScore.getTotalScore().intValue() + "");break;
case "ADL": row.get(34).setValue(totalScore.getTotalScore().intValue() + "");break;
case "HAMA": row.get(35).setValue(totalScore.getTotalScore().intValue() + "");break;
case "HAMD": row.get(36).setValue(totalScore.getTotalScore().intValue() + "");break;
case "NPI": row.get(37).setValue(totalScore.getTotalScore().intValue() + "");break;
}
});
}
// 画钟
// 画钟题目ID
Long hzId = getQuestionId("HZ", 3);
QuestionDto.QueryPatientCanvas hzQuery = new QuestionDto.QueryPatientCanvas();
hzQuery.setPatientReportId(analyse.getId());
hzQuery.setQuestionId(hzId);
List<QuestionVo.PatientCanvas> patientCanvas = questionService.getCanvas(hzQuery, null);
if (CollectionUtil.isNotEmpty(patientCanvas)) {
Integer height = patientCanvas.get(0).getCanvas().getHeight();
QuestionVo.Parameter parameters = patientCanvas.get(0).getParameters();
// 完成总时间
row.get(38).setValue(parameters.getTotalDuration() + "ms");
row.get(39).setValue(parameters.getPaintTime() + "ms");
row.get(40).setValue(parameters.getReflectOnTime() + "ms");
row.get(44).setValue(String.valueOf(parameters.getLineParameterList().size()));
row.get(45).setValue(String.valueOf(parameters.getAveTimes()));
row.get(46).setValue(pxToMm(parameters.getAveLength(), height) + "mm");
row.get(47).setValue(pxToMm(parameters.getLongLine(), height) + "mm");
row.get(51).setValue(pxToMm(parameters.getLongSpeed() * 1000, height) + "mm/s");
row.get(52).setValue(pxToSquare(parameters.getMinCircleAcreage().doubleValue(), height) + "mm²");
row.get(53).setValue(pxToMm(parameters.getShowCentreCoordinate().getX(), height) + "mm");
row.get(54).setValue(pxToMm(parameters.getShowCentreCoordinate().getY(), height) + "mm");
}
Long simpleId = getQuestionId("EasyOne", 4);
initSimple(row, analyse, simpleId, 55);
Long simpleThreeId = getQuestionId("EasyTwo", 5);
initSimple(row, analyse, simpleThreeId, 78);
Long simpleTwentyId = getQuestionId("EasyThree", 6);
initSimple(row, analyse, simpleTwentyId, 101);
}
public String pxToMm(double length, Integer height) {
return new BigDecimal(144).multiply(new BigDecimal(length)).divide(new BigDecimal(height), 2, BigDecimal.ROUND_HALF_UP).toString();
}
public String pxToSquare(double length, Integer height) {
return new BigDecimal(144 * 144).multiply(new BigDecimal(length)).divide(new BigDecimal(height * height), 2, BigDecimal.ROUND_HALF_UP).toString();
}
private void initSimple(List<PoiUtil.PoiUtilCell> row, PatientReportVo.Analyse analyse, Long simpleId, int startIndex) {
QuestionDto.QueryPatientCanvas simpleQuery = new QuestionDto.QueryPatientCanvas();
simpleQuery.setPatientReportId(analyse.getId());
simpleQuery.setQuestionId(simpleId);
List<QuestionVo.PatientCanvas> simpleCanvas = questionService.getCanvas(simpleQuery, null);
if (CollectionUtil.isNotEmpty(simpleCanvas)) {
QuestionVo.Parameter parameters = simpleCanvas.get(0).getParameters();
Integer height = simpleCanvas.get(0).getCanvas().getHeight();
// 完成总时间
row.get(startIndex).setValue(parameters.getTotalDuration() + "ms");
row.get(startIndex + 1).setValue(parameters.getPaintTime() + "ms");
row.get(startIndex + 2).setValue(parameters.getReflectOnTime() + "ms");
row.get(startIndex + 3).setValue(String.valueOf(parameters.getLineParameterList().size()));
row.get(startIndex + 4).setValue(parameters.getAveTimes() + "");
row.get(startIndex + 5).setValue(pxToMm(parameters.getAveLength(), height) + "mm");
row.get(startIndex + 6).setValue(pxToMm(parameters.getLongLine(), height) + "mm");
row.get(startIndex + 8).setValue(pxToMm(parameters.getLongSpeed() * 1000, height) + "mm/s");
row.get(startIndex + 9).setValue(pxToSquare(parameters.getMinRectangleAcreage(), height) + "mm²");
row.get(startIndex + 10).setValue(pxToMm(parameters.getShowCentreCoordinate().getX(), height) + "mm");
row.get(startIndex + 11).setValue(pxToMm(parameters.getShowCentreCoordinate().getY(), height) + "mm");
row.get(startIndex + 12).setValue(pxToMm(parameters.getRight().getX(), height) + "mm");
row.get(startIndex + 13).setValue(pxToMm(parameters.getRight().getY(), height) + "mm");
row.get(startIndex + 15).setValue(String.valueOf(parameters.getLongNums()));
row.get(startIndex + 16).setValue(String.valueOf(parameters.getShortNums()));
row.get(startIndex + 17).setValue(parameters.getTransitionTime() + "ms");
row.get(startIndex + 18).setValue(parameters.getFiveLongLinesTime() + "ms");
row.get(startIndex + 19).setValue(parameters.getLongLineRate() + "%");
}
}
private void initAnalyseTitle(List<List<PoiUtil.PoiUtilCell>> rows, int total) {
List<PoiUtil.PoiUtilCell> headRow = new ArrayList<>();
PoiUtil.PoiUtilCell headCell = new PoiUtil.PoiUtilCell();
headCell.setColspan(total);
headCell.setValue("认知功能神经心理量表检查报告单");
headRow.add(headCell);
rows.add(headRow);
log.info("标题:{}", headCell);
List<PoiUtil.PoiUtilCell> oneTitleRow = new ArrayList<>();
oneTitleRow.add(new PoiUtil.PoiUtilCell("序号",1,2));
oneTitleRow.add(new PoiUtil.PoiUtilCell("基本信息",8,1));
for (int i = 0; i < 7; i++) {
oneTitleRow.add(new PoiUtil.PoiUtilCell("",1,1));
}
oneTitleRow.add(new PoiUtil.PoiUtilCell("MMSE",7,1));
for (int i = 0; i < 6; i++) {
oneTitleRow.add(new PoiUtil.PoiUtilCell("",1,1));
}
oneTitleRow.add(new PoiUtil.PoiUtilCell("MoCA",18,1));
for (int i = 0; i < 17; i++) {
oneTitleRow.add(new PoiUtil.PoiUtilCell("",1,1));
}
oneTitleRow.add(new PoiUtil.PoiUtilCell("其他量表",4,1));
for (int i = 0; i < 3; i++) {
oneTitleRow.add(new PoiUtil.PoiUtilCell("",1,1));
}
oneTitleRow.add(new PoiUtil.PoiUtilCell("画钟",17,1));
for (int i = 0; i < 16; i++) {
oneTitleRow.add(new PoiUtil.PoiUtilCell("",1,1));
}
oneTitleRow.add(new PoiUtil.PoiUtilCell("简单图形测验",23,1));
for (int i = 0; i < 22; i++) {
oneTitleRow.add(new PoiUtil.PoiUtilCell("",1,1));
}
oneTitleRow.add(new PoiUtil.PoiUtilCell("3min回忆",23,1));
for (int i = 0; i < 22; i++) {
oneTitleRow.add(new PoiUtil.PoiUtilCell("",1,1));
}
oneTitleRow.add(new PoiUtil.PoiUtilCell("20min延迟回忆",23,1));
for (int i = 0; i < 22; i++) {
oneTitleRow.add(new PoiUtil.PoiUtilCell("",1,1));
}
rows.add(oneTitleRow);
List<PoiUtil.PoiUtilCell> titleRow = new ArrayList<>();
// 基本信息
titleRow.add(new PoiUtil.PoiUtilCell(""));
titleRow.add(new PoiUtil.PoiUtilCell("测评日期"));
titleRow.add(new PoiUtil.PoiUtilCell("姓名"));
titleRow.add(new PoiUtil.PoiUtilCell("性别"));
titleRow.add(new PoiUtil.PoiUtilCell("年龄"));
titleRow.add(new PoiUtil.PoiUtilCell("文化程度"));
titleRow.add(new PoiUtil.PoiUtilCell("职业"));
titleRow.add(new PoiUtil.PoiUtilCell("临床诊断"));
titleRow.add(new PoiUtil.PoiUtilCell("严重程度"));
// MMSE
titleRow.add(new PoiUtil.PoiUtilCell("定向力"));
titleRow.add(new PoiUtil.PoiUtilCell("记忆力"));
titleRow.add(new PoiUtil.PoiUtilCell("注意力和计算力"));
titleRow.add(new PoiUtil.PoiUtilCell("回忆能力"));
titleRow.add(new PoiUtil.PoiUtilCell("语言能力"));
titleRow.add(new PoiUtil.PoiUtilCell("结构能力"));
titleRow.add(new PoiUtil.PoiUtilCell("总分"));
// MoCA
titleRow.add(new PoiUtil.PoiUtilCell("连线测验"));
titleRow.add(new PoiUtil.PoiUtilCell("立方体"));
titleRow.add(new PoiUtil.PoiUtilCell("画钟"));
// 命名 4-6
titleRow.add(new PoiUtil.PoiUtilCell("命名"));
titleRow.add(new PoiUtil.PoiUtilCell("记忆1"));
titleRow.add(new PoiUtil.PoiUtilCell("记忆2"));
titleRow.add(new PoiUtil.PoiUtilCell("注意顺背"));
titleRow.add(new PoiUtil.PoiUtilCell("注意倒背"));
titleRow.add(new PoiUtil.PoiUtilCell("注意敲1"));
titleRow.add(new PoiUtil.PoiUtilCell("注意100-7"));
// 语言重复 13-14
titleRow.add(new PoiUtil.PoiUtilCell("语言重复"));
titleRow.add(new PoiUtil.PoiUtilCell("流畅性1min"));
titleRow.add(new PoiUtil.PoiUtilCell("抽象"));
titleRow.add(new PoiUtil.PoiUtilCell("延迟回忆"));
// 20
titleRow.add(new PoiUtil.PoiUtilCell("分类提示"));
// 21
titleRow.add(new PoiUtil.PoiUtilCell("多选提示"));
titleRow.add(new PoiUtil.PoiUtilCell("定向"));
titleRow.add(new PoiUtil.PoiUtilCell("总分"));
// 其他量表总分
titleRow.add(new PoiUtil.PoiUtilCell("ADL总分"));
titleRow.add(new PoiUtil.PoiUtilCell("HAMA总分"));
titleRow.add(new PoiUtil.PoiUtilCell("HAMD总分"));
titleRow.add(new PoiUtil.PoiUtilCell("NPI总分"));
// 画钟
//38
titleRow.add(new PoiUtil.PoiUtilCell("完成总时间"));
titleRow.add(new PoiUtil.PoiUtilCell("落笔时间"));
titleRow.add(new PoiUtil.PoiUtilCell("思考时间"));
// 41-42 空字符
titleRow.add(new PoiUtil.PoiUtilCell("钟面后延迟时间"));
titleRow.add(new PoiUtil.PoiUtilCell("第一指针延迟时间"));
titleRow.add(new PoiUtil.PoiUtilCell("第二指针延迟时间"));
titleRow.add(new PoiUtil.PoiUtilCell("总笔画数"));
titleRow.add(new PoiUtil.PoiUtilCell("每分钟笔画数"));
titleRow.add(new PoiUtil.PoiUtilCell("平均长度"));
titleRow.add(new PoiUtil.PoiUtilCell("最长笔画长度"));
// 48 49 空字符串
titleRow.add(new PoiUtil.PoiUtilCell("时针长度"));
titleRow.add(new PoiUtil.PoiUtilCell("分针长度"));
titleRow.add(new PoiUtil.PoiUtilCell("平均速度"));
titleRow.add(new PoiUtil.PoiUtilCell("最长笔画速度"));
titleRow.add(new PoiUtil.PoiUtilCell("最小外接圆面积"));
titleRow.add(new PoiUtil.PoiUtilCell("图形中心水平位置"));
titleRow.add(new PoiUtil.PoiUtilCell("图形中心垂直位置"));
// 简单图形测验
// 55
fillSimplePicture(titleRow);
fillSimplePicture(titleRow);
fillSimplePicture(titleRow);
rows.add(titleRow);
}
private void fillSimplePicture(List<PoiUtil.PoiUtilCell> titleRow) {
titleRow.add(new PoiUtil.PoiUtilCell("完成总时间"));
titleRow.add(new PoiUtil.PoiUtilCell("落笔时间"));
titleRow.add(new PoiUtil.PoiUtilCell("思考时间"));
titleRow.add(new PoiUtil.PoiUtilCell("总笔画数"));
titleRow.add(new PoiUtil.PoiUtilCell("每分钟笔画数"));
titleRow.add(new PoiUtil.PoiUtilCell("平均长度"));
titleRow.add(new PoiUtil.PoiUtilCell("最长笔画长度"));
titleRow.add(new PoiUtil.PoiUtilCell("平均速度"));
titleRow.add(new PoiUtil.PoiUtilCell("最长笔画速度"));
titleRow.add(new PoiUtil.PoiUtilCell("最小外接长方形面积"));
titleRow.add(new PoiUtil.PoiUtilCell("图形中心水平位置"));
titleRow.add(new PoiUtil.PoiUtilCell("图形中心垂直位置"));
titleRow.add(new PoiUtil.PoiUtilCell("图形顶边距离绘图区域中心的距离"));
titleRow.add(new PoiUtil.PoiUtilCell("图形底边距离绘图区域中心的距离"));
titleRow.add(new PoiUtil.PoiUtilCell("每条笔画的长度"));
titleRow.add(new PoiUtil.PoiUtilCell("长笔画数量"));
titleRow.add(new PoiUtil.PoiUtilCell("短笔画数量"));
titleRow.add(new PoiUtil.PoiUtilCell("所有短长笔画序列的过渡时间"));
titleRow.add(new PoiUtil.PoiUtilCell("5个早期长笔画的经过时间"));
titleRow.add(new PoiUtil.PoiUtilCell("前5笔长笔画率"));
titleRow.add(new PoiUtil.PoiUtilCell("相似系数"));
titleRow.add(new PoiUtil.PoiUtilCell("图形重心水平位置"));
titleRow.add(new PoiUtil.PoiUtilCell("图形重心垂直位置"));
}
private List<PatientReportVo.ReportScore> getReportScores(PatientReportDto.ExportCode param, List<PdfUtil.Row> content, List<PatientReportVo.ReportScore> reportScores, PatientReportVo.ReprotPatient reportPatient) {
long reportId = param.getId();
//重新封装报告单信息
List<PatientReportVo.ReportScore> scores = getReportScores(reportScores, reportId);
@ -663,8 +1030,8 @@ public class PatientReportService implements IPatientReportService {
int titleSpan = 2;
PdfUtil.Cell initWordCell = addCell(row, "初步印象", titleSpan, 2);
initWordCell.setHeight(PdfUtil.Cell.defaultHeight * 2);
String initialImpression = "";
PdfUtil.Cell initImplCell = addCell(row, initialImpression, colNum - titleSpan, 2);
String initialImpression = reportPatient.getInitialImpression();
PdfUtil.Cell initImplCell = addCell(row, "", colNum - titleSpan, 2);
initImplCell.setHeight(PdfUtil.Cell.defaultHeight * 2);
initImplCell.setBorderRight(1);
initImplCell.setCenter(false);
@ -745,14 +1112,20 @@ public class PatientReportService implements IPatientReportService {
// 检查目的
if (StrUtil.isNotBlank(title.checkPurpose)) {
PdfUtil.Row row = new PdfUtil.Row();
row.setHeight(100);
PdfUtil.Cell cell = addCell(row, title.checkPurpose, (title.optionList.size() + questionSpan + 1 ) * cols, 1);
cell.setCenter(false);
cell.setBorderRight(1);
cell.setHeight(36);
questionTable.add(row);
}
// 设置表头
PdfUtil.Row row1 = new PdfUtil.Row();
PdfUtil.Row row2 = new PdfUtil.Row();
if (!Constant.Ht.Report.HAMA.equals(code)) {
row2.setFontSize(10);
}
for (int i = 0; i < cols ; i++) {
addCell(row1, "序号", 1, 2);
// addCell(row2, "", 1, 1);

44
ht/src/main/java/com/ccsens/ht/service/QuestionService.java

@ -67,6 +67,9 @@ public class QuestionService implements IQuestionService {
private HtPatientCanvasDao patientCanvasDao;
@Resource
private HtPatientCanvasLineMapper patientCanvasLineMapper;
@Resource
private HtPatientReportRecordDescDao htPatientReportRecordDescDao;
@ -185,7 +188,7 @@ public class QuestionService implements IQuestionService {
}
@Override
public CodeEnum saveScore(QuestionDto.Score score, Long userId) throws IOException, NotSupportedFileTypeException {
public CodeEnum saveScore(QuestionDto.Score score, Long userId) {
log.info("保存分数{}", score);
if (score.getPatientReportId() == null) {
@ -400,7 +403,7 @@ public class QuestionService implements IQuestionService {
* @throws IOException
* @throws NotSupportedFileTypeException
*/
private List<HtPatientScore> getHtPatientScores(QuestionDto.Score score, HtQuestion question, HtPatientReport report, List<HtQuestionScoringRule> ruleList, Map<String, HtQuestionOption> nameOption, Map<Long, HtQuestionOption> idOption) throws IOException, NotSupportedFileTypeException {
private List<HtPatientScore> getHtPatientScores(QuestionDto.Score score, HtQuestion question, HtPatientReport report, List<HtQuestionScoringRule> ruleList, Map<String, HtQuestionOption> nameOption, Map<Long, HtQuestionOption> idOption) {
List<HtPatientScore> scores = new ArrayList<>();
for(QuestionDto.Option option : score.getOptions()) {
HtQuestionOption questionOption = idOption.get(option.getId());
@ -994,7 +997,7 @@ public class QuestionService implements IQuestionService {
lineIndex++;
// 第5条线时,计算长线段的比例
if (lineIndex == lineCount) {
parameter.setLongLineRate(new BigDecimal(longLineIndex).divide(new BigDecimal(lineCount)));
parameter.setLongLineRate(new BigDecimal(longLineIndex * 100).divide(new BigDecimal(lineCount)));
}
}
@ -1029,4 +1032,39 @@ public class QuestionService implements IQuestionService {
});
}
}
@Override
public void saveRecord(QuestionDto.Record batchRecordMsg, Long userId) {
if (batchRecordMsg == null || CollectionUtil.isEmpty(batchRecordMsg.getDetails())) {
return;
}
// 删除原有答案
List<Long> recordIds = new ArrayList<>();
List<HtPatientReportRecordDesc> records = new ArrayList<>();
batchRecordMsg.getDetails().forEach(detail -> {
recordIds.add(detail.getRecordId());
if (CollectionUtil.isEmpty(detail.getAnswers())) {
return;
}
detail.getAnswers().forEach(answer -> {
HtPatientReportRecordDesc recordDesc = new HtPatientReportRecordDesc();
recordDesc.setId(snowflake.nextId());
recordDesc.setPatientReportId(batchRecordMsg.getPatientReportId());
recordDesc.setRecordId(detail.getRecordId());
recordDesc.setAnswer(answer);
records.add(recordDesc);
});
});
HtPatientReportRecordDescExample recordDescExample = new HtPatientReportRecordDescExample();
recordDescExample.createCriteria().andPatientReportIdEqualTo(batchRecordMsg.getPatientReportId())
.andRecordIdIn(recordIds).andIsDelEqualTo(Constant.Ht.NO_DEL);
HtPatientReportRecordDesc update = new HtPatientReportRecordDesc();
update.setIsDel(Constant.Ht.IS_DEL);
htPatientReportRecordDescDao.updateByExampleSelective(update, recordDescExample);
log.info("删除其他记录答案:{},{}", recordIds, batchRecordMsg.getPatientReportId());
// 保存新答案
htPatientReportRecordDescDao.batchSave(records);
log.info("保存新答案");
}
}

49
ht/src/main/java/com/ccsens/ht/uitl/Constant.java

@ -41,7 +41,6 @@ public class Constant {
public static final class Export{
public final static Map<String, ReportExportTitle> TITLE_MAP = new HashMap<>();
static {
TITLE_MAP.put("HAMA", new ReportExportTitle("检查目的:用于焦虑症的诊断及程度划分的依据。",
"近一周内", "圈出最符合病人情况的分数",
@ -49,10 +48,12 @@ public class Constant {
TITLE_MAP.put("HAMD", new ReportExportTitle("检查目的:临床评定抑郁状态。",
"", "圈出最符合病人情况的分数",
"无(0)","轻度(1)","中度(2)","重度(3)","极重度(4)"));
TITLE_MAP.put("ADL", new ReportExportTitle("检查目的:ADL量表用于评定被测试人日常生活能力(包括躯体功能和使用工具能力)。",
TITLE_MAP.put("ADL", new ReportExportTitle("检查目的:ADL量表用于评定被测试人日常生活能力(包括躯体功能和使用工具能力)。",
"", "圈出最符合的情况",
"自己可以做(1)","有些困难(2)","需要帮助(3)","根本无法做(4)"));
}
public static final String MMSE_PURPOSE = "检查目的:MMSE用于筛查痴呆患者、判断认知损害的严重程度并跟踪记录病情变化情况。涵盖了定向力、记忆力、计算及注意力、语言和视空间能力等认知域。";
public static final String MOCA_PURPOSE = "检查目的:MoCA作为总体认知功能评估的筛查量表,覆盖注意力、执行功能、记忆、语言、视空间结构、抽象思维、计算和定向力等认知域。";
}
public static final class ReportExportTitle{
@ -129,9 +130,53 @@ public class Constant {
public final static byte SEX_MAN = 0;
public final static byte SEX_WOMAN = 1;
//1:文盲 2:小学 3:初中 4:高中 5:大学 6:大学以上 7:其他
public static String getEducational(int status) {
switch (status) {
case 1: return "文盲";
case 2: return "小学";
case 3: return "初中";
case 4: return "高中";
case 5: return "大学";
case 6: return "大学以上";
default: return "其他";
}
}
public static String getCareer(int status) {
switch (status) {
case 1: return "农林牧渔水利生产人员";
case 2: return "教师";
case 3: return "医务工作者";
case 4: return "专业技术人员";
case 5: return "生产、运输设备操作人员及有关人员";
case 6: return "商业、服务业人员";
case 7: return "国家机关、事业单位、企业负责人";
case 8: return "商业、服务业人员";
case 9: return "军人";
case 10: return "媒体、文体类工作人员";
case 11: return "在校学生";
case 12: return "未就业";
case 13: return "家务";
default: return "其他";
}
}
/**删除*/
public final static byte IS_DEL = 1;
/**未删除*/
public final static byte NO_DEL = 0;
public static String getPasi(Byte pasi) {
switch (pasi) {
case 0: return "正常";
case 1: return "轻度";
case 2: return "中度";
case 3: return "重度";
default: return "";
}
}
public final static class QuestionRecord{

4
ht/src/main/resources/application.yml

@ -1,4 +1,4 @@
spring:
profiles:
active: test
include: common, util-test
active: prod
include: common, util-prod

150
ht/src/main/resources/mapper_dao/HtPatientReportDao.xml

@ -48,6 +48,29 @@
<result column="chooseStatus" property="chooseStatus"/>
</collection>
</resultMap>
<resultMap id="AnalyseMap" type="com.ccsens.ht.bean.vo.PatientReportVo$Analyse">
<id column="id" property="id"/>
<result column="report_time" property="reportTime"/>
<result column="patientName" property="patientName"/>
<result column="patient_age" property="patientAge"/>
<result column="pasi" property="pasi"/>
<result column="clinical_diagnosis" property="clinicalDiagnosis"/>
<result column="sex" property="sex"/>
<result column="educational_status" property="educationalStatus"/>
<result column="career" property="career"/>
<collection property="mmseScores" ofType="com.ccsens.ht.bean.vo.PatientReportVo$MMSEScore">
<id column="mmseCode" property="code"/>
<result column="mmseScore" property="score"/>
</collection>
<collection property="mocaScores" ofType="com.ccsens.ht.bean.vo.PatientReportVo$MoCAScore">
<id column="mocaSort" property="sort"/>
<result column="mocaScore" property="score"/>
</collection>
<collection property="totalScores" ofType="com.ccsens.ht.bean.vo.PatientReportVo$TotalScore">
<id column="evaluationCode" property="evaluationCode"/>
<result column="totalScore" property="totalScore"/>
</collection>
</resultMap>
<select id="queryReportResult" resultMap="BaseResultMap">
select r.*, d.name as doctor_name, p.name as patient_name, p.sex, p.educational_status, p.educational_status_unit, p.career, p.hospital_number, p.patient_number
@ -83,7 +106,7 @@
GROUP BY t1.code
order by t1.type,t1.sort
</select>
<select id="queryNPIScore" resultType="java.util.Map">
<select id="queryNpiScore" resultType="java.util.Map">
select option_name as optionName, sum(score) as score
from t_ht_patient_score
where patient_report_id = #{id, jdbcType=BIGINT} and question_parent_code = 'NPI'
@ -120,9 +143,36 @@
order by create_time desc
</select>
<select id="queryAllReports" resultType="com.ccsens.ht.bean.vo.PatientReportVo$ReportName">
select r.id, r.name, r.url, r.doctor_id as doctorId, 1 as authority
select t.* from
(select r.id, r.name, r.url, r.doctor_id as doctorId, 1 as authority, r.create_time
<if test="scores != null and scores.size() > 0">
,
SUM(CASE report.code WHEN 'moca' THEN s.score ELSE 0 END) as 'moca',
SUM(CASE report.code WHEN 'mmse' THEN s.score ELSE 0 END) as 'mmse',
SUM(CASE report.code WHEN 'rey' THEN s.score ELSE 0 END) as 'rey',
SUM(CASE report.code WHEN 'hama' THEN s.score ELSE 0 END) as 'hama',
SUM(CASE report.code WHEN 'hamd' THEN s.score ELSE 0 END) as 'hamd',
SUM(CASE report.code WHEN 'adl' THEN s.score ELSE 0 END) as 'adl',
SUM(CASE report.code WHEN 'npi' THEN s.score ELSE 0 END) as 'npi'
</if>
from t_ht_patient_report r, t_ht_patient p
<if test="scores != null and scores.size() > 0">
,
t_ht_report report,
t_ht_question q,
t_ht_patient_score s
</if>
where r.patient_id = p.id
<if test="scores != null and scores.size() > 0">
AND r.id = s.patient_report_id
AND report.CODE = q.evaluation_code
AND q.id = s.question_id
AND report.type = 2
AND s.type IN ( 0, 2 )
</if>
<if test="patientName != null">
and p.name = #{patientName}
</if>
<if test="patientSex != null">
and p.sex = #{patientSex}
</if>
@ -153,39 +203,23 @@
<if test="endTime != null">
and r.report_time &lt;= #{endTime}
</if>
<if test="scores != null and scores.size() > 0">
and r.id in (
SELECT DISTINCT
s.patient_report_id
FROM
t_ht_report r,
t_ht_question q,
t_ht_patient_score s
WHERE
r.CODE = q.evaluation_code
AND q.id = s.question_id
AND r.type = 2
AND s.type IN ( 0, 2 )
GROUP BY
s.patient_report_id,
r.CODE
HAVING
<foreach collection="scores" item="score" separator="and" open="(" close=")">
( r.CODE = #{score.code}
<if test="score.start != null">
AND sum( s.score ) &gt;= #{score.start}
</if>
<if test="score.end != null">
AND sum( s.score ) &lt;= #{score.end}
</if>
)
</foreach>
)
</if>
and r.show_status = 1
AND r.complete_status = 1
and r.is_del = 0
order by r.create_time desc
group by r.id
) t
where 1=1
<if test="scores != null and scores.size() > 0">
<foreach collection="scores" item="score">
<if test="score.start != null">
AND ${score.code} &gt;= #{score.start}
</if>
<if test="score.end != null">
AND ${score.code} &lt;= #{score.end}
</if>
</foreach>
</if>
order by create_time desc
</select>
<select id="countByClinicalDiagnosis" resultType="com.ccsens.ht.bean.vo.PatientReportVo$ClinicalDiagnosis">
select clinical_diagnosis as diagnosis, count(*) as count from t_ht_patient_report
@ -357,6 +391,58 @@
q.sort,
o.sort
</select>
<select id="queryReportAnalyseScore" resultMap="AnalyseMap">
select * from
-- 患者信息
(select r.id, r.patient_age, r.pasi, r.clinical_diagnosis, p.sex, p.educational_status, p.career, r.report_time, p.name as patientName from t_ht_patient_report r , t_ht_patient p where r.patient_id = p.id and r.id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
and r.is_del = 0 and p.is_del = 0) report
left join
-- MMSE 分数
(select s.patient_report_id as mmseReportId, t.code as mmseCode, sum(s.score) as mmseScore from
(
select if(r.parent_code = 'MMSE', r.code, r.parent_code) as code, q.id from
(
select code, parent_code from
(
select code, parent_code, if(FIND_IN_SET(parent_code,@pcode), @pcode := concat(@pcode,',',code),'') as pcode from
t_ht_report,
(select @pcode := 'MMSE') t
where is_del = 0
) r where pcode != ''
) r, t_ht_question q where (q.parent_code = r.code or q.parent_code = r.parent_code) and q.is_del = 0
) t left join t_ht_patient_score s
on t.id = s.question_id and s.is_del = 0 and s.patient_report_id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
and s.type in (0, 2)
group by s.patient_report_id, t.code) mmse
on report.id = mmse.mmseReportId
left join
-- MOCA
(select s.patient_report_id as mocaReportId, q.sort as mocaSort, sum(s.score) as mocaScore from
(select * from t_ht_question where evaluation_code = 'MOCA' AND is_del = 0) q
left join t_ht_patient_score s on q.id = s.question_id and s.patient_report_id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
and s.type in (0, 2)
and s.is_del = 0
group by s.patient_report_id,q.sort
) moca
on report.id = moca.mocaReportId
left join
-- 总成绩
(select q.evaluation_code as evaluationCode, s.patient_report_id as scoreReportId, sum(s.score) as totalScore from t_ht_question q left join t_ht_patient_score s on q.id = s.question_id and s.is_del = 0 where q.is_del = 0 and s.patient_report_id in
<foreach collection="ids" item="id" open="(" close=")" separator=",">
#{id}
</foreach>
group by q.evaluation_code, s.patient_report_id) score
on report.id = score.scoreReportId
</select>
</mapper>

12
ht/src/main/resources/mapper_dao/HtPatientReportRecordDescDao.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ccsens.ht.persist.dao.HtPatientReportRecordDescDao">
<insert id="batchSave">
insert into t_ht_patient_report_record_desc(id, patient_report_id, record_id, answer) values
<foreach collection="list" item="item" separator=",">
(#{item.id}, #{item.patientReportId}, #{item.recordId}, #{item.answer})
</foreach>
</insert>
</mapper>

10
ht/src/main/resources/mapper_dao/HtQuestionDao.xml

@ -38,7 +38,7 @@
<insert id="insertBatch" parameterType="java.util.List">
replace into t_ht_question (id, evaluation_code, parent_code,
sort, question, type,
record_type, record_content, relation_code,
record_type, record_content, relation_code, relation_id,
operate_type, recode_starttime, time_wabei,
allow_clear, clear_times, timing_length,
remark, create_time, update_time,
@ -48,6 +48,14 @@
(#{question.id,jdbcType=BIGINT}, #{question.evaluationCode,jdbcType=VARCHAR}, #{question.parentCode,jdbcType=VARCHAR},
#{question.sort,jdbcType=INTEGER}, #{question.question,jdbcType=VARCHAR}, #{question.type,jdbcType=TINYINT},
#{question.recordType,jdbcType=VARCHAR}, #{question.recordContent,jdbcType=VARCHAR}, #{question.relationCode,jdbcType=VARCHAR},
<choose>
<when test="question.relationId == null">
0,
</when>
<otherwise>
#{question.relationId},
</otherwise>
</choose>
#{question.operateType,jdbcType=TINYINT}, #{question.recodeStarttime,jdbcType=TINYINT}, #{question.timeWabei,jdbcType=TINYINT},
#{question.allowClear,jdbcType=TINYINT}, #{question.clearTimes,jdbcType=INTEGER}, #{question.timingLength,jdbcType=INTEGER},
#{question.remark,jdbcType=VARCHAR}, #{question.createTime,jdbcType=TIMESTAMP}, now(), 0 )

2
pom.xml

@ -12,7 +12,7 @@
<module>util</module>
<!-- <module>game</module>-->
<!-- <module>mt</module>-->
<module>health</module>
<!--<module>health</module>-->
<!-- <module>ct</module>-->
<module>question</module>
</modules>

14
question/src/main/java/com/ccsens/question/api/PatientReportController.java

@ -52,6 +52,20 @@ public class PatientReportController {
return JsonResponse.newInstance().ok();
}
@MustLogin
@DoctorAudit
@ApiOperation(value = "检查患者是否有未完成的报告单, 无则生成",notes = "检查患者是否有未完成的报告单")
@ApiImplicitParams({
@ApiImplicitParam(name = "json", value = "报告单信息", required = true)
})
@RequestMapping(value="/checkPatientComplete", method = RequestMethod.POST)
public JsonResponse<PatientReportVo.CompleteSimple> checkPatientComplete(@RequestBody @ApiParam @Valid QueryDto<PatientReportDto.Patient> dto){
log.info("检查患者是否有未完成的报告单:{}", dto);
PatientReportVo.CompleteSimple complete = patientReportService.checkPatientComplete(dto.getParam(), dto.getUserId());
log.info("检查患者是否有未完成的报告单返回:{}", complete);
return JsonResponse.newInstance().ok(complete);
}
@MustLogin
@DoctorAudit
@ApiOperation(value = "检查是否有未完成的报告单",notes = "检查是否有未完成的报告单")

12
question/src/main/java/com/ccsens/question/bean/dto/PatientReportDto.java

@ -19,6 +19,16 @@ import javax.validation.constraints.NotNull;
*/
public class PatientReportDto {
@Data
@ApiModel("患者信息")
public static class Patient{
@ApiModelProperty("病人ID")
@NotNull(message = "请选择患者信息")
private Long patientId;
@ApiModelProperty("病案号")
private String serialNumber;
}
@Data
@ApiModel("忽略未完成的报告单")
public static class Ignore{
@ -33,6 +43,8 @@ public class PatientReportDto {
@ApiModelProperty("病人ID")
@NotNull(message = "病人ID不能为空")
private Long patientId;
@ApiModelProperty("病案号")
private String serialNumber;
}
@ApiModel("PatientReportDtoEdit")

18
question/src/main/java/com/ccsens/question/bean/vo/PatientReportVo.java

@ -21,6 +21,22 @@ import java.util.*;
*/
public class PatientReportVo {
@Data
@ApiModel("报告单遗留未完成简单版")
public static class CompleteSimple {
@ApiModelProperty("是否有未完成的项目 1:有 0:无")
private byte hasUnfinished = 0;
@ApiModelProperty("报告单ID")
private Long id;
@ApiModelProperty("报告单名字")
private String name;
@ApiModelProperty("病人ID")
private Long patientId;
@ApiModelProperty("病案号")
private String serialNumber;
}
@Data
@ApiModel("报告单遗留未完成")
public static class Complete {
@ -170,7 +186,7 @@ public class PatientReportVo {
String pasiStr = this.pasi == 3 ? "重度" : this.pasi == 2 ? "中度" : this.pasi == 1 ? "轻度" : "";
rows.add(
fillRow(
"病案号:",
"病案号:" + (StrUtil.isEmpty(serialNumber) ? "" : serialNumber),
"临床诊断:" + (StrUtil.isEmpty(this.clinicalDiagnosis) ? "" : this.clinicalDiagnosis),
"严重程度:" + pasiStr)
// "检查日期:" + (date == null ? "" : DateUtil.format(date, "yyyy-MM-dd")))

8
question/src/main/java/com/ccsens/question/persist/dao/HtPatientReportDao.java

@ -104,4 +104,12 @@ public interface HtPatientReportDao extends HtPatientReportMapper {
* @return 报告单
*/
List<PatientReportSearchVo.Search> search(@Param("codes") List<PatientReportSearchDto.Search> codes);
/**
* 检查患者未完成的报告单
* @param param 患者信息
* @param userId 用户ID
* @return 报告单
*/
PatientReportVo.CompleteSimple checkPatientComplete(@Param("patient") PatientReportDto.Patient param, @Param("userId") Long userId);
}

8
question/src/main/java/com/ccsens/question/service/IPatientReportService.java

@ -157,4 +157,12 @@ public interface IPatientReportService {
* @return 报告单
*/
List<PatientReportSearchVo.Search> search(PatientReportSearchDto.SearchList param);
/**
*
* @param param
* @param userId
* @return
*/
PatientReportVo.CompleteSimple checkPatientComplete(PatientReportDto.Patient param, Long userId);
}

28
question/src/main/java/com/ccsens/question/service/PatientReportService.java

@ -87,6 +87,7 @@ public class PatientReportService implements IPatientReportService {
htPatientReport.setId(snowflake.nextId());
// htPatientReport.setDoctorId(doctors.get(0).getId());
htPatientReport.setPatientId(generate.getPatientId());
htPatientReport.setSerialNumber(generate.getSerialNumber());
// htPatientReport.setPatientIdcard(htPatient.getIdcard());
// htPatientReport.setPatientAge(StrUtil.isEmpty(htPatient.getIdcard()) ? null : (byte)IdcardUtil.getAgeByIdCard(htPatient.getIdcard()));
htPatientReport.setEvaluationCode(Constant.Ht.Report.PARENT_CODE);
@ -99,6 +100,7 @@ public class PatientReportService implements IPatientReportService {
log.info("生成病友报告单:{}", generate);
PatientReportVo.Generate generateVo = new PatientReportVo.Generate();
generateVo.setId(htPatientReport.getId());
generateVo.setName(htPatientReport.getName());
return JsonResponse.newInstance().ok(generateVo);
}
@ -607,5 +609,31 @@ public class PatientReportService implements IPatientReportService {
return list;
}
@Override
public PatientReportVo.CompleteSimple checkPatientComplete(PatientReportDto.Patient param, Long userId) {
PatientReportVo.CompleteSimple simple = htPatientReportDao.checkPatientComplete(param, userId);
log.info("检查患者未完成的报告单:{}", simple);
if (simple != null) {
simple.setHasUnfinished(Constant.Ht.UNCLOSED_REPORT);
return simple;
}
PatientReportDto.Generate generate = new PatientReportDto.Generate();
generate.setPatientId(param.getPatientId());
generate.setSerialNumber(param.getSerialNumber());
JsonResponse<PatientReportVo.Generate> result = generatePatientReport(generate, userId);
if (result.getCode() != CodeEnum.SUCCESS.getCode().intValue()) {
throw new BaseException(result.getCode(), result.getMsg());
}
simple = new PatientReportVo.CompleteSimple();
PatientReportVo.Generate data = result.getData();
simple.setId(data.getId());
simple.setName(data.getName());
simple.setPatientId(param.getPatientId());
simple.setSerialNumber(param.getSerialNumber());
return simple;
}
}

2
question/src/main/java/com/ccsens/question/uitl/Constant.java

@ -62,6 +62,8 @@ public class Constant {
public final static byte SEX_WOMAN = 1;
/**删除*/
public final static byte IS_DEL = 1;
/**未结束的报告单*/
public final static byte UNCLOSED_REPORT = 1;

6
question/src/main/resources/mapper_dao/HtPatientReportDao.xml

@ -256,6 +256,12 @@
</if>
</foreach>
</select>
<select id="checkPatientComplete" resultType="com.ccsens.question.bean.vo.PatientReportVo$CompleteSimple">
select r.id, r.name, r.patient_id as patientId, r.serial_number as serialNumber, r.create_time as createTime
from t_ht_patient_report r
where r.patient_id = #{patient.patientId} and r.complete_status = 0 and r.is_del = 0
order by r.create_time desc limit 1
</select>
</mapper>

4
tall/src/main/resources/application.yml

@ -1,4 +1,4 @@
spring:
profiles:
active: test
include: util-test,common
active: dev
include: util-dev,common

10
util/src/main/java/com/ccsens/util/PdfUtil.java

@ -51,7 +51,7 @@ public class PdfUtil {
// 中文字体
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
// 标题字体
Font titleChinese = new Font(bfChinese, 24, Font.BOLD);
Font titleChinese = new Font(bfChinese, 14, Font.NORMAL);
//设置标题
Paragraph par = new Paragraph(title, titleChinese);
par.setAlignment(Element.ALIGN_CENTER);
@ -59,14 +59,14 @@ public class PdfUtil {
if (StrUtil.isNotBlank(subhead)) {
// 标题字体
Font subheadChinese = new Font(bfChinese, 22, Font.NORMAL);
Font subheadChinese = new Font(bfChinese, 15, Font.NORMAL);
//设置标题
Paragraph subheadPar = new Paragraph(subhead, subheadChinese);
subheadPar.setAlignment(Element.ALIGN_CENTER);
document.add(subheadPar);
}
// 每行加空白
fillBlankRow(document, new Font(bfChinese, 12, Font.NORMAL));
fillBlankRow(document, new Font(bfChinese, 8, Font.NORMAL));
//设置介绍内容
if (CollectionUtil.isNotEmpty(intros)) {
fillRow(intros, document);
@ -126,7 +126,7 @@ public class PdfUtil {
PdfPTable table = new PdfPTable(size);
table.setSpacingBefore(0);
table.setWidthPercentage(90);
table.setWidthPercentage(100);
for (int j = 0; j < rows.size(); j++) {
Row row = rows.get(j);
table.setHorizontalAlignment(row.align);
@ -214,7 +214,7 @@ public class PdfUtil {
@Data
public static class Margin{
private float left = 72;
private float right = 0;
private float right = 72;
private float top = 32;
private float bottom = 32;
}

516
util/src/main/java/com/ccsens/util/PoiUtil.java

@ -1,11 +1,17 @@
package com.ccsens.util;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.ccsens.util.exception.BaseException;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.common.usermodel.HyperlinkType;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.springframework.stereotype.Component;
@ -20,17 +26,283 @@ import java.util.Map;
/**
* 导入导出excel
* @author wu
*/
@Slf4j
@Component
public class PoiUtil {
@Data
public static class PoiUtilCell {
/**
* 单元格内容
*/
private String value = "";
/**
* 跨列
*/
private int colspan = 1;
/**
* 跨行
*/
private int rowspan = 1;
/**
* 水平居中
*/
private HorizontalAlignment style = HorizontalAlignment.CENTER;
/**
* 垂直居中
*/
private VerticalAlignment verticalAlignment = VerticalAlignment.CENTER;
/**
* 行高
*/
private Integer height;
/**
* 列宽
*/
private Integer wight;
/**
* 跳转的路径
*/
private String path;
/**
* 函数
*/
private String function;
/**
* 是否是数字格式 0否 1是
*/
private byte num = 0;
public PoiUtilCell() {
}
public PoiUtilCell(String value) {
this.value = value;
}
public PoiUtilCell(String value,String function) {
this.value = value;
this.function = function;
}
public PoiUtilCell(String value, int colspan, int rowspan) {
this.value = value;
this.colspan = colspan;
this.rowspan = rowspan;
}
public PoiUtilCell(String value, Integer height, Integer wight) {
this.value = value;
this.height = height;
this.wight = wight;
}
public PoiUtilCell(String value, int colspan, int rowspan, Integer height, Integer wight) {
this.value = value;
this.colspan = colspan;
this.rowspan = rowspan;
this.height = height;
this.wight = wight;
}
}
/**
* 导出Excel
*
* @param sheetName sheet名称
* @param rows
* @param wb XSSFWorkbook对象 无则创建
* @return 返回生成的excel数据
*/
public static Workbook exportWB(String sheetName, List<List<PoiUtilCell>> rows, Workbook wb) {
// 第一步,创建一个XSSFWorkbook,对应一个Excel文件
if (wb == null) {
wb = new XSSFWorkbook();
}
if (rows == null) {
return wb;
}
// 第二步,在workbook中添加一个sheet,对应Excel文件中的sheet
Sheet sheet = wb.getSheet(sheetName);
if (ObjectUtil.isNull(sheet)) {
sheet = wb.createSheet(sheetName);
}
// // 第三步,在sheet中添加表头第0行,注意老版本poi对Excel的行数列数有限制
// HSSFRow row = sheet.createRow(0);
// 第四步,创建单元格,并设置值表头 设置表头居中
for (int i = 0; i < rows.size(); i++) {
List<PoiUtilCell> cells = rows.get(i);
for (int j = 0; j < cells.size(); j++) {
PoiUtilCell cell = cells.get(j);
//设置列宽
if (ObjectUtil.isNotNull(cell.wight)) {
sheet.setColumnWidth(j, cell.wight * 256);
}
mergedRegion(sheet, i, j, cells.get(j));
}
}
//创建内容
for (int i = 0; i < rows.size(); i++) {
Row row = sheet.getRow(i);
if (ObjectUtil.isNull(row)) {
row = sheet.createRow(i);
}
List<PoiUtilCell> cells = rows.get(i);
for (int j = 0; j < cells.size(); j++) {
PoiUtilCell cell = cells.get(j);
if(ObjectUtil.isNull(cell)){
continue;
}
//查找当前单元格
Cell newCell = row.getCell(j);
if(ObjectUtil.isNull(newCell)){
newCell = row.createCell(j);
}
//查找当前单元格的样式
CellStyle style = newCell.getCellStyle();
if(ObjectUtil.isNull(style)){
style = wb.createCellStyle();
}
// CellStyle style = wb.createCellStyle();
//设置内容
if (!WebConstant.CELL_NULL.equals(cell.value)){
// if(cell.num == 1){
// newCell.setCellValue(Integer.parseInt(cell.value));
// }else {
// newCell.setCellValue(cell.value);
// }
if(ObjectUtil.isNull(cell.value)) {
// log.info("单元格内容为空:{}", cell.value);
}else {
if (cell.value.length() <= 14 && cell.value.matches("\\d+")) {
newCell.setCellValue(Long.parseLong(cell.value));
} else {
newCell.setCellValue(cell.value);
}
}
}
//设置行高
if (ObjectUtil.isNotNull(cell.height)) {
if (j == 0) {
row.setHeight(cell.height.shortValue());
}
}
//设置水平居中和垂直居中
style.setAlignment(cell.style);
style.setVerticalAlignment(cell.verticalAlignment);
//设置跳转路径
if (StrUtil.isNotEmpty(cell.path)) {
XSSFCreationHelper createHelper = (XSSFCreationHelper) wb.getCreationHelper();
XSSFHyperlink link = createHelper.createHyperlink(HyperlinkType.URL);
link.setAddress(cell.path);
newCell.setHyperlink(link);
//设置字体颜色
Font font = wb.createFont();
font.setColor(Font.COLOR_RED);
style.setFont(font);
}
//添加函数
if(StrUtil.isNotEmpty(cell.getFunction())) {
newCell.setCellFormula(cell.getFunction());
}
//设置自动换行
style.setWrapText(true);
//将样式添加至单元格
newCell.setCellStyle(style);
// CellStyle style = wb.createCellStyle();
// 将内容按顺序赋给对应的列对象
// 如果value是cell_null代表次单元格不需要赋值
// if (cell.value.equals(WebConstant.CELL_NULL)){
// continue;
// }
// Cell newCell = row.createCell(j);
// //设置行高
// if (ObjectUtil.isNotNull(cell.height)) {
// if (j == 0) {
// row.setHeight(cell.height.shortValue());
// }
// }
//
// if(cell.num == 1){
// newCell.setCellValue(Integer.parseInt(cell.value));
// }else {
// newCell.setCellValue(cell.value);
// }
// style.setAlignment(cell.style);
// style.setVerticalAlignment(cell.verticalAlignment);
// //设置跳转路径
// if (StrUtil.isNotEmpty(cell.path)) {
// XSSFCreationHelper createHelper = (XSSFCreationHelper) wb.getCreationHelper();
// XSSFHyperlink link = createHelper.createHyperlink(HyperlinkType.URL);
// link.setAddress(cell.path);
// newCell.setHyperlink(link);
// //设置字体颜色
// Font font = wb.createFont();
// font.setColor(Font.COLOR_RED);
// style.setFont(font);
// }
// //添加函数
// if(StrUtil.isNotEmpty(cell.getFunction())) {
// newCell.setCellFormula(cell.getFunction());
// }
// //设置自动换行
// style.setWrapText(true);
// newCell.setCellStyle(style);
}
}
return wb;
}
/**
* 合并单元格
*
* @param sheet 当前sheet
* @param rows 行数
* @param cols 列数
* @param cell 单元格信息
*/
private static void mergedRegion(Sheet sheet, int rows, int cols, PoiUtilCell cell) {
//
// int rowspan = cell.rowspan;
// if (rowspan > 1) {
// sheet.addMergedRegion(new CellRangeAddress(rows, rows + rowspan - 1, cols, cols));
// }
// int colspan = cell.colspan;
//
// if (colspan > 1) {
// sheet.addMergedRegion(new CellRangeAddress(rows, rows, cols, cols + colspan - 1));
// }
int rowspan = cell.rowspan;
int colspan = cell.colspan;
if(rowspan > 1 || colspan > 1){
sheet.addMergedRegion(new CellRangeAddress(rows, rows + rowspan - 1, cols, cols + colspan - 1));
}
}
/**
* @param file
* @param sheetIndex
* @param dataIndex 数据从第几行开始0
* @return
*/
public static List<Object[]> readExce(File file, int sheetIndex, String sheetName, int dataIndex, boolean hasImg) throws Exception{
public static List<Object[]> readExce(File file, int sheetIndex, String sheetName, int dataIndex, boolean hasImg) throws Exception {
if (!file.getPath().endsWith(".xls") && !file.getPath().endsWith(".xlsx")) {
log.info("文件不是excel类型:{}", file.getName());
throw new BaseException(CodeEnum.FILE_FORMAT_ERROR);
@ -38,47 +310,52 @@ public class PoiUtil {
log.info("导入解析开始,fileName:{}", file.getPath());
List<Object[]> list = new ArrayList<>();
List<Object[]> list = new ArrayList<>();
Sheet sheet = createSheet(file, sheetIndex, sheetName);
//读取放在首列的图片
Map<String, String> imgMap = null;
if (hasImg) {
imgMap = getImg(file, sheet);
}
//获取sheet的行数
int rows = sheet.getPhysicalNumberOfRows();
Sheet sheet = createSheet(file, sheetIndex, sheetName);
if(ObjectUtil.isNull(sheet)){
return list;
}
//读取放在首列的图片
Map<String, String> imgMap = null;
if (hasImg) {
imgMap = getImg(file, sheet);
}
//获取sheet的行数
int rows = sheet.getPhysicalNumberOfRows();
//读取数据
for (int i = 0; i < rows; i++) {
//读取数据
for (int i = 0; i < rows; i++) {
Row row = getRow(sheet, i, dataIndex);
if (row == null) {
Row row = getRow(sheet, i, dataIndex);
if (row == null || row.getLastCellNum() <= 0) {
continue;
}
System.out.println(row);
System.out.println(row.getLastCellNum());
Object[] objects = new Object[row.getLastCellNum()];
if (hasImg && imgMap != null) {
for (String key : imgMap.keySet()) {
if (key.startsWith(i + "-")) {
int index = Integer.parseInt(key.split("-")[1]);
objects[index] = imgMap.get(key);
}
}
}
for (int j = 0; j < row.getLastCellNum(); j++) {
Cell cell = row.getCell(j);
if (cell == null) {
continue;
}
Object[] objects = new Object[row.getLastCellNum()];
if (hasImg && imgMap != null) {
for (String key: imgMap.keySet()) {
if (key.startsWith(i+"-")) {
int index = Integer.parseInt(key.split("-")[1]);
objects[index] = imgMap.get(key);
}
}
if (objects[j] == null) {
objects[j] = getCallValue(cell);
}
for (int j = 0; j < row.getLastCellNum(); j++) {
Cell cell = row.getCell(j);
if (cell == null) {
continue;
}
if (objects[j] == null) {
objects[j] = getCallValue(cell);
}
}
list.add(objects);
}
log.info("导入文件解析成功!");
return list;
list.add(objects);
}
log.info("导入文件解析成功!");
return list;
}
@ -121,7 +398,6 @@ public class PoiUtil {
}
private PoiUtil() {
super();
}
@ -163,7 +439,7 @@ public class PoiUtil {
String suffix = pictureData.suggestFileExtension();
//图片
byte[] data = pictureData.getData();
String fileName = "/poi/img/" + cn.hutool.core.date.DateUtil.today() + "/"+ System.currentTimeMillis() + "." + suffix;
String fileName = "/poi/img/" + cn.hutool.core.date.DateUtil.today() + "/" + System.currentTimeMillis() + "." + suffix;
String path = PropUtil.path + fileName;
FileOutputStream out = null;
@ -215,6 +491,7 @@ public class PoiUtil {
return map;
}
/**
* 获取当前行
*/
@ -241,7 +518,6 @@ public class PoiUtil {
/**
* 生成sheet
*
* @param file
* @param index
* @return
@ -251,7 +527,7 @@ public class PoiUtil {
InputStream inputStream = new FileInputStream(file);
Workbook workbook;
if (file.getPath().endsWith(".xls")) {
workbook = new HSSFWorkbook(inputStream);
workbook = new XSSFWorkbook(inputStream);
} else {
workbook = new XSSFWorkbook(inputStream);
}
@ -261,17 +537,165 @@ public class PoiUtil {
return workbook.getSheetAt(index);
}
public static void main(String[] args) throws Exception {
File file = new File("D:\\1.xlsx");
List<Object[]> list = readExce(file, 0, null, 3, true);
for (Object[] arr : list) {
for (Object t : arr) {
System.out.print(t + "---");
/**
* 插入图片
* @param row1起始行
* @param row2终止行
* @param col1起始列
* @param col2终止列
* @throws IOException
*/
public static Workbook setImg(Workbook wb,String sheetName,String imgPath,int row1,int row2,int col1,int col2) throws IOException {
// 第一步,创建一个XSSFWorkbook,对应一个Excel文件
if (wb == null) {
wb = new XSSFWorkbook();
}
// 第二步,在workbook中添加一个sheet,对应Excel文件中的sheet
Sheet sheet = wb.getSheet(sheetName);
if (ObjectUtil.isNull(sheet)) {
sheet = wb.createSheet(sheetName);
}
// 插入 PNG 图片至 Excel
InputStream is = new FileInputStream(imgPath);
if(ObjectUtil.isNull(is)){
return wb;
}
byte[] bytes = IOUtils.toByteArray(is);
int pictureIdx = wb.addPicture(bytes, Workbook.PICTURE_TYPE_PNG);
CreationHelper helper = wb.getCreationHelper();
Drawing drawing = sheet.createDrawingPatriarch();
ClientAnchor anchor = helper.createClientAnchor();
// 图片插入坐标
anchor.setDx1(0);
anchor.setDy1(0);
anchor.setDx2(0);
anchor.setDy2(0);
anchor.setRow1(row1);
anchor.setRow2(row2);
anchor.setCol1(col1);
anchor.setCol2(col2);
// 插入图片
Picture pict = drawing.createPicture(anchor, pictureIdx);
return wb;
}
/**
* 获取excel的列号
* @param num 第几列从1开始
* @return 返回列号
*/
public static String toRadix(Integer num) throws Exception{
String[] array = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"};
int count = 26;
String out = "";
if(num > count){
if(num % count == 0){
out = array[(num / count) - 1 - 1] + array[count - 1];
}else {
out = array[(num / count) - 1] + array[(num % count) - 1];
}
System.out.println("============");
}else{
out = array[num - 1];
}
return out;
}
public static void main(String[] args) throws Exception {
String s = toRadix(3);
System.out.println(s);
// File file = new File("F:\\wenjian\\3.xlsx");
// file.createNewFile();
// InputStream inputStream = new FileInputStream(file);
Workbook workbook = new XSSFWorkbook();
// XSSFSheet sheet = (XSSFSheet) workbook.getSheetAt(0);
// XSSFRow row = sheet.getRow(6);
// XSSFCell newCell = row.createCell(2);
// XSSFCell newCell1 = row.createCell(3);
// //添加公式
// newCell.setCellFormula("A7+B7");
// newCell1.setCellFormula("A8/B8");
// //设置打印区域
// workbook.setPrintArea(
// 0, //工作薄 下标0开始
// 0, //起始列 下标0开始
// 20, //终止列 下标0开始
// 0, //起始行 下标0开始
// 20 //终止行 下标0开始
// );
//// CellStyle style = workbook.createCellStyle();
//// style.setFillBackgroundColor();
//
// OutputStream stream = new FileOutputStream(new File("D:\\1.xlsx"));
// workbook.write(stream);
// stream.close();
PoiUtilCell poiUtilCell = new PoiUtilCell();
poiUtilCell.setValue("111222333");
poiUtilCell.setColspan(2);
poiUtilCell.setRowspan(1);
PoiUtilCell poiUtilCell1 = new PoiUtilCell();
poiUtilCell1.setValue("1112222");
PoiUtilCell poiUtilCell3 = new PoiUtilCell();
poiUtilCell3.setValue("123");
PoiUtilCell poiUtilCell2 = new PoiUtilCell();
poiUtilCell2.setValue("");
poiUtilCell2.setFunction("SUM(A1:C1)");
List<PoiUtilCell> cells = new ArrayList<>();
cells.add(poiUtilCell);
cells.add(poiUtilCell1);
cells.add(poiUtilCell3);
cells.add(poiUtilCell2);
List<List<PoiUtilCell>> list = new ArrayList<>();
list.add(cells);
// list.add(cells);
//
// List<PoiUtilCell> cells1 = new ArrayList<>();
// cells1.add(new PoiUtilCell("两列一行", 2, 1));
// list.add(cells1);
//
// List<PoiUtilCell> cells2 = new ArrayList<>();
// cells2.add(new PoiUtilCell("一列两行", 1, 2));
// list.add(cells2);
// List<PoiUtilCell> cells3 = new ArrayList<>();
// cells3.add(new PoiUtilCell("5"));
// cells3.add(new PoiUtilCell("6"));
// list.add(cells3);
// List<PoiUtilCell> cells4 = new ArrayList<>();
// list.add(cells4);
// List<PoiUtilCell> cells5 = new ArrayList<>();
// cells5.add(new PoiUtilCell("9", 2, 2));
// cells5.add(new PoiUtilCell("9"));
// list.add(cells5);
String fileName = "zzz/" + cn.hutool.core.date.DateUtil.today() + "/" + System.currentTimeMillis() + ".xlsx";
String path = WebConstant.UPLOAD_PATH_BASE + fileName;
File tmpFile = new File(path);
if (!tmpFile.getParentFile().exists()) {
tmpFile.getParentFile().mkdirs();
}
Workbook wbs = exportWB("Sheet1", list, workbook);
OutputStream stream = new FileOutputStream(tmpFile);
wbs.write(stream);
stream.close();
}
}
}

3
util/src/main/java/com/ccsens/util/WebConstant.java

@ -6,7 +6,8 @@ import java.io.File;
public class WebConstant {
/**cell内容不赋值*/
public static final String CELL_NULL = "cell_null";
/**数据存在*/
public static final byte STATUS_EXIT = 0;
/**数据已删除*/

Loading…
Cancel
Save