ソースを参照

商城处方药师拒方功能

cgp 2 日 前
コミット
e2bc9af00c
18 ファイル変更488 行追加749 行削除
  1. 35 18
      fs-doctor-app/src/main/java/com/fs/app/controller/FsPrescribeDataScrmController.java
  2. 0 95
      fs-service/src/main/java/com/fs/his/domain/FsPrescribeDataScrmDrug.java
  3. 3 0
      fs-service/src/main/java/com/fs/his/dto/FsPrescribeDataDrugDoctorUpdateDto.java
  4. 0 61
      fs-service/src/main/java/com/fs/his/mapper/FsPrescribeDataScrmDrugMapper.java
  5. 11 0
      fs-service/src/main/java/com/fs/his/mapper/FsPrescribeDataScrmMapper.java
  6. 9 0
      fs-service/src/main/java/com/fs/his/mapper/FsPrescribeDrugDataScrmMapper.java
  7. 9 0
      fs-service/src/main/java/com/fs/his/mapper/PrescribeScrmTaskRecordMapper.java
  8. 0 60
      fs-service/src/main/java/com/fs/his/service/IFsPrescribeDataScrmDrugService.java
  9. 1 12
      fs-service/src/main/java/com/fs/his/service/IFsPrescribeDataScrmService.java
  10. 17 0
      fs-service/src/main/java/com/fs/his/service/PrescriptionTaskRecordService.java
  11. 0 86
      fs-service/src/main/java/com/fs/his/service/impl/FsPrescribeDataScrmDrugServiceImpl.java
  12. 60 230
      fs-service/src/main/java/com/fs/his/service/impl/FsPrescribeDataScrmServiceImpl.java
  13. 288 3
      fs-service/src/main/java/com/fs/his/service/impl/PrescriptionTaskRecordServiceImpl.java
  14. 8 0
      fs-service/src/main/java/com/fs/qw/vo/FsPrescribeDataScrmVO.java
  15. 0 179
      fs-service/src/main/resources/mapper/his/FsPrescribeDataScrmDrugMapper.xml
  16. 30 5
      fs-service/src/main/resources/mapper/his/FsPrescribeDataScrmMapper.xml
  17. 13 0
      fs-service/src/main/resources/mapper/his/FsPrescribeDrugDataScrmMapper.xml
  18. 4 0
      fs-service/src/main/resources/mapper/his/PrescribeScrmTaskRecordMapper.xml

+ 35 - 18
fs-doctor-app/src/main/java/com/fs/app/controller/FsPrescribeDataScrmController.java

@@ -110,21 +110,6 @@ public class FsPrescribeDataScrmController extends BaseController
         return getDataTable(list);
     }
 
-    /**
-     * 药师---查询待审核商城处方列表
-     * */
-    @GetMapping("/pendingStorePrescribeList")
-    public TableDataInfo pendingStorePrescribeList(FsPrescribeDataDrugDoctorQueryDto queryDto){
-        String doctorId = getDoctorId();
-        if (StringUtils.isBlank(doctorId)){
-            throw new CustomException("登录已过期,请重新登录");
-        }
-        queryDto.setDrugDoctorId(Long.valueOf(doctorId));
-        PageHelper.startPage(queryDto.getPageNum(),queryDto.getPageSize());
-        List<FsPrescribeDataScrmVO> list=fsPrescribeScrmService.pendingStorePrescribeList(queryDto);
-        return getDataTable(list);
-    }
-
     /**
      * 获取医生、药师签名信息
      * @param doctorIds 医生id和药师id
@@ -149,7 +134,7 @@ public class FsPrescribeDataScrmController extends BaseController
     }
 
     /**
-     * 更新处方部分基本信息(诊断、医嘱、过敏史等),不改变状态
+     * 医生更新处方部分基本信息(诊断、医嘱、过敏史等),不改变状态
      */
     @PutMapping("/submitBasicInfo")
     public AjaxResult submitBasicInfo(@RequestBody FsPrescribeDataBasicInfoDto basicInfoDto) {
@@ -162,7 +147,7 @@ public class FsPrescribeDataScrmController extends BaseController
     }
 
     /**
-     * 最终提交处方(确认开方),包含药品列表
+     * 医生最终提交处方(确认开方),包含药品列表
      */
     @PostMapping("/submitPrescribe")
     public AjaxResult submitPrescribe(@RequestBody FsPrescribeDataSubmitDto submitDto) {
@@ -175,7 +160,7 @@ public class FsPrescribeDataScrmController extends BaseController
     }
 
     /**
-     * 商城处方-医生执行拒方
+     * 商城处方-医生拒方
      * */
     @PostMapping("/doctorRejectScrmPrescribe")
     public AjaxResult doctorExecuteScrmPrescribe(@RequestBody FsPrescribeDataDoctorUpdateDto updateDto){
@@ -189,6 +174,38 @@ public class FsPrescribeDataScrmController extends BaseController
         }
         return AjaxResult.error("网络错误,提交失败");
     }
+
+    /**
+     * 药师---查询待审核商城处方列表
+     * */
+    @GetMapping("/pendingStorePrescribeList")
+    public TableDataInfo pendingStorePrescribeList(FsPrescribeDataDrugDoctorQueryDto queryDto){
+        String doctorId = getDoctorId();
+        if (StringUtils.isBlank(doctorId)){
+            throw new CustomException("登录已过期,请重新登录");
+        }
+        queryDto.setDrugDoctorId(Long.valueOf(doctorId));
+        PageHelper.startPage(queryDto.getPageNum(),queryDto.getPageSize());
+        List<FsPrescribeDataScrmVO> list=fsPrescribeScrmService.pendingStorePrescribeList(queryDto);
+        return getDataTable(list);
+    }
+
+    /**
+     * 药师---审核商城处方
+     */
+    @GetMapping("/auditProcess")
+    public AjaxResult auditProcess(FsPrescribeDataDrugDoctorUpdateDto updateDto) {
+        String doctorId = getDoctorId();
+        if (StringUtils.isBlank(doctorId)) {
+            throw new CustomException("登录已过期,请重新登录");
+        }
+        updateDto.setDrugDoctorId(Long.valueOf(doctorId));
+        int result = fsPrescribeScrmService.drugDoctorExecuteScrmPrescribe(updateDto);
+        if (result > 0) {
+            return AjaxResult.success();
+        }
+        return AjaxResult.error("网络错误,提交失败");
+    }
     /**
      * 获取当前登录医生id
      * */

+ 0 - 95
fs-service/src/main/java/com/fs/his/domain/FsPrescribeDataScrmDrug.java

@@ -1,95 +0,0 @@
-package com.fs.his.domain;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-import lombok.Data;
-import java.io.Serializable;
-import java.math.BigDecimal;
-
-/**
- * 商城处方药品表实体类
- * 
- * @author ruoyi
- * @date 2026-06-12
- */
-@Data
-@ApiModel(description = "商城处方药品表")
-public class FsPrescribeDataScrmDrug implements Serializable {
-    private static final long serialVersionUID = 1L;
-
-    /** ID */
-    @ApiModelProperty(value = "ID")
-    private Long drugId;
-
-    /** 处方ID */
-    @ApiModelProperty(value = "处方ID")
-    private Long prescribeId;
-
-    /** 药品名称 */
-    @ApiModelProperty(value = "药品名称")
-    private String drugName;
-
-    /** 规格 */
-    @ApiModelProperty(value = "规格")
-    private String drugSpec;
-
-    /** 使用方法 */
-    @ApiModelProperty(value = "使用方法")
-    private String usageMethod;
-
-    /** 药品频次 */
-    @ApiModelProperty(value = "药品频次")
-    private String usageFrequencyUnit;
-
-    /** 每次用药数量 */
-    @ApiModelProperty(value = "每次用药数量")
-    private String usagePerUseCount;
-
-    /** 每次用药单位 */
-    @ApiModelProperty(value = "每次用药单位")
-    private String usagePerUseUnit;
-
-    /** 天数 */
-    @ApiModelProperty(value = "天数")
-    private String usageDays;
-
-    /** 药品价格 */
-    @ApiModelProperty(value = "药品价格")
-    private BigDecimal drugPrice;
-
-    /** 药品数量 */
-    @ApiModelProperty(value = "药品数量")
-    private Long drugNum;
-
-    /** 药品数量单位 */
-    @ApiModelProperty(value = "药品数量单位")
-    private String drugUnit;
-
-    /** 药品说明书 */
-    @ApiModelProperty(value = "药品说明书")
-    private String instructions;
-
-    /** 产品ID */
-    @ApiModelProperty(value = "产品ID")
-    private Long productId;
-
-    /** 药品图片 */
-    @ApiModelProperty(value = "药品图片")
-    private String drugImgUrl;
-
-    /** 规格ID */
-    @ApiModelProperty(value = "规格ID")
-    private Long productAttrValueId;
-
-    /** 备注 */
-    @ApiModelProperty(value = "备注")
-    private String remark;
-
-    /** 药品类型:1西药 2中药 */
-    @ApiModelProperty(value = "药品类型:1西药 2中药")
-    private Integer drugType;
-
-    /** 是否药品(1:是,0:不是) */
-    @ApiModelProperty(value = "是否药品(1:是,0:不是)")
-    private Integer isDrug;
-}

+ 3 - 0
fs-service/src/main/java/com/fs/his/dto/FsPrescribeDataDrugDoctorUpdateDto.java

