陈昶聿
19 小时以前 a2dd5b42824eff9626d1f48e1561be85f17f6107
smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml
@@ -23,6 +23,7 @@
        <result property="senduuid" column="senduuid"/>
        <result property="result" column="result"/>
        <result property="finishtime" column="finishtime"/>
        <result property="finishState" column="finish_state"/>
        <result property="recordid" column="recordid"/>
        <result property="exrecallcount" column="exrecallcount"/>
        <result property="pulltime" column="pulltime"/>
@@ -72,6 +73,7 @@
        <result property="leavehospitaldistrictname" column="leavehospitaldistrictname"/>
        <result property="excep" column="excep"/>
        <result property="remark" column="remark"/>
        <result property="doctorOpinion" column="doctor_opinion"/>
        <result property="suggest" column="suggest"/>
        <result property="sendstate" column="sendstate"/>
        <result property="inhospid" column="inhospid"/>
@@ -98,6 +100,7 @@
        <result property="scheduleDetailId" column="schedule_detail_id"/>
        <result property="scheduleSeq" column="schedule_seq"/>
        <result property="loopCount" column="loop_count"/>
        <result property="isManuallyCalled" column="is_manually_called"/>
        <result property="campusid" column="campusid"/>
    </resultMap>
@@ -181,6 +184,7 @@
               long_send_time,
               openid,
               remark,
               doctor_opinion,
               service_type,
               libtemplateid,
               libtemplatename,
@@ -201,6 +205,7 @@
               senduuid,
               result,
               finishtime,
               finish_state,
               recordid,
               exrecallcount,
               pulltime,
@@ -213,7 +218,6 @@
               create_time,
               isupload,
               upload_time,
               orgid,
               pid,
               guid,
               text_param,
@@ -236,8 +240,6 @@
               leaveicd10code,
               orgid,
               visit_type,
               management_doctor,
               management_doctor_code,
               continue_flag,
               continue_time_now,
               continue_content,
