liusheng
昨天 09f75e1b4ee21241940ad26b91462ea15c5e4f00
1.短信功能提交
2.优化随访详情页
3.导出两个sheet
已修改8个文件
已添加1个文件
370 ■■■■ 文件已修改
ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/ServiceSubtaskController.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/SmsTempletController.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/domain/ServiceSubtaskDetailRatioExport.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/mapper/ServiceSubtaskMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/service/IServiceSubtaskService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskAnswerServiceImpl.java 138 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/ServiceSubtaskController.java
@@ -224,10 +224,10 @@
    /**
     * å¯¼å‡ºå•一任务(随访宣教)列表
     * å¯¼å‡ºå•一任务列表
     */
    //@PreAuthorize("@ss.hasPermi('system:taskcall:export')")
    @Log(title = "单一任务(随访宣教)", businessType = BusinessType.EXPORT)
    @Log(title = "单一任务", businessType = BusinessType.EXPORT)
    @PostMapping("/patItemExport")
    public void patItemExport(HttpServletResponse response, ServiceSubtaskEntity serviceSubtaskVO) {
        LoginUser loginUser = getLoginUser();
@@ -238,6 +238,7 @@
            serviceSubtaskList = serviceSubtaskService.patItem(serviceSubtaskVO);
        }
        List<ServiceSubtaskExport> serviceSubtaskExports = null;
        List<ServiceSubtaskDetailRatioExport> serviceSubtaskDetailRatioExports = null;
        if (!CollectionUtils.isEmpty(serviceSubtaskList)) {
            serviceSubtaskExports = DtoConversionUtils.sourceToTarget(serviceSubtaskList, ServiceSubtaskExport.class);
            for (ServiceSubtaskExport serviceSubtaskExport : serviceSubtaskExports) {
@@ -255,11 +256,17 @@
                }
            }
        }
        ExcelUtil<ServiceSubtaskExport> util = new ExcelUtil<ServiceSubtaskExport>(ServiceSubtaskExport.class);
        util.exportExcel(response, serviceSubtaskExports, "患者随访信息表单");
    }
            //获取serviceSubtaskList中的所有taskid
            List<Long> taskIds = serviceSubtaskList.stream().map(ServiceSubtaskRes::getTaskid).filter(ObjectUtils::isNotEmpty).distinct().collect(Collectors.toList());
            serviceSubtaskDetailRatioExports = serviceSubtaskService.statQuestionOption(taskIds);
        }
        ExcelUtil<ServiceSubtaskExport> util = new ExcelUtil<ServiceSubtaskExport>(ServiceSubtaskExport.class);
        util.exportExcelTwoSheet(response, serviceSubtaskExports, "患者随访信息表单",
                serviceSubtaskDetailRatioExports, "问题详情占比", ServiceSubtaskDetailRatioExport.class);
    }
    /**
     * æŸ¥è¯¢æ‚£è€…随访信息
ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/SmsTempletController.java
@@ -5,6 +5,8 @@
import javax.servlet.http.HttpServletResponse;
import cn.hutool.core.util.ObjectUtil;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@@ -39,11 +41,16 @@
    //@PreAuthorize("@ss.hasPermi('smartor:smstemplet:list')")
    @PostMapping("/list")
    public Map<String, Object> list(@RequestBody SmsTemplet smsTemplet) {
        if (StringUtils.isEmpty(smsTemplet.getUserName()) && StringUtils.isEmpty(smsTemplet.getWardCode()) && StringUtils.isEmpty(smsTemplet.getDeptCode())) {
            SysUser user = getLoginUser().getUser();
            smsTemplet.setUserName(user.getUserName());
            smsTemplet.setNickName(user.getNickName());
        }
        //这个不需要分页,一个科室也不会有多少条短信模板
        smsTemplet.setPageNum(null);
        smsTemplet.setPageSize(null);
        List<SmsTemplet> list = smsTempletService.selectSmsTempletList(smsTemplet);
        return getDataTable3(ObjectUtil.isNotEmpty(list)?list.size():0, list);
        return getDataTable3(ObjectUtil.isNotEmpty(list) ? list.size() : 0, list);
    }
    /**
@@ -74,6 +81,9 @@
    @Log(title = "短信模板", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    public AjaxResult add(@RequestBody SmsTemplet smsTemplet) {
        SysUser user = getLoginUser().getUser();
        smsTemplet.setUserName(user.getUserName());
        smsTemplet.setNickName(user.getNickName());
        return toAjax(smsTempletService.insertSmsTemplet(smsTemplet));
    }
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
@@ -442,6 +442,102 @@
    }
    /**
     * å¯¼å‡ºåŒ…含两个Sheet的Excel
     * Sheet1: åŸºäºŽå½“前泛型类型T的注解导出
     * Sheet2: åŸºäºŽä¼ å…¥çš„clazz2类型的注解导出
     *
     * @param response   è¿”回数据
     * @param list1      ç¬¬ä¸€ä¸ªSheet的数据集合
     * @param sheetName1 ç¬¬ä¸€ä¸ªSheet的名称
     * @param list2      ç¬¬äºŒä¸ªSheet的数据集合
     * @param sheetName2 ç¬¬äºŒä¸ªSheet的名称
     * @param clazz2     ç¬¬äºŒä¸ªSheet数据对象的Class
     */
    public void exportExcelTwoSheet(HttpServletResponse response,
                                    List<T> list1, String sheetName1,
                                    List<?> list2, String sheetName2, Class<?> clazz2) {
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // åˆå§‹åŒ–并写入Sheet1
        this.init(list1, sheetName1, StringUtils.EMPTY, Type.EXPORT);
        writeSheet();
        // è¿½åР写入Sheet2
        writeAdditionalSheet(list2, sheetName2, clazz2);
        // è¾“出到响应流
        try {
            wb.write(response.getOutputStream());
        } catch (Exception e) {
            log.error("导出Excel异常{}", e.getMessage());
        } finally {
            IOUtils.closeQuietly(wb);
        }
    }
    /**
     * å‘当前工作簿追加写入一个Sheet
     *
     * @param dataList  æ•°æ®é›†åˆ
     * @param sheetName Sheet名称
     * @param dataClazz æ•°æ®å¯¹è±¡çš„Class
     */
    @SuppressWarnings("unchecked")
    public void writeAdditionalSheet(List<?> dataList, String sheetName, Class<?> dataClazz) {
        if (dataList == null) {
            dataList = new ArrayList<>();
        }
        // ä¿å­˜åŽŸå§‹çŠ¶æ€
        Class<T> originClazz = this.clazz;
        List<Object[]> originFields = this.fields;
        List<T> originList = this.list;
        String originSheetName = this.sheetName;
        int originRownum = this.rownum;
        List<Field> originSubFields = this.subFields;
        Method originSubMethod = this.subMethod;
        int originSubMergedFirstRowNum = this.subMergedFirstRowNum;
        int originSubMergedLastRowNum = this.subMergedLastRowNum;
        Map<Integer, Double> originStatistics = this.statistics;
        short originMaxHeight = this.maxHeight;
        // è®¾ç½®æ–°ç±»åž‹
        this.clazz = (Class<T>) dataClazz;
        this.list = (List<T>) dataList;
        this.sheetName = sheetName;
        this.rownum = 0;
        this.subFields = null;
        this.subMethod = null;
        this.subMergedFirstRowNum = 1;
        this.subMergedLastRowNum = 0;
        this.statistics = new HashMap<Integer, Double>();
        // åˆ›å»ºæ–°Sheet
        this.sheet = wb.createSheet();
        wb.setSheetName(wb.getNumberOfSheets() - 1, sheetName);
        // é‡æ–°åˆ›å»ºå­—段
        createExcelField();
        // è¡¥å……新字段的样式
        this.styles.putAll(annotationHeaderStyles(wb, this.styles));
        this.styles.putAll(annotationDataStyles(wb));
        // å†™å…¥æ•°æ®
        writeSheet();
        // æ¢å¤åŽŸå§‹çŠ¶æ€
        this.clazz = originClazz;
        this.fields = originFields;
        this.list = originList;
        this.sheetName = originSheetName;
        this.rownum = originRownum;
        this.subFields = originSubFields;
        this.subMethod = originSubMethod;
        this.subMergedFirstRowNum = originSubMergedFirstRowNum;
        this.subMergedLastRowNum = originSubMergedLastRowNum;
        this.statistics = originStatistics;
        this.maxHeight = originMaxHeight;
    }
    /**
     * å¯¹list数据源将其里面的数据导入到excel表单(带文件名)
     *
     * @param response  è¿”回数据
smartor/src/main/java/com/smartor/domain/ServiceSubtaskDetailRatioExport.java
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
package com.smartor.domain;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.BaseEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.util.Date;
/**
 * é—®é¢˜è¯¦æƒ…占比
 *
 * @author ruoyi
 * @date 2026-06-30
 */
@ApiModel(value = "ServiceSubtaskDetailRatioExport", description = "问题详情占比")
@Data
public class ServiceSubtaskDetailRatioExport extends BaseEntity {
    private static final long serialVersionUID = 1L;
    @Excel(name = "问题内容")
    @ApiModelProperty(value = "问题内容")
    private String questiontext;
    @Excel(name = "选项结果")
    @ApiModelProperty(value = "选项结果")
    private String optionresult;
    @Excel(name = "数量")
    @ApiModelProperty(value = "数量")
    private String count;
    @Excel(name = "比例")
    private String ratio;
    @Excel(name = "任务编号")
    private String taskid;
}
smartor/src/main/java/com/smartor/mapper/ServiceSubtaskMapper.java
@@ -224,4 +224,11 @@
     */
    List<Map<String, Object>> getHeLibraryCount(HeLibraryCountVO heLibraryCountVO);
    /**
     * ç»Ÿè®¡é—®é¢˜çš„选项的百分比
     * @param taskIds
     * @return
     */
    List<ServiceSubtaskDetailRatioExport> statQuestionOption(@Param("taskIds") List<Long> taskIds);
}
smartor/src/main/java/com/smartor/service/IServiceSubtaskService.java
@@ -188,4 +188,11 @@
    public Map<String, Object> getHeLibraryCount(@RequestBody HeLibraryCountVO heLibraryCountVO);
    Map<String, Object> smsSubTask(Long subid);
    /**
     * ç»Ÿè®¡é—®é¢˜çš„选项的百分比
     * @param taskIds
     * @return
     */
    public List<ServiceSubtaskDetailRatioExport> statQuestionOption(List<Long> taskIds);
}
smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskAnswerServiceImpl.java
@@ -348,6 +348,15 @@
                List<SvyTaskTemplateScriptVO> cacheList = serviceSubTaskCacheReq.getSvyTaskTemplateScriptVOS();
                cacheList.sort(Comparator.comparingLong(SvyTaskTemplateScriptVO::getSort));
                log.info("问卷回答结果:{}", cacheList);
                // é¢„查询循环中不变的数据,避免每题重复查数据库
                ServiceSubtaskEntity preSubtaskVO = new ServiceSubtaskEntity();
                preSubtaskVO.setTaskid(tid);
                preSubtaskVO.setPatid(pid);
                preSubtaskVO.setSubId(subid);
                List<ServiceSubtask> preServiceSubtaskList = serviceSubtaskMapper.selectServiceSubtaskList(preSubtaskVO);
                ServiceTask preServiceTask = serviceTaskService.selectServiceTaskByTaskid(tid);
                Map<Long, Long> preDetailIdMap = getExistingDetailIdMap(subid);
                Map<Long, Long> preTraceIdMap = getExistingTraceIdMap(subid);
                for (int i = 0; i < cacheList.size(); i++) {
                    if (i == 0) {
                        //这个时间要找到第一题
@@ -356,7 +365,7 @@
                                //说明是第一题
                                List<SvyTaskTemplateTargetoption> svyTaskTemplateTargetoptions = svyTaskTemplateScriptVO.getSvyTaskTemplateTargetoptions();
                                svyTaskTemplateScriptVO.setSvyTaskTemplateTargetoptions(svyTaskTemplateTargetoptions);
                                Map<String, String> map = setWJInfo(svyTaskTemplateScriptVO, tid, pid, subid);
                                Map<String, String> map = setWJInfo(svyTaskTemplateScriptVO, tid, pid, subid, preServiceSubtaskList, preServiceTask, preDetailIdMap, preTraceIdMap);
                                if (map == null) continue;
                                if (!Objects.isNull(map.get("nextScriptNo")))
                                    nextScriptno = Long.valueOf(map.get("nextScriptNo"));
@@ -376,7 +385,7 @@
                        svyTaskTemplateScriptVO.setSvyTaskTemplateTargetoptions(svyTaskTemplateTargetoptions);
                        if (svyTaskTemplateScriptVO.getSort() != null && svyTaskTemplateScriptVO.getSort().equals(nextScriptno)) {
                            Map<String, String> map = setWJInfo(svyTaskTemplateScriptVO, tid, pid, subid);
                            Map<String, String> map = setWJInfo(svyTaskTemplateScriptVO, tid, pid, subid, preServiceSubtaskList, preServiceTask, preDetailIdMap, preTraceIdMap);
                            log.error("nextScriptNo的信息为:{}", map.get("nextScriptNo"));
                            if (!Objects.isNull(map.get("nextScriptNo")))
                                nextScriptno = Long.valueOf(map.get("nextScriptNo"));
@@ -764,25 +773,29 @@
        if (ObjectUtils.isNotEmpty(scriptInfoByCondition) && ObjectUtils.isNotEmpty(scriptInfoByCondition.get("script"))) {
            if (scriptInfoByCondition.get("type").equals("1")) {
                List<IvrTaskTemplateScriptVO> ivrTaskTemplateScriptVOS = (List<IvrTaskTemplateScriptVO>) scriptInfoByCondition.get("script");
                // æ‰¹é‡æŸ¥è¯¢æ‰€æœ‰æ˜Žç»†ï¼Œé¿å…å¾ªçŽ¯ä¸­é€æ¡æŸ¥æ•°æ®åº“ï¼ˆN+1问题优化)
                Map<Long, ServiceSubtaskDetail> detailMap = getScriptResultMap(subid, patid);
                for (IvrTaskTemplateScriptVO ivrTaskTemplateScriptVO : ivrTaskTemplateScriptVOS) {
                    Map<String, String> scriptResult = getScriptResult(subid, patid, ivrTaskTemplateScriptVO.getId());
                    if (ObjectUtils.isNotEmpty(scriptResult)) {
                        ivrTaskTemplateScriptVO.setScriptResult(scriptResult.get("asrtext"));
                        ivrTaskTemplateScriptVO.setScriptResultId(scriptResult.get("asrtextId"));
                    ServiceSubtaskDetail detail = detailMap.get(ivrTaskTemplateScriptVO.getId());
                    if (detail != null) {
                        ivrTaskTemplateScriptVO.setScriptResult(detail.getAsrtext());
                        ivrTaskTemplateScriptVO.setScriptResultId(String.valueOf(detail.getId()));
                    }
                }
                map.put("scriptResult", ivrTaskTemplateScriptVOS);
                map.put("taskName", scriptInfoByCondition.get("taskName"));
            } else if (scriptInfoByCondition.get("type").equals("2")) {
                List<SvyTaskTemplateScriptVO> svyTaskTemplateScriptVOList = (List) scriptInfoByCondition.get("script");
                // æ‰¹é‡æŸ¥è¯¢æ‰€æœ‰æ˜Žç»†ï¼Œé¿å…å¾ªçŽ¯ä¸­é€æ¡æŸ¥æ•°æ®åº“ï¼ˆN+1问题优化)
                Map<Long, ServiceSubtaskDetail> detailMap = getScriptResultMap(subid, patid);
                for (SvyTaskTemplateScriptVO svyTaskTemplateScriptVO : svyTaskTemplateScriptVOList) {
                    Map<String, String> scriptResult = getScriptResult(subid, patid, svyTaskTemplateScriptVO.getId());
                    if (ObjectUtils.isNotEmpty(scriptResult)) {
                        if (StringUtils.isNotEmpty(scriptResult.get("asrtext")))
                            svyTaskTemplateScriptVO.setScriptResult(StringUtils.isNotEmpty(scriptResult.get("asrtext")) ? scriptResult.get("asrtext").replaceAll("^(\"|')(.*)\\1$", "$2") : "");
                        svyTaskTemplateScriptVO.setScriptResultId(scriptResult.get("asrtextId"));
                        if (StringUtils.isNotEmpty(scriptResult.get("answerps")))
                            svyTaskTemplateScriptVO.setAnswerps(scriptResult.get("answerps"));
                    ServiceSubtaskDetail detail = detailMap.get(svyTaskTemplateScriptVO.getId());
                    if (detail != null) {
                        if (StringUtils.isNotEmpty(detail.getAsrtext()))
                            svyTaskTemplateScriptVO.setScriptResult(detail.getAsrtext().replaceAll("^(\"|')(.*)\\1$", "$2"));
                        svyTaskTemplateScriptVO.setScriptResultId(String.valueOf(detail.getId()));
                        if (StringUtils.isNotEmpty(detail.getAnswerps()))
                            svyTaskTemplateScriptVO.setAnswerps(detail.getAnswerps());
                    }
                }
                map.put("scriptResult", svyTaskTemplateScriptVOList);
@@ -795,6 +808,31 @@
            }
        }
        return map;
    }
    /**
     * æ‰¹é‡æŸ¥è¯¢å­ä»»åŠ¡æ˜Žç»†å¹¶æŒ‰scriptid分组,避免循环中逐条查数据库
     *
     * @param subid å­ä»»åŠ¡ID
     * @param pid   æ‚£è€…ID
     * @return key=scriptid, value=对应的第一条ServiceSubtaskDetail
     */
    private Map<Long, ServiceSubtaskDetail> getScriptResultMap(Long subid, Long pid) {
        ServiceSubtaskDetail query = new ServiceSubtaskDetail();
        query.setSubId(subid);
        query.setPatid(pid);
        List<ServiceSubtaskDetail> details = serviceSubtaskDetailMapper.selectServiceSubtaskDetailList(query);
        if (CollectionUtils.isEmpty(details)) {
            return Collections.emptyMap();
        }
        Map<Long, ServiceSubtaskDetail> result = new HashMap<>();
        for (ServiceSubtaskDetail detail : details) {
            // åŒä¸€ä¸ªscriptid可能有多条记录,只取第一条(与原逻辑一致)
            if (!result.containsKey(detail.getScriptid())) {
                result.put(detail.getScriptid(), detail);
            }
        }
        return result;
    }
@@ -821,6 +859,52 @@
        serviceSubtaskVO.setPatid(patid);
        serviceSubtaskVO.setSubId(subid);
        List<ServiceSubtask> selectServiceSubtaskList = serviceSubtaskMapper.selectServiceSubtaskList(serviceSubtaskVO);
        ServiceTask serviceTask = serviceTaskService.selectServiceTaskByTaskid(taskid);
        Map<Long, Long> existingDetailIdMap = getExistingDetailIdMap(subid);
        Map<Long, Long> existingTraceIdMap = getExistingTraceIdMap(subid);
        return setWJInfo(svyTaskTemplateScriptVO, taskid, patid, subid, selectServiceSubtaskList, serviceTask, existingDetailIdMap, existingTraceIdMap);
    }
    /**
     * æ‰¹é‡æŸ¥è¯¢å·²å­˜åœ¨çš„æ˜Žç»†è®°å½•ID,按scriptid分组(避免循环中逐条查询)
     */
    private Map<Long, Long> getExistingDetailIdMap(Long subid) {
        if (subid == null) return Collections.emptyMap();
        ServiceSubtaskDetail query = new ServiceSubtaskDetail();
        query.setSubId(subid);
        List<ServiceSubtaskDetail> details = serviceSubtaskDetailMapper.selectServiceSubtaskDetailList(query);
        if (CollectionUtils.isEmpty(details)) return Collections.emptyMap();
        Map<Long, Long> map = new HashMap<>();
        for (ServiceSubtaskDetail d : details) {
            if ((d.getDelFlag() == null || "0".equals(d.getDelFlag())) && d.getScriptid() != null && !map.containsKey(d.getScriptid())) {
                map.put(d.getScriptid(), d.getId());
            }
        }
        return map;
    }
    /**
     * æ‰¹é‡æŸ¥è¯¢å¼‚常跟踪记录ID,按scriptid分组(避免循环中逐条查询)
     */
    private Map<Long, Long> getExistingTraceIdMap(Long subid) {
        if (subid == null) return Collections.emptyMap();
        ServiceSubtaskDetailTraceVO query = new ServiceSubtaskDetailTraceVO();
        query.setSubId(subid);
        List<ServiceSubtaskDetailTrace> traces = traceService.selectServiceSubtaskDetailTtraceList(query);
        if (CollectionUtils.isEmpty(traces)) return Collections.emptyMap();
        Map<Long, Long> map = new HashMap<>();
        for (ServiceSubtaskDetailTrace t : traces) {
            if (t.getScriptid() != null && !map.containsKey(t.getScriptid())) {
                map.put(t.getScriptid(), t.getId());
            }
        }
        return map;
    }
    private Map<String, String> setWJInfo(SvyTaskTemplateScriptVO svyTaskTemplateScriptVO, Long taskid, Long patid, Long subid,
                                           List<ServiceSubtask> selectServiceSubtaskList, ServiceTask serviceTask,
                                           Map<Long, Long> existingDetailIdMap, Map<Long, Long> existingTraceIdMap) {
        log.error("-----svyTaskTemplateScriptVO的值为:{}", svyTaskTemplateScriptVO);
        String score = "0";
        //下题跳转
        String nextScriptNo = null;
@@ -860,7 +944,6 @@
                nextScriptNo = getNextScriptNo(svyTaskTemplateScriptVO.getTemplateID(), svyTaskTemplateScriptVO.getScriptContent());
            }
        }
        ServiceTask serviceTask = serviceTaskService.selectServiceTaskByTaskid(taskid);
        serviceSubtaskDetailVO.setQuestiontext(svyTaskTemplateScriptVO.getScriptContent());
        serviceSubtaskDetailVO.setIsMydException(svyTaskTemplateScriptVO.getIsMydException());
        serviceSubtaskDetailVO.setDimension(svyTaskTemplateScriptVO.getDimension());
@@ -884,10 +967,10 @@
        serviceSubtaskDetailVO.setTemplatequestionnum(svyTaskTemplateScriptVO.getId());
        ServiceSubtaskDetail serviceSubtaskDetail = DtoConversionUtils.sourceToTarget(serviceSubtaskDetailVO, ServiceSubtaskDetail.class);
        //先用subid和scriptid查询一下是否存在,如果存在则更新,不存在则插入
        ServiceSubtaskDetailDTO existServiceSubtaskDetail = serviceSubtaskDetailMapper.isExistServiceSubtaskDetail(serviceSubtaskDetailVO.getSubId(), serviceSubtaskDetailVO.getScriptid());
        if (ObjectUtils.isNotEmpty(existServiceSubtaskDetail)) {
            serviceSubtaskDetail.setId(existServiceSubtaskDetail.getId());
        //先用subid和scriptid查询一下是否存在,如果存在则更新,不存在则插入(使用预查询的Map,避免逐条查数据库)
        Long existDetailId = existingDetailIdMap.get(serviceSubtaskDetailVO.getScriptid());
        if (existDetailId != null) {
            serviceSubtaskDetail.setId(existDetailId);
            serviceSubtaskDetail.setUpdateTime(new Date());
            serviceSubtaskDetailMapper.updateServiceSubtaskDetail(serviceSubtaskDetail);
        } else {
@@ -945,23 +1028,16 @@
            subtaskDetailTrace.setUpdateTime(new Date());
            subtaskDetailTrace.setOrgid(selectServiceSubtaskList.get(0).getOrgid());
            ServiceSubtaskDetailTraceVO ssdt = new ServiceSubtaskDetailTraceVO();
            ssdt.setSubId(subtaskDetailTrace.getSubId());
            ssdt.setScriptid(subtaskDetailTrace.getScriptid());
            ssdt.setTemplateType(subtaskDetailTrace.getTemplateType());
            List<ServiceSubtaskDetailTrace> serviceSubtaskDetailTraces = traceService.selectServiceSubtaskDetailTtraceList(ssdt);
            if (CollectionUtils.isNotEmpty(serviceSubtaskDetailTraces)) {
                subtaskDetailTrace.setId(serviceSubtaskDetailTraces.get(0).getId());
            Long existTraceId = existingTraceIdMap.get(subtaskDetailTrace.getScriptid());
            if (existTraceId != null) {
                subtaskDetailTrace.setId(existTraceId);
                traceService.updateServiceSubtaskDetailTtrace(subtaskDetailTrace);
            } else traceService.insertServiceSubtaskDetailTtrace(subtaskDetailTrace);
        } else if (ObjectUtils.isNotEmpty(stt) && stt.getIsabnormal() != 1L) {
            //这里主要是怕医护人员把异常选项改成了非异常的,这里就需要查一下这条数据是不是在满意度异常表,如果在,则要删除
            ServiceSubtaskDetailTraceVO subtaskDetailTraceVO = new ServiceSubtaskDetailTraceVO();
            subtaskDetailTraceVO.setSubId(serviceSubtaskDetailVO.getSubId());
            subtaskDetailTraceVO.setScriptid(svyTaskTemplateScriptVO.getId());
            List<ServiceSubtaskDetailTrace> serviceSubtaskDetailTraces = traceService.selectServiceSubtaskDetailTtraceList(subtaskDetailTraceVO);
            if (CollectionUtils.isNotEmpty(serviceSubtaskDetailTraces)) {
                traceService.deleteServiceSubtaskDetailTtraceById(serviceSubtaskDetailTraces.get(0).getId());
            Long existTraceId = existingTraceIdMap.get(svyTaskTemplateScriptVO.getId());
            if (existTraceId != null) {
                traceService.deleteServiceSubtaskDetailTtraceById(existTraceId);
            }
        }
smartor/src/main/java/com/smartor/service/impl/ServiceSubtaskServiceImpl.java
@@ -28,6 +28,7 @@
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
@@ -4557,6 +4558,11 @@
        return resultMap;
    }
    @Override
    public List<ServiceSubtaskDetailRatioExport> statQuestionOption(List<Long> taskIds) {
        return serviceSubtaskMapper.statQuestionOption(taskIds);
    }
    private Boolean saveServiceSubtaskDetail(ServiceSubtask serviceSubtask) {
        Boolean result = true;
        //3.4 å¦‚æžœ3.1或3.2为true的话,根据type判断什么类型
smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml
@@ -2896,5 +2896,48 @@
        </choose>
    </select>
    <select id="statQuestionOption" resultType="com.smartor.domain.ServiceSubtaskDetailRatioExport">
        SELECT
        d.questiontext AS questiontext,
        t.taskid AS taskid,
        d.asrtext AS optionresult,
        COUNT(*) AS count,
        CONCAT(ROUND(COUNT(*) * 100.0 / t2.total_count, 2), '%') AS ratio
        FROM
        service_task t
        INNER JOIN service_subtask s ON s.taskid = t.taskid
        INNER JOIN service_subtask_detail d ON d.sub_id = s.id
        INNER JOIN (
        SELECT
        t.taskid,
        d.questiontext,
        COUNT(*) AS total_count
        FROM
        service_task t
        INNER JOIN service_subtask s ON s.taskid = t.taskid
        INNER JOIN service_subtask_detail d ON d.sub_id = s.id
        WHERE t.taskid IN
        <foreach collection="taskIds" item="taskId" open="(" separator="," close=")">
            #{taskId}
        </foreach>
        and s.sendstate=6
        GROUP BY
        t.taskid,
        d.questiontext
        ) t2 ON t2.taskid = t.taskid AND t2.questiontext = d.questiontext
        WHERE t.taskid IN
        <foreach collection="taskIds" item="taskId" open="(" separator="," close=")">
            #{taskId}
        </foreach>
        AND s.sendstate = 6
        GROUP BY
        t.taskid,
        d.questiontext,
        d.asrtext
        ORDER BY
        d.questiontext,
        t.taskid
    </select>
</mapper>