瀏覽代碼

Merge branch 'refs/heads/master' into 红德堂

ct 4 天之前
父節點
當前提交
cc18bcf72d

+ 1 - 1
fs-admin/src/main/java/com/fs/his/controller/FsCompanyDivItemController.java

@@ -86,7 +86,7 @@ public class FsCompanyDivItemController extends BaseController
      */
     @PreAuthorize("@ss.hasPermi('his:divItem:confirm')")
     @Log(title = "延迟分账确认", businessType = BusinessType.UPDATE)
-    @PostMapping("/confirm")
+    @PostMapping("/confirmScrm")
     public R confirmScrm(@RequestBody List<String> payCodes)
     {
         return companyDivItemService.confirmByPayCodesScrm(payCodes);

+ 247 - 0
fs-admin/src/main/java/com/fs/his/param/FurtherConsultationParam.java

@@ -0,0 +1,247 @@
+package com.fs.his.param;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * 复诊信息实体请求参数
+ */
+@Data
+@Builder
+public class FurtherConsultationParam {
+
+    /**
+     * 接口调用凭证,可能不用传
+     */
+    private String accessToken;
+
+    /**
+     * 第三方厂商标识
+     */
+    private String clientId;
+
+    /**
+     * 唯一标识,用于唯一确定某条记录,避免重复上传,一般传该条数据的主键
+     */
+    private String thirdUniqueid;
+
+    /**
+     * 机构名称
+     */
+    private String orgName;
+
+    /**
+     * 机构编码,组织机构代码
+     */
+    private String orgCode;
+
+    /**
+     * 诊疗渠道,平台名称
+     */
+    private String channelName;
+
+    /**
+     * 复诊科室
+     */
+    private String section;
+
+    /**
+     * 科室编码,三医
+     */
+    private String sectionCode;
+
+    /**
+     * 复诊医师姓名
+     */
+    private String docName;
+
+    /**
+     * 执业资格证号
+     */
+    private String certificateNum;
+
+    /**
+     * 患者姓名
+     */
+    private String patientName;
+
+    /**
+     * 患者年龄,低于6岁为低龄儿童
+     */
+    private Integer patientAge;
+
+    /**
+     * 患者性别,1男/2女
+     */
+    private String patientSex;
+
+    /**
+     * 证件类型,1 身份证  2 护照
+     */
+    private Integer patientIdcardType;
+
+    /**
+     * 患者证件号码,18位
+     */
+    private String patientIdcardNum;
+
+    /**
+     * 网络复诊编号
+     */
+    private String furtherConsultNo;
+
+    /**
+     * 复诊类别,1、图文诊疗 2语音诊疗 3、视频诊疗
+     */
+    private Integer furtherConsulType;
+
+    /**
+     * 监护人姓名,患者年龄小于6岁,需填此项
+     */
+    private String guardianName;
+
+    /**
+     * 监护人身份证号,患者年龄小于6岁,需填此项
+     */
+    private String guardianIdcardNum;
+
+    /**
+     * 患者简要病史描述,病史摘要
+     */
+    private String medicalHistory;
+
+    /**
+     * 首诊诊断类型,1文字 2图片jpg格式 3图片png格式 4图片bmp格式
+     */
+    private Integer consultDiagnosisType;
+
+    /**
+     * 首诊诊断,复诊患者在首诊医院的诊断,如有多条,使用"|"进行分隔;当传图片时,需要传图片的base64字符串
+     */
+    private String consultDiagnosis;
+
+    /**
+     * 首诊时间,YYYY-MM-DD HH:mm:ss
+     */
+    private String consultTime;
+
+    /**
+     * 首诊机构
+     */
+    private String consultOrg;
+
+    /**
+     * 复诊申请时间,YYYY-MM-DD HH:mm:ss
+     */
+    private String furtherConsultApplyTime;
+
+    /**
+     * 复诊开始时间,YYYY-MM-DD HH:mm:ss
+     */
+    private String furtherConsulStartTime;
+
+    /**
+     * 复诊结束时间,YYYY-MM-DD HH:mm:ss
+     */
+    private String furtherConsulEndTime;
+
+    /**
+     * 复诊是否回复,0未回复 1已回复
+     */
+    private Integer furtherConsulIsReply;
+
+    /**
+     * 费别,1自费 2医保
+     */
+    private Integer feeType;
+
+    /**
+     * 复诊诊断,复诊患者在实体医院的诊断名称,如有多条,使用"|"进行分隔
+     */
+    private String furtherConsultDiagnosis;
+
+    /**
+     * 复诊icd诊断编码
+     */
+    private String furtherConsultDiagnosisNo;
+
+    /**
+     * 复诊价格,单位:元
+     */
+    private Double furtherConsultPrice;
+
+    /**
+     * 患者满意度,1-5,1代表非常满意,5代表非常不满意
+     */
+    private Integer patientEvaluate;
+
+    /**
+     * 投诉举报信息,文本信息
+     */
+    private String complainInfo;
+
+    /**
+     * 处理结果信息,文本信息
+     */
+    private String disposeResult;
+
+    /**
+     * 是否进行诊前风险提示,0否 1是
+     */
+    private Integer isRiskWarn;
+
+    /**
+     * 是否确认患者为签约对象,0否 1是
+     */
+    private Integer isPatientSign;
+
+    /**
+     * 是否开具处方,0否 1是
+     */
+    private Integer isPrescription;
+
+    /**
+     * 上传时间,YYYY-MM-DD HH:mm:ss
+     */
+    private String uploadTime;
+
+    /**
+     * 复诊拒绝时间
+     */
+    private String furtherConsultRefuseTime;
+
+    /**
+     * 复诊拒绝类别,1医生主动拒绝 2超时未回复系统自动拒绝
+     */
+    private Integer furtherConsultRefuseType;
+
+    /**
+     * 复诊拒绝、取消原因
+     */
+    private String furtherConsultRefuseReason;
+
+    /**
+     * ca登录值
+     */
+    private String caLoginSign;
+
+    /**
+     * ca登录时间,YYYY-MM-DD HH:mm:ss
+     */
+    private String caLoginTime;
+
+    /**
+     * 城市id(参考地区字段)
+     */
+    private String cityId;
+
+    /**
+     * 年
+     */
+    private String year;
+
+    /**
+     * 是否留痕,1:代表留痕;0代表未留痕
+     */
+    private String isMark;
+}

+ 329 - 0
fs-admin/src/main/java/com/fs/his/param/PrescriptionParam.java

@@ -0,0 +1,329 @@
+package com.fs.his.param;
+
+import lombok.Builder;
+import lombok.Data;
+
+/**
+ * 电子处方信息上传请求参数
+ */
+@Data
+@Builder
+public class PrescriptionParam {
+
+    /**
+     * 接口调用凭证
+     */
+    private String accessToken;
+
+    /**
+     * 第三方厂商标识
+     */
+    private String clientId;
+
+    /**
+     * 唯一标识,用于唯一确定某条记录,避免重复上传,一般传该条数据的主键
+     */
+    private String thirdUniqueid;
+
+    /**
+     * 机构名称
+     */
+    private String orgName;
+
+    /**
+     * 机构编码
+     */
+    private String orgCode;
+
+    /**
+     * 科室名称
+     */
+    private String section;
+
+    /**
+     * 科室编码
+     */
+    private String sectionCode;
+
+    /**
+     * 医师姓名
+     */
+    private String docName;
+
+    /**
+     * 医师执业资格证号
+     */
+    private String docCertificateNum;
+
+    /**
+     * 药师姓名
+     */
+    private String pharmacistName;
+
+    /**
+     * 药师执业机构
+     */
+    private String pharmacistOrg;
+
+    /**
+     * 药师执业资格证号
+     */
+    private String pharmacistCertificateNum;
+
+    /**
+     * 网络复诊编号,对应接口二
+     */
+    private String furtherConsultNo;
+
+    /**
+     * 复诊诊断,复诊患者在实体医院的诊断名称,如有多条,使用"|"进行分隔
+     */
+    private String furtherConsultDiagnosis;
+
+    /**
+     * 患者姓名
+     */
+    private String patientName;
+
+    /**
+     * 患者性别,1男/2女
+     */
+    private String patientSex;
+
+    /**
+     * 患者年龄,示例:19
+     */
+    private Integer patientAge;
+
+    /**
+     * 证件类型,1 身份证  2 护照
+     */
+    private Integer patientIdcardType;
+
+    /**
+     * 患者证件号码
+     */
+    private String patientIdcardNum;
+
+    /**
+     * 监护人姓名,患者年龄小于6岁需填此项
+     */
+    private String guardianName;
+
+    /**
+     * 监护人身份证,患者年龄小于6岁需填此项
+     */
+    private String guardianIdcardNum;
+
+    /**
+     * 陪伴医师姓名,患者年龄小于6岁需填此项
+     */
+    private String accompanyDocName;
+
+    /**
+     * 陪伴医师执业证号码,患者年龄小于6岁需填此项
+     */
+    private String accompanyCertificateNum;
+
+    /**
+     * 费别,1自费 2医保
+     */
+    private Integer feeType;
+
+    /**
+     * 患者简要病史描述,病史摘要
+     */
+    private String medicalHistory;
+
+    /**
+     * 处方日期,格式:YYYY-MM-DD HH:mm:ss
+     */
+    private String recipeTime;
+
+    /**
+     * 处方类型,1中药 2西药 3成药(三医)
+     */
+    private Integer recipeType;
+
+    /**
+     * 审方日期,格式:YYYY-MM-DD HH:mm:ss
+     */
+    private String reviewTime;
+
+    /**
+     * 处方单价,单位:元
+     */
+    private Double recipeUnitPrice;
+
+    /**
+     * 药品名称商品名,以|作为分隔,相同index位置的为一组数据
+     * 示例:"快克|板蓝根颗粒|阿莫西林胶囊"
+     */
+    private String drugName;
+
+    /**
+     * 药品编码
+     */
+    private String drugCode;
+
+    /**
+     * 药品通用名
+     */
+    private String drugCommonName;
+
+    /**
+     * 规格
+     */
+    private String specification;
+
+    /**
+     * 使用频度
+     * 示例:"2次/天|3次/天|3次/天"
+     */
+    private String frequency;
+
+    /**
+     * 用法
+     */
+    private String usage;
+
+    /**
+     * 剂量单位
+     */
+    private String doseUnit;
+
+    /**
+     * 每次剂量
+     */
+    private String doseEachTime;
+
+    /**
+     * 用药天数
+     */
+    private Double medicationDays;
+
+    /**
+     * 帖数
+     */
+    private Double packetNum;
+
+    /**
+     * 数量
+     */
+    private Double quantity;
+
+    /**
+     * 药品包装
+     */
+    private String drugPackage;
+
+    /**
+     * 处方总价,单位:元
+     */
+    private Double recipeAllPrice;
+
+    /**
+     * 是否经过合理用药判断标志,0 否 1 是
+     */
+    private Integer isRationalDrugUse;
+
+    /**
+     * 合理用药审核结果
+     */
+    private String rationalDrugUseReason;
+
+    /**
+     * 配送单位,配送药企、医院药房发药或药店名称
+     */
+    private String deliveryOrg;
+
+    /**
+     * 核销方式,0 医院取药 1物流配送 2药店取药 3自动失效
+     */
+    private Integer cancelAfterVerifyWay;
+
+    /**
+     * 处方核销状态,0未核销 1已核销
+     */
+    private Integer cancelAfterVerifyStatus;
+
+    /**
+     * 处方核销时间,物流配送、医院药房发药或药店自购时间、自动失效时间
+     */
+    private String cancelAfterVerifyTime;
+
+    /**
+     * 配送金额
+     */
+    private Double deliveryPrice;
+
+    /**
+     * 上传时间,格式:YYYY-MM-DD HH:mm:ss
+     */
+    private String uploadTime;
+
+    /**
+     * 医师ca签名订单id
+     */
+    private String docCaSignOrderId;
+
+    /**
+     * 医师ca签名值
+     */
+    private String docCaSign;
+
+    /**
+     * 医师ca签名时间,格式:YYYY-MM-DD HH:mm:ss
+     */
+    private String docCaSignTime;
+
+    /**
+     * 医师ca登录值
+     */
+    private String docCaLoginSign;
+
+    /**
+     * 医师ca登录时间,格式:YYYY-MM-DD HH:mm:ss
+     */
+    private String docCaLoginTime;
+
+    /**
+     * 药师ca签名订单id
+     */
+    private String pharmacistCaSignOrderId;
+
+    /**
+     * 药师ca签名值
+     */
+    private String pharmacistCaSign;
+
+    /**
+     * 药师ca签名时间,格式:YYYY-MM-DD HH:mm:ss
+     */
+    private String pharmacistCaSignTime;
+
+    /**
+     * 药师ca登录值
+     */
+    private String pharmacistCaLoginSign;
+
+    /**
+     * 药师ca登录时间,格式:YYYY-MM-DD HH:mm:ss
+     */
+    private String pharmacistCaLoginTime;
+
+    /**
+     * 医院处方编号
+     */
+    private String recipeNo;
+
+    /**
+     * 所在城市id(参考地区字段)
+     */
+    private String cityId;
+
+    /**
+     * 职称
+     */
+    private String jobTitle;
+}

+ 480 - 0
fs-admin/src/main/java/com/fs/his/task/NetMedicalService.java

@@ -0,0 +1,480 @@
+package com.fs.his.task;
+
+import cn.hutool.core.convert.Convert;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.file.PathUtil;
+import cn.hutool.core.util.IdcardUtil;
+import cn.hutool.http.HttpRequest;
+import cn.hutool.http.HttpResponse;
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.fs.common.utils.file.ImageUtils;
+import com.fs.framework.interceptor.impl.SameUrlDataInterceptor;
+import com.fs.his.domain.FsInquiryOrderDTO;
+import com.fs.his.domain.FsPrescribeDrugDTO;
+import com.fs.his.dto.FsInquiryOrderPatientDTO;
+import com.fs.his.mapper.FsInquiryOrderMapper;
+import com.fs.his.mapper.FsPrescribeDrugMapper;
+import com.fs.his.param.FurtherConsultationParam;
+import com.fs.his.param.PrescriptionParam;
+import com.fs.his.service.IFsPrescribeService;
+import com.qiniu.util.Json;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+
+/**
+ * 互联网医疗服务定时任务
+ * 润天推送参考:每天从中午12点到下午17点,每个小时的整点执行一次
+ */
+@Component("netMedicalService")
+@AllArgsConstructor
+@Slf4j
+public class NetMedicalService {
+
+    private final String prefix = "https://202.61.88.184:19200/";
+    private final String prescriptionPath = "wjw/upload/uploadRecipe";
+    private final String reconsultPath = "wjw/upload/uploadFurtherConsult";
+
+    private final IFsPrescribeService iFsPrescribeService;
+    private final FsPrescribeDrugMapper durgMapper;
+    private final FsInquiryOrderMapper inquiryOrderMapper;
+
+    public void uploadPrescription() {
+        log.info("互联网医疗服务定时任务启动,时间{}", LocalDateTime.now());
+
+        try {
+            // 1.抽取有生成电子处方and上传了首诊记录的数据
+            LocalDate today = LocalDate.now().minusDays(1);
+            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+            String date = today.format(formatter);
+
+            // 此任务准备在凌晨执行,上传前一天的电子处方。
+            List<Map<String, Object>> result = iFsPrescribeService.selectUploadDate("2025-09-21");//TODO:测试修改
+            log.info("查询到 {} 条待上传处方数据", result.size());
+
+            if (result.isEmpty()) {
+                log.info("没有需要上传的处方数据");
+                return;
+            }
+
+            List<PrescriptionParam> paramList = processPrescriptions(result);
+
+            uploadToRemoteService(paramList);
+
+        } catch (Exception e) {
+            log.error("上传处方任务执行失败", e);
+        }
+    }
+
+    /**
+     * 网络诊疗服务数据上传
+     * TODO:请求体太大,可能需要分批请求;
+     */
+    public void uploadReconsultDate() {
+        log.info("开始执行网络诊疗服务数据上传任务");
+
+        // 使用 DateTimeFormatter 替代 SimpleDateFormat
+        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+
+        LocalDate today = LocalDate.now().minusDays(1);
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+        String date = today.format(formatter);
+
+        log.info("查询日期: {}", date);
+        List<FsInquiryOrderDTO> fsInquiryOrderDTOS = inquiryOrderMapper.selectNeedUploadData("2025-01-01");//TODO:测试修改
+        log.info("查询到需要上传的数据条数: {}", fsInquiryOrderDTOS.size());
+
+        ArrayList<FurtherConsultationParam> paramList = new ArrayList<>();
+        int successCount = 0;
+        int skipCount = 0;
+        int errorCount = 0;
+
+        for (int i = 0; i < fsInquiryOrderDTOS.size(); i++) {
+            FsInquiryOrderDTO fsInquiryOrder = fsInquiryOrderDTOS.get(i);
+            String orderSn = fsInquiryOrder.getOrderSn();
+
+            log.debug("正在处理第 {}/{} 条数据, 订单号: {}", i + 1, fsInquiryOrderDTOS.size(), orderSn);
+
+            try {
+                // 检查是否开具处方
+                int isPrescribe = iFsPrescribeService.selectPrescribeByinquiryOrderId(fsInquiryOrder.getOrderId());
+                log.debug("订单 {} 处方检查结果: {}", orderSn, isPrescribe > 0 ? "有处方" : "无处方");
+
+                String imageUrl = fsInquiryOrder.getReportImages();
+                if (imageUrl == null || imageUrl.trim().isEmpty()) {
+                    log.warn("订单 {} 报告图片URL为空,跳过处理", orderSn);
+                    skipCount++;
+                    continue;
+                }
+
+                log.debug("订单 {} 报告图片URL: {}", orderSn, imageUrl);
+
+                Integer supportedImageFormat = getSupportedImageFormat(imageUrl);
+                if (Objects.isNull(supportedImageFormat)) {
+                    log.warn("订单 {} 不支持的文件后缀,跳过处理,图片URL: {}", orderSn, imageUrl);
+                    skipCount++;
+                    continue;
+                }
+                log.debug("订单 {} 图片格式识别成功: {}", orderSn, supportedImageFormat);
+
+                byte[] image = ImageUtils.getImage(imageUrl);
+                if (image == null || image.length == 0) {
+                    log.warn("订单 {} 无法获取图片数据,图片URL: {}", orderSn, imageUrl);
+                    skipCount++;
+                    continue;
+                }
+                log.debug("订单 {} 成功获取图片数据,图片大小: {} bytes", orderSn, image.length);
+
+                String base64Image = Base64.getEncoder().encodeToString(image);
+                log.debug("订单 {} Base64编码完成,编码后长度: {}", orderSn, base64Image.length());
+
+                // 安全处理时间字段
+                String applyTime = formatDateTimeSafely(fsInquiryOrder.getCreateTime(), dateTimeFormatter);
+                String startTime = formatDateTimeSafely(fsInquiryOrder.getStartTime(), dateTimeFormatter);
+                String endTime = formatDateTimeSafely(fsInquiryOrder.getFinishTime(), dateTimeFormatter);
+                String uploadTime = LocalDateTime.now().format(dateTimeFormatter);//TODO:这个完成时间必须传,业务上判断是否需要未完结的复诊数据
+
+                if (applyTime == null || startTime == null || endTime == null) {
+                    log.warn("订单 {} 时间字段存在空值,跳过处理", orderSn);
+                    skipCount++;
+                    continue;
+                }
+
+                FurtherConsultationParam param = FurtherConsultationParam.builder()
+                        .thirdUniqueid(orderSn)
+                        .orgName(fsInquiryOrder.getHospitalName())
+                        .orgCode("组织结构代码")
+                        .channelName("平台名称")
+                        .section(fsInquiryOrder.getDeptName())
+                        .sectionCode(fsInquiryOrder.getDeptCode())
+                        .docName(fsInquiryOrder.getDoctorName())
+                        .certificateNum(fsInquiryOrder.getCertificateCode())
+                        .patientName(fsInquiryOrder.getPatientName())
+                        .patientAge(IdcardUtil.getAgeByIdCard(fsInquiryOrder.getIdCard()))
+                        .patientSex(fsInquiryOrder.getSex())
+                        .patientIdcardType(1)
+                        .patientIdcardNum(fsInquiryOrder.getIdCard())
+                        .furtherConsultNo(orderSn)
+                        .furtherConsulType(1)
+                        .medicalHistory(fsInquiryOrder.getSelfMedHistory())
+                        .furtherConsultApplyTime(applyTime)
+                        .furtherConsulStartTime(startTime)
+                        .furtherConsulEndTime(endTime)
+                        .furtherConsulIsReply(1)
+                        .feeType(1)
+                        .furtherConsultDiagnosis(fsInquiryOrder.getInquiryResult())
+                        .furtherConsultDiagnosisNo("复诊icd诊断编码")
+                        .furtherConsultPrice(fsInquiryOrder.getMoney().toBigInteger().doubleValue())
+                        .patientEvaluate(1)
+                        .complainInfo("")
+                        .disposeResult("")
+                        .isRiskWarn(1)
+                        .isPatientSign(1)
+                        .isPrescription(isPrescribe > 0 ? 1 : 0)
+                        .uploadTime(uploadTime)
+                        .consultDiagnosisType(supportedImageFormat)
+                        .consultOrg("首诊机构")
+                        .consultDiagnosis(base64Image)
+                        .cityId("")
+                        .isMark("1")
+                        .build();
+
+                paramList.add(param);
+                successCount++;
+                log.debug("订单 {} 参数构建完成,已添加到上传列表", orderSn);
+
+            } catch (Exception e) {
+                errorCount++;
+                log.error("处理订单 {} 时发生异常: {}", orderSn, e.getMessage(), e);
+            }
+        }
+
+        log.info("数据处理完成 - 成功: {}条, 跳过: {}条, 异常: {}条", successCount, skipCount, errorCount);
+
+        if (paramList.isEmpty()) {
+            log.info("没有需要上传的数据,任务结束");
+            return;
+        }
+
+        try {
+            String jsonParam = JSON.toJSONString(paramList);
+            log.info("准备上传数据,参数条数: {}", paramList.size());
+//            log.debug("请求参数JSON: {}", jsonParam);
+
+            String urlPath = prefix + reconsultPath;
+            log.info("请求URL: {}", urlPath);
+
+            HttpRequest post = HttpUtil.createPost(urlPath);
+            post.body(jsonParam, "application/json; charset=utf-8");
+
+            log.info("开始发送HTTP请求...");
+            long startTime = System.currentTimeMillis();
+            HttpResponse response = post.execute();
+            long endTime = System.currentTimeMillis();
+
+            log.info("HTTP请求完成,状态码: {}, 耗时: {}ms", response.getStatus(), endTime - startTime);
+
+            if (response.isOk()) {
+                String responseBody = response.body();
+                log.info("上传成功,响应内容: {}", responseBody);
+
+                // 可以在这里添加响应结果解析和业务逻辑判断
+                try {
+                    JSONObject responseJson = JSON.parseObject(responseBody);
+                    if (responseJson != null) {
+                        String code = responseJson.getString("status");
+                        String message = responseJson.getString("message");
+                        log.info("响应解析 - 状态码: {}, 消息: {}", code, message);
+                    }
+                } catch (Exception e) {
+                    log.warn("响应内容解析失败: {}", e.getMessage());
+                }
+            } else {
+                log.error("上传失败,状态码: {}, 响应内容: {}", response.getStatus(), response.body());
+            }
+
+        } catch (Exception e) {
+            log.error("数据上传过程中发生异常: {}", e.getMessage(), e);
+        }
+        log.info("网络诊疗服务数据上传任务执行完毕");
+    }
+
+    private List<PrescriptionParam> processPrescriptions(List<Map<String, Object>> prescriptions) {
+        List<PrescriptionParam> paramList = new ArrayList<>();
+
+        for (Map<String, Object> prescribe : prescriptions) {
+            try {
+                PrescriptionParam param = processSinglePrescription(prescribe);
+                if (param != null) {
+                    paramList.add(param);
+                }
+            } catch (Exception e) {
+                log.error("处理处方失败, prescribe_id: {}", prescribe.get("prescribe_id"), e);
+            }
+        }
+
+        log.info("成功处理 {} 个处方", paramList.size());
+        return paramList;
+    }
+
+    private PrescriptionParam processSinglePrescription(Map<String, Object> prescribe) {
+        Long prescribeId = Convert.toLong(prescribe.get("prescribe_id"));
+        if (prescribeId == null) {
+            log.warn("处方ID为空,跳过处理");
+            return null;
+        }
+
+        // 药品信息查询
+        List<FsPrescribeDrugDTO> drugs = durgMapper.selectDrugList(prescribeId);
+        if (drugs == null || drugs.isEmpty()) {
+            log.warn("处方 {} 没有药品信息,跳过处理", prescribeId);
+            return null;
+        }
+
+        // 计算总量
+        Double quantity = calculateTotalQuantity(drugs);
+        Double days = calculateTotalDays(drugs);
+
+        // 组装药品信息
+        Map<String, String> drugInfoMap = buildDrugInfoMap(drugs);
+
+        // 构建处方参数
+        return buildPrescriptionParam(prescribe, drugInfoMap, quantity, days);
+    }
+
+    private Double calculateTotalQuantity(List<FsPrescribeDrugDTO> drugs) {
+        return drugs.stream().map(FsPrescribeDrugDTO::getDrugNum).filter(Objects::nonNull).mapToDouble(Convert::toDouble).sum();
+    }
+
+    private Double calculateTotalDays(List<FsPrescribeDrugDTO> drugs) {
+        return drugs.stream().map(FsPrescribeDrugDTO::getUsageDays).filter(Objects::nonNull).mapToDouble(Convert::toDouble).sum();
+    }
+
+    private Map<String, String> buildDrugInfoMap(List<FsPrescribeDrugDTO> drugs) {
+        Map<String, String> resultMap = new HashMap<>();
+        resultMap.put("drugName", join(drugs, FsPrescribeDrugDTO::getDrugName));
+        resultMap.put("specification", join(drugs, FsPrescribeDrugDTO::getDrugSpec));
+        resultMap.put("frequency", join(drugs, FsPrescribeDrugDTO::getUsageFrequencyUnit));
+        resultMap.put("useMethod", join(drugs, FsPrescribeDrugDTO::getUsageMethod));
+        resultMap.put("usagePerUseUnit", join(drugs, FsPrescribeDrugDTO::getUsagePerUseUnit));
+        resultMap.put("drugCode", join(drugs, FsPrescribeDrugDTO::getBarCode));
+        resultMap.put("doseEachTime", join(drugs, FsPrescribeDrugDTO::getUsagePerUseCount)); // 修复类型
+        return resultMap;
+    }
+
+    private PrescriptionParam buildPrescriptionParam(Map<String, Object> prescribe, Map<String, String> drugInfoMap, Double quantity, Double days) {
+        return PrescriptionParam.builder()
+                .thirdUniqueid(getString(prescribe, "prescribe_code"))
+                .orgName(getString(prescribe, "hospital_name"))
+                .orgCode("机构编码") // TODO: 不晓得从哪取
+                .section(getString(prescribe, "dept_name"))
+                .sectionCode(getString(prescribe, "dept_code"))
+                .docName(getString(prescribe, "doctor_name"))
+                .docCertificateNum(getString(prescribe, "certificate_code"))
+                .pharmacistName(getString(prescribe, "doctor_drug_name"))
+                .pharmacistCertificateNum(getString(prescribe, "doctor_drug_code"))
+                .patientName(getString(prescribe, "patient_name"))
+                .patientSex(getString(prescribe, "patient_gender"))
+                .patientAge(getInteger(prescribe, "patient_age"))
+                .patientIdcardType(1)
+                .feeType(1)
+                .patientIdcardNum(getString(prescribe, "id_card"))
+                .recipeTime(getString(prescribe, "create_time"))
+                .reviewTime(getString(prescribe, "create_time"))
+                .recipeUnitPrice(getDouble(prescribe, "total_price"))
+                .drugName(drugInfoMap.get("drugName"))
+                .drugCode(drugInfoMap.get("drugCode"))
+                .drugCommonName(drugInfoMap.get("drugName"))
+                .specification(drugInfoMap.get("specification"))
+                .frequency(drugInfoMap.get("frequency"))
+                .usage(drugInfoMap.get("useMethod"))
+                .doseUnit(drugInfoMap.get("usagePerUseUnit"))
+                .doseEachTime(drugInfoMap.get("doseEachTime"))
+                .medicationDays(days)
+                .quantity(quantity)
+                .drugPackage("药品包装") // TODO: 不晓得去哪取
+                .recipeAllPrice(getDouble(prescribe, "total_price"))
+                .uploadTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")))
+                .recipeNo(getString(prescribe, "prescribe_code"))
+                .cityId("") // TODO: 没有对应字典
+                .build();
+    }
+
+    private void uploadToRemoteService(List<PrescriptionParam> paramList) {
+        if (paramList.isEmpty()) {
+            log.info("没有需要上传的数据");
+            return;
+        }
+
+        try {
+            String url = prefix + prescriptionPath;
+            log.info("开始上传 {} 个处方到: {}", paramList.size(), url);
+
+            HttpRequest post = HttpUtil.createPost(url);
+            String requestBody = JSON.toJSONString(paramList);
+            log.debug("上传数据: {}", requestBody);//很大一坨
+
+            post.body(requestBody);
+            HttpResponse response = post.execute();
+
+//            log.info("上传完成,响应状态: {}", response.getStatus());
+            log.info("响应内容: {}", JSON.toJSONString(response));
+
+        } catch (Exception e) {
+            log.error("上传处方数据到远程服务失败", e);
+            throw new RuntimeException("上传失败", e);
+        }
+    }
+
+    // 工具方法
+    private String getString(Map<String, Object> map, String key) {
+        Object value = map.get(key);
+        return value != null ? value.toString() : "";
+    }
+
+    private Integer getInteger(Map<String, Object> map, String key) {
+        try {
+            Object value = map.get(key);
+            return value != null ? Integer.valueOf(value.toString()) : 0;
+        } catch (NumberFormatException e) {
+            log.warn("字段 {} 转换整数失败, 使用默认值0", key);
+            return 0;
+        }
+    }
+
+    private Double getDouble(Map<String, Object> map, String key) {
+        try {
+            Object value = map.get(key);
+            return value != null ? Double.valueOf(value.toString()) : 0.0;
+        } catch (NumberFormatException e) {
+            log.warn("字段 {} 转换浮点数失败, 使用默认值0.0", key);
+            return 0.0;
+        }
+    }
+
+    private String join(List<FsPrescribeDrugDTO> drugs, Function<FsPrescribeDrugDTO, String> fieldExtractor) {
+        return drugs.stream().map(fieldExtractor).filter(Objects::nonNull).filter(str -> !str.trim().isEmpty()).collect(Collectors.joining("|"));
+    }
+
+    /**
+     * 获取图片格式(只支持jpg、png、bmp)
+     *
+     * @param imagePath 图片路径
+     * @return 图片格式(jpeg, png, bmp),如果不支持则返回null
+     */
+    public static Integer getSupportedImageFormat(String imagePath) {
+        if (imagePath == null || imagePath.trim().isEmpty()) {
+            return null;
+        }
+
+        // 处理URL参数
+        String cleanPath = imagePath.split("[?#]")[0];
+
+        // 获取扩展名
+        String extension = "";
+        int lastDotIndex = cleanPath.lastIndexOf('.');
+        if (lastDotIndex > 0 && lastDotIndex < cleanPath.length() - 1) {
+            extension = cleanPath.substring(lastDotIndex + 1).toLowerCase();
+        }
+
+        // 只支持三种格式
+        switch (extension) {
+            case "jpg":
+            case "jpeg":
+                return 2;
+            case "png":
+                return 3;
+            case "bmp":
+                return 4;
+            default:
+                return null; // 不支持的格式返回null
+        }
+    }
+
+    /**
+     * 安全格式化时间方法,处理各种时间类型
+     */
+    private String formatDateTimeSafely(Object dateTime, DateTimeFormatter formatter) {
+        if (dateTime == null) {
+            log.warn("时间字段为null");
+            return null;
+        }
+
+        try {
+            if (dateTime instanceof java.util.Date) {
+                // 转换 java.util.Date 到 LocalDateTime
+                Instant instant = ((java.util.Date) dateTime).toInstant();
+                return LocalDateTime.ofInstant(instant, ZoneId.systemDefault()).format(formatter);
+            } else if (dateTime instanceof java.sql.Timestamp) {
+                // 转换 java.sql.Timestamp 到 LocalDateTime
+                return ((java.sql.Timestamp) dateTime).toLocalDateTime().format(formatter);
+            } else if (dateTime instanceof LocalDateTime) {
+                // 直接格式化 LocalDateTime
+                return ((LocalDateTime) dateTime).format(formatter);
+            } else if (dateTime instanceof LocalDate) {
+                // 处理 LocalDate,添加时间部分
+                return ((LocalDate) dateTime).atStartOfDay().format(formatter);
+            } else {
+                log.warn("不支持的时间类型: {}", dateTime.getClass().getName());
+                return null;
+            }
+        } catch (Exception e) {
+            log.error("时间格式化失败: {}, 原始值: {}", e.getMessage(), dateTime);
+            return null;
+        }
+    }
+}

+ 19 - 0
fs-service/src/main/java/com/fs/his/domain/FsInquiryOrderDTO.java

@@ -0,0 +1,19 @@
+package com.fs.his.domain;
+
+import lombok.Data;
+
+@Data
+public class FsInquiryOrderDTO extends FsInquiryOrder{
+    private String json;
+    private String doctorName;
+    private String hospitalName;
+    private String deptCode;
+    private String deptName;
+    private String certificateCode;
+    private String patientName;
+    private String idCard;
+    private String sex;
+    private String selfMedHistory;
+    private String inquiryResult;
+    private String reportImages;
+}

+ 8 - 0
fs-service/src/main/java/com/fs/his/domain/FsPrescribeDrugDTO.java

@@ -0,0 +1,8 @@
+package com.fs.his.domain;
+
+import lombok.Data;
+
+@Data
+public class FsPrescribeDrugDTO extends FsPrescribeDrug{
+    private String barCode;
+}

+ 3 - 0
fs-service/src/main/java/com/fs/his/mapper/FsInquiryOrderMapper.java

@@ -2,6 +2,7 @@ package com.fs.his.mapper;
 
 import java.util.List;
 import com.fs.his.domain.FsInquiryOrder;
+import com.fs.his.domain.FsInquiryOrderDTO;
 import com.fs.his.domain.FsInquiryOrderMsg;
 import com.fs.his.domain.FsStoreOrderLogs;
 import com.fs.his.param.FsInquiryOrderListDParam;
@@ -386,4 +387,6 @@ public interface FsInquiryOrderMapper
     Long selectFsInquiryFeedbackExportListVOCount(@Param("maps") FsInquiryOrderParam fsInquiryOrder);
 
     void closeOrder(Long orderId);
+
+    List<FsInquiryOrderDTO> selectNeedUploadData(String date);
 }