@@ -10,6 +10,9 @@ public class FsPrescribeDataDrugDoctorUpdateDto {
     //处方状态 0待药师审核 1审核通过 2药师审核不通过 */
     private Integer status;
 
+    /** 医生是否确认 0待医生开方 1已开方待药师审核 -1医生拒方 */
+    private Integer doctorConfirm;
+
     /** 药师id*/
     private Long drugDoctorId;
 

+ 0 - 61
fs-service/src/main/java/com/fs/his/mapper/FsPrescribeDataScrmDrugMapper.java

@@ -1,61 +0,0 @@
-package com.fs.his.mapper;
-
-import com.fs.his.domain.FsPrescribeDataScrmDrug;
-import org.apache.ibatis.annotations.Param;
-import java.util.List;
-
-/**
- * 商城处方药品表Mapper接口
- * 
- * @author ruoyi
- * @date 2026-06-12
- */
-public interface FsPrescribeDataScrmDrugMapper {
-    /**
-     * 查询商城处方药品表
-     * 
-     * @param drugId 药品ID
-     * @return 商城处方药品表
-     */
-    public FsPrescribeDataScrmDrug selectFsPrescribeDataScrmDrugById(Long drugId);
-
-    /**
-     * 查询商城处方药品表列表
-     * 
-     * @param fsPrescribeDataScrmDrug 商城处方药品表
-     * @return 商城处方药品表集合
-     */
-    public List<FsPrescribeDataScrmDrug> selectFsPrescribeDataScrmDrugList(FsPrescribeDataScrmDrug fsPrescribeDataScrmDrug);
-
-    /**
-     * 新增商城处方药品表
-     * 
-     * @param fsPrescribeDataScrmDrug 商城处方药品表
-     * @return 结果
-     */
-    public int insertFsPrescribeDataScrmDrug(FsPrescribeDataScrmDrug fsPrescribeDataScrmDrug);
-
-    /**
-     * 修改商城处方药品表
-     * 
-     * @param fsPrescribeDataScrmDrug 商城处方药品表
-     * @return 结果
-     */
-    public int updateFsPrescribeDataScrmDrug(FsPrescribeDataScrmDrug fsPrescribeDataScrmDrug);
-
-    /**
-     * 删除商城处方药品表
-     * 
-     * @param drugId 药品ID
-     * @return 结果
-     */
-    public int deleteFsPrescribeDataScrmDrugById(Long drugId);
-
-    /**
-     * 批量删除商城处方药品表
-     * 
-     * @param drugIds 需要删除的药品ID数组
-     * @return 结果
-     */
-    public int deleteFsPrescribeDataScrmDrugByIds(Long[] drugIds);
-}

+ 11 - 0
fs-service/src/main/java/com/fs/his/mapper/FsPrescribeDataScrmMapper.java

@@ -5,6 +5,7 @@ import com.fs.his.dto.FsPrescribeDataDoctorQueryDto;
 import com.fs.his.dto.FsPrescribeDataDrugDoctorQueryDto;
 import com.fs.his.vo.FsPrescribeDataScrmImgVO;
 import com.fs.qw.vo.FsPrescribeDataScrmVO;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 
@@ -83,4 +84,14 @@ public interface FsPrescribeDataScrmMapper
      * 清除商城处方图片(根据处方id设置处方图片为null)
      * */
     void clearPrescribeUrl(Long prescribeId);
+
+    /**
+     * 根据ids查询商城处方列表
+     * */
+    List<FsPrescribeDataScrm> selectFsPrescribeDataScrmListByIds(@Param("prescribeIds") List<Long> prescribeIds);
+
+    /**
+     *  批量更新商城处方图片URL
+     * */
+    int updateBatchPrescribeDataScrmURL(@Param("fsPrescribeDataScrms") List<FsPrescribeDataScrm> fsPrescribeDataScrms);
 }

+ 9 - 0
fs-service/src/main/java/com/fs/his/mapper/FsPrescribeDrugDataScrmMapper.java

@@ -4,6 +4,7 @@ import com.fs.his.domain.FsPrescribeDrugDataScrm;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
+import java.util.Set;
 
 /**
  * 处方药品表Mapper接口
@@ -68,6 +69,14 @@ public interface FsPrescribeDrugDataScrmMapper {
      */
     List<FsPrescribeDrugDataScrm> selectFsPrescribeDrugDataScrmByPrescribeId(Long prescribeId);
 
+    /**
+     * 根据处方ID查询商城处方药品表
+     *
+     * @param prescribeIds 处方ID集合
+     * @return 处方药品表集合
+     */
+    List<FsPrescribeDrugDataScrm> selectFsPrescribeDataScrmDrugListByPrescribeIds(@Param("prescribeIds") Set<Long> prescribeIds);
+
     /**
      * 根据处方ID删除处方药品表
      *

+ 9 - 0
fs-service/src/main/java/com/fs/his/mapper/PrescribeScrmTaskRecordMapper.java

@@ -1,7 +1,10 @@
 package com.fs.his.mapper;
 
 import com.fs.his.domain.PrescribeScrmTaskRecord;
+import com.fs.his.domain.PrescriptionTaskRecord;
 import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
 import java.util.List;
 
 /**
@@ -58,4 +61,10 @@ public interface PrescribeScrmTaskRecordMapper {
      * @return 结果
      */
     public int deletePrescribeScrmTaskRecordByIds(Long[] ids);
+
+
+    /**
+     * 查询待处理的商城处方任务记录
+     * */
+    public List<PrescribeScrmTaskRecord> selectPendingPrescribeScrmTaskRecord();
 }

+ 0 - 60
fs-service/src/main/java/com/fs/his/service/IFsPrescribeDataScrmDrugService.java

@@ -1,60 +0,0 @@
-package com.fs.his.service;
-
-import com.fs.his.domain.FsPrescribeDataScrmDrug;
-import java.util.List;
-
-/**
- * 商城处方药品表Service接口
- * 
- * @author ruoyi
- * @date 2026-06-12
- */
-public interface IFsPrescribeDataScrmDrugService {
-    /**
-     * 查询商城处方药品表
-     * 
-     * @param drugId 药品ID
-     * @return 商城处方药品表
-     */
-    public FsPrescribeDataScrmDrug selectFsPrescribeDataScrmDrugById(Long drugId);
-
-    /**
-     * 查询商城处方药品表列表
-     * 
-     * @param fsPrescribeDataScrmDrug 商城处方药品表
-     * @return 商城处方药品表集合
-     */
-    public List<FsPrescribeDataScrmDrug> selectFsPrescribeDataScrmDrugList(FsPrescribeDataScrmDrug fsPrescribeDataScrmDrug);
-
-    /**
-     * 新增商城处方药品表
-     * 
-     * @param fsPrescribeDataScrmDrug 商城处方药品表
-     * @return 结果
-     */
-    public int insertFsPrescribeDataScrmDrug(FsPrescribeDataScrmDrug fsPrescribeDataScrmDrug);
-
-    /**
-     * 修改商城处方药品表
-     * 
-     * @param fsPrescribeDataScrmDrug 商城处方药品表
-     * @return 结果
-     */
-    public int updateFsPrescribeDataScrmDrug(FsPrescribeDataScrmDrug fsPrescribeDataScrmDrug);
-
-    /**
-     * 批量删除商城处方药品表
-     * 
-     * @param drugIds 需要删除的药品ID数组
-     * @return 结果
-     */
-    public int deleteFsPrescribeDataScrmDrugByIds(Long[] drugIds);
-
-    /**
-     * 删除商城处方药品表信息
-     * 
-     * @param drugId 药品ID
-     * @return 结果
-     */
-    public int deleteFsPrescribeDataScrmDrugById(Long drugId);
-}

+ 1 - 12
fs-service/src/main/java/com/fs/his/service/IFsPrescribeDataScrmService.java

@@ -73,21 +73,10 @@ public interface IFsPrescribeDataScrmService
 
 
     /**
-     * 商城处方-医生执行拒方
+     * 商城处方-医生拒方
      * */
     int doctorRejectScrmPrescribe(FsPrescribeDataDoctorUpdateDto updateDto);
 
-    /**
-     * 生成商城处方图片(异步任务调用)
-     * @param prescribeId 处方ID
-     * @param signFlag 签名标识:1-仅医生签名,2-医生+药师签名
-     * @return Map 包含两个 key:
-     *         "prescribeImgUrl"      - 中药处方图片地址
-     *         "prescribeImgStoreUrl" - 西药处方图片地址
-     *         未生成对应的图片时 value 为 null
-     */
-    Map<String, String> prescribeScrmImgYsyTask(Long prescribeId, Integer signFlag);
-
     /**
      * 清理处方图片(设置业务表字段为null)
      */

+ 17 - 0
fs-service/src/main/java/com/fs/his/service/PrescriptionTaskRecordService.java

@@ -1,5 +1,22 @@
 package com.fs.his.service;
 
+import java.util.Map;
+
 public interface PrescriptionTaskRecordService {
+    //生成互医处方单
     public void generatePrescript();
+
+    //生成商城处方单
+    public void generateScrmPrescript();
+
+    /**
+     * 生成商城处方图片(异步任务调用)
+     * @param prescribeId 处方ID
+     * @param signFlag 签名标识:1-仅医生签名,2-医生+药师签名
+     * @return Map 包含两个 key:
+     *         "prescribeImgUrl"      - 中药处方图片地址
+     *         "prescribeImgStoreUrl" - 西药处方图片地址
+     *         未生成对应的图片时 value 为 null
+     */
+    Map<String, String> prescribeScrmImgYsyTask(Long prescribeId, Integer signFlag);
 }

+ 0 - 86
fs-service/src/main/java/com/fs/his/service/impl/FsPrescribeDataScrmDrugServiceImpl.java

