Ver código fonte

客户端订单列表加入orderPriceStr

zhangchen 6 dias atrás
pai
commit
ba9a4c8612

+ 15 - 1
alien-entity/src/main/java/shop/alien/entity/store/vo/LawyerConsultationOrderVO.java

@@ -8,7 +8,6 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
-import java.math.BigDecimal;
 import java.time.LocalDate;
 import java.time.ZoneId;
 import java.time.temporal.ChronoUnit;
@@ -282,5 +281,20 @@ public class LawyerConsultationOrderVO implements Serializable {
     @TableField("pay_type")
     private  String payType;
 
+    @ApiModelProperty(value = "分钟收费-钱数")
+    private Integer chargeMinute;
+
+    @ApiModelProperty(value = "分钟收费-分钟数")
+    private Integer minuteNum;
+
+    @ApiModelProperty(value = "次数收费-钱数")
+    private Integer chargeTime;
+
+    @ApiModelProperty(value = "次数收费-次数")
+    private Integer timeNum;
+
+    @ApiModelProperty(value = "订单金额字符串(拼接后的字段)")
+    private String orderPriceStr;
+
 }
 

+ 3 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/LawyerViolationDetailVO.java

@@ -59,6 +59,9 @@ public class LawyerViolationDetailVO implements Serializable {
     @ApiModelProperty(value = "被举报用户ID")
     private String reportedUserId;
 
+    @ApiModelProperty(value = "举报用户类型(1:商户,2:用户,3:律师)")
+    private String reportingUserType;
+
     // ========== 订单信息 ==========
     @ApiModelProperty(value = "订单ID")
     private Integer orderId;

+ 6 - 1
alien-entity/src/main/java/shop/alien/mapper/LawyerConsultationOrderMapper.java

@@ -437,7 +437,11 @@ public interface LawyerConsultationOrderMapper extends BaseMapper<LawyerConsulta
             "        lea.expertise_area_info,\n" +
             "        lur.user_name client_user_name,\n" +
             "        lur.user_phone client_user_phone,\n" +
-            "        lco.order_amount - lco.consultation_fee as lawyerEarnings\n" +
+            "        lco.order_amount - lco.consultation_fee as lawyerEarnings,\n" +
+            "        lco.charge_minute,\n" +
+            "        lco.minute_num,\n" +
+            "        lco.charge_time,\n" +
+            "        lco.time_num\n" +
             "        FROM lawyer_consultation_order lco\n" +
             "        LEFT JOIN (\n" +
             "            SELECT luv1.*\n" +
@@ -659,6 +663,7 @@ public interface LawyerConsultationOrderMapper extends BaseMapper<LawyerConsulta
             "lu.head_img, " +
             "lu.nick_name, " +
             "lu.personal_introduction, " +
+            "luv.reporting_user_type, " +
             "lf.firm_name " +
             "FROM lawyer_consultation_order lco " +
             "LEFT JOIN (" +

+ 27 - 3
alien-lawyer/src/main/java/shop/alien/lawyer/controller/LawyerUserViolationController.java

@@ -229,6 +229,13 @@ public class LawyerUserViolationController {
      * <p>
      * 查询举报详情信息,包括举报的详情信息、订单的详情信息以及订单律师名字相关信息
      * </p>
+     * <p>
+     * 功能说明:
+     * 1. 通过订单ID查询订单、举报、律师关联信息
+     * 2. 校验订单是否存在以及是否存在举报记录
+     * 3. 填充举报人姓名和订单价格字符串等附加信息
+     * 4. 返回完整的举报详情信息
+     * </p>
      *
      * @param orderId 订单ID,必须大于0
      * @return 统一响应结果,包含举报详情VO对象(包含举报信息、订单信息、律师信息)
@@ -243,10 +250,10 @@ public class LawyerUserViolationController {
     @GetMapping("/getViolationDetailByOrderId")
     public R<LawyerViolationDetailVO> getViolationDetailByOrderId(
             @RequestParam(value = "orderId", required = true) Integer orderId) {
-        log.info("根据订单ID查询举报详情请求,orderId={}", orderId);
+        log.info("根据订单ID查询举报详情请求开始,orderId={}", orderId);
 
         // 参数校验
-        if (orderId == null || orderId <= 0) {
+        if (!validateOrderId(orderId)) {
             log.warn("根据订单ID查询举报详情失败:订单ID为空或无效,orderId={}", orderId);
             return R.fail("订单ID不能为空");
         }
@@ -258,9 +265,13 @@ public class LawyerUserViolationController {
                 return R.fail("订单不存在或未举报");
             }
 
-            log.info("根据订单ID查询举报详情成功,orderId={}", orderId);
+            log.info("根据订单ID查询举报详情成功,orderId={}, violationId={}, orderNumber={}",
+                    orderId, detailVO.getViolationId(), detailVO.getOrderNumber());
             return R.data(detailVO);
 
+        } catch (IllegalArgumentException e) {
+            log.warn("根据订单ID查询举报详情参数校验失败,orderId={},错误信息:{}", orderId, e.getMessage());
+            return R.fail(e.getMessage());
         } catch (RuntimeException e) {
             log.warn("根据订单ID查询举报详情业务异常,orderId={},异常信息:{}", orderId, e.getMessage());
             return R.fail(e.getMessage());
@@ -270,5 +281,18 @@ public class LawyerUserViolationController {
         }
     }
 
+    /**
+     * 校验订单ID
+     * <p>
+     * 检查订单ID是否为空或无效
+     * </p>
+     *
+     * @param orderId 订单ID
+     * @return true表示有效,false表示无效
+     */
+    private boolean validateOrderId(Integer orderId) {
+        return orderId != null && orderId > 0;
+    }
+
 }
 

+ 219 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerConsultationOrderServiceImpl.java

@@ -68,6 +68,36 @@ public class LawyerConsultationOrderServiceImpl extends ServiceImpl<LawyerConsul
      */
     private static final String SYSTEM_SENDER_ID = "system";
 
+    /**
+     * 金额单位转换:分转元
+     */
+    private static final int FEN_TO_YUAN = 100;
+
+    /**
+     * 默认价格字符串(当所有收费字段都为空时)
+     */
+    private static final String DEFAULT_PRICE_STR = "";
+
+    /**
+     * 默认格式化价格(当价格为null时)
+     */
+    private static final String DEFAULT_FORMATTED_PRICE = "0";
+
+    /**
+     * 价格格式:分钟收费
+     */
+    private static final String PRICE_FORMAT_MINUTE = "¥%s/%d分钟";
+
+    /**
+     * 价格格式:次数收费
+     */
+    private static final String PRICE_FORMAT_TIME = "¥%s/%d次";
+
+    /**
+     * 小数位数:保留2位小数
+     */
+    private static final int DECIMAL_SCALE = 2;
+
     @Value("${order.coefficients}")
     private String coefficients;
 
@@ -633,6 +663,9 @@ public class LawyerConsultationOrderServiceImpl extends ServiceImpl<LawyerConsul
 
             //填充未读消息
             fillUnreadMessage(voPage,userId);
+
+            // 设置订单价格字符串
+            setOrderPriceStrForOrderList(voPage);
         }
 
         // 判断工作日信息
@@ -1824,6 +1857,192 @@ public class LawyerConsultationOrderServiceImpl extends ServiceImpl<LawyerConsul
         return webSocketVo;
     }
 
+    /**
+     * 为订单列表设置订单价格字符串
+     * <p>
+     * 遍历订单列表,为每个订单设置orderPriceStr字段
+     * </p>
+     *
+     * @param voPage 订单列表分页对象
+     */
+    private void setOrderPriceStrForOrderList(IPage<LawyerConsultationOrderVO> voPage) {
+        if (voPage == null || CollectionUtils.isEmpty(voPage.getRecords())) {
+            return;
+        }
+
+        for (LawyerConsultationOrderVO orderVO : voPage.getRecords()) {
+            setOrderPriceStr(orderVO);
+        }
+    }
+
+    /**
+     * 设置订单价格字符串
+     * <p>
+     * 根据charge_minute、minute_num、charge_time、time_num字段设置orderPriceStr
+     * 优先级:charge_minute和minute_num > charge_time和time_num
+     * chargeMinute和chargeTime单位都是分,需要转换为元并保留两位小数,去掉尾随的0
+     * </p>
+     * <p>
+     * 处理逻辑:
+     * 1. 优先检查是否按分钟收费(chargeMinute和minuteNum都不为空)
+     * 2. 其次检查是否按次数收费(chargeTime和timeNum都不为空)
+     * 3. 如果都不满足,则设置为空字符串
+     * </p>
+     *
+     * @param orderVO 订单VO对象,不能为null
+     */
+    private void setOrderPriceStr(LawyerConsultationOrderVO orderVO) {
+        if (orderVO == null) {
+            log.warn("设置订单价格字符串失败:订单VO对象为null");
+            return;
+        }
+
+        try {
+            // 优先处理按分钟收费
+            if (isMinuteBasedCharging(orderVO)) {
+                String orderPriceStr = buildMinuteBasedPriceStr(orderVO);
+                orderVO.setOrderPriceStr(orderPriceStr);
+                log.debug("设置订单价格字符串成功(按分钟收费),chargeMinute={}, minuteNum={}, orderPriceStr={}",
+                        orderVO.getChargeMinute(), orderVO.getMinuteNum(), orderPriceStr);
+                return;
+            }
+
+            // 其次处理按次数收费
+            if (isTimeBasedCharging(orderVO)) {
+                String orderPriceStr = buildTimeBasedPriceStr(orderVO);
+                orderVO.setOrderPriceStr(orderPriceStr);
+                log.debug("设置订单价格字符串成功(按次数收费),chargeTime={}, timeNum={}, orderPriceStr={}",
+                        orderVO.getChargeTime(), orderVO.getTimeNum(), orderPriceStr);
+                return;
+            }
+
+            // 当都为空则返回空
+            orderVO.setOrderPriceStr(DEFAULT_PRICE_STR);
+            log.debug("订单价格字段都为空,设置默认空字符串");
+
+        } catch (Exception e) {
+            log.error("设置订单价格字符串异常,异常信息:{}", e.getMessage(), e);
+            // 异常时设置默认值,避免影响主流程
+            orderVO.setOrderPriceStr(DEFAULT_PRICE_STR);
+        }
+    }
+
+    /**
+     * 判断是否按分钟收费
+     * <p>
+     * 通过检查chargeMinute和minuteNum是否都不为空来判断
+     * </p>
+     *
+     * @param orderVO 订单VO对象
+     * @return true表示按分钟收费,false表示不是
+     */
+    private boolean isMinuteBasedCharging(LawyerConsultationOrderVO orderVO) {
+        return orderVO != null
+                && orderVO.getChargeMinute() != null
+                && orderVO.getMinuteNum() != null;
+    }
+
+    /**
+     * 判断是否按次数收费
+     * <p>
+     * 通过检查chargeTime和timeNum是否都不为空来判断
+     * </p>
+     *
+     * @param orderVO 订单VO对象
+     * @return true表示按次数收费,false表示不是
+     */
+    private boolean isTimeBasedCharging(LawyerConsultationOrderVO orderVO) {
+        return orderVO != null
+                && orderVO.getChargeTime() != null
+                && orderVO.getTimeNum() != null;
+    }
+
+    /**
+     * 构建按分钟收费的价格字符串
+     * <p>
+     * 格式:¥{价格}/{分钟数}分钟
+     * 例如:¥1.5/30分钟
+     * </p>
+     *
+     * @param orderVO 订单VO对象
+     * @return 格式化后的价格字符串
+     */
+    private String buildMinuteBasedPriceStr(LawyerConsultationOrderVO orderVO) {
+        // chargeMinute单位是分,需要转换为元并保留两位小数,去掉尾随的0
+        BigDecimal chargeMinuteYuan = convertFenToYuan(orderVO.getChargeMinute());
+        String priceStr = formatPrice(chargeMinuteYuan);
+        return String.format(PRICE_FORMAT_MINUTE, priceStr, orderVO.getMinuteNum());
+    }
+
+    /**
+     * 构建按次数收费的价格字符串
+     * <p>
+     * 格式:¥{价格}/{次数}次
+     * 例如:¥5/3次
+     * </p>
+     *
+     * @param orderVO 订单VO对象
+     * @return 格式化后的价格字符串
+     */
+    private String buildTimeBasedPriceStr(LawyerConsultationOrderVO orderVO) {
+        // chargeTime单位是分,需要转换为元并保留两位小数,去掉尾随的0
+        BigDecimal chargeTimeYuan = convertFenToYuan(orderVO.getChargeTime());
+        String priceStr = formatPrice(chargeTimeYuan);
+        return String.format(PRICE_FORMAT_TIME, priceStr, orderVO.getTimeNum());
+    }
+
+    /**
+     * 将分转换为元
+     * <p>
+     * 分转元,保留指定小数位数,使用四舍五入
+     * </p>
+     *
+     * @param fen 金额(分),单位:分
+     * @return 金额(元),单位:元,保留2位小数
+     */
+    private BigDecimal convertFenToYuan(Integer fen) {
+        if (fen == null) {
+            log.warn("转换分转元失败:金额为null,返回0");
+            return BigDecimal.ZERO;
+        }
+
+        if (fen < 0) {
+            log.warn("转换分转元失败:金额为负数,fen={},返回0", fen);
+            return BigDecimal.ZERO;
+        }
+
+        return BigDecimal.valueOf(fen)
+                .divide(BigDecimal.valueOf(FEN_TO_YUAN), DECIMAL_SCALE, RoundingMode.HALF_UP);
+    }
+
+    /**
+     * 格式化价格,去掉尾随的0
+     * <p>
+     * 将BigDecimal价格格式化为字符串,去掉尾随的0
+     * 例如:1.00 -> 1, 1.50 -> 1.5, 1.25 -> 1.25
+     * </p>
+     *
+     * @param price 价格(BigDecimal),可能为null
+     * @return 格式化后的价格字符串,如果price为null则返回"0"
+     */
+    private String formatPrice(BigDecimal price) {
+        if (price == null) {
+            log.debug("格式化价格:价格为null,返回默认值0");
+            return DEFAULT_FORMATTED_PRICE;
+        }
+
+        try {
+            // 去掉尾随的0
+            String formattedPrice = price.stripTrailingZeros().toPlainString();
+            log.debug("格式化价格成功,原始价格={}, 格式化后={}", price, formattedPrice);
+            return formattedPrice;
+        } catch (Exception e) {
+            log.error("格式化价格异常,price={},异常信息:{}", price, e.getMessage(), e);
+            // 异常时返回默认值
+            return DEFAULT_FORMATTED_PRICE;
+        }
+    }
+
 
 }
 

