xuhy
2026-01-06 3d8e6a16f98bc01d3cee3a2733fa9a4eff8db2c7
海诊通AI对接,双屏仪报告推送存储
6个文件已添加
13个文件已修改
731 ■■■■■ 已修改文件
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCrmClinicController.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TSysInspectionController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TSysInspectionRiskEstimateController.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/H5AICallbackController.java 248 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TSysAppUserController.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/WxLoginController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TSysInspectionRiskEstimateMapper.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TCrmClinic.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TSysInspection.java 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/TSysInspectionRiskEstimate.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/TSysInspectionRiskEstimateService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TSysInspectionRiskEstimateServiceImpl.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/utils/util/TemplateMessageSendUtil.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletUserEncrypteData.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxAppletTools.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TCrmClinicMapper.xml 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TSysInspectionMapper.xml 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/TSysInspectionRiskEstimateMapper.xml 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TCrmClinicController.java
@@ -7,8 +7,11 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.constant.WxConstant;
import com.ruoyi.common.core.controller.FileController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.WebUtils;
@@ -23,20 +26,31 @@
import com.ruoyi.system.query.TCrmChangePointsQuery;
import com.ruoyi.system.query.TCrmClinicQuery;
import com.ruoyi.system.service.*;
import com.ruoyi.system.utils.util.ObsUploadUtil;
import com.ruoyi.system.utils.wx.model.WeixinProperties;
import com.ruoyi.system.utils.wx.tools.WxAppletTools;
import com.ruoyi.system.utils.xiMaUtil.XimaAIUtil;
import com.ruoyi.system.vo.TCrmClinicVO;
import com.ruoyi.system.vo.TSysAppUserVO;
import com.ruoyi.web.controller.tool.MsgUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
@@ -51,6 +65,7 @@
 * @author xiaochen
 * @since 2025-08-20
 */
@Slf4j
@Api(tags = "crm诊所管理")
@RestController
@RequestMapping("/t-crm-clinic")
@@ -66,8 +81,11 @@
    private final TokenService tokenService;
    private final MsgUtils msgUtils;
    private final TSysMessageTemplateService sysMessageTemplateService;
    private final RedisCache redisCache;
    private final RestTemplate restTemplate;
    private final WeixinProperties wxConfig;
    @Autowired
    public TCrmClinicController(TCrmClinicService crmClinicService, TCrmSupplierService crmSupplierService, TCrmBranchService crmBranchService, TCrmWarehouseService crmWarehouseService, TCrmSalespersonService crmSalespersonService, ISysUserService sysUserService, TCrmDeviceService crmDeviceService, TokenService tokenService, MsgUtils msgUtils, TSysMessageTemplateService sysMessageTemplateService) {
    public TCrmClinicController(TCrmClinicService crmClinicService, TCrmSupplierService crmSupplierService, TCrmBranchService crmBranchService, TCrmWarehouseService crmWarehouseService, TCrmSalespersonService crmSalespersonService, ISysUserService sysUserService, TCrmDeviceService crmDeviceService, TokenService tokenService, MsgUtils msgUtils, TSysMessageTemplateService sysMessageTemplateService, RedisCache redisCache, RestTemplate restTemplate, WeixinProperties wxConfig) {
        this.crmClinicService = crmClinicService;
        this.crmSupplierService = crmSupplierService;
        this.crmBranchService = crmBranchService;
@@ -78,6 +96,9 @@
        this.tokenService = tokenService;
        this.msgUtils = msgUtils;
        this.sysMessageTemplateService = sysMessageTemplateService;
        this.redisCache = redisCache;
        this.restTemplate = restTemplate;
        this.wxConfig = wxConfig;
    }
    /**
@@ -180,14 +201,37 @@
    @Log(title = "crm诊所管理信息-新增crm诊所管理", businessType = BusinessType.INSERT)
    @ApiOperation(value = "添加crm诊所管理")
    @PostMapping(value = "/add")
    public R<Boolean> add(@Validated @RequestBody TCrmClinicDTO dto) {
    public R<String> add(@Validated @RequestBody TCrmClinicDTO dto) {
        Integer roleType = tokenService.getLoginUser().getUser().getRoleType();
        if (roleType == 1){
            dto.setStatus(3);
        }else {
            dto.setStatus(1);
        }
        return crmClinicService.addClinic(dto);
        WxAppletTools wxAppletTools = new WxAppletTools(restTemplate, wxConfig, redisCache);
        // 获取access_token
        String accessToken = wxAppletTools.getAccessToken();
        // 替换CREATE_CODE_URL
        String url = WxConstant.CREATE_CODE_URL.replace("ACCESS_TOKEN", accessToken);
        // 发送请求
        try {
            HashMap<String, String> map = new HashMap<>();
            map.put("path", "");
            map.put("scene", "clinicId=" + dto.getId());
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity requestEntity = new HttpEntity(map, headers);
            ResponseEntity<byte[]> rep = restTemplate.exchange(url, HttpMethod.POST, requestEntity, byte[].class);
            byte[] bytes = rep.getBody();
            ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
            MultipartFile file = new MockMultipartFile(ContentType.APPLICATION_OCTET_STREAM.toString(), byteArrayInputStream);
            String stringApiResult = ObsUploadUtil.obsUpload(file);
            dto.setQrCode(stringApiResult);
        } catch (Exception e) {
            log.error("生成小程序码失败:{}", e.getMessage());
        }
        crmClinicService.addClinic(dto);
        return R.ok();
    }
    /**
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TSysInspectionController.java
@@ -80,12 +80,12 @@
        TCrmClinic crmClinic = crmClinicService.getOne(Wrappers.lambdaQuery(TCrmClinic.class)
                .eq(TCrmClinic::getUserId, userId)
                .last("LIMIT 1"));
        // ---
        if(Objects.isNull(crmClinic)){
            SysUser sysUser = sysUserService.selectUserById(userId);
            crmClinic = crmClinicService.getById(sysUser.getObjectId());
        }
        dto.setClinicId(crmClinic.getId());
        dto.setInspectionType(1);
        return R.ok(sysInspectionService.save(dto));
    }
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TSysInspectionRiskEstimateController.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.web.controller.api;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * <p>
 * 报告疾病风险 前端控制器
 * </p>
 *
 * @author xiaochen
 * @since 2026-01-06
 */
@RestController
@RequestMapping("/t-sys-inspection-risk-estimate")
public class TSysInspectionRiskEstimateController {
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/H5AICallbackController.java
@@ -1,29 +1,27 @@
package com.ruoyi.web.controller.api;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.model.TSysAiConfig;
import com.ruoyi.system.model.TSysAppUser;
import com.ruoyi.system.model.TSysInspection;
import com.ruoyi.system.model.TSysInspectionRiskEstimate;
import com.ruoyi.system.service.TSysAiConfigService;
import com.ruoyi.system.service.TSysAppUserService;
import com.ruoyi.system.service.TSysInspectionRiskEstimateService;
import com.ruoyi.system.service.TSysInspectionService;
import com.ruoyi.system.utils.util.AesSimpleUtil;
import com.ruoyi.system.utils.util.RsaSimpleUtil;
import com.ruoyi.system.utils.wx.model.WeixinProperties;
import com.ruoyi.system.utils.wx.tools.WxAppletTools;
import com.ruoyi.system.utils.xiMaUtil.AesUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
 * <p>
@@ -42,91 +40,94 @@
    private TSysAiConfigService sysAiConfigService;
    @Autowired
    private TSysInspectionService sysInspectionService;
    @Autowired
    private TSysAppUserService sysAppUserService;
    @Autowired
    private TSysInspectionRiskEstimateService sysInspectionRiskEstimateService;
    @PostMapping("/reportReturn")
    public String reportReturn(String encryptedJson, String signEncryptedJson) throws Exception {
        TSysAiConfig sysAiConfig = sysAiConfigService.getById(1);
        // 应用AES秘钥
        String aesKey = sysAiConfig.getAesKey();
        // 平台RSA公钥
        String rsaPublicKey = sysAiConfig.getRsaPublicKey();
        // 1. 先解密
        String source = AesSimpleUtil.decrypt(encryptedJson, aesKey);
        System.out.println("AI问诊回调数据=====:"+ source);
        JSONObject jsonObject = JSONObject.parseObject(source);
        // 2. 再验证签名
        String signSource = String.format("%s_%s",
                jsonObject.getString("thirdId"),
                jsonObject.getString("time"));
        boolean verify = RsaSimpleUtil.verify(signSource, signEncryptedJson, rsaPublicKey);
        if (!verify) {
            return "error";
        }
        // 3. 验证成功,则仅仅业务保存并返回success字符串
        /**
         * {
         *   "returnType": 1,
         *   "name": "张三",
         *   "phone": "13344445555",
         *   "email": null,
         *   "sex": 1,
         *   "age": 42,
         *   "time": "2023-03-08 08:23:13",
         *   "pdf": "https://labelsys-images.oss-cn-hangzhou.aliyuncs.com/tongueFile/check/2023/03/87d76220-085e-4d2e-9fd7-9f5a01da1940.pdf",
         *   "healthIndex": 100.0,
         *   "constitutionNames": "气虚",
         *   "symptomName": "胃气虚证",
         *   "thirdId": "13344445555",
         *   "tongueFeature": "正常人舌色,舌质淡红润泽。舌苔呈现白色。",
         *   "faceFeature": "面部颜色暗沉。"
         * }
         */
        Integer returnType = jsonObject.getInteger("returnType");
        String name = jsonObject.getString("name");
        String phone = jsonObject.getString("phone");
        String email = jsonObject.getString("email");
        Integer sex = jsonObject.getInteger("sex");
        Integer age = jsonObject.getInteger("age");
        String time = jsonObject.getString("time");
        String pdf = jsonObject.getString("pdf");
        Double healthIndex = jsonObject.getDouble("healthIndex");
        String constitutionNames = jsonObject.getString("constitutionNames");
        String symptomName = jsonObject.getString("symptomName");
        String thirdId = jsonObject.getString("thirdId");
        String tongueFeature = jsonObject.getString("tongueFeature");
        String faceFeature = jsonObject.getString("faceFeature");
        if(returnType == 2){
            log.info("用户["+phone+"]检测失败");
        }
        long count = sysInspectionService.count(Wrappers.lambdaQuery(TSysInspection.class)
                .eq(TSysInspection::getPersonPhone, phone)
                .eq(TSysInspection::getCheckTime, time));
        if (count == 0) {
            TSysInspection sysInspection = new TSysInspection();
            sysInspection.setPersonName(name);
            sysInspection.setPersonPhone(phone);
            sysInspection.setPersonSex(sex);
            sysInspection.setPersonAge(age);
            sysInspection.setCheckTime(time);
            sysInspection.setPdfUrl(pdf);
            sysInspection.setHealthIndex(healthIndex);
            sysInspection.setConstitutionNames(constitutionNames);
            sysInspection.setSymptomName(symptomName);
            sysInspection.setTongueFeature(tongueFeature);
            sysInspection.setFaceFeature(faceFeature);
            sysInspection.setAppUserId(thirdId);
            sysInspection.setInspectionType(2);
            sysInspection.setIsPay(0);
            sysInspectionService.save(sysInspection);
        }
        return "success";
    }
//    @PostMapping("/reportReturn")
//    public String reportReturn(String encryptedJson, String signEncryptedJson) throws Exception {
//        TSysAiConfig sysAiConfig = sysAiConfigService.getById(1);
//        // 应用AES秘钥
//        String aesKey = sysAiConfig.getAesKey();
//        // 平台RSA公钥
//        String rsaPublicKey = sysAiConfig.getRsaPublicKey();
//
//        // 1. 先解密
//        String source = AesSimpleUtil.decrypt(encryptedJson, aesKey);
//        System.out.println("AI问诊回调数据=====:"+ source);
//        JSONObject jsonObject = JSONObject.parseObject(source);
//
//        // 2. 再验证签名
//        String signSource = String.format("%s_%s",
//                jsonObject.getString("thirdId"),
//                jsonObject.getString("time"));
//        boolean verify = RsaSimpleUtil.verify(signSource, signEncryptedJson, rsaPublicKey);
//        if (!verify) {
//            return "error";
//        }
//        // 3. 验证成功,则仅仅业务保存并返回success字符串
//        /**
//         * {
//         *   "returnType": 1,
//         *   "name": "张三",
//         *   "phone": "13344445555",
//         *   "email": null,
//         *   "sex": 1,
//         *   "age": 42,
//         *   "time": "2023-03-08 08:23:13",
//         *   "pdf": "https://labelsys-images.oss-cn-hangzhou.aliyuncs.com/tongueFile/check/2023/03/87d76220-085e-4d2e-9fd7-9f5a01da1940.pdf",
//         *   "healthIndex": 100.0,
//         *   "constitutionNames": "气虚",
//         *   "symptomName": "胃气虚证",
//         *   "thirdId": "13344445555",
//         *   "tongueFeature": "正常人舌色,舌质淡红润泽。舌苔呈现白色。",
//         *   "faceFeature": "面部颜色暗沉。"
//         * }
//         */
//
//        Integer returnType = jsonObject.getInteger("returnType");
//        String name = jsonObject.getString("name");
//        String phone = jsonObject.getString("phone");
//        String email = jsonObject.getString("email");
//        Integer sex = jsonObject.getInteger("sex");
//        Integer age = jsonObject.getInteger("age");
//        String time = jsonObject.getString("time");
//        String pdf = jsonObject.getString("pdf");
//        Double healthIndex = jsonObject.getDouble("healthIndex");
//        String constitutionNames = jsonObject.getString("constitutionNames");
//        String symptomName = jsonObject.getString("symptomName");
//        String thirdId = jsonObject.getString("thirdId");
//        String tongueFeature = jsonObject.getString("tongueFeature");
//        String faceFeature = jsonObject.getString("faceFeature");
//
//        if(returnType == 2){
//            log.info("用户["+phone+"]检测失败");
//        }
//
//        long count = sysInspectionService.count(Wrappers.lambdaQuery(TSysInspection.class)
//                .eq(TSysInspection::getPersonPhone, phone)
//                .eq(TSysInspection::getCheckTime, time));
//        if (count == 0) {
//            TSysInspection sysInspection = new TSysInspection();
//            sysInspection.setPersonName(name);
//            sysInspection.setPersonPhone(phone);
//            sysInspection.setPersonSex(sex);
//            sysInspection.setPersonAge(age);
//            sysInspection.setCheckTime(time);
//            sysInspection.setPdfUrl(pdf);
//            sysInspection.setHealthIndex(healthIndex);
//            sysInspection.setConstitutionNames(constitutionNames);
//            sysInspection.setSymptomName(symptomName);
//            sysInspection.setTongueFeature(tongueFeature);
//            sysInspection.setFaceFeature(faceFeature);
//            sysInspection.setAppUserId(thirdId);
//            sysInspection.setInspectionType(2);
//            sysInspection.setIsPay(0);
//            sysInspectionService.save(sysInspection);
//        }
//        return "success";
//    }
@@ -149,6 +150,69 @@
    @PostMapping("/xiMaDoubleScreenReportPush")
    public JSONObject xiMaDoubleScreenReportPush(JSONObject jsonObject) throws Exception {
        log.info("双屏仪报告推送:{}",jsonObject);
        // 主体信息
        String reportTime = jsonObject.getString("report_time");
        String report_print_url = jsonObject.getString("report_print_url");
        String present_history = jsonObject.getString("present_history");
        String tcm_syndrome = jsonObject.getString("tcm_syndrome");
        String disease_history_memo = jsonObject.getString("disease_history_memo");
        String western_medicine_diagnosis = jsonObject.getString("western_medicine_diagnosis");
        TSysInspection sysInspection = new TSysInspection();
        sysInspection.setCheckTime(reportTime);
        sysInspection.setReportPrintUrl(report_print_url);
        sysInspection.setPresentHistory(present_history);
        sysInspection.setTcmSyndrome(tcm_syndrome);
        sysInspection.setDiseaseHistoryMemo(disease_history_memo);
        sysInspection.setWesternMedicineDiagnosis(western_medicine_diagnosis);
        // 用户信息
        JSONObject userInfo = jsonObject.getJSONObject("user_info");
        Long id = userInfo.getLong("id");
        String phone = userInfo.getString("phone");
        String user_name = userInfo.getString("user_name");
        Long device_account_id = userInfo.getLong("device_account_id");
        String sex = userInfo.getString("sex");
        String age = userInfo.getString("age");
        sysInspection.setThreeUserId(id);
        sysInspection.setPhone(phone);
        sysInspection.setNickName(user_name);
        sysInspection.setSex("男".equals(sex) ? 1 : 2);
        sysInspection.setAge(Integer.parseInt(age));
        sysInspection.setDeviceAccountId(device_account_id);
        sysInspection.setInspectionType(3);
        // 通过手机号查询小程序用户
        TSysAppUser sysAppUser = sysAppUserService.getOne(Wrappers.lambdaQuery(TSysAppUser.class)
                .eq(TSysAppUser::getPhone, phone)
                .last("LIMIT 1"));
        if(sysAppUser != null){
            sysInspection.setAppUserId(sysAppUser.getId());
            sysInspection.setClinicId(sysAppUser.getClinicId());
        }
        sysInspectionService.save(sysInspection);
        // 指脉结果
        JSONObject fingerPulseReport = jsonObject.getJSONObject("finger_pulse_report");
        JSONArray riskEstimate = fingerPulseReport.getJSONArray("risk_estimate");
        List<TSysInspectionRiskEstimate> sysInspectionRiskEstimates = new ArrayList<>();
        for (int i = 0; i < riskEstimate.size(); i++) {
            JSONObject json = riskEstimate.getJSONObject(i);
            TSysInspectionRiskEstimate sysInspectionRiskEstimate = new TSysInspectionRiskEstimate();
            sysInspectionRiskEstimate.setInspectionId(sysInspection.getId());
            String name = json.getString("name");
            String link_url = json.getString("link_url");
            String value = json.getString("value");
            String value_desc = json.getString("value_desc");
            sysInspectionRiskEstimate.setRiskName(name);
            sysInspectionRiskEstimate.setRiskLinkUrl(link_url);
            sysInspectionRiskEstimate.setRiskValue(value);
            sysInspectionRiskEstimate.setRiskValueDesc(value_desc);
            sysInspectionRiskEstimates.add(sysInspectionRiskEstimate);
        }
        sysInspectionRiskEstimateService.saveBatch(sysInspectionRiskEstimates);
        JSONObject response = new JSONObject();
        response.put("error_code",0);
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/TSysAppUserController.java
@@ -4,27 +4,29 @@
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.basic.PageInfo;
import com.ruoyi.common.core.controller.FileController;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.model.TCrmClinic;
import com.ruoyi.system.model.TSysAppUser;
import com.ruoyi.system.model.TSysChronicDisease;
import com.ruoyi.system.model.TSysInspection;
import com.ruoyi.system.query.TSysAppUserQuery;
import com.ruoyi.system.service.TSysAppUserService;
import com.ruoyi.system.service.TSysChronicDiseaseService;
import com.ruoyi.system.service.TSysInspectionService;
import com.ruoyi.system.service.TSysOrderService;
import com.ruoyi.system.service.*;
import com.ruoyi.system.utils.wx.model.WeixinProperties;
import com.ruoyi.system.utils.xiMaUtil.XimaAIUtil;
import com.ruoyi.system.vo.TSysAppUserVO;
import com.ruoyi.system.vo.TSysOrderVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import java.util.Arrays;
import java.util.List;
@@ -39,6 +41,7 @@
 * @author xiaochen
 * @since 2025-08-20
 */
@Slf4j
@Api(tags = "用户管理")
@RestController
@RequestMapping("/t-sys-app-user")
@@ -51,8 +54,12 @@
    private final TokenService tokenService;
    private final RedisCache redisCache;
    private final XimaAIUtil ximaAIUtil;
    private final RestTemplate restTemplate;
    private final FileController fileController;
    private final WeixinProperties wxConfig;
    private final TCrmClinicService crmClinicService;
    @Autowired
    public TSysAppUserController(TSysAppUserService sysAppUserService, TSysInspectionService sysInspectionService, TSysOrderService sysOrderService, TSysChronicDiseaseService sysChronicDiseaseService, TokenService tokenService, RedisCache redisCache, XimaAIUtil ximaAIUtil) {
    public TSysAppUserController(TSysAppUserService sysAppUserService, TSysInspectionService sysInspectionService, TSysOrderService sysOrderService, TSysChronicDiseaseService sysChronicDiseaseService, TokenService tokenService, RedisCache redisCache, XimaAIUtil ximaAIUtil, RestTemplate restTemplate, FileController fileController, WeixinProperties wxConfig, TCrmClinicService crmClinicService) {
        this.sysAppUserService = sysAppUserService;
        this.sysInspectionService = sysInspectionService;
        this.sysOrderService = sysOrderService;
@@ -60,6 +67,10 @@
        this.tokenService = tokenService;
        this.redisCache = redisCache;
        this.ximaAIUtil = ximaAIUtil;
        this.restTemplate = restTemplate;
        this.fileController = fileController;
        this.wxConfig = wxConfig;
        this.crmClinicService = crmClinicService;
    }
    /**
@@ -159,5 +170,21 @@
        return R.ok(authorizationH5);
    }
    @ApiOperation(value = "查询诊所邀请码[1229]")
    @GetMapping("/getClinicQrCode")
    public R<String> getClinicQrCode() {
        String userId = tokenService.getLoginUserApplet().getUserId();
        TSysAppUser sysAppUser = sysAppUserService.getById(userId);
        if(StringUtils.isBlank(sysAppUser.getClinicId())){
            return R.fail("请先绑定诊所");
        }
        TCrmClinic crmClinic = crmClinicService.getById(sysAppUser.getClinicId());
        if(Objects.isNull(crmClinic)){
            return R.fail("未找到该诊所信息");
        }
        return R.ok(crmClinic.getQrCode());
    }
}
ruoyi-applet/src/main/java/com/ruoyi/web/controller/api/WxLoginController.java
@@ -1,6 +1,7 @@
package com.ruoyi.web.controller.api;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.framework.web.service.SysLoginService;
import com.ruoyi.framework.web.service.TokenService;
@@ -35,6 +36,8 @@
    private RestTemplate wxRestTemplate;
    @Resource
    private RedisService redisService;
    @Resource
    private RedisCache redisCache;
    @Resource
    private TSysAppUserService sysAppUserService;
    @Resource
@@ -176,7 +179,7 @@
     */
    @PostMapping("/getWXToken")
    public R<String> getWXToken(){
        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig, redisService);
        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig, redisCache);
        String accessToken = appletTools.getAccessToken();
        return R.ok(accessToken);
    }
ruoyi-applet/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -118,7 +118,7 @@
    @PostMapping("/openIdByJsCode")
    public R<Map<String, Object>> openIdByJsCode(@RequestBody AppletUserEncrypteData data) {
        log.info("<<<<<<<<换取openid开始<<<<<<<<:{}", data.getCode());
        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig, redisService);
        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig, redisCache);
        Code2SessionRespBody body = appletTools.getOpenIdByJscode2session(new Code2SessionResqBody().build(data.getCode()));
        String openid = body.getOpenid();
        String sessionKey = body.getSessionKey();
@@ -143,6 +143,7 @@
            sysAppUser.setIdentifierNumber(identifierNumber);
            // 手机号中间四位替换为*
            sysAppUser.setNickName(appletUserDecodeData.getPhoneNumber().replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2"));
            sysAppUser.setClinicId(data.getClinicId());
            sysAppUserService.save(sysAppUser);
        }else {
            // 判断账号是否被冻结
@@ -151,6 +152,7 @@
            }
            // 手机号相同但openId为空的情况
            sysAppUser.setOpenId(appletUserDecodeData.getOpenId());
            sysAppUser.setClinicId(data.getClinicId());
            sysAppUserService.updateById(sysAppUser);
        }
        LoginUserApplet loginUserApplet = new LoginUserApplet();
