| | |
| | | <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"/> |
| | | <result property="deptcode" column="deptcode"/> |
| | | <result property="leaveldeptcode" column="leaveldeptcode"/> |
| | | <result property="labelstatus" column="labelstatus"/> |
| | | <result property="delFlag" column="del_flag"/> |
| | | <result property="updateBy" column="update_by"/> |
| | |
| | | <result property="leaveicd10code" column="leaveicd10code"/> |
| | | <result property="leavediagname" column="leavediagname"/> |
| | | <result property="diagname" column="diagname"/> |
| | | <result property="leaveldeptname" column="leaveldeptname"/> |
| | | <!-- 2026-11:原 sendlimit* 四个空闲列复用为「在院维度」(hospitaldistrict* = 在院病区,deptcode/name = 在院科室) --> |
| | | <result property="hospitaldistrictcode" column="hospitaldistrictcode"/> |
| | | <result property="hospitaldistrictname" column="hospitaldistrictname"/> |
| | | <result property="deptcode" column="deptcode"/> |
| | | <result property="deptname" column="deptname"/> |
| | | <result property="admindate" column="admindate"/> |
| | | <result property="roomno" column="roomno"/> |
| | |
| | | <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"/> |
| | |
| | | <result property="visitCount" column="visit_count"/> |
| | | <result property="isVisitAgain" column="is_visit_again"/> |
| | | <result property="upid" column="upid"/> |
| | | <result property="visitType" column="visit_type"/> |
| | | <result property="visitTime" column="visit_time"/> |
| | | <result property="visitDeptName" column="visit_dept_name"/> |
| | | <result property="visitDeptCode" column="visit_dept_code"/> |
| | |
| | | <result property="loopCount" column="loop_count"/> |
| | | <result property="isManuallyCalled" column="is_manually_called"/> |
| | | <result property="campusid" column="campusid"/> |
| | | <result property="diagType" column="diag_type"/> |
| | | <!-- 2026-11:重要性标记编码(日间手术/日间诊疗/无…),建任务时取自 pat_med_inhosp --> |
| | | <result property="importanceFlagCode" column="importance_flag_code"/> |
| | | <!-- 2026-11:点位编码,建子任务时原样拷自 service_task.point_location --> |
| | | <result property="pointLocation" column="point_location"/> |
| | | </resultMap> |
| | | |
| | | <resultMap type="com.ruoyi.task.domain.ServiceSubtaskCount" id="ServiceSubtaskResult2"> |
| | |
| | | long_send_time, |
| | | openid, |
| | | remark, |
| | | doctor_opinion, |
| | | service_type, |
| | | libtemplateid, |
| | | libtemplatename, |
| | |
| | | senduuid, |
| | | result, |
| | | finishtime, |
| | | finish_state, |
| | | recordid, |
| | | exrecallcount, |
| | | pulltime, |
| | | deptcode, |
| | | leaveldeptcode, |
| | | labelstatus, |
| | | del_flag, |
| | | update_by, |
| | |
| | | sendname, |
| | | roomno, |
| | | admindate, |
| | | leaveldeptname, |
| | | hospitaldistrictcode, |
| | | hospitaldistrictname, |
| | | deptcode, |
| | | deptname, |
| | | importance_flag_code, |
| | | point_location, |
| | | stop_state, |
| | | leavehospitaldistrictcode, |
| | | leavehospitaldistrictname, |
| | |
| | | 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()) |
| | | <= 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) > 0 |
| | | AND COALESCE(#{finishtime,jdbcType=TIMESTAMP}, service_subtask.finishtime, NOW()) |
| | | <= 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> |
| | | |
| | | <!-- 当前执行方式:首次随访 current_preachform 为空时,取 preachform 的第一个执行方式兜底 --> |
| | | <sql id="effectiveCurrentPreachformExpr"> |
| | | COALESCE(NULLIF(TRIM(current_preachform), ''), TRIM(SUBSTRING_INDEX(preachform, ',', 1))) |
| | | </sql> |
| | | |
| | | <select id="selectServiceSubtaskBySendstate" parameterType="com.ruoyi.task.domain.entity.ServiceSubtaskEntity" |
| | |
| | | <if test="continueTimeNext != null ">and continue_time_next = #{continueTimeNext}</if> |
| | | </select> |
| | | |
| | | <select id="selectServiceSubtaskList" parameterType="com.ruoyi.task.domain.entity.ServiceSubtaskEntity" |
| | | resultMap="ServiceSubtaskResult"> |
| | | <include refid="selectServiceSubtaskVo"/> |
| | | <!-- ====================================================================== |
| | | 科室 / 病区筛选(2026-11 修订版) |
| | | 两组条件【各自独立】,互不牵连(在院病区与离院病区不会同时存在): |
| | | 离院组:leavehospitaldistrictcodes → leavehospitaldistrictcode |
| | | leaveldeptcodes → leaveldeptcode |
| | | 在院组:hospitaldistrictcodes → hospitaldistrictcode(在院病区) |
| | | deptcodes → deptcode(在院科室) |
| | | 组内组合方式由 deptOrDistrict 决定:'1' = AND,'2' = OR。 |
| | | ('3'/'4' 是「离院病区 + 随访科室 visit_dept_code」那套,单独分支,不走这里) |
| | | 两组之间是 AND:只传一组时另一组自动不拼。 |
| | | 空数组 [] 一律视为"没传",不会拼出 IN ()。 |
| | | ====================================================================== --> |
| | | <sql id="filterLeaveDimAnd"> |
| | | /* f-v3 */ |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND ( |
| | | leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="lvWardCodeItem" open="(" separator="," close=")"> |
| | | #{lvWardCodeItem} |
| | | </foreach> |
| | | <!-- 延续护理任务(service_type='99')可以在患者还没出院时生成: |
| | | 这类记录只有「在院维度」(hospitaldistrictcode / deptcode),出院维度是 NULL。 |
| | | NULL 不匹配任何 IN,任务会「提示生成成功、列表里却查不到」, |
| | | 所以出院维度为空时用同一套编码体系的在院维度兜底。 --> |
| | | OR (service_type = '99' AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode = '') |
| | | AND hospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="lvWardCodeItem" open="(" separator="," close=")"> |
| | | #{lvWardCodeItem} |
| | | </foreach>) |
| | | ) |
| | | </if> |
| | | <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0"> |
| | | AND ( |
| | | leaveldeptcode IN |
| | | <foreach collection="leaveldeptcodes" item="lvDeptCodeItem" open="(" separator="," close=")"> |
| | | #{lvDeptCodeItem} |
| | | </foreach> |
| | | OR (service_type = '99' AND (leaveldeptcode IS NULL OR leaveldeptcode = '') |
| | | AND deptcode IN |
| | | <foreach collection="leaveldeptcodes" item="lvDeptCodeItem" open="(" separator="," close=")"> |
| | | #{lvDeptCodeItem} |
| | | </foreach>) |
| | | ) |
| | | </if> |
| | | </sql> |
| | | |
| | | <!-- 即将超时过滤:是否即将超时(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"/> > NOW() |
| | | AND <include refid="soonTimeoutDeadlineExpr"/> <= DATE_ADD(NOW(), INTERVAL COALESCE(#{soonTimeoutHours}, 0) HOUR) |
| | | </if> |
| | | </sql> |
| | | |
| | | <sql id="filterLeaveDimOr"> |
| | | /* f-v3 */ |
| | | <if test="(leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0) |
| | | or (leaveldeptcodes != null and leaveldeptcodes.size() > 0)"> |
| | | AND ( |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | ( |
| | | leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="lvWardCodeItem" open="(" separator="," close=")"> |
| | | #{lvWardCodeItem} |
| | | </foreach> |
| | | <!-- 延续护理任务(service_type='99')可以在患者还没出院时生成: |
| | | 这类记录只有「在院维度」(hospitaldistrictcode / deptcode),出院维度是 NULL。 |
| | | NULL 不匹配任何 IN,任务会「提示生成成功、列表里却查不到」, |
| | | 所以出院维度为空时用同一套编码体系的在院维度兜底。 --> |
| | | OR (service_type = '99' AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode = '') |
| | | AND hospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="lvWardCodeItem" open="(" separator="," close=")"> |
| | | #{lvWardCodeItem} |
| | | </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"> |
| | | ( |
| | | leaveldeptcode IN |
| | | <foreach collection="leaveldeptcodes" item="lvDeptCodeItem" open="(" separator="," close=")"> |
| | | #{lvDeptCodeItem} |
| | | </foreach> |
| | | OR (service_type = '99' AND (leaveldeptcode IS NULL OR leaveldeptcode = '') |
| | | AND deptcode IN |
| | | <foreach collection="leaveldeptcodes" item="lvDeptCodeItem" open="(" separator="," close=")"> |
| | | #{lvDeptCodeItem} |
| | | </foreach>) |
| | | ) |
| | | </if> |
| | | ) |
| | | </if> |
| | | </sql> |
| | | |
| | | <sql id="filterInhospDimAnd"> |
| | | /* f-v3 */ |
| | | <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0"> |
| | | AND hospitaldistrictcode IN |
| | | <foreach collection="hospitaldistrictcodes" item="inWardCodeItem" open="(" separator="," close=")"> |
| | | #{inWardCodeItem} |
| | | </foreach> |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND deptcode IN |
| | | <foreach collection="deptcodes" item="inDeptCodeItem" open="(" separator="," close=")"> |
| | | #{inDeptCodeItem} |
| | | </foreach> |
| | | </if> |
| | | </sql> |
| | | |
| | | <sql id="filterInhospDimOr"> |
| | | /* f-v3 */ |
| | | <if test="(hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0) |
| | | or (deptcodes != null and deptcodes.size() > 0)"> |
| | | AND ( |
| | | <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0"> |
| | | hospitaldistrictcode IN |
| | | <foreach collection="hospitaldistrictcodes" item="inWardCodeItem" open="(" separator="," close=")"> |
| | | #{inWardCodeItem} |
| | | </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="inDeptCodeItem" open="(" separator="," close=")"> |
| | | #{inDeptCodeItem} |
| | | </foreach> |
| | | </if> |
| | | ) |
| | | </if> |
| | | </sql> |
| | | |
| | | <!-- ================================================================== |
| | | service_subtask 列表查询的公共 where 片段 |
| | | ================================================================== |
| | | patItem 走「两阶段分页」: |
| | | ① selectServiceSubtaskIdsPage —— 只查 id,走覆盖索引,不为被 offset |
| | | 跳过的每一行回表读 100 列; |
| | | ② selectServiceSubtaskList + subIdList —— 按 id 回表,只读一页的量。 |
| | | 两条语句的 where 必须【逐字一致】,否则第②步会把第①步选出的行过滤掉, |
| | | 导致一页返回不足 pageSize 条。所以收成公共片段,杜绝两份口径漂移。 |
| | | ================================================================== --> |
| | | <sql id="serviceSubtaskWhere"> |
| | | where del_flag = 0 |
| | | <if test="subId != null ">and id = #{subId}</if> |
| | | <if test="continueFlag != null ">and continue_flag = #{continueFlag}</if> |
| | |
| | | '%') |
| | | </if> |
| | | <if test="startOutHospTime != null"> |
| | | AND date_format(endtime,'%y%m%d') >= date_format(#{startOutHospTime},'%y%m%d') |
| | | AND endtime >= DATE(#{startOutHospTime}) |
| | | </if> |
| | | <if test="endOutHospTime != null"> |
| | | AND date_format(endtime,'%y%m%d') <= date_format(#{endOutHospTime},'%y%m%d') |
| | | AND endtime < DATE_ADD(DATE(#{endOutHospTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <if test="startSendDateTime != null"> |
| | | AND date_format(visit_time,'%y%m%d') >= date_format(#{startSendDateTime},'%y%m%d') |
| | | AND visit_time >= DATE(#{startSendDateTime}) |
| | | </if> |
| | | <if test="endSendDateTime != null"> |
| | | AND date_format(visit_time,'%y%m%d') <= date_format(#{endSendDateTime},'%y%m%d') |
| | | AND visit_time < DATE_ADD(DATE(#{endSendDateTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <if test="finishtimeStart != null"> |
| | | AND date_format(finishtime,'%y%m%d') >= date_format(#{finishtimeStart},'%y%m%d') |
| | | AND finishtime >= DATE(#{finishtimeStart}) |
| | | </if> |
| | | <if test="finishtimeEnd != null"> |
| | | AND date_format(finishtime,'%y%m%d') <= date_format(#{finishtimeEnd},'%y%m%d') |
| | | AND finishtime < DATE_ADD(DATE(#{finishtimeEnd}), INTERVAL 1 DAY) |
| | | </if> |
| | | <if test="longSendTime != null"> |
| | | AND date_format(long_send_time,'%y%m%d') <= date_format(#{longSendTime},'%y%m%d') |
| | | AND long_send_time < DATE_ADD(DATE(#{longSendTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <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> |
| | | <!-- |
| | | 科室/病区筛选(2026-11 修订): |
| | | 离院组(leaveldeptcodes / leavehospitaldistrictcodes)保持原逻辑; |
| | | 在院组(deptcodes / hospitaldistrictcodes → deptcode / hospitaldistrictcode)是新增的一组; |
| | | 组内按 deptOrDistrict 取 AND('1') / OR('2'),两组之间 AND(只传一组时另一组不拼)。 |
| | | --> |
| | | <if test='deptOrDistrict == "1"'> |
| | | <include refid="filterLeaveDimAnd"/> |
| | | <include refid="filterInhospDimAnd"/> |
| | | </if> |
| | | <if test="deptOrDistrict==2"> |
| | | AND (1=1 |
| | | <if test="leavehospitaldistrictcodes != null"> |
| | | AND leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" |
| | | separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | </if> |
| | | <if test=" leaveldeptcodes != null"> |
| | | OR deptcode IN |
| | | <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," |
| | | close=")"> |
| | | #{leaveldeptcode} |
| | | </foreach> |
| | | </if> |
| | | ) |
| | | <if test='deptOrDistrict == "2"'> |
| | | <include refid="filterLeaveDimOr"/> |
| | | <include refid="filterInhospDimOr"/> |
| | | </if> |
| | | <if test="deptOrDistrict==3"> |
| | | <!-- ⚠️ deptOrDistrict 是 String:OGNL 里 '1'(单引号单字符)是 char,String != char 恒 false! |
| | | 必须写成双引号字符串(XML 属性用单引号包住),或直接和数字比(OGNL 会做 String→Number 转换)。 --> |
| | | <if test='deptOrDistrict == "3"'> |
| | | AND (1=1 |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND leavehospitaldistrictcode IN |
| | |
| | | </if> |
| | | ) |
| | | </if> |
| | | <if test="deptOrDistrict==4"> |
| | | <if test='deptOrDistrict == "4"'> |
| | | AND (1=1 |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND leavehospitaldistrictcode IN |
| | |
| | | ) |
| | | </if> |
| | | <if test="visitTime != null"> |
| | | AND date_format(visit_time,'%y%m%d') = date_format(#{visitTime},'%y%m%d') |
| | | AND visit_time >= DATE(#{visitTime}) |
| | | AND visit_time < DATE_ADD(DATE(#{visitTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <if test="senddate != null ">and senddate = #{senddate}</if> |
| | | <if test="senduuid != null and senduuid != ''">and senduuid = #{senduuid}</if> |
| | |
| | | <if test="recordid != null ">and recordid = #{recordid}</if> |
| | | <if test="exrecallcount != null ">and exrecallcount = #{exrecallcount}</if> |
| | | <if test="pulltime != null ">and pulltime = #{pulltime}</if> |
| | | <if test="deptcode != null and deptcode != ''">and deptcode = #{deptcode}</if> |
| | | <if test="deptname != null and deptname != ''">and deptname = #{deptname}</if> |
| | | <if test="leaveldeptcode != null and leaveldeptcode != ''">and leaveldeptcode = #{leaveldeptcode}</if> |
| | | <if test="leaveldeptname != null and leaveldeptname != ''">and leaveldeptname = #{leaveldeptname}</if> |
| | | <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="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="currentPreachform != null ">and current_preachform = #{currentPreachform}</if> |
| | | <if test="currentPreachform != null and currentPreachform != '' ">and current_preachform = #{currentPreachform}</if> |
| | | <if test="currentPreachforms != null and currentPreachforms != ''"> |
| | | and FIND_IN_SET(<include refid="effectiveCurrentPreachformExpr"/>, #{currentPreachforms}) |
| | | </if> |
| | | <if test="guid != null and guid != ''">and guid = #{guid}</if> |
| | | <if test="textParam != null and textParam != ''">and text_param = #{textParam}</if> |
| | | <if test="bedNo != null">and bed_no = #{bedNo}</if> |
| | |
| | | <if test="operatorNo != null and operatorNo != ''">and operator_no = #{operatorNo}</if> |
| | | <if test="wechat != null and wechat != ''">and wechat = #{wechat}</if> |
| | | <if test="hospType != null and hospType != ''">and hosp_type = #{hospType}</if> |
| | | <!-- |
| | | 2026-11:重要性标记筛选(对应 service_subtask.importance_flag_code,建任务时取自 |
| | | pat_med_inhosp.importance_flag_code)。 |
| | | ① 模糊(/patItem 用这个) importanceFlagCode → LIKE '%值%' |
| | | 传「日间」即可命中「日间手术」「日间诊疗」「无,日间手术」多值行; |
| | | 传完整值(「日间手术」/「FH0165.01」)退化为精确匹配。 |
| | | ② 精确多值 importanceFlagCodes → IN |
| | | 该列采集时就被拼成**描述串**(ImportFlagEnum 的 desc),多值用英文逗号拼接, |
| | | 所以「日间」这类跨取值查询只能靠模糊;描述与 FH0165.xx 编码两种口径都按原值比, |
| | | 不做值域归一。 |
| | | ⚠️ 同一条件必须同步加到 countByCondition(列表 total / 各状态统计走那条 SQL), |
| | | 否则会出现「列表筛出 N 行、总数还是全量」的错配。 |
| | | --> |
| | | <if test="importanceFlagCode != null and importanceFlagCode != ''"> |
| | | and importance_flag_code like concat('%', #{importanceFlagCode}, '%') |
| | | </if> |
| | | <if test="importanceFlagCodes != null and importanceFlagCodes.size() > 0"> |
| | | AND importance_flag_code IN |
| | | <foreach collection="importanceFlagCodes" item="impFlagItem" open="(" separator="," close=")"> |
| | | #{impFlagItem} |
| | | </foreach> |
| | | </if> |
| | | <!-- |
| | | 2026-11:点位筛选(对应 service_subtask.point_location,建子任务时从 service_task 快照过来)。 |
| | | 只有一条 IN 条件:单选/多选都在 ServiceSubtaskEntity#getPointLocations() 里归一 |
| | | (只传 pointLocation 会自动包成单元素集合),所以不再写等值分支。 |
| | | ⚠️ 同一条件必须同步加到 countByCondition(列表 total / 各状态统计走那条 SQL), |
| | | 否则会出现「列表筛出 N 行、总数还是全量」的错配。 |
| | | --> |
| | | <if test="pointLocations != null and pointLocations.size() > 0"> |
| | | AND point_location IN |
| | | <foreach collection="pointLocations" item="pointLocItem" open="(" separator="," close=")"> |
| | | #{pointLocItem} |
| | | </foreach> |
| | | </if> |
| | | <if test="libtemplateid != null ">and libtemplateid = #{libtemplateid}</if> |
| | | <if test="libtemplatename != null ">and libtemplatename = #{libtemplatename}</if> |
| | | <if test="openid != null ">and openid = #{openid}</if> |
| | |
| | | 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> |
| | |
| | | #{visitDeptCode} |
| | | </foreach> |
| | | </if> |
| | | <include refid="soonTimeoutFilter"/> |
| | | </sql> |
| | | |
| | | <!-- 排序片段:保持原语义,只在调用方显式传 sort 时才拼 order by |
| | | (导出等不分页的调用方行为完全不变) --> |
| | | <sql id="serviceSubtaskOrderBy"> |
| | | <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> |
| | |
| | | <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> |
| | | </sql> |
| | | |
| | | <!-- 分页场景专用排序:sort 为空时兜底 order by id desc。 |
| | | 原来 sort 为空时整条 SQL 没有 order by,limit/offset 取到的是「不确定顺序」, |
| | | 翻页会重复或漏行;这里给一个稳定顺序(想改成 id asc 只改这一行)。 --> |
| | | <sql id="serviceSubtaskOrderByPaged"> |
| | | <include refid="serviceSubtaskOrderBy"/> |
| | | <if test="sort == null">order by id desc</if> |
| | | </sql> |
| | | |
| | | <select id="selectServiceSubtaskList" parameterType="com.ruoyi.task.domain.entity.ServiceSubtaskEntity" |
| | | resultMap="ServiceSubtaskResult"> |
| | | <include refid="selectServiceSubtaskVo"/> |
| | | <include refid="serviceSubtaskWhere"/> |
| | | <include refid="serviceSubtaskOrderBy"/> |
| | | <if test="pageSize != null and pageNum != null">limit ${pageSize} OFFSET ${pageNum}</if> |
| | | </select> |
| | | |
| | | <!-- |
| | | 两阶段分页第 1 步:只取 id。 |
| | | select 列表只有 id,where/order 涉及的列都在 idx_ss_org_cam_del_* 上, |
| | | 因此能走「覆盖索引 + 提前截断」;被 offset 跳过的那几千行不再回表读 100 列。 |
| | | 第 2 步由调用方用 subIdList 回表取整行(见 ServiceSubtaskServiceImpl#selectServiceSubtaskPage)。 |
| | | --> |
| | | <select id="selectServiceSubtaskIdsPage" parameterType="com.ruoyi.task.domain.entity.ServiceSubtaskEntity" |
| | | resultType="java.lang.Long"> |
| | | select id |
| | | from service_subtask |
| | | <include refid="serviceSubtaskWhere"/> |
| | | <include refid="serviceSubtaskOrderByPaged"/> |
| | | limit ${pageSize} OFFSET ${pageNum} |
| | | </select> |
| | | |
| | | <select id="getCompensateServiceSubtaskList" parameterType="com.ruoyi.task.domain.entity.ServiceSubtaskEntity" |
| | |
| | | <if test="visitDeptName != null">and visit_dept_name = #{visitDeptName}</if> |
| | | <if test="managementDoctorCode != null">and management_doctor_code = #{managementDoctorCode}</if> |
| | | <if test="managementDoctor != null">and management_doctor = #{managementDoctor}</if> |
| | | <if test="currentPreachform != null">and current_preachform = #{currentPreachform}</if> |
| | | <if test="currentPreachform != null and currentPreachform != '' ">and current_preachform = #{currentPreachform}</if> |
| | | <if test="isabnormal != null">and isabnormal = #{isabnormal}</if> |
| | | <if test="continueFlag != null ">and continue_flag = #{continueFlag}</if> |
| | | <if test="continueTimeNow != null ">and continue_time_now = #{continueTimeNow,jdbcType=TIMESTAMP}</if> |
| | |
| | | <if test="recordid != null ">and recordid = #{recordid}</if> |
| | | <if test="exrecallcount != null ">and exrecallcount = #{exrecallcount}</if> |
| | | <if test="pulltime != null ">and pulltime = #{pulltime}</if> |
| | | <if test="deptcode != null and deptcode != ''">and deptcode = #{deptcode}</if> |
| | | <if test="deptname != null and deptname != ''">and deptname = #{deptname}</if> |
| | | <if test="leaveldeptcode != null and leaveldeptcode != ''">and leaveldeptcode = #{leaveldeptcode}</if> |
| | | <if test="leaveldeptname != null and leaveldeptname != ''">and leaveldeptname = #{leaveldeptname}</if> |
| | | <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="visitTime != null ">and visit_time = #{visitTime}</if> |
| | | <if test="visitDeptCode != null">and visit_dept_code = #{visitDeptCode}</if> |
| | | <if test="visitDeptName != null">and visit_dept_name = #{visitDeptName}</if> |
| | | <if test="currentPreachform != null">and current_preachform = #{currentPreachform}</if> |
| | | <if test="currentPreachform != null and currentPreachform != '' ">and current_preachform = #{currentPreachform}</if> |
| | | <if test="managementDoctorCode != null">and management_doctor_code = #{managementDoctorCode}</if> |
| | | <if test="isabnormal != null">and isabnormal = #{isabnormal}</if> |
| | | <if test="managementDoctor != null">and management_doctor like concat('%',#{managementDoctor}, '%')</if> |
| | |
| | | <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.ruoyi.task.domain.ServiceSubtask" resultType="Integer"> |
| | |
| | | <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> |
| | | <if test="deptname != null and deptname != ''">and deptname = #{deptname}</if> |
| | | <if test="leaveldeptcode != null and leaveldeptcode != ''">and leaveldeptcode = #{leaveldeptcode}</if> |
| | | <if test="leaveldeptname != null and leaveldeptname != ''">and leaveldeptname = #{leaveldeptname}</if> |
| | | <if test="isabnormal != null">and isabnormal = #{isabnormal}</if> |
| | | <if test="leavehospitaldistrictcode != null and leavehospitaldistrictcode != ''">and |
| | | leavehospitaldistrictcode = #{leavehospitaldistrictcode} |
| | |
| | | <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') >= date_format(#{startOutHospTime},'%y%m%d') |
| | | AND endtime >= DATE(#{startOutHospTime}) |
| | | </if> |
| | | <if test="endOutHospTime != null"> |
| | | AND date_format(endtime,'%y%m%d') <= date_format(#{endOutHospTime},'%y%m%d') |
| | | AND endtime < DATE_ADD(DATE(#{endOutHospTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | ) a |
| | | </select> |
| | |
| | | </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="leaveldeptcode != null and leaveldeptcode != ''">and ss.leaveldeptcode = #{leaveldeptcode}</if> |
| | | <if test="leaveldeptname != null and leaveldeptname != ''">and ss.leaveldeptname = #{leaveldeptname}</if> |
| | | <if test="isabnormal != null">and ss.isabnormal = #{isabnormal}</if> |
| | | <if test="leavehospitaldistrictcode != null and leavehospitaldistrictcode != ''">and |
| | | ss.leavehospitaldistrictcode = #{leavehospitaldistrictcode} |
| | |
| | | AND date_format(ss.endtime,'%y%m%d') <= date_format(#{endOutHospTime},'%y%m%d') |
| | | </if> |
| | | <if test="groupKey != null and groupKey != ''"> |
| | | AND ss.${groupKey} IN |
| | | AND IFNULL(ss.${groupKey}, 'Unknown') IN |
| | | <foreach collection="groupKeyList" item="key" open="(" separator="," |
| | | close=")"> |
| | | #{key} |
| | |
| | | <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> |
| | | <if test="deptcode != null and deptcode != ''">and deptcode = #{deptcode}</if> |
| | | <if test="deptname != null and deptname != ''">and deptname = #{deptname}</if> |
| | | <if test="leaveldeptcode != null and leaveldeptcode != ''">and leaveldeptcode = #{leaveldeptcode}</if> |
| | | <if test="leaveldeptname != null and leaveldeptname != ''">and leaveldeptname = #{leaveldeptname}</if> |
| | | <if test="leavehospitaldistrictcode != null and leavehospitaldistrictcode != ''">and |
| | | leavehospitaldistrictcode = #{leavehospitaldistrictcode} |
| | | </if> |
| | |
| | | </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') >= date_format(#{startOutHospTime},'%y%m%d') |
| | | </if> |
| | | <if test="endOutHospTime != null"> |
| | | AND date_format(endtime,'%y%m%d') <= date_format(#{endOutHospTime},'%y%m%d') |
| | | </if> |
| | | ) a where a.finished =1) |
| | | </select> |
| | | |
| | |
| | | <if test="continueCount != null ">and continue_count = #{continueCount}</if> |
| | | <if test="continueTimeNext != null ">and continue_time_next = #{continueTimeNext}</if> |
| | | <if test="startOutHospTime != null"> |
| | | AND date_format(endtime,'%y%m%d') >= date_format(#{startOutHospTime},'%y%m%d') |
| | | AND endtime >= DATE(#{startOutHospTime}) |
| | | </if> |
| | | <if test="endOutHospTime != null"> |
| | | AND date_format(endtime,'%y%m%d') <= date_format(#{endOutHospTime},'%y%m%d') |
| | | AND endtime < DATE_ADD(DATE(#{endOutHospTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | GROUP BY sendname,sendstate,starttime,endtime,nurse_name,phone,sex,task_name,leavediagname,visit_time |
| | | ORDER BY sendname,visit_time |
| | |
| | | <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> |
| | | <if test="deptcode != null">deptcode,</if> |
| | | <if test="leaveldeptcode != null">leaveldeptcode,</if> |
| | | <!-- 2026-11:原 sendlimit* 复用列(在院维度:在院病区/在院科室),仅出院随访会填值 --> |
| | | <if test="hospitaldistrictcode != null and hospitaldistrictcode != ''">hospitaldistrictcode,</if> |
| | | <if test="hospitaldistrictname != null and hospitaldistrictname != ''">hospitaldistrictname,</if> |
| | | <if test="deptcode != null and deptcode != ''">deptcode,</if> |
| | | <if test="deptname != null and deptname != ''">deptname,</if> |
| | | <!-- 2026-11:重要性标记编码(日间手术/日间诊疗…),建任务时从 pat_med_inhosp 同步 --> |
| | | <if test="importanceFlagCode != null and importanceFlagCode != ''">importance_flag_code,</if> |
| | | <!-- 2026-11:点位编码,建子任务时从 service_task.point_location 同步 --> |
| | | <if test="pointLocation != null and pointLocation != ''">point_location,</if> |
| | | <if test="labelstatus != null">labelstatus,</if> |
| | | <if test="updateBy != null">update_by,</if> |
| | | <if test="updateTime != null">update_time,</if> |
| | |
| | | <if test="wechat != null and wechat != ''">wechat,</if> |
| | | <if test="roomno != null and roomno != ''">roomno,</if> |
| | | <if test="admindate != null">admindate,</if> |
| | | <if test="deptname != null and deptname != ''">deptname,</if> |
| | | <if test="leaveldeptname != null and leaveldeptname != ''">leaveldeptname,</if> |
| | | <if test="leaveicd10code != null and leaveicd10code != ''">leaveicd10code,</if> |
| | | <if test="leavediagname != null and leavediagname != ''">leavediagname,</if> |
| | | <!-- diagname:入院诊断名称。原 insert 漏了这一列,而出院链路的 |
| | | boxedServiceSubtask 一直在 setDiagname(patMedInhosp.diagname), |
| | | 于是 service_subtask.diagname 永远为 NULL(select 侧却一直在读它)。 --> |
| | | <if test="diagname != null and diagname != ''">diagname,</if> |
| | | <if test="libtemplateid != null ">libtemplateid,</if> |
| | | <if test="libtemplatename != null ">libtemplatename,</if> |
| | | <if test="patid != null ">patid,</if> |
| | |
| | | <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> |
| | |
| | | <if test="visitDeptName != null">visit_dept_name,</if> |
| | | <if test="managementDoctorCode != null">management_doctor_code,</if> |
| | | <if test="managementDoctor != null">management_doctor,</if> |
| | | <if test="currentPreachform != null">current_preachform,</if> |
| | | <if test="currentPreachform != null and currentPreachform != '' ">current_preachform,</if> |
| | | <if test="taskSituation != null">task_situation,</if> |
| | | <if test="isabnormal != null">isabnormal,</if> |
| | | <if test="continueFlag != null ">continue_flag,</if> |
| | |
| | | <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> |
| | | <if test="deptcode != null">#{deptcode},</if> |
| | | <if test="leaveldeptcode != null">#{leaveldeptcode},</if> |
| | | <!-- 2026-11:原 sendlimit* 复用列(入院/在院维度),仅出院随访会填值 --> |
| | | <if test="hospitaldistrictcode != null and hospitaldistrictcode != ''">#{hospitaldistrictcode},</if> |
| | | <if test="hospitaldistrictname != null and hospitaldistrictname != ''">#{hospitaldistrictname},</if> |
| | | <if test="deptcode != null and deptcode != ''">#{deptcode},</if> |
| | | <if test="deptname != null and deptname != ''">#{deptname},</if> |
| | | <if test="importanceFlagCode != null and importanceFlagCode != ''">#{importanceFlagCode},</if> |
| | | <if test="pointLocation != null and pointLocation != ''">#{pointLocation},</if> |
| | | <if test="labelstatus != null">#{labelstatus},</if> |
| | | <if test="updateBy != null">#{updateBy},</if> |
| | | <if test="updateTime != null">#{updateTime},</if> |
| | |
| | | <if test="wechat != null and wechat != ''">#{wechat},</if> |
| | | <if test="roomno != null and roomno != ''">#{roomno},</if> |
| | | <if test="admindate != null ">#{admindate},</if> |
| | | <if test="deptname != null and deptname != ''">#{deptname},</if> |
| | | <if test="leaveldeptname != null and leaveldeptname != ''">#{leaveldeptname},</if> |
| | | <if test="leaveicd10code != null and leaveicd10code != ''">#{leaveicd10code},</if> |
| | | <if test="leavediagname != null and leavediagname != ''">#{leavediagname},</if> |
| | | <if test="diagname != null and diagname != ''">#{diagname},</if> |
| | | <if test="libtemplateid != null ">#{libtemplateid},</if> |
| | | <if test="libtemplatename != null ">#{libtemplatename},</if> |
| | | <if test="patid != null ">#{patid},</if> |
| | |
| | | <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> |
| | |
| | | <if test="visitDeptName != null">#{visitDeptName},</if> |
| | | <if test="managementDoctorCode != null">#{managementDoctorCode},</if> |
| | | <if test="managementDoctor != null">#{managementDoctor},</if> |
| | | <if test="currentPreachform != null">#{currentPreachform},</if> |
| | | <if test="currentPreachform != null and currentPreachform != '' ">#{currentPreachform},</if> |
| | | <if test="taskSituation != null">#{taskSituation},</if> |
| | | <if test="isabnormal != null">#{isabnormal},</if> |
| | | <if test="continueFlag != null ">#{continueFlag},</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 <> #{isVisitAgain}) |
| | | </update> |
| | | |
| | | <update id="updateServiceSubtask" parameterType="com.ruoyi.task.domain.ServiceSubtask"> |
| | | update service_subtask |
| | |
| | | <if test="recordid != null">recordid = #{recordid},</if> |
| | | <if test="exrecallcount != null">exrecallcount = #{exrecallcount},</if> |
| | | <if test="pulltime != null">pulltime = #{pulltime},</if> |
| | | <if test="deptcode != null">deptcode = #{deptcode},</if> |
| | | <if test="leaveldeptcode != null">leaveldeptcode = #{leaveldeptcode},</if> |
| | | <if test="labelstatus != null">labelstatus = #{labelstatus},</if> |
| | | <if test="updateBy != null">update_by = #{updateBy},</if> |
| | | <if test="updateTime != null">update_time = #{updateTime},</if> |
| | |
| | | <if test="wechat != null and wechat != ''">wechat = #{wechat},</if> |
| | | <if test="roomno != null and roomno != ''">roomno = #{roomno},</if> |
| | | <if test="admindate != null ">admindate = #{admindate},</if> |
| | | <if test="deptname != null and deptname != ''">deptname = #{deptname},</if> |
| | | <if test="leaveldeptname != null and leaveldeptname != ''">leaveldeptname = #{leaveldeptname},</if> |
| | | <if test="leaveicd10code != null and leaveicd10code != ''">leaveicd10code = #{leaveicd10code},</if> |
| | | <if test="leavediagname != null and leavediagname != ''">leavediagname = #{leavediagname},</if> |
| | | <if test="libtemplateid != null ">libtemplateid = #{libtemplateid},</if> |
| | |
| | | <if test="openid != null ">openid = #{openid},</if> |
| | | <if test="longSendTime != null ">long_send_time = #{longSendTime},</if> |
| | | <if test="sendstate != null ">sendstate = #{sendstate},</if> |
| | | <!-- 完成时间不变量(2026-11):状态一旦不是"完成(6)",就显式清空完成时间与完成时状态。 |
| | | 上面 finishtime 那一段是 if(finishtime != null),传 null 会被整段跳过, |
| | | 所以"清空"必须在这里用 SQL 的 NULL 写出来;否则 3 已发送 / 5 发送失败 / 7 超时 |
| | | 的行会一直带着历史完成时间("超时却有完成时间、及时率虚高"就是这么来的)。 --> |
| | | <if test="sendstate != null and sendstate != 6">finishtime = NULL, finish_state = NULL,</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> |
| | |
| | | <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> |
| | |
| | | <if test="visitDeptName != null">visit_dept_name = #{visitDeptName},</if> |
| | | <if test="managementDoctorCode != null">management_doctor_code = #{managementDoctorCode},</if> |
| | | <if test="managementDoctor != null">management_doctor=#{managementDoctor},</if> |
| | | <if test="currentPreachform != null">current_preachform=#{currentPreachform},</if> |
| | | <if test="currentPreachform != null and currentPreachform != '' ">current_preachform=#{currentPreachform},</if> |
| | | <if test="taskSituation != null">task_situation=#{taskSituation},</if> |
| | | <if test="isabnormal != null">isabnormal=#{isabnormal},</if> |
| | | <if test="continueFlag != null ">continue_flag = #{continueFlag},</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> |
| | | <!-- 2026-11:点位编码(建子任务时的快照;任务上改点位不会自动回写) --> |
| | | <if test="pointLocation != null and pointLocation != ''">point_location = #{pointLocation},</if> |
| | | </trim> |
| | | where id = #{id} |
| | | </update> |
| | | |
| | | <!-- 微信公众号已领取未填写按默认选项完成:只更新当前子任务。 |
| | | 条件 sendstate=1 + 未提交,保证只处理当前被领取且未填写的子任务,不波及其他任务。 --> |
| | | <update id="updateWechatDefaultComplete" parameterType="com.ruoyi.task.domain.ServiceSubtask"> |
| | | update service_subtask |
| | | set sendstate = 6, |
| | | finishtime = #{finishtime}, |
| | | result = #{result}, |
| | | remark = case |
| | | when remark is null or remark = '' then #{remark} |
| | | else concat(remark, ',', #{remark}) |
| | | end, |
| | | update_time = now(), |
| | | finish_state = <include refid="finishStateExpr"/> |
| | | where id = #{id} |
| | | and orgid = #{orgid} |
| | | and sendstate = 1 |
| | | and (submit is null or submit != 1) |
| | | </update> |
| | | |
| | | <update id="updateServiceSubtaskByPatId" parameterType="com.ruoyi.task.domain.ServiceSubtask"> |
| | |
| | | <if test="recordid != null">recordid = #{recordid},</if> |
| | | <if test="exrecallcount != null">exrecallcount = #{exrecallcount},</if> |
| | | <if test="pulltime != null">pulltime = #{pulltime},</if> |
| | | <if test="deptcode != null">deptcode = #{deptcode},</if> |
| | | <if test="leaveldeptcode != null">leaveldeptcode = #{leaveldeptcode},</if> |
| | | <if test="labelstatus != null">labelstatus = #{labelstatus},</if> |
| | | <if test="updateBy != null">update_by = #{updateBy},</if> |
| | | <if test="updateTime != null">update_time = #{updateTime},</if> |
| | |
| | | <if test="wechat != null and wechat != ''">wechat = #{wechat},</if> |
| | | <if test="roomno != null and roomno != ''">roomno = #{roomno},</if> |
| | | <if test="admindate != null">admindate = #{admindate},</if> |
| | | <if test="deptname != null and deptname != ''">deptname = #{deptname},</if> |
| | | <if test="leaveldeptname != null and leaveldeptname != ''">leaveldeptname = #{leaveldeptname},</if> |
| | | <if test="leaveicd10code != null and leaveicd10code != ''">leaveicd10code = #{leaveicd10code},</if> |
| | | <if test="leavediagname != null and leavediagname != ''">leavediagname = #{leavediagname},</if> |
| | | <if test="libtemplateid != null ">libtemplateid = #{libtemplateid},</if> |
| | |
| | | <if test="openid != null ">openid = #{openid},</if> |
| | | <if test="longSendTime != null ">long_send_time = #{longSendTime},</if> |
| | | <if test="sendstate != null ">sendstate = #{sendstate},</if> |
| | | <!-- 完成时间不变量(2026-11):状态一旦不是"完成(6)",就显式清空完成时间与完成时状态。 |
| | | 上面 finishtime 那一段是 if(finishtime != null),传 null 会被整段跳过, |
| | | 所以"清空"必须在这里用 SQL 的 NULL 写出来;否则 3 已发送 / 5 发送失败 / 7 超时 |
| | | 的行会一直带着历史完成时间("超时却有完成时间、及时率虚高"就是这么来的)。 --> |
| | | <if test="sendstate != null and sendstate != 6">finishtime = NULL, finish_state = NULL,</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> |
| | |
| | | <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> |
| | |
| | | <if test="visitDeptName != null">visit_dept_name = #{visitDeptName},</if> |
| | | <if test="managementDoctorCode != null">management_doctor_code = #{managementDoctorCode},</if> |
| | | <if test="managementDoctor != null">management_doctor=#{managementDoctor},</if> |
| | | <if test="currentPreachform != null">current_preachform=#{currentPreachform},</if> |
| | | <if test="currentPreachform != null and currentPreachform != '' ">current_preachform=#{currentPreachform},</if> |
| | | <if test="taskSituation != null">task_situation=#{taskSituation},</if> |
| | | <if test="isabnormal != null">isabnormal=#{isabnormal},</if> |
| | | <if test="continueFlag != null ">continue_flag = #{continueFlag},</if> |
| | |
| | | <if test="sex != null">sex = #{sex},</if> |
| | | <if test="delFlag != null">del_flag = #{delFlag},</if> |
| | | <if test="sendstate != null ">sendstate = #{sendstate},</if> |
| | | <!-- 完成时间不变量(2026-11):状态一旦不是"完成(6)",就显式清空完成时间与完成时状态。 |
| | | 上面 finishtime 那一段是 if(finishtime != null),传 null 会被整段跳过, |
| | | 所以"清空"必须在这里用 SQL 的 NULL 写出来;否则 3 已发送 / 5 发送失败 / 7 超时 |
| | | 的行会一直带着历史完成时间("超时却有完成时间、及时率虚高"就是这么来的)。 --> |
| | | <if test="sendstate != null and sendstate != 6">finishtime = NULL, finish_state = NULL,</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> |
| | |
| | | <if test="recordid != null">recordid = #{recordid},</if> |
| | | <if test="exrecallcount != null">exrecallcount = #{exrecallcount},</if> |
| | | <if test="pulltime != null">pulltime = #{pulltime},</if> |
| | | <if test="deptcode != null">deptcode = #{deptcode},</if> |
| | | <if test="leaveldeptcode != null">leaveldeptcode = #{leaveldeptcode},</if> |
| | | <if test="labelstatus != null">labelstatus = #{labelstatus},</if> |
| | | <if test="updateBy != null">update_by = #{updateBy},</if> |
| | | <if test="updateTime != null">update_time = #{updateTime},</if> |
| | |
| | | <if test="wechat != null and wechat != ''">wechat = #{wechat},</if> |
| | | <if test="roomno != null and roomno != ''">roomno = #{roomno},</if> |
| | | <if test="admindate != null">admindate = #{admindate},</if> |
| | | <if test="deptname != null and deptname != ''">deptname = #{deptname},</if> |
| | | <if test="leaveldeptname != null and leaveldeptname != ''">leaveldeptname = #{leaveldeptname},</if> |
| | | <if test="leaveicd10code != null and leaveicd10code != ''">leaveicd10code = #{leaveicd10code},</if> |
| | | <if test="leavediagname != null and leavediagname != ''">leavediagname = #{leavediagname},</if> |
| | | <if test="libtemplateid != null ">libtemplateid = #{libtemplateid},</if> |
| | |
| | | <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> |
| | |
| | | <if test="visitDeptName != null">visit_dept_name = #{visitDeptName},</if> |
| | | <if test="managementDoctorCode != null">management_doctor_code = #{managementDoctorCode},</if> |
| | | <if test="managementDoctor != null">management_doctor=#{managementDoctor},</if> |
| | | <if test="currentPreachform != null">current_preachform=#{currentPreachform},</if> |
| | | <if test="currentPreachform != null and currentPreachform != '' ">current_preachform=#{currentPreachform},</if> |
| | | <if test="taskSituation != null">task_situation=#{taskSituation},</if> |
| | | <if test="isabnormal != null">isabnormal=#{isabnormal},</if> |
| | | <if test="continueFlag != null ">continue_flag = #{continueFlag},</if> |
| | |
| | | <if test="phone != null">phone = #{phone},</if> |
| | | <if test="sex != null">sex = #{sex},</if> |
| | | <if test="sendstate != null ">sendstate = #{sendstate},</if> |
| | | <!-- 完成时间不变量(2026-11):状态一旦不是"完成(6)",就显式清空完成时间与完成时状态。 |
| | | 上面 finishtime 那一段是 if(finishtime != null),传 null 会被整段跳过, |
| | | 所以"清空"必须在这里用 SQL 的 NULL 写出来;否则 3 已发送 / 5 发送失败 / 7 超时 |
| | | 的行会一直带着历史完成时间("超时却有完成时间、及时率虚高"就是这么来的)。 --> |
| | | <if test="sendstate != null and sendstate != 6">finishtime = NULL, finish_state = NULL,</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> |
| | |
| | | <if test="recordid != null">recordid = #{recordid},</if> |
| | | <if test="exrecallcount != null">exrecallcount = #{exrecallcount},</if> |
| | | <if test="pulltime != null">pulltime = #{pulltime},</if> |
| | | <if test="deptcode != null">deptcode = #{deptcode},</if> |
| | | <if test="leaveldeptcode != null">leaveldeptcode = #{leaveldeptcode},</if> |
| | | <if test="labelstatus != null">labelstatus = #{labelstatus},</if> |
| | | <if test="updateBy != null">update_by = #{updateBy},</if> |
| | | <if test="updateTime != null">update_time = #{updateTime},</if> |
| | |
| | | <if test="admindate != null ">admindate = #{admindate},</if> |
| | | <if test="visitCount != null ">visit_count = #{visitCount},</if> |
| | | <if test="isVisitAgain != null ">is_visit_again = #{isVisitAgain},</if> |
| | | <if test="deptname != null and deptname != ''">deptname = #{deptname},</if> |
| | | <if test="leaveldeptname != null and leaveldeptname != ''">leaveldeptname = #{leaveldeptname},</if> |
| | | <if test="leaveicd10code != null and leaveicd10code != ''">leaveicd10code = #{leaveicd10code},</if> |
| | | <if test="leavediagname != null and leavediagname != ''">leavediagname = #{leavediagname},</if> |
| | | <if test="libtemplateid != null ">libtemplateid = #{libtemplateid},</if> |
| | |
| | | <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> |
| | |
| | | <if test="visitDeptName != null">visit_dept_name = #{visitDeptName},</if> |
| | | <if test="managementDoctorCode != null">management_doctor_code = #{managementDoctorCode},</if> |
| | | <if test="managementDoctor != null">management_doctor=#{managementDoctor},</if> |
| | | <if test="currentPreachform != null">current_preachform=#{currentPreachform},</if> |
| | | <if test="currentPreachform != null and currentPreachform != '' ">current_preachform=#{currentPreachform},</if> |
| | | <if test="taskSituation != null">task_situation=#{taskSituation},</if> |
| | | <if test="isabnormal != null">isabnormal=#{isabnormal},</if> |
| | | <if test="continueFlag != null ">continue_flag = #{continueFlag},</if> |
| | |
| | | where patid = #{patid} and taskid = #{taskid} |
| | | </update> |
| | | |
| | | <!-- 人工随访:软删除患者出院记录对应的未完成随访任务 --> |
| | | <update id="deleteUnfinishedServiceSubtaskByInhospids"> |
| | | update service_subtask |
| | | set del_flag = 1 |
| | | where del_flag = 0 |
| | | and patid = #{patid} |
| | | and sendstate in |
| | | <foreach collection="sendstates" item="sendstate" open="(" separator="," close=")"> |
| | | #{sendstate} |
| | | </foreach> |
| | | and inhospid in |
| | | <foreach collection="inhospids" item="inhospid" open="(" separator="," close=")"> |
| | | #{inhospid} |
| | | </foreach> |
| | | </update> |
| | | |
| | | <!-- 人工随访重复校验:同一患者同一任务下是否已有未完成随访任务 --> |
| | | <select id="countUnfinishedServiceSubtaskByPatidAndTaskid" resultType="int"> |
| | | select count(1) |
| | | from service_subtask |
| | | where del_flag = 0 |
| | | and patid = #{patid} |
| | | and taskid = #{taskid} |
| | | and sendstate in |
| | | <foreach collection="sendstates" item="sendstate" open="(" separator="," close=")"> |
| | | #{sendstate} |
| | | </foreach> |
| | | </select> |
| | | |
| | | <select id="getSfStatistics" parameterType="com.ruoyi.task.domain.ServiceSubtaskCountReq" |
| | | resultMap="ServiceSubtaskResult"> |
| | | select id, |
| | |
| | | management_doctor, |
| | | leavehospitaldistrictcode, |
| | | leavehospitaldistrictname, |
| | | deptcode, |
| | | deptname, |
| | | leaveldeptcode, |
| | | leaveldeptname, |
| | | sendstate, |
| | | preachform, |
| | | current_preachform, |
| | | <include refid="effectiveCurrentPreachformExpr"/> AS current_preachform, |
| | | excep, |
| | | nurse_id, |
| | | nurse_name, |
| | | taskid, |
| | | task_name, |
| | | <if test="groupKey != null and groupKey == 'taskid'"> |
| | | (SELECT st.diag_type FROM service_task st WHERE st.taskid = service_subtask.taskid LIMIT 1) AS diag_type, |
| | | </if> |
| | | visit_time, |
| | | visit_dept_code, |
| | | finishtime, |
| | | endtime, |
| | | senddate, |
| | |
| | | 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="campusid != null and campusid != ''"> |
| | | and campusid = #{campusid} |
| | | </if> |
| | | <!-- 2026-10-21:病区为空时视为"不限" |
| | | 南华满意度子任务的 leavehospitaldistrictcode 有 83%(3236/3811)为 NULL, |
| | | 原来「科室 AND 病区」两个条件永远不可能同时成立 → 整张统计表空。 |
| | | 判空放行只影响病区为空的记录,有病区的数据行为不变。 --> |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND leavehospitaldistrictcode IN |
| | | AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | ) |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND deptcode IN |
| | | AND leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | #{deptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="taskIds != null and taskIds.size() > 0"> |
| | | AND taskid IN |
| | | <foreach collection="taskIds" item="taskId" open="(" separator="," |
| | | close=")"> |
| | | #{taskId} |
| | | </foreach> |
| | | </if> |
| | | <if test="serviceType != null and serviceType.size() > 0"> |
| | |
| | | #{serviceType} |
| | | </foreach> |
| | | </if> |
| | | <!-- 2026-10-21:visit_time 为空(南华满意度 3811/3811 全为 NULL)时按完成/创建时间兜底 --> |
| | | <if test="startTime != null and endTime!=null"> |
| | | AND visit_time >= DATE(#{startTime}) |
| | | AND visit_time < DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY) |
| | | AND IFNULL(visit_time, IFNULL(finishtime, create_time)) >= DATE(#{startTime}) |
| | | AND IFNULL(visit_time, IFNULL(finishtime, create_time)) < DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <if test="hospitalStartTime != null and hospitalEndTime!=null"> |
| | | AND endtime >= DATE(#{hospitalStartTime}) |
| | |
| | | AND visit_count > 1 |
| | | </if> |
| | | <if test="groupKey != null and groupKey != '' and groupKeyList != null and groupKeyList.size>0"> |
| | | AND ${groupKey} IN |
| | | AND IFNULL(${groupKey}, 'Unknown') IN |
| | | <foreach collection="groupKeyList" item="key" open="(" separator="," |
| | | close=")"> |
| | | #{key} |
| | |
| | | </foreach> |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND b.deptcode IN |
| | | AND b.leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | #{deptcode} |
| | |
| | | <select id="getSfStatisticsGroupKey" parameterType="com.ruoyi.task.domain.ServiceSubtaskCountReq" |
| | | resultType="String"> |
| | | select |
| | | <if test="groupKey != null and groupKey != ''"> |
| | | ${groupKey} as groupKey |
| | | </if> |
| | | <choose> |
| | | <when test="groupColumn != null and groupColumn != ''"> |
| | | ${groupColumn} as groupKey |
| | | </when> |
| | | <when test="groupKey != null and groupKey != ''"> |
| | | ${groupKey} as groupKey |
| | | </when> |
| | | <otherwise> |
| | | NULL as groupKey |
| | | </otherwise> |
| | | </choose> |
| | | from service_subtask |
| | | where 1=1 |
| | | and del_flag = 0 |
| | |
| | | <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="," |
| | | <!-- 2026-10-21:病区为空时视为"不限" |
| | | 南华满意度子任务的 leavehospitaldistrictcode 有 83%(3236/3811)为 NULL, |
| | | 原来「科室 AND 病区」两个条件永远不可能同时成立 → 整张统计表空。 |
| | | 判空放行只影响病区为空的记录,有病区的数据行为不变。 --> |
| | | <choose> |
| | | <!-- 满意度统计(getSfStatisticsScript):改用“有效病区”列, |
| | | 出院病区为空则回退到在院病区。筛选因此真正生效, |
| | | 空病区的记录也会归到它真实的在院病区,而不是混进用户选中的病区。 --> |
| | | <when test="districtColumn != null and districtColumn != ''"> |
| | | <!-- 出院病区为空回退到在院病区。这里刻意写成 OR 展开而不是 IFNULL(a,b) IN (...): |
| | | 列被函数包住就用不了索引,56 万行明细表上是全表扫(实测 5.1s → 0.7s)。 |
| | | 两个分支分别命中 idx_ss_district_pair 的 (leave..., hospital...) 前缀。 --> |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND (leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | OR (leavehospitaldistrictcode IS NULL AND hospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | )) |
| | | </if> |
| | | </when> |
| | | <otherwise> |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | ) |
| | | </if> |
| | | </otherwise> |
| | | </choose> |
| | | <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0"> |
| | | AND leaveldeptcode IN |
| | | <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | #{leaveldeptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0"> |
| | | AND (hospitaldistrictcode IS NULL OR hospitaldistrictcode IN |
| | | <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{hospitaldistrictcode} |
| | | </foreach> |
| | | ) |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND deptcode IN |
| | | AND leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | #{deptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="hospitaldeptcodes != null and hospitaldeptcodes.size() > 0"> |
| | | AND deptcode IN |
| | | <foreach collection="hospitaldeptcodes" item="hospitaldeptcode" open="(" separator="," |
| | | close=")"> |
| | | #{hospitaldeptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="taskIds != null and taskIds.size() > 0"> |
| | | AND taskid IN |
| | | <foreach collection="taskIds" item="taskId" open="(" separator="," |
| | | close=")"> |
| | | #{taskId} |
| | | </foreach> |
| | | </if> |
| | | <if test="serviceType != null and serviceType.size() > 0"> |
| | |
| | | #{serviceType} |
| | | </foreach> |
| | | </if> |
| | | <!-- 2026-10-21:visit_time 为空(南华满意度 3811/3811 全为 NULL)时按完成/创建时间兜底 --> |
| | | <if test="startTime != null and endTime!=null"> |
| | | AND visit_time >= DATE(#{startTime}) |
| | | AND visit_time < DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY) |
| | | AND IFNULL(visit_time, IFNULL(finishtime, create_time)) >= DATE(#{startTime}) |
| | | AND IFNULL(visit_time, IFNULL(finishtime, create_time)) < DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <if test="hospitalStartTime != null and hospitalEndTime!=null"> |
| | | AND endtime >= DATE(#{hospitalStartTime}) |
| | |
| | | <if test="visitCount != null and visitCount > 1"> |
| | | AND visit_count > 1 |
| | | </if> |
| | | <if test="groupKey != null and groupKey != ''"> |
| | | group by ${groupKey} |
| | | </if> |
| | | <choose> |
| | | <when test="groupColumn != null and groupColumn != ''"> |
| | | group by ${groupColumn} |
| | | order by ${groupColumn} |
| | | </when> |
| | | <when test="groupKey != null and groupKey != ''"> |
| | | group by ${groupKey} |
| | | order by ${groupKey} |
| | | </when> |
| | | </choose> |
| | | <!-- pageNum 是 1 起始的,OFFSET 必须用 (pageNum-1)*pageSize; |
| | | 以前直接写 OFFSET ${pageNum},第一页会跳掉第一条分组。 --> |
| | | <if test="pageSize != null and pageNum != null"> |
| | | limit ${pageSize} OFFSET ${pageNum} |
| | | limit ${pageSize} OFFSET ${pageOffset} |
| | | </if> |
| | | </select> |
| | | |
| | | <!-- |
| | | ================================================================== |
| | | 随访分类统计(/smartor/serviceSubtask/getSfStatisticsCount)性能优化 |
| | | ================================================================== |
| | | 改造前:getSfStatisticsScript 先把 service_subtask 命中的**全部明细行** |
| | | (getSfStatistics 共 select 39 个字段,含 continue_content / result / suggest 等大字段) |
| | | 捞回 JVM,再在内存里按 drcode/科室/病区 逐行 if 累加;此外还要把这次命中的 |
| | | **全部子任务 id** 灌进 getSfStatisticsCategory 的 IN 列表再查一遍。 |
| | | 命中几千行时,网络传输(远端的库尤其明显)+ 内存遍历 + 超大 IN 列表就是接口慢的主因。 |
| | | |
| | | 改造后:累加下推到数据库,一次 GROUP BY 只返回“分组数”(通常几十行)的统计结果; |
| | | 满意度题目量也同样按分组在库里聚合。统计口径与原来的 getStatisticCategory 逐条对齐。 |
| | | 这两个语句的 where 条件与 getSfStatistics 保持一致,保证结果集不变。 |
| | | |
| | | 分组列(2026-10 起): |
| | | 离院维度 —— groupKey = leaveldeptcode / leavehospitaldistrictcode; |
| | | 在院维度 —— groupKey = deptcode / hospitaldistrictcode; |
| | | 过滤与分组使用同一列(groupColumn = groupKey),避免分组键与聚合行口径不一致。 |
| | | ================================================================== |
| | | --> |
| | | <resultMap type="com.ruoyi.task.domain.ServiceSubtaskStatistic" id="ServiceSubtaskScriptStatisticResult"> |
| | | <result property="groupCode" column="group_code"/> |
| | | <result property="groupName" column="group_name"/> |
| | | <result property="taskId" column="taskid"/> |
| | | <result property="taskName" column="task_name"/> |
| | | <result property="dischargeCount" column="discharge_count"/> |
| | | <result property="firstVisitCount" column="first_visit_count"/> |
| | | <result property="againVisitCount" column="again_visit_count"/> |
| | | <result property="drcode" column="drcode"/> |
| | | <result property="drname" column="drname"/> |
| | | <result property="deptcode" column="deptcode"/> |
| | | <result property="deptname" column="deptname"/> |
| | | <result property="leavehospitaldistrictcode" column="leavehospitaldistrictcode"/> |
| | | <result property="leavehospitaldistrictname" column="leavehospitaldistrictname"/> |
| | | <result property="hospitaldistrictcode" column="hospitaldistrictcode"/> |
| | | <result property="hospitaldistrictname" column="hospitaldistrictname"/> |
| | | <result property="hospitaldeptcode" column="hospitaldeptcode"/> |
| | | <result property="hospitaldeptname" column="hospitaldeptname"/> |
| | | <result property="nonFollowUp" column="non_follow_up"/> |
| | | <result property="followUpNeeded" column="follow_up_needed"/> |
| | | <result property="needFollowUp" column="need_follow_up"/> |
| | | <result property="pendingFollowUp" column="pending_follow_up"/> |
| | | <result property="followUpSuccess" column="follow_up_success"/> |
| | | <result property="followUpFail" column="follow_up_fail"/> |
| | | <result property="manual" column="manual"/> |
| | | <result property="voice" column="voice"/> |
| | | <result property="sms" column="sms"/> |
| | | <result property="weChat" column="we_chat"/> |
| | | <result property="abnormal" column="abnormal"/> |
| | | <result property="needFollowUpAgain" column="need_follow_up_again"/> |
| | | <result property="pendingFollowUpAgain" column="pending_follow_up_again"/> |
| | | <result property="followUpSuccessAgain" column="follow_up_success_again"/> |
| | | <result property="followUpFailAgain" column="follow_up_fail_again"/> |
| | | <result property="manualAgain" column="manual_again"/> |
| | | <result property="voiceAgain" column="voice_again"/> |
| | | <result property="smsAgain" column="sms_again"/> |
| | | <result property="weChatAgain" column="we_chat_again"/> |
| | | <result property="abnormalAgain" column="abnormal_again"/> |
| | | </resultMap> |
| | | |
| | | <!-- |
| | | 按分组聚合随访统计(替代“全量明细回内存再累加”)。 |
| | | 口径说明(与原 ServiceSubtaskServiceImpl.getStatisticCategory 完全一致): |
| | | * 无需随访:sendstate = 4 |
| | | * 应随访:sendstate 非空且 != 4 |
| | | * 首次(visit_count = 1) / 再次(visit_count > 1) 两个分支互斥,与原来的 if / else if 一致 |
| | | * 人工/语音/短信/微信:首次分支**不**排除 sendstate = 4(原代码如此),再次分支同样 |
| | | * 异常:excep = '1' 且 sendstate 非空 |
| | | * 首次随访率 / 再次随访率在 Java 里按原公式(含原来的分母判断)计算 |
| | | --> |
| | | <select id="getSfStatisticsScriptSum" parameterType="com.ruoyi.task.domain.ServiceSubtaskCountReq" |
| | | resultMap="ServiceSubtaskScriptStatisticResult"> |
| | | select |
| | | IFNULL(${groupColumn}, 'Unknown') as group_code, |
| | | <!-- 分组键对应的显示名:病区统计时就是这一组的病区名。 |
| | | 以前这一列是 MAX(hospitaldistrictname),一个组混了多个病区时会随机显示其中一个, |
| | | 于是出现“选血液内科病区却显示骨科中心三病区”。 --> |
| | | <choose> |
| | | <when test="groupKey != null and groupKey == 'taskid'"> |
| | | MAX(task_name) as group_name, |
| | | </when> |
| | | <otherwise> |
| | | MAX(IFNULL(leavehospitaldistrictname, hospitaldistrictname)) as group_name, |
| | | </otherwise> |
| | | </choose> |
| | | MAX(taskid) as taskid, |
| | | MAX(task_name) as task_name, |
| | | MAX(drcode) as drcode, |
| | | MAX(drname) as drname, |
| | | MAX(leaveldeptcode) as deptcode, |
| | | MAX(leaveldeptname) as deptname, |
| | | MAX(leavehospitaldistrictcode) as leavehospitaldistrictcode, |
| | | MAX(leavehospitaldistrictname) as leavehospitaldistrictname, |
| | | MAX(hospitaldistrictcode) as hospitaldistrictcode, |
| | | MAX(hospitaldistrictname) as hospitaldistrictname, |
| | | MAX(deptcode) as hospitaldeptcode, |
| | | MAX(deptname) as hospitaldeptname, |
| | | SUM(CASE WHEN visit_count = 1 THEN 1 ELSE 0 END) as first_visit_count, |
| | | SUM(CASE WHEN visit_count > 1 THEN 1 ELSE 0 END) as again_visit_count, |
| | | SUM(CASE WHEN sendstate = 4 THEN 1 ELSE 0 END) as non_follow_up, |
| | | SUM(CASE WHEN sendstate is not null and sendstate != 4 THEN 1 ELSE 0 END) as follow_up_needed, |
| | | SUM(CASE WHEN visit_count = 1 and sendstate is not null and sendstate != 4 THEN 1 ELSE 0 END) as need_follow_up, |
| | | SUM(CASE WHEN visit_count = 1 and sendstate = 2 THEN 1 ELSE 0 END) as pending_follow_up, |
| | | SUM(CASE WHEN visit_count = 1 and sendstate = 6 THEN 1 ELSE 0 END) as follow_up_success, |
| | | SUM(CASE WHEN visit_count = 1 and (sendstate = 5 or sendstate = 7) THEN 1 ELSE 0 END) as follow_up_fail, |
| | | SUM(CASE WHEN visit_count = 1 and sendstate is not null and current_preachform = '1' THEN 1 ELSE 0 END) as manual, |
| | | SUM(CASE WHEN visit_count = 1 and sendstate is not null and current_preachform = '3' THEN 1 ELSE 0 END) as voice, |
| | | SUM(CASE WHEN visit_count = 1 and sendstate is not null and current_preachform = '4' THEN 1 ELSE 0 END) as sms, |
| | | SUM(CASE WHEN visit_count = 1 and sendstate is not null and current_preachform = '5' THEN 1 ELSE 0 END) as we_chat, |
| | | SUM(CASE WHEN visit_count = 1 and sendstate is not null and excep = '1' THEN 1 ELSE 0 END) as abnormal, |
| | | SUM(CASE WHEN visit_count > 1 and sendstate is not null and sendstate != 4 THEN 1 ELSE 0 END) as need_follow_up_again, |
| | | SUM(CASE WHEN visit_count > 1 and sendstate = 2 THEN 1 ELSE 0 END) as pending_follow_up_again, |
| | | SUM(CASE WHEN visit_count > 1 and (sendstate = 1 or sendstate = 3 or sendstate = 6) THEN 1 ELSE 0 END) as follow_up_success_again, |
| | | SUM(CASE WHEN visit_count > 1 and sendstate = 5 THEN 1 ELSE 0 END) as follow_up_fail_again, |
| | | SUM(CASE WHEN visit_count > 1 and sendstate is not null and current_preachform = '1' THEN 1 ELSE 0 END) as manual_again, |
| | | SUM(CASE WHEN visit_count > 1 and sendstate is not null and current_preachform = '3' THEN 1 ELSE 0 END) as voice_again, |
| | | SUM(CASE WHEN visit_count > 1 and sendstate is not null and current_preachform = '4' THEN 1 ELSE 0 END) as sms_again, |
| | | SUM(CASE WHEN visit_count > 1 and sendstate is not null and current_preachform = '5' THEN 1 ELSE 0 END) as we_chat_again, |
| | | SUM(CASE WHEN visit_count > 1 and sendstate is not null and excep = '1' THEN 1 ELSE 0 END) as abnormal_again, |
| | | <!-- 出院人次:原来的内存实现是 serviceSubtaskList.size(),即分组内命中的子任务条数。 |
| | | 改成本语句后一直没有聚合这一列,页面上“出院人次”恒为 0,与应随访人次自相矛盾。 --> |
| | | COUNT(*) as discharge_count |
| | | 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> |
| | | <choose> |
| | | <!-- 满意度统计:改用“有效病区”列(出院病区为空回退在院病区),筛选才真正生效 --> |
| | | <when test="districtColumn != null and districtColumn != ''"> |
| | | <!-- 出院病区为空回退到在院病区。这里刻意写成 OR 展开而不是 IFNULL(a,b) IN (...): |
| | | 列被函数包住就用不了索引,56 万行明细表上是全表扫(实测 5.1s → 0.7s)。 |
| | | 两个分支分别命中 idx_ss_district_pair 的 (leave..., hospital...) 前缀。 --> |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND (leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | OR (leavehospitaldistrictcode IS NULL AND hospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | )) |
| | | </if> |
| | | </when> |
| | | <otherwise> |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | ) |
| | | </if> |
| | | </otherwise> |
| | | </choose> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | #{deptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0"> |
| | | AND leaveldeptcode IN |
| | | <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," |
| | | close=")"> |
| | | #{leaveldeptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0"> |
| | | AND (hospitaldistrictcode IS NULL OR hospitaldistrictcode IN |
| | | <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{hospitaldistrictcode} |
| | | </foreach> |
| | | ) |
| | | </if> |
| | | <if test="hospitaldeptcodes != null and hospitaldeptcodes.size() > 0"> |
| | | AND deptcode IN |
| | | <foreach collection="hospitaldeptcodes" item="hospitaldeptcode" open="(" separator="," |
| | | close=")"> |
| | | #{hospitaldeptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="serviceType != null and serviceType.size() > 0"> |
| | | AND service_type IN |
| | | <foreach collection="serviceType" item="serviceType" open="(" separator="," |
| | | close=")"> |
| | | #{serviceType} |
| | | </foreach> |
| | | </if> |
| | | <if test="startTime != null and endTime!=null"> |
| | | AND IFNULL(visit_time, IFNULL(finishtime, create_time)) >= DATE(#{startTime}) |
| | | AND IFNULL(visit_time, IFNULL(finishtime, create_time)) < DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <if test="hospitalStartTime != null and hospitalEndTime!=null"> |
| | | AND endtime >= DATE(#{hospitalStartTime}) |
| | | AND endtime < 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> |
| | | <if test="isabnormal != null">and isabnormal = #{isabnormal}</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> |
| | | <if test="continueTimeNext != null ">and continue_time_next = #{continueTimeNext,jdbcType=TIMESTAMP}</if> |
| | | <if test="type != null"> |
| | | and type = #{type} |
| | | </if> |
| | | <if test="visitCount != null and visitCount == 1"> |
| | | AND visit_count = 1 |
| | | </if> |
| | | <if test="visitCount != null and visitCount > 1"> |
| | | AND visit_count > 1 |
| | | </if> |
| | | <!-- 过滤列必须与 GROUP BY 的列一致:都用 groupColumn(满意度病区统计时它是 |
| | | IFNULL(出院病区, 在院病区) 这样的表达式),否则聚合出来的分组键过滤不上,题目量会全变 0。 --> |
| | | <if test="groupColumn != null and groupColumn != '' and groupKeyList != null and groupKeyList.size>0"> |
| | | AND IFNULL(${groupColumn}, 'Unknown') IN |
| | | <foreach collection="groupKeyList" item="key" open="(" separator="," |
| | | close=")"> |
| | | #{key} |
| | | </foreach> |
| | | </if> |
| | | group by IFNULL(${groupColumn}, 'Unknown') |
| | | </select> |
| | | |
| | | <!-- |
| | | 按分组聚合满意度题目量(替代 getSfStatisticsCategory 的“逐子任务 IN 查询 + 内存 N*M 过滤”)。 |
| | | where 条件 = 上面聚合查询的条件 + 原 getSfStatisticsCategory 的明细条件, |
| | | 因此命中的明细集合与改造前(getSfStatisticsCategory 结果再按子任务与分组求交)完全一致。 |
| | | configValue 为空时不调用本语句(原实现在这种场景下题目量一律为 0)。 |
| | | --> |
| | | <select id="getSfStatisticsScriptJoySum" parameterType="com.ruoyi.task.domain.ServiceSubtaskCountReq" |
| | | resultType="map"> |
| | | select |
| | | <choose> |
| | | <when test="districtColumn != null and districtColumn != ''"> |
| | | IFNULL(${districtColumn}, 'Unknown') as groupCode, |
| | | </when> |
| | | <otherwise> |
| | | IFNULL(t.${groupColumn}, 'Unknown') as groupCode, |
| | | </otherwise> |
| | | </choose> |
| | | SUM(CASE WHEN a.categoryid IN(${configValue}) |
| | | THEN 1 ELSE 0 END) as joyAllCount, |
| | | SUM(CASE WHEN a.categoryid IN(${configValue}) |
| | | AND IFNULL(a.matchedtext,a.asrtext) is not null |
| | | AND IFNULL(a.matchedtext,a.asrtext) != '' |
| | | THEN 1 ELSE 0 END) as joyCount |
| | | from service_subtask_detail a |
| | | INNER JOIN service_subtask t on a.sub_id = t.id |
| | | where 1=1 |
| | | and a.del_flag = 0 |
| | | and t.del_flag = 0 |
| | | <if test="orgid != null and orgid != ''"> |
| | | and t.orgid = #{orgid} |
| | | </if> |
| | | <if test="campusid != null and campusid != ''"> |
| | | and t.campusid = #{campusid} |
| | | </if> |
| | | <choose> |
| | | <!-- 满意度统计:与聚合主查询一致,用“有效病区”列过滤, |
| | | 否则题目量会和主查询的行对不上(分组键不一样,过滤不上就全变 0)。 --> |
| | | <when test="districtColumn != null and districtColumn != ''"> |
| | | <!-- 出院病区为空回退到在院病区。这里刻意写成 OR 展开而不是 IFNULL(a,b) IN (...): |
| | | 列被函数包住就用不了索引,56 万行明细表上是全表扫(实测 5.1s → 0.7s)。 |
| | | 两个分支分别命中 idx_ss_district_pair 的 (leave..., hospital...) 前缀。 --> |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND (leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | OR (leavehospitaldistrictcode IS NULL AND hospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | )) |
| | | </if> |
| | | </when> |
| | | <otherwise> |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND (t.leavehospitaldistrictcode IS NULL OR t.leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | ) |
| | | </if> |
| | | </otherwise> |
| | | </choose> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND t.leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | #{deptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0"> |
| | | AND t.leaveldeptcode IN |
| | | <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," |
| | | close=")"> |
| | | #{leaveldeptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0"> |
| | | AND (t.hospitaldistrictcode IS NULL OR t.hospitaldistrictcode IN |
| | | <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{hospitaldistrictcode} |
| | | </foreach> |
| | | ) |
| | | </if> |
| | | <if test="hospitaldeptcodes != null and hospitaldeptcodes.size() > 0"> |
| | | AND t.deptcode IN |
| | | <foreach collection="hospitaldeptcodes" item="hospitaldeptcode" open="(" separator="," |
| | | close=")"> |
| | | #{hospitaldeptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="serviceType != null and serviceType.size() > 0"> |
| | | AND t.service_type IN |
| | | <foreach collection="serviceType" item="serviceType" open="(" separator="," |
| | | close=")"> |
| | | #{serviceType} |
| | | </foreach> |
| | | </if> |
| | | <if test="startTime != null and endTime!=null"> |
| | | AND IFNULL(t.visit_time, IFNULL(t.finishtime, t.create_time)) >= DATE(#{startTime}) |
| | | AND IFNULL(t.visit_time, IFNULL(t.finishtime, t.create_time)) < DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <if test="hospitalStartTime != null and hospitalEndTime!=null"> |
| | | AND t.endtime >= DATE(#{hospitalStartTime}) |
| | | AND t.endtime < DATE_ADD(DATE(#{hospitalEndTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <if test="visitDeptCode != null">and t.visit_dept_code = #{visitDeptCode}</if> |
| | | <if test="visitDeptName != null">and t.visit_dept_name = #{visitDeptName}</if> |
| | | <if test="isabnormal != null">and t.isabnormal = #{isabnormal}</if> |
| | | <if test="continueFlag != null ">and t.continue_flag = #{continueFlag}</if> |
| | | <if test="continueTimeNow != null ">and t.continue_time_now = #{continueTimeNow,jdbcType=TIMESTAMP}</if> |
| | | <if test="continueCount != null ">and t.continue_count = #{continueCount}</if> |
| | | <if test="continueTimeNext != null ">and t.continue_time_next = #{continueTimeNext,jdbcType=TIMESTAMP}</if> |
| | | <if test="type != null"> |
| | | and t.type = #{type} |
| | | </if> |
| | | <if test="visitCount != null and visitCount == 1"> |
| | | AND t.visit_count = 1 |
| | | </if> |
| | | <if test="visitCount != null and visitCount > 1"> |
| | | AND t.visit_count > 1 |
| | | </if> |
| | | <if test="districtColumn != null and districtColumn != '' and groupKeyList != null and groupKeyList.size>0"> |
| | | AND IFNULL(${districtColumn}, 'Unknown') IN |
| | | <foreach collection="groupKeyList" item="key" open="(" separator="," |
| | | close=")"> |
| | | #{key} |
| | | </foreach> |
| | | </if> |
| | | <if test="(districtColumn == null or districtColumn == '') and groupKey != null and groupKey != '' and groupKeyList != null and groupKeyList.size>0"> |
| | | AND IFNULL(t.${groupKey}, 'Unknown') IN |
| | | <foreach collection="groupKeyList" item="key" open="(" separator="," |
| | | close=")"> |
| | | #{key} |
| | | </foreach> |
| | | </if> |
| | | <choose> |
| | | <when test="districtColumn != null and districtColumn != ''"> |
| | | group by IFNULL(${districtColumn}, 'Unknown') |
| | | </when> |
| | | <otherwise> |
| | | group by IFNULL(t.${groupColumn}, 'Unknown') |
| | | </otherwise> |
| | | </choose> |
| | | </select> |
| | | |
| | | <select id="getSfStatisticsHyperlink" parameterType="com.ruoyi.task.domain.ServiceSubtaskCountReq" |
| | |
| | | drname, |
| | | leavehospitaldistrictcode, |
| | | leavehospitaldistrictname, |
| | | deptcode, |
| | | deptname, |
| | | leaveldeptcode, |
| | | leaveldeptname, |
| | | sendstate, |
| | | preachform, |
| | | current_preachform, |
| | | <include refid="effectiveCurrentPreachformExpr"/> AS current_preachform, |
| | | excep, |
| | | nurse_id, |
| | | nurse_name, |
| | | taskid, |
| | | task_name, |
| | | visit_time, |
| | | visit_dept_code, |
| | | visit_dept_name, |
| | | finishtime, |
| | | endtime, |
| | | senddate, |
| | |
| | | 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="campusid != null and campusid != ''"> |
| | | and campusid = #{campusid} |
| | | </if> |
| | | <!-- 2026-10-21:病区为空时视为"不限"(南华满意度 83% 子任务无病区),有病区的数据行为不变 --> |
| | | <!-- 与 getSfStatisticsScript 的汇总行保持一致:出院病区为空则回退到在院病区, |
| | | 否则点“查看详情”查出来的条数会和汇总行的数字对不上。 --> |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND leavehospitaldistrictcode IN |
| | | AND (leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | OR (leavehospitaldistrictcode IS NULL AND hospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | )) |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND deptcode IN |
| | | AND leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | #{deptcode} |
| | |
| | | #{serviceType} |
| | | </foreach> |
| | | </if> |
| | | <!-- 2026-10-21:visit_time 为空时按完成/创建时间兜底 --> |
| | | <if test="startTime != null and endTime!=null"> |
| | | AND visit_time >= DATE(#{startTime}) |
| | | AND visit_time < DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY) |
| | | AND IFNULL(visit_time, IFNULL(finishtime, create_time)) >= DATE(#{startTime}) |
| | | AND IFNULL(visit_time, IFNULL(finishtime, create_time)) < DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <if test="hospitalStartTime != null and hospitalEndTime!=null"> |
| | | AND endtime >= DATE(#{hospitalStartTime}) |
| | | AND endtime < 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> |
| | |
| | | <if test="type != null"> |
| | | and type = #{type} |
| | | </if> |
| | | <if test="visitCount != null and visitCount == 1"> |
| | | <!-- 首个再次随访:精确查 visit_count = 2,与统计口径一致 --> |
| | | <if test="hyperLinkInfoType == 'againFollowUpPushCountInfo'"> |
| | | AND visit_count = 2 |
| | | </if> |
| | | <!-- 其他类型保持原语义:1 首次,>1 再次 --> |
| | | <if test="hyperLinkInfoType != 'againFollowUpPushCountInfo' and visitCount != null and visitCount == 1"> |
| | | AND visit_count = 1 |
| | | </if> |
| | | <if test="visitCount != null and visitCount > 1"> |
| | | <if test="hyperLinkInfoType != 'againFollowUpPushCountInfo' and visitCount != null and visitCount > 1"> |
| | | AND visit_count > 1 |
| | | </if> |
| | | <if test="groupKey != null and groupKey != '' and groupKeyList != null and groupKeyList.size>0"> |
| | | AND ${groupKey} IN |
| | | AND IFNULL(${groupKey}, 'Unknown') IN |
| | | <foreach collection="groupKeyList" item="key" open="(" separator="," |
| | | close=")"> |
| | | #{key} |
| | |
| | | #{state} |
| | | </foreach> |
| | | </if> |
| | | <if test="currentPreachform != null"> |
| | | AND current_preachform = #{currentPreachform} |
| | | <if test="currentPreachform != null and currentPreachform != '' "> |
| | | AND <include refid="effectiveCurrentPreachformExpr"/> = #{currentPreachform} |
| | | <if test="followUpCountStyle != null and followUpCountStyle = '1'"> |
| | | AND sendstate != 4 |
| | | </if> |
| | |
| | | <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> |
| | |
| | | AND leavehospitaldistrictcode = #{leavehospitaldistrictcode} |
| | | </if> |
| | | <if test="deptcode != null and deptcode != ''"> |
| | | AND deptcode = #{deptcode} |
| | | AND leaveldeptcode = #{deptcode} |
| | | </if> |
| | | <if test="isManuallyCalled != null"> |
| | | AND is_manually_called = #{isManuallyCalled} |
| | | </if> |
| | | <if test="suggest != null and suggest != ''"> |
| | | AND TRIM(suggest) = #{suggest} |
| | | </if> |
| | | order by endtime desc |
| | | <if test="pageSize != null and pageNum != null"> |
| | |
| | | <if test="campusid != null and campusid != ''"> |
| | | and campusid = #{campusid} |
| | | </if> |
| | | <!-- 2026-10-21:病区为空时视为"不限"(南华满意度 83% 子任务无病区),有病区的数据行为不变 --> |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND leavehospitaldistrictcode IN |
| | | AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | ) |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND deptcode IN |
| | | AND leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | #{deptcode} |
| | |
| | | </foreach> |
| | | </if> |
| | | <if test="startTime != null and endTime!=null"> |
| | | AND date_format(visit_time,'%y%m%d') >= date_format(#{startTime},'%y%m%d') |
| | | AND date_format(visit_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d') |
| | | AND date_format(IFNULL(visit_time, IFNULL(finishtime, create_time)),'%y%m%d') >= date_format(#{startTime},'%y%m%d') |
| | | AND date_format(IFNULL(visit_time, IFNULL(finishtime, create_time)),'%y%m%d') <= date_format(#{endTime},'%y%m%d') |
| | | </if> |
| | | <if test="visitDeptCode != null">and visit_dept_code = #{visitDeptCode}</if> |
| | | <if test="visitDeptName != null">and visit_dept_name = #{visitDeptName}</if> |
| | |
| | | <if test="campusid != null and campusid != ''"> |
| | | and campusid = #{campusid} |
| | | </if> |
| | | <!-- 2026-10-21:病区为空时视为"不限"(南华满意度 83% 子任务无病区),有病区的数据行为不变 --> |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND leavehospitaldistrictcode IN |
| | | AND (leavehospitaldistrictcode IS NULL OR leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | ) |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND deptcode IN |
| | | AND leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | #{deptcode} |
| | |
| | | </foreach> |
| | | </if> |
| | | <if test="startTime != null and endTime!=null"> |
| | | AND date_format(visit_time,'%y%m%d') >= date_format(#{startTime},'%y%m%d') |
| | | AND date_format(visit_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d') |
| | | AND date_format(IFNULL(visit_time, IFNULL(finishtime, create_time)),'%y%m%d') >= date_format(#{startTime},'%y%m%d') |
| | | AND date_format(IFNULL(visit_time, IFNULL(finishtime, create_time)),'%y%m%d') <= date_format(#{endTime},'%y%m%d') |
| | | </if> |
| | | ) AND targetid=a.id) joyCount , (SELECT COUNT(*) from (select sub_id FROM service_subtask_detail |
| | | WHERE sub_id IN(SELECT id FROM service_subtask t |
| | |
| | | </foreach> |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND deptcode IN |
| | | AND leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | #{deptcode} |
| | |
| | | </foreach> |
| | | </if> |
| | | <if test="startTime != null and endTime!=null"> |
| | | AND date_format(visit_time,'%y%m%d') >= date_format(#{startTime},'%y%m%d') |
| | | AND date_format(visit_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d') |
| | | AND date_format(IFNULL(visit_time, IFNULL(finishtime, create_time)),'%y%m%d') >= date_format(#{startTime},'%y%m%d') |
| | | AND date_format(IFNULL(visit_time, IFNULL(finishtime, create_time)),'%y%m%d') <= date_format(#{endTime},'%y%m%d') |
| | | </if> |
| | | GROUP BY sub_id ) ) ta ) joyAllCount |
| | | FROM ivr_liba_target a |
| | |
| | | <if test="campusid != null and campusid != ''"> |
| | | and t.campusid = #{campusid} |
| | | </if> |
| | | <!-- 2026-10-21:病区为空时视为"不限" |
| | | 南华满意度子任务的 leavehospitaldistrictcode 有 83%(3236/3811)为 NULL, |
| | | 原来「科室 AND 病区」两个条件永远不可能同时成立 → 整张统计表空。 |
| | | 判空放行只影响病区为空的记录,有病区的数据行为不变。 --> |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND t.leavehospitaldistrictcode IN |
| | | AND (t.leavehospitaldistrictcode IS NULL OR t.leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | ) |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND t.deptcode IN |
| | | AND t.leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | #{deptcode} |
| | |
| | | #{serviceType} |
| | | </foreach> |
| | | </if> |
| | | <!-- 2026-10-21:visit_time 为空时按完成/创建时间兜底 --> |
| | | <if test="startTime != null and endTime!=null"> |
| | | AND date_format(t.visit_time,'%y%m%d') >= date_format(#{startTime},'%y%m%d') |
| | | AND date_format(t.visit_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d') |
| | | AND date_format(IFNULL(t.visit_time, IFNULL(t.finishtime, t.create_time)),'%y%m%d') >= date_format(#{startTime},'%y%m%d') |
| | | AND date_format(IFNULL(t.visit_time, IFNULL(t.finishtime, t.create_time)),'%y%m%d') <= date_format(#{endTime},'%y%m%d') |
| | | </if> |
| | | <if test="visitDeptCode != null"> |
| | | and t.visit_dept_code = #{visitDeptCode} |
| | |
| | | <select id="getSfStatisticsScriptDetails" parameterType="com.ruoyi.task.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 |
| | |
| | | AND ss.campusid = #{campusid} |
| | | </if> |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND ss.leavehospitaldistrictcode IN |
| | | AND (ss.leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | OR (ss.leavehospitaldistrictcode IS NULL AND ss.hospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | )) |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND ss.deptcode IN |
| | | AND ss.leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | #{deptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0"> |
| | | AND ss.leaveldeptcode IN |
| | | <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," |
| | | close=")"> |
| | | #{leaveldeptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0"> |
| | | AND ss.hospitaldistrictcode IN |
| | | <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{hospitaldistrictcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="hospitaldeptcodes != null and hospitaldeptcodes.size() > 0"> |
| | | AND ss.deptcode IN |
| | | <foreach collection="hospitaldeptcodes" item="hospitaldeptcode" open="(" separator="," |
| | | close=")"> |
| | | #{hospitaldeptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="serviceType != null and serviceType.size() > 0"> |
| | |
| | | #{serviceType} |
| | | </foreach> |
| | | </if> |
| | | <!-- 2026-10-21:visit_time 为空(南华满意度 3811/3811 全为 NULL)时按完成/创建时间兜底 --> |
| | | <if test="startTime != null and endTime!=null"> |
| | | AND date_format(ss.visit_time,'%y%m%d') >= date_format(#{startTime},'%y%m%d') |
| | | AND date_format(ss.visit_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d') |
| | | AND date_format(IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)),'%y%m%d') >= date_format(#{startTime},'%y%m%d') |
| | | AND date_format(IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)),'%y%m%d') <= date_format(#{endTime},'%y%m%d') |
| | | </if> |
| | | <!-- 目前只统计语音和问卷 --> |
| | | <if test="type != null"> |
| | |
| | | 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.ruoyi.task.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 |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | OR (ss.leavehospitaldistrictcode IS NULL AND ss.hospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | )) |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND ss.leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | #{deptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="leaveldeptcodes != null and leaveldeptcodes.size() > 0"> |
| | | AND ss.leaveldeptcode IN |
| | | <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," |
| | | close=")"> |
| | | #{leaveldeptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="hospitaldistrictcodes != null and hospitaldistrictcodes.size() > 0"> |
| | | AND ss.hospitaldistrictcode IN |
| | | <foreach collection="hospitaldistrictcodes" item="hospitaldistrictcode" open="(" separator="," |
| | | close=")"> |
| | | #{hospitaldistrictcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="hospitaldeptcodes != null and hospitaldeptcodes.size() > 0"> |
| | | AND ss.deptcode IN |
| | | <foreach collection="hospitaldeptcodes" item="hospitaldeptcode" open="(" separator="," |
| | | close=")"> |
| | | #{hospitaldeptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="serviceType != null and serviceType.size() > 0"> |
| | | AND ss.service_type IN |
| | | <foreach collection="serviceType" item="serviceType" open="(" separator="," |
| | | close=")"> |
| | | #{serviceType} |
| | | </foreach> |
| | | </if> |
| | | <!-- 2026-10-21:visit_time 为空(南华满意度 3811/3811 全为 NULL)时按完成/创建时间兜底 --> |
| | | <if test="startTime != null and endTime!=null"> |
| | | AND date_format(IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)),'%y%m%d') >= date_format(#{startTime},'%y%m%d') |
| | | AND date_format(IFNULL(ss.visit_time, IFNULL(ss.finishtime, ss.create_time)),'%y%m%d') <= date_format(#{endTime},'%y%m%d') |
| | | </if> |
| | | <!-- 目前只统计语音和问卷 --> |
| | | <if test="type != null"> |
| | | and ss.type = #{type} |
| | | </if> |
| | | <if test="configValue != null and configValue != ''"> |
| | | AND ssd.categoryid IN (${configValue}) |
| | | </if> |
| | | group by a.script_content, ss.type, IFNULL(ssd.matchedtext,ssd.asrtext) |
| | | </select> |
| | | |
| | | <!-- |
| | | 问题选项数字下钻:返回选择了指定选项的 service_subtask 列表。 |
| | | 过滤口径与 getSfStatisticsScriptDetails / getSfStatisticsScriptItemDetails 保持一致, |
| | | 额外支持 statisticaltype:1-病区、2-科室、3-病种。 |
| | | --> |
| | | <select id="getSfStatisticsScriptDetailsHyperlink" parameterType="com.ruoyi.task.domain.ServiceSubtaskCountReq" |
| | | resultMap="ServiceSubtaskResult"> |
| | | SELECT ss.* |
| | | FROM service_subtask ss |
| | | WHERE ss.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 |
| | |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND ss.deptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")"> |
| | | #{deptcode} |
| | | </foreach> |
| | | </if> |
| | | <if test="serviceType != null and serviceType.size() > 0"> |
| | | AND ss.service_type IN |
| | | <foreach collection="serviceType" item="serviceType" open="(" separator="," |
| | | close=")"> |
| | | <foreach collection="serviceType" item="serviceType" open="(" separator="," close=")"> |
| | | #{serviceType} |
| | | </foreach> |
| | | </if> |
| | | <if test="startTime != null and endTime!=null"> |
| | | AND date_format(ss.visit_time,'%y%m%d') >= date_format(#{startTime},'%y%m%d') |
| | | AND date_format(ss.visit_time,'%y%m%d') <= date_format(#{endTime},'%y%m%d') |
| | | <if test="startTime != null and endTime != null"> |
| | | AND ss.visit_time >= DATE(#{startTime}) |
| | | AND ss.visit_time < DATE_ADD(DATE(#{endTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <!-- 目前只统计语音和问卷 --> |
| | | <if test="type != null"> |
| | | and ss.type = #{type} |
| | | <if test="type != null and type != ''"> |
| | | AND ss.type = #{type} |
| | | </if> |
| | | <if test="configValue != null and configValue != ''"> |
| | | AND ssd.categoryid IN (${configValue}) |
| | | |
| | | <!-- 统计维度:1-按病区 2-按科室 3-按taskid --> |
| | | <if test="statisticaltype != null and statisticaltype == 1"> |
| | | <choose> |
| | | <when test="deptcode != null and deptcode != ''"> |
| | | AND ss.leavehospitaldistrictcode = #{deptcode} |
| | | </when> |
| | | <when test="leavehospitaldistrictcode != null and leavehospitaldistrictcode != ''"> |
| | | AND ss.leavehospitaldistrictcode = #{leavehospitaldistrictcode} |
| | | </when> |
| | | </choose> |
| | | </if> |
| | | group by ssd.scriptid, IFNULL(ssd.matchedtext,ssd.asrtext) |
| | | <if test="statisticaltype != null and statisticaltype == 2 and deptcode != null and deptcode != ''"> |
| | | AND ss.deptcode = #{deptcode} |
| | | </if> |
| | | <if test="statisticaltype != null and statisticaltype == 3 and taskId != null"> |
| | | AND ss.taskid = #{taskId} |
| | | </if> |
| | | <!-- 兼容不传 statisticaltype 时按单值条件过滤 --> |
| | | <if test="statisticaltype == null"> |
| | | <if test="leavehospitaldistrictcode != null and leavehospitaldistrictcode != ''"> |
| | | AND ss.leavehospitaldistrictcode = #{leavehospitaldistrictcode} |
| | | </if> |
| | | <if test="deptcode != null and deptcode != ''"> |
| | | AND ss.deptcode = #{deptcode} |
| | | </if> |
| | | <if test="taskId != null"> |
| | | AND ss.taskid = #{taskId} |
| | | </if> |
| | | </if> |
| | | |
| | | <!-- 题目 + 选项匹配:只保留回答中选择了该选项的子任务 --> |
| | | AND EXISTS ( |
| | | SELECT 1 |
| | | FROM service_subtask_detail ssd |
| | | WHERE ssd.sub_id = ss.id |
| | | AND ssd.del_flag = 0 |
| | | <if test="configValue != null and configValue != ''"> |
| | | AND ssd.categoryid IN (${configValue}) |
| | | </if> |
| | | <choose> |
| | | <when test="optionText != null"> |
| | | AND IFNULL(ssd.matchedtext, ssd.asrtext) = #{optionText} |
| | | </when> |
| | | <otherwise> |
| | | AND 1 = 0 |
| | | </otherwise> |
| | | </choose> |
| | | <choose> |
| | | <!-- 优先按题目内容匹配:同一道题复制到多个任务模板时 scriptid 不同,但 script_content 相同 --> |
| | | <when test="scriptContent != null and scriptContent != ''"> |
| | | AND ssd.scriptid IN ( |
| | | <choose> |
| | | <when test="type == '1'"> |
| | | SELECT its.id FROM ivr_task_template_script its |
| | | WHERE its.script_content = #{scriptContent} |
| | | </when> |
| | | <when test="type == '2'"> |
| | | SELECT sts.id FROM svy_task_template_script sts |
| | | WHERE sts.script_content = #{scriptContent} |
| | | </when> |
| | | <otherwise> |
| | | SELECT its.id FROM ivr_task_template_script its |
| | | WHERE its.script_content = #{scriptContent} |
| | | UNION |
| | | SELECT sts.id FROM svy_task_template_script sts |
| | | WHERE sts.script_content = #{scriptContent} |
| | | </otherwise> |
| | | </choose> |
| | | ) |
| | | </when> |
| | | <when test="scriptid != null"> |
| | | AND ssd.scriptid = #{scriptid} |
| | | </when> |
| | | <otherwise> |
| | | AND 1 = 0 |
| | | </otherwise> |
| | | </choose> |
| | | ) |
| | | ORDER BY ss.endtime DESC, ss.id DESC |
| | | <if test="pageSize != null and pageSize > 0"> |
| | | LIMIT #{pageSize} |
| | | <if test="pageNum != null and pageNum >= 0"> |
| | | OFFSET #{pageNum} |
| | | </if> |
| | | </if> |
| | | </select> |
| | | |
| | | <select id="getDataByTime" resultMap="ServiceSubtaskResult"> |
| | |
| | | recordid, |
| | | exrecallcount, |
| | | pulltime, |
| | | deptcode, |
| | | leaveldeptcode, |
| | | labelstatus, |
| | | del_flag, |
| | | upid, |
| | |
| | | admindate, |
| | | patid, |
| | | service_type, |
| | | deptname, |
| | | leaveldeptname, |
| | | score, |
| | | drname, |
| | | drcode, |
| | |
| | | nurse_id, |
| | | nurse_name, |
| | | remark, |
| | | doctor_opinion, |
| | | inhospid, |
| | | patfrom, |
| | | task_guid, |
| | |
| | | </select> |
| | | |
| | | <select id="getDeptRanking" parameterType="com.ruoyi.common.core.service.dto.PatMedReq" resultType="com.ruoyi.common.core.service.dto.PatMedRes"> |
| | | SELECT deptname, |
| | | SELECT leaveldeptname AS deptname, |
| | | count(1) AS rc |
| | | FROM service_subtask |
| | | WHERE DATE_FORMAT(visit_time, '%Y-%m-%d') >= #{startDate} |
| | |
| | | <if test="campusid != null and campusid != ''"> |
| | | AND campusid = #{campusid} |
| | | </if> |
| | | GROUP BY deptname |
| | | GROUP BY leaveldeptname |
| | | </select> |
| | | |
| | | <!-- 服务统计查询 - 按时间维度统计出院/门诊随访数据 --> |
| | |
| | | AND campusid = #{campusid} |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND deptcode IN |
| | | AND leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," close=")"> |
| | | #{deptcode} |
| | | </foreach> |
| | |
| | | SUM(CASE WHEN sendstate = 1 THEN 1 ELSE 0 END) AS blq, |
| | | SUM(CASE WHEN sendstate = 4 THEN 1 ELSE 0 END) AS wxsf, |
| | | 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 |
| | | SUM(CASE WHEN (sendstate = 1 OR sendstate = 2 OR sendstate = 3 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 |
| | |
| | | <if test="sendname != null and sendname != ''"> |
| | | AND sendname LIKE CONCAT('%', #{sendname}, '%') |
| | | </if> |
| | | <!-- |
| | | 2026-11:重要性标记模糊筛选 —— 必须与 serviceSubtaskWhere 里的同名条件【完全一致】, |
| | | 否则 /patItem 的列表与 total/各状态统计会错配(列表筛了、总数没筛)。 |
| | | 口径见 serviceSubtaskWhere 处的注释。 |
| | | --> |
| | | <if test="importanceFlagCode != null and importanceFlagCode != ''"> |
| | | AND importance_flag_code LIKE CONCAT('%', #{importanceFlagCode}, '%') |
| | | </if> |
| | | <!-- |
| | | 2026-11:点位筛选 —— 必须与 serviceSubtaskWhere 里的同名条件【完全一致】, |
| | | 否则 /patItem 的列表与 total/各状态统计会错配(列表筛了、总数没筛)。 |
| | | 单选/多选归一在 ServiceSubtaskEntity#getPointLocations(),这里只有一条 IN。 |
| | | --> |
| | | <if test="pointLocations != null and pointLocations.size() > 0"> |
| | | AND point_location IN |
| | | <foreach collection="pointLocations" item="pointLocItem" open="(" separator="," close=")"> |
| | | #{pointLocItem} |
| | | </foreach> |
| | | </if> |
| | | <if test="phone != null and phone != ''"> |
| | | AND phone = #{phone} |
| | | </if> |
| | | <if test="finishtimeStart != null"> |
| | | AND date_format(finishtime,'%y%m%d') >= date_format(#{finishtimeStart},'%y%m%d') |
| | | AND finishtime >= DATE(#{finishtimeStart}) |
| | | </if> |
| | | <if test="finishtimeEnd != null"> |
| | | AND date_format(finishtime,'%y%m%d') <= date_format(#{finishtimeEnd},'%y%m%d') |
| | | AND finishtime < DATE_ADD(DATE(#{finishtimeEnd}), INTERVAL 1 DAY) |
| | | </if> |
| | | <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> |
| | | <!-- |
| | | 科室/病区筛选(2026-11 修订): |
| | | 离院组(leaveldeptcodes / leavehospitaldistrictcodes)保持原逻辑; |
| | | 在院组(deptcodes / hospitaldistrictcodes → deptcode / hospitaldistrictcode)是新增的一组; |
| | | 组内按 deptOrDistrict 取 AND('1') / OR('2'),两组之间 AND(只传一组时另一组不拼)。 |
| | | --> |
| | | <if test='deptOrDistrict == "1"'> |
| | | <include refid="filterLeaveDimAnd"/> |
| | | <include refid="filterInhospDimAnd"/> |
| | | </if> |
| | | <if test="deptOrDistrict==2"> |
| | | AND (1=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"> |
| | | OR deptcode IN |
| | | <foreach collection="leaveldeptcodes" item="leaveldeptcode" open="(" separator="," |
| | | close=")"> |
| | | #{leaveldeptcode} |
| | | </foreach> |
| | | </if> |
| | | ) |
| | | <if test='deptOrDistrict == "2"'> |
| | | <include refid="filterLeaveDimOr"/> |
| | | <include refid="filterInhospDimOr"/> |
| | | </if> |
| | | <if test="visitCount != null and visitCount > 1 and visitDeptCodes != null and visitDeptCodes.size() > 0"> |
| | | AND visit_dept_code IN |
| | |
| | | AND templatename LIKE CONCAT('%', #{templatename}, '%') |
| | | </if> |
| | | <if test="startOutHospTime != null"> |
| | | AND DATE_FORMAT(endtime,'%y%m%d') >= DATE_FORMAT(#{startOutHospTime},'%y%m%d') |
| | | AND endtime >= DATE(#{startOutHospTime}) |
| | | </if> |
| | | <if test="endOutHospTime != null"> |
| | | AND DATE_FORMAT(endtime,'%y%m%d') <= DATE_FORMAT(#{endOutHospTime},'%y%m%d') |
| | | AND endtime < DATE_ADD(DATE(#{endOutHospTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <if test="startSendDateTime != null"> |
| | | AND DATE_FORMAT(visit_time,'%y%m%d') >= DATE_FORMAT(#{startSendDateTime},'%y%m%d') |
| | | AND visit_time >= DATE(#{startSendDateTime}) |
| | | </if> |
| | | <if test="endSendDateTime != null"> |
| | | AND DATE_FORMAT(visit_time,'%y%m%d') <= DATE_FORMAT(#{endSendDateTime},'%y%m%d') |
| | | AND visit_time < DATE_ADD(DATE(#{endSendDateTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <if test="longSendTime != null"> |
| | | AND DATE_FORMAT(long_send_time,'%y%m%d') <= DATE_FORMAT(#{longSendTime},'%y%m%d') |
| | | AND long_send_time < DATE_ADD(DATE(#{longSendTime}), INTERVAL 1 DAY) |
| | | </if> |
| | | <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="deptcode != null and deptcode != ''"> |
| | | AND deptcode = #{deptcode} |
| | | <!-- 2026-11:这里原本还有一份与上方 deptOrDistrict==1 完全重复的病区/科室条件, |
| | | 已删除(条件改用 filterSubtaskWardDim / filterSubtaskDeptDim 片段,避免两份口径不一致) --> |
| | | <if test="leaveldeptcode != null and leaveldeptcode != ''"> |
| | | AND leaveldeptcode = #{leaveldeptcode} |
| | | </if> |
| | | <if test="sendstate != null"> |
| | | AND sendstate = #{sendstate} |
| | |
| | | <foreach collection="sendstates" item="state" open="(" separator="," close=")"> |
| | | #{state} |
| | | </foreach> |
| | | </if> |
| | | <if test="currentPreachforms != null and currentPreachforms != ''"> |
| | | AND FIND_IN_SET(<include refid="effectiveCurrentPreachformExpr"/>, #{currentPreachforms}) |
| | | </if> |
| | | <if test="orgid != null and orgid != ''"> |
| | | AND orgid = #{orgid} |
| | |
| | | AND date_format( visit_time, '%y%m%d' ) <= date_format(#{endDate},'%y%m%d') |
| | | </if> |
| | | <if test="deptcodeList != null and deptcodeList.size()>0"> |
| | | and deptcode in |
| | | and leaveldeptcode in |
| | | <foreach collection="deptcodeList" item="deptcode" open="(" separator="," close=")"> |
| | | #{deptcode} |
| | | </foreach> |
| | | </if> |
| | | </select> |
| | | |
| | | <!-- |
| | | 当前登录人「待处理」随访任务,按出院年月(endtime)分组统计,出院随访 / 门诊随访分开计数。 |
| | | 口径(与随访列表「待随访」页签一致): |
| | | 1) 出院随访 service_type = '2',门诊随访 service_type = '3' |
| | | 2) 统计状态 → sendstate IN (1,2,3,7):1 被领取 / 2 待发送 / 3 已发送 / 7 超时 |
| | | (不含 4 不执行、5 发送失败、6 已完成) |
| | | 3) 出院满 7 天 → endtime < (今天 - 7 天) + 1 天, |
| | | 即「7 天前那一天」出院的也计入(用 <= DATE_SUB(...) 只会截到当天 0 点,会漏掉 9 条) |
| | | 4) 只看最近 4 个出院月份(含当月)→ endtime >= 当月往前推 3 个月的 1 号 |
| | | 5) 科室/病区权限用 OR(与列表 deptOrDistrict=2 一致): |
| | | 只有病区权限的用户,任务 leaveldeptcode 与本人科室对不上时也能量到, |
| | | 否则会把整月数据过滤成 0。 |
| | | 说明:GROUP BY 只产出有数据的月份,前端按「当月 + 前 3 个月」补齐,没数据就显示 0 个。 |
| | | 不再限制 current_preachform(人工):该字段只是执行方式, |
| | | 待随访任务里还有短信等方式,限定 '1' 会漏数。 |
| | | --> |
| | | <select id="countPendingManualTaskByMonth" |
| | | parameterType="com.ruoyi.task.domain.entity.ServiceSubtaskEntity" |
| | | resultType="java.util.Map"> |
| | | SELECT DATE_FORMAT(endtime, '%Y-%m') AS month, |
| | | SUM(CASE WHEN service_type = '2' THEN 1 ELSE 0 END) AS dischargeCnt, |
| | | SUM(CASE WHEN service_type = '3' THEN 1 ELSE 0 END) AS outpatientCnt |
| | | FROM service_subtask |
| | | WHERE del_flag = '0' |
| | | AND service_type IN ('2', '3') |
| | | <!-- 浮窗「待处理随访任务」口径:1 被领取 / 2 待发送 / 3 已发送 / 7 超时 --> |
| | | AND sendstate IN (1, 2, 3, 7) |
| | | AND endtime IS NOT NULL |
| | | AND endtime < DATE_ADD(DATE_SUB(CURDATE(), INTERVAL 7 DAY), INTERVAL 1 DAY) |
| | | AND endtime >= DATE_FORMAT(DATE_SUB(CURDATE(), INTERVAL 3 MONTH), '%Y-%m-01') |
| | | <if test="orgid != null and orgid != ''"> |
| | | AND orgid = #{orgid} |
| | | </if> |
| | | <if test="campusid != null and campusid != ''"> |
| | | AND campusid = #{campusid} |
| | | </if> |
| | | <!-- 离院科室/病区:有科室按科室、有病区按病区,两者都有时取 OR --> |
| | | <include refid="filterLeaveDimOr"/> |
| | | GROUP BY DATE_FORMAT(endtime, '%Y-%m') |
| | | ORDER BY month |
| | | </select> |
| | | |
| | | <select id="getCurrentUserServiceSubtaskCount" parameterType="com.ruoyi.task.domain.entity.ServiceSubtaskEntity" |
| | |
| | | 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 > NOW() |
| | | AND t.soon_deadline <= 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="campusid != null and campusid != ''"> |
| | | and campusid = #{campusid} |
| | | and ss.campusid = #{campusid} |
| | | </if> |
| | | <if test="leavehospitaldistrictcodes != null and leavehospitaldistrictcodes.size() > 0"> |
| | | AND leavehospitaldistrictcode IN |
| | | <foreach collection="leavehospitaldistrictcodes" item="leavehospitaldistrictcode" open="(" |
| | | separator="," |
| | | close=")"> |
| | | #{leavehospitaldistrictcode} |
| | | </foreach> |
| | | <!-- 离院科室/病区:有科室按科室、有病区按病区,两者都有时取 OR(原写法 1=1 会让筛选失效) --> |
| | | <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.leaveldeptcode 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> |
| | | ) t |
| | | </select> |
| | | |
| | | <!-- |
| | |
| | | parameterType="com.ruoyi.task.domain.VO.ServiceSubtaskCotinueCountVO" |
| | | resultType="java.util.Map"> |
| | | SELECT |
| | | deptcode AS groupCode, |
| | | deptname AS groupName, |
| | | leaveldeptcode AS groupCode, |
| | | leaveldeptname AS groupName, |
| | | SUM(CASE WHEN continue_flag = 1 THEN 1 ELSE 0 END) AS noContinueCnt, |
| | | SUM(CASE WHEN continue_flag = 2 THEN 1 ELSE 0 END) AS continueCnt |
| | | FROM service_subtask |
| | | WHERE del_flag = 0 |
| | | AND continue_flag IN (1, 2) |
| | | AND deptcode IS NOT NULL AND deptcode != '' |
| | | AND leaveldeptcode IS NOT NULL AND leaveldeptcode != '' |
| | | <if test="orgid != null and orgid != ''"> |
| | | AND orgid = #{orgid} |
| | | </if> |
| | |
| | | AND campusid = #{campusid} |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND deptcode IN |
| | | AND leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="code" open="(" separator="," close=")"> |
| | | #{code} |
| | | </foreach> |
| | | </if> |
| | | GROUP BY deptcode, deptname |
| | | GROUP BY leaveldeptcode, leaveldeptname |
| | | ORDER BY groupCode |
| | | </select> |
| | | |
| | |
| | | leavehospitaldistrictname AS groupName, |
| | | </when> |
| | | <otherwise> |
| | | deptcode AS groupCode, |
| | | deptname AS groupName, |
| | | leaveldeptcode AS groupCode, |
| | | leaveldeptname AS groupName, |
| | | </otherwise> |
| | | </choose> |
| | | COUNT(*) AS totalCount, |
| | |
| | | </when> |
| | | <otherwise> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND deptcode IN |
| | | AND leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="code" open="(" separator="," close=")"> |
| | | #{code} |
| | | </foreach> |
| | | </if> |
| | | GROUP BY deptcode, deptname |
| | | GROUP BY leaveldeptcode, leaveldeptname |
| | | ORDER BY groupCode |
| | | </otherwise> |
| | | </choose> |
| | |
| | | drname, |
| | | leavehospitaldistrictcode, |
| | | leavehospitaldistrictname, |
| | | deptcode, |
| | | deptname, |
| | | leaveldeptcode, |
| | | leaveldeptname, |
| | | sendstate, |
| | | preachform, |
| | | current_preachform, |
| | |
| | | continue_count, |
| | | continue_time_next, |
| | | task_situation, |
| | | remark |
| | | remark, |
| | | doctor_opinion |
| | | from service_subtask |
| | | where 1=1 |
| | | and del_flag = 0 |
| | |
| | | </foreach> |
| | | </if> |
| | | <if test="deptcodes != null and deptcodes.size() > 0"> |
| | | AND deptcode IN |
| | | AND leaveldeptcode IN |
| | | <foreach collection="deptcodes" item="deptcode" open="(" separator="," |
| | | close=")"> |
| | | #{deptcode} |