+ 3 - 4
fs-service/src/main/java/com/fs/his/mapper/FsPrescribeDrugMapper.java

@@ -2,10 +2,7 @@ package com.fs.his.mapper;
 
 import java.util.List;
 
-import com.fs.his.domain.FsDoctorPrescribeDrug;
-import com.fs.his.domain.FsPrescribe;
-import com.fs.his.domain.FsPrescribeDrug;
-import com.fs.his.domain.FsStoreProduct;
+import com.fs.his.domain.*;
 import org.apache.ibatis.annotations.Param;
 import org.apache.ibatis.annotations.Select;
 import org.springframework.stereotype.Service;
@@ -73,4 +70,6 @@ public interface FsPrescribeDrugMapper
     List<FsDoctorPrescribeDrug> selectFsPrescribeDrugListByImg2();
     @Select("select * from fs_store_product where product_name=#{drugName} and store_id=#{storeId} LIMIT 1 ")
     FsStoreProduct selectFsPrescribeDrugCode(@Param("drugName") String drugName, @Param("storeId")Long storeId);
+
+    List<FsPrescribeDrugDTO> selectDrugList(Long prescribeId);
 }

+ 6 - 0
fs-service/src/main/java/com/fs/his/mapper/FsPrescribeMapper.java

@@ -1,6 +1,8 @@
 package com.fs.his.mapper;
 
 import java.util.List;
+import java.util.Map;
+
 import com.fs.his.domain.FsPrescribe;
 import com.fs.his.param.FsPrescribeListDCompanyParam;
 import com.fs.his.param.FsPrescribeListDParam;
@@ -283,4 +285,8 @@ public interface FsPrescribeMapper
     @Select("select p.prescribe_id from fs_store_order o LEFT JOIN fs_prescribe p on p.store_order_id =o.order_id where o.status=2 and  o.order_type=2 and p.prescribe_img_store_url is null ")
     List<Long> selectFsPrescribeByPrescribeIdByOrderType();
 
+    List<Map<String,Object>> selectUploadData(String date);
+
+    @Select("select count(1) from fs_prescribe where inquiry_order_id = #{orderId}")
+    int selectByOrderId(Long orderId);
 }

+ 2 - 7
fs-service/src/main/java/com/fs/his/mapper/FsStorePaymentMapper.java

@@ -74,10 +74,7 @@ public interface FsStorePaymentMapper
             " LEFT JOIN  fs_user u ON u.user_id=sp.user_id LEFT JOIN fs_store s ON s.store_id=sp.store_id " +
             " left join company_user cu on sp.company_user_id=cu.user_id " +
             " left join company c on c.company_id=sp.company_id "+
-            "LEFT JOIN (SELECT t.* FROM ( SELECT sp2.*, ROW_NUMBER() OVER (PARTITION BY sp2.business_code ORDER BY sp2.create_time DESC, sp2.payment_id DESC) as rn " +
-            "FROM fs_store_payment sp2) t WHERE t.rn = 1) " +
-            "latest_sp ON latest_sp.business_code = sp.business_code "+
-            "LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp.app_id" +
+            " left join fs_course_play_source_config csc ON csc.appid = sp.app_id " +
             " where 1=1 " +
             "            <if test=\"maps.payCode != null  and maps.payCode != ''\"> and sp.pay_code = #{maps.payCode}</if>\n" +
             "            <if test=\"maps.coursePlaySourceConfigId != null\"> and csc.id = #{maps.coursePlaySourceConfigId}</if>\n" +
