Quellcode durchsuchen

中台 律所模块 律师用户模块

qxy vor 3 Wochen
Ursprung
Commit
567f83a99d

+ 2 - 2
alien-entity/src/main/java/shop/alien/entity/store/LawFirm.java

@@ -174,9 +174,9 @@ public class LawFirm extends Model<LawFirm> implements Serializable {
 
     @ApiModelProperty(value = "平台佣金比例(百分比)")
     @TableField("platform_commission_ratio")
-    private BigDecimal platformCommissionRatio;
+    private Integer platformCommissionRatio;
 
-    @ApiModelProperty(value = "收款账号列表(临时字段,不映射到数据库)")
+    @ApiModelProperty(value = "律师子表(临时字段,不映射到数据库)")
     @TableField(exist = false)
     private List<LawFirmPayment> paymentList;
 }

+ 2 - 1
alien-entity/src/main/java/shop/alien/entity/store/LawFirmPayment.java

@@ -37,7 +37,7 @@ public class LawFirmPayment extends Model<LawFirmPayment> implements Serializabl
     @TableField("payment_account")
     private String paymentAccount;
 
-    @ApiModelProperty(value = "地址")
+    @ApiModelProperty(value = "详细地址")
     @TableField("address")
     private String address;
 
@@ -65,3 +65,4 @@ public class LawFirmPayment extends Model<LawFirmPayment> implements Serializabl
     private Integer updatedUserId;
 }
 
+

+ 1 - 1
alien-entity/src/main/java/shop/alien/entity/store/LawyerLegalProblemScenario.java

@@ -83,7 +83,7 @@ public class LawyerLegalProblemScenario extends Model<LawyerLegalProblemScenario
     private List<LawyerLegalProblemScenario> children;
 
     @ApiModelProperty(value = "场景图片路径")
-    @TableField(exist = false)
+    @TableField("img_url")
     private String imgUrl;
 
 }

+ 3 - 3
alien-entity/src/main/java/shop/alien/entity/store/excelVo/LawFirmExcelVo.java

@@ -25,7 +25,7 @@ public class LawFirmExcelVo {
     @ApiModelProperty(value = "律所名称")
     private String firmName;
 
-//    @ExcelHeader("统一社会信用代码")
+    @ExcelHeader("统一社会信用代码")
     @ApiModelProperty(value = "统一社会信用代码")
     private String creditCode;
 
@@ -118,10 +118,10 @@ public class LawFirmExcelVo {
     private String certificationStatus;
 
     @ExcelHeader("律师事务所收款账号")
-    @ApiModelProperty(value = "律师事务所收款账号(多个账号用逗号分隔)")
+    @ApiModelProperty(value = "律师事务所收款账号(必须是16位或19位,每行只能填写一个账号,不允许逗号分隔)")
     private String paymentAccount;
 
-//    @ExcelHeader("平台佣金比例")
+    @ExcelHeader("平台佣金比例")
     @ApiModelProperty(value = "平台佣金比例(百分比)")
     private String platformCommissionRatio;
 

+ 109 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/LawFirmPaymentVO.java

@@ -0,0 +1,109 @@
+package shop.alien.entity.store.vo;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 律所子表视图对象(包含律所信息)
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude
+@ApiModel(value = "LawFirmPaymentVO对象", description = "律所子表视图对象(包含律所信息)")
+public class LawFirmPaymentVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    // ========== 律所子表字段 ==========
+    @ExcelIgnore
+    @ApiModelProperty(value = "主键id")
+    private Integer id;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "律师表id")
+    private Integer firmId;
+
+    @ExcelProperty(value = "律师事务所收款账号", index = 3)
+    @ApiModelProperty(value = "律师事务所收款账号")
+    private String paymentAccount;
+
+    @ExcelProperty(value = "详细地址", index = 4)
+    @ApiModelProperty(value = "地址")
+    private String address;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "删除标记, 0:未删除, 1:已删除")
+    private Integer deleteFlag;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "创建人ID")
+    private Integer createdUserId;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "修改时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "修改人ID")
+    private Integer updatedUserId;
+
+    // ========== 律所表字段 ==========
+    @ExcelProperty(value = "律所名称", index = 0)
+    @ApiModelProperty(value = "律所名称")
+    private String firmName;
+
+    @ExcelProperty(value = "统一社会信用代码", index = 1)
+    @ApiModelProperty(value = "统一社会信用代码")
+    private String creditCode;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "律所简称")
+    private String shortName;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "联系电话")
+    private String phone;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "邮箱")
+    private String email;
+
+    @ExcelProperty(value = "负责人姓名", index = 2)
+    @ApiModelProperty(value = "负责人姓名")
+    private String directorName;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "负责人电话")
+    private String directorPhone;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "律所状态, 0:禁用, 1:启用")
+    private Integer status;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "认证状态, 0:未认证, 1:认证中, 2:已认证, 3:认证失败")
+    private Integer certificationStatus;
+
+    @ExcelIgnore
+    @ApiModelProperty(value = "手续费")
+    private Integer platformCommissionRatio;
+}
+
+
+

+ 57 - 0
alien-entity/src/main/java/shop/alien/mapper/LawFirmPaymentMapper.java

@@ -1,8 +1,12 @@
 package shop.alien.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
 import shop.alien.entity.store.LawFirmPayment;
+import shop.alien.entity.store.vo.LawFirmPaymentVO;
 
 /**
  * <p>
@@ -15,5 +19,58 @@ import shop.alien.entity.store.LawFirmPayment;
 @Mapper
 public interface LawFirmPaymentMapper extends BaseMapper<LawFirmPayment> {
 
+    /**
+     * 分页查询律所子表关联律所表
+     *
+     * @param page 分页对象
+     * @param firmId 律所ID
+     * @param paymentAccount 收款账号(模糊查询)
+     * @param firmName 律所名称(模糊查询)
+     * @param creditCode 统一社会信用代码
+     * @param status 律所状态
+     * @param certificationStatus 认证状态
+     * @param directorName 负责人姓名(模糊查询)
+     * @param createdTimeStart 创建时间开始
+     * @param createdTimeEnd 创建时间结束
+     * @return 分页结果
+     */
+    IPage<LawFirmPaymentVO> selectPaymentPageWithFirm(
+            Page<LawFirmPaymentVO> page,
+            @Param("firmId") Integer firmId,
+            @Param("paymentAccount") String paymentAccount,
+            @Param("firmName") String firmName,
+            @Param("creditCode") String creditCode,
+            @Param("status") Integer status,
+            @Param("certificationStatus") Integer certificationStatus,
+            @Param("directorName") String directorName,
+            @Param("createdTimeStart") String createdTimeStart,
+            @Param("createdTimeEnd") String createdTimeEnd
+    );
+
+    /**
+     * 查询律所子表关联律所表总数
+     *
+     * @param firmId 律所ID
+     * @param paymentAccount 收款账号(模糊查询)
+     * @param firmName 律所名称(模糊查询)
+     * @param creditCode 统一社会信用代码
+     * @param status 律所状态
+     * @param certificationStatus 认证状态
+     * @param directorName 负责人姓名(模糊查询)
+     * @param createdTimeStart 创建时间开始
+     * @param createdTimeEnd 创建时间结束
+     * @return 总数
+     */
+    Long selectPaymentPageWithFirmCount(
+            @Param("firmId") Integer firmId,
+            @Param("paymentAccount") String paymentAccount,
+            @Param("firmName") String firmName,
+            @Param("creditCode") String creditCode,
+            @Param("status") Integer status,
+            @Param("certificationStatus") Integer certificationStatus,
+            @Param("directorName") String directorName,
+            @Param("createdTimeStart") String createdTimeStart,
+            @Param("createdTimeEnd") String createdTimeEnd
+    );
 }
 

+ 89 - 0
alien-entity/src/main/resources/mapper/LawFirmPaymentMapper.xml