@@ -168,7 +170,7 @@
    @PostMapping("/openIdByCode")
    public R<Map<String, Object>> openIdByCode(@RequestBody OfficeUserEncrypteData data) {
        log.info("<<<<<<<<换取openid开始<<<<<<<<:{}", data.getCode());
        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig, redisService);
        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, wxConfig, redisCache);
        Code2SessionRespBody body = appletTools.getOpenIdByCode2session(new Code2SessionResqBody().build(data.getCode()));
        String openid = body.getOpenid();
        String phone = data.getPhone();
ruoyi-system/src/main/java/com/ruoyi/system/mapper/TSysInspectionRiskEstimateMapper.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.system.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.system.model.TSysInspectionRiskEstimate;
/**
 * <p>
 * 报告疾病风险 Mapper 接口
 * </p>
 *
 * @author xiaochen
 * @since 2026-01-06
 */
public interface TSysInspectionRiskEstimateMapper extends BaseMapper<TSysInspectionRiskEstimate> {
}
ruoyi-system/src/main/java/com/ruoyi/system/model/TCrmClinic.java
@@ -89,4 +89,8 @@
    @TableField("send_message_count")
    private Integer sendMessageCount;
    @ApiModelProperty(value = "邀请码")
    @TableField("qr_code")
    private String qrCode;
}
ruoyi-system/src/main/java/com/ruoyi/system/model/TSysInspection.java
@@ -1,6 +1,7 @@
package com.ruoyi.system.model;
import com.baomidou.mybatisplus.annotation.*;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.common.core.domain.BaseModel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -37,95 +38,91 @@
    @TableField("clinic_id")
    private String clinicId;
    @ApiModelProperty(value = "检测类型 1=诊所检测 2=小程序自检")
    @TableField("inspection_type")
    private Integer inspectionType;
    @ApiModelProperty(value = "患者姓名")
    @TableField("nick_name")
    private String nickName;
    @ApiModelProperty(value = "性别 1=男 2=女")
    @TableField("sex")
    private Integer sex;
    @ApiModelProperty(value = "年龄")
    @TableField("age")
    private Integer age;
    @ApiModelProperty(value = "科室")
    @TableField("administrative_office")
    private String administrativeOffice;
    @ApiModelProperty(value = "就诊日期")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @TableField("check_time")
    private String checkTime;
    @ApiModelProperty(value = "检测信息")
    @TableField("inspection_info")
    private String inspectionInfo;
    @ApiModelProperty(value = "检测使用设备登录用户所属会员团队编码")
    @TableField("team_code")
    private String teamCode;
    @ApiModelProperty(value = "处方信息")
    @TableField("prescription_info")
    private String prescriptionInfo;
    @ApiModelProperty(value = "检测使用设备登录用户所属会员团队名称")
    @TableField("team_name")
    private String teamName;
    @ApiModelProperty(value = "检测使用的设备编码")
    @TableField("device_code")
    private String deviceCode;
    @ApiModelProperty(value = "检测使用的设备名称")
    @TableField("device_name")
    private String deviceName;
    @ApiModelProperty(value = "检测人名称")
    @TableField("person_name")
    private String personName;
    @ApiModelProperty(value = "检测人性别(1=男,2=女)")
    @TableField("person_sex")
    private Integer personSex;
    @ApiModelProperty(value = "检测人年龄")
    @TableField("person_age")
    private Integer personAge;
    @ApiModelProperty(value = "检测人手机号")
    @TableField("person_phone")
    private String personPhone;
    @ApiModelProperty(value = "检测人身高(单位cm)")
    @TableField("person_height")
    private Double personHeight;
    @ApiModelProperty(value = "检测人体重(单位kg)")
    @TableField("person_weight")
    private Double personWeight;
    @ApiModelProperty(value = "检测时间")
    @TableField("check_time")
    private String checkTime;
    @ApiModelProperty(value = "检测 PDF 报告 URL")
    @TableField("pdf_url")
    private String pdfUrl;
    @ApiModelProperty(value = "健康指数,其值越大表示健康状态越好")
    @TableField("health_index")
    private Double healthIndex;
    @ApiModelProperty(value = "体质")
    @TableField("constitution_names")
    private String constitutionNames;
    @ApiModelProperty(value = "证型,进一步判断体质(constitutionNames)的结果,更为准确体现用户的真实体质")
    @TableField("symptom_name")
    private String symptomName;
    @ApiModelProperty(value = "舌象特征分析")
    @TableField("tongue_feature")
    private String tongueFeature;
    @ApiModelProperty(value = "面象特征分析")
    @TableField("face_feature")
    private String faceFeature;
    @ApiModelProperty(value = "风险疾病名称")
    @TableField("disease_risks")
    private String diseaseRisks;
    @ApiModelProperty(value = "检测类型 1=诊所检测 2=小程序自检 3=硬件检测")
    @TableField("inspection_type")
    private Integer inspectionType;
    @ApiModelProperty(value = "是否已支付 1=是 0=否")
    @TableField("is_pay")
    private Integer isPay;
    @ApiModelProperty(value = "报告H5页面地址")
    @TableField("report_print_url")
    private String reportPrintUrl;
    @ApiModelProperty(value = "现病史")
    @TableField("present_history")
    private String presentHistory;
    @ApiModelProperty(value = "中医证型")
    @TableField("tcm_syndrome")
    private String tcmSyndrome;
    @ApiModelProperty(value = "历史疾病补充")
    @TableField("disease_history_memo")
    private String diseaseHistoryMemo;
    @ApiModelProperty(value = "西医诊断")
    @TableField("western_medicine_diagnosis")
    private String westernMedicineDiagnosis;
    @ApiModelProperty(value = "三方用户id")
    @TableField("three_user_id")
    private Long threeUserId;
    @ApiModelProperty(value = "手机号码")
    @TableField("phone")
    private String phone;
    @ApiModelProperty(value = "设备账号ID")
    @TableField("device_account_id")
    private Long deviceAccountId;
    @ApiModelProperty(value = "面诊结果ID")
    @TableField("face_result_id")
    private Integer faceResultId;
    @ApiModelProperty(value = "舌诊结果ID")
    @TableField("tongue_result_id")
    private Integer tongueResultId;
    @ApiModelProperty(value = "诊所名称")
    @TableField(exist = false)
    private String clinicName;
    @ApiModelProperty(value = "是否已开药 1=是 0=否")
    @TableField(exist = false)
    private Integer isPrescribeMedicine;
    @ApiModelProperty(value = "订单id")
    @TableField(exist = false)
    private String orderId;
ruoyi-system/src/main/java/com/ruoyi/system/model/TSysInspectionRiskEstimate.java
New file
@@ -0,0 +1,54 @@
package com.ruoyi.system.model;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
/**
 * <p>
 * 报告疾病风险
 * </p>
 *
 * @author xiaochen
 * @since 2026-01-06
 */
@Data
@EqualsAndHashCode(callSuper = false)
@TableName("t_sys_inspection_risk_estimate")
@ApiModel(value="TSysInspectionRiskEstimate对象", description="报告疾病风险")
public class TSysInspectionRiskEstimate implements Serializable {
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private String id;
    @ApiModelProperty(value = "报告id")
    @TableField("inspection_id")
    private String inspectionId;
    @ApiModelProperty(value = "疾病名称")
    @TableField("risk_name")
    private String riskName;
    @ApiModelProperty(value = "疾病H5链接")
    @TableField("risk_link_url")
    private String riskLinkUrl;
    @ApiModelProperty(value = "风险值")
    @TableField("risk_value")
    private String riskValue;
    @ApiModelProperty(value = "风险值描述")
    @TableField("risk_value_desc")
    private String riskValueDesc;
}
ruoyi-system/src/main/java/com/ruoyi/system/service/TSysInspectionRiskEstimateService.java
New file
@@ -0,0 +1,16 @@
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.system.model.TSysInspectionRiskEstimate;
/**
 * <p>
 * 报告疾病风险 服务类
 * </p>
 *
 * @author xiaochen
 * @since 2026-01-06
 */
