已修改7个文件
402 ■■■■■ 文件已修改
ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/PatMedInhospController.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/ServiceSubtaskController.java 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java 168 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/domain/PatMedRes.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/java/com/smartor/domain/ServiceSubtaskVO.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/resources/mapper/smartor/PatMedInhospMapper.xml 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/PatMedInhospController.java
@@ -10,7 +10,6 @@
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.service.ISysConfigService;
import com.smartor.domain.PatMedInhosp;
import com.smartor.domain.PatMedInhospVO;
import com.smartor.domain.PatMedReq;
@@ -42,11 +41,6 @@
    @Autowired
    private IPatMedOuthospService iPatMedOuthospService;
    //todo
    @Autowired
    private ISysConfigService configService;
    /**
     * 查询患者住院记录列表
@@ -107,6 +101,9 @@
        return success(patMedInhospService.getDeptCodeByPatId(patMedInhosp));
    }
    /**
     * 查询出、入院看病人次和人数(人数分为首次服务、再次服务、专病服务)
     */
    @PostMapping("/selectPatMedInhospListCount")
    @ApiOperation("查询出、入院看病人次和人数")
    public AjaxResult selectPatMedInhospListCount(@RequestBody PatMedReq patMedReq) {
@@ -212,11 +209,4 @@
//        }
//    }
    @ApiOperation("测试定时任务dealOutHospInfo")
    @PostMapping("/dealOutHospInfo")
    public void dealOutHospInfo() {
        String config = configService.selectConfigByKey("visit.early.day");
        //出院表
        patMedInhospService.dealOutHospInfo(config);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/ServiceSubtaskController.java
@@ -2,6 +2,8 @@
import com.github.pagehelper.ISelect;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.constant.CacheConstants;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
@@ -15,6 +17,8 @@
import com.ruoyi.common.utils.DtoConversionUtils;
import com.ruoyi.common.utils.PageUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.reflect.ReflectUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.smartor.domain.*;
import com.smartor.mapper.PatMedInhospMapper;
import com.smartor.mapper.PatMedOuthospMapper;
@@ -27,6 +31,7 @@
import lombok.extern.slf4j.Slf4j;
import net.bytebuddy.implementation.bytecode.Throw;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
@@ -39,6 +44,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
/**
@@ -63,6 +69,9 @@
    @Value("${spring.profiles.active}")
    private String active;
    @Autowired
    private RedisCache redisCache;
    /**
     * 查询患者随访信息
@@ -90,7 +99,17 @@
            ServiceTask serviceTask = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
            if (ObjectUtils.isNotEmpty(serviceTask)) serviceSubtask.setPreachform(serviceTask.getPreachform());
        }
        Map<String, Object> map = serviceSubtaskService.patItemCount(serviceSubtaskVO);
        /**
         * 代码优化 分离统计
        Map<String, Object> map = new HashMap<>();
        map.put("serviceSubtaskList", serviceSubtaskList);
        List<Map<String, Object>> list = new ArrayList<>();
        list.add(map);
         **/
        //Map<String, Object> map = serviceSubtaskService.patItemCount(serviceSubtaskVO);
        //patItemCount 调用redisCache记录统计数据
        Map<String, Object> map = patItemCount(serviceSubtaskVO);
        map.put("serviceSubtaskList", serviceSubtaskList);
        List<Map<String, Object>> list = new ArrayList<>();
        list.add(map);
@@ -104,6 +123,69 @@
            }
        });
        return getDataTable2(total, list);
    }
    /**
     * 统计随访数据
     */
    @ApiOperation("统计随访数据")
    @PostMapping("/patItemCount")
    public Map<String, Object> patItemCount(@RequestBody ServiceSubtaskVO serviceSubtaskVO) {
        Map<String, Object> map = new HashMap<>();
        // 通过redis记录结果
        Map<String, Object> redisMap = new HashMap<>();
        LoginUser loginUser = getLoginUser();
        SysUser user = null;
        Long userId = null;
        if(ObjectUtils.isNotEmpty(loginUser)){
            user = loginUser.getUser();
            if(ObjectUtils.isNotEmpty(user)){
                userId = user.getUserId();
            }
        }
        if(ObjectUtils.isNotEmpty(userId)){
            redisMap = redisCache.getCacheObject(userId + "patItemCount");
            //记录是否有可用缓存
            Boolean redisFlag = false;
            ServiceSubtaskVO oldCondition = null;
            if(MapUtils.isNotEmpty(redisMap)){
                oldCondition = (ServiceSubtaskVO)redisMap.get("searchCondition");
                // 比较查询条件是否一致
                if(ObjectUtils.isNotEmpty(oldCondition) &&
                        isSameCondition(oldCondition, serviceSubtaskVO)){
                    // 条件一致,使用缓存
                    redisFlag = true;
                    map = redisMap;
                    redisCache.setCacheObject(userId + "patItemCount", map, 120, TimeUnit.MINUTES);
                }
            }
            // 如果没有缓存或者条件不一致,重新查询
            if(!redisFlag){
                map = serviceSubtaskService.patItemCount(serviceSubtaskVO);
                map.put("searchCondition", serviceSubtaskVO);
                redisCache.setCacheObject(userId + "patItemCount", map, 120, TimeUnit.MINUTES);
            }
        }
        map.put("code", HttpStatus.SUCCESS);
        return map;
    }
    /**
     * 比较两个ServiceSubtaskVO的查询条件是否一致
     * 使用反射比较所有字段,排除分页参数和无关字段
     */
    private boolean isSameCondition(ServiceSubtaskVO oldCondition, ServiceSubtaskVO newCondition) {
        // 使用ReflectUtils的通用方法比较,排除分页参数等无关字段
        return ReflectUtils.equalsAllFields(
                oldCondition,
                newCondition,
                // 排除的字段:分页参数、序列化ID、时间戳等
                "pageNum", "pageSize", "serialVersionUID",
                "createBy", "createTime", "updateBy", "updateTime",
                "searchValue", "params"
        );
    }
