Просмотр исходного кода

Merge remote-tracking branch 'origin/master'

wks 4 месяцев назад
Родитель
Сommit
405a881100
77 измененных файлов с 2064 добавлено и 230 удалено
  1. 5 0
      .gitignore
  2. 6 0
      commons/pom.xml
  3. 6 0
      commons/src/main/java/com/jzg/commons/config/MultiTenantHandler.java
  4. 1 1
      commons/src/main/java/com/jzg/commons/core/base/PartnerBaseModel.java
  5. 4 0
      commons/src/main/java/com/jzg/commons/entity/po/SysUploadFiles.java
  6. 44 0
      commons/src/main/java/com/jzg/commons/entity/po/SysUserSignIn.java
  7. 49 0
      commons/src/main/java/com/jzg/commons/entity/po/SysUserSignInRule.java
  8. 5 0
      commons/src/main/java/com/jzg/commons/entity/quote/vo/AccidentalDrivingVo.java
  9. 67 0
      commons/src/main/java/com/jzg/commons/entity/vo/LocalActivityTableVO.java
  10. 54 0
      commons/src/main/java/com/jzg/commons/entity/vo/LotteryActivityAwardVO.java
  11. 71 0
      commons/src/main/java/com/jzg/commons/entity/vo/LotteryActivityVO.java
  12. 20 0
      commons/src/main/java/com/jzg/commons/entity/vo/OrderRuleVO.java
  13. 20 0
      commons/src/main/java/com/jzg/commons/entity/vo/SignRuleVO.java
  14. 24 0
      commons/src/main/java/com/jzg/commons/entity/vo/UnderwritingRuleVO.java
  15. 50 0
      commons/src/main/java/com/jzg/commons/util/TenantContextUtils.java
  16. 1 1
      consoleStatistics/src/main/resources/application-dev.yml
  17. 7 9
      gateway/src/main/resources/application.yml
  18. 1 1
      partner/src/main/java/com/jzg/PartnerApplication.java
  19. 18 0
      partner/src/main/java/com/jzg/config/ScheduledThreadPoolConfig.java
  20. 1 1
      partner/src/main/java/com/jzg/controller/PartnerUserController.java
  21. 0 4
      partner/src/main/java/com/jzg/entity/PartnerUser.java
  22. 3 0
      partner/src/main/java/com/jzg/entity/param/PartnerKickbackChangeParam.java
  23. 2 1
      partner/src/main/java/com/jzg/entity/param/PartnerRuleEntity.java
  24. 5 0
      partner/src/main/java/com/jzg/mapper/PartnerUserMapper.java
  25. 2 2
      partner/src/main/java/com/jzg/service/Impl/PartnerKickbackChangeImpl.java
  26. 1 1
      partner/src/main/java/com/jzg/service/Impl/PartnerPremiumDetailsServiceImpl.java
  27. 5 0
      partner/src/main/java/com/jzg/service/Impl/PartnerRuleServiceImpl.java
  28. 2 0
      partner/src/main/java/com/jzg/service/PartnerRuleService.java
  29. 84 58
      partner/src/main/java/com/jzg/utils/TimedTaskUtils.java
  30. 4 3
      partner/src/main/resources/application-dev.yml
  31. 2 1
      partner/src/main/resources/mapper/PartnerAttributeMapper.xml
  32. 10 3
      partner/src/main/resources/mapper/PartnerUserMapper.xml
  33. 8 4
      platform/src/main/java/com/jzg/controller/EsmInsCompanyController.java
  34. 5 4
      platform/src/main/java/com/jzg/service/impl/SysSystemServiceImpl.java
  35. 2 0
      platform/src/main/resources/mapper/PtlAgreementAttributionMapper.xml
  36. 5 1
      tenant/costsorrule/src/main/java/com/jzg/costsorrule/service/impl/RuleServiceImpl.java
  37. 3 3
      tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/api/service/impl/BoHaiApiRequestImpl.java
  38. BIN
      tenant/insurance/quotation-bohai/中介车险业务接口文档-v1.1.2.doc
  39. 1 1
      tenant/insurance/quotation-commons/pom.xml
  40. 9 0
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/client/PlatformClient.java
  41. 15 2
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/component/RequestComponent.java
  42. 0 1
      tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/HttpUtil.java
  43. 4 7
      tenant/insurance/quotation-dajia/src/main/java/com/jzg/quotation/dajia/api/compoment/DaJiaApiRequestComponent.java
  44. 8 2
      tenant/insurance/quotation-dajia/src/main/java/com/jzg/quotation/dajia/api/entity/request/ODR1009Request.java
  45. 21 4
      tenant/insurance/quotation-dajia/src/main/java/com/jzg/quotation/dajia/api/service/impl/DaJiaApiRequestImpl.java
  46. 192 72
      tenant/insurance/quotation-guoren/src/main/java/com/jzg/quotation/guoren/api/service/Impl/GuoRenApiRequestImpl.java
  47. 3 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/InsOrdersController.java
  48. 2 4
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/UnifyOrderManager.java
  49. 1 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsOrdersService.java
  50. 9 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrdersServiceImpl.java
  51. 6 1
      tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/QuoteRuleMappingServiceImpl.java
  52. 2 7
      tenant/insurance/quotation-summary/src/main/resources/application-dev.yaml
  53. 11 11
      tenant/insurance/quotation-summary/src/main/resources/application-prod.yaml
  54. 17 0
      tenant/insurance/quotation-summary/src/test/resources/application-local.yaml
  55. 3 1
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/build/ZiJinAPIQuoteResultsVoBuild.java
  56. 32 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/constant/enums/AccidentHealthInsuranceProductsEnum.java
  57. 108 0
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/constant/enums/FileTypeEnum.java
  58. 2 2
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/entity/request/SubmitVerifyRequest.java
  59. 112 8
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/service/Impl/ZiJinApiRequestImpl.java
  60. 1 1
      tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/service/Impl/ZiJinOrderServiceImpl.java
  61. 25 0
      tenant/organization/src/main/java/com/jzg/organization/client/LotteryActivityClient.java
  62. 6 0
      tenant/organization/src/main/java/com/jzg/organization/controller/SchemeController.java
  63. 86 0
      tenant/organization/src/main/java/com/jzg/organization/controller/SignInController.java
  64. 20 0
      tenant/organization/src/main/java/com/jzg/organization/entity/dto/SignInDTO.java
  65. 28 0
      tenant/organization/src/main/java/com/jzg/organization/entity/vo/SignInRecordVO.java
  66. 34 0
      tenant/organization/src/main/java/com/jzg/organization/entity/vo/SignInStatisticsVO.java
  67. 39 0
      tenant/organization/src/main/java/com/jzg/organization/entity/vo/SignInVO.java
  68. 41 0
      tenant/organization/src/main/java/com/jzg/organization/mapper/SysUserSignInMapper.java
  69. 28 0
      tenant/organization/src/main/java/com/jzg/organization/mapper/SysUserSignInRuleMapper.java
  70. 86 0
      tenant/organization/src/main/java/com/jzg/organization/service/LotteryActivityService.java
  71. 42 0
      tenant/organization/src/main/java/com/jzg/organization/service/SignInService.java
  72. 4 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementCostServiceImpl.java
  73. 17 5
      tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlSchemeServiceImpl.java
  74. 365 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SignInServiceImpl.java
  75. 25 0
      tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserServiceImpl.java
  76. 38 0
      tenant/organization/src/main/resources/mapper/SysUserSignInMapper.xml
  77. 24 0
      tenant/organization/src/main/resources/mapper/SysUserSignInRuleMapper.xml

+ 5 - 0
.gitignore

@@ -34,6 +34,9 @@ build/
 ### VS Code ###
 .vscode/
 
+## person document
+pdoc/
+
 ### Mac OS ###
 .DS_Store
 /commons/dependency-reduced-pom.xml
@@ -52,3 +55,5 @@ build/
 /tenant/openfeign/dependency-reduced-pom.xml
 /tenant/organization/dependency-reduced-pom.xml
 /commons/src/main/java/com/jzg/commons/JwtAuthenticationTokenFilter.java
+
+pdoc/

+ 6 - 0
commons/pom.xml

@@ -146,6 +146,12 @@
                 <configuration>
                     <source>14</source>
                     <target>14</target>
+                    <annotationProcessorPaths>
+                        <path>
+                            <groupId>org.projectlombok</groupId>
+                            <artifactId>lombok</artifactId>
+                        </path>
+                    </annotationProcessorPaths>
                 </configuration>
             </plugin>
         </plugins>

+ 6 - 0
commons/src/main/java/com/jzg/commons/config/MultiTenantHandler.java

@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
 import com.jzg.commons.core.base.BaseController;
 import com.jzg.commons.core.base.TenantContext;
 import com.jzg.commons.entity.properties.TenantProperties;
+import com.jzg.commons.util.TenantContextUtils;
 import jakarta.servlet.http.HttpServletRequest;
 import jodd.util.StringUtil;
 import net.sf.jsqlparser.expression.Expression;
@@ -44,6 +45,11 @@ public class MultiTenantHandler implements TenantLineHandler {
      */
     @Override
     public Expression getTenantId() {
+        // 用于合伙人定时任务处理租户code
+        String customTenantId = TenantContextUtils.getCustomTenantId();
+        if (StringUtil.isNotEmpty(customTenantId)) {
+            return new StringValue(customTenantId);
+        }
         // 实际应该从用户信息中获取,框架一般都有获取用户信息的接口
         String tenant_id = controller.getUserLoginSystem();
         //如果使用的是APP 则从请求头中获取租户id

+ 1 - 1
commons/src/main/java/com/jzg/commons/core/base/PartnerBaseModel.java

@@ -35,7 +35,7 @@ public class PartnerBaseModel implements Serializable {
     @TableField(fill = FieldFill.INSERT_UPDATE)
     private LocalDateTime updateTime;
 
-
+    @TableField(value = "system_code")
     private String systemCode;
 
 }

+ 4 - 0
commons/src/main/java/com/jzg/commons/entity/po/SysUploadFiles.java

@@ -1,8 +1,10 @@
 package com.jzg.commons.entity.po;
 
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
 
 import java.time.LocalDateTime;
 
@@ -22,6 +24,8 @@ public class SysUploadFiles {
 
     private String etag;
 
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private LocalDateTime createTime;
 
     private String createBy;

+ 44 - 0
commons/src/main/java/com/jzg/commons/entity/po/SysUserSignIn.java

@@ -0,0 +1,44 @@
+package com.jzg.commons.entity.po;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.jzg.commons.core.base.BaseModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 用户签到记录表
+ * 支持多租户
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_user_sign_in")
+public class SysUserSignIn extends BaseModel {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(type = IdType.ASSIGN_ID)
+    private String id;
+
+    @Schema(description = "租户ID")
+    private String tenantId;
+
+    @Schema(description = "用户ID")
+    private String userId;
+
+    @Schema(description = "签到日期")
+    private LocalDate signInDate;
+
+    @Schema(description = "连续签到天数(截至当天)")
+    private Integer continuousDays;
+
+    @Schema(description = "签到时间")
+    private LocalDateTime signInTime;
+
+    @Schema(description = "备注")
+    private String remark;
+}

+ 49 - 0
commons/src/main/java/com/jzg/commons/entity/po/SysUserSignInRule.java

@@ -0,0 +1,49 @@
+package com.jzg.commons.entity.po;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.jzg.commons.core.base.BaseModel;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.time.LocalDateTime;
+
+/**
+ * 用户签到规则完成记录表
+ * 记录用户在某个活动期间完成了哪些签到规则,每个规则活动期间只能完成一次
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@TableName("sys_user_sign_in_rule")
+public class SysUserSignInRule extends BaseModel {
+    private static final long serialVersionUID = 1L;
+
+    @TableId(type = IdType.ASSIGN_ID)
+    private String id;
+
+    @Schema(description = "租户ID")
+    private String tenantId;
+
+    @Schema(description = "用户ID")
+    private String userId;
+
+    @Schema(description = "活动ID(lottery_activity_id)")
+    private String activityId;
+
+    @Schema(description = "本地活动表ID(local_activity_table_id)")
+    private String localActivityTableId;
+
+    @Schema(description = "规则标识(signNum,如:2、4)")
+    private String ruleSignNum;
+
+    @Schema(description = "获得抽奖次数")
+    private Integer lotteryNum;
+
+    @Schema(description = "领取状态 0-未领取 1-已领取")
+    private Integer status;
+
+    @Schema(description = "领取时间")
+    private LocalDateTime receiveTime;
+}

+ 5 - 0
commons/src/main/java/com/jzg/commons/entity/quote/vo/AccidentalDrivingVo.java

@@ -21,6 +21,11 @@ public class AccidentalDrivingVo implements Serializable {
     @Serial
     private static final long serialVersionUID = -4823674553515932817L;
 
+    /**
+     * 险种编码
+     */
+    @Schema(description = "驾意险id")
+    private String id;
     /**
      * 险种编码
      */

+ 67 - 0
commons/src/main/java/com/jzg/commons/entity/vo/LocalActivityTableVO.java

@@ -0,0 +1,67 @@
+package com.jzg.commons.entity.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 本地活动表
+ */
+@Data
+public class LocalActivityTableVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "ID")
+    private String id;
+
+    @Schema(description = "标题")
+    private String title;
+
+    @Schema(description = "说明")
+    private String instructions;
+
+    @Schema(description = "开始时间")
+    private LocalDateTime startTime;
+
+    @Schema(description = "结束时间")
+    private LocalDateTime endTime;
+
+    @Schema(description = "用户类型")
+    private String userType;
+
+    @Schema(description = "用户等级ID")
+    private String userLevelId;
+
+    @Schema(description = "奖品类型")
+    private String awardType;
+
+    @Schema(description = "转盘ID")
+    private String turntableId;
+
+    @Schema(description = "类型 6-报价 7-签到 8-出单")
+    private String type;
+
+    @Schema(description = "背景图")
+    private String backImage;
+
+    @Schema(description = "报价次数")
+    private String qutNum;
+
+    @Schema(description = "报价获得抽奖次数")
+    private String qutLotteryNum;
+
+    @Schema(description = "报价最大抽奖次数")
+    private String qutLotteryMax;
+
+    @Schema(description = "签到规则列表")
+    private List<SignRuleVO> signRules;
+
+    @Schema(description = "出单规则列表")
+    private List<OrderRuleVO> orderRules;
+
+    @Schema(description = "核保规则列表")
+    private List<UnderwritingRuleVO> underwritingRules;
+}

+ 54 - 0
commons/src/main/java/com/jzg/commons/entity/vo/LotteryActivityAwardVO.java

@@ -0,0 +1,54 @@
+package com.jzg.commons.entity.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 抽奖活动奖品
+ */
+@Data
+public class LotteryActivityAwardVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "奖品ID")
+    private String id;
+
+    @Schema(description = "活动ID")
+    private String activityId;
+
+    @Schema(description = "奖品类型 1-现金 2-积分 5-感谢参与 6-会员")
+    private Integer awardType;
+
+    @Schema(description = "优惠券ID")
+    private String couponId;
+
+    @Schema(description = "优惠券名称")
+    private String couponName;
+
+    @Schema(description = "奖品图标")
+    private String icon;
+
+    @Schema(description = "中奖概率")
+    private Integer winningProbability;
+
+    @Schema(description = "兑换类型")
+    private Integer redemptionType;
+
+    @Schema(description = "奖品名称")
+    private String awardName;
+
+    @Schema(description = "积分数量")
+    private Integer pointNum;
+
+    @Schema(description = "红包金额")
+    private BigDecimal redAmount;
+
+    @Schema(description = "付费会员ID")
+    private Long paidMemberId;
+
+    @Schema(description = "付费会员规则ID")
+    private Long paidMemberRulesId;
+}

+ 71 - 0
commons/src/main/java/com/jzg/commons/entity/vo/LotteryActivityVO.java

@@ -0,0 +1,71 @@
+package com.jzg.commons.entity.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 抽奖活动信息
+ */
+@Data
+public class LotteryActivityVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "活动ID")
+    private String id;
+
+    @Schema(description = "活动名称")
+    private String activityName;
+
+    @Schema(description = "场景编码")
+    private Integer scene;
+
+    @Schema(description = "场景名称")
+    private String sceneName;
+
+    @Schema(description = "类型")
+    private Integer type;
+
+    @Schema(description = "活动开始时间")
+    private LocalDate activityStartTime;
+
+    @Schema(description = "活动结束时间")
+    private LocalDate activityEndTime;
+
+    @Schema(description = "参与规则")
+    private Integer participationRules;
+
+    @Schema(description = "活动背景图")
+    private String activityBackgroundImage;
+
+    @Schema(description = "海报背景图")
+    private String posterBackgroundImage;
+
+    @Schema(description = "活动链接")
+    private String activityUrl;
+
+    @Schema(description = "活动描述")
+    private String activityDescribe;
+
+    @Schema(description = "创建人")
+    private String createBy;
+
+    @Schema(description = "更新人")
+    private String updateBy;
+
+    @Schema(description = "创建时间")
+    private LocalDateTime createTime;
+
+    @Schema(description = "更新时间")
+    private LocalDateTime updateTime;
+
+    @Schema(description = "奖品列表")
+    private List<LotteryActivityAwardVO> lotteryActivityAwards;
+
+    @Schema(description = "本地活动表")
+    private List<LocalActivityTableVO> localActivityTables;
+}

+ 20 - 0
commons/src/main/java/com/jzg/commons/entity/vo/OrderRuleVO.java

@@ -0,0 +1,20 @@
+package com.jzg.commons.entity.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 出单规则
+ */
+@Data
+public class OrderRuleVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "出单数量")
+    private String ordNum;
+
+    @Schema(description = "获得抽奖次数")
+    private Integer ordLotteryNum;
+}

+ 20 - 0
commons/src/main/java/com/jzg/commons/entity/vo/SignRuleVO.java

@@ -0,0 +1,20 @@
+package com.jzg.commons.entity.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 签到规则
+ */
+@Data
+public class SignRuleVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "签到天数")
+    private String signNum;
+
+    @Schema(description = "获得抽奖次数")
+    private String signLotteryNum;
+}

+ 24 - 0
commons/src/main/java/com/jzg/commons/entity/vo/UnderwritingRuleVO.java

@@ -0,0 +1,24 @@
+package com.jzg.commons.entity.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * 核保规则
+ */
+@Data
+public class UnderwritingRuleVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "最小保费")
+    private BigDecimal uwMinPremium;
+
+    @Schema(description = "最大保费")
+    private BigDecimal uwMaxPremium;
+
+    @Schema(description = "获得抽奖次数")
+    private String uwLotteryNum;
+}

+ 50 - 0
commons/src/main/java/com/jzg/commons/util/TenantContextUtils.java

@@ -0,0 +1,50 @@
+package com.jzg.commons.util;
+
+public class TenantContextUtils {
+
+    private static final ThreadLocal<Boolean> INTERNAL_INVOCATION = ThreadLocal.withInitial(() -> false);
+
+    public static boolean isInternalInvocation() {
+        return INTERNAL_INVOCATION.get();
+    }
+    public static void setInternalInvocation(boolean internalInvocation) {
+        INTERNAL_INVOCATION.set(internalInvocation);
+    }
+    public static void clearInternalInvocation() {
+        INTERNAL_INVOCATION.remove();
+    }
+
+    // ===================== 新增:自定义租户ID 核心代码 =====================
+    // 线程隔离存储自定义租户ID
+    private static final ThreadLocal<String> CUSTOM_TENANT_ID = new ThreadLocal<>();
+
+    /**
+     * 手动设置自定义租户ID
+     */
+    public static void setCustomTenantId(String tenantId) {
+        CUSTOM_TENANT_ID.set(tenantId);
+    }
+
+    /**
+     * 获取自定义租户ID
+     */
+    public static String getCustomTenantId() {
+        return CUSTOM_TENANT_ID.get();
+    }
+
+    /**
+     * 清空自定义租户ID(必须调用,防止内存泄漏)
+     */
+    public static void clearCustomTenantId() {
+        CUSTOM_TENANT_ID.remove();
+    }
+
+    /**
+     * 一键清空所有租户上下文(推荐使用)
+     */
+    public static void clear() {
+        clearInternalInvocation();
+        clearCustomTenantId();
+    }
+
+}