+ 381 - 53
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerUserViolationServiceImpl.java

@@ -1478,9 +1478,19 @@ public class LawyerUserViolationServiceImpl extends ServiceImpl<LawyerUserViolat
      * <p>
      * 查询举报详情信息,包括举报的详情信息、订单的详情信息以及订单律师名字相关信息
      * </p>
+     * <p>
+     * 处理流程:
+     * 1. 参数校验:订单ID必须大于0
+     * 2. 查询举报详情:通过Mapper查询订单、举报、律师关联信息
+     * 3. 校验举报信息:检查是否存在举报记录(violationId不为null)
+     * 4. 填充举报人姓名:根据举报人ID查询并设置举报人姓名
+     * 5. 设置订单价格字符串:根据收费方式格式化价格显示
+     * </p>
      *
      * @param orderId 订单ID,必须大于0
      * @return 举报详情VO对象,包含举报信息、订单信息、律师信息,如果订单不存在或未举报则返回null
+     * @throws IllegalArgumentException 当订单ID无效时抛出
+     * @throws RuntimeException        当查询异常时抛出
      * @author system
      * @since 2025-01-XX
      */
@@ -1489,37 +1499,32 @@ public class LawyerUserViolationServiceImpl extends ServiceImpl<LawyerUserViolat
         log.info("根据订单ID查询举报详情开始,orderId={}", orderId);
 
         // 参数校验