@@ -152,7 +234,9 @@
            serviceSubtaskRecord.setTaskid(serviceSubtask.getTaskid().toString());
            serviceSubtask.setServiceSubtaskRecordList(serviceSubtaskRecordService.selectServiceSubtaskRecordList(serviceSubtaskRecord));
        }
        //todo 代码优化
        Map<String, Object> map = serviceSubtaskService.patItemCount(serviceSubtaskVO);
//        Map<String, Object> map = patItemCount(serviceSubtaskVO);
        map.put("serviceSubtaskList", serviceSubtaskList);
        List<Map<String, Object>> list = new ArrayList<>();
        list.add(map);
ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java
@@ -6,7 +6,13 @@
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.poi.ss.usermodel.DateUtil;
@@ -407,4 +413,166 @@
        }
        return new RuntimeException(msg, e);
    }
    /**
     * 比较两个相同类型对象的所有字段值是否相等
     * 使用反射获取所有字段(包括父类字段),并逐个比较
     *
     * @param obj1 第一个对象
     * @param obj2 第二个对象
     * @return 如果所有字段值都相等返回true,否则返回false
     * *示例1:比较所有字段
     *      *   boolean result = ReflectUtils.equalsAllFields(user1, user2);
     */
    public static boolean equalsAllFields(Object obj1, Object obj2)
    {
        return equalsAllFields(obj1, obj2, new String[]{});
    }
    /**
     * 比较两个相同类型对象的所有字段值是否相等(可排除指定字段)
     * 使用反射获取所有字段(包括父类字段),并逐个比较
     *
     * @param obj1 第一个对象
     * @param obj2 第二个对象
     * @param excludeFields 要排除的字段名称数组
     * @return 如果所有字段值都相等返回true,否则返回false
     * // 示例2:排除分页参数
     *      *   boolean result = ReflectUtils.equalsAllFields(vo1, vo2, "pageNum", "pageSize");
     */
    public static boolean equalsAllFields(Object obj1, Object obj2, String... excludeFields)
    {
        // 两个对象都为null,认为相等
        if (obj1 == null && obj2 == null) return true;
        // 只有一个为null,不相等
        if (obj1 == null || obj2 == null) return false;
        // 如果是同一个对象引用,直接返回true
        if (obj1 == obj2) return true;
        // 类型不同,不相等
        if (!obj1.getClass().equals(obj2.getClass())) return false;
        // 将排除字段转换为Set,便于快速查找
        Set<String> excludeFieldSet = new HashSet<>(Arrays.asList(excludeFields));
        // 获取所有字段(包括父类字段)
        List<Field> allFields = getAllFields(obj1);
        // 逐个比较字段值
        for (Field field : allFields)
        {
            // 跳过排除的字段
            if (excludeFieldSet.contains(field.getName())) continue;
            // 跳过static和transient字段
            if (Modifier.isStatic(field.getModifiers()) || Modifier.isTransient(field.getModifiers()))
            {
                continue;
            }
            try{
                makeAccessible(field);
                Object value1 = field.get(obj1);
                Object value2 = field.get(obj2);
                // 使用Objects.equals进行比较,可以正确处理null值
                if (!Objects.equals(value1, value2))
                {
                    //logger.debug("字段 [{}] 的值不相等: obj1={}, obj2={}", field.getName(), value1, value2);
                    return false;
                }
            }catch (IllegalAccessException e)
            {
                //logger.error("访问字段 [{}] 时发生错误: {}", field.getName(), e.getMessage());
                return false;
            }
        }
        return true;
    }
    /**
     * 获取对象的所有字段(包括父类字段)
     *
     * @param obj 目标对象
     * @return 所有字段的列表
     */
    public static List<Field> getAllFields(Object obj)
    {
        List<Field> allFields = new ArrayList<>();
        Class<?> clazz = obj.getClass();
        // 循环向上遍历父类,获取所有字段
        while (clazz != null && clazz != Object.class)
        {
            Field[] fields = clazz.getDeclaredFields();
            allFields.addAll(Arrays.asList(fields));
            clazz = clazz.getSuperclass();
        }
        return allFields;
    }
    /**
     * 比较两个对象指定字段的值是否相等
     *
     * @param obj1 第一个对象
     * @param obj2 第二个对象
     * @param includeFields 要比较的字段名称数组
     * @return 如果指定字段值都相等返回true,否则返回false
     *
     *   // 示例3:只比较关键字段
     *   boolean result = ReflectUtils.equalsSpecifiedFields(user1, user2, "userId", "userName", "email");
     */
    public static boolean equalsSpecifiedFields(Object obj1, Object obj2, String... includeFields)
    {
        // 两个对象都为null,认为相等
        if (obj1 == null && obj2 == null) return true;
        // 只有一个为null,不相等
        if (obj1 == null || obj2 == null) return false;
        // 如果是同一个对象引用,直接返回true
        if (obj1 == obj2) return true;
        // 类型不同,不相等
        if (!obj1.getClass().equals(obj2.getClass())) return false;
        // 如果没有指定字段,返回true
        if (includeFields == null || includeFields.length == 0) return true;
        // 逐个比较指定字段的值
        for (String fieldName : includeFields)
        {
            Field field = getAccessibleField(obj1, fieldName);
            if (field == null)
            {
                //logger.warn("在 [{}] 中未找到字段 [{}]", obj1.getClass().getName(), fieldName);
                continue;
            }
            try
            {
                makeAccessible(field);
                Object value1 = field.get(obj1);
                Object value2 = field.get(obj2);
                // 使用Objects.equals进行比较,可以正确处理null值
                if (!Objects.equals(value1, value2))
                {
                    //logger.debug("字段 [{}] 的值不相等: obj1={}, obj2={}", fieldName, value1, value2);
                    return false;
                }
            }
            catch (IllegalAccessException e)
            {
                //logger.error("访问字段 [{}] 时发生错误: {}", fieldName, e.getMessage());
                return false;
            }
        }
        return true;
    }
}
smartor/src/main/java/com/smartor/domain/PatMedRes.java
@@ -35,4 +35,21 @@
    @ApiModelProperty(value = "人数")
    private Integer rs;
    /**
     * 首次随访人数
     */
    @ApiModelProperty(value = "首次随访人数")
    private Integer scsf;
    /**
     * 再次随访人数
     */
    @ApiModelProperty(value = "再次随访人数")
    private Integer zcsf;
    /**
     * 专病随访人数
     */
    @ApiModelProperty(value = "专病随访人数")
    private Integer zbsf;
}
smartor/src/main/java/com/smartor/domain/ServiceSubtaskVO.java
@@ -734,4 +734,10 @@
    @ApiModelProperty(value = "随访部门编码集合")
    private List<String> visitDeptCodes;