@@ -248,8 +250,56 @@
               schedule_detail_id,
               schedule_seq,
               loop_count,
               task_situation
               task_situation,
               is_manually_called
        from service_subtask
    </sql>
    <!-- 超时完成、延期完成逻辑 完成时状态(finish_state)计算:仅当本次更新把 sendstate 置为 6(随访完成)时使用。
         基准截止时间 base = endtime + send_day(缺省1) + (Σ service_subtask_preachform.compensate_time + 1) 天,
         与 RyTask/RedisMqReceiver 的 isSubtaskDeadline 口径保持一致;
         delay = COALESCE(service_task.delay_finish_days, 0);
         finish_time = COALESCE(入参 finishtime, 库中 finishtime, NOW()):
           finish_time <= base                                    -> 1 正常完成
           delay > 0 且 finish_time <= base + delay               -> 2 延期完成
           其余(含 delay 为 0 或 NULL、或已超出延期窗口)          -> 3 超时完成
         finishtime 为空时用 NOW() 兜底,保证完成时一定写入状态;
         仅当 endtime 为空导致无法计算时才保持原值不覆盖。 -->
    <sql id="finishStateExpr">
        CASE
        WHEN service_subtask.endtime IS NULL THEN finish_state
        WHEN COALESCE(#{finishtime,jdbcType=TIMESTAMP}, service_subtask.finishtime, NOW())
        &lt;= DATE_ADD(
        DATE_ADD(
        service_subtask.endtime,
        INTERVAL COALESCE((SELECT st.send_day FROM service_task st
        WHERE st.taskid = service_subtask.taskid AND st.del_flag = '0' LIMIT 1), 1) DAY
        ),
        INTERVAL (COALESCE((SELECT SUM(CAST(COALESCE(NULLIF(TRIM(pf.compensate_time), ''), '0') AS SIGNED))
        FROM service_subtask_preachform pf
        WHERE pf.subid = service_subtask.id AND pf.del_flag = 0), 0) + 1) DAY
        )
        THEN 1
        WHEN COALESCE((SELECT st.delay_finish_days FROM service_task st
        WHERE st.taskid = service_subtask.taskid AND st.del_flag = '0' LIMIT 1), 0) &gt; 0
        AND COALESCE(#{finishtime,jdbcType=TIMESTAMP}, service_subtask.finishtime, NOW())
        &lt;= DATE_ADD(
        DATE_ADD(
        DATE_ADD(
        service_subtask.endtime,
        INTERVAL COALESCE((SELECT st.send_day FROM service_task st
        WHERE st.taskid = service_subtask.taskid AND st.del_flag = '0' LIMIT 1), 1) DAY
        ),
        INTERVAL (COALESCE((SELECT SUM(CAST(COALESCE(NULLIF(TRIM(pf.compensate_time), ''), '0') AS SIGNED))
        FROM service_subtask_preachform pf
        WHERE pf.subid = service_subtask.id AND pf.del_flag = 0), 0) + 1) DAY
        ),
        INTERVAL COALESCE((SELECT st.delay_finish_days FROM service_task st
        WHERE st.taskid = service_subtask.taskid AND st.del_flag = '0' LIMIT 1), 0) DAY
        )
        THEN 2
        ELSE 3
        END
    </sql>
    <select id="selectServiceSubtaskBySendstate" parameterType="com.smartor.domain.entity.ServiceSubtaskEntity"
@@ -257,9 +307,8 @@
        <include refid="selectServiceSubtaskVo"/>
        where 1=1
        and del_flag = 0
        <if test="orgid != null and orgid != ''">
            and orgid = #{orgid}
        </if>
        <if test="orgid != null and orgid != ''">and orgid = #{orgid}</if>
        <if test="campusid != null and campusid != ''">and campusid = #{campusid}</if>
        <if test="taskid != null ">and taskid = #{taskid}</if>
        <if test="continueFlag != null ">and continue_flag = #{continueFlag}</if>
        <if test="continueTimeNow != null ">and continue_time_now = #{continueTimeNow,jdbcType=TIMESTAMP}</if>
@@ -281,16 +330,11 @@
        <include refid="selectServiceSubtaskVo"/>
        where 1=1
        and del_flag = 0
        <if test="orgid != null and orgid != ''">
            and orgid = #{orgid}
        </if>
        <if test="subId != null">
            AND id = #{subId}
        </if>
        <if test="orgid != null and orgid != ''">and orgid = #{orgid}</if>
        <if test="campusid != null and campusid != ''">and campusid = #{campusid}</if>
        <if test="subId != null">and id = #{subId}</if>
        <if test="taskid != null ">and taskid = #{taskid}</if>
        <if test="visitTime != null">
            AND date_format(visit_time,'%y%m%d') &lt;= date_format(#{visitTime},'%y%m%d')
        </if>
        <if test="visitTime != null">and date_format(visit_time,'%y%m%d') &lt;= date_format(#{visitTime},'%y%m%d')</if>
        <if test="sendstate != null ">and sendstate = #{sendstate}</if>
        <if test="continueFlag != null ">and continue_flag = #{continueFlag}</if>
        <if test="continueTimeNow != null ">and continue_time_now = #{continueTimeNow,jdbcType=TIMESTAMP}</if>
@@ -298,6 +342,36 @@
        <if test="continueTimeNext != null ">and continue_time_next = #{continueTimeNext}</if>
    </select>
    <!-- 即将超时过滤:是否即将超时(soonTimeout=1) + 即将超时时间(soonTimeoutHours,单位小时)。
         截止时间口径与 RyTask/RedisMqReceiver 的 isSubtaskDeadline 保持一致:
         service_subtask.endtime + service_task.send_day(缺省1) + (Σ service_subtask_preachform.compensate_time + 1) 天;
         仅当存在有效补偿记录时才计算截止时间(无补偿记录不参与即将超时);
         仅统计“尚未超时、且在 N 小时内将要超时”的数据。 -->
    <sql id="soonTimeoutDeadlineExpr">
        (
        SELECT DATE_ADD(
        DATE_ADD(ss.endtime, INTERVAL COALESCE(st.send_day, 1) DAY),
        INTERVAL (COALESCE(pf.compensate_days, 0) + 1) DAY
        )
        FROM service_subtask ss
        LEFT JOIN service_task st ON st.taskid = ss.taskid AND st.del_flag = '0'
        INNER JOIN (
        SELECT subid,
        SUM(CAST(COALESCE(NULLIF(TRIM(compensate_time), ''), '0') AS SIGNED)) AS compensate_days
        FROM service_subtask_preachform
        WHERE del_flag = 0
        GROUP BY subid
        ) pf ON pf.subid = ss.id
        WHERE ss.id = service_subtask.id
        )
    </sql>
    <sql id="soonTimeoutFilter">
        <if test="soonTimeout != null and soonTimeout == 1">
            AND <include refid="soonTimeoutDeadlineExpr"/> &gt; NOW()
            AND <include refid="soonTimeoutDeadlineExpr"/> &lt;= DATE_ADD(NOW(), INTERVAL COALESCE(#{soonTimeoutHours}, 0) HOUR)
        </if>
    </sql>
    <select id="selectServiceSubtaskList" parameterType="com.smartor.domain.entity.ServiceSubtaskEntity"
            resultMap="ServiceSubtaskResult">
@@ -364,6 +438,12 @@
                #{operationItemIdItem}
            </foreach>
        </if>
        <if test="inhospids != null and inhospids.size() > 0">
            AND inhospid IN
            <foreach collection="inhospids" item="inhospidItem" open="(" separator="," close=")">
                #{inhospidItem}
            </foreach>
        </if>
        <if test="templateid != null  and templateid != ''">and templateid = #{templateid}</if>
        <if test="templatename != null  and templatename != ''">and templatename like concat('%', #{templatename},
            '%')
@@ -407,17 +487,21 @@
            </if>
        </if>
        <if test="deptOrDistrict==2">
            AND (1=1
            <if test="leavehospitaldistrictcodes != null">
                AND leavehospitaldistrictcode IN
            AND (
            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
                leavehospitaldistrictcode IN
                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="("
                         separator=","
                         close=")">
                    #{leavehospitaldistrictcode}
                </foreach>
            </if>
            <if test=" leaveldeptcodes != null">
                OR deptcode IN
            <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0)
                and (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
                OR
            </if>
            <if test=" leaveldeptcodes != null and leaveldeptcodes.size() > 0">
                deptcode IN
                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
                         close=")">
                    #{leaveldeptcode}
@@ -512,10 +596,12 @@
            AND visit_count > 1
        </if>
        <if test="remark != null">and remark = #{remark}</if>
        <if test="doctorOpinion != null and doctorOpinion != ''">and doctor_opinion like concat('%', #{doctorOpinion}, '%')</if>
        <if test="suggest != null">and suggest = #{suggest}</if>
        <if test="createBy != null">and create_by = #{createBy}</if>
        <if test="taskGuid != null">and task_guid = #{taskGuid}</if>
        <if test="isabnormal != null">and isabnormal = #{isabnormal}</if>
        <if test="isManuallyCalled != null">and is_manually_called = #{isManuallyCalled}</if>
        <if test="isVisitAgain != null">and is_visit_again = #{isVisitAgain}</if>
        <if test="visitCount != null and visitCount > 1 and visitDeptCodes != null and visitDeptCodes.size() > 0">
            AND visit_dept_code IN
@@ -525,6 +611,7 @@
                #{visitDeptCode}
            </foreach>
        </if>
        <include refid="soonTimeoutFilter"/>
        <if test="sort != null  and sort==0">order by endtime asc</if>
        <if test="sort != null  and sort==1">order by endtime desc</if>
        <if test="sort != null  and sort==2">order by visit_time asc</if>
@@ -534,7 +621,9 @@
        <if test="sort != null  and sort==7">order by visit_time asc</if>
        <if test="sort != null  and sort==8">order by visit_time desc</if>
        <if test="sort != null  and sort==9">order by sendname asc</if>
        <if test="pageSize != null  and pageNum != null">limit ${pageSize} OFFSET ${pageNum}</if>
        <if test="pageSize != null  and pageNum != null">
            LIMIT ${pageSize} OFFSET ${pageNum}
        </if>
    </select>
    <select id="selectSatisfactionSubtaskList" parameterType="com.smartor.domain.VO.PatSatisfactionReqVO"
@@ -576,15 +665,10 @@
        <include refid="selectServiceSubtaskVo"/>
        where del_flag = 0
        and sendstate != 5
        <if test="orgid != null and orgid != ''">
            and orgid = #{orgid}
        </if>
        <if test="visitTime != null">
            AND date_format(visit_time,'%y%m%d') &lt;= date_format(#{visitTime},'%y%m%d')
        </if>
        <if test="subId != null">
            AND id = #{subId}
        </if>
        <if test="orgid != null and orgid != ''">and orgid = #{orgid}</if>
        <if test="campusid != null and campusid != ''">and campusid = #{campusid}</if>
        <if test="visitTime != null">and date_format(visit_time,'%y%m%d') &lt;= date_format(#{visitTime},'%y%m%d') </if>
        <if test="subId != null">and id = #{subId} </if>
        <if test="sendstate != null ">and sendstate = #{sendstate}</if>
        <if test="continueFlag != null ">and continue_flag = #{continueFlag}</if>
        <if test="continueTimeNow != null ">and continue_time_now = #{continueTimeNow,jdbcType=TIMESTAMP}</if>
@@ -594,9 +678,8 @@
        <include refid="selectServiceSubtaskVo"/>
        where del_flag = 0
        and sendstate = 5
        <if test="orgid != null and orgid != ''">
            and orgid = #{orgid}
        </if>
        <if test="orgid != null and orgid != ''">and orgid = #{orgid}</if>
        <if test="campusid != null and campusid != ''">and campusid = #{campusid}</if>
        <if test="visitTime != null">
            AND date_format(visit_time,'%y%m%d') &lt;= date_format(DATE_ADD(#{visitTime}, INTERVAL 1 DAY),'%y%m%d')
        </if>
@@ -614,9 +697,8 @@
            resultMap="ServiceSubtaskResult">
        <include refid="selectServiceSubtaskVo"/>
        where del_flag = 0
        <if test="orgid != null and orgid != ''">
            and orgid = #{orgid}
        </if>
        <if test="orgid != null and orgid != ''">and orgid = #{orgid}</if>
        <if test="campusid != null and campusid != ''">and campusid = #{campusid}</if>
        <if test="createStartTime != null  and createEndTime != null">and create_time BETWEEN #{createStartTime} AND
            #{createEndTime}
        </if>
@@ -663,7 +745,8 @@
        <if test="labelstatus != null ">and labelstatus = #{labelstatus}</if>
        <if test="isupload != null ">and isupload = #{isupload}</if>
        <if test="uploadTime != null ">and upload_time = #{uploadTime}</if>
        <if test="orgid != null  and orgid != ''">and orgid = #{orgid}</if>
        <if test="orgid != null and orgid != ''">and orgid = #{orgid}</if>
        <if test="campusid != null and campusid != ''">and campusid = #{campusid}</if>
        <if test="pid != null ">and pid = #{pid}</if>
        <if test="preachform != null ">and preachform = #{preachform}</if>
        <if test="guid != null  and guid != ''">and guid = #{guid}</if>
@@ -698,6 +781,7 @@
        <if test="continueTimeNow != null ">and continue_time_now = #{continueTimeNow,jdbcType=TIMESTAMP}</if>
        <if test="continueCount != null ">and continue_count = #{continueCount}</if>
        <if test="continueTimeNext != null ">and continue_time_next = #{continueTimeNext}</if>
        <include refid="soonTimeoutFilter"/>
    </select>
    <select id="selectSendstateByCondition" parameterType="com.smartor.domain.ServiceSubtask" resultType="Integer">
@@ -711,9 +795,8 @@
            DATE_FORMAT(b.create_time, '%Y-%m-%d') LIKE CONCAT(#{createTimeNew}, '%')
        </if>
        <if test="sendstate != null ">and b.sendstate = #{sendstate}</if>
        <if test="orgid != null and orgid != ''">
            and b.orgid = #{orgid}
        </if>
        <if test="orgid != null and orgid != ''">and b.orgid = #{orgid}</if>
        <if test="campusid != null and campusid != ''">and b.campusid = #{campusid}</if>
    </select>
    <select id="selectTimelyRate" parameterType="com.smartor.domain.ServiceSubtask" resultType="double">
@@ -730,7 +813,8 @@
            AND date_format(visit_time,'%y%m%d') >= date_format(#{starttime},'%y%m%d')
            AND date_format(visit_time,'%y%m%d') &lt;= date_format(#{endtime},'%y%m%d')
        </if>
        <if test="orgid != null  and orgid != ''">and orgid = #{orgid}</if>
        <if test="orgid != null and orgid != ''">and orgid = #{orgid}</if>
        <if test="campusid != null and campusid != ''">and campusid = #{campusid}</if>
        <if test="serviceType != null and serviceType != ''">and service_type = #{serviceType}</if>
        <if test="serviceTypes != null and serviceTypes != ''">and service_type IN (#{serviceTypes})</if>
        <if test="deptcode != null  and deptcode != ''">and deptcode = #{deptcode}</if>
@@ -744,6 +828,12 @@
        </if>
        <if test="managementDoctorCode != null">and management_doctor_code = #{managementDoctorCode}</if>
        <if test="managementDoctor != null">and management_doctor like concat('%',#{managementDoctor}, '%')</if>
        <if test="startOutHospTime != null">
            AND date_format(endtime,'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
        </if>
        <if test="endOutHospTime != null">
            AND date_format(endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
        </if>
        ) a
    </select>
@@ -776,6 +866,7 @@
        </if>
        WHERE ss.del_flag = 0
        AND ss.visit_time IS NOT NULL
        AND ss.sendstate != 4
        <if test="starttime == null and endtime==null">
            AND DATE(ss.visit_time) &lt; DATE(NOW())
        </if>
@@ -784,6 +875,7 @@
            AND ss.visit_time &lt; DATE_ADD(#{endtime}, INTERVAL 1 DAY)
        </if>
        <if test="orgid != null and orgid != ''">AND ss.orgid = #{orgid}</if>
        <if test="campusid != null and campusid != ''">and ss.campusid = #{campusid}</if>
        <if test="deptcode != null  and deptcode != ''">and ss.deptcode = #{deptcode}</if>
        <if test="deptname != null  and deptname != ''">and ss.deptname = #{deptname}</if>
        <if test="isabnormal != null">and ss.isabnormal = #{isabnormal}</if>
@@ -807,6 +899,12 @@
                     close=")">
                #{serviceType}
            </foreach>
        </if>
        <if test="startOutHospTime != null">
            AND date_format(ss.endtime,'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
        </if>
        <if test="endOutHospTime != null">
            AND date_format(ss.endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
        </if>
        <if test="groupKey != null and groupKey != ''">
            AND ss.${groupKey} IN
@@ -837,6 +935,7 @@
            AND date_format(visit_time,'%y%m%d') &lt;= date_format(#{endtime},'%y%m%d')
        </if>
        <if test="orgid != null  and orgid != ''">and orgid = #{orgid}</if>
        <if test="campusid != null and campusid != ''">and campusid = #{campusid}</if>
        <if test="serviceType != null and serviceType != ''">and service_type = #{serviceType}</if>
        <if test="serviceTypes != null and serviceTypes != ''">and service_type IN (#{serviceTypes})</if>
        <if test="isabnormal != null ">and isabnormal = #{isabnormal}</if>
@@ -867,7 +966,8 @@
        <if test="sendname != null">and sendname like concat('%',#{sendname}, '%')</if>
        <if test="taskName != null">and task_name like concat('%',#{taskName}, '%')</if>
        <if test="sendstate != null">and sendstate = #{sendstate}</if>
        <if test="orgid != null">and orgid =#{orgid}</if>
        <if test="orgid != null and orgid != ''">and orgid = #{orgid} </if>
        <if test="campusid != null and campusid != ''">and campusid = #{campusid}</if>
        <if test="continueFlag != null ">and continue_flag = #{continueFlag}</if>
        <if test="continueTimeNow != null ">and continue_time_now = #{continueTimeNow,jdbcType=TIMESTAMP}</if>
        <if test="continueCount != null ">and continue_count = #{continueCount}</if>
@@ -902,6 +1002,7 @@
            <if test="senduuid != null">senduuid,</if>
            <if test="result != null">result,</if>
            <if test="finishtime != null">finishtime,</if>
            <if test="finishState != null">finish_state,</if>
            <if test="recordid != null">recordid,</if>
            <if test="exrecallcount != null">exrecallcount,</if>
            <if test="pulltime != null">pulltime,</if>
@@ -913,7 +1014,8 @@
            <if test="createTime != null">create_time,</if>
            <if test="isupload != null">isupload,</if>
            <if test="uploadTime != null">upload_time,</if>
            <if test="orgid != null">orgid,</if>
            <if test="orgid != null and orgid != ''">orgid,</if>
            <if test="campusid != null and campusid != ''">campusid,</if>
            <if test="pid != null">pid,</if>
            <if test="guid != null">guid,</if>
            <if test="textParam != null">text_param,</if>
@@ -954,6 +1056,7 @@
            <if test="nurseName != null ">nurse_name,</if>
            <if test="nurseId != null ">nurse_id,</if>
            <if test="remark != null ">remark,</if>
            <if test="doctorOpinion != null ">doctor_opinion,</if>
            <if test="suggest != null ">suggest,</if>
            <if test="sendstate != null ">sendstate,</if>
            <if test="inhospid != null ">inhospid,</if>
@@ -977,11 +1080,11 @@
            <if test="continueTimeNext != null ">continue_time_next,</if>
            <if test="continueContent != null ">continue_content,</if>
            <if test="operationItemId != null ">operation_item_id,</if>
            <if test="campusid != null">campusid,</if>
            <if test="scheduleId != null ">schedule_id,</if>
            <if test="scheduleDetailId != null ">schedule_detail_id,</if>
            <if test="scheduleSeq != null ">schedule_seq,</if>
            <if test="loopCount != null ">loop_count,</if>
            <if test="isManuallyCalled != null ">is_manually_called,</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="sendname != null">#{sendname},</if>
@@ -999,6 +1102,7 @@
            <if test="senduuid != null">#{senduuid},</if>
            <if test="result != null">#{result},</if>
            <if test="finishtime != null">#{finishtime},</if>
            <if test="finishState != null">#{finishState},</if>
            <if test="recordid != null">#{recordid},</if>
            <if test="exrecallcount != null">#{exrecallcount},</if>
            <if test="pulltime != null">#{pulltime},</if>
@@ -1010,7 +1114,8 @@
            <if test="createTime != null">#{createTime},</if>
            <if test="isupload != null">#{isupload},</if>
            <if test="uploadTime != null">#{uploadTime},</if>
            <if test="orgid != null">#{orgid},</if>
            <if test="orgid != null and orgid != ''">#{orgid},</if>
            <if test="campusid != null and campusid != ''">#{campusid},</if>
            <if test="pid != null">#{pid},</if>
            <if test="guid != null">#{guid},</if>
            <if test="textParam != null">#{textParam},</if>
@@ -1051,6 +1156,7 @@
            <if test="nurseName != null ">#{nurseName},</if>
            <if test="nurseId != null ">#{nurseId},</if>
            <if test="remark != null ">#{remark},</if>
            <if test="doctorOpinion != null ">#{doctorOpinion},</if>
            <if test="suggest != null ">#{suggest},</if>
            <if test="sendstate != null ">#{sendstate},</if>
            <if test="inhospid != null ">#{inhospid},</if>
@@ -1074,13 +1180,22 @@
            <if test="continueTimeNext != null ">#{continueTimeNext,jdbcType=TIMESTAMP},</if>
            <if test="continueContent != null ">#{continueContent},</if>
            <if test="operationItemId != null ">#{operationItemId},</if>
            <if test="campusid != null">#{campusid},</if>
            <if test="scheduleId != null ">#{scheduleId},</if>
            <if test="scheduleDetailId != null ">#{scheduleDetailId},</if>
            <if test="scheduleSeq != null ">#{scheduleSeq},</if>
            <if test="loopCount != null ">#{loopCount},</if>
            <if test="isManuallyCalled != null ">#{isManuallyCalled},</if>
        </trim>
    </insert>
    <!-- 二次随访幂等:仅当 is_visit_again 不是目标值时更新,返回受影响行数 -->
    <update id="updateIsVisitAgainById">
        update service_subtask
        set is_visit_again = #{isVisitAgain},
            update_time = now()
        where id = #{id}
          and (is_visit_again is null or is_visit_again &lt;&gt; #{isVisitAgain})
    </update>
    <update id="updateServiceSubtask" parameterType="com.smartor.domain.ServiceSubtask">
        update service_subtask
@@ -1112,7 +1227,8 @@
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="isupload != null">isupload = #{isupload},</if>
            <if test="uploadTime != null">upload_time = #{uploadTime},</if>
            <if test="orgid != null">orgid = #{orgid},</if>
            <if test="orgid != null and orgid != ''">orgid = #{orgid},</if>
            <if test="campusid != null and campusid != ''">campusid = #{campusid},</if>
            <if test="pid != null">pid = #{pid},</if>
            <if test="guid != null">guid = #{guid},</if>
            <if test="textParam != null">text_param = #{textParam},</if>
@@ -1137,6 +1253,7 @@
            <if test="openid != null ">openid = #{openid},</if>
            <if test="longSendTime != null ">long_send_time = #{longSendTime},</if>
            <if test="sendstate != null ">sendstate = #{sendstate},</if>
            <if test="sendstate != null and sendstate == 6">finish_state = <include refid="finishStateExpr"/>,</if>
            <if test="serviceType != null ">service_type = #{serviceType},</if>
            <if test="score != null ">score = #{score},</if>
            <if test="submit != null ">submit = #{submit},</if>
@@ -1154,6 +1271,7 @@
            <if test="nurseName != null ">nurse_name=#{nurseName},</if>
            <if test="nurseId != null ">nurse_id=#{nurseId},</if>
            <if test="remark != null ">remark=#{remark},</if>
            <if test="doctorOpinion != null ">doctor_opinion=#{doctorOpinion},</if>
            <if test="suggest != null ">suggest=#{suggest},</if>
            <if test="inhospid != null ">inhospid=#{inhospid},</if>
            <if test="patfrom != null ">patfrom=#{patfrom},</if>
@@ -1176,11 +1294,11 @@
            <if test="continueTimeNext != null ">continue_time_next = #{continueTimeNext,jdbcType=TIMESTAMP},</if>
            <if test="continueContent != null ">continue_content = #{continueContent},</if>
            <if test="operationItemId != null ">operation_item_id = #{operationItemId},</if>
            <if test="campusid != null">campusid=#{campusid},</if>
            <if test="scheduleId != null ">schedule_id = #{scheduleId},</if>
            <if test="scheduleDetailId != null ">schedule_detail_id = #{scheduleDetailId},</if>
            <if test="scheduleSeq != null ">schedule_seq = #{scheduleSeq},</if>
            <if test="loopCount != null ">loop_count = #{loopCount},</if>
            <if test="isManuallyCalled != null ">is_manually_called = #{isManuallyCalled},</if>
        </trim>
        where id = #{id}
    </update>
@@ -1215,7 +1333,8 @@
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="isupload != null">isupload = #{isupload},</if>
            <if test="uploadTime != null">upload_time = #{uploadTime},</if>
            <if test="orgid != null">orgid = #{orgid},</if>
            <if test="orgid != null and orgid != ''">orgid = #{orgid},</if>
            <if test="campusid != null and campusid != ''">campusid = #{campusid},</if>
            <if test="pid != null">pid = #{pid},</if>
            <if test="guid != null">guid = #{guid},</if>
            <if test="textParam != null">text_param = #{textParam},</if>
@@ -1240,6 +1359,7 @@
            <if test="openid != null ">openid = #{openid},</if>
            <if test="longSendTime != null ">long_send_time = #{longSendTime},</if>
            <if test="sendstate != null ">sendstate = #{sendstate},</if>
            <if test="sendstate != null and sendstate == 6">finish_state = <include refid="finishStateExpr"/>,</if>
            <if test="serviceType != null ">service_type = #{serviceType},</if>
            <if test="score != null ">score = #{score},</if>
            <if test="visitCount != null ">visit_count = #{visitCount},</if>
@@ -1258,6 +1378,7 @@
            <if test="nurseName != null ">nurse_name=#{nurseName},</if>
            <if test="nurseId != null ">nurse_id=#{nurseId},</if>
            <if test="remark != null ">remark=#{remark},</if>
            <if test="doctorOpinion != null ">doctor_opinion=#{doctorOpinion},</if>
            <if test="suggest != null ">suggest=#{suggest},</if>
            <if test="inhospid != null ">inhospid=#{inhospid},</if>
            <if test="patfrom != null ">patfrom=#{patfrom},</if>
@@ -1278,13 +1399,13 @@
            <if test="continueCount != null ">continue_count = #{continueCount},</if>
            <if test="continueTimeNext != null ">continue_time_next = #{continueTimeNext,jdbcType=TIMESTAMP},</if>
            <if test="continueContent != null ">continue_content = #{continueContent},</if>
            <if test="isManuallyCalled != null ">is_manually_called = #{isManuallyCalled},</if>
        </trim>
        where 1=1
        <if test="patid != null ">and patid = #{patid}</if>
        <if test="taskid != null ">and taskid = #{taskid}</if>
        <if test="orgid != null and orgid != ''">
            and orgid = #{orgid}
        </if>
        <if test="orgid != null and orgid != ''">and orgid = #{orgid}</if>
        <if test="campusid != null and campusid != ''">and campusid = #{campusid}</if>
    </update>
    <update id="updateServiceSubtaskByCondition" parameterType="com.smartor.domain.ServiceSubtask">
@@ -1295,6 +1416,7 @@
            <if test="sex != null">sex = #{sex},</if>
            <if test="delFlag != null">del_flag = #{delFlag},</if>
            <if test="sendstate != null ">sendstate = #{sendstate},</if>
            <if test="sendstate != null and sendstate == 6">finish_state = <include refid="finishStateExpr"/>,</if>
            <if test="age != null">age = #{age},</if>
            <if test="sfzh != null">sfzh = #{sfzh},</if>
            <if test="addr != null">addr = #{addr},</if>
@@ -1318,7 +1440,8 @@
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="isupload != null">isupload = #{isupload},</if>
            <if test="uploadTime != null">upload_time = #{uploadTime},</if>
            <if test="orgid != null">orgid = #{orgid},</if>
            <if test="orgid != null and orgid != ''">orgid = #{orgid},</if>
            <if test="campusid != null and campusid != ''">campusid = #{campusid},</if>
            <if test="pid != null">pid = #{pid},</if>
            <if test="guid != null">guid = #{guid},</if>
            <if test="visitCount != null">visit_count = #{visitCount},</if>
@@ -1361,6 +1484,7 @@
            <if test="nurseName != null ">nurse_name=#{nurseName},</if>
            <if test="nurseId != null ">nurse_id=#{nurseId},</if>
            <if test="remark != null ">remark=#{remark},</if>
            <if test="doctorOpinion != null ">doctor_opinion=#{doctorOpinion},</if>
            <if test="suggest != null ">suggest=#{suggest},</if>
            <if test="inhospid != null ">inhospid=#{inhospid},</if>
            <if test="patfrom != null ">patfrom=#{patfrom},</if>
@@ -1380,6 +1504,7 @@
            <if test="continueCount != null ">continue_count = #{continueCount},</if>
            <if test="continueTimeNext != null ">continue_time_next = #{continueTimeNext,jdbcType=TIMESTAMP},</if>
            <if test="continueContent != null ">continue_content = #{continueContent},</if>
            <if test="isManuallyCalled != null ">is_manually_called = #{isManuallyCalled},</if>
        </trim>
        <where>
            <if test="patid != null ">
@@ -1391,6 +1516,9 @@
            <if test="id != null ">
                and id = #{id}
            </if>
            <if test="inhospid != null ">
                and inhospid = #{inhospid}
            </if>
        </where>
    </update>
@@ -1401,6 +1529,7 @@
            <if test="phone != null">phone = #{phone},</if>
            <if test="sex != null">sex = #{sex},</if>
            <if test="sendstate != null ">sendstate = #{sendstate},</if>
            <if test="sendstate != null and sendstate == 6">finish_state = <include refid="finishStateExpr"/>,</if>
            <if test="age != null">age = #{age},</if>
            <if test="sfzh != null">sfzh = #{sfzh},</if>
            <if test="addr != null">addr = #{addr},</if>
@@ -1424,7 +1553,8 @@
            <if test="createTime != null">create_time = #{createTime},</if>
            <if test="isupload != null">isupload = #{isupload},</if>
            <if test="uploadTime != null">upload_time = #{uploadTime},</if>
            <if test="orgid != null">orgid = #{orgid},</if>
            <if test="orgid != null and orgid != ''">orgid = #{orgid},</if>
            <if test="campusid != null and campusid != ''">campusid = #{campusid},</if>
            <if test="pid != null">pid = #{pid},</if>
            <if test="guid != null">guid = #{guid},</if>
            <if test="textParam != null">text_param = #{textParam},</if>
@@ -1467,6 +1597,7 @@
            <if test="nurseName != null ">nurse_name=#{nurseName},</if>
            <if test="nurseId != null ">nurse_id=#{nurseId},</if>
            <if test="remark != null ">remark=#{remark},</if>
            <if test="doctorOpinion != null ">doctor_opinion=#{doctorOpinion},</if>
            <if test="suggest != null ">suggest=#{suggest},</if>
            <if test="inhospid != null ">inhospid=#{inhospid},</if>
            <if test="patfrom != null ">patfrom=#{patfrom},</if>
@@ -1486,6 +1617,7 @@
            <if test="continueCount != null ">continue_count = #{continueCount},</if>
            <if test="continueTimeNext != null ">continue_time_next = #{continueTimeNext,jdbcType=TIMESTAMP},</if>
            <if test="continueContent != null ">continue_content = #{continueContent},</if>
            <if test="isManuallyCalled != null ">is_manually_called = #{isManuallyCalled},</if>
        </trim>
        where task_guid = #{taskGuid} and task_name = #{taskName}
    </update>
@@ -1548,12 +1680,17 @@
        continue_content,
        continue_count,
        continue_time_next,
        task_situation
        task_situation,
        finish_state,
        is_manually_called
        from service_subtask
        where 1=1
        and 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="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
            AND leavehospitaldistrictcode IN
@@ -1643,12 +1780,9 @@
        and a.del_flag = '0'
        and b.del_flag = '0'
        and a.appltype = '3'
        <if test="orgid != null and orgid != ''">
            and a.orgid = #{orgid}
        </if>
        <if test="taskId != null">
            and a.task_id = #{taskId}
        </if>
        <if test="orgid != null and orgid != ''">and a.orgid = #{orgid}</if>
        <if test="campusid != null and campusid != ''">and b.campusid = #{campusid}</if>
        <if test="taskId != null">and a.task_id = #{taskId}</if>
        <if test="taskName != null and taskName != ''">
            and a.task_name like concat('%', #{taskName}, '%')
        </if>
@@ -1737,6 +1871,9 @@
        and 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="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
            AND leavehospitaldistrictcode IN
@@ -1832,12 +1969,18 @@
        continue_count,
        continue_time_next,
        task_situation,
        remark
        remark,
        doctor_opinion,
        finish_state,
        is_manually_called
        from service_subtask
        where 1=1
        and 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="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
            AND leavehospitaldistrictcode IN
@@ -1863,6 +2006,10 @@
        <if test="startTime != null and endTime!=null">
            AND visit_time >= DATE(#{startTime})
            AND visit_time &lt; DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY)
        </if>
        <if test="hospitalStartTime != null and hospitalEndTime!=null">
            AND endtime >= DATE(#{hospitalStartTime})
            AND endtime &lt; DATE_ADD(DATE(#{hospitalEndTime}), INTERVAL 1 DAY)
        </if>
        <if test="visitDeptCode != null">and visit_dept_code = #{visitDeptCode}</if>
        <if test="visitDeptName != null">and visit_dept_name = #{visitDeptName}</if>
@@ -1907,6 +2054,9 @@
        <if test="taskSituation != null">
            AND task_situation = #{taskSituation}
        </if>
        <if test="finishState != null">
            AND finish_state = #{finishState}
        </if>
        <if test="drcode != null and drcode != ''">
            AND drcode = #{drcode}
        </if>
@@ -1915,6 +2065,9 @@
        </if>
        <if test="deptcode != null and deptcode != ''">
            AND deptcode = #{deptcode}
        </if>
        <if test="isManuallyCalled != null">
            AND is_manually_called = #{isManuallyCalled}
        </if>
        order by endtime desc
        <if test="pageSize != null  and pageNum != null">
@@ -1933,6 +2086,9 @@
        and 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="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
            AND leavehospitaldistrictcode IN
@@ -1978,6 +2134,9 @@
        <if test="orgid != null and orgid != ''">
            and orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            and campusid = #{campusid}
        </if>
        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
            AND leavehospitaldistrictcode IN
            <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator=","
@@ -2009,6 +2168,9 @@
        and 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="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">AND
            leavehospitaldistrictcode IN
@@ -2065,6 +2227,9 @@
        <if test="orgid != null and orgid != ''">
            and t.orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            and t.campusid = #{campusid}
        </if>
        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
            AND t.leavehospitaldistrictcode IN
            <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator=","
@@ -2116,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
@@ -2147,6 +2312,9 @@
        AND ssd.del_flag = 0
        <if test="orgid != null and orgid != ''">
            AND ss.orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            AND ss.campusid = #{campusid}
        </if>
        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
            AND ss.leavehospitaldistrictcode IN
@@ -2183,27 +2351,42 @@
        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>
        <if test="campusid != null and campusid != ''">
            and ss.campusid = #{campusid}
        </if>
        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
            AND ss.leavehospitaldistrictcode IN
@@ -2237,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">
@@ -2308,6 +2491,7 @@
               nurse_id,
               nurse_name,
               remark,
               doctor_opinion,
               inhospid,
               patfrom,
               task_guid,
@@ -2362,8 +2546,11 @@
        AND DATE_FORMAT(visit_time, '%Y-%m-%d') &lt;= #{endDate}
        AND service_type IN (2, 13)
        AND del_flag = '0'
        <if test="orgid != null">
        <if test="orgid != null and orgid != ''">
            AND orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            AND campusid = #{campusid}
        </if>
        GROUP BY deptname
    </select>
@@ -2409,10 +2596,12 @@
            AND visit_time &lt;= DATE_ADD(#{endDate}, INTERVAL 1 DAY)
        </if>
        <if test="orgid != null">
        <if test="orgid != null and orgid != ''">
            AND orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            AND campusid = #{campusid}
        </if>
        <if test="deptcodes != null and deptcodes.size() > 0">
            AND deptcode IN
            <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")">
@@ -2466,10 +2655,12 @@
            AND endtime &lt;= DATE_ADD(#{endDate}, INTERVAL 1 DAY)
        </if>
        AND inhospstate=1
        <if test="orgid != null">
        <if test="orgid != null and orgid != ''">
            AND orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            AND campusid = #{campusid}
        </if>
        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
            AND leavehospitaldistrictcode IN
            <foreach collection="leavehospitaldistrictcodes" item="districtcode" open="(" separator="," close=")">
@@ -2516,9 +2707,11 @@
        <!--            AND admitdate &lt;= DATE_ADD(#{endDate}, INTERVAL 1 DAY)-->
        <!--        </if>-->
        <!--        <if test="orgid != null">-->
        <!--            AND orgid = #{orgid}-->
        <!--             AND orgid = #{orgid}-->
        <!--        </if>-->
        <!--        <if test="campusid != null">-->
        <!--             AND campusid = #{campusid}-->
        <!--        </if>-->
        <!--        <if test="deptcodes != null and deptcodes.size() > 0">-->
        <!--            AND deptcode IN-->
        <!--            <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")">-->
@@ -2543,7 +2736,10 @@
        SUM(CASE WHEN sendstate != 4 THEN 1 ELSE 0 END) AS xsf,
        SUM(CASE WHEN (sendstate = 1 OR sendstate = 2 OR sendstate = 3 OR sendstate = 5 OR sendstate = 7 ) THEN 1 ELSE 0
        END) AS dsf,
        SUM(CASE WHEN sendstate != 2 THEN 1 ELSE 0 END) AS yfs,
        SUM(CASE WHEN sendstate = 2 THEN 1 ELSE 0 END) AS wfs,
        SUM(CASE WHEN sendstate = 6 THEN 1 ELSE 0 END) AS ywc,
        SUM(CASE WHEN sendstate = 7 THEN 1 ELSE 0 END) AS cs,
        SUM(CASE WHEN excep IS NOT NULL AND excep = '1' THEN 1 ELSE 0 END) AS yc,
        SUM(CASE WHEN excep IS NOT NULL AND excep = '2' THEN 1 ELSE 0 END) AS jg,
        COUNT(1) as total
@@ -2555,6 +2751,12 @@
        </if>
        <if test="phone != null and phone != ''">
            AND phone = #{phone}
        </if>
        <if test="finishtimeStart != null">
            AND date_format(finishtime,'%y%m%d') &gt;= date_format(#{finishtimeStart},'%y%m%d')
        </if>
        <if test="finishtimeEnd != null">
            AND date_format(finishtime,'%y%m%d') &lt;= date_format(#{finishtimeEnd},'%y%m%d')
        </if>
        <if test="deptOrDistrict==1">
            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
@@ -2574,17 +2776,21 @@
            </if>
        </if>
        <if test="deptOrDistrict==2">
            AND (1=1
            AND (
            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
                AND leavehospitaldistrictcode IN
                leavehospitaldistrictcode IN
                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="("
                         separator=","
                         close=")">
                    #{leavehospitaldistrictcode}
                </foreach>
            </if>
            <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0)
                and (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
                OR
            </if>
            <if test=" leaveldeptcodes != null and leaveldeptcodes.size()>0">
                OR deptcode IN
                deptcode IN
                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
                         close=")">
                    #{leaveldeptcode}
@@ -2742,8 +2948,11 @@
        where 1=1
        and del_flag = 0
        and service_type=3
        <if test="orgid != null">
            and orgid = #{orgid}
        <if test="orgid != null and orgid != ''">
            AND orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            AND campusid = #{campusid}
        </if>
        <if test="startDate != null">
            AND date_format( visit_time, '%y%m%d' ) &gt;= date_format( #{startDate}, '%y%m%d' )
@@ -2767,29 +2976,73 @@
        COUNT(CASE WHEN sendstate = 5 THEN 1 END) AS failedVisitCount,
        SUM(CASE WHEN excep IS NOT NULL AND excep = '1' THEN 1 ELSE 0 END) AS abnormalVisitCount,
        SUM(CASE WHEN excep IS NOT NULL AND excep = '2' THEN 1 ELSE 0 END) AS warnningVisitCount,
        COUNT(*) AS allVisitCount
        FROM service_subtask
        WHERE del_flag = '0'
        AND service_type = '2'
        AND visit_count = 1
        COUNT(*) AS allVisitCount,
        <choose>
            <when test="soonTimeoutHours != null and soonTimeoutHours > 0">
                COUNT(CASE WHEN t.soon_deadline &gt; NOW()
                AND t.soon_deadline &lt;= DATE_ADD(NOW(), INTERVAL #{soonTimeoutHours} HOUR)
                THEN 1 END) AS soonTimeoutCount
            </when>
            <otherwise>
                0 AS soonTimeoutCount
            </otherwise>
        </choose>
        FROM (
        SELECT ss.*,
        <!-- 即将超时截止时间 = 出院时间(endtime) + 发送日(send_day, 缺省1) + 补偿天数(compensate_time 求和后再 +1 天),
             与 RyTask/RedisMqReceiver 的 isSubtaskDeadline 口径保持一致;
             无有效补偿记录(cp.subid 为空)时截止时间为 NULL,不参与即将超时统计 -->
        CASE
        WHEN cp.subid IS NULL THEN NULL
        ELSE DATE_ADD(
        DATE_ADD(ss.endtime, INTERVAL COALESCE(st.send_day, 1) DAY),
        INTERVAL (COALESCE(cp.compensate_days, 0) + 1) DAY
        )
        END AS soon_deadline
        FROM service_subtask ss
        LEFT JOIN service_task st ON st.taskid = ss.taskid AND st.del_flag = '0'
        <!-- 补偿时间:先按子任务聚合成一行再关联,避免一对多放大计数;
             compensate_time 是 varchar 且可能存成空串,需先置空再转数字 -->
        LEFT JOIN (
        SELECT subid,
        SUM(CAST(COALESCE(NULLIF(TRIM(compensate_time), ''), '0') AS SIGNED)) AS compensate_days
        FROM service_subtask_preachform
        WHERE del_flag = 0
        GROUP BY subid
        ) cp ON cp.subid = ss.id
        WHERE ss.del_flag = '0'
        AND ss.service_type = '2'
        AND ss.visit_count = 1
        <if test="orgid != null and orgid != ''">
            AND orgid = #{orgid}
            AND ss.orgid = #{orgid}
        </if>
        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
            AND leavehospitaldistrictcode IN
            <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="("
                     separator=","
                     close=")">
                #{leavehospitaldistrictcode}
            </foreach>
        <if test="campusid != null and campusid != ''">
            and ss.campusid = #{campusid}
        </if>
        <if test=" leaveldeptcodes != null and leaveldeptcodes.size()>0">
            AND deptcode IN
            <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
                     close=")">
                #{leaveldeptcode}
            </foreach>
        <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0)
                or (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
            AND (
            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
                ss.leavehospitaldistrictcode IN
                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="("
                         separator=","
                         close=")">
                    #{leavehospitaldistrictcode}
                </foreach>
            </if>
            <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0)
                and (leaveldeptcodes != null and leaveldeptcodes.size() > 0)">
                OR
            </if>
            <if test=" leaveldeptcodes != null and leaveldeptcodes.size()>0">
                ss.deptcode IN
                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
                         close=")">
                    #{leaveldeptcode}
                </foreach>
            </if>)
        </if>
        ) t
    </select>
    <select id="querySendCount" parameterType="com.smartor.domain.entity.ServiceSubtaskSatisfactionEntity"
@@ -2862,6 +3115,9 @@
        <if test="orgid != null and orgid != ''">
            AND orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            AND campusid = #{campusid}
        </if>
        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
            AND leavehospitaldistrictcode IN
            <foreach collection="leavehospitaldistrictcodes" item="code" open="(" separator="," close=")">
@@ -2887,6 +3143,9 @@
        AND deptcode IS NOT NULL AND deptcode != ''
        <if test="orgid != null and orgid != ''">
            AND orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            AND campusid = #{campusid}
        </if>
        <if test="deptcodes != null and deptcodes.size() > 0">
            AND deptcode IN
@@ -2919,6 +3178,9 @@
        AND service_type = 4
        <if test="orgid != null and orgid != ''">
            and orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            and campusid = #{campusid}
        </if>
        <if test="sendstate != null">
            AND sendstate = #{sendstate}
@@ -2961,6 +3223,117 @@
          and loop_count = #{loopCount}
          and (del_flag is null or del_flag = '0')
          and sendstate in (1, 2, 3)
    </select>
    <select id="mydTrend" resultType="com.smartor.domain.DTO.MydTrendReqDTO">
        SELECT CASE #{type}
                   WHEN 'year' THEN DATE_FORMAT(d.create_time, '%Y')
                   WHEN 'quarter' THEN CONCAT(YEAR(d.create_time), '-Q', QUARTER(d.create_time))
                   WHEN 'month' THEN DATE_FORMAT(d.create_time, '%Y-%m')
                   WHEN 'week' THEN FLOOR(DATEDIFF(d.create_time, #{startFinishTime}) / 7) + 1
                   ELSE DATE_FORMAT(d.create_time, '%Y-%m-%d')
                   END                AS period,
               ROUND(avg(d.score), 2) AS totalScore
        FROM service_subtask_detail d
                 JOIN service_task t ON d.taskid = t.taskid
        WHERE t.service_type IN (14)
          AND t.del_flag = 0
          AND d.del_flag = 0
          AND d.create_time >= #{startFinishTime}
          AND d.create_time &lt; DATE_ADD(#{endFinishTime}, INTERVAL 1 DAY)
        GROUP BY period
        ORDER BY period;
    </select>
    <select id="sltdMydTotalByDimension" resultType="com.smartor.domain.DTO.MydTrendReqDTO">
        SELECT
        p.period,
        dim.dimension,
        IFNULL(ROUND(SUM(d.score), 2), 0) AS totalScore
        FROM (
        <!-- 生成查询范围内实际出现过的时间段 -->
        SELECT DISTINCT
        CASE #{type}
        WHEN 'year' THEN DATE_FORMAT(d.create_time, '%Y')
        WHEN 'quarter' THEN CONCAT(YEAR(d.create_time), '-Q', QUARTER(d.create_time))
        WHEN 'month' THEN DATE_FORMAT(d.create_time, '%Y-%m')
        WHEN 'week' THEN FLOOR(DATEDIFF(d.create_time, #{startFinishTime}) / 7) + 1
        ELSE DATE_FORMAT(d.create_time, '%Y-%m-%d')
        END AS period
        FROM service_subtask_detail d
        WHERE d.del_flag = 0
        AND d.create_time >= #{startFinishTime}
        AND d.create_time &lt; #{endFinishTime}
        ) p
        CROSS JOIN (
        <!-- 所有需要展示的 dimension -->
        SELECT DISTINCT dimension
        FROM service_subtask_detail
        WHERE del_flag = 0
        AND dimension IS NOT NULL
        ) dim
        LEFT JOIN service_task t
        ON t.service_type IN (6, 14)
        AND t.del_flag = 0
        LEFT JOIN service_subtask_detail d
        ON d.taskid = t.taskid
        AND d.del_flag = 0
        AND d.dimension = dim.dimension
        AND CASE #{type}
        WHEN 'year' THEN DATE_FORMAT(d.create_time, '%Y')
        WHEN 'quarter' THEN CONCAT(YEAR(d.create_time), '-Q', QUARTER(d.create_time))
        WHEN 'month' THEN DATE_FORMAT(d.create_time, '%Y-%m')
        WHEN 'week' THEN FLOOR(DATEDIFF(d.create_time, #{startFinishTime}) / 7) + 1
        ELSE DATE_FORMAT(d.create_time, '%Y-%m-%d')
        END = p.period
        AND d.create_time >= #{startFinishTime}
        AND d.create_time &lt; #{endFinishTime}
        GROUP BY p.period, dim.dimension
        ORDER BY p.period, dim.dimension
    </select>
    <select id="sltdMydTotalByYQ" resultType="com.smartor.domain.DTO.MydTrendReqDTO">
        SELECT p.period,
               c.campusid,
               IFNULL(ROUND(AVG(d.score), 2), 0) AS totalScore
        FROM (
                 -- 生成查询范围内实际出现过的时间段
                 SELECT DISTINCT CASE #{type}
                                     WHEN 'year' THEN DATE_FORMAT(d.create_time, '%Y')
                                     WHEN 'quarter' THEN CONCAT(YEAR(d.create_time), '-Q', QUARTER(d.create_time))
                                     WHEN 'month' THEN DATE_FORMAT(d.create_time, '%Y-%m')
                                     WHEN 'week' THEN FLOOR(DATEDIFF(d.create_time, #{startFinishTime}) / 7) + 1
                                     ELSE DATE_FORMAT(d.create_time, '%Y-%m-%d')
                                     END AS period
                 FROM service_subtask_detail d
                 WHERE d.del_flag = 0
                   AND d.create_time >= #{startFinishTime}
                   AND d.create_time &lt; #{endFinishTime}) p
                 CROSS JOIN (
            -- 所有需要展示的院区
            SELECT DISTINCT campusid
            FROM service_task
            WHERE service_type IN (6, 14)
              AND del_flag = 0
              AND campusid IS NOT NULL) c
                 LEFT JOIN service_task t
                           ON t.campusid = c.campusid
                               AND t.service_type IN (6, 14)
                               AND t.del_flag = 0
                 LEFT JOIN service_subtask_detail d
                           ON d.taskid = t.taskid
                               AND d.del_flag = 0
                               AND CASE #{type}
                                       WHEN 'year' THEN DATE_FORMAT(d.create_time, '%Y')
                                       WHEN 'quarter' THEN CONCAT(YEAR(d.create_time), '-Q', QUARTER(d.create_time))
                                       WHEN 'month' THEN DATE_FORMAT(d.create_time, '%Y-%m')
                                       WHEN 'week' THEN FLOOR(DATEDIFF(d.create_time, #{startFinishTime}) / 7) + 1
                                       ELSE DATE_FORMAT(d.create_time, '%Y-%m-%d')
                                       END = p.period
                               AND d.create_time >= #{startFinishTime}
                               AND d.create_time &lt; #{endFinishTime}
        GROUP BY p.period, c.campusid
        ORDER BY p.period, c.campusid;
    </select>
    <!-- 任务组(appltype=5)滚动调度用:拉本轮全量 subtask,作为下一轮的克隆模板 -->
@@ -3012,13 +3385,17 @@
        continue_count,
        continue_time_next,
        task_situation,
        remark
        remark,
        doctor_opinion
        from service_subtask
        where 1=1
        and del_flag = 0
        AND service_type = 4
        <if test="orgid != null and orgid != ''">
            and orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            and campusid = #{campusid}
        </if>
        <if test="sendstate != null">
            AND sendstate = #{sendstate}
@@ -3082,6 +3459,13 @@
                #{taskId}
            </foreach>
        </if>
        <!-- 传了 subtaskIds 只统计这批子任务(本次导出的患者) -->
        <if test="subtaskIds != null and subtaskIds.size() > 0">
            AND s.id IN
            <foreach collection="subtaskIds" item="subtaskId" open="(" separator="," close=")">
                #{subtaskId}
            </foreach>
        </if>
        <if test="valueType != null">AND d.value_type = #{valueType}</if>
        <if test="scoreStart != null">AND d.score &gt;= #{scoreStart}</if>
        <if test="scoreEnd != null">AND d.score &lt;= #{scoreEnd}</if>
@@ -3090,6 +3474,19 @@
        </if>
        and s.sendstate=6
        and d.del_flag=0
        <!-- 分母必须和明细用同一套时间条件,否则选了时间范围后比例会按全量历史被稀释 -->
        <if test="startOutHospTime != null">
            AND date_format(s.endtime,'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
        </if>
        <if test="endOutHospTime != null">
            AND date_format(s.endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
        </if>
        <if test="startFinishTime != null">
            AND date_format(s.finishtime,'%y%m%d') &gt;= date_format(#{startFinishTime},'%y%m%d')
        </if>
        <if test="endFinishTime != null">
            AND date_format(s.finishtime,'%y%m%d') &lt;= date_format(#{endFinishTime},'%y%m%d')
        </if>
        GROUP BY
        t.taskid,
        d.questiontext
@@ -3099,6 +3496,12 @@
            AND t.taskid IN
            <foreach collection="taskIds" item="taskId" open="(" separator="," close=")">
                #{taskId}
            </foreach>
        </if>
        <if test="subtaskIds != null and subtaskIds.size() > 0">
            AND s.id IN
            <foreach collection="subtaskIds" item="subtaskId" open="(" separator="," close=")">
                #{subtaskId}
            </foreach>
        </if>
        <if test="valueType != null">AND d.value_type = #{valueType}</if>
@@ -3115,6 +3518,12 @@
        <if test="endOutHospTime != null">
            AND date_format(s.endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
        </if>
        <if test="startFinishTime != null">
            AND date_format(s.finishtime,'%y%m%d') &gt;= date_format(#{startFinishTime},'%y%m%d')
        </if>
        <if test="endFinishTime != null">
            AND date_format(s.finishtime,'%y%m%d') &lt;= date_format(#{endFinishTime},'%y%m%d')
        </if>
        GROUP BY
        t.taskid,
        d.questiontext,
@@ -3125,6 +3534,64 @@
        ORDER BY
        d.questiontext,
        t.taskid
    </select>
    <!--
      导出「问题详情占比」专用统计(只统计本次导出的这批患者)
      数量 = 选择该选项的患者数(COUNT(DISTINCT s.id),并用 MAX(id) 保证同一患者同一题只算最新一条)
      分数 = 该选项明细的 score 之和
      比例 = 数量 / 该题作答患者数,在 Java 侧统一计算,因此「单题各选项数量之和 = 该题作答患者数」
    -->
    <select id="statMydQuestionOptionForExport" resultType="com.smartor.domain.DTO.ServiceSubtaskOptionStatDTO">
        SELECT
        t.taskid AS taskid,
        t.task_name AS taskName,
        d.questiontext AS questiontext,
        d.asrtext AS optionresult,
        d.targetvalue AS targetvalue,
        d.value_type AS valueType,
        COUNT(DISTINCT s.id) AS patientCount,
        SUM(COALESCE(CAST(d.score AS DECIMAL(18,2)), 0)) AS scoreSum
        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 1=1
        AND s.del_flag = '0'
        AND d.del_flag = 0
        <if test="subtaskIds != null and subtaskIds.size() > 0">
            AND s.id IN
            <foreach collection="subtaskIds" item="subtaskId" open="(" separator="," close=")">
                #{subtaskId}
            </foreach>
        </if>
        <!-- 不传子任务时直接查不到数据,避免误统计全量 -->
        <if test="subtaskIds == null or subtaskIds.size() == 0">
            AND 1 = 0
        </if>
        <if test="questiontext != null and questiontext != ''">
            AND d.questiontext LIKE CONCAT('%', #{questiontext}, '%')
        </if>
        <!-- 同一患者同一题目只保留最新一条,重答不重复计入数量 -->
        AND d.id = (
        SELECT MAX(d2.id)
        FROM service_subtask_detail d2
        WHERE d2.sub_id = d.sub_id
        AND d2.questiontext &lt;=&gt; d.questiontext
        AND d2.del_flag = '0'
        )
        GROUP BY
        t.taskid,
        t.task_name,
        d.questiontext,
        d.asrtext,
        d.targetvalue,
        d.value_type
        <!-- 按任务名称分组展示:先任务名称、再任务编号,同一任务的题目/选项连续排列 -->
        ORDER BY
        t.task_name,
        t.taskid,
        d.questiontext
    </select>
    <!-- 新方法:根据子任务 ID 统计问题选项百分比 (用于满意度统计 serviceType=6) -->
@@ -3147,6 +3614,14 @@
        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
        <!-- 去重:同一子任务同一题目只保留最新一条,避免重答/重复回调把同一道题重复计入项数(与 mzMydScoreRank 口径一致) -->
        AND d.id = (
        SELECT MAX(d2.id)
        FROM service_subtask_detail d2
        WHERE d2.sub_id = d.sub_id
        AND d2.questiontext &lt;=&gt; d.questiontext
        AND d2.del_flag = '0'
        )
        INNER JOIN (
        SELECT
        d.questiontext,
@@ -3155,6 +3630,14 @@
        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
        <!-- 去重:分母(该题有效答卷总数)与明细口径保持一致,保证各选项比例合计 100% -->
        AND d.id = (
        SELECT MAX(d4.id)
        FROM service_subtask_detail d4
        WHERE d4.sub_id = d.sub_id
        AND d4.questiontext &lt;=&gt; d.questiontext
        AND d4.del_flag = '0'
        )
        WHERE 1=1
        <if test="subtaskIds != null and subtaskIds.size() > 0">
            AND s.id IN
@@ -3163,16 +3646,37 @@
            </foreach>
        </if>
        <if test="valueType != null">AND d.value_type &gt;= #{valueType}</if>
        <if test="scoreStart != null">AND d.score = #{scoreStart}</if>
        <if test="scoreStart != null">AND d.score &gt;= #{scoreStart}</if>
        <if test="scoreEnd != null">AND d.score &lt;= #{scoreEnd}</if>
        <if test="questiontext != null  and questiontext != ''">and d.questiontext like concat('%', #{questiontext},
            '%')
        </if>
        AND s.sendstate = 6
        AND d.del_flag=0
        <!-- 分母与明细用同一套时间条件,否则选了日期区间后各选项比例合计不到 100% -->
        <if test="startOutHospTime != null">
            AND date_format(s.endtime,'%y%m%d') &gt;= date_format(#{startOutHospTime},'%y%m%d')
        </if>
        <if test="endOutHospTime != null">
            AND date_format(s.endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
        </if>
        <if test="startFinishTime != null">
            AND date_format(s.finishtime,'%y%m%d') &gt;= date_format(#{startFinishTime},'%y%m%d')
        </if>
        <if test="endFinishTime != null">
            AND date_format(s.finishtime,'%y%m%d') &lt;= date_format(#{endFinishTime},'%y%m%d')
        </if>
        GROUP BY d.questiontext
        ) t2 ON t2.questiontext = d.questiontext
        WHERE 1=1
        <!-- 去重:明细行同一子任务同一题目只保留最新一条,重答不重复计入项数 -->
        AND d.id = (
        SELECT MAX(d3.id)
        FROM service_subtask_detail d3
        WHERE d3.sub_id = d.sub_id
        AND d3.questiontext &lt;=&gt; d.questiontext
        AND d3.del_flag = '0'
        )
        <if test="subtaskIds != null and subtaskIds.size() > 0">
            AND s.id IN
            <foreach collection="subtaskIds" item="subtaskId" open="(" separator="," close=")">
@@ -3193,12 +3697,24 @@
        <if test="endOutHospTime != null">
            AND date_format(s.endtime,'%y%m%d') &lt;= date_format(#{endOutHospTime},'%y%m%d')
        </if>
        <if test="startFinishTime != null">
            AND date_format(s.finishtime,'%y%m%d') &gt;= date_format(#{startFinishTime},'%y%m%d')
        </if>
        <if test="endFinishTime != null">
            AND date_format(s.finishtime,'%y%m%d') &lt;= date_format(#{endFinishTime},'%y%m%d')
        </if>
        GROUP BY
        t.taskid,
        d.questiontext,
        d.score,
        d.targetvalue,
        d.asrtext
        d.asrtext,
        t.task_name,
        s.deptcode,
        s.deptname,
        s.leavehospitaldistrictcode,
        s.leavehospitaldistrictname,
        d.value_type
        ORDER BY
        d.questiontext,
        t.taskid
@@ -3206,44 +3722,61 @@
    <select id="statQuestionOptionByKsOrBq" resultType="com.smartor.domain.DTO.QuestionCountKsOrBqDTO"
            parameterType="com.smartor.domain.VO.QuestionCountKsOrBqVO">
        SELECT questiontext,
        d.taskid,
        s.deptname,
        s.leavehospitaldistrictname,
        d.targetvalue,
        d.asrtext,
        COUNT(d.asrtext) AS answercount,
        SUM(d.score) AS singleScore
        FROM service_subtask_detail d,
        service_task s
        WHERE d.taskid = s.taskid
        AND deptname IS NOT NULL
        AND leavehospitaldistrictname IS NOT NULL
        SELECT
        s.deptname AS deptname,
        s.leavehospitaldistrictname AS leavehospitaldistrictname,
        d.questiontext AS questionText,
        d.targetvalue AS targetvalue, -- 所有选项拼接
        d.asrtext AS asrtext, -- 用户实际选中的选项
        d.score AS singleScore -- 单条记录的分数
        FROM service_subtask_detail d
        JOIN service_subtask s ON d.sub_id = s.id
        WHERE s.del_flag = 0
        AND d.del_flag = 0
        AND s.service_type IN ('6', '14')
        <if test="taskTemplateid != null">
            AND s.templateid = #{taskTemplateid}
        </if>
        <if test="endFinishTime != null">
            AND create_time &lt; #{endFinishTime}
            AND d.create_time &lt; #{endFinishTime}
        </if>
        <if test="startFinishTime != null">
            AND create_time &gt;= #{startFinishTime}
            AND d.create_time &gt;= #{startFinishTime}
        </if>
        <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
            AND leavehospitaldistrictcode IN
            <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="("
                     separator=","
                     close=")">
                #{leavehospitaldistrictcode}
            </foreach>
        <if test="deptOrDistrict ==1">
            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
                AND leavehospitaldistrictcode IN
                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="("
                         separator=","
                         close=")">
                    #{leavehospitaldistrictcode}
                </foreach>
            </if>
            <if test=" leaveldeptcodes != null and leaveldeptcodes.size()>0">
                AND deptcode IN
                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
                         close=")">
                    #{leaveldeptcode}
                </foreach>
            </if>
        </if>
        <if test=" leaveldeptcodes != null and leaveldeptcodes.size()>0">
            AND deptcode IN
            <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
                     close=")">
                #{leaveldeptcode}
            </foreach>
        <if test="deptOrDistrict ==2">
            <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0">
                AND leavehospitaldistrictcode IN
                <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="("
                         separator=","
                         close=")">
                    #{leavehospitaldistrictcode}
                </foreach>
            </if>
            <if test=" leaveldeptcodes != null and leaveldeptcodes.size()>0">
                OR deptcode IN
                <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator=","
                         close=")">
                    #{leaveldeptcode}
                </foreach>
            </if>
        </if>
        GROUP BY d.questiontext,
        d.taskid,
        d.asrtext
        ORDER BY d.taskid
    </select>
    <select id="selectServiceSubtaskListDeadLine" parameterType="com.smartor.domain.entity.ServiceSubtaskEntity"
@@ -3255,5 +3788,96 @@
        and endtime
    </select>
    <!-- 门诊满意度综合得分排名(按科室或病区) -->
    <!-- 综合满意度 = Σ(评分明细权重) / 评分明细条数 × 100%,权重只取 1、0.8、0.6、0.4、0.2 五档 -->
    <select id="selectMzMydScoreRank" parameterType="com.smartor.domain.VO.MzMydScoreRankVO"
            resultType="com.smartor.domain.DTO.MzMydScoreRankDTO">
        SELECT
        t.code                   AS code,
        t.name                   AS name,
        ROUND(AVG(t.w) * 100, 2) AS score,
        COUNT(*)                 AS itemCount
        FROM (
        SELECT
        <choose>
            <when test='dimensionType == "2"'>
                s.leavehospitaldistrictcode AS code,
                s.leavehospitaldistrictname AS name,
            </when>
            <otherwise>
                s.deptcode AS code,
                s.deptname AS name,
            </otherwise>
        </choose>
        CAST(d.score AS DECIMAL(10,4)) AS w
        FROM service_subtask s
        INNER JOIN service_subtask_detail d ON d.sub_id = s.id
        WHERE s.del_flag = '0'
        AND d.del_flag = '0'
        AND s.sendstate = 6
        <if test="serviceTypes != null and serviceTypes.size() > 0">
            AND service_type IN
            <foreach collection="serviceTypes" item="serviceType" open="(" separator=","
                     close=")">
                #{serviceType}
            </foreach>
        </if>
<!--        &lt;!&ndash; 只取公式里的五档权重,空值/0/未答等既不进分子也不进分母 &ndash;&gt;-->
<!--        AND CAST(d.score AS DECIMAL(10,4)) IN (1, 0.8, 0.6, 0.4, 0.2)-->
        <!-- 同一子任务同一题目只保留最新一条,避免重答被重复计入项数 -->
        AND d.id = (
        SELECT MAX(d2.id)
        FROM service_subtask_detail d2
        WHERE d2.sub_id = d.sub_id
        AND d2.questiontext &lt;=&gt; d.questiontext
        AND d2.del_flag = '0'
        )
        <if test="orgid != null and orgid != ''">
            AND s.orgid = #{orgid}
        </if>
        <if test="campusid != null and campusid != ''">
            AND s.campusid = #{campusid}
        </if>
        <if test="startFinishTime != null">
            AND s.finishtime &gt;= #{startFinishTime}
        </if>
        <if test="endFinishTime != null">
            AND s.finishtime &lt; DATE_ADD(#{endFinishTime}, INTERVAL 1 DAY)
        </if>
        <if test="questionText != null  and questionText != ''">and d.questiontext like concat('%', #{questionText},
            '%')
        </if>
        <choose>
            <when test='dimensionType == "2"'>
                AND s.leavehospitaldistrictcode IS NOT NULL AND s.leavehospitaldistrictcode &lt;&gt; ''
                AND s.leavehospitaldistrictname IS NOT NULL AND s.leavehospitaldistrictname &lt;&gt; ''
                <if test="districtCodes != null and districtCodes.size() > 0">
                    AND s.leavehospitaldistrictcode IN
                    <foreach collection="districtCodes" item="districtCode" open="(" separator="," close=")">
                        #{districtCode}
                    </foreach>
                </if>
            </when>
            <otherwise>
                AND s.deptcode IS NOT NULL AND s.deptcode &lt;&gt; ''
                AND s.deptname IS NOT NULL AND s.deptname &lt;&gt; ''
                <if test="deptCodes != null and deptCodes.size() > 0">
                    AND s.deptcode IN
                    <foreach collection="deptCodes" item="deptCode" open="(" separator="," close=")">
                        #{deptCode}
                    </foreach>
                </if>
            </otherwise>
        </choose>
        ) t
        GROUP BY t.code, t.name
        ORDER BY AVG(t.w) DESC, COUNT(*) DESC
        <if test="limit != null and limit > 0">
            LIMIT #{limit}
        </if>
    </select>
</mapper>