+ 1 - 1
consoleStatistics/src/main/resources/application-dev.yml

@@ -1,7 +1,7 @@
 spring:
   cloud:
     nacos:
-      server-addr: localhost:8848
+      server-addr: 192.168.5.250:8848
       username: nacos
       password: nacos
       config:

+ 7 - 9
gateway/src/main/resources/application.yml

@@ -8,14 +8,12 @@ spring:
     allow-bean-definition-overriding: true
   application:
     name: jzg-gateway
-#  redis:
-#    redisson:
-##      address: redis://172.24.144.227:6379
-##      password: 123456
-##      database: 0
-#
-#      address: redis://192.168.5.250:6379
-#      password: 123456
-#      database: 0
+  redis:
+    redisson:
+      address: redis://192.168.5.250:6379
+      password: 123456
+      database: 0
+ssl:
+  trust-all: true
 
 isEncrypted: false

+ 1 - 1
partner/src/main/java/com/jzg/PartnerApplication.java

@@ -12,6 +12,6 @@ import org.springframework.scheduling.annotation.EnableScheduling;
 @EnableScheduling
 public class PartnerApplication {
     public static void main(String[] args) {
-        SpringApplication.run(PartnerApplication.class);
+        SpringApplication.run(PartnerApplication.class,args);
     }
 }

+ 18 - 0
partner/src/main/java/com/jzg/config/ScheduledThreadPoolConfig.java

@@ -0,0 +1,18 @@
+package com.jzg.config;
+
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
+
+@Configuration
+public class ScheduledThreadPoolConfig implements SchedulingConfigurer {
+    @Override
+    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
+        ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
+        scheduler.setPoolSize(10);
+        scheduler.setThreadNamePrefix("partner-task-");
+        scheduler.initialize();
+        taskRegistrar.setTaskScheduler(scheduler);
+    }
+}

+ 1 - 1
partner/src/main/java/com/jzg/controller/PartnerUserController.java