-        if (orderId == null || orderId <= 0) {
-            log.warn("根据订单ID查询举报详情失败:订单ID为空或无效,orderId={}", orderId);
-            return null;
-        }
+        validateOrderIdForViolationDetail(orderId);
 
         try {
             // 查询举报详情
-            LawyerViolationDetailVO detailVO = consultationOrderMapper.getViolationDetailByOrderId(orderId);
+            LawyerViolationDetailVO detailVO = queryViolationDetailByOrderId(orderId);
             if (detailVO == null) {
                 log.warn("根据订单ID查询举报详情:订单不存在,orderId={}", orderId);
                 return null;
             }
 
             // 检查是否存在举报信息(如果violationId为null,说明没有举报记录)
-            if (detailVO.getViolationId() == null) {
+            if (!hasViolationInfo(detailVO)) {
                 log.warn("根据订单ID查询举报详情:订单存在但没有举报信息,orderId={}", orderId);
                 return null;
             }
 
-            // 查询举报人姓名
-            if (StringUtils.isNotEmpty(detailVO.getReportingUserId())) {
-                String reportingUserName = getReportingUserNameById(detailVO.getReportingUserId());
-                detailVO.setReportingUserName(reportingUserName);
-            }
-
-            // 设置订单价格字符串
-            setOrderPriceStr(detailVO);
+            // 填充举报详情附加信息
+            fillViolationDetailAdditionalInfo(detailVO);
 
-            log.info("根据订单ID查询举报详情成功,orderId={}, violationId={}", orderId, detailVO.getViolationId());
+            log.info("根据订单ID查询举报详情成功,orderId={}, violationId={}, orderNumber={}",
+                    orderId, detailVO.getViolationId(), detailVO.getOrderNumber());
             return detailVO;
 
+        } catch (IllegalArgumentException e) {
+            log.warn("根据订单ID查询举报详情参数校验失败,orderId={},错误信息:{}", orderId, e.getMessage());
+            throw e;
         } catch (Exception e) {
             log.error("根据订单ID查询举报详情异常,orderId={},异常信息:{}", orderId, e.getMessage(), e);
             throw new RuntimeException("查询举报详情失败:" + e.getMessage(), e);
@@ -1527,102 +1532,425 @@ public class LawyerUserViolationServiceImpl extends ServiceImpl<LawyerUserViolat
     }
 
     /**
+     * 校验订单ID(用于查询举报详情)
+     * <p>
+     * 检查订单ID是否为空或无效
+     * </p>
+     *
+     * @param orderId 订单ID
+     * @throws IllegalArgumentException 当订单ID为空或无效时抛出
+     */
+    private void validateOrderIdForViolationDetail(Integer orderId) {
+        if (orderId == null) {
+            log.warn("根据订单ID查询举报详情参数校验失败:订单ID为null");
+            throw new IllegalArgumentException("订单ID不能为空");
+        }
+
+        if (orderId <= 0) {
+            log.warn("根据订单ID查询举报详情参数校验失败:订单ID无效,orderId={}", orderId);
+            throw new IllegalArgumentException("订单ID必须大于0");
+        }
+    }
+
+    /**
+     * 查询举报详情
+     * <p>
+     * 通过Mapper查询订单、举报、律师关联信息
+     * </p>
+     *
+     * @param orderId 订单ID
+     * @return 举报详情VO对象,如果订单不存在返回null
+     */
+    private LawyerViolationDetailVO queryViolationDetailByOrderId(Integer orderId) {
+        try {
+            LawyerViolationDetailVO detailVO = consultationOrderMapper.getViolationDetailByOrderId(orderId);
+            if (detailVO != null) {
+                log.debug("查询举报详情成功,orderId={}, orderNumber={}", orderId, detailVO.getOrderNumber());
+            }
+            return detailVO;
+        } catch (Exception e) {
+            log.error("查询举报详情数据库异常,orderId={},异常信息:{}", orderId, e.getMessage(), e);
+            throw new RuntimeException("查询举报详情失败:" + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 检查是否存在举报信息
+     * <p>
+     * 通过检查violationId是否为null来判断是否存在举报记录
+     * </p>
+     *
+     * @param detailVO 举报详情VO对象
+     * @return true表示存在举报信息,false表示不存在
+     */
+    private boolean hasViolationInfo(LawyerViolationDetailVO detailVO) {
+        return detailVO != null && detailVO.getViolationId() != null;
+    }
+
+    /**
+     * 填充举报详情附加信息
+     * <p>
+     * 填充举报人姓名和订单价格字符串等附加信息
+     * </p>
+     *
+     * @param detailVO 举报详情VO对象
+     */
+    private void fillViolationDetailAdditionalInfo(LawyerViolationDetailVO detailVO) {
+        if (detailVO == null) {
+            return;
+        }
+
+        // 填充举报人姓名
+        fillReportingUserName(detailVO);
+
+        // 设置订单价格字符串
+        setOrderPriceStr(detailVO);
+    }
+
+    /**
+     * 填充举报人姓名
+     * <p>
+     * 根据举报人类型和ID查询并设置举报人姓名
+     * </p>
+     *
+     * @param detailVO 举报详情VO对象
+     */
+    private void fillReportingUserName(LawyerViolationDetailVO detailVO) {
+        if (detailVO == null) {
+            return;
+        }
+
+        String reportingUserId = detailVO.getReportingUserId();
+        String reportingUserType = detailVO.getReportingUserType();
+
+        if (StringUtils.isEmpty(reportingUserId)) {
+            log.debug("举报人ID为空,无需填充举报人姓名");
+            return;
+        }
+
+        if (StringUtils.isEmpty(reportingUserType)) {
+            log.warn("举报人类型为空,无法确定查询表,reportingUserId={}", reportingUserId);
+            return;
+        }
+
+        String reportingUserName = getReportingUserNameByTypeAndId(reportingUserType, reportingUserId);
+        detailVO.setReportingUserName(reportingUserName);
+        log.debug("填充举报人姓名成功,reportingUserType={}, reportingUserId={}, reportingUserName={}",
+                reportingUserType, reportingUserId, reportingUserName);
+    }
+
+    /**
      * 金额单位转换:分转元
      */
     private static final int FEN_TO_YUAN = 100;
 
     /**
+     * 默认价格字符串(当所有收费字段都为空时)
+     */
+    private static final String DEFAULT_PRICE_STR = "";
+
+    /**
+     * 默认格式化价格(当价格为null时)
+     */
+    private static final String DEFAULT_FORMATTED_PRICE = "0";
+
+    /**
+     * 价格格式:分钟收费
+     */
+    private static final String PRICE_FORMAT_MINUTE = "¥%s/%d分钟";
+
+    /**
+     * 价格格式:次数收费
+     */
+    private static final String PRICE_FORMAT_TIME = "¥%s/%d次";
+
+    /**
+     * 小数位数:保留2位小数
+     */
+    private static final int DECIMAL_SCALE = 2;
+
+    /**
      * 设置订单价格字符串
      * <p>
      * 根据charge_minute、minute_num、charge_time、time_num字段设置orderPriceStr
      * 优先级:charge_minute和minute_num > charge_time和time_num
      * chargeMinute和chargeTime单位都是分,需要转换为元并保留两位小数,去掉尾随的0
      * </p>
+     * <p>
+     * 处理逻辑:
+     * 1. 优先检查是否按分钟收费(chargeMinute和minuteNum都不为空)
+     * 2. 其次检查是否按次数收费(chargeTime和timeNum都不为空)
+     * 3. 如果都不满足,则设置为空字符串
+     * </p>
      *
-     * @param detailVO 举报详情VO对象
+     * @param detailVO 举报详情VO对象,不能为null
      */
     private void setOrderPriceStr(LawyerViolationDetailVO detailVO) {
         if (detailVO == null) {
+            log.warn("设置订单价格字符串失败:举报详情VO对象为null");
             return;
         }
 
-        // 当charge_minute和minute_num不为空时,返回"¥charge_minute/minute_num分钟"
-        // chargeMinute单位是分,需要转换为元并保留两位小数,去掉尾随的0
-        if (detailVO.getChargeMinute() != null && detailVO.getMinuteNum() != null) {
-            BigDecimal chargeMinuteYuan = BigDecimal.valueOf(detailVO.getChargeMinute())
-                    .divide(BigDecimal.valueOf(FEN_TO_YUAN), 2, RoundingMode.HALF_UP);
-            String priceStr = formatPrice(chargeMinuteYuan);
-            String orderPriceStr = String.format("¥%s/%d分钟", priceStr, detailVO.getMinuteNum());
-            detailVO.setOrderPriceStr(orderPriceStr);
-            return;
+        try {
+            // 优先处理按分钟收费
+            if (isMinuteBasedCharging(detailVO)) {
+                String orderPriceStr = buildMinuteBasedPriceStr(detailVO);
+                detailVO.setOrderPriceStr(orderPriceStr);
+                log.debug("设置订单价格字符串成功(按分钟收费),chargeMinute={}, minuteNum={}, orderPriceStr={}",
+                        detailVO.getChargeMinute(), detailVO.getMinuteNum(), orderPriceStr);
+                return;
+            }
+
+            // 其次处理按次数收费
+            if (isTimeBasedCharging(detailVO)) {
+                String orderPriceStr = buildTimeBasedPriceStr(detailVO);
+                detailVO.setOrderPriceStr(orderPriceStr);
+                log.debug("设置订单价格字符串成功(按次数收费),chargeTime={}, timeNum={}, orderPriceStr={}",
+                        detailVO.getChargeTime(), detailVO.getTimeNum(), orderPriceStr);
+                return;
+            }
+
+            // 当都为空则返回空
+            detailVO.setOrderPriceStr(DEFAULT_PRICE_STR);
+            log.debug("订单价格字段都为空,设置默认空字符串");
+
+        } catch (Exception e) {
+            log.error("设置订单价格字符串异常,异常信息:{}", e.getMessage(), e);
+            // 异常时设置默认值,避免影响主流程
+            detailVO.setOrderPriceStr(DEFAULT_PRICE_STR);
         }
+    }
+
+    /**
+     * 判断是否按分钟收费
+     * <p>
+     * 通过检查chargeMinute和minuteNum是否都不为空来判断
+     * </p>
+     *
+     * @param detailVO 举报详情VO对象
+     * @return true表示按分钟收费,false表示不是
+     */
+    private boolean isMinuteBasedCharging(LawyerViolationDetailVO detailVO) {
+        return detailVO != null
+                && detailVO.getChargeMinute() != null
+                && detailVO.getMinuteNum() != null;
+    }
+
+    /**
+     * 判断是否按次数收费
+     * <p>
+     * 通过检查chargeTime和timeNum是否都不为空来判断
+     * </p>
+     *
+     * @param detailVO 举报详情VO对象
+     * @return true表示按次数收费,false表示不是
+     */
+    private boolean isTimeBasedCharging(LawyerViolationDetailVO detailVO) {
+        return detailVO != null
+                && detailVO.getChargeTime() != null
+                && detailVO.getTimeNum() != null;
+    }
+
+    /**
+     * 构建按分钟收费的价格字符串
+     * <p>
+     * 格式:¥{价格}/{分钟数}分钟
+     * 例如:¥1.5/30分钟
+     * </p>
+     *
+     * @param detailVO 举报详情VO对象
+     * @return 格式化后的价格字符串
+     */
+    private String buildMinuteBasedPriceStr(LawyerViolationDetailVO detailVO) {
+        // chargeMinute单位是分,需要转换为元并保留两位小数,去掉尾随的0
+        BigDecimal chargeMinuteYuan = convertFenToYuan(detailVO.getChargeMinute());
+        String priceStr = formatPrice(chargeMinuteYuan);
+        return String.format(PRICE_FORMAT_MINUTE, priceStr, detailVO.getMinuteNum());
+    }
 
-        // 当charge_time和time_num不为空时,返回"¥charge_time/time_num次"
+    /**
+     * 构建按次数收费的价格字符串
+     * <p>
+     * 格式:¥{价格}/{次数}次
+     * 例如:¥5/3次
+     * </p>
+     *
+     * @param detailVO 举报详情VO对象
+     * @return 格式化后的价格字符串
+     */
+    private String buildTimeBasedPriceStr(LawyerViolationDetailVO detailVO) {
         // chargeTime单位是分,需要转换为元并保留两位小数,去掉尾随的0
-        if (detailVO.getChargeTime() != null && detailVO.getTimeNum() != null) {
-            BigDecimal chargeTimeYuan = BigDecimal.valueOf(detailVO.getChargeTime())
-                    .divide(BigDecimal.valueOf(FEN_TO_YUAN), 2, RoundingMode.HALF_UP);
-            String priceStr = formatPrice(chargeTimeYuan);
-            String orderPriceStr = String.format("¥%s/%d次", priceStr, detailVO.getTimeNum());
-            detailVO.setOrderPriceStr(orderPriceStr);
-            return;
+        BigDecimal chargeTimeYuan = convertFenToYuan(detailVO.getChargeTime());
+        String priceStr = formatPrice(chargeTimeYuan);
+        return String.format(PRICE_FORMAT_TIME, priceStr, detailVO.getTimeNum());
+    }
+
+    /**
+     * 将分转换为元
+     * <p>
+     * 分转元,保留指定小数位数,使用四舍五入
+     * </p>
+     *
+     * @param fen 金额(分),单位:分
+     * @return 金额(元),单位:元,保留2位小数
+     */
+    private BigDecimal convertFenToYuan(Integer fen) {
+        if (fen == null) {
+            log.warn("转换分转元失败:金额为null,返回0");
+            return BigDecimal.ZERO;
+        }
+
+        if (fen < 0) {
+            log.warn("转换分转元失败:金额为负数,fen={},返回0", fen);
+            return BigDecimal.ZERO;
         }
 
-        // 当都为空则返回空
-        detailVO.setOrderPriceStr("");
+        return BigDecimal.valueOf(fen)
+                .divide(BigDecimal.valueOf(FEN_TO_YUAN), DECIMAL_SCALE, RoundingMode.HALF_UP);
     }
 
     /**
      * 格式化价格,去掉尾随的0
      * <p>
+     * 将BigDecimal价格格式化为字符串,去掉尾随的0
      * 例如:1.00 -> 1, 1.50 -> 1.5, 1.25 -> 1.25
      * </p>
      *
-     * @param price 价格(BigDecimal)
-     * @return 格式化后的价格字符串
+     * @param price 价格(BigDecimal),可能为null
+     * @return 格式化后的价格字符串,如果price为null则返回"0"
      */
     private String formatPrice(BigDecimal price) {
         if (price == null) {
-            return "0";
+            log.debug("格式化价格:价格为null,返回默认值0");
+            return DEFAULT_FORMATTED_PRICE;
+        }
+
+        try {
+            // 去掉尾随的0
+            String formattedPrice = price.stripTrailingZeros().toPlainString();
+            log.debug("格式化价格成功,原始价格={}, 格式化后={}", price, formattedPrice);
+            return formattedPrice;
+        } catch (Exception e) {
+            log.error("格式化价格异常,price={},异常信息:{}", price, e.getMessage(), e);
+            // 异常时返回默认值
+            return DEFAULT_FORMATTED_PRICE;
         }
-        // 去掉尾随的0
-        return price.stripTrailingZeros().toPlainString();
     }
 
     /**
-     * 根据用户ID获取举报人姓名
+     * 根据用户类型和ID获取举报人姓名
+     * <p>
+     * 根据用户类型直接查询对应的表,提高查询效率:
+     * 1. 律师用户(type='3'):从lawyer_user表查询name字段
+     * 2. 商户用户(type='1'):从store_user表查询nick_name字段
+     * 3. 普通用户(type='2'):从life_user表查询user_name字段
+     * </p>
      *
-     * @param userId 用户ID
-     * @return 用户姓名,如果用户不存在返回null
+     * @param userType 用户类型,1:商户,2:用户,3:律师
+     * @param userId   用户ID,不能为空
+     * @return 用户姓名,如果用户不存在或查询异常则返回null
      */
-    private String getReportingUserNameById(String userId) {
+    private String getReportingUserNameByTypeAndId(String userType, String userId) {
+        if (StringUtils.isEmpty(userType)) {
+            log.warn("获取举报人姓名失败:用户类型为空,userId={}", userId);
+            return null;
+        }
+
         if (StringUtils.isEmpty(userId)) {
+            log.warn("获取举报人姓名失败:用户ID为空,userType={}", userType);
             return null;
         }
 
         try {
-            // 查询举报人信息(可能是律师、商户或普通用户)
-            // 先尝试查询律师用户
+            // 根据用户类型直接查询对应的表,避免依次查询多张表
+            if (USER_TYPE_LAWYER.equals(userType)) {
+                // 律师用户:从lawyer_user表查询
+                return queryLawyerUserName(userId);
+            } else if (USER_TYPE_STORE.equals(userType)) {
+                // 商户用户:从store_user表查询
+                return queryStoreUserName(userId);
+            } else if (USER_TYPE_LIFE.equals(userType)) {
+                // 普通用户:从life_user表查询
+                return queryLifeUserName(userId);
+            } else {
+                log.warn("获取举报人姓名失败:未知的用户类型,userType={}, userId={}", userType, userId);
+                return null;
+            }
+
+        } catch (Exception e) {
+            log.error("获取举报人姓名异常,userType={}, userId={},异常信息:{}", userType, userId, e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * 查询律师用户姓名
+     * <p>
+     * 从lawyer_user表查询律师用户姓名
+     * </p>
+     *
+     * @param userId 用户ID
+     * @return 律师用户姓名,如果用户不存在则返回null
+     */
+    private String queryLawyerUserName(String userId) {
+        try {
             LawyerUser lawyerUser = lawyerUserMapper.selectById(userId);
-            if (lawyerUser != null) {
+            if (lawyerUser != null && StringUtils.isNotEmpty(lawyerUser.getName())) {
+                log.debug("查询律师用户姓名成功,userId={}, userName={}", userId, lawyerUser.getName());
                 return lawyerUser.getName();
             }
+            log.debug("查询律师用户姓名:用户不存在或姓名为空,userId={}", userId);
+            return null;
+        } catch (Exception e) {
+            log.error("查询律师用户姓名异常,userId={},异常信息:{}", userId, e.getMessage(), e);
+            return null;
+        }
+    }
 
-            // 查询商户用户
+    /**
+     * 查询商户用户姓名
+     * <p>
+     * 从store_user表查询商户用户昵称
+     * </p>
+     *
+     * @param userId 用户ID
+     * @return 商户用户昵称,如果用户不存在则返回null
+     */
+    private String queryStoreUserName(String userId) {
+        try {
             StoreUser storeUser = storeUserMapper.selectById(userId);
-            if (storeUser != null) {
+            if (storeUser != null && StringUtils.isNotEmpty(storeUser.getNickName())) {
+                log.debug("查询商户用户姓名成功,userId={}, userName={}", userId, storeUser.getNickName());
                 return storeUser.getNickName();
             }
+            log.debug("查询商户用户姓名:用户不存在或姓名为空,userId={}", userId);
+            return null;
+        } catch (Exception e) {
+            log.error("查询商户用户姓名异常,userId={},异常信息:{}", userId, e.getMessage(), e);
+            return null;
+        }
+    }
 
-            // 查询普通用户
+    /**
+     * 查询普通用户姓名
+     * <p>
+     * 从life_user表查询普通用户姓名
+     * </p>
+     *
+     * @param userId 用户ID
+     * @return 普通用户姓名,如果用户不存在则返回null
+     */
+    private String queryLifeUserName(String userId) {
+        try {
             LifeUser lifeUser = lifeUserMapper.selectById(userId);
-            if (lifeUser != null) {
+            if (lifeUser != null && StringUtils.isNotEmpty(lifeUser.getUserName())) {
+                log.debug("查询普通用户姓名成功,userId={}, userName={}", userId, lifeUser.getUserName());
                 return lifeUser.getUserName();
             }
-
+            log.debug("查询普通用户姓名:用户不存在或姓名为空,userId={}", userId);
             return null;
         } catch (Exception e) {
-            log.error("获取举报人姓名异常,userId={},异常信息:{}", userId, e.getMessage(), e);
+            log.error("查询普通用户姓名异常,userId={},异常信息:{}", userId, e.getMessage(), e);
             return null;
         }
     }