public interface TSysInspectionRiskEstimateService extends IService<TSysInspectionRiskEstimate> {
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/TSysInspectionRiskEstimateServiceImpl.java
New file
@@ -0,0 +1,20 @@
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.mapper.TSysInspectionRiskEstimateMapper;
import com.ruoyi.system.model.TSysInspectionRiskEstimate;
import com.ruoyi.system.service.TSysInspectionRiskEstimateService;
import org.springframework.stereotype.Service;
/**
 * <p>
 * 报告疾病风险 服务实现类
 * </p>
 *
 * @author xiaochen
 * @since 2026-01-06
 */
@Service
public class TSysInspectionRiskEstimateServiceImpl extends ServiceImpl<TSysInspectionRiskEstimateMapper, TSysInspectionRiskEstimate> implements TSysInspectionRiskEstimateService {
}
ruoyi-system/src/main/java/com/ruoyi/system/utils/util/TemplateMessageSendUtil.java
@@ -45,7 +45,7 @@
     * @param startTime 开始时间
     */
    public String wxTemplateAppLiveResultRequest(String openId,String liveTitle,String startTime) {
        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, weixinProperties, redisService);
        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, weixinProperties, redisCache);
        // 1,获取access_token
        String accessToken = redisCache.getCacheObject(ACCESS_TOKEN_CACHE_KEY);
        if (!StringUtils.hasLength(accessToken)) {
@@ -87,7 +87,7 @@
     * @param startTime 开始时间
     */
    public String wxOfficeTemplateAppLiveRequest(String openId,String liveTitle,String startTime) {
        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, weixinProperties, redisService);
        WxAppletTools appletTools = new WxAppletTools(wxRestTemplate, weixinProperties, redisCache);
        // 1,获取access_token
        String accessToken = redisCache.getCacheObject(ACCESS_TOKEN_OFFICE_CACHE_KEY);
        if (!StringUtils.hasLength(accessToken)) {
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/pojo/AppletUserEncrypteData.java
@@ -17,4 +17,6 @@
    private String code;
    @ApiModelProperty(value = "邀请用户id")
    private Long inviteUserId;
    @ApiModelProperty(value = "邀请诊所id")
    private String clinicId;
}
ruoyi-system/src/main/java/com/ruoyi/system/utils/wx/tools/WxAppletTools.java
@@ -1,6 +1,7 @@
package com.ruoyi.system.utils.wx.tools;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.system.utils.wx.body.resp.AccessTokenRespBody;
import com.ruoyi.system.utils.wx.body.resp.Code2SessionRespBody;
@@ -78,12 +79,12 @@
    public static String ACCESS_TOKEN_URL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}";
    private WeixinProperties wxConfig;
    private RestTemplate wxRestTemplate;
    private RedisService redisService;
    private RedisCache redisCache;
    public WxAppletTools(RestTemplate wxRestTemplate, WeixinProperties wxConfig, RedisService redisService) {
    public WxAppletTools(RestTemplate wxRestTemplate, WeixinProperties wxConfig, RedisCache redisCache) {
        this.wxRestTemplate = wxRestTemplate;
        this.wxConfig = wxConfig;
        this.redisService = redisService;
        this.redisCache = redisCache;
    }
    /**
@@ -146,7 +147,7 @@
     * @return
     */
    public String getAccessToken() {
        String accessToken = redisService.getCacheObject(ACCESSTOKEN_CACHE_KEY);
        String accessToken = redisCache.getCacheObject(ACCESSTOKEN_CACHE_KEY);
        if (StringUtils.hasLength(accessToken)) {
            return accessToken;
        }
@@ -158,7 +159,7 @@
            // 抛出错误
            throw new WxException(accessTokenRespBody.getErrorCode() + ":" + accessTokenRespBody.getErrorMsg());
        }
        redisService.setCacheObject(ACCESSTOKEN_CACHE_KEY, accessTokenRespBody.getAccessToken(), 7200L, TimeUnit.SECONDS);
        redisCache.setCacheObject(ACCESSTOKEN_CACHE_KEY, accessTokenRespBody.getAccessToken(), 7200, TimeUnit.SECONDS);
        return accessTokenRespBody.getAccessToken();
    }
@@ -166,7 +167,7 @@
     * @return
     */
    public String getAccessTokenOffice() {
        String accessToken = redisService.getCacheObject(ACCESS_TOKEN_OFFICE_CACHE_KEY);
        String accessToken = redisCache.getCacheObject(ACCESS_TOKEN_OFFICE_CACHE_KEY);
        if (StringUtils.hasLength(accessToken)) {
            return accessToken;
        }
@@ -178,7 +179,7 @@
            // 抛出错误
            throw new WxException(accessTokenRespBody.getErrorCode() + ":" + accessTokenRespBody.getErrorMsg());
        }
        redisService.setCacheObject(ACCESS_TOKEN_OFFICE_CACHE_KEY, accessTokenRespBody.getAccessToken(), 7200L, TimeUnit.SECONDS);
        redisCache.setCacheObject(ACCESS_TOKEN_OFFICE_CACHE_KEY, accessTokenRespBody.getAccessToken(), 7200, TimeUnit.SECONDS);
        return accessTokenRespBody.getAccessToken();
    }
ruoyi-system/src/main/resources/mapper/system/TCrmClinicMapper.xml
@@ -19,6 +19,7 @@
        <result column="audit_remark" property="auditRemark" />
        <result column="performance_count" property="performanceCount" />
        <result column="send_message_count" property="sendMessageCount" />
        <result column="qr_code" property="qrCode" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
        <result column="create_by" property="createBy" />