@@ -1,86 +0,0 @@
-package com.fs.his.service.impl;
-
-import com.fs.his.domain.FsPrescribeDataScrmDrug;
-import com.fs.his.mapper.FsPrescribeDataScrmDrugMapper;
-import com.fs.his.service.IFsPrescribeDataScrmDrugService;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import java.util.List;
-
-/**
- * 商城处方药品表Service业务层处理
- * 
- * @author ruoyi
- * @date 2026-06-12
- */
-@Service
-public class FsPrescribeDataScrmDrugServiceImpl implements IFsPrescribeDataScrmDrugService {
-    @Autowired
-    private FsPrescribeDataScrmDrugMapper fsPrescribeDataScrmDrugMapper;
-
-    /**
-     * 查询商城处方药品表
-     * 
-     * @param drugId 药品ID
-     * @return 商城处方药品表
-     */
-    @Override
-    public FsPrescribeDataScrmDrug selectFsPrescribeDataScrmDrugById(Long drugId) {
-        return fsPrescribeDataScrmDrugMapper.selectFsPrescribeDataScrmDrugById(drugId);
-    }
-
-    /**
-     * 查询商城处方药品表列表
-     * 
-     * @param fsPrescribeDataScrmDrug 商城处方药品表
-     * @return 商城处方药品表
-     */
-    @Override
-    public List<FsPrescribeDataScrmDrug> selectFsPrescribeDataScrmDrugList(FsPrescribeDataScrmDrug fsPrescribeDataScrmDrug) {
-        return fsPrescribeDataScrmDrugMapper.selectFsPrescribeDataScrmDrugList(fsPrescribeDataScrmDrug);
-    }
-
-    /**
-     * 新增商城处方药品表
-     * 
-     * @param fsPrescribeDataScrmDrug 商城处方药品表
-     * @return 结果
-     */
-    @Override
-    public int insertFsPrescribeDataScrmDrug(FsPrescribeDataScrmDrug fsPrescribeDataScrmDrug) {
-        return fsPrescribeDataScrmDrugMapper.insertFsPrescribeDataScrmDrug(fsPrescribeDataScrmDrug);
-    }
-
-    /**
-     * 修改商城处方药品表
-     * 
-     * @param fsPrescribeDataScrmDrug 商城处方药品表
-     * @return 结果
-     */
-    @Override
-    public int updateFsPrescribeDataScrmDrug(FsPrescribeDataScrmDrug fsPrescribeDataScrmDrug) {
-        return fsPrescribeDataScrmDrugMapper.updateFsPrescribeDataScrmDrug(fsPrescribeDataScrmDrug);
-    }
-
-    /**
-     * 批量删除商城处方药品表
-     * 
-     * @param drugIds 需要删除的商城处方药品表主键
-     * @return 结果
-     */
-    @Override
-    public int deleteFsPrescribeDataScrmDrugByIds(Long[] drugIds) {
-        return fsPrescribeDataScrmDrugMapper.deleteFsPrescribeDataScrmDrugByIds(drugIds);
-    }
-
-    /**
-     * 删除商城处方药品表信息
-     * 
-     * @param drugId 药品ID
-     * @return 结果
-     */
-    @Override
-    public int deleteFsPrescribeDataScrmDrugById(Long drugId) {
-        return fsPrescribeDataScrmDrugMapper.deleteFsPrescribeDataScrmDrugById(drugId);
-    }
-}

+ 60 - 230
fs-service/src/main/java/com/fs/his/service/impl/FsPrescribeDataScrmServiceImpl.java

@@ -4,19 +4,13 @@ import cn.hutool.core.util.IdUtil;
 import com.fs.common.BeanCopyUtils;
 import com.fs.common.exception.CustomException;
 import com.fs.common.utils.DateUtils;
-import com.fs.common.utils.uuid.UUID;
 import com.fs.his.domain.*;
 import com.fs.his.dto.*;
 import com.fs.his.enums.DoctorTypeEnum;
 import com.fs.his.mapper.*;
-import com.fs.his.param.PrescribeXyImgParam;
 import com.fs.his.service.IFsPrescribeDataScrmService;
 import com.fs.his.service.IPollingAssignDoctorService;
-import com.fs.his.service.PrescriptionImageService;
 import com.fs.his.vo.DoctorSignVO;
-import com.fs.his.vo.FsPrescribeDataScrmImgVO;
-import com.fs.hisStore.domain.FsStoreProductScrm;
-import com.fs.hisStore.mapper.FsStoreProductScrmMapper;
 import com.fs.qw.domain.FsCompanyCustomer;
 import com.fs.qw.mapper.FsCompanyCustomerMapper;
 import com.fs.qw.service.IFsCompanyCustomerService;
