liusheng
2026-10-10 33e1839c6214ad72cc5a76ae254ce0bb542e9263
smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml
@@ -571,6 +571,43 @@
            AND date_format(visit_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d')
        </if>
    </select>
    <!--
        满意度统计:只查本次条件下实际存在哪些 type。
        过滤条件与 selectSatisfactionSubtaskList 完全一致,只是:
          1) 只 select distinct type(原来是把上百个字段全查回来);
          2) visit_time 改成可走索引的范围条件(原来对列套 date_format,索引用不上)。
    -->
    <select id="selectSatisfactionSubtaskTypes" parameterType="com.smartor.domain.VO.PatSatisfactionReqVO"
            resultType="java.lang.String">
        select distinct type
        from service_subtask
        where del_flag = 0
        <if test="questionType != null">and type = #{questionType}</if>
        <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0">
            AND leavehospitaldistrictcode IN
            <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="(" separator=","
                     close=")">
                #{hospitaldistrictcode}
            </foreach>
        </if>
        <if test="deptcodes != null and deptcodes.size() > 0">
            AND deptcode IN
            <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")">
                #{deptcode}
            </foreach>
        </if>
        <if test="serviceTypes != null and serviceTypes.size() > 0">
            AND service_type IN
            <foreach collection="serviceTypes" item="serviceType" open="(" separator="," close=")">
                #{serviceType}
            </foreach>
        </if>
        <if test="startTime != null and endTime != null">
            AND visit_time &gt;= #{startTime}
            AND visit_time &lt; date_add(#{endTime}, interval 1 day)
        </if>
    </select>
    <select id="getCompensateServiceSubtaskList" parameterType="com.smartor.domain.entity.ServiceSubtaskEntity"
            resultMap="ServiceSubtaskResult">
        <include refid="selectServiceSubtaskVo"/>
@@ -2896,6 +2933,60 @@
    </select>
    <!--
        满意度柱状图:一次性统计本次请求全部模板的发送量。
        与 querySendCount 的过滤条件完全一致,区别是:
          1) 按 libtemplateid 分组,一次返回所有模板(替代逐个模板查询);
          2) visit_time 改成可走索引的范围条件(原来对列套 date_format,索引用不上)。
    -->
    <select id="selectSatisfactionSendCount" parameterType="com.smartor.domain.entity.SatisfactionStatQuery"
            resultType="java.util.Map">
        select libtemplateid as libtemplateid, count(distinct id) as cnt
        from service_subtask
        where del_flag = 0
        <if test="orgid != null and orgid != ''">
            and orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            and campusid = #{campusid}
        </if>
        <if test="type != null and type != ''">and type = #{type}</if>
        <if test="startTime != null">
            and visit_time &gt;= #{startTime}
        </if>
        <if test="endTime != null">
            and visit_time &lt; date_add(#{endTime}, interval 1 day)
        </if>
        <if test="libTemplateIds != null and libTemplateIds.size() > 0">
            and libtemplateid IN
            <foreach collection="libTemplateIds" item="libTemplateId" open="(" separator="," close=")">
                #{libTemplateId}
            </foreach>
        </if>
        <if test="(hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0) or (deptcodes != null and deptcodes.size() > 0)">
            AND (
            <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0">
                leavehospitaldistrictcode IN
                <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="("
                         separator=","
                         close=")">
                    #{hospitaldistrictcode}
                </foreach>
            </if>
            <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0 and deptcodes != null and deptcodes.size() > 0">
                OR
            </if>
            <if test="deptcodes != null and deptcodes.size() > 0">
                deptcode IN
                <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")">
                    #{deptcode}
                </foreach>
            </if>
            )
        </if>
        group by libtemplateid
    </select>
    <!--
        按病区或科室分组统计 continue_flag 数量
        传了 leavehospitaldistrictcodes → 按病区维度
        传了 deptcodes              → 按科室维度
@@ -3399,14 +3490,15 @@
    <select id="statQuestionOptionBySubtaskIds" resultType="com.smartor.domain.ServiceSubtaskDetailRatioExport">
        SELECT
        d.questiontext AS questiontext,
        t.taskid AS taskid,
        t.task_name AS taskName,
        <!-- 明细已按「题目 + 选项」汇总,任务/科室/病区只是附带信息,必须用聚合函数取值(MySQL ONLY_FULL_GROUP_BY) -->
        MAX(t.taskid) AS taskid,
        MAX(t.task_name) AS taskName,
        d.asrtext AS optionresult,
        d.score AS score,
        s.deptcode AS deptcode,
        s.deptname AS deptname,
        s.leavehospitaldistrictcode AS leavehospitaldistrictcode,
        s.leavehospitaldistrictname AS leavehospitaldistrictname,
        MAX(s.deptcode) AS deptcode,
        MAX(s.deptname) AS deptname,
        MAX(s.leavehospitaldistrictcode) AS leavehospitaldistrictcode,
        MAX(s.leavehospitaldistrictname) AS leavehospitaldistrictname,
        d.targetvalue AS targetvalue,
        d.value_type AS valueType,
        COUNT(*) AS count,
@@ -3424,9 +3516,15 @@
        AND d2.del_flag = '0'
        )
        INNER JOIN (
        <!-- 分母 = 该题各选项项数之和(未作答的空 asrtext 不进分母),这样一道题各选项比例合计才是 100% -->
        SELECT
        x.questiontext AS questiontext,
        SUM(x.option_count) AS total_count
        FROM (
        SELECT
        d.questiontext,
        COUNT(*) AS total_count
        d.asrtext,
        COUNT(*) AS option_count
        FROM
        service_task t
        INNER JOIN service_subtask s ON s.taskid = t.taskid
@@ -3467,7 +3565,11 @@
        <if test="endFinishTime != null">
            AND date_format(s.finishtime,'%y%m%d') &lt;= date_format(#{endFinishTime},'%y%m%d')
        </if>
        GROUP BY d.questiontext
        <!-- 未作答(asrtext 为空)的明细不计入分母 -->
        AND d.asrtext IS NOT NULL AND TRIM(d.asrtext) &lt;&gt; ''
        GROUP BY d.questiontext, d.asrtext
        ) x
        GROUP BY x.questiontext
        ) t2 ON t2.questiontext = d.questiontext
        WHERE 1=1
        <!-- 去重:明细行同一子任务同一题目只保留最新一条,重答不重复计入项数 -->
@@ -3486,6 +3588,8 @@
        </if>
        AND s.sendstate = 6
        AND d.del_flag=0
        <!-- 未作答(asrtext 为空)不算任何选项,明细里直接排除,避免出现空选项行 -->
        AND d.asrtext IS NOT NULL AND TRIM(d.asrtext) &lt;&gt; ''
        <if test="valueType != null">AND d.value_type &gt;= #{valueType}</if>
        <if test="scoreStart != null">AND d.score &gt;= #{scoreStart}</if>
        <if test="scoreEnd != null">AND d.score &lt;= #{scoreEnd}</if>
@@ -3504,21 +3608,17 @@
        <if test="endFinishTime != null">
            AND date_format(s.finishtime,'%y%m%d') &lt;= date_format(#{endFinishTime},'%y%m%d')
        </if>
        <!-- 只按「题目 + 选项」汇总:原来 GROUP BY 带上 taskid/科室/病区,同一个选项被拆成多行、每行数量都是 1,
             前端/导出拿到的「数量」就永远做不了累加 -->
        GROUP BY
        t.taskid,
        d.questiontext,
        d.asrtext,
        d.score,
        d.targetvalue,
        d.asrtext,
        t.task_name,
        s.deptcode,
        s.deptname,
        s.leavehospitaldistrictcode,
        s.leavehospitaldistrictname,
        d.value_type
        ORDER BY
        d.questiontext,
        t.taskid
        MIN(t.taskid)
    </select>
    <select id="statQuestionOptionByKsOrBq" resultType="com.smartor.domain.DTO.QuestionCountKsOrBqDTO"