@@ -208,9 +205,6 @@ public interface FsStorePaymentMapper
             "LEFT JOIN company_user cu ON \n" +
             "    ( cu.user_id = fso.company_user_id) OR\n" +
             "    (cu.user_id = fio.company_user_id) " +
-            "LEFT JOIN (SELECT t.* FROM ( SELECT sp2.*, ROW_NUMBER() OVER (PARTITION BY sp2.business_code ORDER BY sp2.create_time DESC, sp2.payment_id DESC) as rn " +
-            "FROM fs_store_payment sp2) t WHERE t.rn = 1) " +
-            "latest_sp ON latest_sp.business_code = sp.business_code "+
             "LEFT JOIN fs_course_play_source_config csc ON csc.appid = sp.app_id" +
             " where 1=1 " +
             "            <if test=\"maps.payCode != null  and maps.payCode != ''\"> and sp.pay_code = #{maps.payCode}</if>\n" +
@@ -236,6 +230,7 @@ public interface FsStorePaymentMapper
             "            <if test=\"maps.refundEndTime != null \">  and DATE(sp.refund_time) &lt;= DATE(#{maps.refundEndTime})</if>\n" +
             "            <if test=\"maps.payBeginTime != null \">  and DATE(sp.pay_time) &gt;= DATE(#{maps.payBeginTime})</if>\n" +
             "            <if test=\"maps.payEndTime != null \">  and DATE(sp.pay_time) &lt;= DATE(#{maps.payEndTime})</if>\n" +