//    /**
//     * 日期限制 目前由前端控制
//     */
//    @ApiModelProperty(value = "日期限制:0全部服务    1截止当前日期")
//    private String dateLimit;
}
smartor/src/main/resources/mapper/smartor/PatMedInhospMapper.xml
@@ -920,11 +920,18 @@
    <select id="selectPatMedInhospCount" parameterType="com.smartor.domain.PatMedReq"
            resultType="com.smartor.domain.PatMedRes">
        SELECT SUM( rs ) AS rs,
        SUM( rc ) AS rc
        SUM( rc ) AS rc,
        SUM( scsf ) AS scsf,
        SUM( zcsf ) AS zcsf,
        SUM( zbsf ) AS zbsf
        FROM (
        <!-- 出院人次-->
        SELECT
        COUNT(1) AS rc,
        0 AS rs
        0 AS rs,
        0 AS scsf,
        0 AS zcsf,
        0 AS zbsf
        FROM
        pat_med_inhosp
        <where>
@@ -954,12 +961,15 @@
                    </foreach>
                </if>
            </if>
        </where>
        <!-- 随访服务人数 -->
        union all
        select
        0 AS rc,
        count(1) AS rs
        count(1) AS rs,
        0 AS scsf,
        0 AS zcsf,
        0 AS zbsf
        FROM
        service_subtask
        <where>
@@ -981,6 +991,96 @@
                </foreach>
            </if>
        </where>
        <!-- 首次随访人数 -->
        union all
        select
        0 AS rc,
        0 AS rs,
        count(1) AS scsf,
        0 AS zcsf,
        0 AS zbsf
        FROM
        service_subtask
        <where>
            del_flag = 0
            and service_type=2
            and is_visit_again = 0
            <if test="orgid != null">
                AND orgid = #{orgid}
            </if>
            <if test="startDate != null">
                AND date_format( visit_time, '%y%m%d' ) &gt;= date_format( #{startDate}, '%y%m%d' )
            </if>
            <if test="endDate != null">
                AND date_format( visit_time, '%y%m%d' ) &lt;= date_format(#{endDate},'%y%m%d')
            </if>
            <if test="deptcodeList != null   and deptcodeList.size() > 0">
                and deptcode in
                <foreach collection="deptcodeList" item="deptcode" open="(" separator="," close=")">
                    #{deptcode}
                </foreach>
            </if>
        </where>
        <!-- 再次随访人数 -->
        union all
        select
        0 AS rc,
        0 AS rs,
        0 AS scsf,
        count(1) AS zcsf,
        0 AS zbsf
        FROM
        service_subtask
        <where>
            del_flag = 0
            and service_type=2
            and is_visit_again = 1
            <if test="orgid != null">
                AND orgid = #{orgid}
            </if>
            <if test="startDate != null">
                AND date_format( visit_time, '%y%m%d' ) &gt;= date_format( #{startDate}, '%y%m%d' )
            </if>
            <if test="endDate != null">
                AND date_format( visit_time, '%y%m%d' ) &lt;= date_format(#{endDate},'%y%m%d')
            </if>
            <if test="deptcodeList != null   and deptcodeList.size() > 0">
                and deptcode in
                <foreach collection="deptcodeList" item="deptcode" open="(" separator="," close=")">
                    #{deptcode}
                </foreach>
            </if>
        </where>
        <!-- 专病随访人数 -->
        union all
        select
        0 AS rc,
        0 AS rs,
        0 AS scsf,
        0 AS zcsf,
        count(1) AS zbsf
        FROM
        service_subtask
        <where>
            del_flag = 0
            and service_type=13
            <if test="orgid != null">
                AND orgid = #{orgid}
            </if>
            <if test="startDate != null">
                AND date_format( visit_time, '%y%m%d' ) &gt;= date_format( #{startDate}, '%y%m%d' )
            </if>
            <if test="endDate != null">
                AND date_format( visit_time, '%y%m%d' ) &lt;= date_format(#{endDate},'%y%m%d')
            </if>
            <if test="deptcodeList != null   and deptcodeList.size() > 0">
                and deptcode in
                <foreach collection="deptcodeList" item="deptcode" open="(" separator="," close=")">
                    #{deptcode}
                </foreach>
            </if>
        </where>
        ) AS combined_data
    </select>
</mapper>
smartor/src/main/resources/mapper/smartor/ServiceSubtaskMapper.xml
@@ -369,6 +369,7 @@
            <if test="taskGuid != null">and task_guid = #{taskGuid}</if>
            <if test="isabnormal != null">and isabnormal = #{isabnormal}</if>
            <if test="isVisitAgain != null">and is_visit_again = #{isVisitAgain}</if>
<!--            <if test="dateLimit != null and dateLimit = '1'"> and CURDATE() + 1 > long_send_time</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>-->