@@ -24,14 +18,12 @@ import com.fs.qw.vo.FsPrescribeDataScrmVO;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
-import org.apache.http.util.Asserts;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.ApplicationContext;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.*;
-import java.util.function.Function;
 import java.util.stream.Collectors;
 
 /**
@@ -46,16 +38,12 @@ public class FsPrescribeDataScrmServiceImpl implements IFsPrescribeDataScrmServi
 
     @Autowired
     private FsPrescribeDataScrmMapper fsPrescribeDataScrmMapper;
+
     @Autowired
     private PrescribeScrmTaskRecordMapper scrmTaskRecordMapper;
+
     @Autowired
     private FsCompanyCustomerMapper companyCustomerMapper;
-    @Autowired
-    private FsPrescribeDataScrmDrugMapper dataScrmDrugMapper;
-    @Autowired
-    private PrescriptionImageService prescriptionImageService;
-    @Autowired
-    private FsStoreProductScrmMapper fsStoreProductScrmMapper;
 
     @Autowired
     private FsPrescribeDrugDataScrmMapper drugDataScrmMapper;
@@ -72,6 +60,9 @@ public class FsPrescribeDataScrmServiceImpl implements IFsPrescribeDataScrmServi
     @Autowired
     private IPollingAssignDoctorService pollingAssignDoctorService;
 
+    @Autowired
+    private FsPrescibeRecordDataScrmMapper fsPrescibeRecordDataScrmMapper;
+
     private IFsPrescribeDataScrmService self() {
         return applicationContext.getBean(IFsPrescribeDataScrmService.class);
     }
@@ -139,6 +130,17 @@ public class FsPrescribeDataScrmServiceImpl implements IFsPrescribeDataScrmServi
     @Override
     public List<FsPrescribeDataScrmVO> pendingStorePrescribeList(FsPrescribeDataDrugDoctorQueryDto queryDto) {
         List<FsPrescribeDataScrmVO> list = fsPrescribeDataScrmMapper.pendingStorePrescribeList(queryDto);
+        //收集处方id集合
+        Set<Long> prescribeIds = list.stream().map(FsPrescribeDataScrmVO::getPrescribeId).collect(Collectors.toSet());
+        //查询处方药品列表
+        if (CollectionUtils.isEmpty(prescribeIds)){
+            return Collections.emptyList();
+        }
+        List<FsPrescribeDrugDataScrm> drugList = drugDataScrmMapper.selectFsPrescribeDataScrmDrugListByPrescribeIds(prescribeIds);
+        //遍历两个集合将相同的处方id进行匹配
+        for (FsPrescribeDataScrmVO vo : list) {
+            vo.setDrugsList(drugList.stream().filter(d -> d.getPrescribeId().equals(vo.getPrescribeId())).collect(Collectors.toList()));
+        }
         return CollectionUtils.isEmpty(list) ? Collections.emptyList() : list;
     }
 
@@ -146,28 +148,24 @@ public class FsPrescribeDataScrmServiceImpl implements IFsPrescribeDataScrmServi
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int doctorRejectScrmPrescribe(FsPrescribeDataDoctorUpdateDto updateDto) {
+        if (getPrescribeIsDocument(updateDto.getPrescribeId())){
+            throw new CustomException("销售已制单,当前操作不可执行,请刷新后重试!");
+        }
         // 1. 清除原有基础处方图片
         clearPrescriptionImage(updateDto.getPrescribeId());
 
         // 2. 更新处方主记录
         FsPrescribeDataScrm updatePrescribe = new FsPrescribeDataScrm();
         BeanCopyUtils.copy(updateDto, updatePrescribe);
+        updatePrescribe.setDoctorConfirm(-1);
         int updateCount = fsPrescribeDataScrmMapper.updateFsPrescribeDataScrm(updatePrescribe);
-
-        // 3. 根据医生确认结果进行后续处理
-        if (updateDto.getDoctorConfirm() == 1) {
-            // 确认开方 → 异步生成医生签名处方图片
-            submitPrescribeImageTask(updateDto.getPrescribeId(), 1);
-            // 更新用户状态为待审核
-            updateCustomerStatus(updateDto.getPrescribeId(), WAIT_AUDIT);
-        } else if (updateDto.getDoctorConfirm() == -1) {
-            // 拒方
-            if (StringUtils.isBlank(updateDto.getAuditReason())) {
-                throw new CustomException("拒方原因不能为空");
-            }
-            // 更新用户状态为已拒方
-            updateCustomerStatus(updateDto.getPrescribeId(), REJECT_PRESCRIBE);
+        // 拒方
+        if (StringUtils.isBlank(updateDto.getAuditReason())) {
+            throw new CustomException("拒方原因不能为空");
         }
+        // 更新客户信息表状态为已拒方
+        updateCustomerStatus(updateDto.getPrescribeId(), REJECT_PRESCRIBE);
+
         return updateCount;
     }
 
@@ -175,16 +173,27 @@ public class FsPrescribeDataScrmServiceImpl implements IFsPrescribeDataScrmServi
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int drugDoctorExecuteScrmPrescribe(FsPrescribeDataDrugDoctorUpdateDto updateDto) {
+        if (getPrescribeIsDocument(updateDto.getPrescribeId())){
+            throw new CustomException("销售已制单,当前操作不可执行,请刷新后重试!");
+        }
+        FsPrescribeDataScrm prescribeDataScrm = fsPrescribeDataScrmMapper.selectFsPrescribeDataScrmByPrescribeId(updateDto.getPrescribeId());
+        if (prescribeDataScrm == null){
+            throw new CustomException("商城处方单不存在");
+        }
+        //生成商城处方单的审核记录
+        FsPrescibeRecordDataScrm record = new FsPrescibeRecordDataScrm();
+        BeanCopyUtils.copy(prescribeDataScrm, record);
+        fsPrescibeRecordDataScrmMapper.insertFsPrescibeRecordDataScrm(record);
         if (updateDto.getStatus() == 1) {
-            // 审核通过 → 异步生成医生+药师签名处方图片
+            // 审核通过 → 异步生成医生+药师签名处方图片任务
             submitPrescribeImageTask(updateDto.getPrescribeId(), 2);
             updateCustomerStatus(updateDto.getPrescribeId(), OPEN_PRESCRIBE);
         } else if (updateDto.getStatus() == 2) {
             // 审核不通过 → 清除处方图片,退回状态
             clearPrescriptionImage(updateDto.getPrescribeId());
+            updateDto.setDoctorConfirm(0);//药师审核不通过,处方医生状态回退为"待开方"
             updateCustomerStatus(updateDto.getPrescribeId(), IS_PRESCRIBING);
         }
-
         // 更新处方主记录
         FsPrescribeDataScrm updatePrescribe = new FsPrescribeDataScrm();
         BeanCopyUtils.copy(updateDto, updatePrescribe);
@@ -231,6 +240,9 @@ public class FsPrescribeDataScrmServiceImpl implements IFsPrescribeDataScrmServi
 
     @Override
     public int addDoctorAdvice(BeforePrescribeAddDoctorAdviceDTO addDoctorAdviceDTO) {
+        if (getPrescribeIsDocument(addDoctorAdviceDTO.getPrescribeId())){
+            throw new CustomException("销售已制单,当前操作不可执行,请刷新后重试!");
+        }
         //获取处方信息
         FsPrescribeDataScrm fsPrescribeDataScrm = fsPrescribeDataScrmMapper.selectFsPrescribeDataScrmByPrescribeId(addDoctorAdviceDTO.getPrescribeId());
         if (fsPrescribeDataScrm == null) {
@@ -249,6 +261,9 @@ public class FsPrescribeDataScrmServiceImpl implements IFsPrescribeDataScrmServi
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int updateBasicInfo(FsPrescribeDataBasicInfoDto basicInfoDto) {
+        if (getPrescribeIsDocument(basicInfoDto.getPrescribeId())){
+            throw new CustomException("销售已制单,当前操作不可执行,请刷新后重试!");
+        }
         FsPrescribeDataScrm update = new FsPrescribeDataScrm();
         update.setPrescribeId(basicInfoDto.getPrescribeId());
         update.setDiagnose(basicInfoDto.getDiagnose());
@@ -263,6 +278,9 @@ public class FsPrescribeDataScrmServiceImpl implements IFsPrescribeDataScrmServi
     @Override
     @Transactional(rollbackFor = Exception.class)
     public int submitPrescribe(FsPrescribeDataSubmitDto submitDto) {
+        if (getPrescribeIsDocument(submitDto.getPrescribeId())){
+            throw new CustomException("销售已制单,当前操作不可执行,请刷新后重试!");
+        }
         // 1. 清除原处方图片(如果有)
         clearPrescriptionImage(submitDto.getPrescribeId());
 
@@ -270,6 +288,7 @@ public class FsPrescribeDataScrmServiceImpl implements IFsPrescribeDataScrmServi
         FsPrescribeDataScrm update = new FsPrescribeDataScrm();
         BeanCopyUtils.copy(submitDto, update);
         update.setDoctorConfirm(1);  // 确认开方
+        update.setStatus(0);  // 待药师审核
         int updateCount = fsPrescribeDataScrmMapper.updateFsPrescribeDataScrm(update);
 
         // 3. 全量覆盖药品列表(删除旧的全部,插入新的)
@@ -281,7 +300,7 @@ public class FsPrescribeDataScrmServiceImpl implements IFsPrescribeDataScrmServi
             syncDrugsFullCover(submitDto.getPrescribeId(), submitDto.getDrugs());
         }
 
-        // 4. 异步生成处方图片(根据处方类型和药品)
+        // 4. 生成医生签名处方图片任务(根据处方类型和药品)
         submitPrescribeImageTask(submitDto.getPrescribeId(), 1);
 
         // 5. 更新用户状态为待审核(如果有需要)
@@ -372,123 +391,7 @@ public class FsPrescribeDataScrmServiceImpl implements IFsPrescribeDataScrmServi
         companyCustomerMapper.updateFsCompanyCustomer(mapCustomer);
     }
 
-    // ==================== 处方图片生成 ====================
-    /**
-     * 生成处方图片(异步任务调用)
-     * @param prescribeId 处方ID
-     * @param signFlag 签名标识:1-仅医生签名,2-医生+药师签名
-     * @return Map 包含两个 key:
-     *         "prescribeImgUrl"      - 中药处方图片地址
-     *         "prescribeImgStoreUrl" - 西药处方图片地址
-     *         未生成对应的图片时 value 为 null
-     */
-    @Override
-    public Map<String, String> prescribeScrmImgYsyTask(Long prescribeId, Integer signFlag) {
-        FsPrescribeDataScrmImgVO imgVO = fsPrescribeDataScrmMapper.selectFsPrescribeDataScrmImgVOByPrescribeId(prescribeId);
-        Asserts.notNull(imgVO, String.format("处方 %d 未找到!", prescribeId));
-        Asserts.notNull(imgVO.getDoctorId(), String.format("医生 %s 未找到!", imgVO.getDoctorId()));
-        Asserts.notNull(imgVO.getDrugDoctorId(), String.format("药师 %s 未找到!", imgVO.getDrugDoctorId()));
-
-        // 1. 获取并过滤药品
-        FsPrescribeDataScrmDrug query = new FsPrescribeDataScrmDrug();
-        query.setPrescribeId(prescribeId);
-        List<FsPrescribeDataScrmDrug> drugList = dataScrmDrugMapper.selectFsPrescribeDataScrmDrugList(query);
-        if (CollectionUtils.isEmpty(drugList)) {
-            throw new CustomException(String.format("处方单 %d 对应药品为空!", prescribeId));
-        }
-
-        List<FsPrescribeDataScrmDrug> effectiveDrugs = filterNonDrugScrmPrescribe(drugList);
-
-        // 2. 按药品类型分组
-        Map<Integer, List<FsPrescribeDataScrmDrug>> drugTypeMap = effectiveDrugs.stream()
-                .collect(Collectors.groupingBy(FsPrescribeDataScrmDrug::getDrugType));
-        List<FsPrescribeDataScrmDrug> westernDrugs = drugTypeMap.getOrDefault(1, Collections.emptyList()); // 西药
-        List<FsPrescribeDataScrmDrug> chineseDrugs = drugTypeMap.getOrDefault(2, Collections.emptyList()); // 中药
-
-        // 3. 根据处方类型决定要生成的图片
-        Integer prescribeType = imgVO.getPrescribeType();
-        boolean needWestern = (prescribeType == 1 || prescribeType == 3) && !westernDrugs.isEmpty();
-        boolean needChinese = (prescribeType == 2 || prescribeType == 3) && !chineseDrugs.isEmpty();
-
-        // 4. 分别生成图片并更新数据库
-        FsPrescribeDataScrm updateData = new FsPrescribeDataScrm();
-        updateData.setPrescribeId(prescribeId);
-        boolean hasUpdate = false;
-
-        // 生成西药图片 → prescribeImgStoreUrl
-        if (needWestern) {
-            if (StringUtils.isBlank(imgVO.getPrescribeImgStoreUrl())) {
-                String url = generatePrescriptionImageForType(imgVO, signFlag, westernDrugs);
-                updateData.setPrescribeImgStoreUrl(url);
-                hasUpdate = true;
-            } else {
-                log.info("处方 {} 西药图片已存在,跳过生成", prescribeId);
-            }
-        }
 
-        // 生成中药图片 → prescribeImgUrl
-        if (needChinese) {
-            if (StringUtils.isBlank(imgVO.getPrescribeImgUrl())) {
-                String url = generatePrescriptionImageForType(imgVO, signFlag, chineseDrugs);
-                updateData.setPrescribeImgUrl(url);
-                hasUpdate = true;
-            } else {
-                log.info("处方 {} 中药图片已存在,跳过生成", prescribeId);
-            }
-        }
-
-        if (hasUpdate) {
-            fsPrescribeDataScrmMapper.updateFsPrescribeDataScrm(updateData);
-        }
-
-        // 5. 构建返回结果(重新查询一次确保拿到最新值)
-        FsPrescribeDataScrmImgVO latest = fsPrescribeDataScrmMapper.selectFsPrescribeDataScrmImgVOByPrescribeId(prescribeId);
-        Map<String, String> result = new HashMap<>();
-        result.put("prescribeImgUrl", latest != null ? latest.getPrescribeImgUrl() : null);
-        result.put("prescribeImgStoreUrl", latest != null ? latest.getPrescribeImgStoreUrl() : null);
-        return result;
-    }
-
-    /**
-     * 生成处方图片(按药品类型)
-     */
-    private String generatePrescriptionImageForType(FsPrescribeDataScrmImgVO imgVO,
-                                                    Integer signFlag,
-                                                    List<FsPrescribeDataScrmDrug> drugList) {
-        PrescribeXyImgParam imgParam = new PrescribeXyImgParam();
-        imgParam.setTime(imgVO.getCreateTime());
-        imgParam.setPrescribeId(imgVO.getPrescribeCode());
-        imgParam.setPatientName(imgVO.getPatientName());
-        imgParam.setPatientGender(String.valueOf(imgVO.getPatientGender()));
-        imgParam.setPatientAge(imgVO.getPatientAge());
-        imgParam.setOutpatientId(imgVO.getPrescribeCode());
-
-        if (com.fs.common.utils.StringUtils.isNotBlank(imgVO.getRemark())) {
-            imgParam.setRemark(imgVO.getRemark());
-        } else {
-            log.error("PrescribeImgYsyTask 处方id:{},缺失医嘱内容", imgVO.getPrescribeId());
-            imgParam.setRemark("请按照用药说明书服用药品,如有不适,请及时就医!");
-        }
-
-        imgParam.setHistoryAllergic(imgVO.getHistoryAllergic());
-        imgParam.setDiagnose(imgVO.getDiagnose());
-        imgParam.setPrescribeDrug(convertToPrescribeDrugList(drugList));
-
-        // 签名设置(保底默认全部签名)
-        imgParam.setUrl(imgVO.getDoctorSign());
-        if (signFlag == null || signFlag == 2) {
-            imgParam.setDrugDoctorUrl(imgVO.getDrugDoctorSignUrl());
-        }
-
-        imgParam.setDoctorName(imgVO.getDoctorName());
-        imgParam.setAuditDoctor(imgVO.getDrugDoctorName());
-        imgParam.setTelPhone(imgVO.getPatientTel());
-        imgParam.setJobLicenseNumber(imgVO.getPractiseCode());
-        imgParam.setDoctorNo(imgVO.getDoctorCertificate());
-        imgParam.setDoctorTitle(imgVO.getDoctorPosition());
-
-        return prescriptionImageService.generatePrescriptionImage(imgParam);
-    }
 
     @Override
     public void clearPrescribeUrl(Long prescribeId) {
@@ -524,91 +427,18 @@ public class FsPrescribeDataScrmServiceImpl implements IFsPrescribeDataScrmServi
         self().clearPrescribeUrl(prescribeId);
     }
 
-    // ==================== 药品过滤与转换 ====================
     /**
-     * 根据产品最新状态过滤处方单药品列表。
-     * <p>
-     * 该方法的过滤规则如下:
-     * - 对于 productId 非空的处方药,使用其对应产品表(FsStoreProduct)中的 isDrug 状态进行判断,只保留 isDrug=1 的项。
-     * - 对于 productId 为空的处方药,直接使用其自身的 isDrug 状态进行判断,只保留 isDrug=1 的项。
-     * </p>
-     *
-     * @param prescribeDrugs 待过滤的处方单药品列表。如果为 null 或空,则直接返回空列表。
-     * @return 一个符合上述规则的新列表。
-     */
-    public List<FsPrescribeDataScrmDrug> filterNonDrugScrmPrescribe(List<FsPrescribeDataScrmDrug> prescribeDrugs) {
-        if (CollectionUtils.isEmpty(prescribeDrugs)) {
-            return Collections.emptyList();
-        }
-
-        Set<Long> productIds = prescribeDrugs.stream()
-                .map(FsPrescribeDataScrmDrug::getProductId)
-                .filter(Objects::nonNull)
-                .collect(Collectors.toSet());
-
-        List<FsStoreProductScrm> storeProductIns = Collections.emptyList();
-        if (!productIds.isEmpty()) {
-            storeProductIns = fsStoreProductScrmMapper.getStoreProductInProductIds(new ArrayList<>(productIds));
-            if (storeProductIns.isEmpty()) {
-                log.error("查询产品id列表:{}查询产品信息为空!", productIds);
-            }
-        }
-
-        Map<Long, FsStoreProductScrm> storeProductMap = storeProductIns.stream()
-                .collect(Collectors.toMap(FsStoreProductScrm::getProductId, Function.identity()));
-
-        List<FsPrescribeDataScrmDrug> filteredDrugs = new ArrayList<>();
-        for (FsPrescribeDataScrmDrug drug : prescribeDrugs) {
-            boolean shouldKeep = false;
-            if (drug.getProductId() != null) {
-                FsStoreProductScrm product = storeProductMap.get(drug.getProductId());
-                if (product != null) {
-                    shouldKeep = Integer.valueOf(1).equals(product.getIsDrug());
-                } else {
-                    log.warn("药品 '{}' (ID: {}) 在产品表中未找到对应记录,将被过滤。", drug.getDrugName(), drug.getProductId());
-                }
-            } else {
-                shouldKeep = Integer.valueOf(1).equals(drug.getIsDrug());
-            }
-
-            if (shouldKeep) {
-                filteredDrugs.add(drug);
-            }
-        }
-        return filteredDrugs;
-    }
-
-    /**
-     * 转换处方单药品列表
+     * 获取处方单的最新制单状态,若销售已制单,所有的处方写操作都不可执行
+     * @return true:已制单,false:未制单
      * */
-    private List<FsPrescribeDrug> convertToPrescribeDrugList(List<FsPrescribeDataScrmDrug> sourceList) {
-        if (sourceList == null || sourceList.isEmpty()) {
-            return new ArrayList<>();
+    private Boolean getPrescribeIsDocument(Long prescribeId) {
+        FsPrescribeDataScrm fsPrescribeDataScrm = fsPrescribeDataScrmMapper.selectFsPrescribeDataScrmByPrescribeId(prescribeId);
+        if (fsPrescribeDataScrm == null){
+            throw new CustomException("未查询到有效处方信息");
+        }
+        if (fsPrescribeDataScrm.getIsDocument() == 1){
+            return true;
         }
-        return sourceList.stream()
-                .map(source -> {
-                    FsPrescribeDrug target = new FsPrescribeDrug();
-                    target.setDrugId(source.getDrugId());
-                    target.setPrescribeId(source.getPrescribeId());
-                    target.setDrugName(source.getDrugName());
-                    target.setDrugSpec(source.getDrugSpec());
-                    target.setUsageMethod(source.getUsageMethod());
-                    target.setUsageFrequencyUnit(source.getUsageFrequencyUnit());
-                    target.setUsagePerUseCount(source.getUsagePerUseCount());
-                    target.setUsagePerUseUnit(source.getUsagePerUseUnit());
-                    target.setUsageDays(source.getUsageDays());
-                    target.setDrugPrice(source.getDrugPrice());
-                    target.setDrugUnit(source.getDrugUnit());
-                    target.setInstructions(source.getInstructions());
-                    target.setProductId(source.getProductId());
-                    target.setDrugImgUrl(source.getDrugImgUrl());
-                    target.setProductAttrValueId(source.getProductAttrValueId());
-                    target.setRemark(source.getRemark());
-                    target.setDrugType(source.getDrugType());
-                    target.setIsDrug(source.getIsDrug());
-                    target.setDrugNum(source.getDrugNum());
-                    return target;
-                })
-                .collect(Collectors.toList());
+        return false;
     }
 }

+ 288 - 3
fs-service/src/main/java/com/fs/his/service/impl/PrescriptionTaskRecordServiceImpl.java

@@ -1,17 +1,31 @@
 package com.fs.his.service.impl;
 
-import com.fs.his.domain.FsPrescribe;
-import com.fs.his.domain.PrescriptionTaskRecord;
+import com.fs.common.exception.CustomException;
+import com.fs.common.utils.DateUtils;
+import com.fs.his.domain.*;
+import com.fs.his.mapper.FsPrescribeDataScrmMapper;
+import com.fs.his.mapper.FsPrescribeDrugDataScrmMapper;
+import com.fs.his.mapper.PrescribeScrmTaskRecordMapper;
 import com.fs.his.mapper.PrescriptionTaskRecordMapper;
+import com.fs.his.param.PrescribeXyImgParam;
 import com.fs.his.service.IFsPrescribeService;
+import com.fs.his.service.PrescriptionImageService;
 import com.fs.his.service.PrescriptionTaskRecordService;
+import com.fs.his.vo.FsPrescribeDataScrmImgVO;
+import com.fs.hisStore.domain.FsStoreProductScrm;
+import com.fs.hisStore.mapper.FsStoreProductScrmMapper;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang.exception.ExceptionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.util.Asserts;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
-import java.util.List;
+import java.util.*;
+import java.util.function.Function;
+import java.util.stream.Collectors;
 
 
 @Slf4j
@@ -24,6 +38,21 @@ public class PrescriptionTaskRecordServiceImpl implements PrescriptionTaskRecord
     @Autowired
     private IFsPrescribeService fsPrescribeService;
 
+    @Autowired
+    private PrescribeScrmTaskRecordMapper prescribeScrmTaskRecordMapper;
+
+    @Autowired
+    private FsPrescribeDataScrmMapper fsPrescribeDataScrmMapper;
+
+    @Autowired
+    private FsPrescribeDrugDataScrmMapper drugDataScrmMapper;
+
+    @Autowired
+    private PrescriptionImageService prescriptionImageService;
+
+    @Autowired
+    private FsStoreProductScrmMapper fsStoreProductScrmMapper;
+
     /**
      * 生成处方签名
      */
@@ -75,4 +104,260 @@ public class PrescriptionTaskRecordServiceImpl implements PrescriptionTaskRecord
         log.info("处方生成定时任务执行完成,总处理: {}条,成功: {}条,失败: {}条,耗时: {}毫秒",
                 prescriptionTaskRecords.size(), successCount, failCount, costTime);
     }