+            "            <if test=\"maps.appId != null\"> and csc.appid = #{maps.appId}</if>\n" +
             " ORDER BY payment_id desc  "+
             "</script>"})
     List<FsStorePaymentExcelVO> selectFsStorePaymentExcelVO(@Param("maps") FsStorePaymentParam fsStorePayment);

+ 5 - 0
fs-service/src/main/java/com/fs/his/service/IFsPrescribeService.java

@@ -1,6 +1,7 @@
 package com.fs.his.service;
 
 import java.util.List;
+import java.util.Map;
 
 import com.fs.common.core.domain.R;
 import com.fs.his.domain.FsPackageOrder;
@@ -106,4 +107,8 @@ public interface IFsPrescribeService
     void PrescribeStoreImg(Long id);
 
     List<FsPrescribeListDVO> selectFsPrescribeListDVOByCompanyUser(FsPrescribeListDCompanyParam param);
+
+    List<Map<String,Object>> selectUploadDate(String date);
+
+    int selectPrescribeByinquiryOrderId(Long orderId);
 }

+ 10 - 0
fs-service/src/main/java/com/fs/his/service/impl/FsPrescribeServiceImpl.java

@@ -966,4 +966,14 @@ public class FsPrescribeServiceImpl implements IFsPrescribeService
 
     }
 
