| | |
| | | import com.smartor.common.MtSubmitSmUtil; |
| | | import com.smartor.common.ScheduleSubtaskBuilder; |
| | | import com.smartor.config.PhoneUtils; |
| | | import com.smartor.domain.DTO.MydTrendReqDTO; |
| | | import com.smartor.domain.DTO.QuestionCountKsOrBqDTO; |
| | | import com.smartor.domain.DTO.ServiceSubtaskDetailDTO; |
| | | import com.smartor.domain.*; |
| | |
| | | serviceSubtask.setUpdateTime(DateUtils.getNowDate()); |
| | | if (serviceSubtask.getSendstate() != null && serviceSubtask.getSendstate() == 6) |
| | | serviceSubtask.setFinishtime(new Date()); |
| | | |
| | | return serviceSubtaskMapper.updateServiceSubtask(serviceSubtask); |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | @Override |
| | | public List<ServiceSubtaskDetailRatioExport> statQuestionOption(List<Long> taskIds, Date startOutHospTime, Date endOutHospTime, String scriptContent, Double scoreStart, Double scoreEnd, String valueType) { |
| | | public List<ServiceSubtaskDetailRatioExport> statQuestionOption(List<Long> taskIds, Date startFinishTime, Date endFinishTime, Date startOutHospTime, Date endOutHospTime, String scriptContent, Double scoreStart, Double scoreEnd, String valueType) { |
| | | //先清理一下重复数据 |
| | | List<Long> repeatIds = serviceSubtaskDetailMapper.selectRepeatDetailIds(); |
| | | if (!CollectionUtils.isEmpty(repeatIds)) { |
| | | serviceSubtaskDetailMapper.deleteRepeatDetailByIds(repeatIds); |
| | | } |
| | | List<ServiceSubtaskDetailRatioExport> serviceSubtaskDetailRatioExports = serviceSubtaskMapper.statQuestionOption(taskIds, startOutHospTime, endOutHospTime, scoreStart, scoreEnd, scriptContent, valueType); |
| | | List<ServiceSubtaskDetailRatioExport> serviceSubtaskDetailRatioExports = serviceSubtaskMapper.statQuestionOption(taskIds, startOutHospTime, endOutHospTime, startFinishTime, endFinishTime, scoreStart, scoreEnd, scriptContent, valueType); |
| | | |
| | | // 处理 targetvalue:按 & 分割成多条记录 |
| | | List<ServiceSubtaskDetailRatioExport> result = new ArrayList<>(); |
| | |
| | | * 根据科室或病区统计问卷选项(科室、题目查询的科室评分表) |
| | | */ |
| | | @Override |
| | | public List<QuestionCountKsOrBqDTO> statQuestionOptionByKsOrBq(QuestionCountKsOrBqVO vo) { |
| | | public Map<String, Map<String, List<QuestionCountKsOrBqDTO>>> statQuestionOptionByKsOrBq(QuestionCountKsOrBqVO vo) { |
| | | |
| | | // 1. 查明细 |
| | | List<QuestionCountKsOrBqDTO> sourceList = serviceSubtaskMapper.statQuestionOptionByKsOrBq(vo); |
| | | if (CollectionUtils.isEmpty(sourceList)) { |
| | | return Collections.emptyList(); |
| | | return Collections.emptyMap(); |
| | | } |
| | | |
| | | // 2. 判断按科室还是按病区 |
| | | boolean byDept = vo.getLeaveldeptcodes() != null; |
| | | boolean byDistrict = !byDept && vo.getLeavehospitaldistrictcodes() != null; |
| | | if (!byDept && !byDistrict) { |
| | | return Collections.emptyList(); |
| | | return Collections.emptyMap(); |
| | | } |
| | | |
| | | // 3. key = 科室/病区 + 题目 + 选项 |
| | | Map<String, QuestionCountKsOrBqDTO> map = new LinkedHashMap<>(); |
| | | |
| | | for (QuestionCountKsOrBqDTO dto : sourceList) { |
| | | |
| | | if (StringUtils.isEmpty(dto.getTargetvalue())) { |
| | | continue; |
| | | } |
| | | |
| | | // 分组名:科室 或 病区 |
| | | String groupName = byDept ? dto.getDeptname() : dto.getLeavehospitaldistrictname(); |
| | | if (StringUtils.isEmpty(groupName)) { |
| | | continue; |
| | | } |
| | | |
| | | // 关键:两边都用 trimAll,兼容全角空格 |
| | | String asrtext = trimAll(dto.getAsrtext()); |
| | | String questionKey = dto.getTaskid() + "\u0001" + trimAll(dto.getQeustionText()); |
| | | String asrtext = trimAll(dto.getAsrtext()); // 用户实际选中的选项 |
| | | String questionText = trimAll(dto.getQuestionText()); // 题目 |
| | | if (StringUtils.isEmpty(questionText)) { |
| | | continue; |
| | | } |
| | | |
| | | // 拆分 targetvalue,每个选项都要有一条记录 |
| | | for (String raw : dto.getTargetvalue().split("&")) { |
| | | String option = trimAll(raw); // ← 修复点:用 trimAll 而不是 trim |
| | | |
| | | String option = trimAll(raw); |
| | | if (option.isEmpty()) { |
| | | continue; |
| | | } |
| | | |
| | | String key = buildKey(groupName, option, questionKey); |
| | | // key = 科室/病区 + 题目 + 选项 |
| | | String key = buildKey(groupName, questionText, option); |
| | | |
| | | QuestionCountKsOrBqDTO item = map.get(key); |
| | | if (item == null) { |
| | | item = DtoConversionUtils.sourceToTarget(dto, QuestionCountKsOrBqDTO.class); |
| | | item.setTargetvalue(option); // 输出的 targetvalue 就是当前选项 |
| | | item.setTargetvalue(option); |
| | | item.setAsrtext(option); |
| | | item.setQuestionText(dto.getQuestionText()); |
| | | item.setAnswerCount("0"); |
| | | item.setSingleScore("0"); |
| | | map.put(key, item); |
| | | } |
| | | |
| | | // 只有当前选项 == 用户实际选中的选项,才累加 |
| | | if (option.equals(asrtext)) { |
| | | item.setAnswerCount(String.valueOf(parseCount(item.getAnswerCount()) + 1)); |
| | | item.setSingleScore(String.valueOf(new BigDecimal(item.getSingleScore()).add(new BigDecimal(dto.getSingleScore())))); |
| | | int count = parseCount(item.getAnswerCount()) + 1; |
| | | item.setAnswerCount(String.valueOf(count)); |
| | | |
| | | BigDecimal totalScore = new BigDecimal(item.getSingleScore()) |
| | | .add(new BigDecimal(dto.getSingleScore() == null ? "0" : dto.getSingleScore())); |
| | | item.setSingleScore(totalScore.toPlainString()); |
| | | } |
| | | } |
| | | } |
| | | ArrayList<QuestionCountKsOrBqDTO> questionCountKsOrBqDTOS = new ArrayList<>(map.values()); |
| | | for (QuestionCountKsOrBqDTO questionCountKsOrBqDTO : questionCountKsOrBqDTOS) { |
| | | String singleScore = questionCountKsOrBqDTO.getSingleScore(); |
| | | String answerCount = questionCountKsOrBqDTO.getAnswerCount(); |
| | | |
| | | // 4. 计算平均分 |
| | | for (QuestionCountKsOrBqDTO dto : map.values()) { |
| | | String answerCount = dto.getAnswerCount(); |
| | | String singleScore = dto.getSingleScore(); |
| | | |
| | | BigDecimal avg; |
| | | if (StringUtils.isEmpty(answerCount) |
| | | || BigDecimal.ZERO.compareTo(new BigDecimal(answerCount.trim())) == 0) { |
| | | // 除数为 0,避免 / by zero |
| | | avg = BigDecimal.ZERO; |
| | | } else { |
| | | avg = new BigDecimal(singleScore) |
| | | avg = new BigDecimal(singleScore == null ? "0" : singleScore) |
| | | .divide(new BigDecimal(answerCount.trim()), 2, RoundingMode.HALF_UP); |
| | | } |
| | | questionCountKsOrBqDTO.setAvgScore(avg.toPlainString()); |
| | | |
| | | dto.setAvgScore(avg.toPlainString()); |
| | | } |
| | | |
| | | return questionCountKsOrBqDTOS; |
| | | // 5. 转成 Map<String, Map<String, List<QuestionCountKsOrBqDTO>>> |
| | | // 第一层 key:科室/病区 |
| | | // 第二层 key:题目 |
| | | // 第二层 value:该题目下的所有选项列表 |
| | | Map<String, Map<String, List<QuestionCountKsOrBqDTO>>> result = new LinkedHashMap<>(); |
| | | |
| | | for (QuestionCountKsOrBqDTO dto : map.values()) { |
| | | |
| | | // 分组名 |
| | | String groupName = byDept ? dto.getDeptname() : dto.getLeavehospitaldistrictname(); |
| | | if (StringUtils.isEmpty(groupName)) { |
| | | continue; |
| | | } |
| | | |
| | | // 题目名 |
| | | String questionText = dto.getQuestionText(); |
| | | if (StringUtils.isEmpty(questionText)) { |
| | | continue; |
| | | } |
| | | |
| | | // 第一层:科室/病区 |
| | | Map<String, List<QuestionCountKsOrBqDTO>> questionMap = |
| | | result.computeIfAbsent(groupName, k -> new LinkedHashMap<>()); |
| | | |
| | | // 第二层:题目 |
| | | List<QuestionCountKsOrBqDTO> optionList = |
| | | questionMap.computeIfAbsent(questionText, k -> new ArrayList<>()); |
| | | |
| | | optionList.add(dto); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | | public List<ServiceSubtaskDetailRatioExport> statQuestionOptionBySubtaskIds(List<Long> subtaskIds, Date startOutHospTime, Date endOutHospTime, String scriptContent, Double scoreStart, Double scoreEnd, String valueType) { |
| | | public List<ServiceSubtaskDetailRatioExport> statQuestionOptionBySubtaskIds(List<Long> subtaskIds, Date startOutHospTime, Date endOutHospTime, Date startFinishTime, Date endFinishTime, String scriptContent, Double scoreStart, Double scoreEnd, String valueType) { |
| | | //先清理一下重复数据 |
| | | List<Long> repeatIds = serviceSubtaskDetailMapper.selectRepeatDetailIds(); |
| | | if (!CollectionUtils.isEmpty(repeatIds)) { |
| | | serviceSubtaskDetailMapper.deleteRepeatDetailByIds(repeatIds); |
| | | } |
| | | |
| | | List<ServiceSubtaskDetailRatioExport> serviceSubtaskDetailRatioExports = serviceSubtaskMapper.statQuestionOptionBySubtaskIds(subtaskIds, startOutHospTime, endOutHospTime, scoreStart, scoreEnd, scriptContent, valueType); |
| | | List<ServiceSubtaskDetailRatioExport> serviceSubtaskDetailRatioExports = serviceSubtaskMapper.statQuestionOptionBySubtaskIds(subtaskIds, startOutHospTime, endOutHospTime, startFinishTime, endFinishTime, scoreStart, scoreEnd, scriptContent, valueType); |
| | | // 处理 targetvalue:按 & 分割成多条记录 |
| | | List<ServiceSubtaskDetailRatioExport> result = new ArrayList<>(); |
| | | for (ServiceSubtaskDetailRatioExport export : serviceSubtaskDetailRatioExports) { |
| | |
| | | } |
| | | return content; |
| | | } |
| | | |
| | | /** |
| | | * 满意度趋势查询 |
| | | * |
| | | * @param mydTrendReqVO |
| | | * @return |
| | | */ |
| | | @Override |
| | | public List<MydTrendReqDTO> mydTrend(MydTrendReqVO mydTrendReqVO) { |
| | | List<MydTrendReqDTO> list = serviceSubtaskMapper.mydTrend(mydTrendReqVO.getStartFinishTime(), mydTrendReqVO.getEndFinishTime(), mydTrendReqVO.getType()); |
| | | if (mydTrendReqVO.getType().equals("week")) list = getWeekDate(mydTrendReqVO, list); |
| | | if (mydTrendReqVO.getType().equals("year")) list = getYearDate(mydTrendReqVO, list); |
| | | if (mydTrendReqVO.getType().equals("month")) list = getMonthDate(mydTrendReqVO, list); |
| | | if (mydTrendReqVO.getType().equals("day")) list = getDayDate(mydTrendReqVO, list); |
| | | return list; |
| | | } |
| | | |
| | | @Override |
| | | public List<MydTrendReqDTO> sltdMydTotalByDimension(MydTrendReqVO mydTrendReqVO) { |
| | | List<MydTrendReqDTO> list = null; |
| | | if (mydTrendReqVO.getDimensionType().equals("1")) |
| | | list = serviceSubtaskMapper.sltdMydTotalByDimension(mydTrendReqVO.getStartFinishTime(), mydTrendReqVO.getEndFinishTime(), mydTrendReqVO.getType()); |
| | | else if (mydTrendReqVO.getDimensionType().equals("2")) |
| | | list = serviceSubtaskMapper.sltdMydTotalByYQ(mydTrendReqVO.getStartFinishTime(), mydTrendReqVO.getEndFinishTime(), mydTrendReqVO.getType()); |
| | | |
| | | return list; |
| | | } |
| | | |
| | | |
| | | public ServiceSubtask boxedServiceSubtask(ServiceTask serviceTask, ServiceTaskdept serviceTaskdept, PatArchive patArchive) { |
| | | ServiceSubtask serviceSubtask = DtoConversionUtils.sourceToTarget(serviceTask, ServiceSubtask.class); |
| | |
| | | /** |
| | | * 问题结果占比 |
| | | * |
| | | * @param questionResultVO |
| | | * @param sltdMydTotalVO |
| | | * @param serviceSubtaskRes |
| | | * @return |
| | | */ |
| | | public List<ServiceSubtaskDetailRatioExport> getDetailRatio(QuestionResultVO questionResultVO, List<ServiceSubtaskRes> serviceSubtaskRes) { |
| | | public List<ServiceSubtaskDetailRatioExport> getDetailRatio(SltdMydTotalVO sltdMydTotalVO, List<ServiceSubtaskRes> serviceSubtaskRes) { |
| | | List<ServiceSubtaskDetailRatioExport> serviceSubtaskDetailRatioExports = null; |
| | | if (StringUtils.isNotEmpty(questionResultVO.getServiceType()) && questionResultVO.getServiceType().equals("2")) { |
| | | if (CollectionUtils.isNotEmpty(sltdMydTotalVO.getServiceTypeList()) && sltdMydTotalVO.getServiceTypeList().contains("2") && (sltdMydTotalVO.getServiceTypeList().contains("6") || sltdMydTotalVO.getServiceTypeList().contains("14"))) { |
| | | //serviceType,即有随访又有满意度,暂时没法统计 |
| | | return serviceSubtaskDetailRatioExports; |
| | | } else if (CollectionUtils.isNotEmpty(sltdMydTotalVO.getServiceTypeList()) && sltdMydTotalVO.getServiceTypeList().contains("2")) { |
| | | //获取serviceSubtaskList中的所有taskid |
| | | List<Long> taskIds = serviceSubtaskRes.stream().map(ServiceSubtaskRes::getTaskid).filter(ObjectUtils::isNotEmpty).distinct().collect(Collectors.toList()); |
| | | serviceSubtaskDetailRatioExports = statQuestionOption(taskIds, questionResultVO.getStartOutHospTime(), questionResultVO.getEndOutHospTime(), questionResultVO.getQuestionContent(), questionResultVO.getStartScore(), questionResultVO.getEndScore(), questionResultVO.getValueType()); |
| | | } else if (StringUtils.isNotEmpty(questionResultVO.getServiceType()) && questionResultVO.getServiceType().equals("6")) { |
| | | serviceSubtaskDetailRatioExports = statQuestionOption(taskIds, sltdMydTotalVO.getStartFinishTime(), sltdMydTotalVO.getEndFinishTime(), sltdMydTotalVO.getStartOutHospTime(), sltdMydTotalVO.getEndOutHospTime(), sltdMydTotalVO.getQuestionContent(), sltdMydTotalVO.getStartScore(), sltdMydTotalVO.getEndScore(), sltdMydTotalVO.getValueType()); |
| | | } else if (CollectionUtils.isNotEmpty(sltdMydTotalVO.getServiceTypeList()) && sltdMydTotalVO.getServiceTypeList().contains("6") || sltdMydTotalVO.getServiceTypeList().contains("14")) { |
| | | //满意度统计 (通过 subtask 的 id 去统计) |
| | | List<Long> subtaskIds = serviceSubtaskRes.stream().map(ServiceSubtaskRes::getId).collect(Collectors.toList()); |
| | | serviceSubtaskDetailRatioExports = statQuestionOptionBySubtaskIds(subtaskIds, questionResultVO.getStartOutHospTime(), questionResultVO.getEndOutHospTime(), questionResultVO.getQuestionContent(), questionResultVO.getStartScore(), questionResultVO.getEndScore(), questionResultVO.getValueType()); |
| | | serviceSubtaskDetailRatioExports = statQuestionOptionBySubtaskIds(subtaskIds, sltdMydTotalVO.getStartOutHospTime(), sltdMydTotalVO.getEndOutHospTime(), sltdMydTotalVO.getStartFinishTime(), sltdMydTotalVO.getEndFinishTime(), sltdMydTotalVO.getQuestionContent(), sltdMydTotalVO.getStartScore(), sltdMydTotalVO.getEndScore(), sltdMydTotalVO.getValueType()); |
| | | } |
| | | return serviceSubtaskDetailRatioExports; |
| | | } |
| | |
| | | private static Boolean isBlankChar(char c) { |
| | | return c == '\u3000' // 全角空格 |
| | | || c == ' ' // 半角空格 |
| | | || c == '\t' |
| | | || c == '\n' |
| | | || c == '\r' |
| | | || c == '\f' |
| | | || Character.isWhitespace(c); |
| | | || c == '\t' || c == '\n' || c == '\r' || c == '\f' || Character.isWhitespace(c); |
| | | } |
| | | |
| | | private String buildKey(String groupName, String option, String questionKey) { |
| | | return questionKey + KEY_SEP + groupName + KEY_SEP + option; |
| | | |
| | | private String buildKey(String groupName, String questionText, String option) { |
| | | return groupName + "\u0001" + questionText + "\u0001" + option; |
| | | } |
| | | |
| | | private static int parseCount(String s) { |
| | |
| | | return 0; |
| | | } |
| | | } |
| | | |
| | | private List<MydTrendReqDTO> getWeekDate(MydTrendReqVO mydTrendReqVO, List<MydTrendReqDTO> list) { |
| | | // 1. 计算总周数(和 SQL 里的公式保持一致) |
| | | long days = (mydTrendReqVO.getEndFinishTime().getTime() - mydTrendReqVO.getStartFinishTime().getTime()) / (1000L * 60 * 60 * 24); |
| | | int totalWeeks = (int) (days / 7) + 1; |
| | | |
| | | // 2. 已有数据:period -> totalScore |
| | | Map<Integer, String> exist = new HashMap<>(); |
| | | for (MydTrendReqDTO row : list) { |
| | | // period 是数字,可能是 Integer / Long / BigDecimal,统一转 int |
| | | int p = Integer.parseInt(StringUtils.isNotEmpty(row.getPeriod()) ? row.getPeriod() : "0"); |
| | | exist.put(p, row.getTotalScore() != null ? row.getTotalScore() : "0"); |
| | | // 下面这行按你的原逻辑保留(虽然看起来有点多余) |
| | | exist.put(p, String.valueOf(row.getTotalScore() != null ? row.getTotalScore() : 0)); |
| | | } |
| | | |
| | | // 3. 补全 1..totalWeeks |
| | | List<MydTrendReqDTO> result = new ArrayList<>(totalWeeks); |
| | | |
| | | // 获取整体的开始时间 |
| | | long startTimeMillis = mydTrendReqVO.getStartFinishTime().getTime(); |
| | | long endTimeMillis = mydTrendReqVO.getEndFinishTime().getTime(); |
| | | long oneWeekMillis = 7L * 24 * 60 * 60 * 1000; // 一周的毫秒数 |
| | | |
| | | for (int i = 1; i <= totalWeeks; i++) { |
| | | MydTrendReqDTO row = new MydTrendReqDTO(); |
| | | row.setPeriod(String.valueOf(i)); |
| | | row.setTotalScore(exist.getOrDefault(i, "0")); |
| | | |
| | | // -------- 新增:设置每周的 startDate 和 endDate -------- |
| | | // 当前周开始时间 = 整体开始时间 + (i - 1) * 7天 |
| | | long currentStartMillis = startTimeMillis + (long) (i - 1) * oneWeekMillis; |
| | | |
| | | // 当前周结束时间 = 当前周开始时间 + 7天 - 1毫秒(保证是这一周的最后一刻) |
| | | long currentEndMillis = currentStartMillis + oneWeekMillis - 1; |
| | | |
| | | // 如果是最后一周,结束时间不能超过整体的 endTime |
| | | if (i == totalWeeks) { |
| | | currentEndMillis = endTimeMillis; |
| | | } |
| | | |
| | | row.setStartDate(new Date(currentStartMillis)); |
| | | row.setEndDate(new Date(currentEndMillis)); |
| | | // ---------------------------------------------------- |
| | | |
| | | result.add(row); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | private List<MydTrendReqDTO> getYearDate(MydTrendReqVO mydTrendReqVO, List<MydTrendReqDTO> list) { |
| | | // 获取整体开始和结束时间 |
| | | Date startTime = mydTrendReqVO.getStartFinishTime(); |
| | | Date endTime = mydTrendReqVO.getEndFinishTime(); |
| | | |
| | | // 1. 计算年份范围 |
| | | // 使用 Calendar 获取起始年份和结束年份 |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.setTime(startTime); |
| | | int startYear = cal.get(Calendar.YEAR); |
| | | |
| | | cal.setTime(endTime); |
| | | int endYear = cal.get(Calendar.YEAR); |
| | | |
| | | // 总年数 (包含首尾) |
| | | int totalYears = endYear - startYear + 1; |
| | | |
| | | // 2. 已有数据:period -> totalScore (假设 period 存的是年份字符串,如 "2024") |
| | | Map<String, String> exist = new HashMap<>(); |
| | | for (MydTrendReqDTO row : list) { |
| | | String period = row.getPeriod() != null ? row.getPeriod() : ""; |
| | | exist.put(period, row.getTotalScore() != null ? row.getTotalScore() : "0"); |
| | | } |
| | | |
| | | // 3. 补全所有年份 |
| | | List<MydTrendReqDTO> result = new ArrayList<>(totalYears); |
| | | |
| | | for (int i = 0; i < totalYears; i++) { |
| | | int currentYear = startYear + i; |
| | | String periodKey = String.valueOf(currentYear); |
| | | |
| | | MydTrendReqDTO row = new MydTrendReqDTO(); |
| | | row.setPeriod(periodKey); |
| | | // 如果没有该年份的数据,默认给 "0" |
| | | row.setTotalScore(exist.getOrDefault(periodKey, "0")); |
| | | |
| | | // -------- 设置该年份的 startDate 和 endDate -------- |
| | | Calendar yearCal = Calendar.getInstance(); |
| | | // 设置为该年的 1月1日 00:00:00 |
| | | yearCal.set(currentYear, Calendar.JANUARY, 1, 0, 0, 0); |
| | | yearCal.set(Calendar.MILLISECOND, 0); |
| | | row.setStartDate(yearCal.getTime()); |
| | | |
| | | // 设置为该年的 12月31日 23:59:59 |
| | | yearCal.set(currentYear, Calendar.DECEMBER, 31, 23, 59, 59); |
| | | yearCal.set(Calendar.MILLISECOND, 999); |
| | | row.setEndDate(yearCal.getTime()); |
| | | // ---------------------------------------------------- |
| | | |
| | | result.add(row); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | private List<MydTrendReqDTO> getMonthDate(MydTrendReqVO mydTrendReqVO, List<MydTrendReqDTO> list) { |
| | | // 获取整体开始和结束时间 |
| | | Date startTime = mydTrendReqVO.getStartFinishTime(); |
| | | Date endTime = mydTrendReqVO.getEndFinishTime(); |
| | | |
| | | // 1. 计算月份范围 |
| | | Calendar cal = Calendar.getInstance(); |
| | | cal.setTime(startTime); |
| | | int startYear = cal.get(Calendar.YEAR); |
| | | int startMonth = cal.get(Calendar.MONTH); // 注意:Calendar.MONTH 从 0 开始 |
| | | |
| | | cal.setTime(endTime); |
| | | int endYear = cal.get(Calendar.YEAR); |
| | | int endMonth = cal.get(Calendar.MONTH); |
| | | |
| | | // 总月数 = (结束年 - 开始年) * 12 + (结束月 - 开始月) + 1 |
| | | int totalMonths = (endYear - startYear) * 12 + (endMonth - startMonth) + 1; |
| | | |
| | | // 2. 已有数据:period -> totalScore (period 存的是月份字符串,如 "2024-06") |
| | | Map<String, String> exist = new HashMap<>(); |
| | | for (MydTrendReqDTO row : list) { |
| | | String period = row.getPeriod() != null ? row.getPeriod() : ""; |
| | | exist.put(period, row.getTotalScore() != null ? row.getTotalScore() : "0"); |
| | | } |
| | | |
| | | // 3. 补全所有月份 |
| | | List<MydTrendReqDTO> result = new ArrayList<>(totalMonths); |
| | | |
| | | Calendar monthCal = Calendar.getInstance(); |
| | | monthCal.set(startYear, startMonth, 1, 0, 0, 0); |
| | | monthCal.set(Calendar.MILLISECOND, 0); |
| | | |
| | | for (int i = 0; i < totalMonths; i++) { |
| | | int currentYear = monthCal.get(Calendar.YEAR); |
| | | int currentMonth = monthCal.get(Calendar.MONTH) + 1; // 转成 1-12 月 |
| | | |
| | | // 拼接 period,格式:yyyy-MM,比如 "2024-06" |
| | | // 如果你希望是 "2024-6",可以把 String.format 改成 currentMonth |
| | | String periodKey = String.format("%04d-%02d", currentYear, currentMonth); |
| | | |
| | | MydTrendReqDTO row = new MydTrendReqDTO(); |
| | | row.setPeriod(periodKey); |
| | | row.setTotalScore(exist.getOrDefault(periodKey, "0")); |
| | | |
| | | // -------- 设置该月的 startDate 和 endDate -------- |
| | | // 当月开始时间:1号 00:00:00.000 |
| | | Calendar startCal = (Calendar) monthCal.clone(); |
| | | row.setStartDate(startCal.getTime()); |
| | | |
| | | // 当月结束时间:下个月1号 00:00:00.000 减 1 毫秒 |
| | | Calendar endCal = (Calendar) monthCal.clone(); |
| | | endCal.add(Calendar.MONTH, 1); |
| | | endCal.add(Calendar.MILLISECOND, -1); |
| | | row.setEndDate(endCal.getTime()); |
| | | // ---------------------------------------------------- |
| | | |
| | | result.add(row); |
| | | |
| | | // 进入下一个月 |
| | | monthCal.add(Calendar.MONTH, 1); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | private List<MydTrendReqDTO> getDayDate(MydTrendReqVO mydTrendReqVO, List<MydTrendReqDTO> list) { |
| | | // 获取整体开始和结束时间 |
| | | Date startTime = mydTrendReqVO.getStartFinishTime(); |
| | | Date endTime = mydTrendReqVO.getEndFinishTime(); |
| | | |
| | | // 1. 计算总天数 |
| | | long oneDayMillis = 24L * 60 * 60 * 1000; |
| | | // 注意:这里只算日期差,不考虑时分秒,否则可能差一天 |
| | | Calendar startCal = Calendar.getInstance(); |
| | | startCal.setTime(startTime); |
| | | startCal.set(Calendar.HOUR_OF_DAY, 0); |
| | | startCal.set(Calendar.MINUTE, 0); |
| | | startCal.set(Calendar.SECOND, 0); |
| | | startCal.set(Calendar.MILLISECOND, 0); |
| | | |
| | | Calendar endCal = Calendar.getInstance(); |
| | | endCal.setTime(endTime); |
| | | endCal.set(Calendar.HOUR_OF_DAY, 0); |
| | | endCal.set(Calendar.MINUTE, 0); |
| | | endCal.set(Calendar.SECOND, 0); |
| | | endCal.set(Calendar.MILLISECOND, 0); |
| | | |
| | | long days = (endCal.getTimeInMillis() - startCal.getTimeInMillis()) / oneDayMillis; |
| | | int totalDays = (int) days + 1; |
| | | |
| | | // 2. 已有数据:period -> totalScore (period 存的是日期字符串,如 "2024-06-01") |
| | | Map<String, String> exist = new HashMap<>(); |
| | | for (MydTrendReqDTO row : list) { |
| | | String period = row.getPeriod() != null ? row.getPeriod() : ""; |
| | | exist.put(period, row.getTotalScore() != null ? row.getTotalScore() : "0"); |
| | | } |
| | | |
| | | // 3. 补全所有日期 |
| | | List<MydTrendReqDTO> result = new ArrayList<>(totalDays); |
| | | |
| | | Calendar dayCal = (Calendar) startCal.clone(); |
| | | for (int i = 0; i < totalDays; i++) { |
| | | // 拼接 period,格式:yyyy-MM-dd |
| | | String periodKey = String.format("%04d-%02d-%02d", dayCal.get(Calendar.YEAR), dayCal.get(Calendar.MONTH) + 1, dayCal.get(Calendar.DAY_OF_MONTH)); |
| | | |
| | | MydTrendReqDTO row = new MydTrendReqDTO(); |
| | | row.setPeriod(periodKey); |
| | | row.setTotalScore(exist.getOrDefault(periodKey, "0")); |
| | | |
| | | // -------- 设置该天的 startDate 和 endDate -------- |
| | | Calendar startOfDay = (Calendar) dayCal.clone(); |
| | | row.setStartDate(startOfDay.getTime()); |
| | | |
| | | Calendar endOfDay = (Calendar) dayCal.clone(); |
| | | endOfDay.set(Calendar.HOUR_OF_DAY, 23); |
| | | endOfDay.set(Calendar.MINUTE, 59); |
| | | endOfDay.set(Calendar.SECOND, 59); |
| | | endOfDay.set(Calendar.MILLISECOND, 999); |
| | | row.setEndDate(endOfDay.getTime()); |
| | | // ---------------------------------------------------- |
| | | |
| | | result.add(row); |
| | | |
| | | // 进入下一天 |
| | | dayCal.add(Calendar.DAY_OF_MONTH, 1); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | } |