ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/ServiceSubtaskController.java
@@ -811,8 +811,18 @@ LoginUser loginUser = getLoginUser(); String orgid = loginUser.getUser().getOrgid(); serviceSubtaskCountReq.setOrgid(orgid); PageUtils.startPageByPost(serviceSubtaskCountReq.getPageNum(), serviceSubtaskCountReq.getPageSize()); return success(serviceSubtaskService.getSfStatisticsScriptDetails(serviceSubtaskCountReq)); //注意:这里不能再调用 PageUtils.startPageByPost。 //返回结构是 Map,且不传 type 时会执行两条 SQL,PageHelper 只作用于第一条 SQL, //分页已放到 Service 里按题目(scriptid)完成,保证 total 是题目总数。 Map<String, Object> details = serviceSubtaskService.getSfStatisticsScriptDetails(serviceSubtaskCountReq); AjaxResult ajax = success(details.get("data")); //兼容旧前端:data 仍然是 {scriptid: 题目} 的 Map; //同时按 RuoYi 习惯补上 rows/total/pageNum/pageSize 方便前端分页 ajax.put("rows", details.get("rows")); ajax.put("total", details.get("total")); ajax.put("pageNum", details.get("pageNum")); ajax.put("pageSize", details.get("pageSize")); return ajax; } /** smartor/src/main/java/com/smartor/domain/PatArchiveReq.java
@@ -227,6 +227,18 @@ private Integer cry; /** * 创建时间 */ @JsonFormat(pattern = "yyyy-MM-dd") private Date createTimeStart; /** * 创建时间 */ @JsonFormat(pattern = "yyyy-MM-dd") private Date createTimeEnd; /** * 机构ID */ @ApiModelProperty("院区") smartor/src/main/java/com/smartor/service/IServiceSubtaskService.java
@@ -200,7 +200,7 @@ public List<ServiceSubtaskStatistic> getSfStatisticsScript(ServiceSubtaskCountReq serviceSubtaskCountReq); public Map<String, ServiceSubtaskScriptCount> getSfStatisticsScriptDetails(ServiceSubtaskCountReq serviceSubtaskCountReq); public Map<String, Object> getSfStatisticsScriptDetails(ServiceSubtaskCountReq serviceSubtaskCountReq); public List<PatArchiveSrmVO> sendMsgTemplate(List<PatArchiveSrmVO> patArchiveSrmVOS); smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskServiceImpl.java
@@ -4367,7 +4367,8 @@ serviceSubtaskStatistic.setDrname(serviceSubtaskList.get(0).getDrname()); serviceSubtaskStatistic.setJoyCount(0); serviceSubtaskStatistic.setJoyAllCount(0); //出院人次 serviceSubtaskStatistic.setDischargeCount(serviceSubtaskList.size()); //获取随访统计 if (subCounts == null) { subCounts = new ArrayList<>(); @@ -4873,7 +4874,7 @@ * @return */ @Override @Cacheable(value = "getSfStatisticsScript", key = "T(org.springframework.util.DigestUtils).md5DigestAsHex(#serviceSubtaskCountReq.toString().getBytes())", unless = "#result == null or #result.isEmpty()") // @Cacheable(value = "getSfStatisticsScript", key = "T(org.springframework.util.DigestUtils).md5DigestAsHex(#serviceSubtaskCountReq.toString().getBytes())", unless = "#result == null or #result.isEmpty()") public List<ServiceSubtaskStatistic> getSfStatisticsScript(ServiceSubtaskCountReq serviceSubtaskCountReq) { log.info("getSfStatisticsScript的入参为:{}", serviceSubtaskCountReq); List<ServiceSubtaskStatistic> serviceSubtaskStatistics = new ArrayList<>(); @@ -4881,13 +4882,13 @@ // 根据条件进行分组 Map<String, List<ServiceSubtask>> collect = new HashMap<>(); String groupKey = "drcode"; if (serviceSubtaskCountReq.getLeavehospitaldistrictcodes() != null && !serviceSubtaskCountReq.getLeavehospitaldistrictcodes().isEmpty()) { if (serviceSubtaskCountReq.getStatisticaltype() != null && serviceSubtaskCountReq.getStatisticaltype() == 1) { if (serviceSubtaskCountReq.getDrcode() != null && !serviceSubtaskCountReq.getDrcode().isEmpty()) { groupKey = "drcode"; } else { groupKey = "leavehospitaldistrictcode"; } } else if (serviceSubtaskCountReq.getDeptcodes() != null && !serviceSubtaskCountReq.getDeptcodes().isEmpty()) { } else if (serviceSubtaskCountReq.getStatisticaltype() != null && serviceSubtaskCountReq.getStatisticaltype() == 2) { if (serviceSubtaskCountReq.getDrcode() != null && !serviceSubtaskCountReq.getDrcode().isEmpty()) { groupKey = "drcode"; } else { @@ -5003,8 +5004,7 @@ } @Override public Map<String, ServiceSubtaskScriptCount> getSfStatisticsScriptDetails(ServiceSubtaskCountReq serviceSubtaskCountReq) { Map<String, ServiceSubtaskScriptCount> result = new HashMap<>(); public Map<String, Object> getSfStatisticsScriptDetails(ServiceSubtaskCountReq serviceSubtaskCountReq) { List<ServiceSubtaskScriptCount> allCounts = new ArrayList<>(); List<ServiceSubtaskScriptCount> allItemCounts = new ArrayList<>(); String type = serviceSubtaskCountReq.getType(); @@ -5028,7 +5028,23 @@ allItemCounts = serviceSubtaskMapper.getSfStatisticsScriptItemDetails(serviceSubtaskCountReq); } for (ServiceSubtaskScriptCount count : allCounts) { //返回结构是 Map,且不传 type 时会执行两条 SQL,PageHelper 没法对整体分页, //所以在题目合并完成之后按题目(scriptid)在这里分页,保证 total 和每页数据都是题目维度的。 allCounts.sort(Comparator .comparing(ServiceSubtaskScriptCount::getSubtaskType, Comparator.nullsLast(String::compareTo)) .thenComparing(ServiceSubtaskScriptCount::getScriptid, Comparator.nullsLast(Long::compareTo))); int pageNum = ObjectUtils.isNotEmpty(serviceSubtaskCountReq.getPageNum()) && serviceSubtaskCountReq.getPageNum() > 0 ? serviceSubtaskCountReq.getPageNum() : 1; int pageSize = ObjectUtils.isNotEmpty(serviceSubtaskCountReq.getPageSize()) && serviceSubtaskCountReq.getPageSize() > 0 ? serviceSubtaskCountReq.getPageSize() : 10; int total = allCounts.size(); int fromIndex = (int) Math.min((long) (pageNum - 1) * pageSize, total); int toIndex = Math.min(fromIndex + pageSize, total); List<ServiceSubtaskScriptCount> pageCounts = allCounts.subList(fromIndex, toIndex); Map<String, ServiceSubtaskScriptCount> pageData = new LinkedHashMap<>(); for (ServiceSubtaskScriptCount count : pageCounts) { Map<String, ServiceSubtaskScriptCount> itemCountMap = new HashMap<>(); //问卷加上空白选项 if (ObjectUtils.isNotEmpty(count.getTemplateid()) && ObjectUtils.isNotEmpty(count.getSubtaskType()) && count.getSubtaskType().equals("2")) { @@ -5059,31 +5075,42 @@ } } allItemCounts.forEach(itemCount -> { if (ObjectUtils.isNotEmpty(count.getScriptid()) && ObjectUtils.isNotEmpty(itemCount.getScriptid())) { if (count.getScriptid().equals(itemCount.getScriptid())) { //放入统计信息 itemCount.setScriptContent(count.getScriptContent()); itemCount.setScriptType(count.getScriptType()); itemCount.setSubtaskType(count.getSubtaskType()); itemCount.setCompletedQuantity(count.getCompletedQuantity()); itemCount.setAllQuantity(count.getAllQuantity()); itemCount.setCompletedPercentage(count.getCompletedPercentage()); itemCount.setTemplateid(count.getTemplateid()); //计算选择比例 int chosenQuantity = ObjectUtils.isNotEmpty(itemCount.getChosenQuantity()) ? itemCount.getChosenQuantity() : 0; int completedQuantity = itemCount.getCompletedQuantity(); if (ObjectUtils.isNotEmpty(completedQuantity) && completedQuantity != 0) { BigDecimal chosenPercentage = (new BigDecimal(chosenQuantity)).divide(new BigDecimal(completedQuantity), 2, RoundingMode.HALF_UP); itemCount.setChosenPercentage(chosenPercentage.toString()); } itemCountMap.put(itemCount.getOptionText(), itemCount); //明细行已按“题目内容+任务类型”聚合并带出 script_content,不能用 scriptid 匹配: //同一道题会被复制到多个任务模板,每个模板的 scriptid 都不同 boolean sameQuestion = ObjectUtils.isNotEmpty(count.getScriptContent()) && ObjectUtils.isNotEmpty(itemCount.getScriptContent()) && count.getScriptContent().equals(itemCount.getScriptContent()) && Objects.equals(count.getSubtaskType(), itemCount.getSubtaskType()); if (sameQuestion) { //放入统计信息 itemCount.setScriptContent(count.getScriptContent()); itemCount.setScriptType(count.getScriptType()); itemCount.setSubtaskType(count.getSubtaskType()); itemCount.setCompletedQuantity(count.getCompletedQuantity()); itemCount.setAllQuantity(count.getAllQuantity()); itemCount.setCompletedPercentage(count.getCompletedPercentage()); itemCount.setTemplateid(count.getTemplateid()); //计算选择比例 int chosenQuantity = ObjectUtils.isNotEmpty(itemCount.getChosenQuantity()) ? itemCount.getChosenQuantity() : 0; int completedQuantity = itemCount.getCompletedQuantity(); if (ObjectUtils.isNotEmpty(completedQuantity) && completedQuantity != 0) { BigDecimal chosenPercentage = (new BigDecimal(chosenQuantity)).divide(new BigDecimal(completedQuantity), 2, RoundingMode.HALF_UP); itemCount.setChosenPercentage(chosenPercentage.toString()); } itemCountMap.put(itemCount.getOptionText(), itemCount); } }); List<ServiceSubtaskScriptCount> itemCounts = new ArrayList<>(itemCountMap.values()); count.setDetails(itemCounts); result.put(count.getScriptid().toString(), count); pageData.put(count.getScriptid().toString(), count); } Map<String, Object> result = new HashMap<>(); // total 是题目总数(已按题目合并),rows/data 是当前页数据 result.put("total", total); result.put("pageNum", pageNum); result.put("pageSize", pageSize); result.put("rows", new ArrayList<>(pageCounts)); result.put("data", pageData); return result; } smartor/src/main/java/com/smartor/service/impl/SvyLibTemplateScriptServiceImpl.java
@@ -16,6 +16,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import static net.sf.jsqlparser.parser.feature.Feature.values; @@ -157,25 +158,28 @@ } } itemCounts.forEach(itemCount ->{ if(ObjectUtils.isNotEmpty(count.getScriptid()) && ObjectUtils.isNotEmpty(itemCount.getScriptid())){ if(count.getScriptid().equals(itemCount.getScriptid())){ //放入统计信息 itemCount.setScriptContent(count.getScriptContent()); itemCount.setScriptType(count.getScriptType()); itemCount.setSubtaskType(count.getSubtaskType()); itemCount.setCompletedQuantity(count.getCompletedQuantity()); itemCount.setAllQuantity(count.getAllQuantity()); itemCount.setCompletedPercentage(count.getCompletedPercentage()); itemCount.setTemplateid(count.getTemplateid()); //计算选择比例 int chosenQuantity = ObjectUtils.isNotEmpty(itemCount.getChosenQuantity())?itemCount.getChosenQuantity():0; int completedQuantity = itemCount.getCompletedQuantity(); if(ObjectUtils.isNotEmpty(completedQuantity) && completedQuantity != 0){ BigDecimal chosenPercentage = (new BigDecimal(chosenQuantity)).divide(new BigDecimal(completedQuantity), 2, RoundingMode.HALF_UP); itemCount.setChosenPercentage(chosenPercentage.toString()); } itemCountMap.put(itemCount.getOptionText(), itemCount); //明细行已按“题目内容+任务类型”聚合,不能用 scriptid 匹配(同一道题在每个任务模板里的 scriptid 都不同) boolean sameQuestion = ObjectUtils.isNotEmpty(count.getScriptContent()) && ObjectUtils.isNotEmpty(itemCount.getScriptContent()) && count.getScriptContent().equals(itemCount.getScriptContent()) && Objects.equals(count.getSubtaskType(), itemCount.getSubtaskType()); if(sameQuestion){ //放入统计信息 itemCount.setScriptContent(count.getScriptContent()); itemCount.setScriptType(count.getScriptType()); itemCount.setSubtaskType(count.getSubtaskType()); itemCount.setCompletedQuantity(count.getCompletedQuantity()); itemCount.setAllQuantity(count.getAllQuantity()); itemCount.setCompletedPercentage(count.getCompletedPercentage()); itemCount.setTemplateid(count.getTemplateid()); //计算选择比例 int chosenQuantity = ObjectUtils.isNotEmpty(itemCount.getChosenQuantity())?itemCount.getChosenQuantity():0; int completedQuantity = itemCount.getCompletedQuantity(); if(ObjectUtils.isNotEmpty(completedQuantity) && completedQuantity != 0){ BigDecimal chosenPercentage = (new BigDecimal(chosenQuantity)).divide(new BigDecimal(completedQuantity), 2, RoundingMode.HALF_UP); itemCount.setChosenPercentage(chosenPercentage.toString()); } itemCountMap.put(itemCount.getOptionText(), itemCount); } }); List<ServiceSubtaskScriptCount> details = new ArrayList<>(itemCountMap.values()); smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml
@@ -2281,14 +2281,14 @@ <select id="getSfStatisticsScriptDetails" parameterType="com.smartor.domain.ServiceSubtaskCountReq" resultMap="ServiceSubtaskScriptCountResult"> SELECT a.id as scriptid, a.templateid as templateid, a.script_type, MIN(a.id) as scriptid, MIN(a.templateid) as templateid, MIN(a.script_type) as script_type, a.script_content, b.subtask_type, b.completed_quantity, b.all_quantity, ROUND(b.completed_quantity/b.all_quantity,2) as completed_percentage SUM(b.completed_quantity) as completed_quantity, SUM(b.all_quantity) as all_quantity, ROUND(SUM(b.completed_quantity)/SUM(b.all_quantity),2) as completed_percentage FROM <if test="type == 1"> ivr_task_template_script a @@ -2351,25 +2351,37 @@ group by ssd.scriptid) b ON a.id = b.scriptid <!-- 适用单条查询 --> <if test="scriptids != null"> <if test="scriptids != null and scriptids != ''"> AND a.scriptid in (SELECT lib_script.scriptid FROM svy_lib_template_script lib_script WHERE lib_script.scriptid in (${scriptids})) </if> <!-- 同一道题会被复制到多个任务模板,按题目内容合并,保证一道题只返回一条 --> GROUP BY a.script_content, b.subtask_type ORDER BY MIN(a.id) </select> <select id="getSfStatisticsScriptItemDetails" parameterType="com.smartor.domain.ServiceSubtaskCountReq" resultMap="ServiceSubtaskScriptCountResult"> SELECT ssd.scriptid, a.script_content, ss.type as subtask_type, IFNULL(ssd.matchedtext,ssd.asrtext) AS option_text, COUNT(*) AS chosen_quantity FROM service_subtask_detail ssd INNER JOIN service_subtask ss ON ssd.sub_id = ss.id INNER JOIN <if test="type == 1"> ivr_task_template_script a ON a.id = ssd.scriptid </if> <if test="type == 2"> svy_task_template_script a ON a.id = ssd.scriptid </if> where 1=1 and ss.del_flag=0 and ssd.del_flag=0 <if test="orgid != null and orgid != ''"> and ss.orgid = #{orgid} </if> @@ -2408,7 +2420,7 @@ <if test="configValue != null and configValue != ''"> AND ssd.categoryid IN (${configValue}) </if> group by ssd.scriptid, IFNULL(ssd.matchedtext,ssd.asrtext) group by a.script_content, ss.type, IFNULL(ssd.matchedtext,ssd.asrtext) </select> <select id="getDataByTime" resultMap="ServiceSubtaskResult">