@@ -30,13 +31,14 @@
    <sql id="Base_Column_List">
        id, branch_id, salesperson_id, warehouse_id,user_id, clinic_name, person_charge_name, phone, low_procurement_money,
          clinic_address, qualification_picture, status,audit_remark,performance_count,send_message_count,
          create_time, update_time, create_by, update_by, disabled
          create_time, update_time, create_by, update_by, disabled,qr_code
    </sql>
    <select id="pageList" resultType="com.ruoyi.system.vo.TCrmClinicVO">
        SELECT
        tcc.id, tcc.branch_id, tcc.salesperson_id, tcc.warehouse_id,tcc.user_id, tcc.clinic_name, tcc.person_charge_name,
        tcc.phone, tcc.low_procurement_money, tcc.clinic_address, tcc.qualification_picture, tcc.status,tcc.audit_remark,
        tcc.create_time, tcc.update_time, tcc.create_by, tcc.update_by, tcc.disabled,tcc.performance_count,tcc.send_message_count,
        tcc.create_time, tcc.update_time, tcc.create_by, tcc.update_by, tcc.disabled,tcc.performance_count,
        tcc.send_message_count,tcc.qr_code,
        tcb.branch_name, tcs.salesperson_name, tcw.warehouse_name
        from t_crm_clinic tcc
        left join t_crm_branch tcb on tcc.branch_id = tcb.id
@@ -97,7 +99,8 @@
        SELECT
        tcc.id, tcc.branch_id, tcc.salesperson_id, tcc.warehouse_id,tcc.user_id, tcc.clinic_name, tcc.person_charge_name,
        tcc.phone, tcc.low_procurement_money, tcc.clinic_address, tcc.qualification_picture, tcc.status,tcc.audit_remark,
        tcc.create_time, tcc.update_time, tcc.create_by, tcc.update_by, tcc.disabled,tcc.performance_count,tcc.send_message_count,
        tcc.create_time, tcc.update_time, tcc.create_by, tcc.update_by, tcc.disabled,tcc.performance_count,
        tcc.send_message_count,tcc.qr_code,
        tcb.branch_name, tcs.salesperson_name, tcw.warehouse_name
        from t_crm_clinic tcc
        left join t_crm_branch tcb on tcc.branch_id = tcb.id
@@ -131,7 +134,8 @@
        SELECT
        tcc.id, tcc.branch_id, tcc.salesperson_id, tcc.warehouse_id,tcc.user_id, tcc.clinic_name, tcc.person_charge_name,
        tcc.phone, tcc.low_procurement_money, tcc.clinic_address, tcc.qualification_picture, tcc.status,tcc.audit_remark,
        tcc.create_time, tcc.update_time, tcc.create_by, tcc.update_by, tcc.disabled,tcc.performance_count,tcc.send_message_count,
        tcc.create_time, tcc.update_time, tcc.create_by, tcc.update_by, tcc.disabled,tcc.performance_count,
        tcc.send_message_count,tcc.qr_code,
        tcb.branch_name, tcs.salesperson_name, tcw.warehouse_name
        from t_crm_clinic tcc
        left join t_crm_branch tcb on tcc.branch_id = tcb.id
@@ -165,7 +169,8 @@
        SELECT
        tcc.id, tcc.branch_id, tcc.salesperson_id, tcc.warehouse_id,tcc.user_id, tcc.clinic_name, tcc.person_charge_name,
        tcc.phone, tcc.low_procurement_money, tcc.clinic_address, tcc.qualification_picture, tcc.status,tcc.audit_remark,
        tcc.create_time, tcc.update_time, tcc.create_by, tcc.update_by, tcc.disabled,tcc.performance_count,tcc.send_message_count,
        tcc.create_time, tcc.update_time, tcc.create_by, tcc.update_by, tcc.disabled,tcc.performance_count,
        tcc.send_message_count,tcc.qr_code,
        tcb.branch_name, tcs.salesperson_name, tcw.warehouse_name
        from t_crm_clinic tcc
        left join t_crm_branch tcb on tcc.branch_id = tcb.id