@@ -0,0 +1,89 @@
+<?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="shop.alien.mapper.LawFirmPaymentMapper">
+
+    <!-- 律所子表关联律所表查询结果映射 -->
+    <resultMap id="LawFirmPaymentVOResultMap" type="shop.alien.entity.store.vo.LawFirmPaymentVO">
+        <!-- 律所子表字段 -->
+        <id column="payment_id" property="id" />
+        <result column="payment_firm_id" property="firmId" />
+        <result column="payment_account" property="paymentAccount" />
+        <result column="payment_address" property="address" />
+        <result column="payment_delete_flag" property="deleteFlag" />
+        <result column="payment_created_time" property="createdTime" />
+        <result column="payment_created_user_id" property="createdUserId" />
+        <result column="payment_updated_time" property="updatedTime" />
+        <result column="payment_updated_user_id" property="updatedUserId" />
+        <!-- 律所表字段 -->
+        <result column="firm_name" property="firmName" />
+        <result column="credit_code" property="creditCode" />
+        <result column="short_name" property="shortName" />
+        <result column="phone" property="phone" />
+        <result column="email" property="email" />
+        <result column="director_name" property="directorName" />
+        <result column="director_phone" property="directorPhone" />
+        <result column="status" property="status" />
+        <result column="certification_status" property="certificationStatus" />
+        <result column="platform_commission_ratio" property="platformCommissionRatio" />
+    </resultMap>
+
+    <!-- 分页查询律所子表关联律所表 -->
+    <select id="selectPaymentPageWithFirm" resultMap="LawFirmPaymentVOResultMap">
+        SELECT
+            p.id AS payment_id,
+            p.firm_id AS payment_firm_id,
+            p.payment_account,
+            p.address AS payment_address,
+            p.delete_flag AS payment_delete_flag,
+            p.created_time AS payment_created_time,
+            p.created_user_id AS payment_created_user_id,
+            p.updated_time AS payment_updated_time,
+            p.updated_user_id AS payment_updated_user_id,
+            f.firm_name,
+            f.credit_code,
+            f.short_name,
+            f.phone,
+            f.email,
+            f.director_name,
+            f.director_phone,
+            f.status,
+            f.platform_commission_ratio,
+            f.certification_status
+        FROM
+            law_firm_payment p
+        LEFT JOIN law_firm f ON f.id = p.firm_id AND f.delete_flag = 0
+        WHERE
+            p.delete_flag = 0
+        <if test="firmId != null">AND p.firm_id = #{firmId}</if>
+        <if test="paymentAccount != null and paymentAccount != ''">AND p.payment_account LIKE CONCAT('%', #{paymentAccount}, '%')</if>
+        <if test="firmName != null and firmName != ''">AND f.firm_name LIKE CONCAT('%', #{firmName}, '%')</if>
+        <if test="creditCode != null and creditCode != ''">AND f.credit_code = #{creditCode}</if>
+        <if test="status != null">AND f.status = #{status}</if>
+        <if test="certificationStatus != null">AND f.certification_status = #{certificationStatus}</if>
+        <if test="directorName != null and directorName != ''">AND f.director_name LIKE CONCAT('%', #{directorName}, '%')</if>
+        <if test="createdTimeStart != null and createdTimeStart != ''">AND p.created_time &gt;= #{createdTimeStart}</if>
+        <if test="createdTimeEnd != null and createdTimeEnd != ''">AND p.created_time &lt;= #{createdTimeEnd}</if>
+        ORDER BY f.id ASC, p.created_time DESC
+    </select>
+
+    <!-- 查询律所子表关联律所表总数 -->
+    <select id="selectPaymentPageWithFirmCount" resultType="java.lang.Long">
+        SELECT COUNT(*)
+        FROM
+            law_firm_payment p
+        LEFT JOIN law_firm f ON f.id = p.firm_id AND f.delete_flag = 0
+        WHERE
+            p.delete_flag = 0
+        <if test="firmId != null">AND p.firm_id = #{firmId}</if>
+        <if test="paymentAccount != null and paymentAccount != ''">AND p.payment_account LIKE CONCAT('%', #{paymentAccount}, '%')</if>
+        <if test="firmName != null and firmName != ''">AND f.firm_name LIKE CONCAT('%', #{firmName}, '%')</if>
+        <if test="creditCode != null and creditCode != ''">AND f.credit_code = #{creditCode}</if>
+        <if test="status != null">AND f.status = #{status}</if>
+        <if test="certificationStatus != null">AND f.certification_status = #{certificationStatus}</if>
+        <if test="directorName != null and directorName != ''">AND f.director_name LIKE CONCAT('%', #{directorName}, '%')</if>
+        <if test="createdTimeStart != null and createdTimeStart != ''">AND p.created_time &gt;= #{createdTimeStart}</if>
+        <if test="createdTimeEnd != null and createdTimeEnd != ''">AND p.created_time &lt;= #{createdTimeEnd}</if>
+    </select>
+
+</mapper>
+

+ 5 - 8
alien-entity/src/main/resources/mapper/LawyerUserMapper.xml

@@ -114,26 +114,23 @@
         user.delete_flag,
         user.created_time,
         firm.firm_name AS firmName,
-        firm.payment_account AS paymentNum,
+        firmTwo.payment_account AS paymentNum,
+        firmTwo.address AS address,
         GROUP_CONCAT(a.name SEPARATOR ',') AS scenarioNames,
-        (SELECT GROUP_CONCAT(`name` SEPARATOR ',') FROM lawyer_legal_problem_scenario WHERE level = 1) AS firstLevelScenario,
-        b.expertise_area_info AS expertiseAreaInfo
+        (SELECT GROUP_CONCAT(`name` SEPARATOR ',') FROM lawyer_legal_problem_scenario WHERE level = 1) AS firstLevelScenario
         FROM
         lawyer_user user
         LEFT JOIN law_firm firm ON firm.id = user.firm_id
+        LEFT JOIN law_firm_payment firmTwo ON firmTwo.firm_id = user.firm_id
         LEFT JOIN lawyer_service_area area ON area.lawyer_user_id = user.id
         LEFT JOIN lawyer_legal_problem_scenario a ON a.id = area.problem_scenario_id
-        LEFT JOIN lawyer_expertise_area b ON b.id = user.specialty_fields
         WHERE user.delete_flag = 0
         <if test="name != null and name != ''">AND user.name LIKE CONCAT('%', #{name}, '%')</if>
         <if test="phone != null and phone != ''">AND user.phone LIKE CONCAT('%', #{phone}, '%')</if>
         <if test="firmId != null">AND user.firm_id = #{firmId}</if>
         <if test="createdTimeStart != null and createdTimeStart != ''">AND user.created_time &gt;= #{createdTimeStart}</if>
         GROUP BY
-        user.id, user.phone, user.`name`, user.firm_id, user.head_img,
-        user.personal_introduction, user.order_receiving_status, user.practice_start_date,
-        user.address, user.status, user.delete_flag, user.created_time,
-        firm.firm_name, firm.payment_account, b.expertise_area_info
+        user.id
         ORDER BY user.created_time DESC
     </select>
 

+ 127 - 4
alien-gateway/src/main/java/shop/alien/gateway/controller/SystemController.java

@@ -208,7 +208,7 @@ public class SystemController {
                     "            \"icon\": \"Briefcase\",\n" +
                     "            \"title\": \"专业领域\",\n" +
                     "            \"isLink\": \"\",\n" +
-                    "            \"isHide\": false,\n" +
+                    "            \"isHide\": true,\n" +
                     "            \"isFull\": false,\n" +
                     "            \"isAffix\": false,\n" +
                     "            \"isKeepAlive\": false\n" +
@@ -227,6 +227,20 @@ public class SystemController {
                     "            \"isAffix\": false,\n" +
                     "            \"isKeepAlive\": false\n" +
                     "          }\n" +
+                    "        },\n" +
+                    "        {\n" +
+                    "          \"path\": \"/lawyerManagement/reconciliation/lawyerDetail\",\n" +
+                    "          \"name\": \"lawyerDetail\",\n" +
+                    "          \"component\": \"/lawyerManagement/reconciliation/lawyerDetail\",\n" +
+                    "          \"meta\": {\n" +
+                    "            \"icon\": \"Briefcase\",\n" +
+                    "            \"title\": \"对账总览\",\n" +
+                    "            \"isLink\": \"\",\n" +
+                    "            \"isHide\": true,\n" +
+                    "            \"isFull\": false,\n" +
+                    "            \"isAffix\": false,\n" +
+                    "            \"isKeepAlive\": false\n" +
+                    "          }\n" +
                     "        }\n" +
                     "      ]\n" +
                     "    },\n" +
@@ -243,6 +257,34 @@ public class SystemController {
                     "        \"isAffix\": false,\n" +
                     "        \"isKeepAlive\": false\n" +
                     "      }\n" +
+                    "    },\n" +
+                    "    {\n" +
+                    "      \"path\": \"/refund\",\n" +
+                    "      \"name\": \"refund\",\n" +
+                    "      \"component\": \"/refund/index\",\n" +
+                    "      \"meta\": {\n" +
+                    "        \"icon\": \"UserFilled\",\n" +
+                    "        \"title\": \"举报审核\",\n" +
+                    "        \"isLink\": \"\",\n" +
+                    "        \"isHide\": false,\n" +
+                    "        \"isFull\": false,\n" +
+                    "        \"isAffix\": false,\n" +
+                    "        \"isKeepAlive\": false\n" +
+                    "      }\n" +
+                    "    },\n" +
+                    "    {\n" +
+                    "      \"path\": \"/appeal\",\n" +
+                    "      \"name\": \"appeal\",\n" +
+                    "      \"component\": \"/appeal/index\",\n" +
+                    "      \"meta\": {\n" +
+                    "        \"icon\": \"UserFilled\",\n" +
+                    "        \"title\": \"申诉审核\",\n" +
+                    "        \"isLink\": \"\",\n" +
+                    "        \"isHide\": false,\n" +
+                    "        \"isFull\": false,\n" +
+                    "        \"isAffix\": false,\n" +
+                    "        \"isKeepAlive\": false\n" +
+                    "      }\n" +
                     "    }\n" +
                     "  ],\n" +
                     "  \"msg\": \"成功\"\n" +
@@ -308,7 +350,34 @@ public class SystemController {
                     "            \"isKeepAlive\": false\n" +
                     "          }\n" +
                     "        },\n" +
-                    "       \n" +
+                    "        {\n" +
+                    "          \"path\": \"/lawyerManagement/legalScene\",\n" +
+                    "          \"name\": \"legalScene\",\n" +
+                    "          \"component\": \"/lawyerManagement/legalScene/index\",\n" +
+                    "          \"meta\": {\n" +
+                    "            \"icon\": \"Briefcase\",\n" +
+                    "            \"title\": \"法律场景\",\n" +
+                    "            \"isLink\": \"\",\n" +
+                    "            \"isHide\": true,\n" +
+                    "            \"isFull\": false,\n" +
+                    "            \"isAffix\": false,\n" +
+                    "            \"isKeepAlive\": false\n" +
+                    "          }\n" +
+                    "        },\n" +
+                    "        {\n" +
+                    "          \"path\": \"/lawyerManagement/professionalField\",\n" +
+                    "          \"name\": \"professionalField\",\n" +
+                    "          \"component\": \"/lawyerManagement/professionalField/index\",\n" +
+                    "          \"meta\": {\n" +
+                    "            \"icon\": \"Briefcase\",\n" +
+                    "            \"title\": \"专业领域\",\n" +
+                    "            \"isLink\": \"\",\n" +
+                    "            \"isHide\": true,\n" +
+                    "            \"isFull\": false,\n" +
+                    "            \"isAffix\": false,\n" +
+                    "            \"isKeepAlive\": false\n" +
+                    "          }\n" +
+                    "        },\n" +
                     "        {\n" +
                     "          \"path\": \"/lawyerManagement/reconciliation\",\n" +
                     "          \"name\": \"reconciliation\",\n" +
@@ -317,6 +386,20 @@ public class SystemController {
                     "            \"icon\": \"Briefcase\",\n" +
                     "            \"title\": \"对账总览\",\n" +
                     "            \"isLink\": \"\",\n" +
+                    "            \"isHide\": true,\n" +
+                    "            \"isFull\": false,\n" +
+                    "            \"isAffix\": false,\n" +
+                    "            \"isKeepAlive\": false\n" +
+                    "          }\n" +
+                    "        },\n" +
+                    "        {\n" +
+                    "          \"path\": \"/lawyerManagement/reconciliation/lawyerDetail\",\n" +
+                    "          \"name\": \"lawyerDetail\",\n" +
+                    "          \"component\": \"/lawyerManagement/reconciliation/lawyerDetail\",\n" +
+                    "          \"meta\": {\n" +
+                    "            \"icon\": \"Briefcase\",\n" +
+                    "            \"title\": \"对账总览\",\n" +
+                    "            \"isLink\": \"\",\n" +
                     "            \"isHide\": false,\n" +
                     "            \"isFull\": false,\n" +
                     "            \"isAffix\": false,\n" +
@@ -325,8 +408,48 @@ public class SystemController {
                     "        }\n" +
                     "      ]\n" +
                     "    },\n" +
-                    "    \n" +
-                    "    \n" +
+                    "    {\n" +
+                    "      \"path\": \"/userManagement\",\n" +
+                    "      \"name\": \"userManagement\",\n" +
+                    "      \"component\": \"/userManagement/index\",\n" +
+                    "      \"meta\": {\n" +
+                    "        \"icon\": \"UserFilled\",\n" +
+                    "        \"title\": \"用户管理\",\n" +
+                    "        \"isLink\": \"\",\n" +
+                    "        \"isHide\": true,\n" +
+                    "        \"isFull\": false,\n" +
+                    "        \"isAffix\": false,\n" +
+                    "        \"isKeepAlive\": false\n" +
+                    "      }\n" +
+                    "    },\n" +
+                    "    {\n" +
+                    "      \"path\": \"/refund\",\n" +
+                    "      \"name\": \"refund\",\n" +
+                    "      \"component\": \"/refund/index\",\n" +
+                    "      \"meta\": {\n" +
+                    "        \"icon\": \"UserFilled\",\n" +
+                    "        \"title\": \"举报审核\",\n" +
+                    "        \"isLink\": \"\",\n" +
+                    "        \"isHide\": true,\n" +
+                    "        \"isFull\": false,\n" +
+                    "        \"isAffix\": false,\n" +
+                    "        \"isKeepAlive\": false\n" +
+                    "      }\n" +
+                    "    },\n" +
+                    "    {\n" +
+                    "      \"path\": \"/appeal\",\n" +
+                    "      \"name\": \"appeal\",\n" +
+                    "      \"component\": \"/appeal/index\",\n" +
+                    "      \"meta\": {\n" +
+                    "        \"icon\": \"UserFilled\",\n" +
+                    "        \"title\": \"申诉审核\",\n" +
+                    "        \"isLink\": \"\",\n" +
+                    "        \"isHide\": true,\n" +
+                    "        \"isFull\": false,\n" +
+                    "        \"isAffix\": false,\n" +
+                    "        \"isKeepAlive\": false\n" +
+                    "      }\n" +
+                    "    }\n" +
                     "  ],\n" +
                     "  \"msg\": \"成功\"\n" +
                     "}";

+ 56 - 21
alien-lawyer/src/main/java/shop/alien/lawyer/controller/LawFirmController.java

@@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.LawFirm;
+import shop.alien.entity.store.vo.LawFirmPaymentVO;
 import shop.alien.lawyer.service.LawFirmService;
 import shop.alien.util.myBaticsPlus.QueryBuilder;
 
@@ -33,10 +34,10 @@ public class LawFirmController {
 
     private final LawFirmService lawFirmService;
 
-    @ApiOperation(value = "新增律所", notes = "新增律所信息,支持同时添加收款账号列表。收款账号(payment_account)必须唯一,不能重复添加。")
+    @ApiOperation(value = "新增律所", notes = "新增律所信息,支持同时添加收款账号列表。如果统一社会信用代码(creditCode)已存在,将自动执行更新操作。收款账号(payment_account)必须唯一,不能重复添加。")
     @ApiOperationSupport(order = 1)
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "lawFirm", value = "律所信息对象,包含paymentList(收款账号列表)", dataType = "LawFirm", paramType = "body", required = true)
+            @ApiImplicitParam(name = "lawFirm", value = "律所信息对象,包含paymentList(收款账号列表)。如果creditCode已存在,将更新现有记录", dataType = "LawFirm", paramType = "body", required = true)
     })
     @PostMapping("/addLawFirm")
     public R<LawFirm> addLawFirm(@RequestBody LawFirm lawFirm) {
@@ -55,25 +56,28 @@ public class LawFirmController {
         return lawFirmService.editLawFirm(lawFirm);
     }
 
-    @ApiOperation("删除律所")
+    @ApiOperation(value = "删除律所", notes = "根据律所子表id删除收款账号。删除后如果该律所没有其他收款账号,将自动删除律所主表")
     @ApiOperationSupport(order = 3)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "律所子表ID(收款账号ID)", dataType = "Integer", paramType = "query", required = true)
+    })
     @DeleteMapping("/deleteLawFirm")
     public R<Boolean> deleteLawFirm(@RequestParam(value = "id") Integer id) {
-        log.info("LawFirmController.deleteLawFirm?id={}", id);
+        log.info("LawFirmController.deleteLawFirm?paymentId={}", id);
         return lawFirmService.deleteLawFirm(id);
     }
 
-    @ApiOperation(value = "保存或更新律所", notes = "根据是否有id判断新增或更新。注意:此接口不支持收款账号的关联操作,建议使用addLawFirm或editLawFirm接口")
-    @ApiOperationSupport(order = 4)
-    @PostMapping("/saveOrUpdate")
-    public R<LawFirm> saveOrUpdate(@RequestBody LawFirm lawFirm) {
-        log.info("LawFirmController.saveOrUpdate?lawFirm={}", lawFirm);
-        boolean result = lawFirmService.saveOrUpdate(lawFirm);
-        if (result) {
-            return R.data(lawFirm);
-        }
-        return R.fail("操作失败");
-    }
+//    @ApiOperation(value = "保存或更新律所", notes = "根据是否有id判断新增或更新。注意:此接口不支持收款账号的关联操作,建议使用addLawFirm或editLawFirm接口")
+//    @ApiOperationSupport(order = 4)
+//    @PostMapping("/saveOrUpdate")
+//    public R<LawFirm> saveOrUpdate(@RequestBody LawFirm lawFirm) {
+//        log.info("LawFirmController.saveOrUpdate?lawFirm={}", lawFirm);
+//        boolean result = lawFirmService.saveOrUpdate(lawFirm);
+//        if (result) {
+//            return R.data(lawFirm);
+//        }
+//        return R.fail("操作失败");
+//    }
 
     @ApiOperation(value = "通用列表查询", notes = "查询律所列表,包含收款账号列表(paymentList)")
     @ApiOperationSupport(order = 5)
@@ -109,9 +113,6 @@ public class LawFirmController {
             @ApiImplicitParam(name = "firmName", value = "律所名称(支持模糊查询)", dataType = "String", paramType = "query"),
             @ApiImplicitParam(name = "creditCode", value = "统一社会信用代码", dataType = "String", paramType = "query"),
             @ApiImplicitParam(name = "status", value = "律所状态, 0:禁用, 1:启用", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "certificationStatus", value = "认证状态, 0:未认证, 1:认证中, 2:已认证, 3:认证失败", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "province", value = "所属省份", dataType = "String", paramType = "query"),
-            @ApiImplicitParam(name = "city", value = "所属城市", dataType = "String", paramType = "query"),
             @ApiImplicitParam(name = "createdTime_Start", value = "创建时间开始(范围查询)", dataType = "String", paramType = "query"),
             @ApiImplicitParam(name = "createdTime_End", value = "创建时间结束(范围查询)", dataType = "String", paramType = "query")
     })
@@ -148,12 +149,12 @@ public class LawFirmController {
     @ApiOperation(value = "导出律所数据到Excel", notes = "导出律所数据到Excel文件,包含收款账号信息")
     @ApiOperationSupport(order = 8)
     @GetMapping("/export")
-    public R<String> exportLawFirm(HttpServletResponse response) {
+    public void exportLawFirm(HttpServletResponse response) throws IOException {
         log.info("LawFirmController.exportLawFirm");
-        return lawFirmService.exportLawFirm(response);
+        lawFirmService.exportLawFirm(response);
     }
 
-    @ApiOperation(value = "从Excel导入律所数据", notes = "从Excel文件导入律所数据,支持批量导入。导入时会自动校验收款账号的唯一性,重复的收款账号将导致导入失败")
+    @ApiOperation(value = "从Excel导入律所数据", notes = "从Excel文件导入律所数据,支持批量导入。导入规则:1. 按统一社会信用代码(creditCode)分组,相同信用代码的数据会自动合并;2. 相同信用代码的多行数据会合并收款账号;3. 如果统一社会信用代码已存在,将更新现有记录并合并收款账号;4. 收款账号必须全局唯一,已存在的收款账号将跳过添加")
     @ApiOperationSupport(order = 9)
     @PostMapping("/import")
     public R<String> importLawFirm(MultipartFile file) {
@@ -168,6 +169,40 @@ public class LawFirmController {
         log.info("LawFirmController.downloadTemplate");
         lawFirmService.downloadTemplate(response);
     }
+
+    @ApiOperation(value = "分页查询律所子表关联律所表", notes = "以律所子表(law_firm_payment)为主表,关联律所表(law_firm)进行分页查询")
+    @ApiOperationSupport(order = 11)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "page", value = "页数(默认1)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "size", value = "页容(默认10)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "paymentAccount", value = "收款账号(支持模糊查询)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "firmName", value = "律所名称(支持模糊查询)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "creditCode", value = "统一社会信用代码", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "status", value = "律所状态, 0:禁用, 1:启用", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "certificationStatus", value = "认证状态, 0:未认证, 1:认证中, 2:已认证, 3:认证失败", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "directorName", value = "负责人姓名(支持模糊查询)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "createdTimeStart", value = "创建时间开始(范围查询)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "createdTimeEnd", value = "创建时间结束(范围查询)", dataType = "String", paramType = "query")
+    })
+    @GetMapping("/getPaymentPageWithFirm")
+    public R<IPage<LawFirmPaymentVO>> getPaymentPageWithFirm(
+            @RequestParam(defaultValue = "1") int page,
+            @RequestParam(defaultValue = "10") int size,
+            @RequestParam(required = false) Integer firmId,
+            @RequestParam(required = false) String paymentAccount,
+            @RequestParam(required = false) String firmName,
+            @RequestParam(required = false) String creditCode,
+            @RequestParam(required = false) Integer status,
+            @RequestParam(required = false) Integer certificationStatus,
+            @RequestParam(required = false) String directorName,
+            @RequestParam(required = false) String createdTimeStart,
+            @RequestParam(required = false) String createdTimeEnd) {
+        log.info("LawFirmController.getPaymentPageWithFirm?page={},size={},firmId={},paymentAccount={},firmName={},creditCode={},status={},certificationStatus={},directorName={},createdTimeStart={},createdTimeEnd={}",
+                page, size, firmId, paymentAccount, firmName, creditCode, status, certificationStatus, directorName, createdTimeStart, createdTimeEnd);
+        int pageNum = page > 0 ? page : 1;
+        int pageSize = size > 0 ? size : 10;
+        return lawFirmService.getPaymentPageWithFirm(pageNum, pageSize, firmId, paymentAccount, firmName, creditCode, status, certificationStatus, directorName, createdTimeStart, createdTimeEnd);
+    }
 }
 
 

+ 1 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/service/LawFirmPaymentService.java

@@ -13,3 +13,4 @@ public interface LawFirmPaymentService extends IService<LawFirmPayment> {
 
 }
 
+

+ 26 - 2
alien-lawyer/src/main/java/shop/alien/lawyer/service/LawFirmService.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import org.springframework.web.multipart.MultipartFile;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.LawFirm;
+import shop.alien.entity.store.vo.LawFirmPaymentVO;
 
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
@@ -65,9 +66,9 @@ public interface LawFirmService extends IService<LawFirm> {
      * 导出律所数据到Excel
      *
      * @param response HTTP响应
-     * @return R<String> 返回文件路径或成功信息
+     * @throws IOException IO异常
      */
-    R<String> exportLawFirm(HttpServletResponse response);
+    void exportLawFirm(HttpServletResponse response) throws IOException;
 
     /**
      * 导入律所数据从Excel
@@ -99,6 +100,29 @@ public interface LawFirmService extends IService<LawFirm> {
      * @param lawFirmList 律所列表
      */
     void fillPaymentList(List<LawFirm> lawFirmList);
+
+    /**
+     * 分页查询律所子表关联律所表
+     *
+     * @param pageNum 页码
+     * @param pageSize 页容
+     * @param firmId 律所ID
+     * @param paymentAccount 收款账号(模糊查询)
+     * @param firmName 律所名称(模糊查询)
+     * @param creditCode 统一社会信用代码
+     * @param status 律所状态
+     * @param certificationStatus 认证状态
+     * @param directorName 负责人姓名(模糊查询)
+     * @param createdTimeStart 创建时间开始
+     * @param createdTimeEnd 创建时间结束
+     * @return IPage<LawFirmPaymentVO>
+     */
+    R<IPage<LawFirmPaymentVO>> getPaymentPageWithFirm(
+            int pageNum, int pageSize,
+            Integer firmId, String paymentAccount, String firmName, String creditCode,
+            Integer status, Integer certificationStatus, String directorName,
+            String createdTimeStart, String createdTimeEnd
+    );
 }
 
 

+ 2 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawFirmPaymentServiceImpl.java

@@ -25,3 +25,5 @@ public class LawFirmPaymentServiceImpl extends ServiceImpl<LawFirmPaymentMapper,
 
 }
 
+
+

+ 499 - 196
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawFirmServiceImpl.java

@@ -19,9 +19,12 @@ import shop.alien.entity.store.LawFirm;
 import shop.alien.entity.store.LawFirmPayment;
 import shop.alien.entity.store.excelVo.LawFirmExcelVo;
 import shop.alien.entity.store.excelVo.util.ExcelHeader;
+import shop.alien.entity.store.vo.LawFirmPaymentVO;
 import shop.alien.lawyer.service.LawFirmPaymentService;
 import shop.alien.lawyer.service.LawFirmService;
 import shop.alien.mapper.LawFirmMapper;
+import shop.alien.mapper.LawFirmPaymentMapper;
+import shop.alien.util.excel.EasyExcelUtil;
 
 import org.apache.poi.ss.usermodel.DateUtil;
 
@@ -50,6 +53,7 @@ public class LawFirmServiceImpl extends ServiceImpl<LawFirmMapper, LawFirm> impl
 
     private final LawFirmMapper lawFirmMapper;
     private final LawFirmPaymentService lawFirmPaymentService;
+    private final LawFirmPaymentMapper lawFirmPaymentMapper;
 
     @Override
     public R<IPage<LawFirm>> getLawFirmList(int pageNum, int pageSize, String firmName, Integer status) {
@@ -70,106 +74,214 @@ public class LawFirmServiceImpl extends ServiceImpl<LawFirmMapper, LawFirm> impl
 
     @Override
     public R<LawFirm> addLawFirm(LawFirm lawFirm) {
-        log.info("LawFirmServiceImpl.addLawFirm?lawFirm={}", lawFirm);
-
-        // 校验收款账号唯一性
+        log.info("LawFirmServiceImpl.addLawFirm?lawFirm={}, platformCommissionRatio={}", lawFirm, lawFirm.getPlatformCommissionRatio());
+        
+        // 第一步:先校验收款账号,如果 paymentAccount 在数据库中存在,不让新增
         if (lawFirm.getPaymentList() != null && !lawFirm.getPaymentList().isEmpty()) {
             for (LawFirmPayment payment : lawFirm.getPaymentList()) {
                 if (StringUtils.hasText(payment.getPaymentAccount())) {
-                    // 检查收款账号是否已存在
+                    String paymentAccount = payment.getPaymentAccount().trim();
+                    
+                    // 检查收款账号是否在数据库中存在
                     LambdaQueryWrapper<LawFirmPayment> queryWrapper = new LambdaQueryWrapper<>();
-                    queryWrapper.eq(LawFirmPayment::getPaymentAccount, payment.getPaymentAccount());
+                    queryWrapper.eq(LawFirmPayment::getPaymentAccount, paymentAccount);
                     queryWrapper.eq(LawFirmPayment::getDeleteFlag, 0);
                     long count = lawFirmPaymentService.count(queryWrapper);
                     if (count > 0) {
-                        return R.fail("收款账号[" + payment.getPaymentAccount() + "]已存在,不能重复添加");
+                        return R.fail("收款账号[" + paymentAccount + "]在数据库中已存在,不能添加");
                     }
                 }
             }
         }
-
-        // 保存主表
-        boolean result = this.save(lawFirm);
-        if (!result) {
-            return R.fail("新增失败");
+        
+        // 第二步:paymentAccount 校验通过后,检查统一社会信用代码是否已存在
+        LawFirm existingLawFirm = null;
+        if (StringUtils.hasText(lawFirm.getCreditCode())) {
+            LambdaQueryWrapper<LawFirm> creditCodeWrapper = new LambdaQueryWrapper<>();
+            creditCodeWrapper.eq(LawFirm::getCreditCode, lawFirm.getCreditCode());
+            creditCodeWrapper.eq(LawFirm::getDeleteFlag, 0);
+            existingLawFirm = this.getOne(creditCodeWrapper);
         }
-
-        // 保存子表数据
-        if (lawFirm.getPaymentList() != null && !lawFirm.getPaymentList().isEmpty()) {
-            for (LawFirmPayment payment : lawFirm.getPaymentList()) {
-                try {
+        
+        // existingLawFirm 不为空执行更新子表,否则执行新增主子表操作
+        if (existingLawFirm != null) {
+            // 更新子表操作:只更新子表数据,不更新主表
+            Integer firmId = existingLawFirm.getId();
+            log.info("统一社会信用代码[{}]已存在,只更新子表数据,律所ID={}", lawFirm.getCreditCode(), firmId);
+            
+            // 保存子表数据
+            if (lawFirm.getPaymentList() != null && !lawFirm.getPaymentList().isEmpty()) {
+                for (LawFirmPayment payment : lawFirm.getPaymentList()) {
+                    if (!StringUtils.hasText(payment.getPaymentAccount())) {
+                        continue;
+                    }
+                    
+                    String paymentAccount = payment.getPaymentAccount().trim();
+                    
+                    // 再次检查账号是否已存在(防止并发问题)
+                    LambdaQueryWrapper<LawFirmPayment> checkWrapper = new LambdaQueryWrapper<>();
+                    checkWrapper.eq(LawFirmPayment::getPaymentAccount, paymentAccount);
+                    checkWrapper.eq(LawFirmPayment::getDeleteFlag, 0);
+                    long checkCount = lawFirmPaymentService.count(checkWrapper);
+                    if (checkCount > 0) {
+                        return R.fail("收款账号[" + paymentAccount + "]在数据库中已存在,不能添加");
+                    }
+                    
+                    // 新增收款账号
+                    LawFirmPayment newPayment = new LawFirmPayment();
+                    newPayment.setFirmId(firmId);
+                    newPayment.setPaymentAccount(paymentAccount);
+                    if (StringUtils.hasText(payment.getAddress())) {
+                        newPayment.setAddress(payment.getAddress().trim());
+                    }
+                    newPayment.setDeleteFlag(0);
+                    
+                    boolean saveResult = lawFirmPaymentService.save(newPayment);
+                    if (!saveResult) {
+                        log.error("保存收款账号失败,firmId={}, paymentAccount={}", firmId, paymentAccount);
+                        return R.fail("保存收款账号失败:" + paymentAccount);
+                    }
+                    log.info("保存收款账号成功,firmId={}, paymentAccount={}, id={}", 
+                            firmId, paymentAccount, newPayment.getId());
+                }
+            }
+            
+            return R.data(existingLawFirm, "统一社会信用代码已存在,已更新收款账号列表");
+        } else {
+            // 新增主子表操作
+            // 保存主表
+            log.info("新增律所,platformCommissionRatio={}", lawFirm.getPlatformCommissionRatio());
+            boolean result = this.save(lawFirm);
+            if (!result) {
+                return R.fail("新增失败");
+            }
+            Integer firmId = lawFirm.getId();
+            
+            // 验证 platformCommissionRatio 是否保存成功
+            LawFirm savedLawFirm = this.getById(firmId);
+            if (savedLawFirm != null) {
+                log.info("保存后的律所,platformCommissionRatio={}", savedLawFirm.getPlatformCommissionRatio());
+            }
+            
+            // 保存子表数据
+            if (lawFirm.getPaymentList() != null && !lawFirm.getPaymentList().isEmpty()) {
+                for (LawFirmPayment payment : lawFirm.getPaymentList()) {
+                    if (!StringUtils.hasText(payment.getPaymentAccount())) {
+                        continue;
+                    }
+                    
+                    String paymentAccount = payment.getPaymentAccount().trim();
+                    
+                    // 再次检查账号是否已存在(防止并发问题)
+                    LambdaQueryWrapper<LawFirmPayment> checkWrapper = new LambdaQueryWrapper<>();
+                    checkWrapper.eq(LawFirmPayment::getPaymentAccount, paymentAccount);
+                    checkWrapper.eq(LawFirmPayment::getDeleteFlag, 0);
+                    long checkCount = lawFirmPaymentService.count(checkWrapper);
+                    if (checkCount > 0) {
+                        return R.fail("收款账号[" + paymentAccount + "]在数据库中已存在,不能添加");
+                    }
+                    
                     // 创建新的对象,避免污染原对象
                     LawFirmPayment newPayment = new LawFirmPayment();
-                    newPayment.setFirmId(lawFirm.getId());
-                    newPayment.setPaymentAccount(payment.getPaymentAccount().trim());
+                    newPayment.setFirmId(firmId);
+                    newPayment.setPaymentAccount(paymentAccount);
                     if (StringUtils.hasText(payment.getAddress())) {
                         newPayment.setAddress(payment.getAddress().trim());
                     }
+                    newPayment.setDeleteFlag(0);
 
                     boolean saveResult = lawFirmPaymentService.save(newPayment);
                     if (!saveResult) {
-                        log.error("保存收款账号失败,firmId={}, paymentAccount={}", lawFirm.getId(), payment.getPaymentAccount());
-                        return R.fail("保存收款账号失败:" + payment.getPaymentAccount());
+                        log.error("保存收款账号失败,firmId={}, paymentAccount={}", firmId, paymentAccount);
+                        return R.fail("保存收款账号失败:" + paymentAccount);
                     }
-                    log.info("保存收款账号成功,firmId={}, paymentAccount={}, id={}", lawFirm.getId(), payment.getPaymentAccount(), newPayment.getId());
-                } catch (Exception e) {
-                    log.error("保存收款账号异常,firmId={}, paymentAccount={}", lawFirm.getId(), payment.getPaymentAccount(), e);
-                    return R.fail("保存收款账号异常:" + e.getMessage());
+                    log.info("保存收款账号成功,firmId={}, paymentAccount={}, id={}", 
+                            firmId, paymentAccount, newPayment.getId());
                 }
             }
+            
+            return R.data(lawFirm);
         }
-        return R.data(lawFirm);
     }
 
     @Override
     public R<LawFirm> editLawFirm(LawFirm lawFirm) {
         log.info("LawFirmServiceImpl.editLawFirm?lawFirm={}", lawFirm);
-
+        
+        // 校验律所ID
         if (lawFirm.getId() == null) {
             return R.fail("律所ID不能为空");
         }
-
-        // 校验收款账号唯一性(排除当前律所的账号)
+        
+        // 检查律所是否存在
+        LawFirm existingLawFirm = this.getById(lawFirm.getId());
+        if (existingLawFirm == null || existingLawFirm.getDeleteFlag() == 1) {
+            return R.fail("律所不存在");
+        }
+        
+        // 第一步:先校验收款账号,如果 paymentAccount 在数据库中存在,不让新增或修改
         if (lawFirm.getPaymentList() != null && !lawFirm.getPaymentList().isEmpty()) {
+            // 查询当前律所下现有的收款账号记录(用于判断是新增还是更新)
+            LambdaQueryWrapper<LawFirmPayment> existingWrapper = new LambdaQueryWrapper<>();
+            existingWrapper.eq(LawFirmPayment::getFirmId, lawFirm.getId());
+            existingWrapper.eq(LawFirmPayment::getDeleteFlag, 0);
+            List<LawFirmPayment> existingPayments = lawFirmPaymentService.list(existingWrapper);
+            Map<Integer, String> existingPaymentMap = existingPayments.stream()
+                    .collect(Collectors.toMap(LawFirmPayment::getId, LawFirmPayment::getPaymentAccount));
+            
             for (LawFirmPayment payment : lawFirm.getPaymentList()) {
                 if (StringUtils.hasText(payment.getPaymentAccount())) {
-                    // 检查收款账号是否已存在(排除当前律所和当前记录)
-                    LambdaQueryWrapper<LawFirmPayment> queryWrapper = new LambdaQueryWrapper<>();
-                    queryWrapper.eq(LawFirmPayment::getPaymentAccount, payment.getPaymentAccount());
-                    queryWrapper.eq(LawFirmPayment::getDeleteFlag, 0);
-                    queryWrapper.ne(LawFirmPayment::getFirmId, lawFirm.getId());
-                    // 如果是更新操作,排除当前记录
+                    String paymentAccount = payment.getPaymentAccount().trim();
+                    
+                    // 如果是更新操作,检查账号是否被修改
                     if (payment.getId() != null) {
-                        queryWrapper.ne(LawFirmPayment::getId, payment.getId());
-                    }
-                    long count = lawFirmPaymentService.count(queryWrapper);
-                    if (count > 0) {
-                        return R.fail("收款账号[" + payment.getPaymentAccount() + "]已存在,不能重复添加");
+                        String originalAccount = existingPaymentMap.get(payment.getId());
+                        // 如果账号被修改了,需要检查新账号是否已存在
+                        if (originalAccount != null && !originalAccount.equals(paymentAccount)) {
+                            // 检查新账号是否在数据库中存在(排除当前记录)
+                            LambdaQueryWrapper<LawFirmPayment> queryWrapper = new LambdaQueryWrapper<>();
+                            queryWrapper.eq(LawFirmPayment::getPaymentAccount, paymentAccount);
+                            queryWrapper.eq(LawFirmPayment::getDeleteFlag, 0);
+                            queryWrapper.ne(LawFirmPayment::getId, payment.getId());
+                            long count = lawFirmPaymentService.count(queryWrapper);
+                            if (count > 0) {
+                                return R.fail("新收款账号数据库已存在");
+                            }
+                        }
+                    } else {
+                        // 新增操作:检查账号是否在数据库中存在
+                        LambdaQueryWrapper<LawFirmPayment> queryWrapper = new LambdaQueryWrapper<>();
+                        queryWrapper.eq(LawFirmPayment::getPaymentAccount, paymentAccount);
+                        queryWrapper.eq(LawFirmPayment::getDeleteFlag, 0);
+                        long count = lawFirmPaymentService.count(queryWrapper);
+                        if (count > 0) {
+                            return R.fail("收款账号[" + paymentAccount + "]在数据库中已存在,不能添加");
+                        }
                     }
                 }
             }
         }
-
-        // 更新主表
+        
+        // 第二步:更新主表
         boolean result = this.updateById(lawFirm);
         if (!result) {
-            return R.fail("修改失败");
+        return R.fail("修改失败");
         }
-
-        // 处理子表数据
+        
+        // 第三步:处理子表数据
         if (lawFirm.getPaymentList() != null) {
             // 查询现有的收款账号记录
             LambdaQueryWrapper<LawFirmPayment> existingWrapper = new LambdaQueryWrapper<>();
             existingWrapper.eq(LawFirmPayment::getFirmId, lawFirm.getId());
             existingWrapper.eq(LawFirmPayment::getDeleteFlag, 0);
             List<LawFirmPayment> existingPayments = lawFirmPaymentService.list(existingWrapper);
-
+            
             // 收集前端传来的收款账号ID
             Set<Integer> incomingIds = lawFirm.getPaymentList().stream()
                     .filter(p -> p.getId() != null)
                     .map(LawFirmPayment::getId)
                     .collect(Collectors.toSet());
-
+            
             // 删除不在前端列表中的记录(逻辑删除)
             for (LawFirmPayment existing : existingPayments) {
                 if (!incomingIds.contains(existing.getId())) {
@@ -177,33 +289,133 @@ public class LawFirmServiceImpl extends ServiceImpl<LawFirmMapper, LawFirm> impl
                     lawFirmPaymentService.updateById(existing);
                 }
             }
-
+            
             // 新增或更新收款账号记录
             for (LawFirmPayment payment : lawFirm.getPaymentList()) {
-                payment.setFirmId(lawFirm.getId());
-                if (payment.getId() != null) {
-                    // 更新
-                    payment.setDeleteFlag(0);
-                    lawFirmPaymentService.updateById(payment);
-                } else {
-                    // 新增
-                    payment.setDeleteFlag(0);
-                    lawFirmPaymentService.save(payment);
+                if (!StringUtils.hasText(payment.getPaymentAccount())) {
+                    continue;
+                }
+                
+                String paymentAccount = payment.getPaymentAccount().trim();
+                
+                try {
+                    if (payment.getId() != null) {
+                        // 更新:获取原始记录
+                        LawFirmPayment existingPayment = existingPayments.stream()
+                                .filter(p -> p.getId().equals(payment.getId()))
+                                .findFirst()
+                                .orElse(null);
+                        
+                        if (existingPayment != null) {
+                            String originalAccount = existingPayment.getPaymentAccount();
+                            
+                            // 如果 paymentAccount 被修改了,不更新 paymentAccount 字段,保持原值
+                            LawFirmPayment updatePayment = new LawFirmPayment();
+                            updatePayment.setId(payment.getId());
+                            updatePayment.setFirmId(lawFirm.getId());
+                            
+                            // 如果账号被修改了,保持原值;否则使用新值
+                            if (!originalAccount.equals(paymentAccount)) {
+                                updatePayment.setPaymentAccount(originalAccount); // 保持原值
+                            } else {
+                                updatePayment.setPaymentAccount(paymentAccount);
+                            }
+                            
+                            // 更新其他字段
+                            if (StringUtils.hasText(payment.getAddress())) {
+                                updatePayment.setAddress(payment.getAddress().trim());
+                            } else {
+                                updatePayment.setAddress(existingPayment.getAddress());
+                            }
+                            
+                            boolean updateResult = lawFirmPaymentService.updateById(updatePayment);
+                            if (!updateResult) {
+                                log.error("更新收款账号失败,firmId={}, paymentAccount={}, id={}", 
+                                        lawFirm.getId(), paymentAccount, payment.getId());
+                                return R.fail("更新收款账号失败:" + paymentAccount);
+                            }
+                            log.info("更新收款账号成功,firmId={}, paymentAccount={}, id={}", 
+                                    lawFirm.getId(), existingPayment.getPaymentAccount(), updatePayment.getId());
+                        }
+                    } else {
+                        // 新增:再次检查账号是否已存在(防止并发问题)
+                        LambdaQueryWrapper<LawFirmPayment> checkWrapper = new LambdaQueryWrapper<>();
+                        checkWrapper.eq(LawFirmPayment::getPaymentAccount, paymentAccount);
+                        checkWrapper.eq(LawFirmPayment::getDeleteFlag, 0);
+                        long checkCount = lawFirmPaymentService.count(checkWrapper);
+                        if (checkCount > 0) {
+                            return R.fail("收款账号[" + paymentAccount + "]在数据库中已存在,不能添加");
+                        }
+                        
+                        // 新增收款账号
+                        LawFirmPayment newPayment = new LawFirmPayment();
+                        newPayment.setFirmId(lawFirm.getId());
+                        newPayment.setPaymentAccount(paymentAccount);
+                        if (StringUtils.hasText(payment.getAddress())) {
+                            newPayment.setAddress(payment.getAddress().trim());
+                        }
+                        newPayment.setDeleteFlag(0);
+                        
+                        boolean saveResult = lawFirmPaymentService.save(newPayment);
+                        if (!saveResult) {
+                            log.error("保存收款账号失败,firmId={}, paymentAccount={}", lawFirm.getId(), paymentAccount);
+                            return R.fail("保存收款账号失败:" + paymentAccount);
+                        }
+                        log.info("保存收款账号成功,firmId={}, paymentAccount={}, id={}", 
+                                lawFirm.getId(), paymentAccount, newPayment.getId());
+                    }
+                } catch (Exception e) {
+                    log.error("处理收款账号异常,firmId={}, paymentAccount={}", lawFirm.getId(), paymentAccount, e);
+                    return R.fail("处理收款账号异常:" + e.getMessage());
                 }
             }
         }
-
+        
         return R.data(lawFirm);
     }
 
     @Override
     public R<Boolean> deleteLawFirm(Integer id) {
-        log.info("LawFirmServiceImpl.deleteLawFirm?id={}", id);
-        boolean result = this.removeById(id);
-        if (result) {
+        log.info("LawFirmServiceImpl.deleteLawFirm?paymentId={}", id);
+        
+        // 1. 根据律所子表id查询子表记录
+        LawFirmPayment payment = lawFirmPaymentService.getById(id);
+        if (payment == null || payment.getDeleteFlag() == 1) {
+            return R.fail("收款账号记录不存在或已被删除");
+        }
+        
+        Integer firmId = payment.getFirmId();
+        if (firmId == null) {
+            return R.fail("律所ID为空,无法删除");
+        }
+        
+        // 2. 删除子表记录(逻辑删除)
+        boolean deletePaymentResult = lawFirmPaymentService.removeById(id);
+        if (!deletePaymentResult) {
+            return R.fail("删除收款账号失败");
+        }
+        log.info("删除收款账号成功,paymentId={}, firmId={}", id, firmId);
+        
+        // 3. 查询该律所是否还有关联的子表(未删除的)
+        LambdaQueryWrapper<LawFirmPayment> paymentWrapper = new LambdaQueryWrapper<>();
+        paymentWrapper.eq(LawFirmPayment::getFirmId, firmId);
+        paymentWrapper.eq(LawFirmPayment::getDeleteFlag, 0);
+        long remainingPaymentCount = lawFirmPaymentService.count(paymentWrapper);
+        
+        // 4. 如果没有子表了,继续删除主表(逻辑删除)
+        if (remainingPaymentCount == 0) {
+            log.info("律所[{}]没有关联的收款账号了,删除主表", firmId);
+            boolean deleteFirmResult = this.removeById(firmId);
+            if (!deleteFirmResult) {
+                log.warn("删除律所主表失败,firmId={}", firmId);
+                return R.success("收款账号删除成功,但删除律所主表失败");
+            }
+            log.info("删除律所主表成功,firmId={}", firmId);
+            return R.success("删除成功,已同时删除律所主表");
+        } else {
+            log.info("律所[{}]还有{}个收款账号,保留主表", firmId, remainingPaymentCount);
             return R.success("删除成功");
         }
-        return R.fail("删除失败");
     }
 
     @Override
@@ -290,76 +502,33 @@ public class LawFirmServiceImpl extends ServiceImpl<LawFirmMapper, LawFirm> impl
     }
 
     @Override
-    public R<String> exportLawFirm(HttpServletResponse response) {
+    public void exportLawFirm(HttpServletResponse response) throws IOException {
         log.info("LawFirmServiceImpl.exportLawFirm");
         try {
-            // 查询所有未删除的律所
-            LambdaQueryWrapper<LawFirm> queryWrapper = new LambdaQueryWrapper<>();
-            queryWrapper.eq(LawFirm::getDeleteFlag, 0);
-            queryWrapper.orderByDesc(LawFirm::getCreatedTime);
-            List<LawFirm> lawFirmList = this.list(queryWrapper);
-
-            if (lawFirmList.isEmpty()) {
-                return R.fail("暂无数据可导出");
-            }
-
-            // 按律所名称分组
-            Map<String, List<LawFirm>> firmNameMap = lawFirmList.stream()
-                    .collect(Collectors.groupingBy(LawFirm::getFirmName));
-
-            // 转换为ExcelVo,相同律所名称的每个账号一行
-            List<LawFirmExcelVo> excelVoList = new ArrayList<>();
-            int serialNumber = 0;
-            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
-            SimpleDateFormat dateTimeFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-
-            for (Map.Entry<String, List<LawFirm>> entry : firmNameMap.entrySet()) {
-                List<LawFirm> firms = entry.getValue();
-                // 合并所有账号(从子表获取)
-                Set<String> accountSet = new HashSet<>();
-                for (LawFirm firm : firms) {
-                    LambdaQueryWrapper<LawFirmPayment> paymentWrapper = new LambdaQueryWrapper<>();
-                    paymentWrapper.eq(LawFirmPayment::getFirmId, firm.getId());
-                    paymentWrapper.eq(LawFirmPayment::getDeleteFlag, 0);
-                    List<LawFirmPayment> payments = lawFirmPaymentService.list(paymentWrapper);
-                    for (LawFirmPayment payment : payments) {
-                        if (StringUtils.hasText(payment.getPaymentAccount())) {
-                            accountSet.add(payment.getPaymentAccount());
-                        }
-                    }
-                }
-                String allPaymentAccounts = String.join(",", accountSet);
-
-                // 为每个账号创建一行(如果账号为空,至少创建一行)
-                if (firms.isEmpty()) {
-                    continue;
-                }
-
-                // 如果账号为空或只有一个账号,创建一行
-                if (allPaymentAccounts.isEmpty() || !allPaymentAccounts.contains(",")) {
-                    LawFirm firstFirm = firms.get(0);
-                    LawFirmExcelVo excelVo = convertToExcelVo(firstFirm, ++serialNumber, dateFormat, dateTimeFormat);
-                    excelVo.setPaymentAccount(allPaymentAccounts);
-                    excelVoList.add(excelVo);
-                } else {
-                    // 多个账号,每个账号一行
-                    String[] accounts = allPaymentAccounts.split(",");
-                    for (int i = 0; i < accounts.length; i++) {
-                        LawFirm firstFirm = firms.get(0);
-                        LawFirmExcelVo excelVo = convertToExcelVo(firstFirm, ++serialNumber, dateFormat, dateTimeFormat);
-                        excelVo.setPaymentAccount(accounts[i].trim());
-                        excelVoList.add(excelVo);
-                    }
-                }
+            // 使用 getPaymentPageWithFirm 的方式查询所有数据(不分页)
+            // 设置一个很大的页面大小来获取所有数据
+            Page<LawFirmPaymentVO> page = new Page<>(1, Integer.MAX_VALUE);
+            IPage<LawFirmPaymentVO> pageResult = lawFirmPaymentMapper.selectPaymentPageWithFirm(
+                    page, null, null, null, null, null, null, null, null, null
+            );
+
+            List<LawFirmPaymentVO> paymentList = pageResult.getRecords();
+
+            if (paymentList == null || paymentList.isEmpty()) {
+                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+                response.getWriter().write("暂无数据可导出");
+                return;
             }
 
-            // 生成Excel
-            generateExcelWithMerge(response, excelVoList, firmNameMap);
-
-            return R.success("导出成功");
+            // 使用 EasyExcelUtil 导出
+            EasyExcelUtil.exportExcel(response, paymentList, LawFirmPaymentVO.class, "律所列表", "律所列表");
         } catch (Exception e) {
             log.error("导出律所数据失败", e);
-            return R.fail("导出失败:" + e.getMessage());
+            if (!response.isCommitted()) {
+                response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+                response.getWriter().write("导出失败:" + e.getMessage());
+            }
+            throw new IOException("导出失败:" + e.getMessage(), e);
         }
     }
 
@@ -483,24 +652,20 @@ public class LawFirmServiceImpl extends ServiceImpl<LawFirmMapper, LawFirm> impl
             Set<String> allImportAccounts = new HashSet<>();
             Map<String, String> accountToFirmNameMap = new HashMap<>(); // 账号 -> 律所名称,用于错误提示
 
-            // 先收集所有账号,检查导入数据中的重复
+            // 先收集所有账号,检查导入数据中的重复(不允许逗号分隔)
             for (LawFirmExcelVo excelVo : excelVoList) {
                 String paymentAccount = excelVo.getPaymentAccount();
                 if (StringUtils.hasText(paymentAccount)) {
-                    // 账号可能包含多个,用逗号分隔
-                    String[] accounts = paymentAccount.split(",");
-                    for (String account : accounts) {
-                        String trimmedAccount = account.trim();
-                        if (!trimmedAccount.isEmpty()) {
-                            if (allImportAccounts.contains(trimmedAccount)) {
-                                // 发现重复账号
-                                String existingFirmName = accountToFirmNameMap.get(trimmedAccount);
-                                return R.fail(String.format("导入数据中存在重复的收款账号[%s],律所[%s]和律所[%s]使用了相同的账号,无法导入",
-                                        trimmedAccount, existingFirmName, excelVo.getFirmName()));
-                            }
-                            allImportAccounts.add(trimmedAccount);
-                            accountToFirmNameMap.put(trimmedAccount, excelVo.getFirmName());
+                    String trimmedAccount = paymentAccount.trim();
+                    if (!trimmedAccount.isEmpty()) {
+                        if (allImportAccounts.contains(trimmedAccount)) {
+                            // 发现重复账号
+                            String existingFirmName = accountToFirmNameMap.get(trimmedAccount);
+                            return R.fail(String.format("导入数据中存在重复的收款账号[%s],律所[%s]和律所[%s]使用了相同的账号,无法导入",
+                                    trimmedAccount, existingFirmName, excelVo.getFirmName()));
                         }
+                        allImportAccounts.add(trimmedAccount);
+                        accountToFirmNameMap.put(trimmedAccount, excelVo.getFirmName());
                     }
                 }
             }
@@ -537,77 +702,183 @@ public class LawFirmServiceImpl extends ServiceImpl<LawFirmMapper, LawFirm> impl
                 }
             }
 
-            // 按律所名称分组,合并账号
-            Map<String, List<LawFirmExcelVo>> firmNameMap = excelVoList.stream()
-                    .collect(Collectors.groupingBy(LawFirmExcelVo::getFirmName));
+            // 按统一社会信用代码分组,合并数据
+            // 先检查是否有空的信用代码
+            for (LawFirmExcelVo excelVo : excelVoList) {
+                if (!StringUtils.hasText(excelVo.getCreditCode())) {
+                    return R.fail("导入数据中存在空的统一社会信用代码,请检查第" + (excelVoList.indexOf(excelVo) + 2) + "行数据");
+                }
+            }
+
+            // 按统一社会信用代码分组
+            Map<String, List<LawFirmExcelVo>> creditCodeMap = excelVoList.stream()
+                    .filter(vo -> StringUtils.hasText(vo.getCreditCode()))
+                    .collect(Collectors.groupingBy(LawFirmExcelVo::getCreditCode));
 
             int successCount = 0;
             int failCount = 0;
+            int updateCount = 0;
             List<String> importErrors = new ArrayList<>();
 
-            for (Map.Entry<String, List<LawFirmExcelVo>> entry : firmNameMap.entrySet()) {
-                String firmName = entry.getKey();
+            for (Map.Entry<String, List<LawFirmExcelVo>> entry : creditCodeMap.entrySet()) {
+                String creditCode = entry.getKey();
                 List<LawFirmExcelVo> voList = entry.getValue();
 
-                // 合并账号
-                String paymentAccounts = voList.stream()
-                        .map(LawFirmExcelVo::getPaymentAccount)
-                        .filter(Objects::nonNull)
-                        .filter(acc -> !acc.trim().isEmpty())
-                        .distinct()
-                        .collect(Collectors.joining(","));
+                // 合并收款账号,并维护账号和地址的对应关系(不允许逗号分隔)
+                // 使用LinkedHashMap保持顺序,后出现的账号地址会覆盖先出现的(如果地址不为空)
+                Map<String, String> accountAddressMap = new LinkedHashMap<>();
+                for (LawFirmExcelVo vo : voList) {
+                    String paymentAccount = vo.getPaymentAccount();
+                    String address = vo.getAddress();
+                    if (StringUtils.hasText(paymentAccount)) {
+                        String trimmedAccount = paymentAccount.trim();
+                        if (!trimmedAccount.isEmpty()) {
+                            // 如果账号已存在但地址为空,且当前地址不为空,则更新地址
+                            // 如果账号不存在,直接添加
+                            if (!accountAddressMap.containsKey(trimmedAccount) || 
+                                (StringUtils.hasText(address) && !StringUtils.hasText(accountAddressMap.get(trimmedAccount)))) {
+                                accountAddressMap.put(trimmedAccount, address != null ? address.trim() : "");
+                            }
+                        }
+                    }
+                }
 
-                // 使用第一个数据作为主数据
+                // 使用第一个数据作为主数据,其他数据补充缺失字段
                 LawFirmExcelVo firstVo = voList.get(0);
                 LawFirm lawFirm = convertToLawFirm(firstVo);
-
-                // 保存主表
-                boolean saveResult = this.save(lawFirm);
-                if (!saveResult) {
-                    importErrors.add("律所[" + firmName + "]保存失败");
-                    failCount++;
-                    continue;
-                }
-
-                // 保存子表收款账号
-                if (StringUtils.hasText(paymentAccounts)) {
-                    String[] accounts = paymentAccounts.split(",");
-                    for (String account : accounts) {
-                        String trimmedAccount = account.trim();
-                        if (!trimmedAccount.isEmpty()) {
-                            LawFirmPayment payment = new LawFirmPayment();
-                            payment.setFirmId(lawFirm.getId());
-                            payment.setPaymentAccount(trimmedAccount);
-                            payment.setDeleteFlag(0);
-                            lawFirmPaymentService.save(payment);
+                
+                // 如果第一个数据缺少某些字段,尝试从其他数据中获取
+                for (int i = 1; i < voList.size(); i++) {
+                    LawFirmExcelVo otherVo = voList.get(i);
+                    // 补充缺失的字段(这里可以根据需要补充其他字段)
+                    if (!StringUtils.hasText(lawFirm.getFirmName()) && StringUtils.hasText(otherVo.getFirmName())) {
+                        lawFirm.setFirmName(otherVo.getFirmName());
+                    }
+                    if (!StringUtils.hasText(lawFirm.getPhone()) && StringUtils.hasText(otherVo.getPhone())) {
+                        lawFirm.setPhone(otherVo.getPhone());
+                    }
+                    if (!StringUtils.hasText(lawFirm.getDirectorName()) && StringUtils.hasText(otherVo.getDirectorName())) {
+                        lawFirm.setDirectorName(otherVo.getDirectorName());
+                    }
+                    if (!StringUtils.hasText(lawFirm.getDirectorPhone()) && StringUtils.hasText(otherVo.getDirectorPhone())) {
+                        lawFirm.setDirectorPhone(otherVo.getDirectorPhone());
+                    }
+                    // 补充平台佣金比例(只支持纯数字格式,不支持百分号)
+                    if (lawFirm.getPlatformCommissionRatio() == null && StringUtils.hasText(otherVo.getPlatformCommissionRatio())) {
+                        try {
+                            String ratioStr = otherVo.getPlatformCommissionRatio().trim();
+                            // 解析为整数(必须是纯数字)
+                            Integer ratio = Integer.parseInt(ratioStr);
+                            lawFirm.setPlatformCommissionRatio(ratio);
+                        } catch (Exception e) {
+                            log.warn("解析佣金比例失败:{},必须是纯数字格式", otherVo.getPlatformCommissionRatio(), e);
                         }
                     }
                 }
 
-                // 校验统一社会信用代码是否已存在
-//                LambdaQueryWrapper<LawFirm> creditCodeWrapper = new LambdaQueryWrapper<>();
-//                creditCodeWrapper.eq(LawFirm::getCreditCode, lawFirm.getCreditCode());
-//                creditCodeWrapper.eq(LawFirm::getDeleteFlag, 0);
-//                long creditCodeCount = this.count(creditCodeWrapper);
-//                if (creditCodeCount > 0) {
-//                    importErrors.add("律所[" + firmName + "]的统一社会信用代码[" + lawFirm.getCreditCode() + "]已存在");
-//                    failCount++;
-//                    continue;
-//                }
-
-                // 设置默认值
+                // 检查统一社会信用代码是否已存在
+                LambdaQueryWrapper<LawFirm> creditCodeWrapper = new LambdaQueryWrapper<>();
+                creditCodeWrapper.eq(LawFirm::getCreditCode, creditCode);
+                creditCodeWrapper.eq(LawFirm::getDeleteFlag, 0);
+                LawFirm existingLawFirm = this.getOne(creditCodeWrapper);
+                
+                boolean isUpdate = false;
+                if (existingLawFirm != null) {
+                    // 如果已存在,更新现有记录
+                    isUpdate = true;
+                    lawFirm.setId(existingLawFirm.getId());
+                    // 保留原有的一些字段(如果新数据没有提供)
+                    if (!StringUtils.hasText(lawFirm.getFirmName())) {
+                        lawFirm.setFirmName(existingLawFirm.getFirmName());
+                    }
+                    if (!StringUtils.hasText(lawFirm.getPhone())) {
+                        lawFirm.setPhone(existingLawFirm.getPhone());
+                    }
+                    if (lawFirm.getStatus() == null) {
+                        lawFirm.setStatus(existingLawFirm.getStatus());
+                    }
+                    // 如果新数据没有提供平台佣金比例,保留原有值
+                    if (lawFirm.getPlatformCommissionRatio() == null) {
+                        lawFirm.setPlatformCommissionRatio(existingLawFirm.getPlatformCommissionRatio());
+                    }
+                } else {
+                    // 设置默认值(新增时)
                 if (lawFirm.getStatus() == null) {
                     lawFirm.setStatus(1);
                 }
+                }
+                
                 if (lawFirm.getDeleteFlag() == null) {
                     lawFirm.setDeleteFlag(0);
                 }
+                
+                // 保存或更新主表
+                boolean saveResult;
+                if (isUpdate) {
+                    saveResult = this.updateById(lawFirm);
+                } else {
+                    saveResult = this.save(lawFirm);
+                }
+                
+                if (!saveResult) {
+                    importErrors.add("统一社会信用代码[" + creditCode + "]" + (isUpdate ? "更新" : "保存") + "失败");
+                    failCount++;
+                    continue;
+                }
+                
+                // 处理子表收款账号
+                if (!accountAddressMap.isEmpty()) {
+                    // 查询现有的收款账号
+                    LambdaQueryWrapper<LawFirmPayment> existingPaymentWrapper = new LambdaQueryWrapper<>();
+                    existingPaymentWrapper.eq(LawFirmPayment::getFirmId, lawFirm.getId());
+                    existingPaymentWrapper.eq(LawFirmPayment::getDeleteFlag, 0);
+                    List<LawFirmPayment> existingPayments = lawFirmPaymentService.list(existingPaymentWrapper);
+                    
+                    // 收集现有的收款账号
+                    Set<String> existingAccountSet = existingPayments.stream()
+                            .map(LawFirmPayment::getPaymentAccount)
+                            .filter(Objects::nonNull)
+                            .filter(acc -> !acc.trim().isEmpty())
+                            .collect(Collectors.toSet());
+                    
+                    // 添加新的收款账号(排除已存在的),每个账号使用其对应的地址
+                    for (Map.Entry<String, String> accountEntry : accountAddressMap.entrySet()) {
+                        String trimmedAccount = accountEntry.getKey();
+                        String address = accountEntry.getValue();
+                        
+                        if (!trimmedAccount.isEmpty() && !existingAccountSet.contains(trimmedAccount)) {
+                            // 检查账号是否已存在(全局唯一性校验)
+                            LambdaQueryWrapper<LawFirmPayment> accountWrapper = new LambdaQueryWrapper<>();
+                            accountWrapper.eq(LawFirmPayment::getPaymentAccount, trimmedAccount);
+                            accountWrapper.eq(LawFirmPayment::getDeleteFlag, 0);
+                            long accountCount = lawFirmPaymentService.count(accountWrapper);
+                            if (accountCount == 0) {
+                                // 账号不存在,可以添加
+                                LawFirmPayment payment = new LawFirmPayment();
+                                payment.setFirmId(lawFirm.getId());
+                                payment.setPaymentAccount(trimmedAccount);
+                                // 设置详细地址(使用该账号对应的地址)
+                                if (StringUtils.hasText(address)) {
+                                    payment.setAddress(address.trim());
+                                }
+                                payment.setDeleteFlag(0);
+                                lawFirmPaymentService.save(payment);
+                            } else {
+                                // 账号已存在,记录警告但不阻止导入
+                                log.warn("收款账号[{}]已存在,跳过添加", trimmedAccount);
+                            }
+                        }
+                    }
+                }
 
-                // 保存主表(已在上面保存)
-                successCount++;
+                if (isUpdate) {
+                    updateCount++;
+                } else {
+                    successCount++;
+                }
             }
 
-            String resultMsg = String.format("导入完成:成功%d条,失败%d条", successCount, failCount);
+            String resultMsg = String.format("导入完成:新增%d条,更新%d条,失败%d条", successCount, updateCount, failCount);
             if (!importErrors.isEmpty()) {
                 resultMsg += "\n失败详情:\n" + String.join("\n", importErrors);
             }
@@ -742,11 +1013,11 @@ public class LawFirmServiceImpl extends ServiceImpl<LawFirmMapper, LawFirm> impl
         String fileName = URLEncoder.encode("律所列表", "UTF-8").replaceAll("\\+", "%20");
         response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
 
-        // 输出
+        // 输出(不要关闭 response 的输出流,由容器管理)
         OutputStream outputStream = response.getOutputStream();
         workbook.write(outputStream);
+        outputStream.flush();
         workbook.close();
-        outputStream.close();
     }
 
     /**
@@ -834,9 +1105,9 @@ public class LawFirmServiceImpl extends ServiceImpl<LawFirmMapper, LawFirm> impl
         if (!StringUtils.hasText(excelVo.getFirmName())) {
             return "第" + rowIndex + "行:律所名称不能为空";
         }
-//        if (!StringUtils.hasText(excelVo.getCreditCode())) {
-//            return "第" + rowIndex + "行:统一社会信用代码不能为空";
-//        }
+        if (!StringUtils.hasText(excelVo.getCreditCode())) {
+            return "第" + rowIndex + "行:统一社会信用代码不能为空";
+        }
 //        if (!StringUtils.hasText(excelVo.getPhone())) {
 //            return "第" + rowIndex + "行:联系电话不能为空";
 //        }
@@ -847,6 +1118,20 @@ public class LawFirmServiceImpl extends ServiceImpl<LawFirmMapper, LawFirm> impl
 //            return "第" + rowIndex + "行:负责人电话不能为空";
 //        }
 
+        // 校验收款账号(不允许逗号分隔,必须是单个16位或19位账号)
+        if (StringUtils.hasText(excelVo.getPaymentAccount())) {
+            String paymentAccount = excelVo.getPaymentAccount().trim();
+            // 不允许包含逗号
+            if (paymentAccount.contains(",")) {
+                return "第" + rowIndex + "行:收款账号不允许包含逗号,每行只能填写一个账号";
+            }
+            // 校验长度(必须是16位或19位)
+            int length = paymentAccount.length();
+            if (length != 16 && length != 19) {
+                return "第" + rowIndex + "行:收款账号[" + paymentAccount + "]长度不正确,必须是16位或19位,当前为" + length + "位";
+            }
+        }
+
         // 校验邮箱格式
 //        if (StringUtils.hasText(excelVo.getEmail())) {
 //            if (!excelVo.getEmail().matches("^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$")) {
@@ -930,13 +1215,15 @@ public class LawFirmServiceImpl extends ServiceImpl<LawFirmMapper, LawFirm> impl
             }
         }
 
-        // 解析佣金比例
+        // 解析佣金比例(只支持纯数字格式,不支持百分号)
         if (StringUtils.hasText(excelVo.getPlatformCommissionRatio())) {
             try {
-                String ratio = excelVo.getPlatformCommissionRatio().replace("%", "").trim();
-                lawFirm.setPlatformCommissionRatio(new BigDecimal(ratio));
+                String ratioStr = excelVo.getPlatformCommissionRatio().trim();
+                // 解析为整数(必须是纯数字)
+                Integer ratio = Integer.parseInt(ratioStr);
+                lawFirm.setPlatformCommissionRatio(ratio);
             } catch (Exception e) {
-                log.warn("解析佣金比例失败:{}", excelVo.getPlatformCommissionRatio());
+                log.warn("解析佣金比例失败:{},必须是纯数字格式", excelVo.getPlatformCommissionRatio(), e);
             }
         }
 
@@ -1097,6 +1384,22 @@ public class LawFirmServiceImpl extends ServiceImpl<LawFirmMapper, LawFirm> impl
             lawFirm.setPaymentList(paymentList);
         });
     }
+
+    @Override
+    public R<IPage<LawFirmPaymentVO>> getPaymentPageWithFirm(
+            int pageNum, int pageSize,
+            Integer firmId, String paymentAccount, String firmName, String creditCode,
+            Integer status, Integer certificationStatus, String directorName,
+            String createdTimeStart, String createdTimeEnd) {
+        log.info("LawFirmServiceImpl.getPaymentPageWithFirm?pageNum={},pageSize={},firmId={},paymentAccount={},firmName={},creditCode={},status={},certificationStatus={},directorName={},createdTimeStart={},createdTimeEnd={}",
+                pageNum, pageSize, firmId, paymentAccount, firmName, creditCode, status, certificationStatus, directorName, createdTimeStart, createdTimeEnd);
+        
+        Page<LawFirmPaymentVO> page = new Page<>(pageNum, pageSize);
+        IPage<LawFirmPaymentVO> pageResult = lawFirmPaymentMapper.selectPaymentPageWithFirm(
+                page, firmId, paymentAccount, firmName, creditCode, status, certificationStatus, directorName, createdTimeStart, createdTimeEnd
+        );
+        return R.data(pageResult);
+    }
 }
 
 

+ 5 - 0
alien-store/src/main/java/shop/alien/store/service/impl/StoreDictServiceImpl.java

@@ -1,12 +1,17 @@
 package shop.alien.store.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import org.apache.commons.lang.StringUtils;
+import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
 import shop.alien.entity.store.StoreDictionary;
+import shop.alien.entity.store.StoreMenu;
+import shop.alien.entity.store.vo.StoreDictionaryVo;
 import shop.alien.entity.store.vo.SystemConfigVo;
 import shop.alien.mapper.StoreDictionaryMapper;
 import shop.alien.store.service.StoreDictService;

+ 0 - 1
alien-store/src/main/java/shop/alien/store/service/impl/StoreOfficialAlbumServiceImpl.java

@@ -14,7 +14,6 @@ import shop.alien.mapper.StoreImgMapper;
 import shop.alien.mapper.StoreOfficialAlbumMapper;
 import shop.alien.store.service.StoreOfficialAlbumService;
 import shop.alien.store.util.CommonConstant;
-
 import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;