+
+    @Override
+    public void generateScrmPrescript() {
+        long startTime = System.currentTimeMillis();
+        log.info("商城处方图片生成定时任务开始执行");
+
+        // 1. 查询所有待处理的商城处方任务
+        List<PrescribeScrmTaskRecord> taskRecords = prescribeScrmTaskRecordMapper.selectPendingPrescribeScrmTaskRecord();
+        if (CollectionUtils.isEmpty(taskRecords)) {
+            log.info("没有待处理的商城处方任务");
+            return;
+        }
+        log.info("查询到待处理的商城处方任务记录数量: {}", taskRecords.size());
+
+        int successCount = 0;
+        int failCount = 0;
+
+        // 2. 逐条处理(确保单条失败不影响其他)
+        for (PrescribeScrmTaskRecord record : taskRecords) {
+            log.info("开始处理商城处方任务,处方ID: {}", record.getPrescribeId());
+            try {
+                // 调用图片生成方法(内部会更新处方表的图片URL,并返回最新URL)
+                Map<String, String> urlMap = prescribeScrmImgYsyTask(record.getPrescribeId(), record.getSignFlag());
+
+                // 任务执行成功,更新状态
+                record.setExecuteStatus(2);          // 2-成功
+                log.info("商城处方任务处理成功,处方ID: {}, 中药图片: {}, 西药图片: {}",
+                        record.getPrescribeId(), urlMap.get("prescribeImgUrl"), urlMap.get("prescribeImgStoreUrl"));
+                successCount++;
+            } catch (Exception e) {
+                log.error("生成商城处方图片失败,处方ID: {}", record.getPrescribeId(), e);
+                // 任务执行失败,更新状态和重试信息
+                record.setExecuteStatus(3);          // 3-失败
+                record.setRetryCount(record.getRetryCount() + 1);
+                record.setErrorMessage(ExceptionUtils.getFullStackTrace(e));
+                failCount++;
+            } finally {
+                // 无论成功还是失败,都更新任务记录(更新时间、执行状态等)
+                record.setUpdateTime(DateUtils.getNowDate());
+                prescribeScrmTaskRecordMapper.updatePrescribeScrmTaskRecord(record);
+                log.info("商城处方任务记录更新完成,处方ID: {}, 执行状态: {}",
+                        record.getPrescribeId(), record.getExecuteStatus());
+            }
+        }
+
+        long costTime = System.currentTimeMillis() - startTime;
+        log.info("商城处方图片生成定时任务执行完成,总处理: {}条,成功: {}条,失败: {}条,耗时: {}毫秒",
+                taskRecords.size(), successCount, failCount, costTime);
+    }
+    // ==================== 处方图片生成 ====================
+    /**
+     * 生成处方图片(异步任务调用)
+     * @param prescribeId 处方ID
+     * @param signFlag 签名标识:1-仅医生签名,2-医生+药师签名
+     * @return Map 包含两个 key:
+     *         "prescribeImgUrl"      - 中药处方图片地址
+     *         "prescribeImgStoreUrl" - 西药处方图片地址
+     *         未生成对应的图片时 value 为 null
+     */
+    @Override
+    public Map<String, String> prescribeScrmImgYsyTask(Long prescribeId, Integer signFlag) {
+        FsPrescribeDataScrmImgVO imgVO = fsPrescribeDataScrmMapper.selectFsPrescribeDataScrmImgVOByPrescribeId(prescribeId);
+        Asserts.notNull(imgVO, String.format("处方 %d 未找到!", prescribeId));
+        Asserts.notNull(imgVO.getDoctorId(), String.format("医生 %s 未找到!", imgVO.getDoctorId()));
+        Asserts.notNull(imgVO.getDrugDoctorId(), String.format("药师 %s 未找到!", imgVO.getDrugDoctorId()));
+
+        // 1. 获取并过滤药品
+        FsPrescribeDrugDataScrm query = new FsPrescribeDrugDataScrm();
+        query.setPrescribeId(prescribeId);
+        List<FsPrescribeDrugDataScrm> drugList = drugDataScrmMapper.selectFsPrescribeDrugDataScrmList(query);
+        if (CollectionUtils.isEmpty(drugList)) {
+            throw new CustomException(String.format("处方单 %d 对应药品为空!", prescribeId));
+        }
+
+        List<FsPrescribeDrugDataScrm> effectiveDrugs = filterNonDrugScrmPrescribe(drugList);
+
+        // 2. 按药品类型分组
+        Map<Integer, List<FsPrescribeDrugDataScrm>> drugTypeMap = effectiveDrugs.stream()
+                .collect(Collectors.groupingBy(FsPrescribeDrugDataScrm::getDrugType));
+        List<FsPrescribeDrugDataScrm> westernDrugs = drugTypeMap.getOrDefault(1, Collections.emptyList()); // 西药
+        List<FsPrescribeDrugDataScrm> chineseDrugs = drugTypeMap.getOrDefault(2, Collections.emptyList()); // 中药
+
+        // 3. 根据处方类型决定要生成的图片
+        Integer prescribeType = imgVO.getPrescribeType();
+        boolean needWestern = (prescribeType == 1 || prescribeType == 3) && !westernDrugs.isEmpty();
+        boolean needChinese = (prescribeType == 2 || prescribeType == 3) && !chineseDrugs.isEmpty();
+
+        // 4. 分别生成图片并更新数据库
+        FsPrescribeDataScrm updateData = new FsPrescribeDataScrm();
+        updateData.setPrescribeId(prescribeId);
+        boolean hasUpdate = false;
+
+        // 生成西药图片 → prescribeImgStoreUrl
+        if (needWestern) {
+            if (StringUtils.isBlank(imgVO.getPrescribeImgStoreUrl())) {
+                String url = generatePrescriptionImageForType(imgVO, signFlag, westernDrugs);
+                updateData.setPrescribeImgStoreUrl(url);
+                hasUpdate = true;
+            } else {
+                log.info("处方 {} 西药图片已存在,跳过生成", prescribeId);
+            }
+        }
+
+        // 生成中药图片 → prescribeImgUrl
+        if (needChinese) {
+            if (StringUtils.isBlank(imgVO.getPrescribeImgUrl())) {
+                String url = generatePrescriptionImageForType(imgVO, signFlag, chineseDrugs);
+                updateData.setPrescribeImgUrl(url);
+                hasUpdate = true;
+            } else {
+                log.info("处方 {} 中药图片已存在,跳过生成", prescribeId);
+            }
+        }
+
+        if (hasUpdate) {
+            fsPrescribeDataScrmMapper.updateFsPrescribeDataScrm(updateData);
+        }
+
+        // 5. 构建返回结果(重新查询一次确保拿到最新值)
+        FsPrescribeDataScrmImgVO latest = fsPrescribeDataScrmMapper.selectFsPrescribeDataScrmImgVOByPrescribeId(prescribeId);
+        Map<String, String> result = new HashMap<>();
+        result.put("prescribeImgUrl", latest != null ? latest.getPrescribeImgUrl() : null);
+        result.put("prescribeImgStoreUrl", latest != null ? latest.getPrescribeImgStoreUrl() : null);
+        return result;
+    }
+
+    /**
+     * 生成处方图片(按药品类型)
+     */
+    private String generatePrescriptionImageForType(FsPrescribeDataScrmImgVO imgVO,
+                                                    Integer signFlag,
+                                                    List<FsPrescribeDrugDataScrm> drugList) {
+        PrescribeXyImgParam imgParam = new PrescribeXyImgParam();
+        imgParam.setTime(imgVO.getCreateTime());
+        imgParam.setPrescribeId(imgVO.getPrescribeCode());
+        imgParam.setPatientName(imgVO.getPatientName());
+        imgParam.setPatientGender(String.valueOf(imgVO.getPatientGender()));
+        imgParam.setPatientAge(imgVO.getPatientAge());
+        imgParam.setOutpatientId(imgVO.getPrescribeCode());
+
+        if (com.fs.common.utils.StringUtils.isNotBlank(imgVO.getRemark())) {
+            imgParam.setRemark(imgVO.getRemark());
+        } else {
+            log.error("PrescribeImgYsyTask 处方id:{},缺失医嘱内容", imgVO.getPrescribeId());
+            imgParam.setRemark("请按照用药说明书服用药品,如有不适,请及时就医!");
+        }
+
+        imgParam.setHistoryAllergic(imgVO.getHistoryAllergic());
+        imgParam.setDiagnose(imgVO.getDiagnose());
+        imgParam.setPrescribeDrug(convertToPrescribeDrugList(drugList));
+
+        // 签名设置(保底默认全部签名)
+        imgParam.setUrl(imgVO.getDoctorSign());
+        if (signFlag == null || signFlag == 2) {
+            imgParam.setDrugDoctorUrl(imgVO.getDrugDoctorSignUrl());
+        }
+
+        imgParam.setDoctorName(imgVO.getDoctorName());
+        imgParam.setAuditDoctor(imgVO.getDrugDoctorName());
+        imgParam.setTelPhone(imgVO.getPatientTel());
+        imgParam.setJobLicenseNumber(imgVO.getPractiseCode());
+        imgParam.setDoctorNo(imgVO.getDoctorCertificate());
+        imgParam.setDoctorTitle(imgVO.getDoctorPosition());
+
+        return prescriptionImageService.generatePrescriptionImage(imgParam);
+    }
+
+    // ==================== 药品过滤与转换 ====================
+    /**
+     * 根据产品最新状态过滤处方单药品列表。
+     * <p>
+     * 该方法的过滤规则如下:
+     * - 对于 productId 非空的处方药,使用其对应产品表(FsStoreProduct)中的 isDrug 状态进行判断,只保留 isDrug=1 的项。
+     * - 对于 productId 为空的处方药,直接使用其自身的 isDrug 状态进行判断,只保留 isDrug=1 的项。
+     * </p>
+     *
+     * @param prescribeDrugs 待过滤的处方单药品列表。如果为 null 或空,则直接返回空列表。
+     * @return 一个符合上述规则的新列表。
+     */
+    public List<FsPrescribeDrugDataScrm> filterNonDrugScrmPrescribe(List<FsPrescribeDrugDataScrm> prescribeDrugs) {
+        if (CollectionUtils.isEmpty(prescribeDrugs)) {
+            return Collections.emptyList();
+        }
+
+        Set<Long> productIds = prescribeDrugs.stream()
+                .map(FsPrescribeDrugDataScrm::getProductId)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+
+        List<FsStoreProductScrm> storeProductIns = Collections.emptyList();
+        if (!productIds.isEmpty()) {
+            storeProductIns = fsStoreProductScrmMapper.getStoreProductInProductIds(new ArrayList<>(productIds));
+            if (storeProductIns.isEmpty()) {
+                log.error("查询产品id列表:{}查询产品信息为空!", productIds);
+            }
+        }
+
+        Map<Long, FsStoreProductScrm> storeProductMap = storeProductIns.stream()
+                .collect(Collectors.toMap(FsStoreProductScrm::getProductId, Function.identity()));
+
+        List<FsPrescribeDrugDataScrm> filteredDrugs = new ArrayList<>();
+        for (FsPrescribeDrugDataScrm drug : prescribeDrugs) {
+            boolean shouldKeep = false;
+            if (drug.getProductId() != null) {
+                FsStoreProductScrm product = storeProductMap.get(drug.getProductId());
+                if (product != null) {
+                    shouldKeep = Integer.valueOf(1).equals(product.getIsDrug());
+                } else {
+                    log.warn("药品 '{}' (ID: {}) 在产品表中未找到对应记录,将被过滤。", drug.getDrugName(), drug.getProductId());
+                }
+            } else {
+                shouldKeep = Integer.valueOf(1).equals(drug.getIsDrug());
+            }
+
+            if (shouldKeep) {
+                filteredDrugs.add(drug);
+            }
+        }
+        return filteredDrugs;
+    }
+
+    /**
+     * 转换处方单药品列表
+     * */
+    private List<FsPrescribeDrug> convertToPrescribeDrugList(List<FsPrescribeDrugDataScrm> sourceList) {
+        if (sourceList == null || sourceList.isEmpty()) {
+            return new ArrayList<>();
+        }
+        return sourceList.stream()
+                .map(source -> {
+                    FsPrescribeDrug target = new FsPrescribeDrug();
+                    target.setDrugId(source.getDrugId());
+                    target.setPrescribeId(source.getPrescribeId());
+                    target.setDrugName(source.getDrugName());
+                    target.setDrugSpec(source.getDrugSpec());
+                    target.setUsageMethod(source.getUsageMethod());
+                    target.setUsageFrequencyUnit(source.getUsageFrequencyUnit());
+                    target.setUsagePerUseCount(source.getUsagePerUseCount());
+                    target.setUsagePerUseUnit(source.getUsagePerUseUnit());
+                    target.setUsageDays(source.getUsageDays());
+                    target.setDrugPrice(source.getDrugPrice());
+                    target.setDrugUnit(source.getDrugUnit());
+                    target.setInstructions(source.getInstructions());
+                    target.setProductId(source.getProductId());
+                    target.setDrugImgUrl(source.getDrugImgUrl());
+                    target.setProductAttrValueId(source.getProductAttrValueId());
+                    target.setRemark(source.getRemark());
+                    target.setDrugType(source.getDrugType());
+                    target.setIsDrug(source.getIsDrug());
+                    if (source.getDrugNum() != null){
+                        target.setDrugNum(Long.valueOf(source.getDrugNum()));
+                    }
+                    return target;
+                })
+                .collect(Collectors.toList());
+    }
 }

+ 8 - 0
fs-service/src/main/java/com/fs/qw/vo/FsPrescribeDataScrmVO.java

@@ -1,10 +1,13 @@
 package com.fs.qw.vo;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fs.his.domain.FsPrescribeDrugDataScrm;
 import lombok.Data;
 
 import java.io.Serializable;
 import java.util.Date;
+import java.util.List;
+
 @Data
 public class FsPrescribeDataScrmVO implements Serializable {
     private static final long serialVersionUID = 1L;
@@ -180,4 +183,9 @@ public class FsPrescribeDataScrmVO implements Serializable {
 
     /** 舌诊、面诊、手诊 */
     private String facialDiagnosis;
+
+    /** 是否制单(0:否,1:是),只有值为0才能被医生修改 */
+    private Integer isDocument;
+
+    private List<FsPrescribeDrugDataScrm> drugsList;
 }

+ 0 - 179
fs-service/src/main/resources/mapper/his/FsPrescribeDataScrmDrugMapper.xml

@@ -1,179 +0,0 @@
-<?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.fs.his.mapper.FsPrescribeDataScrmDrugMapper">
-
-    <resultMap type="com.fs.his.domain.FsPrescribeDataScrmDrug" id="FsPrescribeDataScrmDrugResult">
-        <result property="drugId"               column="drug_id"                />
-        <result property="prescribeId"          column="prescribe_id"           />
-        <result property="drugName"             column="drug_name"              />
-        <result property="drugSpec"             column="drug_spec"              />
-        <result property="usageMethod"          column="usage_method"           />
-        <result property="usageFrequencyUnit"   column="usage_frequency_unit"   />
-        <result property="usagePerUseCount"     column="usage_per_use_count"    />
-        <result property="usagePerUseUnit"      column="usage_per_use_unit"     />
-        <result property="usageDays"            column="usage_days"             />
-        <result property="drugPrice"            column="drug_price"             />
-        <result property="drugNum"              column="drug_num"               />
-        <result property="drugUnit"             column="drug_unit"              />
-        <result property="instructions"         column="instructions"           />
-        <result property="productId"            column="product_id"             />
-        <result property="drugImgUrl"           column="drug_img_url"           />
-        <result property="productAttrValueId"   column="product_attr_value_id"  />
-        <result property="remark"               column="remark"                 />
-        <result property="drugType"             column="drug_type"              />
-        <result property="isDrug"               column="is_drug"                />
-    </resultMap>
-
-    <sql id="selectFsPrescribeDataScrmDrugVo">
-        select drug_id, prescribe_id, drug_name, drug_spec, usage_method, usage_frequency_unit,
-               usage_per_use_count, usage_per_use_unit, usage_days, drug_price, drug_num,
-               drug_unit, instructions, product_id, drug_img_url, product_attr_value_id,
-               remark, drug_type, is_drug
-        from fs_prescribe_data_scrm_drug
-    </sql>
-
-    <select id="selectFsPrescribeDataScrmDrugList" parameterType="FsPrescribeDataScrmDrug" resultMap="FsPrescribeDataScrmDrugResult">
-        <include refid="selectFsPrescribeDataScrmDrugVo"/>
-        <where>
-            <if test="prescribeId != null">
-                and prescribe_id = #{prescribeId}
-            </if>
-            <if test="drugName != null and drugName != ''">
-                and drug_name like concat('%', #{drugName}, '%')
-            </if>
-            <if test="drugSpec != null and drugSpec != ''">
-                and drug_spec like concat('%', #{drugSpec}, '%')
-            </if>
-            <if test="usageMethod != null and usageMethod != ''">
-                and usage_method like concat('%', #{usageMethod}, '%')
-            </if>
-            <if test="usageFrequencyUnit != null and usageFrequencyUnit != ''">
-                and usage_frequency_unit = #{usageFrequencyUnit}
-            </if>
-            <if test="usagePerUseCount != null and usagePerUseCount != ''">
-                and usage_per_use_count = #{usagePerUseCount}
-            </if>
-            <if test="usagePerUseUnit != null and usagePerUseUnit != ''">
-                and usage_per_use_unit = #{usagePerUseUnit}
-            </if>
-            <if test="usageDays != null and usageDays != ''">
-                and usage_days = #{usageDays}
-            </if>
-            <if test="drugPrice != null">
-                and drug_price = #{drugPrice}
-            </if>
-            <if test="drugNum != null">
-                and drug_num = #{drugNum}
-            </if>
-            <if test="drugUnit != null and drugUnit != ''">
-                and drug_unit = #{drugUnit}
-            </if>
-            <if test="instructions != null and instructions != ''">
-                and instructions like concat('%', #{instructions}, '%')
-            </if>
-            <if test="productId != null">
-                and product_id = #{productId}
-            </if>
-            <if test="productAttrValueId != null">
-                and product_attr_value_id = #{productAttrValueId}
-            </if>
-            <if test="remark != null and remark != ''">
-                and remark like concat('%', #{remark}, '%')
-            </if>
-            <if test="drugType != null">
-                and drug_type = #{drugType}
-            </if>
-            <if test="isDrug != null">
-                and is_drug = #{isDrug}
-            </if>
-        </where>
-        order by drug_id desc
-    </select>
-
-    <select id="selectFsPrescribeDataScrmDrugById" parameterType="Long" resultMap="FsPrescribeDataScrmDrugResult">
-        <include refid="selectFsPrescribeDataScrmDrugVo"/>
-        where drug_id = #{drugId}
-    </select>
-
-    <insert id="insertFsPrescribeDataScrmDrug" parameterType="FsPrescribeDataScrmDrug" useGeneratedKeys="true" keyProperty="drugId">
-        insert into fs_prescribe_data_scrm_drug
-        <trim prefix="(" suffix=")" suffixOverrides=",">
-            <if test="prescribeId != null">prescribe_id,</if>
-            <if test="drugName != null">drug_name,</if>
-            <if test="drugSpec != null">drug_spec,</if>
-            <if test="usageMethod != null">usage_method,</if>
-            <if test="usageFrequencyUnit != null">usage_frequency_unit,</if>
-            <if test="usagePerUseCount != null">usage_per_use_count,</if>
-            <if test="usagePerUseUnit != null">usage_per_use_unit,</if>
-            <if test="usageDays != null">usage_days,</if>
-            <if test="drugPrice != null">drug_price,</if>
-            <if test="drugNum != null">drug_num,</if>
-            <if test="drugUnit != null">drug_unit,</if>
-            <if test="instructions != null">instructions,</if>
-            <if test="productId != null">product_id,</if>
-            <if test="drugImgUrl != null">drug_img_url,</if>
-            <if test="productAttrValueId != null">product_attr_value_id,</if>
-            <if test="remark != null">remark,</if>
-            <if test="drugType != null">drug_type,</if>
-            <if test="isDrug != null">is_drug,</if>
-        </trim>
-        <trim prefix="values (" suffix=")" suffixOverrides=",">
-            <if test="prescribeId != null">#{prescribeId},</if>
-            <if test="drugName != null">#{drugName},</if>
-            <if test="drugSpec != null">#{drugSpec},</if>
-            <if test="usageMethod != null">#{usageMethod},</if>
-            <if test="usageFrequencyUnit != null">#{usageFrequencyUnit},</if>
-            <if test="usagePerUseCount != null">#{usagePerUseCount},</if>
-            <if test="usagePerUseUnit != null">#{usagePerUseUnit},</if>
-            <if test="usageDays != null">#{usageDays},</if>
-            <if test="drugPrice != null">#{drugPrice},</if>
-            <if test="drugNum != null">#{drugNum},</if>
-            <if test="drugUnit != null">#{drugUnit},</if>
-            <if test="instructions != null">#{instructions},</if>
-            <if test="productId != null">#{productId},</if>
-            <if test="drugImgUrl != null">#{drugImgUrl},</if>
-            <if test="productAttrValueId != null">#{productAttrValueId},</if>
-            <if test="remark != null">#{remark},</if>
-            <if test="drugType != null">#{drugType},</if>
-            <if test="isDrug != null">#{isDrug},</if>
-        </trim>
-    </insert>
-
-    <update id="updateFsPrescribeDataScrmDrug" parameterType="FsPrescribeDataScrmDrug">
-        update fs_prescribe_data_scrm_drug
-        <set>
-            <if test="prescribeId != null">prescribe_id = #{prescribeId},</if>
-            <if test="drugName != null">drug_name = #{drugName},</if>
-            <if test="drugSpec != null">drug_spec = #{drugSpec},</if>
-            <if test="usageMethod != null">usage_method = #{usageMethod},</if>
-            <if test="usageFrequencyUnit != null">usage_frequency_unit = #{usageFrequencyUnit},</if>
-            <if test="usagePerUseCount != null">usage_per_use_count = #{usagePerUseCount},</if>
-            <if test="usagePerUseUnit != null">usage_per_use_unit = #{usagePerUseUnit},</if>
-            <if test="usageDays != null">usage_days = #{usageDays},</if>
-            <if test="drugPrice != null">drug_price = #{drugPrice},</if>
-            <if test="drugNum != null">drug_num = #{drugNum},</if>
-            <if test="drugUnit != null">drug_unit = #{drugUnit},</if>
-            <if test="instructions != null">instructions = #{instructions},</if>
-            <if test="productId != null">product_id = #{productId},</if>
-            <if test="drugImgUrl != null">drug_img_url = #{drugImgUrl},</if>
-            <if test="productAttrValueId != null">product_attr_value_id = #{productAttrValueId},</if>
-            <if test="remark != null">remark = #{remark},</if>
-            <if test="drugType != null">drug_type = #{drugType},</if>
-            <if test="isDrug != null">is_drug = #{isDrug},</if>
-        </set>
-        where drug_id = #{drugId}
-    </update>
-
-    <delete id="deleteFsPrescribeDataScrmDrugById" parameterType="Long">
-        delete from fs_prescribe_data_scrm_drug where drug_id = #{drugId}
-    </delete>
-
-    <delete id="deleteFsPrescribeDataScrmDrugByIds" parameterType="Long">
-        delete from fs_prescribe_data_scrm_drug where drug_id in
-        <foreach collection="array" item="drugId" open="(" separator="," close=")">
-            #{drugId}
-        </foreach>
-    </delete>
-</mapper>

+ 30 - 5
fs-service/src/main/resources/mapper/his/FsPrescribeDataScrmMapper.xml

@@ -154,11 +154,13 @@
         select pds.* from fs_prescribe_data_scrm pds
         left join fs_company_customer fcc on pds.prescribe_id = fcc.prescribe_id
         <where>
-            pds.drug_doctor_id = #{drugDoctorId} and doctor_confirm = 1
-            <if test="orderCode != null"> and order_code = #{orderCode}</if>
-            <if test="prescribeCode != null and prescribeCode != ''"> and prescribe_code = #{prescribeCode}</if>
-            <if test="patientName != null and patientName != ''"> and patient_name like concat('%', #{patientName}, '%')</if>
-            <if test="status != null"> and status = #{status}</if>
+            <if test="status != 2">
+            pds.drug_doctor_id = #{drugDoctorId} and pds.doctor_confirm = 1
+            </if>
+            <if test="orderCode != null"> and pds.order_code = #{orderCode}</if>
+            <if test="prescribeCode != null and prescribeCode != ''"> and pds.prescribe_code = #{prescribeCode}</if>
+            <if test="patientName != null and patientName != ''"> and pds.patient_name like concat('%', #{patientName}, '%')</if>
+            <if test="status != null"> and pds.status = #{status}</if>
         </where>
         order by create_time desc
     </select>
@@ -180,6 +182,13 @@
         where fpds.prescribe_id = #{prescribeId}
     </select>
 
+    <select id="selectFsPrescribeDataScrmListByIds" resultType="com.fs.his.domain.FsPrescribeDataScrm">
+        select * from fs_prescribe_data_scrm where prescribe_id in
+        <foreach item="item" collection="prescribeIds" separator="," open="(" close=")">
+            #{item}
+        </foreach>
+    </select>
+
     <insert id="insertFsPrescribeDataScrm" parameterType="FsPrescribeDataScrm" useGeneratedKeys="true" keyProperty="prescribeId">
         insert into fs_prescribe_data_scrm
         <trim prefix="(" suffix=")" suffixOverrides=",">
@@ -379,4 +388,20 @@
         SET prescribe_img_url = NULL, prescribe_img_store_url = NULL
         WHERE prescribe_id = 1;
     </update>
+
+    <!-- 批量更新处方图片URL(仅更新非空字段) -->
+    <update id="updateBatchPrescribeDataScrmURL">
+        <foreach collection="fsPrescribeDataScrms" item="item" separator=";">
+            UPDATE fs_prescribe_data_scrm
+            <set>
+                <if test="item.prescribeImgUrl != null and item.prescribeImgUrl != ''">
+                    prescribe_img_url = #{item.prescribeImgUrl},
+                </if>
+                <if test="item.prescribeImgStoreUrl != null and item.prescribeImgStoreUrl != ''">
+                    prescribe_img_store_url = #{item.prescribeImgStoreUrl},
+                </if>
+            </set>
+            WHERE prescribe_id = #{item.prescribeId}
+        </foreach>
+    </update>
 </mapper>

+ 13 - 0
fs-service/src/main/resources/mapper/his/FsPrescribeDrugDataScrmMapper.xml

@@ -69,6 +69,19 @@
         where prescribe_id = #{prescribeId}
     </select>
 
+    <select id="selectFsPrescribeDataScrmDrugListByPrescribeIds" resultType="com.fs.his.domain.FsPrescribeDrugDataScrm">
+        SELECT drug_id, prescribe_id, drug_name, drug_spec, usage_method, usage_frequency_unit,
+        usage_per_use_count, usage_per_use_unit, usage_days, drug_price, drug_num,
+        drug_unit, instructions, product_id, drug_img_url, product_attr_value_id,
+        remark, drug_type, is_drug
+        FROM fs_prescribe_drug_data_scrm
+        WHERE prescribe_id IN
+        <foreach collection="prescribeIds" item="prescribeId" open="(" separator="," close=")">
+            #{prescribeId}
+        </foreach>
+        ORDER BY drug_id DESC
+    </select>
+
     <insert id="insertFsPrescribeDrugDataScrm" parameterType="FsPrescribeDrugDataScrm" useGeneratedKeys="true" keyProperty="drugId">
         insert into fs_prescribe_drug_data_scrm
         <trim prefix="(" suffix=")" suffixOverrides=",">

+ 4 - 0
fs-service/src/main/resources/mapper/his/PrescribeScrmTaskRecordMapper.xml

@@ -63,6 +63,10 @@
         where id = #{id}
     </select>
 
+    <select id="selectPendingPrescribeScrmTaskRecord" resultType="com.fs.his.domain.PrescribeScrmTaskRecord">
+        select * from prescrib_scrm_task_record where retry_count &lt; 3 and execute_status in (0,3) limit 10
+    </select>
+
     <insert id="insertPrescribeScrmTaskRecord" parameterType="PrescribeScrmTaskRecord" useGeneratedKeys="true" keyProperty="id">
         insert into prescrib_scrm_task_record
         <trim prefix="(" suffix=")" suffixOverrides=",">