ruoyi-system/src/main/resources/mapper/system/TSysInspectionMapper.xml
@@ -7,27 +7,25 @@
        <id column="id" property="id" />
        <result column="app_user_id" property="appUserId" />
        <result column="clinic_id" property="clinicId" />
        <result column="inspection_type" property="inspectionType" />
        <result column="inspection_info" property="inspectionInfo" />
        <result column="team_code" property="teamCode" />
        <result column="team_name" property="teamName" />
        <result column="device_code" property="deviceCode" />
        <result column="device_name" property="deviceName" />
        <result column="person_name" property="personName" />
        <result column="person_sex" property="personSex" />
        <result column="person_age" property="personAge" />
        <result column="person_phone" property="personPhone" />
        <result column="person_height" property="personHeight" />
        <result column="person_weight" property="personWeight" />
        <result column="nick_name" property="nickName" />
        <result column="sex" property="sex" />
        <result column="age" property="age" />
        <result column="administrative_office" property="administrativeOffice" />
        <result column="check_time" property="checkTime" />
        <result column="pdf_url" property="pdfUrl" />
        <result column="health_index" property="healthIndex" />
        <result column="constitution_names" property="constitutionNames" />
        <result column="symptom_name" property="symptomName" />
        <result column="tongue_feature" property="tongueFeature" />
        <result column="face_feature" property="faceFeature" />
        <result column="disease_risks" property="diseaseRisks" />
        <result column="inspection_info" property="inspectionInfo" />
        <result column="prescription_info" property="prescriptionInfo" />
        <result column="inspection_type" property="inspectionType" />
        <result column="is_pay" property="isPay" />
        <result column="report_print_url" property="reportPrintUrl" />
        <result column="present_history" property="presentHistory" />
        <result column="tcm_syndrome" property="tcmSyndrome" />
        <result column="disease_history_memo" property="diseaseHistoryMemo" />
        <result column="western_medicine_diagnosis" property="westernMedicineDiagnosis" />
        <result column="three_user_id" property="threeUserId" />
        <result column="phone" property="phone" />
        <result column="device_account_id" property="deviceAccountId" />
        <result column="face_result_id" property="faceResultId" />
        <result column="tongue_result_id" property="tongueResultId" />
        <result column="create_time" property="createTime" />
        <result column="update_time" property="updateTime" />
        <result column="create_by" property="createBy" />
@@ -37,18 +35,18 @@
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, app_user_id,clinic_id, inspection_info,inspection_type, team_code, team_name, device_code, device_name, person_name,
          person_sex, person_age, person_phone, person_height, person_weight, check_time, pdf_url, health_index,
          constitution_names, symptom_name, tongue_feature,face_feature, disease_risks,is_pay, create_time, update_time,
          create_by, update_by, disabled, create_id
        id, app_user_id,clinic_id, nick_name, sex, age, administrative_office, check_time,
          inspection_info,inspection_type, is_pay, create_time, update_time,
          create_by, update_by, disabled, create_id,report_print_url, present_history, tcm_syndrome, disease_history_memo,
          western_medicine_diagnosis, three_user_id, phone, device_account_id, face_result_id, tongue_result_id
    </sql>
    <select id="pageList" resultType="com.ruoyi.system.vo.TSysInspectionVO">
        SELECT
        tsi.id, tsi.app_user_id,tsi.clinic_id, tsi.inspection_info,tsi.inspection_type, tsi.team_code, tsi.team_name,
        tsi.device_code, tsi.device_name, tsi.person_name,
        tsi.person_sex, tsi.person_age, tsi.person_phone, tsi.person_height, tsi.person_weight, tsi.check_time, tsi.pdf_url, tsi.health_index,
        tsi.constitution_names, tsi.symptom_name, tsi.tongue_feature,tsi.face_feature, tsi.disease_risks,tsi.is_pay, tsi.create_time, tsi.update_time,
        tsi.create_by, tsi.update_by, tsi.disabled, tsi.create_id,tau.nick_name as nickName
        tsi.id, tsi.app_user_id,tsi.clinic_id, tsi.nick_name, tsi.sex, tsi.age, tsi.administrative_office,
        tsi.check_time,tsi.inspection_info,tsi.inspection_type,tsi.is_pay, tsi.create_time, tsi.update_time,
        tsi.create_by, tsi.update_by, tsi.disabled, tsi.create_id,tsi.report_print_url, tsi.present_history,
        tsi.tcm_syndrome, tsi.disease_history_memo,tsi.western_medicine_diagnosis, tsi.three_user_id,
        tsi.phone, tsi.device_account_id, tsi.face_result_id, tsi.tongue_result_id,tau.nick_name as nickName
            FROM t_sys_inspection tsi
        left join t_sys_app_user tau on tsi.app_user_id = tau.id
        <where>
ruoyi-system/src/main/resources/mapper/system/TSysInspectionRiskEstimateMapper.xml
New file
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ruoyi.system.mapper.TSysInspectionRiskEstimateMapper">
    <!-- 通用查询映射结果 -->
    <resultMap id="BaseResultMap" type="com.ruoyi.system.model.TSysInspectionRiskEstimate">
        <id column="id" property="id" />
        <result column="inspection_id" property="inspectionId" />
        <result column="risk_name" property="riskName" />
        <result column="risk_link_url" property="riskLinkUrl" />
        <result column="risk_value" property="riskValue" />
        <result column="risk_value_desc" property="riskValueDesc" />
    </resultMap>
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, inspection_id, risk_name, risk_link_url, risk_value, risk_value_desc
    </sql>
</mapper>