@@ -241,7 +241,7 @@ public class PartnerUserController extends BaseController {
      */
     @GetMapping("checkCommissionExpireTime")
     public void checkCommissionExpireTime() {
-        SpringUtil.getBean(TimedTaskUtils.class).checkCommissionExpireTime();
+        SpringUtil.getBean(TimedTaskUtils.class).updateOrderDateNoon();
     }
 
 

+ 0 - 4
partner/src/main/java/com/jzg/entity/PartnerUser.java

@@ -90,10 +90,6 @@ public class PartnerUser extends PartnerBaseModel {
      */
     private Date upgradeTime;
 
-
-    @TableField(value = "system_code")
-    private String systemCode;
-
     @TableField(value = "status")
     private boolean status;
 

+ 3 - 0
partner/src/main/java/com/jzg/entity/param/PartnerKickbackChangeParam.java

@@ -19,6 +19,9 @@ public class PartnerKickbackChangeParam extends PageRequest {
     @Schema(description = "工号")
     private String userId;
 
+    @Schema(description = "用户等级")
+    private String grade;
+
     @Schema(description = "用户等级")
     private String userGrade;
 

+ 2 - 1
partner/src/main/java/com/jzg/entity/param/PartnerRuleEntity.java

@@ -59,6 +59,7 @@ public class PartnerRuleEntity implements Serializable {
     @TableField(exist = false)
     private String assessmentEndDate;
 
-
+    @Schema(description = "租户code")
+    private String  systemCode;
 
 }

+ 5 - 0
partner/src/main/java/com/jzg/mapper/PartnerUserMapper.java

@@ -1,6 +1,7 @@
 package com.jzg.mapper;
 
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
@@ -216,4 +217,8 @@ public interface PartnerUserMapper extends BaseMapper<PartnerUser> {
     List<PartnerUser> selectListByUserId(@Param("userId") String userId);
 
     SysPartnerAccount selectFee(@Param("userId") String userId);
+
+    @InterceptorIgnore(tenantLine = "true")
+    List<String> distinctSystemCode();
+
 }

+ 2 - 2
partner/src/main/java/com/jzg/service/Impl/PartnerKickbackChangeImpl.java

@@ -42,8 +42,8 @@ public class PartnerKickbackChangeImpl extends ServiceImpl<PartnerKickbackChange
         if (StringUtils.isNotBlank(changeParam.getUserId())){
             wrapper.like("c.user_id",changeParam.getUserId());
         }
-        if (StringUtils.isNotBlank(changeParam.getUserGrade())){
-            wrapper.eq("c.user_grade",changeParam.getUserGrade());
+        if (StringUtils.isNotBlank(changeParam.getGrade())){
+            wrapper.eq("c.user_grade",changeParam.getGrade());
         }
         List<String> changeTimes = changeParam.getChangeTimes();
         if (CollectionUtil.isNotEmpty(changeTimes)){

+ 1 - 1
partner/src/main/java/com/jzg/service/Impl/PartnerPremiumDetailsServiceImpl.java

@@ -62,7 +62,7 @@ public class PartnerPremiumDetailsServiceImpl extends ServiceImpl<PartnerPremium
         log.info("查询佣金明细:detailsParam=[{}]", JSONUtil.toJsonStr(detailsParam));
         QueryWrapper<PartnerPremiumDetails> queryWrapper = new QueryWrapper<>();
 
-        queryWrapper.like(StringUtils.isNotBlank(detailsParam.getUserName()), "u.`name`",detailsParam.getUserName());
+        queryWrapper.like(StringUtils.isNotBlank(detailsParam.getUserName()), "info.`name`",detailsParam.getUserName());
         queryWrapper.like(StringUtils.isNotBlank(detailsParam.getMobile()), "u.mobile",detailsParam.getMobile());
         queryWrapper.like(StringUtils.isNotBlank(detailsParam.getUserId()), "d.user_id",detailsParam.getUserId());
         queryWrapper.like(StringUtils.isNotBlank(detailsParam.getOrderno()), "d.orderno",detailsParam.getOrderno());

+ 5 - 0
partner/src/main/java/com/jzg/service/Impl/PartnerRuleServiceImpl.java

@@ -328,6 +328,11 @@ public class PartnerRuleServiceImpl extends ServiceImpl<PartnerRuleMapper, Partn
         return new BigDecimal(number);
     }
 
+    @Override
+    public List<PartnerRuleEntity> querySystemCodeAll() {
+        return attributeMapper.queryAll();
+    }
+
     @Override
     public  CommissionValidityPeriod getCommissionValidityPeriod(PartnerAttribute cycle1, String userId, String grade) {
         CommissionValidityPeriod period = new CommissionValidityPeriod();

+ 2 - 0
partner/src/main/java/com/jzg/service/PartnerRuleService.java

@@ -54,4 +54,6 @@ public interface PartnerRuleService {
 
     BigDecimal getInviteData(String userId, String grade, CommissionValidityPeriod period);
 
+    List<PartnerRuleEntity> querySystemCodeAll();
+
 }

+ 84 - 58
partner/src/main/java/com/jzg/utils/TimedTaskUtils.java

@@ -6,6 +6,7 @@ import cn.hutool.extra.spring.SpringUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.jzg.commons.util.StringUtils;
+import com.jzg.commons.util.TenantContextUtils;
 import com.jzg.entity.*;
 import com.jzg.entity.param.PartnerRuleEntity;
 import com.jzg.mapper.PartnerExpiredCommissionMapper;
@@ -61,35 +62,46 @@ public class TimedTaskUtils {
     @Scheduled(cron = "0 0 0 * * *")
     public void updateOrderDateNoon() {
         log.info("记录佣金过期定时任务开始执行:{}", expireDays);
-        List<PartnerUser> partnerUserList = partnerUserMapper.queryExpiredRecords(expireDays);
-        for (PartnerUser partnerUser : partnerUserList) {
-            String date = PartnerDateUtils.timeExample(expireDays + 1);
-            LambdaQueryWrapper<PartnerPremiumDetails> lambdaQueryWrapper = new LambdaQueryWrapper<>();
-            lambdaQueryWrapper.eq(PartnerPremiumDetails::getUserId, partnerUser.getUserId())
-                    .eq(PartnerPremiumDetails::getSource, partnerUser.getGrade())
-                    .eq(PartnerPremiumDetails::getAppStatus, 1)
-                    .between(PartnerPremiumDetails::getCreateTime,date+" 00:00:00",date+" 23:59:59");
-            List<PartnerPremiumDetails> partnerPremiumDetails = premiumDetailsMapper.selectList(lambdaQueryWrapper);
-            if (CollectionUtil.isNotEmpty(partnerPremiumDetails)){
-                BigDecimal lockCommission = partnerPremiumDetails.stream().map(PartnerPremiumDetails::getExtractFee).reduce(BigDecimal.ZERO, BigDecimal::add);
-                PartnerExpiredCommission commission = getExpiredUserCommission(partnerUser,lockCommission,date);
-                expiredCommissionMapper.insert(commission);
-                if (null != lockCommission){
-                    PartnerPartnerAccount account = accountMapper.selectOne(new LambdaQueryWrapper<>(PartnerPartnerAccount.class)
-                            .eq(PartnerPartnerAccount::getUserId, partnerUser.getUserId()).eq(PartnerPartnerAccount::getGrade, partnerUser.getGrade()));
-                    if (null == account) {
-                        continue;
-                    }
-                    if (null != lockCommission){
-                        account.setExpiredAmount(account.getExpiredAmount().add(lockCommission));
-                        accountMapper.updateById(account);
-                    }
-                    //更新单据状态
-                    for (PartnerPremiumDetails detail : partnerPremiumDetails) {
-                        detail.setAppStatus(2);
-                        premiumDetailsMapper.updateById(detail);
+        // 查询所有用户的租户code
+        List<String> systemCodeList = partnerUserMapper.distinctSystemCode();
+        for (String systemCode : systemCodeList) {
+            TenantContextUtils.setCustomTenantId(systemCode);
+            try {
+                List<PartnerUser> partnerUserList = partnerUserMapper.queryExpiredRecords(expireDays);
+                for (PartnerUser partnerUser : partnerUserList) {
+                    String date = PartnerDateUtils.timeExample(expireDays + 1);
+                    LambdaQueryWrapper<PartnerPremiumDetails> lambdaQueryWrapper = new LambdaQueryWrapper<>();
+                    lambdaQueryWrapper.eq(PartnerPremiumDetails::getUserId, partnerUser.getUserId())
+                            .eq(PartnerPremiumDetails::getSource, partnerUser.getGrade())
+                            .eq(PartnerPremiumDetails::getAppStatus, 1)
+                            .between(PartnerPremiumDetails::getCreateTime,date+" 00:00:00",date+" 23:59:59");
+                    List<PartnerPremiumDetails> partnerPremiumDetails = premiumDetailsMapper.selectList(lambdaQueryWrapper);
+                    if (CollectionUtil.isNotEmpty(partnerPremiumDetails)){
+                        BigDecimal lockCommission = partnerPremiumDetails.stream().map(PartnerPremiumDetails::getExtractFee).reduce(BigDecimal.ZERO, BigDecimal::add);
+                        PartnerExpiredCommission commission = getExpiredUserCommission(partnerUser,lockCommission,date);
+                        expiredCommissionMapper.insert(commission);
+                        if (null != lockCommission){
+                            PartnerPartnerAccount account = accountMapper.selectOne(new LambdaQueryWrapper<>(PartnerPartnerAccount.class)
+                                    .eq(PartnerPartnerAccount::getUserId, partnerUser.getUserId()).eq(PartnerPartnerAccount::getGrade, partnerUser.getGrade()));
+                            if (null == account) {
+                                continue;
+                            }
+                            if (null != lockCommission){
+                                account.setExpiredAmount(account.getExpiredAmount().add(lockCommission));
+                                accountMapper.updateById(account);
+                            }
+                            //更新单据状态
+                            for (PartnerPremiumDetails detail : partnerPremiumDetails) {
+                                detail.setAppStatus(2);
+                                premiumDetailsMapper.updateById(detail);
+                            }
+                        }
                     }
                 }
+            }catch (Exception e){
+                log.error("updateOrderDateNoon定时任务执行失败:{}",e.getMessage());
+            }finally {
+                TenantContextUtils.clear();
             }
         }
     }
@@ -135,40 +147,54 @@ public class TimedTaskUtils {
     //@XxlJob("checkCommissionExpireTime")
     @Scheduled(cron = "0 0 0 * * *")
     public void checkCommissionExpireTime() {
-        // TODO等级规则
-        List<PartnerRuleEntity> partnerRuleEntities = partnerRuleService.queryAll();
-        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-        List<PartnerUser> partnerUsers = partnerUserMapper.queryDowngradedData();
-        Date date = new Date();
-        for (PartnerUser partnerUser : partnerUsers) {
-            PartnerRuleEntity rule = getRule(String.valueOf(partnerUser.getGrade()), partnerRuleEntities);
-            Integer khDays = rule.getKhDays();
-            Date upgradeStartTime = getUpgradeStartTime(partnerUser);
-            if (null == upgradeStartTime){
-                continue;
-            }
-            log.info("开始时间:{}", formatter.format(upgradeStartTime));
-            //  生成结束时间
-            Date upgradeEndTime = PartnerDateUtils.generateEndTime(upgradeStartTime, khDays);
-            log.info("结束时间:{}", formatter.format(upgradeEndTime));
-            if (date.compareTo(upgradeEndTime) >= 0){
-                // TODO考核条件  不满足时需锁定
-                ExpiredCommissionUtils commissionUtils = SpringUtil.getBean(ExpiredCommissionUtils.class);
-                boolean checked = commissionUtils.checkUpgradeConditions(partnerUser);
-                if (!checked){
-                    //TODO  不满足
-                    commissionUtils.generateLockRecords(partnerUser);
+
+        // 查询所有用户的租户code
+        List<String> systemCodeList = partnerUserMapper.distinctSystemCode();
+        for (String systemCode : systemCodeList) {
+            try {
+                TenantContextUtils.setCustomTenantId(systemCode);
+                // TODO等级规则
+                List<PartnerRuleEntity> partnerRuleEntities = partnerRuleService.querySystemCodeAll();
+                SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                List<PartnerUser> partnerUsers = partnerUserMapper.queryDowngradedData();
+                Date date = new Date();
+                for (PartnerUser partnerUser : partnerUsers) {
+                    PartnerRuleEntity rule = getRule(String.valueOf(partnerUser.getGrade()), partnerRuleEntities);
+                    Integer khDays = rule.getKhDays();
+                    Date upgradeStartTime = getUpgradeStartTime(partnerUser);
+                    if (null == upgradeStartTime){
+                        continue;
+                    }
+                    log.info("开始时间:{}", formatter.format(upgradeStartTime));
+                    //  生成结束时间
+                    Date upgradeEndTime = PartnerDateUtils.generateEndTime(upgradeStartTime, khDays);
+                    log.info("结束时间:{}", formatter.format(upgradeEndTime));
+                    if (date.compareTo(upgradeEndTime) >= 0){
+                        // TODO考核条件  不满足时需锁定
+                        ExpiredCommissionUtils commissionUtils = SpringUtil.getBean(ExpiredCommissionUtils.class);
+                        boolean checked = commissionUtils.checkUpgradeConditions(partnerUser);
+                        if (!checked){
+                            //TODO  不满足
+                            commissionUtils.generateLockRecords(partnerUser);
+                        }
+                        //TODO    更新考核周期
+                        partnerUserMapper.updateUpgradeCycleStartTime(partnerUser.getUserId(), PartnerDateUtils.addDaysToday(upgradeEndTime,1),partnerUser.getGrade());
+                        partnerUserMapper.updateNextLevelAssessmentTime(partnerUser.getUserId(), (partnerUser.getGrade() + 1),PartnerDateUtils.addDaysToday(upgradeEndTime,1));
+                    }
+
                 }
-                //TODO    更新考核周期
-                partnerUserMapper.updateUpgradeCycleStartTime(partnerUser.getUserId(), PartnerDateUtils.addDaysToday(upgradeEndTime,1),partnerUser.getGrade());
-                partnerUserMapper.updateNextLevelAssessmentTime(partnerUser.getUserId(), (partnerUser.getGrade() + 1),PartnerDateUtils.addDaysToday(upgradeEndTime,1));
+                List<String> idList = partnerUsers.stream()
+                        .map(PartnerUser::getId)
+                        .collect(Collectors.toList());
+                update(partnerRuleEntities,idList);
+            }catch (Exception e){
+                e.printStackTrace();
+                log.error("checkCommissionExpireTime定时任务执行失败:{}",e.getMessage());
+            }finally {
+                TenantContextUtils.clear();
             }
-
         }
-        List<String> idList = partnerUsers.stream()
-                .map(PartnerUser::getId)
-                .collect(Collectors.toList());
-        update(partnerRuleEntities,idList);
+
     }
 
 

+ 4 - 3
partner/src/main/resources/application-dev.yml

@@ -1,21 +1,22 @@
 spring:
   cloud:
     nacos:
-      server-addr: 192.168.0.250:8848
+      server-addr: 192.168.5.250:8848
       username: nacos
       password: nacos
       config:
         file-extension: yaml
-        namespace: bf63c033-4d4b-4aef-85be-1d0499c261d4
+        namespace: 353f8f05-4d2c-4a17-b64d-b678408f5759
         group: DEFAULT_GROUP
       discovery:
-        namespace: bf63c033-4d4b-4aef-85be-1d0499c261d4
+        namespace: 353f8f05-4d2c-4a17-b64d-b678408f5759
   config:
     import:
       - nacos:mysql
       - nacos:redisson
 
 
+
 feign:
   client:
     jzg-org:

+ 2 - 1
partner/src/main/resources/mapper/PartnerAttributeMapper.xml

@@ -14,6 +14,7 @@
         <result property="khDays" column="kh_days"/>
         <result property="fallTick" column="fall_tick"/>
         <result property="fallAmount" column="fall_amount"/>
+        <result property="systemCode" column="system_code"/>
         <association property="cycle"  column="id=id" select="selectCycle" />
         <collection property="strategyArray" column="id=id" select="selectStrategy" />
         <collection property="requirement" column="id=id" select="selectRequirement" />
@@ -36,7 +37,7 @@
     </resultMap>
 
     <select id="queryAll" resultMap="BaseMapper">
-        select id, upgrade, relegation, grade_name, grade, appraise, rel_satisfy,strategy,kh_days,fall_tick,fall_amount from partner_rule
+        select id, upgrade, relegation, grade_name, grade, appraise, rel_satisfy,strategy,kh_days,fall_tick,fall_amount,system_code from partner_rule
     </select>
 
 

+ 10 - 3
partner/src/main/resources/mapper/PartnerUserMapper.xml

@@ -15,7 +15,7 @@
             info.create_by,
             info.create_time,
             d.`name` deptName,
-            (SELECT sa.partner_status  FROM sys_user_jzg_info_salesman sa WHERE sa.type_attr = 3 AND sa.sys_user_jzg_info_id = info.id) AS `status`,
+            sa.partner_status AS `status`,
             info.referrer_id,
             referrer.`name` AS referrerName,
             info.leader_id,
@@ -76,9 +76,11 @@
             LEFT JOIN sys_user_jzg_info referrer ON referrer.id = info.referrer_id
             LEFT JOIN sys_user_jzg_info leader ON leader.id = info.leader_id
             LEFT JOIN sys_user referrerMobile ON referrerMobile.id = referrer.user_id
+            LEFT JOIN sys_user_jzg_info_salesman sa ON  sa.sys_user_jzg_info_id = db.user_id
             <where>
-                <if test="queryVo.isEnable != null and queryVo.isEnable != ''">
-                    and info.status = #{queryVo.status}
+                sa.type_attr = 3
+                <if test="queryVo.status != null and queryVo.status != ''">
+                    and sa.partner_status = #{queryVo.status}
                 </if>
                 <if test="queryVo.deptId != null and queryVo.deptId != ''">
                     and db.dept_id = #{queryVo.deptId}
@@ -1230,4 +1232,9 @@ SELECT
     </select>
 
 
+    <select id="distinctSystemCode" resultType="java.lang.String">
+        SELECT DISTINCT system_code FROM partner_user where system_code is not null and system_code != ''
+    </select>
+
+
 </mapper>

+ 8 - 4
platform/src/main/java/com/jzg/controller/EsmInsCompanyController.java

@@ -33,10 +33,8 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.Arrays;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
+import java.text.Collator;
+import java.util.*;
 import java.util.stream.Collectors;
 
 /**
@@ -333,6 +331,12 @@ public class EsmInsCompanyController extends BaseController {
             }
         }
         List<EsmInsCompanyResVo> esmInsCompanyResVos = BeanUtil.copyToList(list, EsmInsCompanyResVo.class);
+        // modify by lipf, 2026年4月16日17:44:27 对结果进行优化,按照中文进行排序
+        // 1. 获取中文 Collator 实例
+        Collator collator = Collator.getInstance(Locale.CHINA);
+        // 2. 使用 Comparator.comparing 进行排序
+        // 升序 (A-Z)
+        esmInsCompanyResVos.sort(Comparator.comparing(EsmInsCompanyResVo::getNameSimple, collator));
         return HttpResult.ok(esmInsCompanyResVos);
     }
 

+ 5 - 4
platform/src/main/java/com/jzg/service/impl/SysSystemServiceImpl.java

@@ -585,8 +585,10 @@ public class SysSystemServiceImpl extends ServiceImpl<SysSystemMapper, SysSystem
         SysSystemBusPerms sysSystemBusPerms = sysSystemBusPermsMapper.selectOne(new LambdaQueryWrapper<SysSystemBusPerms>()
                 .eq(SysSystemBusPerms::getSystemCode, systemCode));
 
+        if(Objects.isNull(sysSystemBusPerms)){
+            log.info("租户[{}]不存在租户功能配置,请到【平台系统】-【租户管理】-【租户权限】页面进行配置-",systemCode);
+        }
         AssertionUtils.isFail(Objects.isNull(sysSystemBusPerms),"该租户不存在租户功能配置");
-
         List<SysSystemBusPermsLink> sysSystemBusPermsLinks = sysSystemBusPermsLinkMapper.selectList(new LambdaQueryWrapper<SysSystemBusPermsLink>()
                 .eq(SysSystemBusPermsLink::getPermsId, sysSystemBusPerms.getId()));
         return new SysSystemBusPermsVo(sysSystemBusPerms,sysSystemBusPermsLinks);
@@ -608,9 +610,8 @@ public class SysSystemServiceImpl extends ServiceImpl<SysSystemMapper, SysSystem
         if(busPerms.getQuoteCompany() == 2){
             companyIds = busPerms.getQuoteCompanyList();
         }
-        List<EsmInsCompany> companyList = new ArrayList<>();
-        companyList = baseMapper.getCompanyList(companyIds);
-        log.info("租户代码[{}]匹配到保险公司[{}]个。",systemCode, CollUtil.size(companyList));
+        List<EsmInsCompany> companyList = baseMapper.getCompanyList(companyIds);
+        log.info("租户代码[{}]匹配到有报价权限的保险公司[{}]个。",systemCode, CollUtil.size(companyList));
         //log.debug("匹配到的保险公司分别是[{}]", JSONUtil.toJsonStr(companyList));
         // 根据用户权限获取 可使用的协议
         List<String> companyIdList = companyList.stream().map(EsmInsCompany::getId).collect(Collectors.toList());

+ 2 - 0
platform/src/main/resources/mapper/PtlAgreementAttributionMapper.xml

@@ -20,6 +20,8 @@
         paa.user_desc,
         paa.use_status,
         paa.quote_status,
+        paa.create_time,
+        paa.update_time,
         eic.name_simple as insCompanyName,
         pau.url as url,
         sd.name as deptName

+ 5 - 1
tenant/costsorrule/src/main/java/com/jzg/costsorrule/service/impl/RuleServiceImpl.java

@@ -130,7 +130,11 @@ public class RuleServiceImpl implements RuleService {
     }
 
     private boolean checkBoxEqual(RuleAttrLinkVo linkVo, String value) {
-        String[] split = linkVo.getMin().split(",");
+        String min = linkVo.getMin();
+        if (min == null || min.isEmpty()) {
+            return false;
+        }
+        String[] split = min.split(",");
         for (String sp : split) {
             if (sp.equals(value)) {
                 return true;

+ 3 - 3
tenant/insurance/quotation-bohai/src/main/java/com/jzg/quotation/bohai/api/service/impl/BoHaiApiRequestImpl.java

@@ -130,9 +130,9 @@ public class BoHaiApiRequestImpl implements BoHaiApiRequest {
         CarInfoVo carInfoVo = quoteVo.getCarInfoVo();
         // 车辆型号截去汉字
         String brandName = carInfoVo.getBrandName();
-        String processedName = brandName.replaceAll("[\\u4e00-\\u9fa5]", "");
+       // String processedName = brandName.replaceAll("[\\u4e00-\\u9fa5]", "");
         //查询车辆
-        VehicleTypeQueryRequest vehicleTypeQueryRequest = new VehicleTypeQueryRequest(parameters, processedName, orderNo);
+        VehicleTypeQueryRequest vehicleTypeQueryRequest = new VehicleTypeQueryRequest(parameters, brandName, orderNo);
         // 调用 车辆查询和车辆确认接口
         Map<String, Object> map = new HashMap<>();
         try {
@@ -207,7 +207,7 @@ public class BoHaiApiRequestImpl implements BoHaiApiRequest {
                 underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.AUDIT_FAIL);
                 StringBuilder sb = new StringBuilder();
                 if (null != underwritingResponse.getData().getTrafficResultMsg()) {
-                    sb.append(String.format("交强险提示信息:%s", underwritingResponse.getData().getTrafficResultMsg()));
+                        sb.append(String.format("交强险提示信息:%s", underwritingResponse.getData().getTrafficResultMsg()));
                 }
                 if (null != underwritingResponse.getData().getBusinessResultMsg()) {
                     sb.append(String.format("商业险提示信息:%s", underwritingResponse.getData().getBusinessResultMsg()));

BIN
tenant/insurance/quotation-bohai/中介车险业务接口文档-v1.1.2.doc


+ 1 - 1
tenant/insurance/quotation-commons/pom.xml

@@ -28,7 +28,7 @@
         <dependency>
             <groupId>cn.hutool</groupId>
             <artifactId>hutool-all</artifactId>
-            <version>5.7.21</version>
+            <version>5.8.31</version>
         </dependency>
         <!--thumbnailator图片处理-->
         <dependency>

+ 9 - 0
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/client/PlatformClient.java

@@ -9,6 +9,7 @@ import com.jzg.commons.entity.po.QrBarcodeConfig;
 import com.jzg.commons.entity.po.SysUploadFiles;
 import com.jzg.commons.entity.vo.CompanyClauseVo;
 import com.jzg.commons.entity.vo.InsCompanyClauseVo;
+import com.jzg.commons.entity.vo.JyxConfigVo;
 import io.swagger.v3.oas.annotations.Operation;
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.http.MediaType;
@@ -126,4 +127,12 @@ public interface PlatformClient {
     @PostMapping("/esmInsCompany/getParentIds")
     HttpResult getParentIds(@RequestBody List<String> companyIds);
 
+    /**
+     * 查询驾意险的信息
+     *
+     * @return
+     */
+    @GetMapping("/jyxConfig/getById")
+    HttpResult<JyxConfigVo> jyxConfigGetById(@RequestParam String id);
+
 }

+ 15 - 2
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/component/RequestComponent.java

@@ -492,9 +492,22 @@ public class RequestComponent {
             log.error("WebClient请求失败,状态码: {}, 响应头: {}", e.getStatusCode(), e.getHeaders(), e);
             throw e;
         } catch (Exception e) {
-            // 处理其他异常
+            // 处理其他异常(修复NPE)
             log.error("请求失败", e);
-            throw new WebClientResponseException(500, "Request failed: " + e.getMessage(), HttpHeaders.EMPTY, e.getMessage().getBytes(StandardCharsets.UTF_8), null);
+
+            // 核心修复:e.getMessage() 可能为 null,必须判空
+            String errorMsg = e.getMessage();
+            if (errorMsg == null) {
+                errorMsg = "网络请求超时或服务端无响应";
+            }
+
+            throw new WebClientResponseException(
+                    500,
+                    "Request failed: " + errorMsg,
+                    HttpHeaders.EMPTY,
+                    errorMsg.getBytes(StandardCharsets.UTF_8),
+                    null
+            );
         }
     }
 

+ 0 - 1
tenant/insurance/quotation-commons/src/main/java/com/jzg/quotation/commons/utils/HttpUtil.java

@@ -183,5 +183,4 @@ public class HttpUtil {
         return null;
     }
 
-
 }

+ 4 - 7
tenant/insurance/quotation-dajia/src/main/java/com/jzg/quotation/dajia/api/compoment/DaJiaApiRequestComponent.java

@@ -35,16 +35,13 @@ public class DaJiaApiRequestComponent {
             HttpHeaders httpHeaders = new HttpHeaders();
             httpHeaders.setContentType(MediaType.TEXT_PLAIN);
             httpHeaders.set("User-Agent","");
-            System.out.println("\n\t---------> URl: {"
-                    +url+"} \n---------> 保险公司:{"
-                    + InsuranceEnum.DJPC.getName()+"}\n---------> 请求参数:{"
-                    +JSON.toJSONString(requestBody)+"}");
+            log.info("\n\t-------> URL=[{}],\r\n------> 保险公司[{}],\r\n------> 请求参数[{}]", url, InsuranceEnum.DJPC.getName(),JSON.toJSONString(requestBody));
             String encrypt = AESEncrypt.encrypt(JSON.toJSONString(requestBody), daJiaApiProperties.getEncryptKey());
-            System.out.println(encrypt);
+            log.info("加密后的参数[{}]",encrypt);
             HttpEntity<String> httpEntity = new HttpEntity<>(encrypt, httpHeaders);
             ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST,  httpEntity, String.class);
             String body = response.getBody();
-            System.out.println("\n\n---------> 响应参数:{"+body+"}");
+            log.info("\r\n---------> 响应参数:[{}]",body);
             if(ObjectUtils.isEmpty(body)){
                 throw new SystemException("请求失败");
             }
@@ -63,7 +60,7 @@ public class DaJiaApiRequestComponent {
             }
             return b;
         }catch (Exception e){
-            System.out.println(e.getMessage());
+            log.error("大家车险报价异常",e);
             throw new SystemException(e.getMessage());
         }
     }

+ 8 - 2
tenant/insurance/quotation-dajia/src/main/java/com/jzg/quotation/dajia/api/entity/request/ODR1009Request.java

@@ -12,6 +12,8 @@ import com.jzg.quotation.dajia.api.entity.DaJiaBaseRequest;
 import com.jzg.quotation.dajia.api.entity.response.ODR1016Response;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import java.io.Serializable;
 import java.util.ArrayList;
@@ -21,7 +23,7 @@ import java.util.Objects;
 import static com.jzg.quotation.dajia.api.constant.CPayTaxType.T5002;
 
 /**
- * @version
+ *
  * @description: ODR1008 保费计算 请求参数
  * @author: wenks
  * @date: 2023/11/14 16:51
@@ -33,6 +35,8 @@ public class ODR1009Request extends DaJiaBaseRequest {
 
     private static final long serialVersionUID = -3271826016394642480L;
 
+    private static final Logger log = LoggerFactory.getLogger(ODR1009Request.class);
+
     @JsonProperty("body")
     private BodyDTO body;
 
@@ -184,7 +188,7 @@ public class ODR1009Request extends DaJiaBaseRequest {
     //商业险别信息(列表)
     public void setCoverageList(QuoteVo quoteVo,ODR1016Response odr1016Response){
         ArrayList<BodyDTO.coverageListDTO> coverageListDTOS = new ArrayList<>();
-        Integer seatCount = Integer.parseInt(quoteVo.getCarInfoVo().getSeatCount());
+        int seatCount = Integer.parseInt(quoteVo.getCarInfoVo().getSeatCount());
         List<KindInfoVo> kindInfoVos = quoteVo.getKindInfoVo();
         kindInfoVos.forEach(kindInfoVo->{
             BodyDTO.coverageListDTO coverageListDTO = new BodyDTO.coverageListDTO();
@@ -307,6 +311,8 @@ public class ODR1009Request extends DaJiaBaseRequest {
             //非车投保份数
             nvhPolicyListDTO.setNoVhlSum(item.getQuantity() + "");
             //非车险每份保费
+            log.info("item.getSumPremium()=[{}],item.getQuantity()=[{}]",item.getSumPremium(), item.getQuantity());
+            //item.setSumPremium("10000");
             nvhPolicyListDTO.setNvhlPrm(Double.parseDouble(item.getSumPremium()) / item.getQuantity() + "");
             //险别代码
             nvhPolicyListDTO.setNvhlSumPrm(item.getSumPremium());

+ 21 - 4
tenant/insurance/quotation-dajia/src/main/java/com/jzg/quotation/dajia/api/service/impl/DaJiaApiRequestImpl.java

@@ -1,8 +1,8 @@
 package com.jzg.quotation.dajia.api.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.json.JSONUtil;
 import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.jzg.commons.constants.InsuranceRisk;
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
@@ -33,7 +33,8 @@ import com.jzg.quotation.dajia.api.entity.vo.PersonAreaVo;
 import com.jzg.quotation.dajia.api.service.DaJiaApiOrderService;
 import com.jzg.quotation.dajia.api.service.DaJiaApiRequest;
 import lombok.RequiredArgsConstructor;
-import org.springframework.stereotype.Service;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.text.SimpleDateFormat;
@@ -49,6 +50,8 @@ import java.util.stream.Collectors;
 @Transactional
 public class DaJiaApiRequestImpl implements DaJiaApiRequest {
 
+    private static final Logger log = LoggerFactory.getLogger(DaJiaApiRequestImpl.class);
+
     private final DaJiaApiRequestComponent daJiaApiRequestComponent;
 
     private final DaJiaApiOrderService daJiaCrawlerOrderService;
@@ -67,10 +70,13 @@ public class DaJiaApiRequestImpl implements DaJiaApiRequest {
 
     @Override
     public QuoteResultsVo quote(QuoteVo quoteVo) throws JsonProcessingException {
+        log.info("大家保险车险API报价:quoteVo=[{}]", JSONUtil.toJsonStr(quoteVo));
         OrderBase order = quoteVo.getOrder();
         AttributionInformationVo attributionInformationVo = order.getAttributionInformationVo();
         // 配置信息
         String url = getApiUrl(order.getInsuranceCompanyCode());
+        // 临时验证
+        //url = "https://open-ics.djbx.com/dip-agent/agent/invokeForVchicle/api/";
         DaJiaApiConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(DaJiaApiConfigureParameters.class,
                 attributionInformationVo.getConfigInfo());
         // 获取业务订单号
@@ -102,15 +108,18 @@ public class DaJiaApiRequestImpl implements DaJiaApiRequest {
         // 报价
         ODR1009Response odr1009Response = quotation(orderNo, quoteVo, odr1016Response, parameters,url);
         if(!odr1009Response.getStatus().equals("0000")){
+            log.info("大家保险报价失败,失败原因:{}]",odr1009Response.getMessage());
             throw new SystemException(odr1009Response.getMessage());
         }
         List<AccidentalDrivingVo> accidentalDrivings = quoteVo.getAccidentalDrivings();
         NVHLODR1001Response nvhlodr1001Response = null;
         if (CollUtil.isNotEmpty(accidentalDrivings)) {
+            log.debug("大家保险进行非车险报价. accidentalDrivings=[{}]", JSONUtil.toJsonStr(accidentalDrivings));
             //6.驾意险报价
             NVHLODR1001Request nvhlodr1001Request = new NVHLODR1001Request(parameters, odr1009Response, order.getOrdersNo(), accidentalDrivings, quoteVo);
             nvhlodr1001Response = daJiaApiRequestComponent.accidentPremiumCalculation(nvhlodr1001Request,url);
             if (!"2000".equals(nvhlodr1001Response.getStatus())) {
+                log.info("大家保险进行非车险报价失败。nvhlodr1001Response=[{}]", JSONUtil.toJsonStr(nvhlodr1001Response));
                 throw new SystemException("驾意险报价失败");
             }
         }
@@ -146,8 +155,13 @@ public class DaJiaApiRequestImpl implements DaJiaApiRequest {
     private void repeatCoverhandler(ODR1009Response odr1009Response, QuoteVo quoteVo, String orderNo, ODR1016Response odr1016Response, DaJiaApiConfigureParameters parameters,String url) {
         if (odr1009Response.getStatus().equals(Message.M0002.getCode())) {
             //获取重复投保信息
-            String jqAppStatusMessage = odr1009Response.getResult().getJqAppStatusMessage() == null ? "" : odr1009Response.getResult().getJqAppStatusMessage().toString();
-            String syAppStatusMessage = odr1009Response.getResult().getReInsuredInfo() == null ? "" : odr1009Response.getResult().getReInsuredInfo();
+            ODR1009Response.ResultDTO res =  odr1009Response.getResult();
+            String jqAppStatusMessage="";
+            String syAppStatusMessage="";
+            if(res != null){
+                jqAppStatusMessage = odr1009Response.getResult().getJqAppStatusMessage() == null ? "" : odr1009Response.getResult().getJqAppStatusMessage().toString();
+                syAppStatusMessage = odr1009Response.getResult().getReInsuredInfo() == null ? "" : odr1009Response.getResult().getReInsuredInfo();
+            }
             if (jqAppStatusMessage.contains("重复投保") || syAppStatusMessage.contains("重复投保")) {
                 //交强重复投保
                 RiskInfoVo ciRiskInfoVo = quoteVo.getCiRiskInfoVo();
@@ -217,6 +231,9 @@ public class DaJiaApiRequestImpl implements DaJiaApiRequest {
             LocalDateTime timePlusOneSecond = time.plusSeconds(1);
             newStDate = timePlusOneSecond.format(formatter);
         }
+        if(newStDate == null || newStDate.endsWith("")){
+            newStDate = "2026-04-17 12:00:34";
+        }
 
         LocalDateTime start = DateTimeUtil.parseLocalDateTime(newStDate, DateTimeUtil.DATETIME_PATTERN);
         List<String> result = new ArrayList<>();

+ 192 - 72
tenant/insurance/quotation-guoren/src/main/java/com/jzg/quotation/guoren/api/service/Impl/GuoRenApiRequestImpl.java

@@ -11,12 +11,14 @@ import com.jzg.commons.entity.agreement.po.PtlAgreementUrl;
 import com.jzg.commons.entity.orders.po.InsOrders;
 import com.jzg.commons.entity.orders.po.InsOrdersPolicy;
 import com.jzg.commons.entity.po.InsCompanyClause;
+import com.jzg.commons.entity.po.SysUploadFiles;
 import com.jzg.commons.entity.quote.vo.AccidentalDrivingVo;
 import com.jzg.commons.entity.quote.vo.CarInfoVo;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.commons.entity.quote.vo.aggregated.*;
 import com.jzg.commons.exception.SystemException;
 import com.jzg.commons.util.AssertionUtils;
+import com.jzg.commons.util.MinioUtils;
 import com.jzg.commons.util.StringUtils;
 import com.jzg.quotation.commons.annotation.QuoteApiService;
 import com.jzg.quotation.commons.client.PlatformClient;
@@ -27,6 +29,7 @@ import com.jzg.commons.entity.quote.vo.image.InsuranceImageVo;
 import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
 import com.jzg.quotation.commons.utils.DateTimeUtil;
 import com.jzg.quotation.commons.utils.HttpUtil;
+import com.jzg.quotation.commons.utils.TimeProcessing;
 import com.jzg.quotation.guoren.api.build.GuoRenApiQuoteResultsVoBuild;
 import com.jzg.quotation.guoren.api.component.GuoRenRequestApiComponent;
 import com.jzg.quotation.guoren.api.component.GuorenDuplicateInsuranceComponent;
@@ -42,6 +45,7 @@ import com.jzg.quotation.guoren.api.properties.GuoRenApiConfigurationProperties;
 import com.jzg.quotation.guoren.api.service.GuoRenApiOrderService;
 import com.jzg.quotation.guoren.api.service.GuoRenApiRequest;
 import lombok.RequiredArgsConstructor;
+import org.apache.commons.compress.utils.IOUtils;
 import org.apache.commons.httpclient.methods.multipart.FilePart;
 import org.apache.commons.httpclient.methods.multipart.Part;
 import org.apache.commons.httpclient.methods.multipart.StringPart;
@@ -52,6 +56,7 @@ import org.springframework.util.ObjectUtils;
 
 import java.io.File;
 import java.io.FileOutputStream;
+import java.io.InputStream;
 import java.math.BigDecimal;
 import java.util.*;
 import java.util.stream.Collectors;
@@ -59,6 +64,7 @@ import java.util.stream.Collectors;
 
 /**
  * description:
+ *
  * @author: shenwd
  * @date: 2025/3/14 09:58
  **/
@@ -79,6 +85,8 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
 
     private final PlatformClient platformClient;
 
+    private final MinioUtils minioUtils;
+
     public String getApiUrl(String companyId) {
         // 获取保司配置url地址
         HttpResult<PtlAgreementUrl> ptlAgreementUrl = platformClient.getAgreementUrlByCompanyId(companyId);
@@ -87,6 +95,7 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
 
     /**
      * 报价
+     *
      * @param quoteVo 报价实体
      * @return 报价信息
      */
@@ -103,11 +112,11 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
         vinQueryRequest.setFrameNo(carInfoVo.getVinNo());
         vinQueryRequest.setLicenseNo(carInfoVo.getLicenseNo());
 
-        VinQueryResponse.DataDTO vinQuery = vinQuery(vinQueryRequest, parameters,url);
+        VinQueryResponse.DataDTO vinQuery = vinQuery(vinQueryRequest, parameters, url);
         AssertionUtils.isEmpty(vinQuery, "未找到匹配的车辆信息");
 
         //车价查询
-        CarPriceResponse.DataDTO carPriceQuery = carPriceQuery(quoteVo, vinQuery, parameters,url);
+        CarPriceResponse.DataDTO carPriceQuery = carPriceQuery(quoteVo, vinQuery, parameters, url);
         AssertionUtils.isEmpty(carPriceQuery, "车价获取失败");
 
         //创建非车订单
@@ -142,11 +151,11 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
             guoRenApiOrder.setId(orderBase.getOrdersNo());
             guoRenApiOrder.setOrdersNo(orderBase.getOrdersNo());
             guoRenApiOrder.setProductsCode(orderBase.getProductId());
-            return handleFailedQuote(guoRenApiOrder,quoteVo,premiumResponse);
+            return handleFailedQuote(guoRenApiOrder, quoteVo, premiumResponse);
         } else {
             //保存投保单 该接口返回投保单号
             InsuranceSlipResponse insuranceSlipResponse = guoRenRequestApiComponent.insuranceSlip(quoteVo,
-                    carPriceQuery.getInputvo(), orderCode, specialAgreements,url);
+                    carPriceQuery.getInputvo(), orderCode, specialAgreements, url);
             if (insuranceSlipResponse.getResultCode() == 1) {
                 throw new SystemException(insuranceSlipResponse.getResultMsg());
             }
@@ -163,22 +172,21 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
             guoRenApiOrder.setCarTax(BigDecimal.valueOf(premiumResponse.getData().getSumPayTax()));
             guoRenApiOrder.setOthBusinessNo(carPriceQuery.getInputvo());
             guoRenApiOrder.setNoCarOrderNo(nonAutoInsOrderResponse != null ? nonAutoInsOrderResponse.getData().getOrderCode() : "");
-            return handleSuccessQuote(guoRenApiOrder,quoteVo, premiumResponse,nonAutoInsOrderResponse);
+            return handleSuccessQuote(guoRenApiOrder, quoteVo, premiumResponse, nonAutoInsOrderResponse);
         }
     }
 
-    private QuoteResultsVo handleFailedQuote(GuoRenApiOrder guoRenApiOrder,QuoteVo quoteVo,PremiumResponse response) {
+    private QuoteResultsVo handleFailedQuote(GuoRenApiOrder guoRenApiOrder, QuoteVo quoteVo, PremiumResponse response) {
         guoRenApiOrderService.save(guoRenApiOrder);
         return GuoRenApiQuoteResultsVoBuild.buildQuoteFailResultsVo(response);
     }
 
-    private QuoteResultsVo handleSuccessQuote(GuoRenApiOrder guoRenApiOrder,QuoteVo quoteVo,PremiumResponse response,NonAutoInsOrderResponse nonAutoInsOrderResponse) {
+    private QuoteResultsVo handleSuccessQuote(GuoRenApiOrder guoRenApiOrder, QuoteVo quoteVo, PremiumResponse response, NonAutoInsOrderResponse nonAutoInsOrderResponse) {
         guoRenApiOrderService.save(guoRenApiOrder);
-        return GuoRenApiQuoteResultsVoBuild.buildQuoteResultsVo(quoteVo,response,nonAutoInsOrderResponse);
+        return GuoRenApiQuoteResultsVoBuild.buildQuoteResultsVo(quoteVo, response, nonAutoInsOrderResponse);
     }
 
 
-
     /**
      * 提交核保 子订单
      *
@@ -192,7 +200,7 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
         GuoRenConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(GuoRenConfigureParameters.class, orderBase.getAttributionInformationVo().getConfigInfo());
         GuoRenApiOrder guoRenApiOrder = guoRenApiOrderService.findByOrdersNo(orderBase.getOrdersNo());
 
-        SubmitAuditResponse auditResponse = guoRenRequestApiComponent.submitAudit(guoRenApiOrder, parameters,url);
+        SubmitAuditResponse auditResponse = guoRenRequestApiComponent.submitAudit(guoRenApiOrder, parameters, url);
         UnderwritingResultsVo underwritingResultsVo = new UnderwritingResultsVo();
         String jqStatus = auditResponse.getData().get(0).getUnderWriteFlagCI();
         String syStatus = auditResponse.getData().get(0).getUnderWriteFlagBI();
@@ -200,14 +208,14 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
         // 0初始值/1通过/2不通过/3无需核保/9人工核保
         if (StringUtils.isEmpty(jqStatus) && StringUtils.isEmpty(syStatus)) {
             underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.AUDIT_FAIL);
-            underwritingResultsVo.setUnderwritingResult("核保失败:"+ message);
+            underwritingResultsVo.setUnderwritingResult("核保失败:" + message);
             return underwritingResultsVo;
         }
         // 单交核保状态
         if (StringUtils.isNotEmpty(jqStatus) && StringUtils.isEmpty(syStatus)) {
             if (jqStatus.equals("1") || jqStatus.equals("3")) {
                 underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.PAY_PENDING);
-                SignatureResponse signature = getSignature(guoRenApiOrder,url);
+                SignatureResponse signature = getSignature(guoRenApiOrder, url);
                 underwritingResultsVo.setPaymentLink(signature.getQrCode());
             } else if (jqStatus.equals("2") || jqStatus.equals("0")) {
                 underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.AUDIT_FAIL);
@@ -218,7 +226,7 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
         if (StringUtils.isEmpty(syStatus) && StringUtils.isNotEmpty(syStatus)) {
             if (syStatus.equals("1") || syStatus.equals("3")) {
                 underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.PAY_PENDING);
-                SignatureResponse signature = getSignature(guoRenApiOrder,url);
+                SignatureResponse signature = getSignature(guoRenApiOrder, url);
                 underwritingResultsVo.setPaymentLink(signature.getQrCode());
 
             } else if (syStatus.equals("2") || syStatus.equals("0")) {
@@ -234,11 +242,11 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
                 underwritingResultsVo.setUnderwritingResult(message);
             } else if (jqStatus.equals("1") && syStatus.equals("1")) {
                 underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.PAY_PENDING);
-                SignatureResponse signature = getSignature(guoRenApiOrder,url);
+                SignatureResponse signature = getSignature(guoRenApiOrder, url);
                 underwritingResultsVo.setPaymentLink(signature.getQrCode());
             } else if (jqStatus.equals("3") && syStatus.equals("3")) {
                 underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.PAY_PENDING);
-                SignatureResponse signature = getSignature(guoRenApiOrder,url);
+                SignatureResponse signature = getSignature(guoRenApiOrder, url);
                 underwritingResultsVo.setPaymentLink(signature.getQrCode());
             }
         }
@@ -248,13 +256,14 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
     /**
      * 通过二维码扫描获取电子投保单签名
      */
-    public SignatureResponse getSignature(GuoRenApiOrder guoRenApiOrder,String url) {
-        return guoRenRequestApiComponent.signature(guoRenApiOrder,url);
+    public SignatureResponse getSignature(GuoRenApiOrder guoRenApiOrder, String url) {
+        return guoRenRequestApiComponent.signature(guoRenApiOrder, url);
     }
 
 
     /**
      * 获取支付链接
+     *
      * @param paymentLinkVo
      */
     @Override
@@ -264,7 +273,7 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
         GuoRenConfigureParameters parameters = ConfigureParametersConversion.conversionEntity(GuoRenConfigureParameters.class, paymentLinkVo.getOrder().getAttributionInformationVo().getConfigInfo());
         GuoRenApiOrder guoRenApiOrder = guoRenApiOrderService.findByOrdersNo(paymentLinkVo.getOrder().getOrdersNo());
 
-        PayResponse.DataDTO dataDTO = guoRenRequestApiComponent.getPaid(guoRenApiOrder, parameters,url);
+        PayResponse.DataDTO dataDTO = guoRenRequestApiComponent.getPaid(guoRenApiOrder, parameters, url);
         PaymentLinkResultsVo resultsVo = new PaymentLinkResultsVo();
         resultsVo.setPaymentLink(dataDTO.getPayUrl());
         return resultsVo;
@@ -272,6 +281,7 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
 
     /**
      * 上传影像
+     *
      * @param insuranceUploadImageVo
      */
     @Override
@@ -291,6 +301,7 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
 
     /**
      * 下载保单
+     *
      * @param downloadPolicyVo
      */
     @Override
@@ -304,16 +315,16 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
         String syPolicyNo = policie.getSyPolicyNo();
         String jyPolicyNo = policie.getJyPolicyNo();
         if (jqPolicyNo != null) {
-            PolicyResponse jqResponse = guoRenRequestApiComponent.policyPrint(jqPolicyNo,url);
+            PolicyResponse jqResponse = guoRenRequestApiComponent.policyPrint(jqPolicyNo, url);
             downloadPolicyResultVo.setJqFlagUrl(properties.getPolicyFlagUrl() + jqResponse.getData());
             downloadPolicyResultVo.setJqUrl(properties.getPolicyUrl() + jqResponse.getData());
         }
         if (syPolicyNo != null) {
-            PolicyResponse syResponse = guoRenRequestApiComponent.policyPrint(syPolicyNo,url);
+            PolicyResponse syResponse = guoRenRequestApiComponent.policyPrint(syPolicyNo, url);
             downloadPolicyResultVo.setSyUrl(properties.getPolicyUrl() + syResponse.getData());
         }
         if (jyPolicyNo != null) {
-            String jyResponse = guoRenRequestApiComponent.noCarElectronicPolicy(properties.getChannelCode(),guoRenApiOrder.getOthBusinessNo(),jyPolicyNo,url);
+            String jyResponse = guoRenRequestApiComponent.noCarElectronicPolicy(properties.getChannelCode(), guoRenApiOrder.getOthBusinessNo(), jyPolicyNo, url);
             downloadPolicyResultVo.setJyUrl(jyResponse);
         }
         return downloadPolicyResultVo;
@@ -326,13 +337,17 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
      */
     @Override
     public OrderStatusResultVo queryOrderState(OrderStatusVo orderBase) {
+        GuoRenApiOrder guoRenApiOrder = guoRenApiOrderService.findByOrdersNo(orderBase.getOrder().getOrdersNo());
+
         //查询投保单信息
         InsOrdersPolicy insOrdersPolicy = orderBase.getInsOrdersPolicy();
+        insOrdersPolicy.setJqApplyNo(guoRenApiOrder.getJqApplyNo());
+        insOrdersPolicy.setSyApplyNo(guoRenApiOrder.getSyApplyNo());
+
         InsOrders insOrders = orderBase.getInsOrders();
         String url = getApiUrl(orderBase.getOrder().getInsuranceCompanyId());
         // 获取保司订单状态
-        OrderStateResponse orderStateResponse = insOrderStatus(insOrdersPolicy,url);
-        GuoRenApiOrder guoRenApiOrder = guoRenApiOrderService.findByOrdersNo(orderBase.getOrder().getOrdersNo());
+        OrderStateResponse orderStateResponse = insOrderStatus(insOrdersPolicy, url);
         OrderStatusResultVo orderStatusResultVo = new OrderStatusResultVo();
         if (null != orderStateResponse && CollUtil.isNotEmpty(orderStateResponse.getData())) {
             OrderStateResponse.DataDTO jqDataDTO =
@@ -370,7 +385,7 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
             // 支付
             if (updateFlag) {
                 orderStatusResultVo.setOrderStatus(InsOrderStatusEnum.UNDERWRITED);
-                List<DrivingInsuranceDTO> drivingInsuranceDTOList = guoRenRequestApiComponent.queryNoCarPolicyNo(guoRenApiOrder,url);
+                List<DrivingInsuranceDTO> drivingInsuranceDTOList = guoRenRequestApiComponent.queryNoCarPolicyNo(guoRenApiOrder, url);
                 drivingInsuranceDTOList.forEach(drivingInsuranceDTO -> {
                     orderStatusResultVo.setJyPolicyno(drivingInsuranceDTO.getPolicyNumber());
                     orderStatusResultVo.setJyApplyNo(drivingInsuranceDTO.getApplicationNumber());
@@ -381,7 +396,7 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
         return null;
     }
 
-    public OrderStateResponse insOrderStatus(InsOrdersPolicy insOrdersPolicy,String url) {
+    public OrderStateResponse insOrderStatus(InsOrdersPolicy insOrdersPolicy, String url) {
         OrderStateRequest orderStateRequest = new OrderStateRequest();
         // 交强投保单号
         orderStateRequest.addProposalNos(insOrdersPolicy.getJqApplyNo());
@@ -389,19 +404,20 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
         orderStateRequest.addProposalNos(insOrdersPolicy.getSyApplyNo());
         //投保单状态查询
         return guoRenRequestApiComponent.request(orderStateRequest, PlatformInterfaceCode.API_IIRBT00010,
-                OrderStateResponse.class,url);
+                OrderStateResponse.class, url);
     }
 
     /**
      * vin码查询车辆信息
+     *
      * @return VinQueryResp.DataDTO
      * @author: lig
      * @date: 2023年08月18日 0018
      */
-    public VinQueryResponse.DataDTO vinQuery(VinQueryRequest vinQueryReq, GuoRenConfigureParameters parameters,String url) {
+    public VinQueryResponse.DataDTO vinQuery(VinQueryRequest vinQueryReq, GuoRenConfigureParameters parameters, String url) {
         VinQueryRequest req = new VinQueryRequest(vinQueryReq, parameters);
         VinQueryResponse resp = guoRenRequestApiComponent.request(req, PlatformInterfaceCode.API_IIRBT00009,
-                VinQueryResponse.class,url);
+                VinQueryResponse.class, url);
         if (resp.getResultCode() == 1) {
             throw new SystemException(resp.getResultMsg() == null ? "未找到车辆信息" : resp.getResultMsg());
         }
@@ -412,10 +428,10 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
      * 车价查询
      */
     public CarPriceResponse.DataDTO carPriceQuery(QuoteVo quoteVo, VinQueryResponse.DataDTO vinQ,
-                                                  GuoRenConfigureParameters parameters,String url) {
+                                                  GuoRenConfigureParameters parameters, String url) {
 
         CarPriceRequest req = CarPriceRequest.buildCarPriceParam(quoteVo, vinQ, parameters);
-        JSONObject request = guoRenRequestApiComponent.request(req, PlatformInterfaceCode.API_IIRBT00003,url);
+        JSONObject request = guoRenRequestApiComponent.request(req, PlatformInterfaceCode.API_IIRBT00003, url);
         Object cars = request.get("cars");
 
         if (ObjectUtils.isEmpty(cars)) {
@@ -438,7 +454,7 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
                 //车辆年款不能超过注册日期
                 List<CarPriceMuchResponse.DataDTO.CarsDTO> vehicleInfoList =
                         respMuch.getData().getCars().stream().filter(a -> DateTimeUtil.dateIsAfter(carInfo.getRegisterDate(),
-                                    a.getCarYear())).collect(Collectors.toList());
+                                a.getCarYear())).collect(Collectors.toList());
 
                 //匹配的车辆信息数据  为空
                 if (CollUtil.isEmpty(vehicleInfoList)) {
@@ -458,7 +474,7 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
                         confirmCarMuch = vehicleInfoList.get(0);
                     }
                 }
-                return carPriceQueryMuch(respMuch.getData().getInputvo(), confirmCarMuch,url
+                return carPriceQueryMuch(respMuch.getData().getInputvo(), confirmCarMuch, url
                 );
             }
         }
@@ -468,12 +484,12 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
     /**
      * (多条)车价查询
      */
-    public CarPriceResponse.DataDTO carPriceQueryMuch(String uuid, CarPriceMuchResponse.DataDTO.CarsDTO carsDTO,String url) {
+    public CarPriceResponse.DataDTO carPriceQueryMuch(String uuid, CarPriceMuchResponse.DataDTO.CarsDTO carsDTO, String url) {
         //构造请求参数
         CarPriceMuchRequest req = new CarPriceMuchRequest();
         req.setUuid(uuid);
         req.setCarPriceMuchResp(carsDTO);
-        JSONObject request = guoRenRequestApiComponent.request(req, PlatformInterfaceCode.API_IIRBT00017,url);
+        JSONObject request = guoRenRequestApiComponent.request(req, PlatformInterfaceCode.API_IIRBT00017, url);
         CarPriceResponse resp = request.toJavaObject(CarPriceResponse.class);
         if (resp.getResultCode() == 1) {
             throw new SystemException(resp.getResultMsg() == null ? "未获取到车价信息,请联系管理员" : resp.getResultMsg());
@@ -484,6 +500,7 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
 
     /**
      * 意外险转换
+     *
      * @param accidentalDrivingVoList
      * @return
      */
@@ -504,23 +521,25 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
 
     /**
      * 创建非车订单
+     *
      * @author: lig
      * @date: 2023-09-28
      */
     public NonAutoInsOrderResponse nonAutoInsOrder(QuoteVo quoteVo,
                                                    GuoRenAccidentalDrivingVo accidentalDrivingVo,
                                                    String carPriceUuid, GuoRenConfigureParameters channelInfo,
-                                                   VinQueryResponse.DataDTO vinQ,String url) {
+                                                   VinQueryResponse.DataDTO vinQ, String url) {
         //构造请求参数
         NonAutoInsOrderRequest nonAutoInsOrderReq = new NonAutoInsOrderRequest(quoteVo, vinQ, accidentalDrivingVo,
                 channelInfo,
                 carPriceUuid, properties.getChannelCode());
         return guoRenRequestApiComponent.request(nonAutoInsOrderReq, PlatformInterfaceCode.API_IIIRBT00054,
-                NonAutoInsOrderResponse.class,url);
+                NonAutoInsOrderResponse.class, url);
     }
 
     /**
      * 查询国任特约数据
+     *
      * @param quoteVo 原参数为agreementId,以后看orderbase中的配置信息map中是否可以获取
      * @return
      */
@@ -551,7 +570,6 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
 //        }
 //        return list;
 //    }
-
     public List<GuoRenSpecialAgreementVo> getSpecialAgreements(QuoteVo quoteVo) {
         List<InsCompanyClause> companyClauseVos = quoteVo.getSpecialInfoVo();
         List<GuoRenSpecialAgreementVo> list = new ArrayList<>();
@@ -563,7 +581,7 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
     }
 
     public PremiumResponse premiumQuery(QuoteVo quoteVo, CarPriceResponse.DataDTO carPriceQuery, VinQueryResponse.DataDTO vinQuery, Boolean isNoCar,
-                                        List<GuoRenSpecialAgreementVo> specialAgreements, String noCarPremium, String goodsCode,String url) {
+                                        List<GuoRenSpecialAgreementVo> specialAgreements, String noCarPremium, String goodsCode, String url) {
         boolean boo;
         //请求信息列表
         List<String> requestInfoList = new ArrayList<>();
@@ -572,7 +590,7 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
         PremiumResponse premiumResponse;
         int a = 0;
         for (; ; ) {
-            premiumResponse = guoRenRequestApiComponent.request(premiumRequest, PlatformInterfaceCode.API_IIRBT00004, PremiumResponse.class,url);
+            premiumResponse = guoRenRequestApiComponent.request(premiumRequest, PlatformInterfaceCode.API_IIRBT00004, PremiumResponse.class, url);
 
             premiumRequest.getCi().getPrpTmain().setAnswer(null);
             premiumRequest.getBi().getPrpTmain().setAnswer(null);
@@ -608,72 +626,174 @@ public class GuoRenApiRequestImpl implements GuoRenApiRequest {
 
     /**
      * 影像上传 调用三方
+     * 请求参数:
+     * - businessNo: 投保单号(交商同保传交强)
+     * - operatorCode: 操作人代码
+     * - comCode: 机构代码
+     * - fileGroup: 影像类型(DZ—单证影像,YC-验车影像)
+     * - file: 图片对象
      */
     public void imageUpdate(GuoRenApiOrder guoRenApiOrder, GuoRenConfigureParameters parameters, InsuranceUploadImageVo insuranceUploadImageVo) {
+        // 获取交强险投保单号(交商同保传交强)
+        String businessNo = guoRenApiOrder.getJqApplyNo();
+        if (StringUtils.isEmpty(businessNo)) {
+            logger.error("国任上传影像失败,交强险投保单号为空");
+            throw new SystemException("国任,影像上传失败,投保单号为空");
+        }
 
-        //构造请求参数
-        Map<String, Object> formMap = new HashMap<>();
-        formMap.put("businessNo", StringUtils.isEmpty(guoRenApiOrder.getJqApplyNo()) ? guoRenApiOrder.getSyApplyNo() : guoRenApiOrder.getJqApplyNo());
-        formMap.put("operatorCode", parameters.getHandlerCode());
-        formMap.put("comCode", parameters.getComCode());
-        formMap.put("fileGroup", "DZ");
+        // 操作人代码
+        String operatorCode = parameters.getHandlerCode();
+        // 机构代码
+        String comCode = parameters.getComCode();
 
         List<InsuranceImageVo> imageVoList = insuranceUploadImageVo.getImageVoList();
-        Map<String, List<String>> map = new HashMap<>();
+        Map<String, List<String>> resultMap = new HashMap<>();
+
+        if (CollUtil.isEmpty(imageVoList)) {
+            logger.warn("国任上传影像失败,影像列表为空");
+            return;
+        }
+
+        for (InsuranceImageVo imageVo : imageVoList) {
+            if (imageVo == null) {
+                continue;
+            }
 
-        imageVoList.forEach(insuranceImageVo -> {
             List<String> imageIds = new ArrayList<>();
-            for (InsuranceImageVo.ImageDTO imageDTO : insuranceImageVo.getImageBase64List()) {
-                try {
-                    //需要设置一个临时图片路径
-                    File tempFile = File.createTempFile("upload_temp_",  getFileSuffix(imageDTO.getImageName()));
-                    FilePart file1 = new FilePart("file", tempFile);
+            List<InsuranceImageVo.ImageDTO> imageList = imageVo.getImageBase64List();
+
+            if (CollUtil.isEmpty(imageList)) {
+                logger.warn("国任上传影像失败,影像Base64列表为空,类型:{}", imageVo.getImageType());
+                continue;
+            }
+
+            // 根据影像类型确定fileGroup
+            String fileGroup = getFileGroup(imageVo);
+
+            byte[] imageBytes;
+            String fileName;
+
+            for (InsuranceImageVo.ImageDTO imageDTO : imageList) {
+                if (imageDTO == null) {
+                    logger.warn("国任上传影像失败,图片DTO为空");
+                    continue;
+                }
+
+                try {  // 根据imageId查询文件信息
+                    SysUploadFiles uploadFile = platformClient.getUploadFile(imageDTO.getImageId());
+                    if (uploadFile == null) {
+                        logger.error("国任上传影像失败,未找到文件信息,imageId:{}", imageDTO.getImageId());
+                        continue;
+                    }
+
+                    // 获取文件名
+                    fileName = uploadFile.getFileName();
+
+                    // 获取文件流
+                    String imgUrl = minioUtils.getPresignedObjectUrl(uploadFile.getBucketName(), fileName);
+                    logger.info("国任影像上传,获取文件预签名URL,imgUrl:{}", imgUrl);
+                    InputStream inputStream = minioUtils.getObject(uploadFile.getBucketName(), fileName);
+                    if (inputStream == null) {
+                        logger.error("国任上传影像失败,获取文件预签名URL失败,imageId:{}", imageDTO.getImageId());
+                        continue;
+                    }
+
+                    // 下载文件内容为byte[]
+                    imageBytes = IOUtils.toByteArray(inputStream);
+                    if (imageBytes == null || imageBytes.length == 0) {
+                        logger.error("国任上传影像失败,文件内容为空,imageId:{}", imageDTO.getImageId());
+                        continue;
+                    }
+
+                    logger.info("国任下载影像成功,imageId:{},fileName:{}", imageDTO.getImageId(), fileName);
+
+
+                    // 生成临时文件
+                    String fileSuffix = getFileSuffix(fileName);
+                    File tempFile = File.createTempFile("upload_temp_", fileSuffix);
                     tempFile.deleteOnExit();
 
                     // 将字节数组写入临时文件
                     try (FileOutputStream fos = new FileOutputStream(tempFile)) {
-                        fos.write(imageDTO.getImageByte());
+                        fos.write(imageBytes);
                         fos.flush();
                     }
 
-                    Part[] parts = {file1, new StringPart("businessNo", formMap.get("businessNo").toString()),
-                            new StringPart("operatorCode",
-                                    formMap.get("operatorCode").toString()), new StringPart("comCode",
-                            formMap.get("comCode").toString()),
-                            new StringPart("fileGroup", formMap.get("fileGroup").toString())};
-
+                    // 构造请求参数
+                    FilePart filePart = new FilePart("file", tempFile);
+                    Part[] parts = {
+                            filePart,
+                            new StringPart("businessNo", businessNo),
+                            new StringPart("operatorCode", operatorCode),
+                            new StringPart("comCode", comCode),
+                            new StringPart("fileGroup", fileGroup)
+                    };
+
+                    // 发送请求
                     String result = HttpUtil.sendPostFromFile(parts, properties.getUploadUrl());
+
                     if (StringUtils.isEmpty(result)) {
+                        logger.error("国任上传影像失败,接口返回为空,imageId:{}", imageDTO.getImageId());
                         throw new SystemException("国任,影像上传失败");
                     }
 
                     JSONObject jsonObject = JSON.parseObject(result);
+                    Integer resultCode = StringUtils.toInt(jsonObject.get("resultCode"));
 
-                    if (StringUtils.toInt(jsonObject.get("resultCode")) != 0) {
-                        throw new SystemException("国任,影像上传失败");
+                    if (resultCode == null || resultCode != 0) {
+                        String resultMsg = jsonObject.getString("resultMsg");
+                        logger.error("国任上传影像失败,resultCode:{},resultMsg:{},imageId:{}", resultCode, resultMsg, imageDTO.getImageId());
+                        throw new SystemException("国任,影像上传失败:" + resultMsg);
                     }
+
                     imageIds.add(imageDTO.getImageId());
+                    logger.info("国任上传影像成功,imageId:{},businessNo:{}", imageDTO.getImageId(), businessNo);
+
                 } catch (Exception e) {
-                    logger.error("国任上传影像异常:{}", e.getMessage());
-                    // 上传的影像存入redis
-                    insImagesUploadCacheComponent.setUploadImageCache(insuranceUploadImageVo.getOrder().getInsuranceCompanyCode(), map);
-                    throw new SystemException("国任,影像上传失败,类型:" + insuranceImageVo.getImageType());
+                    logger.error("国任上传影像异常:{},imageId:{}", e.getMessage(), imageDTO.getImageId(), e);
+                    insImagesUploadCacheComponent.setUploadImageCache(insuranceUploadImageVo.getOrder().getInsuranceCompanyCode(), resultMap);
+                    throw new SystemException("国任,影像上传失败,类型:" + imageVo.getImageType());
                 }
             }
-            map.put(insuranceImageVo.getImageCode(), imageIds);
-        });
 
-        insImagesUploadCacheComponent.setUploadImageCache(insuranceUploadImageVo.getOrder().getInsuranceCompanyCode(), map);
+            if (CollUtil.isNotEmpty(imageIds)) {
+                resultMap.put(imageVo.getImageCode(), imageIds);
+            }
+        }
+
+        // 将上传成功的影像存入缓存
+        insImagesUploadCacheComponent.setUploadImageCache(insuranceUploadImageVo.getOrder().getInsuranceCompanyCode(), resultMap);
+    }
+
+    /**
+     * 根据影像类型获取fileGroup
+     * DZ—单证影像, YC-验车影像
+     */
+    private String getFileGroup(InsuranceImageVo imageVo) {
+        String imageType = imageVo.getImageType();
+        if (StringUtils.isEmpty(imageType)) {
+            return "DZ";
+        }
+        // 验车相关的影像类型使用YC
+        if (imageType.contains("验车") || imageType.contains("YC")) {
+            return "YC";
+        }
+        // 默认使用单证影像
+        return "DZ";
     }
 
     /**
      * 工具方法:从文件名中提取后缀(如 "test.txt" → "txt")
      */
-    private static String getFileSuffix(String fileName) {
-        if (fileName.contains(".")) {
-            return fileName.substring(fileName.lastIndexOf("."));
+    private String getFileSuffix(String fileName) {
+        if (StringUtils.isEmpty(fileName)) {
+            return ".bin"; // 默认后缀
+        }
+        int lastIndexOf = fileName.lastIndexOf(".");
+        if (lastIndexOf == -1) {
+            return ".bin";
         }
-        return "bin"; // 默认后缀(二进制文件)
+        return fileName.substring(lastIndexOf);
     }
 
 

+ 3 - 1
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/InsOrdersController.java

@@ -3,12 +3,14 @@ package com.jzg.quotation.summary.controller;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.jzg.commons.aop.OperatorTrajectory;
 import com.jzg.commons.core.base.BaseController;
 import com.jzg.commons.core.page.HttpResult;
 import com.jzg.commons.entity.dto.InsOrdersParam;
 import com.jzg.commons.entity.dto.InsOrdersParamVO;
 import com.jzg.commons.entity.orders.vo.HistoryQuoteQueryVo;
+import com.jzg.commons.entity.orders.vo.HistoryQuoteResultVo;
 import com.jzg.commons.entity.po.InsFeeOrders;
 import com.jzg.commons.entity.quote.vo.KindInfoVo;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
@@ -138,7 +140,7 @@ public class InsOrdersController extends BaseController {
 
     @Operation(summary = "获取历史报价列表")
     @PostMapping("/getHistoryQuoteList")
-    public HttpResult getHistoryQuoteList(@RequestBody HistoryQuoteQueryVo historyQuoteQueryVo){
+    public HttpResult<Page<HistoryQuoteResultVo>> getHistoryQuoteList(@RequestBody HistoryQuoteQueryVo historyQuoteQueryVo){
         return HttpResult.ok(insOrdersService.getHistoryQuoteList(historyQuoteQueryVo));
     }
 

+ 2 - 4
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/controller/UnifyOrderManager.java

@@ -171,7 +171,7 @@ public class UnifyOrderManager {
      * @param insuranceUploadImageVo
      * @return
      */
-    @PostMapping("imageSave")
+    @PostMapping("/imageSave")
     @Operation(summary = "本地影像存储")
     public HttpResult imageSave(@RequestBody InsuranceUploadImageVo insuranceUploadImageVo) {
 
@@ -213,11 +213,9 @@ public class UnifyOrderManager {
         }
         quoteVo.getOrder().setAgreementId(ptlAgreement.getId());
         quoteVo.getOrder().setApiType(ptlAgreement.getApiType());
-        // 设置人员区划
+        // 设置人员区划. (将投保人的地址信息,按照行政区域进行划分)
         insOrdersService.setUserAreaCode(quoteVo);
         log.debug("设置人员区域后信息是:quoteVo=[{}]", JSONUtil.toJsonStr(quoteVo));
-
-
         //获取保司实体
         QuotationBaseService quoteService = companyFactory.getQuoteService(esmInsCompanyHttpResult.getData()
                 .getCompanyCode(), quoteVo.getOrder()

+ 1 - 1
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/InsOrdersService.java

@@ -141,7 +141,7 @@ public interface InsOrdersService extends IService<InsOrders> {
     /**
      * 获取历史报价列表
      *
-     * @return
+     * @return Page<HistoryQuoteResultVo>
      */
     Page<HistoryQuoteResultVo> getHistoryQuoteList(HistoryQuoteQueryVo historyQuoteQueryVo);
 

+ 9 - 1
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/InsOrdersServiceImpl.java

@@ -928,11 +928,19 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
     }
 
 
+    /**
+     * 生成一个主订单和多个子订单
+     *
+     * @return 返回的是主订单的订单号
+     * @author lipf
+     * @date 2026/4/18 15:29
+     */
     @Override
     @Transactional
     public String generateOrders(QuoteVo quoteVo, String companyName) {
         // 生成订单的条件
         // 1个保险公司只有一个主订单   不区分险种
+        // 唯一性的判定标准:保险公司编号+ 车牌号 + 车架号
         InsOrders mainOrders = this.getMainOrders(
                 quoteVo.getOrder().getInsuranceCompanyCode(),
                 quoteVo.getCarInfoVo().getLicenseNo(),
@@ -1000,7 +1008,7 @@ public class InsOrdersServiceImpl extends ServiceImpl<InsOrdersMapper, InsOrders
         insOrdersMapper.insert(insOrders);
 
         // 保存订单车辆信息
-        InsOrdersCarInfo carInfo = ordersCarInfoService.createCarInfo(insOrders, quoteVo.getCarInfoVo());
+        ordersCarInfoService.createCarInfo(insOrders, quoteVo.getCarInfoVo());
 
         // 保存订单用户信息
         List<InsOrdersCarUserInfo> insOrdersCarUserInfoList = new ArrayList<>();

+ 6 - 1
tenant/insurance/quotation-summary/src/main/java/com/jzg/quotation/summary/service/impl/QuoteRuleMappingServiceImpl.java

@@ -5,6 +5,8 @@ import com.jzg.commons.exception.SystemException;
 import com.jzg.quotation.summary.entity.po.QuoteRuleMapping;
 import com.jzg.quotation.summary.mapper.QuoteRuleMappingMapper;
 import com.jzg.quotation.summary.service.QuoteRuleMappingService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
@@ -14,12 +16,14 @@ import java.util.stream.Collectors;
 /**
  * @author Administrator
  * @description 针对表【quote_kind_mapping(报价险种映射)】的数据库操作Service实现
- * @createDate 2025-02-20 11:00:39
+ * @date 2025-02-20 11:00:39
  */
 @Service
 public class QuoteRuleMappingServiceImpl extends ServiceImpl<QuoteRuleMappingMapper, QuoteRuleMapping>
         implements QuoteRuleMappingService {
 
+    private static final Logger log = LoggerFactory.getLogger(QuoteRuleMappingServiceImpl.class);
+
     @Override
     public Map<String, List<QuoteRuleMapping>> getByInsuranceCompanyCode(String insuranceCompanyCode) {
         List<QuoteRuleMapping> list = lambdaQuery()
@@ -27,6 +31,7 @@ public class QuoteRuleMappingServiceImpl extends ServiceImpl<QuoteRuleMappingMap
                 .list();
 
         if (list.isEmpty()) {
+            log.info("序号为[{}]的保险公司没有配置险种映射",insuranceCompanyCode);
             throw new SystemException("该保险公司未配置险种映射");
         }
 

+ 2 - 7
tenant/insurance/quotation-summary/src/main/resources/application-dev.yaml

@@ -6,10 +6,10 @@ spring:
       password: nacos
       config:
         file-extension: yaml
-        namespace: 9fceaca4-c1d2-4bb8-aac9-f64d4b7de73c
+        namespace: 353f8f05-4d2c-4a17-b64d-b678408f5759
         group: DEFAULT_GROUP
       discovery:
-        namespace: 9fceaca4-c1d2-4bb8-aac9-f64d4b7de73c
+        namespace: 353f8f05-4d2c-4a17-b64d-b678408f5759
   config:
     import:
       - nacos:mysql
@@ -18,11 +18,6 @@ spring:
       - nacos:mongodb
       - nacos:identify
       - nacos:crawler-config
-  redis:
-    host: 192.168.5.250
-    port: 6379
-    password: 123456  # 如果没有密码,可删除此行
-    database: 0
 #百度图片识别API
 baidu:
   clientId: xG9M8tSjNvYPwSTNavM0ELlD

+ 11 - 11
tenant/insurance/quotation-summary/src/main/resources/application-prod.yaml

@@ -198,24 +198,24 @@ zhongmei:
 
 zijin:
   api:
-#        appKey: SXTQ-C-SX
-#        appSecret: vAI9sW4bM1m5Y074AUT72wvxKu55SbGY
-#        proposalCityCode: 320100
-#        proposalAreaCode: 320000
+    appKey: SXTQ-C-SX
+    appSecret: kARQdHR9OisOrbHpts6Raj7YzQzfvZoO
+    proposalCityCode: 410718
+    proposalAreaCode: 140000
 #     为接入方提供获取token服务
-    accessTokenUrl: https://test-open.zking.com/api/v1/public/token/getAccessToken
+    accessTokenUrl: https://open.zking.com/api/v1/public/token/getAccessToken
     # 车险业务
-    url: http://test-open.zking.com/api/v1/insurance/autoMobile/carInsurance/
+    url: http://open.zking.com/api/v1/insurance/autoMobile/carInsurance/
     # 支付
-    payUrl: http://test-open.zking.com/api/v1/public/payment/cashier/zbfAggregatePay
+    payUrl: http://open.zking.com/api/v1/public/payment/cashier/zbfAggregatePay
     # 新支付
-    newPayUrl: http://test-open.zking.com/api/v1/open/open-aggregate/auth/newPay
+    newPayUrl: http://open.zking.com/api/v1/open/open-aggregate/auth/newPay
     # 订单详情查询服务
-    orderUrl: http://test-open.zking.com/api/v1/insurance/public/getOrderDetail
+    orderUrl: http://open.zking.com/api/v1/business-order/insurance-order/auth/order/queryOrderDetailById
     # 订单状态查询
-    orderDetailUrl: http://test-open.zking.com/api/v1/insurance/autoMobile/geelyCarInsurance/queryOrderDetail
+    orderDetailUrl: http://open.zking.com/api/v1/insurance/autoMobile/geelyCarInsurance/queryOrderDetail
     # 下载保单地址
-    downLoadDocument: http://test-open.zking.com/temp/api/v1/insurance/nonAutoMobile/queryPolicy/downLoadDocument
+    downLoadDocument: http://open.zking.com/temp/api/v1/insurance/nonAutoMobile/queryPolicy/downLoadDocument
     # 对接三方渠道验车链接接口
     sendCheckCarLink: http://open.zking.com/api/v1/open/open-aggregate/auth/wanJiaYun/sendCheckCarLink
 

+ 17 - 0
tenant/insurance/quotation-summary/src/test/resources/application-local.yaml

@@ -0,0 +1,17 @@
+spring:
+  cloud:
+    nacos:
+      config:
+        enabled: false
+      discovery:
+        enabled: false
+  config:
+    import: optional:nacos:  # 使用 optional 禁用 Nacos 配置导入检查
+
+# 禁用 Nacos 配置检查
+spring.cloud.nacos.config.import-check.enabled: false
+
+# 本地测试数据库配置(可根据实际情况修改)
+#spring.datasource.url: jdbc:mysql://localhost:3306/test_db
+#spring.datasource.username: root
+#spring.datasource.password: root

+ 3 - 1
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/build/ZiJinAPIQuoteResultsVoBuild.java

@@ -30,9 +30,11 @@ public final class ZiJinAPIQuoteResultsVoBuild {
         throw new IllegalStateException("Utility class");
     }
 
-    public static QuoteResultsVo buildQuoteResultsVo(String orderNo, QuoteVo quoteVo, CalculatePremiumResponse calculatePremiumResponse) {
+    public static QuoteResultsVo buildQuoteResultsVo(String orderNo, QuoteVo quoteVo, CalculatePremiumResponse calculatePremiumResponse, String companyOrderNo) {
         QuoteResultsVo quoteResultsVo = new QuoteResultsVo();
         quoteResultsVo.setOrdersNo(orderNo);
+        // 赋值从保险公司获取的订单号
+        quoteResultsVo.setCompanyOrderNo(companyOrderNo);
 
         quoteResultsVo.setQuoteStatusEnum(InsOrderStatusEnum.WAIT_AUDIT);
         quoteResultsVo.setQuoteStatus(InsOrderStatusEnum.WAIT_AUDIT.getCode());

+ 32 - 0
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/constant/enums/AccidentHealthInsuranceProductsEnum.java

@@ -0,0 +1,32 @@
+package com.jzg.quotation.zijin.api.constant.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @description: 关联单标识
+ * @author: wenks
+ * @date: 2023/9/20 9:19
+ **/
+
+@Getter
+@AllArgsConstructor
+public enum AccidentHealthInsuranceProductsEnum {
+    /**
+     * 紫金驾乘人意外伤害保险
+     */
+    ZIJIN_CHENGJIA_REN_ACCIDENT("0737", "紫金驾乘人意外伤害保险"),
+
+    /**
+     * 紫金驾驶人意外伤害保险
+     */
+    ZIJIN_JIASHI_REN_ACCIDENT("0733", "紫金驾驶人意外伤害保险"),
+
+    /**
+     * 紫金驾乘人员人生意外保险
+     */
+    ZIJIN_CHENGJIA_PERSONNEL_ACCIDENT("0767", "紫金驾乘人员人生意外保险");
+
+    private final String code;
+    private final String name;
+}

+ 108 - 0
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/constant/enums/FileTypeEnum.java

@@ -0,0 +1,108 @@
+package com.jzg.quotation.zijin.api.constant.enums;
+
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+
+@AllArgsConstructor
+@Getter
+public enum FileTypeEnum {
+
+    /**
+     * 验车照片
+     */
+    YAN_CHE_ZHAO_PIAN("1", "验车照片"),
+    /**
+     * 其他车辆证件
+     */
+    QI_TA_CHE_LIANG_ZHENG_JIAN("2", "其他车辆证件"),
+    /**
+     * 其他客户证件
+     */
+    QI_TA_KE_HU_ZHENG_JIAN("3", "其他客户证件"),
+    /**
+     * 车辆购置证明
+     */
+    CHE_LIANG_GOU_ZHI_ZHENG_MING("4", "车辆购置证明"),
+    /**
+     * 过户证明
+     */
+    GUO_HU_ZHENG_MING("5", "过户证明"),
+    /**
+     * 退保证明
+     */
+    TUI_BAO_ZHENG_MING("6", "退保证明"),
+    /**
+     * 单证
+     */
+    DAN_ZHENG("7", "单证"),
+    /**
+     * 申请书
+     */
+    SHEN_QING_SHU("8", "申请书"),
+    /**
+     * 其他
+     */
+    QI_TA("9", "其他"),
+    /**
+     * OA审批
+     */
+    OA_SHEN_PI("16", "OA审批"),
+    /**
+     * 实名缴费证明
+     */
+    SHI_MING_JIAO_FEI_ZHENG_MING("19", "实名缴费证明"),
+    /**
+     * 银行卡
+     */
+    YIN_HANG_KA("51", "银行卡"),
+    /**
+     * 驾驶证
+     */
+    JIA_SHI_ZHENG("52", "驾驶证"),
+    /**
+     * 身份证
+     */
+    SHEN_FEN_ZHENG("53", "身份证"),
+    /**
+     * 增值税发票
+     */
+    ZENG_ZHI_SHUI_FA_PIAO("54", "增值税发票"),
+    /**
+     * 车辆合格证
+     */
+    CHE_LIANG_HE_GE_ZHENG("55", "车辆合格证"),
+    /**
+     * 行驶证
+     */
+    XING_SHI_ZHENG("56", "行驶证"),
+    /**
+     * 充电桩影像资料
+     */
+    CHONG_DIAN_ZHUANG_YING_XIANG_ZI_LIAO("41", "充电桩影像资料"),
+    /**
+     * 是否为新能源证明材料
+     */
+    SHI_FOU_WEI_XIN_NENG_YUAN_ZHENG_MING_CAI_LIAO("42", "是否为新能源证明材料"),
+    /**
+     * 授权委托书
+     */
+    SHOU_QUAN_WEI_TUO_SHU("30", "授权委托书"),
+    /**
+     * 完税凭证
+     */
+    WAN_SHUI_PING_ZHENG("31", "完税凭证"),
+    /**
+     * 电子投保单
+     */
+    DIAN_ZI_TOU_BAO_DAN("10", "电子投保单"),
+    /**
+     * 社会统一信用代码证
+     */
+    SHE_HUI_TONG_YI_XIN_YONG_DAI_MA_ZHENG("57", "社会统一信用代码证");
+
+    private final String code;
+    private final String name;
+
+}

+ 2 - 2
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/entity/request/SubmitVerifyRequest.java

@@ -28,7 +28,7 @@ public class SubmitVerifyRequest implements Serializable {
     @JsonProperty("engageList")
     private List<EngageListDTO> engageList;
 
-    @JsonProperty("underWritingRequestVehicleDTO")
+    @JsonProperty("underWritingRequestVehicleDto")
     private UnderWritingRequestVehicleDTO underWritingRequestVehicleDto;
 
     @JsonProperty("orderId")
@@ -45,7 +45,7 @@ public class SubmitVerifyRequest implements Serializable {
                 .map(EngageListDTO::new)
                 .collect(Collectors.toList());
         String code;
-        if (ziJinApiOrder.getProductsCode().equals(ProductsType.PT_034002.getCode())) {
+        if (ProductsType.PT_034002.getCode().equals(ziJinApiOrder.getProductsCode())) {
             code = CarCheckReasonEnum.CCR_3.getCode();
         } else {
             code = CarCheckReasonEnum.CCR_2.getCode();

+ 112 - 8
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/service/Impl/ZiJinApiRequestImpl.java

@@ -1,23 +1,31 @@
 package com.jzg.quotation.zijin.api.service.Impl;
 
 import com.jzg.commons.constants.dict.InsOrderStatusEnum;
+import com.jzg.commons.constants.quote.enums.base.InsuranceImageEnum;
+import com.jzg.commons.core.page.HttpResult;
 import com.jzg.commons.entity.orders.po.InsOrdersCosts;
-import com.jzg.commons.entity.po.InsCompanyClause;
+import com.jzg.commons.entity.po.JyxConfig;
+import com.jzg.commons.entity.po.SysUploadFiles;
+import com.jzg.commons.entity.quote.vo.AccidentalDrivingVo;
 import com.jzg.commons.entity.quote.vo.AttributionInformationVo;
 import com.jzg.commons.entity.quote.vo.CarInfoVo;
 import com.jzg.commons.entity.quote.vo.QuoteVo;
 import com.jzg.commons.entity.quote.vo.aggregated.*;
+import com.jzg.commons.entity.quote.vo.base.OrderBase;
+import com.jzg.commons.entity.quote.vo.image.InsuranceImageVo;
+import com.jzg.commons.entity.quote.vo.underwriting.SpecialAppointmentsVo;
+import com.jzg.commons.entity.vo.JyxConfigVo;
 import com.jzg.commons.exception.SystemException;
+import com.jzg.commons.util.MinioUtils;
 import com.jzg.quotation.commons.annotation.QuoteApiService;
 import com.jzg.quotation.commons.client.PlatformClient;
 import com.jzg.quotation.commons.constant.InsuranceCode;
-import com.jzg.commons.entity.quote.vo.base.OrderBase;
-import com.jzg.commons.entity.quote.vo.image.InsuranceImageVo;
-import com.jzg.commons.entity.quote.vo.underwriting.SpecialAppointmentsVo;
 import com.jzg.quotation.commons.filter.CarModelsFilterUtils;
 import com.jzg.quotation.commons.standard.conversion.ConfigureParametersConversion;
 import com.jzg.quotation.zijin.api.build.ZiJinAPIQuoteResultsVoBuild;
 import com.jzg.quotation.zijin.api.component.ZiJinApiRequestComponent;
+import com.jzg.quotation.zijin.api.constant.enums.AccidentHealthInsuranceProductsEnum;
+import com.jzg.quotation.zijin.api.constant.enums.FileTypeEnum;
 import com.jzg.quotation.zijin.api.constant.enums.RiskCodeEnum;
 import com.jzg.quotation.zijin.api.entity.ZiJinApiConfigureParameters;
 import com.jzg.quotation.zijin.api.entity.constants.enums.BusType;
@@ -27,13 +35,15 @@ import com.jzg.quotation.zijin.api.entity.request.*;
 import com.jzg.quotation.zijin.api.entity.response.*;
 import com.jzg.quotation.zijin.api.service.ZiJinApiRequest;
 import com.jzg.quotation.zijin.api.service.ZiJinOrderService;
-import com.jzg.quotation.zijin.crawler.service.ZiJinCrawlerOrderService;
 import lombok.RequiredArgsConstructor;
+import org.apache.commons.io.IOUtils;
 import org.jetbrains.annotations.NotNull;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpHeaders;
 
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Base64;
 import java.util.List;
 import java.util.Objects;
 
@@ -52,6 +62,8 @@ public class ZiJinApiRequestImpl implements ZiJinApiRequest {
 
     private final PlatformClient platformClient;
 
+    private final MinioUtils minioUtils;
+
 
     // 重复投保次数
     private static final int REPEAT_NUMBER = 3;
@@ -75,11 +87,13 @@ public class ZiJinApiRequestImpl implements ZiJinApiRequest {
         // 计算车辆价格
         QueryActualValueRequest queryActualValueRequest = new QueryActualValueRequest(carInfoVo, vehicleModelInfosDTO.getPurchasePrice(), quoteVo);
         QueryActualValueResponse queryActualValueResponse = ziJinApiRequestComponent.queryActualValue(queryActualValueRequest, httpHeaders);
+        // 补全驾意险的参数
+        setAccidentalDriving(quoteVo);
         // 报价
         CalculatePremiumRequest calculatePremiumRequest = new CalculatePremiumRequest(quoteVo, vehicleModelInfosDTO, queryActualValueResponse.getActualValue(), parameters, modelQueryResponse);
         CalculatePremiumResponse calculatePremiumResponse = ziJinApiRequestComponent.calculatePremium(calculatePremiumRequest, httpHeaders,modelQueryRequest,queryActualValueRequest,REPEAT_NUMBER,RETRY_NUMBER);
         ziJinOrderService.saveOrderInfo(quoteVo, modelQueryResponse);
-        return ZiJinAPIQuoteResultsVoBuild.buildQuoteResultsVo(order.getOrdersNo(), quoteVo, calculatePremiumResponse);
+        return ZiJinAPIQuoteResultsVoBuild.buildQuoteResultsVo(order.getOrdersNo(), quoteVo, calculatePremiumResponse, modelQueryResponse.getOrderNo());
     }
 
     @Override
@@ -106,7 +120,7 @@ public class ZiJinApiRequestImpl implements ZiJinApiRequest {
             underwritingResultsVo.setUnderwritingStatus(InsOrderStatusEnum.PAY_PENDING);
 
             String multiply = insOrdersCosts.getSumPremium().toPlainString();
-            NewPayRequest newPayRequest = new NewPayRequest(multiply, orderBase.getOrdersNo(), parameters);
+            NewPayRequest newPayRequest = new NewPayRequest(multiply, ziJinApiOrder.getOrderNo(), parameters);
             NewPayRequestResponse newPayRequestResponse = ziJinApiRequestComponent.newPay(newPayRequest, httpHeaders);
             underwritingResultsVo.setPaymentLink(newPayRequestResponse.getTwoDimentionImageUrl());
         } catch (SystemException systemException) {
@@ -219,6 +233,27 @@ public class ZiJinApiRequestImpl implements ZiJinApiRequest {
             imageVo
                     .getImageBase64List()
                     .forEach(imageBase64 -> {
+                        // 只有imageId,根据imageId获取文件流,然后获取base64编码后的文件
+                        String imageId = imageBase64.getImageId();
+                        // 1. 根据 imageId 获取文件信息
+                        SysUploadFiles sysUploadFiles = platformClient.getUploadFile(imageId);
+                        String fileName = sysUploadFiles.getFileName();
+                        // 2. 从 MinIO 获取文件输入流
+                        InputStream inputStream = minioUtils.getObject("jzg", fileName);
+                        // 3. 输入流转 byte[] → 再转 Base64
+                        byte[] fileBytes = null;
+                        try {
+                            fileBytes = IOUtils.toByteArray(inputStream);
+                        } catch (IOException e) {
+                            throw new RuntimeException(e);
+                        }
+                        String fileBase64 = Base64.getEncoder().encodeToString(fileBytes);
+                        // 组装参数
+                        imageBase64.setImageName(fileName);
+                        imageBase64.setImageBase64Str(fileBase64);
+                        // 文件类型映射
+                        fileTypeMapping(imageVo);
+
                         UploadFileRequest uploadImageRequest = new UploadFileRequest(imageBase64, imageVo.getImageCode(), ziJinApiOrder.getOrderNo());
                         // 文件上传
                         UploadFileResponse uploadFileResponse = ziJinApiRequestComponent.uploadFile(uploadImageRequest, httpHeaders);
@@ -320,4 +355,73 @@ public class ZiJinApiRequestImpl implements ZiJinApiRequest {
         }
         return orderStatusResultVo;
     }
+
+    /**
+     * 文件类型映射,从系统定义的值转换成紫金对应的文件类型
+     * @param imageVo
+     */
+    private static void fileTypeMapping(InsuranceImageVo imageVo) {
+        if (InsuranceImageEnum.C01.getCode().equals(imageVo.getImageCode()) || InsuranceImageEnum.D01.getCode().equals(imageVo.getImageCode())) {
+            // 行驶证正面/反面 → 行驶证(56)
+            imageVo.setImageCode(FileTypeEnum.XING_SHI_ZHENG.getCode());
+        } else if (InsuranceImageEnum.C02.getCode().equals(imageVo.getImageCode()) || InsuranceImageEnum.D02.getCode().equals(imageVo.getImageCode())
+                || InsuranceImageEnum.C03.getCode().equals(imageVo.getImageCode()) || InsuranceImageEnum.D03.getCode().equals(imageVo.getImageCode())
+                || InsuranceImageEnum.C04.getCode().equals(imageVo.getImageCode()) || InsuranceImageEnum.D04.getCode().equals(imageVo.getImageCode())) {
+            // 车主/投保人/被保人 身份证正反面 → 身份证(53)
+            imageVo.setImageCode(FileTypeEnum.SHEN_FEN_ZHENG.getCode());
+        } else if (InsuranceImageEnum.Y02.getCode().equals(imageVo.getImageCode()) || InsuranceImageEnum.Y03.getCode().equals(imageVo.getImageCode())
+                || InsuranceImageEnum.Y04.getCode().equals(imageVo.getImageCode())) {
+            // 车主/投保人/被保人 营业执照 → 社会统一信用代码证(57)
+            imageVo.setImageCode(FileTypeEnum.SHE_HUI_TONG_YI_XIN_YONG_DAI_MA_ZHENG.getCode());
+        } else if (InsuranceImageEnum.YHK_01.getCode().equals(imageVo.getImageCode())) {
+            // 银行卡正面 → 银行卡(51)
+            imageVo.setImageCode(FileTypeEnum.YIN_HANG_KA.getCode());
+        } else if (InsuranceImageEnum.XC00.getCode().equals(imageVo.getImageCode())) {
+            // 新车合格证 → 车辆合格证(55)
+            imageVo.setImageCode(FileTypeEnum.CHE_LIANG_HE_GE_ZHENG.getCode());
+        } else if (InsuranceImageEnum.GC00.getCode().equals(imageVo.getImageCode())) {
+            // 购车发票 → 增值税发票(54)
+            imageVo.setImageCode(FileTypeEnum.ZENG_ZHI_SHUI_FA_PIAO.getCode());
+        } else if (InsuranceImageEnum.SQ00.getCode().equals(imageVo.getImageCode())) {
+            // 授权书 → 授权委托书(30)
+            imageVo.setImageCode(FileTypeEnum.SHOU_QUAN_WEI_TUO_SHU.getCode());
+        } else if (InsuranceImageEnum.C0500.getCode().equals(imageVo.getImageCode()) || InsuranceImageEnum.C0501.getCode().equals(imageVo.getImageCode())
+                || InsuranceImageEnum.C0502.getCode().equals(imageVo.getImageCode()) || InsuranceImageEnum.C0503.getCode().equals(imageVo.getImageCode())
+                || InsuranceImageEnum.C0504.getCode().equals(imageVo.getImageCode()) || InsuranceImageEnum.C0505.getCode().equals(imageVo.getImageCode())
+                || InsuranceImageEnum.C0506.getCode().equals(imageVo.getImageCode()) || InsuranceImageEnum.C0507.getCode().equals(imageVo.getImageCode())
+                || InsuranceImageEnum.C0508.getCode().equals(imageVo.getImageCode()) || InsuranceImageEnum.C0509.getCode().equals(imageVo.getImageCode())
+                || InsuranceImageEnum.C0510.getCode().equals(imageVo.getImageCode())) {
+            // 所有验车照 → 验车照片(1)
+            imageVo.setImageCode(FileTypeEnum.YAN_CHE_ZHAO_PIAN.getCode());
+        } else if (InsuranceImageEnum.TAR05.getCode().equals(imageVo.getImageCode())) {
+            // 机动车辆登记证书 → 其他车辆证件(2)
+            imageVo.setImageCode(FileTypeEnum.QI_TA_CHE_LIANG_ZHENG_JIAN.getCode());
+        } else if (InsuranceImageEnum.INSURANCE_POLICY.getCode().equals(imageVo.getImageCode())) {
+            // 上年商业险保单 → 单证(7)
+            imageVo.setImageCode(FileTypeEnum.DAN_ZHENG.getCode());
+        } else if (InsuranceImageEnum.GX00.getCode().equals(imageVo.getImageCode())) {
+            // 关系证明 → 其他(9)
+            imageVo.setImageCode(FileTypeEnum.QI_TA.getCode());
+        } else {
+            // 未匹配到的 → 其他(9)
+            imageVo.setImageCode(FileTypeEnum.QI_TA.getCode());
+        }
+    }
+
+    /**
+     * 补全驾意险的参数
+     * @param quoteVo
+     */
+    private void setAccidentalDriving(QuoteVo quoteVo) {
+        // 默认选中"0767"->"紫金驾乘人员人生意外保险"
+        for (AccidentalDrivingVo accidentalDriving : quoteVo.getAccidentalDrivings()) {
+            accidentalDriving.setRiskCode(AccidentHealthInsuranceProductsEnum.ZIJIN_CHENGJIA_PERSONNEL_ACCIDENT.getCode());
+            accidentalDriving.setRiskName(AccidentHealthInsuranceProductsEnum.ZIJIN_CHENGJIA_PERSONNEL_ACCIDENT.getName());
+            // 查询jyx_config表,拿到总保额和总保费
+            HttpResult<JyxConfigVo> jyxConfigVoHttpResult = platformClient.jyxConfigGetById(accidentalDriving.getId());
+            JyxConfigVo jyxConfigVo = jyxConfigVoHttpResult.getData();
+            accidentalDriving.setSumAmount(jyxConfigVo.getCoverage());
+            accidentalDriving.setSumPremium(jyxConfigVo.getPremium());
+        }
+    }
 }

+ 1 - 1
tenant/insurance/quotation-zijin/src/main/java/com/jzg/quotation/zijin/api/service/Impl/ZiJinOrderServiceImpl.java

@@ -21,7 +21,7 @@ public class ZiJinOrderServiceImpl implements ZiJinOrderService {
         ziJinApiOrder.setId(quoteVo.getOrder().getOrdersNo());
         ziJinApiOrder.setOrderNo(modelQueryResponse.getOrderNo());
         ziJinApiOrder.setOrderId(modelQueryResponse.getOrderId());
-        ziJinApiOrder.setProductsCode(quoteVo.getProductId());
+        ziJinApiOrder.setProductsCode(quoteVo.getOrder().getProductId());
         ziJinApiOrder.setInsuredIdentify(quoteVo
                 .getInsuredPersonInfo()
                 .getIdentifyNumber());

+ 25 - 0
tenant/organization/src/main/java/com/jzg/organization/client/LotteryActivityClient.java

@@ -0,0 +1,25 @@
+package com.jzg.organization.client;
+
+import com.jzg.commons.core.page.HttpResult;
+import com.jzg.commons.entity.vo.LotteryActivityVO;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+
+import java.util.List;
+
+/**
+ * 抽奖活动客户端
+ */
+@FeignClient(name = "lottery-activity", url = "http://t5936d89.natappfree.cc/jeecg-boot/")
+public interface LotteryActivityClient {
+
+    /**
+     * 查询抽奖活动规则
+     *
+     * @param scene 场景编码
+     * @return 活动列表
+     */
+    @GetMapping("/lotteryActivity/queryActivityRules")
+    HttpResult<List<LotteryActivityVO>> queryActivityRules(@RequestParam("scene") Integer scene);
+}

+ 6 - 0
tenant/organization/src/main/java/com/jzg/organization/controller/SchemeController.java

@@ -20,6 +20,12 @@ public class SchemeController {
     @Autowired
     private PtlSchemeService ptlSchemeService;
 
+    /**
+     * 方案新增和修改接口
+     *
+     * @author lipf
+     * @date 2026/4/21 16:26
+     */
     //region 基础方案配置
     @Operation(summary = "保存方案")
     @PostMapping("/saveScheme")

+ 86 - 0
tenant/organization/src/main/java/com/jzg/organization/controller/SignInController.java

@@ -0,0 +1,86 @@
+package com.jzg.organization.controller;
+
+import com.jzg.commons.core.base.BaseController;
+import com.jzg.commons.core.page.HttpResult;
+import com.jzg.organization.entity.dto.SignInDTO;
+import com.jzg.organization.entity.vo.SignInRecordVO;
+import com.jzg.organization.entity.vo.SignInStatisticsVO;
+import com.jzg.organization.entity.vo.SignInVO;
+import com.jzg.organization.service.SignInService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+/**
+ * 签到控制器
+ */
+@Slf4j
+@RestController
+@RequestMapping("/api/signIn")
+@Tag(name = "签到管理", description = "用户签到相关接口")
+public class SignInController extends BaseController {
+
+    @Autowired
+    private SignInService signInService;
+
+    /**
+     * 用户签到
+     */
+    @PostMapping("/doSignIn")
+    @Operation(summary = "用户签到", description = "用户每日签到,支持多租户")
+    public HttpResult<SignInVO> signIn(@RequestBody SignInDTO dto) {
+        // 如果前端未传租户ID和用户ID,从当前登录信息获取
+        if (dto.getTenantId() == null) {
+            dto.setTenantId(getSystemCode());
+        }
+        if (dto.getUserId() == null) {
+            dto.setUserId(getUserId());
+        }
+        return signInService.signIn(dto);
+    }
+
+    /**
+     * 查询签到统计信息
+     */
+    @GetMapping("/getStatistics")
+    @Operation(summary = "查询签到统计", description = "获取用户签到统计信息,包括连续天数、累计天数等")
+    public HttpResult<SignInStatisticsVO> getStatistics(
+            @Parameter(description = "租户ID(不传则从登录信息获取)")
+            @RequestParam(required = false) String tenantId,
+            @Parameter(description = "用户ID(不传则从登录信息获取)")
+            @RequestParam(required = false) String userId) {
+        if (tenantId == null) {
+            tenantId = getSystemCode();
+        }
+        if (userId == null) {
+            userId = getUserId();
+        }
+        return signInService.getStatistics(tenantId, userId);
+    }
+
+    /**
+     * 查询签到记录列表
+     */
+    @GetMapping("/getRecords")
+    @Operation(summary = "查询签到记录", description = "获取用户最近签到记录列表")
+    public HttpResult<List<SignInRecordVO>> getRecords(
+            @Parameter(description = "租户ID(不传则从登录信息获取)")
+            @RequestParam(required = false) String tenantId,
+            @Parameter(description = "用户ID(不传则从登录信息获取)")
+            @RequestParam(required = false) String userId,
+            @Parameter(description = "查询最近天数,默认30天")
+            @RequestParam(required = false, defaultValue = "30") Integer days) {
+        if (tenantId == null) {
+            tenantId = getSystemCode();
+        }
+        if (userId == null) {
+            userId = getUserId();
+        }
+        return signInService.getRecords(tenantId, userId, days);
+    }
+}

+ 20 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/dto/SignInDTO.java

@@ -0,0 +1,20 @@
+package com.jzg.organization.entity.dto;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 签到请求DTO
+ */
+@Data
+public class SignInDTO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "租户ID(不传则从登录信息获取)")
+    private String tenantId;
+
+    @Schema(description = "用户ID(不传则从登录信息获取)")
+    private String userId;
+}

+ 28 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/vo/SignInRecordVO.java

@@ -0,0 +1,28 @@
+package com.jzg.organization.entity.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+
+/**
+ * 签到记录VO
+ */
+@Data
+public class SignInRecordVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "记录ID")
+    private String id;
+
+    @Schema(description = "签到日期")
+    private LocalDate signInDate;
+
+    @Schema(description = "当日连续签到天数")
+    private Integer continuousDays;
+
+    @Schema(description = "签到时间")
+    private LocalDateTime signInTime;
+}

+ 34 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/vo/SignInStatisticsVO.java

@@ -0,0 +1,34 @@
+package com.jzg.organization.entity.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * 签到统计信息VO
+ */
+@Data
+public class SignInStatisticsVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "本月累计签到天数")
+    private Integer monthTotalDays;
+
+    @Schema(description = "当前连续签到天数")
+    private Integer currentContinuousDays;
+
+    @Schema(description = "历史最高连续签到天数")
+    private Integer maxContinuousDays;
+
+    @Schema(description = "总累计签到天数")
+    private Integer totalDays;
+
+    @Schema(description = "今日是否已签到")
+    private Boolean todaySigned;
+
+    @Schema(description = "最近签到日期列表(本月)")
+    private List<LocalDate> recentSignDates;
+}

+ 39 - 0
tenant/organization/src/main/java/com/jzg/organization/entity/vo/SignInVO.java

@@ -0,0 +1,39 @@
+package com.jzg.organization.entity.vo;
+
+import com.jzg.commons.entity.vo.SignRuleVO;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 签到结果VO
+ */
+@Data
+public class SignInVO implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    @Schema(description = "是否签到成功")
+    private Boolean success;
+
+    @Schema(description = "签到日期")
+    private LocalDate signInDate;
+
+    @Schema(description = "连续签到天数")
+    private Integer continuousDays;
+
+    @Schema(description = "本次签到获得抽奖次数")
+    private Integer lotteryChance;
+
+    @Schema(description = "触发的签到规则列表")
+    private List<SignRuleVO> triggeredRules;
+
+    @Schema(description = "提示消息")
+    private String message;
+
+    @Schema(description = "签到时间")
+    private LocalDateTime signInTime;
+}

+ 41 - 0
tenant/organization/src/main/java/com/jzg/organization/mapper/SysUserSignInMapper.java

@@ -0,0 +1,41 @@
+package com.jzg.organization.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jzg.commons.entity.po.SysUserSignIn;
+import org.apache.ibatis.annotations.Param;
+
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * 用户签到记录Mapper
+ */
+public interface SysUserSignInMapper extends BaseMapper<SysUserSignIn> {
+
+    /**
+     * 查询用户最新的签到记录
+     */
+    SysUserSignIn selectLatestByUser(@Param("tenantId") String tenantId,
+                                      @Param("userId") String userId);
+
+    /**
+     * 查询用户指定日期是否已签到
+     */
+    int countByDate(@Param("tenantId") String tenantId,
+                    @Param("userId") String userId,
+                    @Param("signInDate") LocalDate signInDate);
+
+    /**
+     * 查询用户的签到记录列表
+     */
+    List<SysUserSignIn> selectListByUser(@Param("tenantId") String tenantId,
+                                         @Param("userId") String userId,
+                                         @Param("startDate") LocalDate startDate,
+                                         @Param("endDate") LocalDate endDate);
+
+    /**
+     * 查询历史最高连续签到天数
+     */
+    Integer selectMaxContinuousDays(@Param("tenantId") String tenantId,
+                                    @Param("userId") String userId);
+}

+ 28 - 0
tenant/organization/src/main/java/com/jzg/organization/mapper/SysUserSignInRuleMapper.java

@@ -0,0 +1,28 @@
+package com.jzg.organization.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.jzg.commons.entity.po.SysUserSignInRule;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 用户签到规则完成记录Mapper
+ */
+public interface SysUserSignInRuleMapper extends BaseMapper<SysUserSignInRule> {
+
+    /**
+     * 查询用户已完成的规则
+     */
+    List<SysUserSignInRule> selectCompletedRules(@Param("tenantId") String tenantId,
+                                                 @Param("userId") String userId,
+                                                 @Param("activityId") String activityId);
+
+    /**
+     * 查询特定规则的完成状态
+     */
+    SysUserSignInRule selectByRule(@Param("tenantId") String tenantId,
+                                   @Param("userId") String userId,
+                                   @Param("activityId") String activityId,
+                                   @Param("ruleSignNum") String ruleSignNum);
+}

+ 86 - 0
tenant/organization/src/main/java/com/jzg/organization/service/LotteryActivityService.java

@@ -0,0 +1,86 @@
+package com.jzg.organization.service;
+
+import com.jzg.commons.core.page.HttpResult;
+import com.jzg.commons.entity.vo.LotteryActivityVO;
+import com.jzg.commons.entity.vo.LocalActivityTableVO;
+import com.jzg.commons.entity.vo.SignRuleVO;
+import com.jzg.organization.client.LotteryActivityClient;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 抽奖活动服务
+ */
+@Slf4j
+@Service
+public class LotteryActivityService {
+
+    @Autowired
+    private LotteryActivityClient lotteryActivityClient;
+
+    /**
+     * 根据场景查询活动列表
+     */
+    public List<LotteryActivityVO> getActivitiesByScene(Integer scene) {
+        HttpResult<List<LotteryActivityVO>> result = lotteryActivityClient.queryActivityRules(scene);
+        if (result == null || result.getCode() != 200 || result.getData() == null) {
+            log.warn("查询抽奖活动规则失败,scene={}", scene);
+            return Collections.emptyList();
+        }
+        return result.getData();
+    }
+
+    /**
+     * 查询签到规则(type=7)
+     */
+    public List<SignRuleVO> getSignRules(Integer scene) {
+        List<LotteryActivityVO> activities = getActivitiesByScene(scene);
+        List<SignRuleVO> signRules = new ArrayList<>();
+
+        for (LotteryActivityVO activity : activities) {
+            if (activity.getLocalActivityTables() == null) {
+                continue;
+            }
+            for (LocalActivityTableVO table : activity.getLocalActivityTables()) {
+                if ("7".equals(table.getType()) && table.getSignRules() != null) {
+                    signRules.addAll(table.getSignRules());
+                }
+            }
+        }
+        return signRules;
+    }
+
+    /**
+     * 获取指定活动的签到规则
+     */
+    public List<SignRuleVO> getSignRulesByActivity(Integer scene, String activityId) {
+        List<LotteryActivityVO> activities = getActivitiesByScene(scene);
+        return activities.stream()
+                .filter(a -> activityId.equals(a.getId()))
+                .filter(a -> a.getLocalActivityTables() != null)
+                .flatMap(a -> a.getLocalActivityTables().stream())
+                .filter(t -> "7".equals(t.getType()))
+                .filter(t -> t.getSignRules() != null)
+                .flatMap(t -> t.getSignRules().stream())
+                .collect(Collectors.toList());
+    }
+
+    /**
+     * 检查活动是否有效
+     */
+    public boolean isActivityValid(LotteryActivityVO activity) {
+        if (activity == null) {
+            return false;
+        }
+        LocalDate now = LocalDate.now();
+        return !now.isBefore(activity.getActivityStartTime())
+                && !now.isAfter(activity.getActivityEndTime());
+    }
+}

+ 42 - 0
tenant/organization/src/main/java/com/jzg/organization/service/SignInService.java

@@ -0,0 +1,42 @@
+package com.jzg.organization.service;
+
+import com.jzg.commons.core.page.HttpResult;
+import com.jzg.organization.entity.dto.SignInDTO;
+import com.jzg.organization.entity.vo.SignInStatisticsVO;
+import com.jzg.organization.entity.vo.SignInVO;
+import com.jzg.organization.entity.vo.SignInRecordVO;
+
+import java.util.List;
+
+/**
+ * 签到服务接口
+ */
+public interface SignInService {
+
+    /**
+     * 用户签到
+     *
+     * @param dto 签到请求
+     * @return 签到结果
+     */
+    HttpResult<SignInVO> signIn(SignInDTO dto);
+
+    /**
+     * 查询签到统计信息
+     *
+     * @param tenantId 租户ID(可选)
+     * @param userId   用户ID(可选)
+     * @return 统计信息
+     */
+    HttpResult<SignInStatisticsVO> getStatistics(String tenantId, String userId);
+
+    /**
+     * 查询签到记录列表
+     *
+     * @param tenantId 租户ID(可选)
+     * @param userId   用户ID(可选)
+     * @param days     查询最近天数,默认30天
+     * @return 记录列表
+     */
+    HttpResult<List<SignInRecordVO>> getRecords(String tenantId, String userId, Integer days);
+}

+ 4 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlAgreementCostServiceImpl.java

@@ -2,6 +2,7 @@ package com.jzg.organization.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -320,6 +321,9 @@ public class PtlAgreementCostServiceImpl extends ServiceImpl<PtlAgreementCostMap
 
 
     public static boolean isValid(String effectiveTime, String failureTime) {
+        if (StrUtil.isBlank(effectiveTime) || StrUtil.isBlank(failureTime)){
+            return false;
+        }
         LocalDateTime now = LocalDateTime.now();
         LocalDateTime start = LocalDateTime.parse(effectiveTime,
                 DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

+ 17 - 5
tenant/organization/src/main/java/com/jzg/organization/service/impl/PtlSchemeServiceImpl.java

@@ -107,6 +107,13 @@ public class PtlSchemeServiceImpl extends ServiceImpl<PtlSchemeMapper, PtlScheme
 
         //方案信息
         List<PtlSchemeInfo> ptlSchemeInfoList = ptlSchemeSaveVo.getPtlSchemeInfoList();
+        // modify by lipf, 解决描述为空时,修改失效的bug 2026年4月21日17:04:15
+        for (PtlSchemeInfo ptlSchemeInfo : ptlSchemeInfoList) {
+            var desc =  ptlSchemeInfo.getDescription();
+            if(desc == null){
+                ptlSchemeInfo.setDescription("");
+            }
+        }
         ptlSchemeInfoMapper.insertOrUpdate(ptlSchemeInfoList);
 
         //商业险信息
@@ -346,8 +353,12 @@ public class PtlSchemeServiceImpl extends ServiceImpl<PtlSchemeMapper, PtlScheme
         log.info("租户[{}]有权限的保司有[{}]个", systemCode, CollUtil.size(companyListResult.getData()));
         AssertionUtils.isFail(companyListResult.getCode() != 200, companyListResult.getMsg());
         List<EsmInsCompany> companyList = companyListResult.getData();
-        log.info("根据权限获取到的保司个数是[{}].systemCode=[{}],systemCode=[{}]", CollUtil.size(companyList),systemCode,systemCode);
-        AssertionUtils.isFail(companyList.isEmpty(), "没有可报价的保险公司");
+        log.info("根据权限获取到的保司个数是[{}].systemCode=[{}]", CollUtil.size(companyList),systemCode);
+        if(CollUtil.isEmpty(companyList)){
+            log.info("租户[{}]没有可报价的保险公司,请到平台系统的【租户管理】-【功能配置】页面进行配置并且查看对应公司的协议,费用是否维护好",systemCode);
+            AssertionUtils.isFail(companyList.isEmpty(), "没有可报价的保险公司");
+        }
+
         //根据基本规则 能源、车辆类型、使用性质获取方案
         List<PtlScheme> ptlSchemes = ptlSchemeMapper.selectList(new LambdaQueryWrapper<PtlScheme>()
                 .eq(PtlScheme::getEnergyType, schemeRuleFilterVo.getCarInfo().getEnergyTypeCode())
@@ -355,6 +366,9 @@ public class PtlSchemeServiceImpl extends ServiceImpl<PtlSchemeMapper, PtlScheme
                 .like(PtlScheme::getVehicleType, schemeRuleFilterVo.getCarInfo().getCarKindCode())
                 .eq(PtlScheme::getProductId, schemeRuleFilterVo.getProductId())
                 .eq(PtlScheme::getIsDelete, 0));
+        log.info("根据车辆信息匹配保险方案:匹配到[{}]个方案。 energyType(能源类型)=[{}],carNatureCode(使用性质)=[{}],carKindCode(车辆性质)=[{}], productId(产品id)=[{}]",
+                CollUtil.size(ptlSchemes), schemeRuleFilterVo.getCarInfo().getEnergyTypeCode(), schemeRuleFilterVo.getCarInfo().getCarNatureCode(),schemeRuleFilterVo.getCarInfo().getCarKindCode(),
+                schemeRuleFilterVo.getProductId());
 
         // 查找规则
         List<String> ptlSchemeIds = ptlSchemes.stream().map(PtlScheme::getId).collect(Collectors.toList());
@@ -498,9 +512,7 @@ public class PtlSchemeServiceImpl extends ServiceImpl<PtlSchemeMapper, PtlScheme
 
         List<SchemeResultVo.SchemeInfoVo> allInfo = new ArrayList<>();
 
-        schemeVo.forEach(scheme -> scheme.getInfos().forEach(item -> {
-            allInfo.add(item);
-        }));
+        schemeVo.forEach(scheme -> allInfo.addAll(scheme.getInfos()));
 
         schemeResultVo.setSchemes(allInfo);
         //把基础方案的商业险的value 赋值

+ 365 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/SignInServiceImpl.java

@@ -0,0 +1,365 @@
+package com.jzg.organization.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.jzg.commons.core.base.BaseController;
+import com.jzg.commons.core.page.HttpResult;
+import com.jzg.commons.entity.po.SysUserSignIn;
+import com.jzg.commons.entity.po.SysUserSignInRule;
+import com.jzg.commons.entity.vo.LotteryActivityVO;
+import com.jzg.commons.entity.vo.LocalActivityTableVO;
+import com.jzg.commons.entity.vo.SignRuleVO;
+import com.jzg.organization.entity.dto.SignInDTO;
+import com.jzg.organization.entity.vo.SignInRecordVO;
+import com.jzg.organization.entity.vo.SignInStatisticsVO;
+import com.jzg.organization.entity.vo.SignInVO;
+import com.jzg.organization.mapper.SysUserSignInMapper;
+import com.jzg.organization.mapper.SysUserSignInRuleMapper;
+import com.jzg.organization.service.LotteryActivityService;
+import com.jzg.organization.service.SignInService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import jakarta.servlet.http.HttpServletRequest;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.temporal.TemporalAdjusters;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+/**
+ * 签到服务实现类
+ */
+@Slf4j
+@Service
+public class SignInServiceImpl implements SignInService {
+
+    @Autowired
+    private SysUserSignInMapper signInMapper;
+
+    @Autowired
+    private SysUserSignInRuleMapper signInRuleMapper;
+
+    @Autowired
+    private LotteryActivityService lotteryActivityService;
+
+    @Autowired
+    private HttpServletRequest request;
+
+    @Value("${lottery.activity.scene:3}")
+    private Integer lotteryScene;
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public HttpResult<SignInVO> signIn(SignInDTO dto) {
+        // 获取当前用户和租户信息
+        String tenantId = getTenantId(dto.getTenantId());
+        String userId = getUserId(dto.getUserId());
+
+        if (StrUtil.isBlank(tenantId) || StrUtil.isBlank(userId)) {
+            return HttpResult.error("用户未登录或登录信息异常");
+        }
+
+        LocalDate today = LocalDate.now();
+
+        // 检查今日是否已签到
+        int count = signInMapper.countByDate(tenantId, userId, today);
+        if (count > 0) {
+            return HttpResult.error("今日已签到,请勿重复签到");
+        }
+
+        // 计算连续签到天数
+        Integer continuousDays = calculateContinuousDays(tenantId, userId);
+
+        // 保存签到记录
+        SysUserSignIn signIn = new SysUserSignIn();
+        signIn.setTenantId(tenantId);
+        signIn.setUserId(userId);
+        signIn.setSignInDate(today);
+        signIn.setContinuousDays(continuousDays);
+        signIn.setSignInTime(LocalDateTime.now());
+        signInMapper.insert(signIn);
+
+        // 检查并触发签到规则
+        List<SignRuleVO> triggeredRules = checkAndTriggerSignRules(tenantId, userId, continuousDays);
+
+        // 统计本次获得的抽奖次数
+        int totalLotteryChance = triggeredRules.stream()
+                .filter(r -> StrUtil.isNotBlank(r.getSignLotteryNum()))
+                .mapToInt(r -> Integer.parseInt(r.getSignLotteryNum()))
+                .sum();
+
+        // 构建返回结果
+        SignInVO vo = new SignInVO();
+        vo.setSuccess(true);
+        vo.setSignInDate(today);
+        vo.setContinuousDays(continuousDays);
+        vo.setLotteryChance(totalLotteryChance);
+        vo.setTriggeredRules(triggeredRules);
+        vo.setSignInTime(LocalDateTime.now());
+
+        String message = buildSuccessMessage(continuousDays, totalLotteryChance, triggeredRules);
+        vo.setMessage(message);
+
+        log.info("用户签到成功,tenantId={}, userId={}, continuousDays={}, lotteryChance={}",
+                tenantId, userId, continuousDays, totalLotteryChance);
+
+        return HttpResult.ok(message, vo);
+    }
+
+    /**
+     * 检查并触发可完成的签到规则
+     * 每个规则在活动期间只能完成一次
+     */
+    private List<SignRuleVO> checkAndTriggerSignRules(String tenantId, String userId, Integer continuousDays) {
+        List<SignRuleVO> triggeredRules = new ArrayList<>();
+
+        // 获取当前有效的活动
+        List<LotteryActivityVO> activities = lotteryActivityService.getActivitiesByScene(lotteryScene);
+
+        for (LotteryActivityVO activity : activities) {
+            // 检查活动是否有效
+            if (!lotteryActivityService.isActivityValid(activity)) {
+                continue;
+            }
+
+            if (activity.getLocalActivityTables() == null) {
+                continue;
+            }
+
+            // 获取用户已完成的规则
+            List<SysUserSignInRule> completedRules = signInRuleMapper.selectCompletedRules(
+                    tenantId, userId, activity.getId());
+            Set<String> completedSignNums = completedRules.stream()
+                    .map(SysUserSignInRule::getRuleSignNum)
+                    .collect(Collectors.toSet());
+
+            // 遍历所有本地活动表
+            for (LocalActivityTableVO table : activity.getLocalActivityTables()) {
+                // 只处理 type=7 的签到规则
+                if (!"7".equals(table.getType()) || table.getSignRules() == null) {
+                    continue;
+                }
+
+                // 检查每个签到规则
+                for (SignRuleVO rule : table.getSignRules()) {
+                    if (StrUtil.isBlank(rule.getSignNum())) {
+                        continue;
+                    }
+
+                    Integer requiredDays = Integer.parseInt(rule.getSignNum());
+
+                    // 判断是否满足条件且未完成过
+                    if (continuousDays >= requiredDays
+                            && !completedSignNums.contains(rule.getSignNum())) {
+
+                        // 记录规则完成
+                        completeSignRule(tenantId, userId, activity.getId(),
+                                table.getId(), rule);
+
+                        triggeredRules.add(rule);
+                    }
+                }
+            }
+        }
+
+        return triggeredRules;
+    }
+
+    /**
+     * 记录规则完成
+     */
+    private void completeSignRule(String tenantId, String userId, String activityId,
+                                    String tableId, SignRuleVO rule) {
+        // 先查询是否已存在记录(防重入)
+        SysUserSignInRule exist = signInRuleMapper.selectByRule(
+                tenantId, userId, activityId, rule.getSignNum());
+
+        if (exist != null) {
+            return;
+        }
+
+        SysUserSignInRule record = new SysUserSignInRule();
+        record.setTenantId(tenantId);
+        record.setUserId(userId);
+        record.setActivityId(activityId);
+        record.setLocalActivityTableId(tableId);
+        record.setRuleSignNum(rule.getSignNum());
+        record.setLotteryNum(StrUtil.isNotBlank(rule.getSignLotteryNum())
+                ? Integer.parseInt(rule.getSignLotteryNum()) : 0);
+        record.setStatus(1);
+        record.setReceiveTime(LocalDateTime.now());
+
+        signInRuleMapper.insert(record);
+
+        log.info("签到规则完成,tenantId={}, userId={}, activityId={}, ruleSignNum={}, lotteryNum={}",
+                tenantId, userId, activityId, rule.getSignNum(), record.getLotteryNum());
+    }
+
+    /**
+     * 计算连续签到天数
+     */
+    private Integer calculateContinuousDays(String tenantId, String userId) {
+        SysUserSignIn latest = signInMapper.selectLatestByUser(tenantId, userId);
+
+        if (latest == null) {
+            return 1; // 首次签到
+        }
+
+        LocalDate yesterday = LocalDate.now().minusDays(1);
+
+        // 如果上次签到是昨天,则连续天数+1
+        if (latest.getSignInDate().isEqual(yesterday)) {
+            return latest.getContinuousDays() + 1;
+        }
+
+        // 如果上次签到是今天(重复签到,理论上不会走到这里)
+        if (latest.getSignInDate().isEqual(LocalDate.now())) {
+            return latest.getContinuousDays();
+        }
+
+        // 断签了,从1开始
+        return 1;
+    }
+
+    /**
+     * 构建成功消息
+     */
+    private String buildSuccessMessage(Integer continuousDays, Integer lotteryChance, List<SignRuleVO> rules) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("签到成功!连续签到").append(continuousDays).append("天");
+
+        if (lotteryChance > 0 && CollUtil.isNotEmpty(rules)) {
+            sb.append(",恭喜完成");
+            for (int i = 0; i < rules.size(); i++) {
+                SignRuleVO rule = rules.get(i);
+                if (i > 0) {
+                    sb.append("、");
+                }
+                sb.append(rule.getSignNum()).append("天签到任务");
+            }
+            sb.append(",获得").append(lotteryChance).append("次抽奖机会");
+        }
+
+        return sb.toString();
+    }
+
+    @Override
+    public HttpResult<SignInStatisticsVO> getStatistics(String tenantId, String userId) {
+        String tId = getTenantId(tenantId);
+        String uId = getUserId(userId);
+
+        if (StrUtil.isBlank(tId) || StrUtil.isBlank(uId)) {
+            return HttpResult.error("用户未登录或登录信息异常");
+        }
+
+        LocalDate today = LocalDate.now();
+        LocalDate monthStart = today.with(TemporalAdjusters.firstDayOfMonth());
+
+        // 查询本月签到记录
+        List<SysUserSignIn> monthRecords = signInMapper.selectListByUser(tId, uId, monthStart, today);
+
+        // 查询历史最高连续天数
+        Integer maxContinuousDays = signInMapper.selectMaxContinuousDays(tId, uId);
+        if (maxContinuousDays == null) {
+            maxContinuousDays = 0;
+        }
+
+        // 查询今日是否已签到
+        int todayCount = signInMapper.countByDate(tId, uId, today);
+
+        // 计算当前连续天数
+        Integer currentContinuous = 0;
+        if (CollUtil.isNotEmpty(monthRecords)) {
+            SysUserSignIn latest = monthRecords.get(0);
+            if (latest.getSignInDate().isEqual(today) || latest.getSignInDate().isEqual(today.minusDays(1))) {
+                currentContinuous = latest.getContinuousDays();
+            }
+        }
+
+        // 查询累计签到天数
+        Integer totalDays = signInMapper.selectCount(
+                Wrappers.<SysUserSignIn>lambdaQuery()
+                        .eq(SysUserSignIn::getTenantId, tId)
+                        .eq(SysUserSignIn::getUserId, uId)
+                        .eq(SysUserSignIn::getIsDelete, 0)
+        ).intValue();
+
+        SignInStatisticsVO vo = new SignInStatisticsVO();
+        vo.setMonthTotalDays(monthRecords.size());
+        vo.setCurrentContinuousDays(currentContinuous);
+        vo.setMaxContinuousDays(maxContinuousDays);
+        vo.setTotalDays(totalDays);
+        vo.setTodaySigned(todayCount > 0);
+        vo.setRecentSignDates(monthRecords.stream()
+                .map(SysUserSignIn::getSignInDate)
+                .collect(Collectors.toList()));
+
+        return HttpResult.ok(vo);
+    }
+
+    @Override
+    public HttpResult<List<SignInRecordVO>> getRecords(String tenantId, String userId, Integer days) {
+        String tId = getTenantId(tenantId);
+        String uId = getUserId(userId);
+
+        if (StrUtil.isBlank(tId) || StrUtil.isBlank(uId)) {
+            return HttpResult.error("用户未登录或登录信息异常");
+        }
+
+        if (days == null || days <= 0) {
+            days = 30;
+        }
+
+        LocalDate endDate = LocalDate.now();
+        LocalDate startDate = endDate.minusDays(days - 1);
+
+        List<SysUserSignIn> records = signInMapper.selectListByUser(tId, uId, startDate, endDate);
+
+        if (CollUtil.isEmpty(records)) {
+            return HttpResult.ok(Collections.emptyList());
+        }
+
+        List<SignInRecordVO> voList = records.stream().map(r -> {
+            SignInRecordVO vo = new SignInRecordVO();
+            vo.setId(r.getId());
+            vo.setSignInDate(r.getSignInDate());
+            vo.setContinuousDays(r.getContinuousDays());
+            vo.setSignInTime(r.getSignInTime());
+            return vo;
+        }).collect(Collectors.toList());
+
+        return HttpResult.ok(voList);
+    }
+
+    /**
+     * 获取租户ID
+     */
+    private String getTenantId(String dtoTenantId) {
+        if (StrUtil.isNotBlank(dtoTenantId)) {
+            return dtoTenantId;
+        }
+        // 从请求头或上下文中获取
+        Object tenantObj = request.getAttribute("tenantId");
+        return tenantObj != null ? tenantObj.toString() : null;
+    }
+
+    /**
+     * 获取用户ID
+     */
+    private String getUserId(String dtoUserId) {
+        if (StrUtil.isNotBlank(dtoUserId)) {
+            return dtoUserId;
+        }
+        // 从请求头或上下文中获取
+        Object userObj = request.getAttribute("userId");
+        return userObj != null ? userObj.toString() : null;
+    }
+}

+ 25 - 0
tenant/organization/src/main/java/com/jzg/organization/service/impl/SysUserServiceImpl.java

@@ -2,6 +2,7 @@ package com.jzg.organization.service.impl;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -45,6 +46,8 @@ import org.springframework.web.context.request.RequestAttributes;
 import org.springframework.web.context.request.RequestContextHolder;
 import org.springframework.web.context.request.ServletRequestAttributes;
 
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
 import java.util.stream.Collectors;
@@ -867,8 +870,10 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
     @Override
     @Transactional(rollbackFor = Exception.class)
     public HttpResult<Boolean> updateUserInfo(SysUserVo sysUserVo) {
+        log.info("修改人员信息:sysUserVo=[{}]", JSONUtil.toJsonStr(sysUserVo));
         SysUserJzgInfo sysUserJzgInfo = sysUserJzgInfoService.getById(sysUserVo.getId());
         if (Objects.isNull(sysUserJzgInfo)) {
+            log.info("id=[{}]的人员不存在", sysUserVo.getId());
             throw new SystemException("该业务员不存在");
         }
 //        if (sysUserJzgInfo.getIsEnable() == 0) {
@@ -885,6 +890,24 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
             }
 
         }
+        // modify by lipf, 解决身份证信息没有更新的问题
+        SysUser originSysUser = sysUserService.getById(sysUserVo.getUserId());
+        if(originSysUser != null){
+            log.info("更新身份证等信息。原信息originSysUser=[{}]",JSONUtil.toJsonStr(originSysUser));
+            originSysUser.setIdentity(sysUserVo.getIdentity());
+            if(StrUtil.isEmpty(sysUserVo.getIdentityTimeStart())){
+                originSysUser.setIdentityTimeStart(null);
+            }else{
+                originSysUser.setIdentityTimeStart(LocalDate.parse(sysUserVo.getIdentityTimeStart(), DateTimeFormatter.ISO_DATE));
+            }
+
+            if(StrUtil.isEmpty(sysUserVo.getIdentityTimeEnd())){
+                originSysUser.setIdentityTimeEnd(null);
+            }else{
+                originSysUser.setIdentityTimeEnd(LocalDate.parse(sysUserVo.getIdentityTimeEnd(), DateTimeFormatter.ISO_DATE));
+            }
+            sysUserService.updateById(originSysUser);
+        }
         sysUserJzgInfoService.updateById(sysUserJzgInfo);
 
         //用户角色处理
@@ -919,10 +942,12 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
     @Override
     public HttpResult getUserInfoByUserId(String id) {
         SysUserJzgInfo sysUserJzgInfo = sysUserJzgInfoService.getUserByUserId(id);
+        log.info("根据id=[{}]查询用户信息sysUserJzgInfo=[{}]",id, JSONUtil.toJsonStr(sysUserJzgInfo));
         if (sysUserJzgInfo == null) {
             throw new SystemException("该用户不存在");
         }
         SysUser sysUser = sysUserService.getById(sysUserJzgInfo.getUserId());
+        log.info("sysUser=[{}]", JSONUtil.toJsonStr(sysUser));
         if (sysUser == null) {
             throw new SystemException("该用户不存在");
         }

+ 38 - 0
tenant/organization/src/main/resources/mapper/SysUserSignInMapper.xml

@@ -0,0 +1,38 @@
+<?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.jzg.organization.mapper.SysUserSignInMapper">
+
+    <select id="selectLatestByUser" resultType="com.jzg.commons.entity.po.SysUserSignIn">
+        SELECT * FROM sys_user_sign_in
+        WHERE tenant_id = #{tenantId}
+          AND user_id = #{userId}
+          AND is_delete = 0
+        ORDER BY sign_in_date DESC
+        LIMIT 1
+    </select>
+
+    <select id="countByDate" resultType="java.lang.Integer">
+        SELECT COUNT(*) FROM sys_user_sign_in
+        WHERE tenant_id = #{tenantId}
+          AND user_id = #{userId}
+          AND sign_in_date = #{signInDate}
+          AND is_delete = 0
+    </select>
+
+    <select id="selectListByUser" resultType="com.jzg.commons.entity.po.SysUserSignIn">
+        SELECT * FROM sys_user_sign_in
+        WHERE tenant_id = #{tenantId}
+          AND user_id = #{userId}
+          AND sign_in_date BETWEEN #{startDate} AND #{endDate}
+          AND is_delete = 0
+        ORDER BY sign_in_date DESC
+    </select>
+
+    <select id="selectMaxContinuousDays" resultType="java.lang.Integer">
+        SELECT MAX(continuous_days) FROM sys_user_sign_in
+        WHERE tenant_id = #{tenantId}
+          AND user_id = #{userId}
+          AND is_delete = 0
+    </select>
+
+</mapper>

+ 24 - 0
tenant/organization/src/main/resources/mapper/SysUserSignInRuleMapper.xml

@@ -0,0 +1,24 @@
+<?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.jzg.organization.mapper.SysUserSignInRuleMapper">
+
+    <select id="selectCompletedRules" resultType="com.jzg.commons.entity.po.SysUserSignInRule">
+        SELECT * FROM sys_user_sign_in_rule
+        WHERE tenant_id = #{tenantId}
+          AND user_id = #{userId}
+          AND activity_id = #{activityId}
+          AND status = 1
+          AND is_delete = 0
+    </select>
+
+    <select id="selectByRule" resultType="com.jzg.commons.entity.po.SysUserSignInRule">
+        SELECT * FROM sys_user_sign_in_rule
+        WHERE tenant_id = #{tenantId}
+          AND user_id = #{userId}
+          AND activity_id = #{activityId}
+          AND rule_sign_num = #{ruleSignNum}
+          AND is_delete = 0
+        LIMIT 1
+    </select>
+
+</mapper>