+    @Override
+    public List<Map<String,Object>> selectUploadDate(String date) {
+        return fsPrescribeMapper.selectUploadData(date);
+    }
+
+    @Override
+    public int selectPrescribeByinquiryOrderId(Long orderId) {
+        return fsPrescribeMapper.selectByOrderId(orderId);
+    }
+
 }

+ 23 - 1
fs-service/src/main/java/com/fs/huifuPay/sdk/opps/core/utils/HuiFuUtils.java

@@ -26,13 +26,14 @@ import com.fs.huifuPay.service.HuiFuService;
 import com.fs.system.domain.SysConfig;
 import com.fs.system.mapper.SysConfigMapper;
 import com.google.gson.Gson;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
 
-
+@Slf4j
 public class HuiFuUtils {
     private static ICompanyDivConfigService companyDivConfigService = SpringUtils.getBean(ICompanyDivConfigService.class);
     private static ICompanyDivItemService companyDivItemService = SpringUtils.getBean(ICompanyDivItemService.class);
@@ -193,6 +194,24 @@ public class HuiFuUtils {
         if (companyDivItem != null) {
             companyDivItem.setIsPay(1);
             companyDivItemService.updateCompanyDivItem(companyDivItem);
+            try {
+                //查询是否分账payment
+                FsStorePayment fsStorePayment = fsStorePaymentMapper.selectFsStorePaymentByPaymentCode(payCode);
+                if (fsStorePayment == null) {
+                    FsStorePaymentScrm fsStorePaymentScrm = fsStorePaymentScrmMapper.selectFsStorePaymentByPaymentCode(payCode);
+                    if (fsStorePaymentScrm != null) {
+                        fsStorePaymentScrm.setShareStatus(1);
+                        fsStorePaymentScrm.setShareMoney(fsStorePaymentScrm.getPayMoney());
+                        fsStorePaymentScrmMapper.updateFsStorePayment(fsStorePaymentScrm);
+                    }
+                } else {
+                    fsStorePayment.setShareStatus(1);
+                    fsStorePayment.setShareMoney(fsStorePayment.getPayMoney());
+                    fsStorePaymentMapper.updateFsStorePayment(fsStorePayment);
+                }
+            } catch (Exception e) {
+                log.error("更新payment表分账状态失败{}", e.getMessage());
+            }
         }
     }
 
@@ -359,6 +378,9 @@ public class HuiFuUtils {
                         break;
                 }
                 confirmOrder.setOrgReqSeqId(orgReqSeqId);
+                if (payTime == null) {
+                    return;
+                }
                 confirmOrder.setOrgReqDate(DateUtils.parseDateToStr("yyyyMMdd", payTime));
                 confirmOrder.setAppId(appId);
                 HuiFuQueryOrderResult huiFuResult = huiFuService.delayTransConfirm(confirmOrder);

+ 9 - 0
fs-service/src/main/resources/application-config-druid-bnkc.yml

@@ -91,3 +91,12 @@ wx_miniapp_temp:
   inquiry_temp_id:
 
 
+
+
+jwt:
+  # 加密秘钥
+  secret: 8d1e6a2f0d579f86b67cde581c0f9eb5
+  # token有效时长,7天,单位秒
+  expire: 31536000
+  header: AppToken
+

+ 26 - 0
fs-service/src/main/resources/mapper/his/FsInquiryOrderMapper.xml

@@ -270,5 +270,31 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <if test="maps.doctorAccount != null"> and dc.account = #{maps.doctorAccount}</if>
         <if test="maps.companyUserNickName != null and maps.companyUserNickName != ''"> and cu.nick_name like concat( #{maps.companyUserNickName}, '%')</if>
     </select>
+    <!--只查询有首诊图片路径的数据上传-->
+    <select id="selectNeedUploadData" resultType="com.fs.his.domain.FsInquiryOrderDTO">
+        SELECT
+            fio.*,
+            fior.patient_json->>'$.reportImages' as reportImages,
+            fior.inquiry_result as inquiryResult,
+            fp.patient_name,
+            fd.id_card as idCard,
+            fd.sex as sex,
+            fp.self_med_history as selfMedHistory,
+            fd.doctor_name,
+            fh.hospital_name as json,
+            fdp.dept_name as deptName,
+            fdp.dept_code as deptCode,
+            fd.certificate_code as certificateCode
+        FROM fs_inquiry_order fio
+                 INNER JOIN fs_inquiry_order_report fior ON fior.order_id = fio.order_id
+                 LEFT JOIN fs_doctor fd ON fd.doctor_id = fio.doctor_id
+                 LEFT JOIN fs_hospital fh ON fd.hospital_id = fh.hospital_id
+                 LEFT JOIN fs_department fdp ON fdp.dept_id = fio.department_id
+                 LEFT JOIN fs_patient fp ON fp.patient_id = fio.patient_id
+        WHERE
+            fio.create_time >= #{date}
+          AND fior.patient_json IS NOT NULL
+          AND fior.patient_json->>'$.reportImages' != '';
+    </select>
 
 </mapper>

+ 27 - 0
fs-service/src/main/resources/mapper/his/FsPrescribeDrugMapper.xml

@@ -50,6 +50,33 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <include refid="selectFsPrescribeDrugVo"/>
         where drug_id = #{drugId}
     </select>
+    <select id="selectDrugList" resultType="com.fs.his.domain.FsPrescribeDrugDTO">
+        SELECT
+            fpd.drug_id,
+            fpd.prescribe_id,
+            fpd.is_drug,
+            fpd.drug_name,
+            fpd.drug_spec,
+            fpd.usage_method,
+            fpd.usage_frequency_unit,
+            fpd.usage_per_use_count,
+            fpd.usage_per_use_unit,
+            fpd.usage_days,
+            fpd.drug_num,
+            fpd.drug_price,
+            fpd.drug_unit,
+            fpd.instructions,
+            fpd.drug_img_url,
+            fpd.product_id,
+            fpd.product_attr_value_id,
+            fpd.remark,
+            fpd.drug_type,
+            fsp.bar_code
+        FROM
+            fs_prescribe_drug fpd
+        LEFT JOIN fs_store_product fsp ON fsp.product_id = fpd.prescribe_id
+        WHERE fpd.prescribe_id = #{prescribeId}
+    </select>
 
     <insert id="insertFsPrescribeDrug" parameterType="FsPrescribeDrug" useGeneratedKeys="true" keyProperty="drugId">
         insert into fs_prescribe_drug

+ 29 - 0
fs-service/src/main/resources/mapper/his/FsPrescribeMapper.xml

@@ -270,4 +270,33 @@
         <if test="orderStatus != null "> and fso.`status` = #{orderStatus}</if>
         <if test="storeId != null "> and so.store_id = #{storeId}</if>
     </select>
+
+    <!--只需要当天且开具了电子处方的数据,据观察数据量很少不考虑分页-->
+    <select id="selectUploadData" resultType="java.util.Map">
+        SELECT
+            so.*,
+            us.nick_name,
+            dc.doctor_name,
+            dc.certificate_code,
+            dp.doctor_name doctor_drug_name,
+            dp.certificate_code as doctor_drug_code,
+            fso.order_code,
+            fso.`status` order_status,
+            fso.total_price,
+            fsp.id_card,
+            fh.hospital_name,
+            fd.dept_name,
+            fd.dept_code
+        FROM
+            fs_prescribe so
+                LEFT JOIN fs_user us ON us.user_id = so.user_id
+                LEFT JOIN fs_doctor dc ON dc.doctor_id = so.doctor_id
+                LEFT JOIN fs_doctor dp ON dp.doctor_id = so.drug_doctor_id
+                LEFT JOIN fs_store_order fso ON fso.order_id = so.store_order_id
+                LEFT JOIN fs_patient fsp ON fsp.patient_id = so.patient_id
+                LEFT JOIN fs_hospital fh ON fh.hospital_id = dc.hospital_id
+                LEFT JOIN fs_department fd ON fd.dept_id = dc.dept_id
+        WHERE so.create_time > #{date}
+        AND so.prescribe_img_url is not null
+    </select>
 </mapper>