Bladeren bron

Merge remote-tracking branch 'origin/store-plantform' into store-plantform

zjy 2 weken geleden
bovenliggende
commit
dc26fb7dd6
49 gewijzigde bestanden met toevoegingen van 992 en 114 verwijderingen
  1. 4 0
      alien-entity/src/main/java/shop/alien/entity/store/CommentAppeal.java
  2. 4 1
      alien-entity/src/main/java/shop/alien/entity/store/LawyerConsultationOrder.java
  3. 2 2
      alien-entity/src/main/java/shop/alien/entity/store/LawyerUser.java
  4. 4 1
      alien-entity/src/main/java/shop/alien/entity/store/LifeCoupon.java
  5. 3 3
      alien-entity/src/main/java/shop/alien/entity/store/LifeDiscountCoupon.java
  6. 65 0
      alien-entity/src/main/java/shop/alien/entity/store/OcrImageUpload.java
  7. 3 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/CommentAppealVo.java
  8. 4 1
      alien-entity/src/main/java/shop/alien/entity/store/vo/LawyerConsultationOrderVO.java
  9. 2 2
      alien-entity/src/main/java/shop/alien/entity/store/vo/LawyerUserVo.java
  10. 3 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/OrderReviewVo.java
  11. 12 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreCashOutRecordVo.java
  12. 3 0
      alien-entity/src/main/java/shop/alien/mapper/LawyerConsultationOrderMapper.java
  13. 16 0
      alien-entity/src/main/java/shop/alien/mapper/OcrImageUploadMapper.java
  14. 8 0
      alien-entity/src/main/java/shop/alien/mapper/OrderReviewMapper.java
  15. 7 0
      alien-entity/src/main/java/shop/alien/mapper/StoreClockInMapper.java
  16. 7 8
      alien-entity/src/main/resources/mapper/CommentAppealMapper.xml
  17. 10 0
      alien-entity/src/main/resources/mapper/LawyerConsultationOrderMapper.xml
  18. 30 0
      alien-entity/src/main/resources/mapper/OrderReviewMapper.xml
  19. 1 1
      alien-gateway/src/main/java/shop/alien/gateway/controller/SystemController.java
  20. 5 1
      alien-job/src/main/java/shop/alien/job/store/LawyerOrderJob.java
  21. 14 1
      alien-lawyer/src/main/java/shop/alien/lawyer/controller/AliController.java
  22. 4 0
      alien-lawyer/src/main/java/shop/alien/lawyer/controller/LawyerUserLogInController.java
  23. 38 9
      alien-lawyer/src/main/java/shop/alien/lawyer/controller/OrderReviewController.java
  24. 18 2
      alien-lawyer/src/main/java/shop/alien/lawyer/service/OrderReviewService.java
  25. 35 17
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/CommentAppealServiceImpl.java
  26. 2 7
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerClientConsultationOrderServiceImpl.java
  27. 3 3
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerUserServiceImpl.java
  28. 8 0
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderExpirationServiceImpl.java
  29. 98 26
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderReviewServiceImpl.java
  30. 96 0
      alien-lawyer/src/main/java/shop/alien/lawyer/util/ali/AliApi.java
  31. 14 1
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/LifeCouponPlatformController.java
  32. 1 1
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/CouponManageServiceImpl.java
  33. 10 3
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/IncomeManageServiceImpl.java
  34. 12 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/LifeCouponPlatformServiceImpl.java
  35. 9 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/LifeDiscountCouponPlatformServiceImpl.java
  36. 6 6
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformLoginServiceImpl.java
  37. 20 1
      alien-store/src/main/java/shop/alien/store/controller/AliController.java
  38. 14 0
      alien-store/src/main/java/shop/alien/store/service/LifeUserStoreService.java
  39. 96 0
      alien-store/src/main/java/shop/alien/store/service/OcrImageUploadService.java
  40. 6 0
      alien-store/src/main/java/shop/alien/store/service/StoreClockInService.java
  41. 2 2
      alien-store/src/main/java/shop/alien/store/service/impl/LawyerUserServiceImpl.java
  42. 98 0
      alien-store/src/main/java/shop/alien/store/service/impl/OcrImageUploadServiceImpl.java
  43. 10 0
      alien-store/src/main/java/shop/alien/store/service/impl/StoreClockInServiceImpl.java
  44. 15 10
      alien-store/src/main/java/shop/alien/store/util/ali/AliApi.java
  45. 15 1
      alien-store/src/main/java/shop/alien/store/util/ali/ocr/AbstractOcrStrategy.java
  46. 19 0
      alien-store/src/main/java/shop/alien/store/util/ali/ocr/OcrStrategy.java
  47. 44 3
      alien-store/src/main/java/shop/alien/store/util/ali/ocr/strategy/BusinessLicenseOcrStrategy.java
  48. 43 0
      alien-store/src/main/java/shop/alien/store/util/ali/ocr/strategy/FoodManageLicenseOcrStrategy.java
  49. 49 1
      alien-store/src/main/java/shop/alien/store/util/ali/ocr/strategy/IdCardOcrStrategy.java

+ 4 - 0
alien-entity/src/main/java/shop/alien/entity/store/CommentAppeal.java

@@ -92,5 +92,9 @@ public class CommentAppeal extends Model<CommentAppeal> {
     @ApiModelProperty(value = "申诉人id")
     @TableField("lawyer_user_id")
     private String lawyerUserId;
+
+    @ApiModelProperty(value = "订单ID")
+    @TableField("order_id")
+    private Integer orderId;
 }
 

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

@@ -8,7 +8,6 @@ import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
-import java.math.BigDecimal;
 import java.util.Date;
 
 /**
@@ -169,6 +168,10 @@ public class LawyerConsultationOrder extends Model<LawyerConsultationOrder> {
     @TableField("reject_refund_reason")
     private String rejectRefundReason;
 
+    @ApiModelProperty(value = "是否已被申诉, 0:未申诉, 1:已申诉, 2:申诉中")
+    @TableField("is_appealed")
+    private Integer isAppealed;
+
     @ApiModelProperty(value = "退款申请处理动作:1-同意,2-拒绝")
     @TableField(exist = false)
     private String processAction;

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

@@ -211,9 +211,9 @@ public class LawyerUser extends Model<LawyerUser> {
     @TableField("id_card_back_image")
     private String idCardBackImage;
 
-    @ApiModelProperty(value = "服务评分, 0-5分")
+    @ApiModelProperty(value = "服务评分, 0-5分(保留一位小数)")
     @TableField("service_score")
-    private Integer serviceScore;
+    private Double serviceScore;
 
     @ApiModelProperty(value = "服务次数")
     @TableField("service_count")

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

@@ -56,17 +56,20 @@ public class LifeCoupon {
     private Integer expirationDate;
 
     @ApiModelProperty(value = "开始日期")
-    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8" )
+    @TableField(value = "start_date", fill = FieldFill.UPDATE)
     private Date startDate;
 
     @ApiModelProperty(value = "结束日期")
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
+    @TableField(value = "end_date", fill = FieldFill.UPDATE)
     private Date endDate;
 
     @ApiModelProperty(value = "不可用时间")
     private String unusedDate;
 
     @ApiModelProperty(value = "优惠券数量")
+    @TableField(value = "single_qty", fill = FieldFill.UPDATE)
     private Integer singleQty;
 
     @ApiModelProperty(value = "限制购买数")

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

@@ -42,7 +42,7 @@ public class LifeDiscountCoupon extends Model<LifeDiscountCoupon> {
     private String name;
 
     @ApiModelProperty(value = "面值")
-    @TableField("nominal_value")
+    @TableField(value = "nominal_value", fill = FieldFill.UPDATE)
     private BigDecimal nominalValue;
 
     @ApiModelProperty(value = "有效期(天)")
@@ -58,7 +58,7 @@ public class LifeDiscountCoupon extends Model<LifeDiscountCoupon> {
     private LocalDate endDate;
 
     @ApiModelProperty(value = "库存(优惠券数量)")
-    @TableField("single_qty")
+    @TableField(value = "single_qty", fill = FieldFill.UPDATE)
     private Integer singleQty;
 
     @ApiModelProperty(value = "补充说明")
@@ -74,7 +74,7 @@ public class LifeDiscountCoupon extends Model<LifeDiscountCoupon> {
     private Integer restrictedQuantity;
 
     @ApiModelProperty(value = "最低消费")
-    @TableField("minimum_spending_amount")
+    @TableField(value = "minimum_spending_amount", fill = FieldFill.UPDATE)
     private BigDecimal minimumSpendingAmount;
 
     @ApiModelProperty(value = "类型   1-优惠券  2-红包 3-平台优惠券")

+ 65 - 0
alien-entity/src/main/java/shop/alien/entity/store/OcrImageUpload.java

@@ -0,0 +1,65 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+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;
+
+/**
+ * OCR图片上传记录表
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude
+@TableName("ocr_image_uploads")
+@ApiModel(value = "OcrImageUpload对象", description = "OCR图片上传记录表")
+public class OcrImageUpload implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "用户ID(上传图片的用户唯一标识)")
+    @TableField("user_id")
+    private String userId;
+
+    @ApiModelProperty(value = "店铺ID(若图片关联具体店铺,可为NULL表示无店铺关联)")
+    @TableField("store_id")
+    private String storeId;
+
+    @ApiModelProperty(value = "店铺用户ID(店铺内上传图片的操作员ID,与store_id配套使用)")
+    @TableField("store_user_id")
+    private String storeUserId;
+
+    @ApiModelProperty(value = "图片存储路径(本地路径或云存储URL,如OSS / S3地址)")
+    @TableField("image_url")
+    private String imageUrl;
+
+    @ApiModelProperty(value = "OCR识别结果(JSON格式或纯文本,存储识别后的文字内容)")
+    @TableField("ocr_result")
+    private String ocrResult;
+
+    @ApiModelProperty(value = "OCR识别类型")
+    @TableField("ocr_type")
+    private String ocrType;
+
+    @ApiModelProperty(value = "图片上传时间")
+    @TableField(value = "create_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+    @ApiModelProperty(value = "记录更新时间(如OCR状态变更时间)")
+    @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
+}
+

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

@@ -139,5 +139,8 @@ public class CommentAppealVo implements Serializable {
 
     @ApiModelProperty(value = "申诉单号")
     private String appealNumber;
+
+    @ApiModelProperty(value = "订单ID")
+    private Integer orderId;
 }
 

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

@@ -114,7 +114,7 @@ public class LawyerConsultationOrderVO implements Serializable {
     private Integer certificationStatus;
 
     @ApiModelProperty(value = "服务评分, 0-5分")
-    private Integer serviceScore;
+    private Double serviceScore;
 
     @ApiModelProperty(value = "服务次数")
     private Integer serviceCount;
@@ -248,6 +248,9 @@ public class LawyerConsultationOrderVO implements Serializable {
     @ApiModelProperty(value = "律师接单状态")
     private int orderReceivingStatus;
 
+    @ApiModelProperty(value = "申诉处理状态 0 审核中 1审核通过 2驳回")
+    private String commentStatus;
+
 
     /**
      * 获取执业年限(根据执业开始日期自动计算)

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

@@ -173,9 +173,9 @@ public class LawyerUserVo implements Serializable {
     @TableField("id_card_back_image")
     private String idCardBackImage;
 
-    @ApiModelProperty(value = "服务评分, 0-5分")
+    @ApiModelProperty(value = "服务评分, 0-5分(保留一位小数)")
     @TableField("service_score")
-    private Integer serviceScore;
+    private Double serviceScore;
 
     @ApiModelProperty(value = "服务次数")
     @TableField("service_count")

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

@@ -88,5 +88,8 @@ public class OrderReviewVo {
 
     @ApiModelProperty(value = "逻辑删除")
     private Integer deleteFlag;
+
+    @ApiModelProperty(value = "订单申诉状态")
+    private Integer isAppealed;
 }
 

+ 12 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreCashOutRecordVo.java

@@ -35,4 +35,16 @@ public class StoreCashOutRecordVo extends StoreCashOutRecord {
 
     @ApiModelProperty(value = "收益记录")
     private JSONArray incomeList;
+
+    @ApiModelProperty(value = "当前页码")
+    private Long currentPage;
+
+    @ApiModelProperty(value = "每页条数")
+    private Long pageSize;
+
+    @ApiModelProperty(value = "总记录数")
+    private Long total;
+
+    @ApiModelProperty(value = "总页数")
+    private Long totalPages;
 }

+ 3 - 0
alien-entity/src/main/java/shop/alien/mapper/LawyerConsultationOrderMapper.java

@@ -351,12 +351,15 @@ public interface LawyerConsultationOrderMapper extends BaseMapper<LawyerConsulta
             "        luv.processing_status,\n" +
             "        luv.processing_time,\n" +
             "        lur.user_image,\n" +
+            "        cas.status as commentStatus,\n" +
             "        luv.report_result\n" +
             "        FROM lawyer_consultation_order lco\n" +
             "        LEFT JOIN lawyer_user lu ON lco.lawyer_user_id = lu.id AND lu.delete_flag = 0\n" +
             "        LEFT JOIN law_firm lf on lf.id = lu.firm_id\n" +
             "        left join lawyer_expertise_area lea on lea.id = lu.lawyer_expertise_area_id and lea.delete_flag = 0 " +
             "        left join life_user lur on lur.id = lco.client_user_id " +
+            "        left join lawyer_order_review lor on lor.order_id = lco.id " +
+            "        left join comment_appeals cas on cas.comment_id = lor.id and cas.delete_flag = 0  " +
             "        left join lawyer_user_violation luv on luv.order_number = lco.order_number and luv.delete_flag = 0 " +
             " ${ew.customSqlSegment}")
     IPage<LawyerConsultationOrderVO> getLawyerConsultationOrderInfo(

+ 16 - 0
alien-entity/src/main/java/shop/alien/mapper/OcrImageUploadMapper.java

@@ -0,0 +1,16 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.OcrImageUpload;
+
+/**
+ * OCR图片上传记录 Mapper 接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Mapper
+public interface OcrImageUploadMapper extends BaseMapper<OcrImageUpload> {
+}
+

+ 8 - 0
alien-entity/src/main/java/shop/alien/mapper/OrderReviewMapper.java

@@ -128,5 +128,13 @@ public interface OrderReviewMapper extends BaseMapper<OrderReview> {
      * @return 有图评价数量
      */
     Integer getImageReviewCountByLawyerUserId(@Param("lawyerUserId") Integer lawyerUserId);
+
+    /**
+     * 根据订单ID查询关联评价
+     *
+     * @param orderId 订单ID
+     * @return 评价信息
+     */
+    OrderReviewVo getOrderEvaluation(@Param("orderId") Integer orderId);
 }
 

+ 7 - 0
alien-entity/src/main/java/shop/alien/mapper/StoreClockInMapper.java

@@ -50,4 +50,11 @@ public interface StoreClockInMapper extends BaseMapper<StoreClockIn> {
      */
     @Select("SELECT store_id as storeId, count(store_id) as count FROM `store_clock_in` where delete_flag = 0 GROUP BY store_id ")
     List<Map<Integer, Integer>> getStoreClockInCount();
+     /**
+      * 获取所有店铺打卡次数(有图片并且设置为可见的)
+      *
+      * @return map
+      */
+    @Select("SELECT store_id as storeId, count(store_id) as count FROM `store_clock_in` where delete_flag = 0 and permission = 1 and img_url is not null GROUP BY store_id ")
+    List<Map<Integer, Integer>> getStoreClockInWithCanLookCount();
 }

+ 7 - 8
alien-entity/src/main/resources/mapper/CommentAppealMapper.xml

@@ -15,6 +15,7 @@
         <result column="updated_time" property="updatedTime" />
         <result column="updated_user_id" property="updatedUserId" />
         <result column="appeal_time" property="appealTime" />
+        <result column="order_id" property="orderId" />
     </resultMap>
 
     <!-- 申诉历史列表查询结果映射 -->
@@ -52,6 +53,7 @@
         <result column="lawyer_user_id" property="lawyerUserId" />
         <result column="lawyer_name" property="lawyerName" />
         <result column="lawyer_phone" property="lawyerPhone" />
+        <result column="order_id" property="orderId" />
     </resultMap>
 
     <!-- 查询申诉历史列表(包含评价和用户信息) -->
@@ -71,11 +73,9 @@
             ca.updated_time,
             ca.updated_user_id,
             ca.updated_user_id AS audit_user_id,
+            ca.order_id,
             orv.user_id AS review_user_id,
-            CASE
-                WHEN orv.is_anonymous = 1 THEN '匿名用户'
-                ELSE lu.user_name
-            END AS user_name,
+            lu.user_name,
             CASE
                 WHEN orv.is_anonymous = 1 THEN NULL
                 ELSE lu.user_image
@@ -118,11 +118,9 @@
             ca.updated_user_id,
             ca.updated_user_id AS audit_user_id,
             ca.appeal_number,
+            ca.order_id,
             orv.user_id AS review_user_id,
-            CASE
-                WHEN orv.is_anonymous = 1 THEN '匿名用户'
-                ELSE lu.user_name
-            END AS review_user_name,
+            lu.user_name AS review_user_name,
             CASE
                 WHEN orv.is_anonymous = 1 THEN NULL
                 ELSE lu.user_image
@@ -159,6 +157,7 @@
             ca.updated_time,
             ca.updated_user_id,
             ca.updated_user_id AS audit_user_id,
+            ca.order_id,
             orv.order_number,
             orv.user_id AS review_user_id,
             CASE

+ 10 - 0
alien-entity/src/main/resources/mapper/LawyerConsultationOrderMapper.xml

@@ -29,6 +29,16 @@
         <result column="alipay_no" property="alipayNo" />
         <result column="order_str" property="orderStr" />
         <result column="place_id" property="placeId" />
+        <result column="lawyer_earnings" property="lawyerEarnings" />
+        <result column="accept_orders_time" property="acceptOrdersTime" />
+        <result column="reason_order_refusal" property="reasonOrderRefusal" />
+        <result column="accept_orders_status" property="acceptOrdersStatus" />
+        <result column="apply_refund_status" property="applyRefundStatus" />
+        <result column="apply_refund_time" property="applyRefundTime" />
+        <result column="apply_refund_process_time" property="applyRefundProcessTime" />
+        <result column="apply_refund_reason" property="applyRefundReason" />
+        <result column="reject_refund_reason" property="rejectRefundReason" />
+        <result column="is_appealed" property="isAppealed" />
     </resultMap>
 
     <!-- 通用查询结果列 -->

+ 30 - 0
alien-entity/src/main/resources/mapper/OrderReviewMapper.xml

@@ -25,6 +25,7 @@
         <result column="comment_count" property="commentCount" />
         <result column="is_liked" property="isLiked" />
         <result column="created_time" property="createdTime" />
+        <result column="is_appealed" property="isAppealed" />
     </resultMap>
 
     <!-- 分页查询评价列表(包含用户和律师信息) -->
@@ -210,6 +211,7 @@
         LEFT JOIN lawyer_order_review orv ON orv.order_id = lco.id AND orv.delete_flag = 0
         WHERE lco.delete_flag = 0
         AND lco.order_status = 3
+        AND lco.is_appealed = 0
         AND lco.client_user_id = #{userId}
         AND orv.id IS NULL
         ORDER BY lco.end_time DESC
@@ -361,5 +363,33 @@
         ORDER BY orv.created_time DESC
     </select>
 
+    <!-- 根据订单ID查询评价 -->
+    <select id="getOrderEvaluation" resultMap="OrderReviewVoResultMap">
+        SELECT
+            orv.id,
+            orv.order_id,
+            orv.order_number,
+            orv.user_id,
+            orv.lawyer_user_id,
+            orv.overall_rating,
+            orv.service_attitude_rating,
+            orv.response_time_rating,
+            orv.professional_ability_rating,
+            orv.review_content,
+            orv.review_images,
+            orv.is_anonymous,
+            orv.like_count,
+            orv.comment_count,
+            orv.created_time,
+            lco.is_appealed,
+            lu.user_name
+        FROM lawyer_order_review orv
+        INNER JOIN lawyer_consultation_order lco ON lco.id = orv.order_id AND lco.delete_flag = 0
+        LEFT JOIN life_user lu ON lu.id = orv.user_id AND lu.delete_flag = 0
+        WHERE orv.delete_flag = 0
+        AND orv.order_id = #{orderId}
+        LIMIT 1
+    </select>
+
 </mapper>
 

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

@@ -60,7 +60,7 @@ public class SystemController {
     @ApiOperation(value = "web中台退出登录", notes = "用户退出登录,清除Redis中的token缓存")
     @ApiOperationSupport(order = 2)
     @PostMapping(value = "/logout")
-    public R<SystemLoginVo> logout(@ApiIgnore @TokenInfo UserLoginInfo userLoginInfo) {
+    public R<SystemLoginVo> logout(@RequestBody UserLoginInfo userLoginInfo) {
         log.info("SystemController.logout?userId={}, userName={}", 
                 userLoginInfo != null ? userLoginInfo.getUserId() : null,
                 userLoginInfo != null ? userLoginInfo.getUserName() : null);

+ 5 - 1
alien-job/src/main/java/shop/alien/job/store/LawyerOrderJob.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.xxl.job.core.context.XxlJobHelper;
 import com.xxl.job.core.handler.annotation.XxlJob;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
@@ -38,8 +39,10 @@ public class LawyerOrderJob {
      */
     @XxlJob("acceptOrderStatus")
     @Transactional(rollbackFor = Exception.class)
-    public void acceptOrderStatus(String param) {
+    public void acceptOrderStatus() {
+        String param = XxlJobHelper.getJobParam();
         if (StringUtils.isNotEmpty(param)) {
+            log.info("开始执行测试待接单订单超时处理任务");
             LambdaQueryWrapper<LawyerConsultationOrder> lambdaQueryWrapper = new LambdaQueryWrapper<LawyerConsultationOrder>()
                     .eq(LawyerConsultationOrder::getOrderStatus, 2)
                     .eq(LawyerConsultationOrder::getDeleteFlag, 0);
@@ -50,6 +53,7 @@ public class LawyerOrderJob {
                 lawyerConsultationOrderLambdaUpdateWrapper.set(LawyerConsultationOrder::getOrderStatus, 3)
                         .in(LawyerConsultationOrder::getId, collect);
                 lawyerConsultationOrderMapper.update(null, lawyerConsultationOrderLambdaUpdateWrapper);
+                log.info("待接单订单超时处理完成,处理数量:{}", collect.size());
             }
         } else {
             log.info("开始执行待接单订单超时处理任务");

+ 14 - 1
alien-lawyer/src/main/java/shop/alien/lawyer/controller/AliController.java

@@ -6,7 +6,6 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.web.bind.annotation.*;
 import shop.alien.entity.result.R;
-import shop.alien.entity.store.StoreAliPayLog;
 import shop.alien.lawyer.util.AliSms;
 import shop.alien.lawyer.util.ali.AliApi;
 
@@ -89,4 +88,18 @@ public class AliController {
                                 @RequestParam(value = "partialRefundCode") String partialRefundCode) {
         return R.data(aliApi.processRefund(outTradeNo, refundAmount, refundReason, partialRefundCode));
     }
+
+
+
+    @ApiOperation("根据订单号查询订单支付状态")
+    @ApiOperationSupport(order = 15)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "outTradeNo", value = "订单号", dataType = "String", paramType = "query", required = true),
+    })
+    @GetMapping("/queryPayment")
+    public R<String> queryPayment(String outTradeNo)  {
+
+        return aliApi.queryPayment(outTradeNo);
+    }
+
 }

+ 4 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/controller/LawyerUserLogInController.java

@@ -70,6 +70,10 @@ public class LawyerUserLogInController {
         if (lawyerUser.getStatus() == 0) {
             return R.fail("账号被禁用");
         }
+        LawyerUser lawyerUser1 = new LawyerUser();
+        lawyerUser1.setId(lawyerUser.getId());
+        lawyerUser1.setIsOnline(1);
+        lawyerUserMapper.updateById(lawyerUser1);
         return Optional.ofNullable(lawyerUser).
                 map(user -> lawyerUserDto.getIsPassword() ? checkPassword(user, lawyerUserDto.getPassword()) : lawyerUserService.createToKen(user)).
                 orElseGet(() -> R.fail("手机号不存在"));

+ 38 - 9
alien-lawyer/src/main/java/shop/alien/lawyer/controller/OrderReviewController.java

@@ -119,22 +119,36 @@ public class OrderReviewController {
         return orderReviewService.getReviewList(page, size, orderId, lawyerUserId, userId, currentUserId);
     }
 
-    @ApiOperation("删除评价(删除评价时,会级联删除该评价下的所有评论和回复)")
+    @ApiOperation("用户删除评价(只能删除自己的评价,删除评价时,会级联删除该评价下的所有评论和回复)")
     @ApiOperationSupport(order = 4)
     @ApiImplicitParams({
             @ApiImplicitParam(name = "reviewId", value = "评价ID", dataType = "int", paramType = "query", required = true),
-            @ApiImplicitParam(name = "userId", value = "用户ID(可选,有值时只能删除自己的评价,为空时允许删除任何评价)", dataType = "int", paramType = "query", required = false)
+            @ApiImplicitParam(name = "userId", value = "用户ID(必填,只能删除自己的评价)", dataType = "int", paramType = "query", required = true)
     })
     @PostMapping("/delete/reviewId")
     public R<Boolean> deleteReview(@RequestParam Integer reviewId,
-                                   @RequestParam(required = false) Integer userId) {
+                                   @RequestParam Integer userId) {
         log.info("OrderReviewController.deleteReview?reviewId={}, userId={}", reviewId, userId);
+        if (userId == null) {
+            return R.fail("用户ID不能为空");
+        }
         return orderReviewService.deleteReview(reviewId, userId);
     }
 
-    @ApiOperation("根据订单ID查询评价")
+    @ApiOperation("管理员删除评价(可以删除任何评价,删除评价时,会级联删除该评价下的所有评论和回复)")
     @ApiOperationSupport(order = 5)
     @ApiImplicitParams({
+            @ApiImplicitParam(name = "reviewId", value = "评价ID", dataType = "int", paramType = "query", required = true)
+    })
+    @PostMapping("/admin/delete/reviewId")
+    public R<Boolean> deleteReviewByAdmin(@RequestParam Integer reviewId) {
+        log.info("OrderReviewController.deleteReviewByAdmin?reviewId={}", reviewId);
+        return orderReviewService.deleteReviewByAdmin(reviewId);
+    }
+
+    @ApiOperation("根据订单ID查询评价")
+    @ApiOperationSupport(order = 6)
+    @ApiImplicitParams({
             @ApiImplicitParam(name = "orderId", value = "订单ID", dataType = "int", paramType = "query", required = true),
             @ApiImplicitParam(name = "currentUserId", value = "当前用户ID(用于判断是否已点赞)", dataType = "int", paramType = "query")
     })
@@ -148,7 +162,7 @@ public class OrderReviewController {
 
 
     @ApiOperation("分页查询我的评价列表")
-    @ApiOperationSupport(order = 6)
+    @ApiOperationSupport(order = 7)
     @ApiImplicitParams({
             @ApiImplicitParam(name = "page", value = "页数(默认1)", dataType = "int", paramType = "query"),
             @ApiImplicitParam(name = "size", value = "页容(默认10)", dataType = "int", paramType = "query"),
@@ -167,7 +181,7 @@ public class OrderReviewController {
     }
 
     @ApiOperation("分页查询我的评价列表(查询当前用户的所有评价)")
-    @ApiOperationSupport(order = 7)
+    @ApiOperationSupport(order = 8)
     @ApiImplicitParams({
             @ApiImplicitParam(name = "page", value = "页数(默认1)", dataType = "int", paramType = "query"),
             @ApiImplicitParam(name = "size", value = "页容(默认10)", dataType = "int", paramType = "query"),
@@ -188,7 +202,7 @@ public class OrderReviewController {
     }
 
     @ApiOperation("获取律师评价统计数据(全部数量、好评数量、中评数量、差评数量、有图数量)")
-    @ApiOperationSupport(order = 9)
+    @ApiOperationSupport(order = 10)
     @ApiImplicitParams({
             @ApiImplicitParam(name = "lawyerUserId", value = "律师用户ID", dataType = "int", paramType = "query", required = true)
     })
@@ -202,7 +216,7 @@ public class OrderReviewController {
     }
 
     @ApiOperation("根据律师ID分页查询评价列表(查询指定律师的所有评价)")
-    @ApiOperationSupport(order = 10)
+    @ApiOperationSupport(order = 11)
     @ApiImplicitParams({
             @ApiImplicitParam(name = "page", value = "页数(默认1)", dataType = "int", paramType = "query"),
             @ApiImplicitParam(name = "size", value = "页容(默认10)", dataType = "int", paramType = "query"),
@@ -224,7 +238,7 @@ public class OrderReviewController {
     }
 
     @ApiOperation("根据律师ID和类型分页查询评价列表(不包含评论)")
-    @ApiOperationSupport(order = 11)
+    @ApiOperationSupport(order = 12)
     @ApiImplicitParams({
             @ApiImplicitParam(name = "page", value = "页数(默认1)", dataType = "int", paramType = "query"),
             @ApiImplicitParam(name = "size", value = "页容(默认10)", dataType = "int", paramType = "query"),
@@ -246,5 +260,20 @@ public class OrderReviewController {
         }
         return orderReviewService.getReviewListByLawyerAndType(page, size, lawyerUserId, type, currentUserId);
     }
+
+    @ApiOperation("根据订单ID查询订单关联的评价")
+    @ApiOperationSupport(order = 13)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "orderId", value = "订单ID", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/getByOrderId")
+    public R<OrderReviewVo> queryReviewByOrderId(
+            @RequestParam Integer orderId) {
+        log.info("OrderReviewController.queryReviewByOrderId?orderId={}", orderId);
+        if (orderId == null) {
+            return R.fail("订单ID不能为空");
+        }
+        return orderReviewService.getOrderEvaluation(orderId);
+    }
 }
 

+ 18 - 2
alien-lawyer/src/main/java/shop/alien/lawyer/service/OrderReviewService.java

@@ -68,15 +68,23 @@ public interface OrderReviewService extends IService<OrderReview> {
 
 
     /**
-     * 删除评价(删除评价时,会级联删除该评价下的所有评论和回复)
+     * 用户删除评价(只能删除自己的评价,删除评价时,会级联删除该评价下的所有评论和回复)
      *
      * @param reviewId 评价ID
-     * @param userId 用户ID(可选,有值时只能删除自己的评价,为空时允许删除任何评价)
+     * @param userId 用户ID(必填,只能删除自己的评价)
      * @return R<Boolean>
      */
     R<Boolean> deleteReview(Integer reviewId, Integer userId);
 
     /**
+     * 管理员删除评价(可以删除任何评价,删除评价时,会级联删除该评价下的所有评论和回复)
+     *
+     * @param reviewId 评价ID
+     * @return R<Boolean>
+     */
+    R<Boolean> deleteReviewByAdmin(Integer reviewId);
+
+    /**
      * 根据订单ID查询评价
      *
      * @param orderId 订单ID
@@ -126,5 +134,13 @@ public interface OrderReviewService extends IService<OrderReview> {
      */
     R<shop.alien.entity.store.vo.LawyerReviewStatisticsVo> getLawyerReviewStatistics(Integer lawyerUserId);
 
+    /**
+     * 根据订单ID查询关联评价
+     *
+     * @param orderId 订单ID
+     * @return R<OrderReviewVo>
+     */
+    R<OrderReviewVo> getOrderEvaluation(Integer orderId);
+
 }
 

+ 35 - 17
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/CommentAppealServiceImpl.java

@@ -46,6 +46,7 @@ public class CommentAppealServiceImpl extends ServiceImpl<CommentAppealMapper, C
     private final OrderReviewMapper orderReviewMapper;
     private final LifeUserMapper lifeUserMapper;
     private final LawyerUserMapper lawyerUserMapper;
+    private final LawyerConsultationOrderMapper lawyerConsultationOrderMapper;
 
 
     @Override
@@ -70,6 +71,14 @@ public class CommentAppealServiceImpl extends ServiceImpl<CommentAppealMapper, C
             return R.fail("该评论已有申诉记录,无法重复申诉");
         }
 
+        // 如果orderId为空,从OrderReview中获取
+        if (commentAppeal.getOrderId() == null) {
+            OrderReview orderReview = orderReviewMapper.selectById(commentAppeal.getCommentId());
+            if (orderReview != null && orderReview.getOrderId() != null) {
+                commentAppeal.setOrderId(orderReview.getOrderId());
+            }
+        }
+
         // 设置默认值
         commentAppeal.setStatus(0); // 待处理
         if (commentAppeal.getDeleteFlag() == null) {
@@ -81,9 +90,18 @@ public class CommentAppealServiceImpl extends ServiceImpl<CommentAppealMapper, C
         if (result) {
             log.info("提交申诉成功,id={}", commentAppeal.getId());
             
+            // 更新订单表的申诉状态为2(申诉中)
+            if (commentAppeal.getOrderId() != null) {
+                LambdaUpdateWrapper<LawyerConsultationOrder> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+                lambdaUpdateWrapper.eq(LawyerConsultationOrder::getId, commentAppeal.getOrderId())
+                        .set(LawyerConsultationOrder::getIsAppealed, 2);
+                lawyerConsultationOrderMapper.update(null, lambdaUpdateWrapper);
+                log.info("更新订单申诉状态成功,orderId={}, isAppealed=2", commentAppeal.getOrderId());
+            }
+
             // 发送通知给评价用户,告知其评价被申诉了
             sendSubmitAppealNotification(commentAppeal);
-            
+
             return R.data(commentAppeal, "申诉提交成功");
         } else {
             return R.fail("申诉提交失败");
@@ -152,7 +170,7 @@ public class CommentAppealServiceImpl extends ServiceImpl<CommentAppealMapper, C
             // 如果申诉通过,删除评价及该评价下的所有评论和回复
             if (status == 1) {
 //                deleteReviewAndRelatedData(appeal.getCommentId());
-                orderReviewService.deleteReview(appeal.getCommentId(),null);
+                orderReviewService.deleteReviewByAdmin(appeal.getCommentId());
             }
 
             // 发送通知
@@ -173,21 +191,21 @@ public class CommentAppealServiceImpl extends ServiceImpl<CommentAppealMapper, C
         try {
             // 查询律师用户信息
             LambdaQueryWrapper<LawyerUser> lawyerUser = new LambdaQueryWrapper<>();
-            lawyerUser.eq(LawyerUser :: getId, appeal.getLawyerUserId());
+            lawyerUser.eq(LawyerUser::getId, appeal.getLawyerUserId());
             LawyerUser lifeUser = lawyerUserMapper.selectOne(lawyerUser);
             if (lifeUser == null) {
                 log.warn("评价用户不存在,userId={}", lifeUser.getId());
                 return;
             }
             LambdaQueryWrapper<OrderReview> orderReviewLambdaQueryWrapper = new LambdaQueryWrapper<>();
-            orderReviewLambdaQueryWrapper.eq(OrderReview ::  getId, appeal.getCommentId());
+            orderReviewLambdaQueryWrapper.eq(OrderReview::getId, appeal.getCommentId());
             OrderReview orderReview = orderReviewMapper.selectOne(orderReviewLambdaQueryWrapper);
             String orderNumber = "";
-            if(orderReview != null){
+            if (orderReview != null) {
                 orderNumber = orderReview.getOrderNumber();
             }
             String receiverId = "user_" + lifeUser.getPhone();
-            String message = String.format("您提交的差评申诉信息,订单编号为"+ orderNumber +",已提交至平台审核,1-3个工作日会发送您审核结果,请注意查收。");
+            String message = String.format("您提交的差评申诉信息,订单编号为" + orderNumber + ",已提交至平台审核,1-3个工作日会发送您审核结果,请注意查收。");
 
             LifeNotice lifeNotice = new LifeNotice();
             lifeNotice.setReceiverId(receiverId);
@@ -253,7 +271,7 @@ public class CommentAppealServiceImpl extends ServiceImpl<CommentAppealMapper, C
             }
 
             String receiverId = "user_" + lifeUser.getUserPhone();
-            String message = String.format("您对订单编号为"+ orderReview.getOrderNumber() +"的评价,律师已进行申诉,经核实,您的评价不实,平台已删除此条评价及回复。");
+            String message = String.format("您对订单编号为" + orderReview.getOrderNumber() + "的评价,律师已进行申诉,经核实,您的评价不实,平台已删除此条评价及回复。");
 
             LifeNotice lifeNotice = new LifeNotice();
             lifeNotice.setReceiverId(receiverId);
@@ -296,9 +314,9 @@ public class CommentAppealServiceImpl extends ServiceImpl<CommentAppealMapper, C
             // 律师的接收ID格式可能是 "lawyer_" + phone 或其他格式,需要根据实际情况调整
             String receiverId = "lawyer_" + lawyerUser.getPhone();
             String title = isSuccess ? "申诉成功通知" : "申诉失败通知";
-            String message = isSuccess 
-                    ? String.format("您的编号"+ orderReview.getOrderNumber() +"的订单,提交的差评申诉信息,经核实,评价内容不实,平台已删除此条评价。")
-                    : String.format("您的编号"+ orderReview.getOrderNumber() +"的订单,提交的差评申诉信息,经核实,评价内容属实。失败原因:"+ reviewReasons +"。");
+            String message = isSuccess
+                    ? String.format("您的编号" + orderReview.getOrderNumber() + "的订单,提交的差评申诉信息,经核实,评价内容不实,平台已删除此条评价。")
+                    : String.format("您的编号" + orderReview.getOrderNumber() + "的订单,提交的差评申诉信息,经核实,评价内容属实。失败原因:" + reviewReasons + "。");
 
             LifeNotice lifeNotice = new LifeNotice();
             lifeNotice.setReceiverId(receiverId);
@@ -347,8 +365,8 @@ public class CommentAppealServiceImpl extends ServiceImpl<CommentAppealMapper, C
 
     @Override
     public R<IPage<CommentAppealVo>> getAppealPage(Integer pageNum, Integer pageSize, Integer status,
-                                                     String orderNumber, String userName, String userPhone, String lawyerName, String lawyerPhone,
-                                                     String startTime, String endTime) {
+                                                   String orderNumber, String userName, String userPhone, String lawyerName, String lawyerPhone,
+                                                   String startTime, String endTime) {
         log.info("CommentAppealServiceImpl.getAppealPage?pageNum={}, pageSize={}, status={}, orderNumber={}, userName={}, userPhone={}, lawyerName={}, lawyerPhone={}, startTime={}, endTime={}",
                 pageNum, pageSize, status, orderNumber, userName, userPhone, lawyerName, lawyerPhone, startTime, endTime);
 
@@ -526,11 +544,11 @@ public class CommentAppealServiceImpl extends ServiceImpl<CommentAppealMapper, C
                 pageNum, pageSize, status, lawyerUserId);
         List<CommentAppealVo> appealList = new ArrayList<>();
         //status 3 查全部
-        if(status ==3){
-            appealList  = baseMapper.getAppealHistoryList(null, lawyerUserId);
-        }else{
+        if (status == 3) {
+            appealList = baseMapper.getAppealHistoryList(null, lawyerUserId);
+        } else {
             // 查询申诉历史列表
-            appealList  = baseMapper.getAppealHistoryList(status, lawyerUserId);
+            appealList = baseMapper.getAppealHistoryList(status, lawyerUserId);
         }
 
         // 处理数据转换(图片列表等)
@@ -539,7 +557,7 @@ public class CommentAppealServiceImpl extends ServiceImpl<CommentAppealMapper, C
         }
 
         ListToPage.setPage(appealList, pageNum, pageSize);
-        
+
         return appealList;
     }
 }

+ 2 - 7
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerClientConsultationOrderServiceImpl.java

@@ -1,5 +1,7 @@
 package shop.alien.lawyer.service.impl;
 
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
 import com.alibaba.nacos.common.utils.CollectionUtils;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -9,7 +11,6 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang.math.RandomUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
@@ -17,28 +18,22 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.StringUtils;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.*;
-import shop.alien.entity.store.dto.LawyerConsultationOrderDto;
-import shop.alien.entity.store.dto.PayStatusRequest;
 import shop.alien.entity.store.vo.LawyerConsultationOrderVO;
 import shop.alien.entity.store.vo.WebSocketVo;
 import shop.alien.lawyer.config.WebSocketProcess;
 import shop.alien.lawyer.feign.AlienStoreFeign;
 import shop.alien.lawyer.service.LawyerClientConsultationOrderService;
-import shop.alien.lawyer.service.LawyerConsultationOrderService;
 import shop.alien.lawyer.service.LawyerUserService;
 import shop.alien.lawyer.service.OrderExpirationService;
 import shop.alien.mapper.*;
 import shop.alien.util.common.constant.LawyerStatusEnum;
 import shop.alien.util.common.constant.OrderActionType;
-import com.alibaba.fastjson2.JSON;
-import com.alibaba.fastjson2.JSONObject;
 
 import java.text.SimpleDateFormat;
 import java.time.LocalDateTime;
 import java.time.ZoneId;
 import java.util.*;
 import java.util.stream.Collectors;
-import java.util.Objects;
 
 /**
  * 咨询订单 服务实现类

+ 3 - 3
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerUserServiceImpl.java

@@ -137,8 +137,8 @@ public class LawyerUserServiceImpl extends ServiceImpl<LawyerUserMapper, LawyerU
         result.put("education", lawyer.getEducationBackground() != null ? lawyer.getEducationBackground() : "");
         result.put("credentials", new ArrayList<>());  // TODO: 需要查询资质证书
         result.put("caseCount", lawyer.getServiceCount() != null ? lawyer.getServiceCount() : 0);
-        // 评分:服务评分已经是0-5分,直接转换为Double类型
-        result.put("rating", lawyer.getServiceScore() != null ? lawyer.getServiceScore().doubleValue() : 0.0);
+        // 评分:服务评分已经是0-5分(保留一位小数),直接使用
+        result.put("rating", lawyer.getServiceScore() != null ? lawyer.getServiceScore() : 0.0);
         result.put("reviewCount", lawyer.getGoodReviewCount() != null ?
                 (lawyer.getGoodReviewCount() + (lawyer.getMediumReviewCount() != null ? lawyer.getMediumReviewCount() : 0) +
                         (lawyer.getBadReviewCount() != null ? lawyer.getBadReviewCount() : 0)) : 0);
@@ -360,7 +360,7 @@ public class LawyerUserServiceImpl extends ServiceImpl<LawyerUserMapper, LawyerU
 
         // 如果昵称不为空,添加昵称模糊查询条件
         if (nickName != null && !nickName.trim().isEmpty()) {
-            queryWrapper.like("name", nickName.trim());
+            queryWrapper.like("nick_name", nickName.trim());
         }
 
         // 排序:优先推荐律师 -> 在线律师 -> 注册时间

+ 8 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderExpirationServiceImpl.java

@@ -181,6 +181,14 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
 
                 // 處理訂單退款
                 String refundResult = aliController.processRefund(order.getAlipayNo(), new BigDecimal(order.getOrderAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString(), refundReason, "");
+
+                // 微信/支付宝退款
+                /*paramMap.put("payType", "1".equals(order.getPayType()) ? PaymentEnum.ALIPAY.getType() : PaymentEnum.WECHAT_PAY.getType());
+                paramMap.put("outTradeNo", order.getAlipayNo());
+                paramMap.put("refundReason", refundReason);
+                paramMap.put("refundAmount", new BigDecimal(order.getOrderAmount()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP).toString());
+                R refunds = alienStoreFeign.paymentRefunds(paramMap);*/
+
                 if ("调用成功".equals(refundResult)) {
                     log.info("訂單退款成功,訂單no: {}", orderNo);
 

+ 98 - 26
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderReviewServiceImpl.java

@@ -128,7 +128,7 @@ public class OrderReviewServiceImpl extends ServiceImpl<OrderReviewMapper, Order
             log.info("创建评价成功,评价ID={}", review.getId());
             // 更新律师评分
             updateLawyerServiceScore(review.getLawyerUserId());
-            return R.data(review, "评价成功");
+            return R.data(review, "提交成功");
         } else {
             log.error("创建评价失败");
             return R.fail("创建评价失败");
@@ -151,17 +151,17 @@ public class OrderReviewServiceImpl extends ServiceImpl<OrderReviewMapper, Order
         try {
             // 计算平均评分(1-5星)
             Double averageRating = orderReviewMapper.getAverageRatingByLawyerUserId(lawyerUserId);
-
-            Integer serviceScore;
+            
+            Double serviceScore;
             if (averageRating != null) {
-                // 转换为0-5分:service_score = averageRating(四舍五入)
-                serviceScore = (int) Math.round(averageRating);
+                // 转换为0-5分,保留一位小数(直接截取,不四舍五入)
+                serviceScore = Math.floor(averageRating * 10.0) / 10.0;
                 // 确保在0-5范围内
-                serviceScore = Math.max(0, Math.min(5, serviceScore));
+                serviceScore = Math.max(0.0, Math.min(5.0, serviceScore));
             } else {
-                // 如果没有评价,设置为0
-                serviceScore = 0;
-                log.info("律师暂无评价,将评分设置为0,律师ID={}", lawyerUserId);
+                // 如果没有评价,设置为0.0
+                serviceScore = 0.0;
+                log.info("律师暂无评价,将评分设置为0.0,律师ID={}", lawyerUserId);
             }
 
             // 统计好评、中评、差评数量
@@ -294,19 +294,52 @@ public class OrderReviewServiceImpl extends ServiceImpl<OrderReviewMapper, Order
             return R.fail("评价ID不能为空");
         }
 
+        if (userId == null) {
+            return R.fail("用户ID不能为空");
+        }
+
         // 查询评价
         OrderReview review = this.getById(reviewId);
         if (review == null) {
             return R.fail("评价不存在");
         }
 
-        // 当userId有值时,验证是否为评价用户(只能删除自己的评价)
-        if (userId != null) {
-            if (!review.getUserId().equals(userId)) {
-                return R.fail("只能删除自己的评价");
-            }
+        // 验证是否为评价用户(只能删除自己的评价)
+        if (!review.getUserId().equals(userId)) {
+            return R.fail("只能删除自己的评价");
+        }
+
+        return deleteReviewInternal(reviewId, userId, review);
+    }
+
+    @Override
+    public R<Boolean> deleteReviewByAdmin(Integer reviewId) {
+        log.info("OrderReviewServiceImpl.deleteReviewByAdmin?reviewId={}", reviewId);
+
+        if (reviewId == null) {
+            return R.fail("评价ID不能为空");
         }
 
+
+        // 查询评价
+        OrderReview review = this.getById(reviewId);
+        if (review == null) {
+            return R.fail("评价不存在");
+        }
+
+        return deleteReviewInternal(reviewId, null, review);
+    }
+
+    /**
+     * 内部删除评价方法(删除评价时,会级联删除该评价下的所有评论和回复)
+     *
+     * @param reviewId 评价ID
+     * @param userId 用户ID(可为null,管理员删除时为空)
+     * @param review 评价对象
+     * @return R<Boolean>
+     */
+    private R<Boolean> deleteReviewInternal(Integer reviewId, Integer userId, OrderReview review) {
+
         // 查询该评价下的所有评论
         LambdaQueryWrapper<ReviewComment> commentWrapper = new LambdaQueryWrapper<>();
         commentWrapper.eq(ReviewComment::getReviewId, reviewId)
@@ -314,18 +347,9 @@ public class OrderReviewServiceImpl extends ServiceImpl<OrderReviewMapper, Order
         List<ReviewComment> comments = reviewCommentService.list(commentWrapper);
 
         // 删除评价(逻辑删除)
-//        review.setDeleteFlag(1);
-//        review.setUpdatedUserId(userId);
-//        review.setUpdatedTime(new Date());
-//        boolean success = this.updateById(review);
-
-
-        LambdaUpdateWrapper<OrderReview> updateWrapper = new LambdaUpdateWrapper<>();
-        updateWrapper.eq(OrderReview::getId, reviewId);
-        updateWrapper.set(OrderReview::getDeleteFlag, 1);
-         int num = orderReviewMapper.update(null, updateWrapper);
+        int num = orderReviewMapper.deleteById(reviewId);
 
-        if (num>0) {
+        if (num > 0) {
             // 级联删除该评价下的所有评论和回复
             for (ReviewComment comment : comments) {
                 // 删除评论下的所有回复(逻辑删除)
@@ -352,8 +376,27 @@ public class OrderReviewServiceImpl extends ServiceImpl<OrderReviewMapper, Order
             // 更新律师评分
             updateLawyerServiceScore(review.getLawyerUserId());
 
+            // 管理员删除时,更新订单的 is_appealed 字段为 1
+            if (userId == null && review.getOrderId() != null) {
+                try {
+                    LambdaUpdateWrapper<LawyerConsultationOrder> orderUpdateWrapper = new LambdaUpdateWrapper<>();
+                    orderUpdateWrapper.eq(LawyerConsultationOrder::getId, review.getOrderId())
+                            .set(LawyerConsultationOrder::getIsAppealed, 1);
+                    int updateResult = lawyerConsultationOrderMapper.update(null, orderUpdateWrapper);
+                    if (updateResult > 0) {
+                        log.info("管理员删除评价时,已更新订单的申诉状态,评价ID={}, 订单ID={}", reviewId, review.getOrderId());
+                    } else {
+                        log.warn("管理员删除评价时,更新订单申诉状态失败,评价ID={}, 订单ID={}", reviewId, review.getOrderId());
+                    }
+                } catch (Exception e) {
+                    log.error("管理员删除评价时,更新订单申诉状态异常,评价ID={}, 订单ID={}, 错误信息={}", 
+                            reviewId, review.getOrderId(), e.getMessage(), e);
+                    // 更新订单申诉状态失败不影响删除评价的操作
+                }
+            }
+
             if (userId != null) {
-                log.info("删除评价成功,评价ID={}, 操作人ID={}", reviewId, userId);
+                log.info("用户删除评价成功,评价ID={}, 操作人ID={}", reviewId, userId);
             } else {
                 log.info("管理员删除评价成功,评价ID={}", reviewId);
             }
@@ -618,5 +661,34 @@ public class OrderReviewServiceImpl extends ServiceImpl<OrderReviewMapper, Order
             return R.fail("获取统计数据失败");
         }
     }
+
+    @Override
+    public R<OrderReviewVo> getOrderEvaluation(Integer orderId) {
+        log.info("OrderReviewServiceImpl.getOrderEvaluation?orderId={}", orderId);
+
+        if (orderId == null) {
+            return R.fail("订单ID不能为空");
+        }
+
+        OrderReviewVo reviewVo = orderReviewMapper.getOrderEvaluation(orderId);
+        if (reviewVo == null) {
+            return R.fail("该订单暂无评价");
+        }
+
+        // 处理评价图片:从JSON字符串解析为List
+        if (reviewVo.getReviewImagesJson() != null && !reviewVo.getReviewImagesJson().trim().isEmpty()) {
+            try {
+                List<String> images = JSON.parseArray(reviewVo.getReviewImagesJson(), String.class);
+                reviewVo.setReviewImages(images != null ? images : new ArrayList<>());
+            } catch (Exception e) {
+                log.warn("解析评价图片失败:{}", e.getMessage());
+                reviewVo.setReviewImages(new ArrayList<>());
+            }
+        } else {
+            reviewVo.setReviewImages(new ArrayList<>());
+        }
+
+        return R.data(reviewVo);
+    }
 }
 

+ 96 - 0
alien-lawyer/src/main/java/shop/alien/lawyer/util/ali/AliApi.java

@@ -15,6 +15,7 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
+import shop.alien.entity.result.R;
 import shop.alien.entity.store.*;
 import shop.alien.lawyer.service.StoreAliPayRefundLogService;
 import shop.alien.lawyer.service.StoreAliPayErrorLogService;
@@ -22,6 +23,7 @@ import shop.alien.util.common.UniqueRandomNumGenerator;
 import shop.alien.util.common.UrlEncode;
 import shop.alien.util.system.OSUtil;
 
+import java.io.UnsupportedEncodingException;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -310,6 +312,100 @@ private final StoreAliPayErrorLogService storeAliPayErrorLogService;
 
 
 
+//   public R<String> queryPayment(String outTradeNo) {
+//
+//       try {
+//           AlipayClient alipayClient = new DefaultAlipayClient(setAlipayConfig(null));
+//           // 2. 构造查询请求
+//           AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
+//           // 设置biz_content(JSON格式)
+//           String bizContent = "{\"out_trade_no\":\" "+outTradeNo+"\"}";
+//           request.setBizContent(bizContent);
+//           // 3. 调用接口并获取响应
+//           AlipayTradeQueryResponse response = alipayClient.certificateExecute(request);
+//           if (response.isSuccess()) {
+//               // 4. 解析支付状态
+//               String tradeStatus = response.getTradeStatus();
+//               log.info("订单查询成功,支付状态:" + tradeStatus);
+//
+//               // 支付状态说明:
+//               // WAIT_BUYER_PAY:等待买家付款
+//               // TRADE_CLOSED:交易关闭(超时未支付/已取消)
+//               // TRADE_SUCCESS:支付成功(即时到账/普通转账)
+//               // TRADE_FINISHED:交易完成(不可退款的场景,如即时到账)
+//                if ("TRADE_SUCCESS".equals(tradeStatus)){
+//                    return  R.success("支付成功");
+//                }
+//           } else {
+//               System.out.println();
+//
+//               return R.fail("订单查询失败:" + response.getMsg() + "(" + response.getSubMsg() + ")");
+//           }
+//       } catch (AlipayApiException e) {
+//           e.printStackTrace();
+//       }
+//       return R.fail("支付失败");
+//    }
+
+
+    public R<String> queryPayment(String outTradeNo, String tradeNo) {
+        try {
+            AlipayClient alipayClient = new DefaultAlipayClient(setAlipayConfig(null));
+            // 2. 构造查询请求
+            AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
+
+            // 设置biz_content(JSON格式)
+            JSONObject bizContent = new JSONObject();
+            if (StringUtils.isNotBlank(outTradeNo)) {
+                bizContent.put("out_trade_no", outTradeNo);
+            }
+//            if (StringUtils.isNotBlank(tradeNo)) {
+//                bizContent.put("trade_no", tradeNo);
+//            }
+            request.setBizContent(bizContent.toJSONString());
+
+            // 3. 调用接口并获取响应
+            AlipayTradeQueryResponse response = alipayClient.certificateExecute(request);
+            if (response.isSuccess()) {
+                // 4. 解析支付状态
+                String tradeStatus = response.getTradeStatus();
+                log.info("订单查询成功,支付状态:" + tradeStatus);
+
+                // 支付状态说明:
+                // WAIT_BUYER_PAY:等待买家付款
+                // TRADE_CLOSED:交易关闭(超时未支付/已取消)
+                // TRADE_SUCCESS:支付成功(即时到账/普通转账)
+                // TRADE_FINISHED:交易完成(不可退款的场景,如即时到账)
+                if ("TRADE_SUCCESS".equals(tradeStatus)) {
+                    return R.success("支付成功");
+                } else if ("TRADE_CLOSED".equals(tradeStatus)) {
+                    return R.fail("交易已关闭");
+                } else if ("WAIT_BUYER_PAY".equals(tradeStatus)) {
+                    return R.fail("等待买家付款");
+                } else if ("TRADE_FINISHED".equals(tradeStatus)) {
+                    return R.success("交易完成");
+                }
+                return R.success("订单状态:" + tradeStatus);
+            } else {
+                return R.fail("订单查询失败:" + response.getMsg() + "(" + response.getSubMsg() + ")");
+            }
+        } catch (AlipayApiException e) {
+            log.error("支付宝订单查询异常", e);
+            return R.fail("查询异常:" + e.getMessage());
+        }
+    }
+
+    // 保持原有方法以兼容旧调用
+    public R<String> queryPayment(String outTradeNo) {
+        return queryPayment(outTradeNo, null);
+    }
+
+
+
+
+
+
+
 
 
 }

+ 14 - 1
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/LifeCouponPlatformController.java

@@ -128,7 +128,20 @@ public class LifeCouponPlatformController {
         log.info("LifeCouponController.getCouponDetail?id={}", id);
         LambdaQueryWrapper<LifeCoupon> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
         objectLambdaQueryWrapper.eq(LifeCoupon::getId, id);
-        return R.data(lifeCouponService.getOne(objectLambdaQueryWrapper));
+        LifeCoupon coupon = lifeCouponService.getOne(objectLambdaQueryWrapper);
+        if (coupon.getSingleQty() == null || coupon.getSingleQty() == 0) {
+            coupon.setSingleQty(null);
+        }
+
+        if ("0".equals(coupon.getSingleCanUse())) {
+            coupon.setSingleCanUse(null);
+        }
+
+        if ("0".equals(coupon.getPurchaseLimitCode())) {
+            coupon.setPurchaseLimitCode(null);
+        }
+
+        return R.data(coupon);
     }
 
 

+ 1 - 1
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/CouponManageServiceImpl.java

@@ -236,7 +236,7 @@ public class CouponManageServiceImpl implements CouponManageService {
         // 限制日期: 1234567;节日id
         if ("2".equals(lifeCoupon.getUnusedType())) {
             if (StringUtils.isEmpty(lifeCoupon.getUnavaiLableDate())) {
-                return R.success("无不可用日期限制");
+                return R.fail("未查到可用日期限制");
             }
 
             LocalDate nowDate = LocalDate.now();

+ 10 - 3
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/IncomeManageServiceImpl.java

@@ -189,7 +189,8 @@ public class IncomeManageServiceImpl extends ServiceImpl<StoreIncomeDetailsRecor
                         DateUtils.calcDays(new Date(), -27),
                         DateUtils.calcDays(new Date(), -4))
                 .isNull(StoreIncomeDetailsRecord::getCashOutId)  // 未绑定提现记录
-                .eq(StoreIncomeDetailsRecord::getStoreId, storeId);
+                .eq(StoreIncomeDetailsRecord::getStoreId, storeId)
+                .eq(StoreIncomeDetailsRecord::getIncomeType, CouponTypeEnum.COUPON.getCode());
 
         List<StoreIncomeDetailsRecord> incomeList = storeIncomeDetailsRecordMapper.selectList(wrapper);
         
@@ -413,8 +414,14 @@ public class IncomeManageServiceImpl extends ServiceImpl<StoreIncomeDetailsRecor
         // 提现记录总数
         vo.setCashOutNum(recordList.size());
 
-        log.info("IncomeManageServiceImpl.getCashOutRecordList - 查询完成: 总记录数={}, 总金额={}元",
-                recordList.size(), cashOutAllMoney);
+        // 分页信息
+        vo.setCurrentPage(storeCashOutRecordIPage.getCurrent());
+        vo.setPageSize(storeCashOutRecordIPage.getSize());
+        vo.setTotal(storeCashOutRecordIPage.getTotal());
+        vo.setTotalPages(storeCashOutRecordIPage.getPages());
+
+        log.info("IncomeManageServiceImpl.getCashOutRecordList - 查询完成: 总记录数={}, 总金额={}元, 当前页={}/{}, 总页数={}",
+                recordList.size(), cashOutAllMoney, vo.getCurrentPage(), vo.getPageSize(), vo.getTotalPages());
 
         return vo;
     }

+ 12 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/LifeCouponPlatformServiceImpl.java

@@ -83,6 +83,18 @@ public class LifeCouponPlatformServiceImpl extends ServiceImpl<LifeCouponMapper,
             lifeCoupon.setDiscountTagName(String.join(",", businessTypeNames));
         }
 
+        if (lifeCoupon.getPurchaseLimitCode() == null || "".equals(lifeCoupon.getPurchaseLimitCode())) {
+            lifeCoupon.setPurchaseLimitCode("0");
+        }
+
+        if (lifeCoupon.getSingleCanUse() == null || "".equals(lifeCoupon.getSingleCanUse())) {
+            lifeCoupon.setSingleCanUse("0");
+        }
+
+        if (lifeCoupon.getSingleQty() == null || "".equals(lifeCoupon.getSingleQty())) {
+            lifeCoupon.setSingleQty(0);
+        }
+
         lifeCoupon.setStatus(1);
         if (StringUtils.isEmpty(lifeCoupon.getId())) {
             lifeCoupon.setType(1);

+ 9 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/LifeDiscountCouponPlatformServiceImpl.java

@@ -19,6 +19,7 @@ import shop.alien.storeplatform.service.LifeDiscountCouponPlatformService;
 import shop.alien.storeplatform.service.LifeDiscountCouponQuantumRulesPlatformService;
 import shop.alien.util.common.constant.DiscountCouponEnum;
 
+import java.math.BigDecimal;
 import java.time.Instant;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
@@ -96,6 +97,11 @@ public class LifeDiscountCouponPlatformServiceImpl extends ServiceImpl<LifeDisco
                     lifeDiscountCoupon.setValidDate(validDateLocalDate);
                 }
             }
+
+            if (lifeDiscountCoupon.getMinimumSpendingAmount() == null) {
+                lifeDiscountCoupon.setMinimumSpendingAmount(BigDecimal.valueOf(0));
+            }
+
             lifeDiscountCouponMapper.insert(lifeDiscountCoupon);
             //发布优惠券规则信息
             //周中规则保存
@@ -375,6 +381,9 @@ public class LifeDiscountCouponPlatformServiceImpl extends ServiceImpl<LifeDisco
         lifeDiscountCouponVo.setAvailableTimeQuantum(availableTimeQuantumList);
         lifeDiscountCouponVo.setCustomizeUnavailableTimeQuantum(customizeUnavailableTimeQuantumList);
         lifeDiscountCouponVo.setCreatedTime(lifeDiscountCoupon.getCreatedTime());
+        if (lifeDiscountCouponVo.getMinimumSpendingAmount() != null && lifeDiscountCouponVo.getMinimumSpendingAmount().compareTo(BigDecimal.ZERO) == 0) {
+            lifeDiscountCouponVo.setMinimumSpendingAmount(null);
+        }
         return lifeDiscountCouponVo;
     }
 

+ 6 - 6
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformLoginServiceImpl.java

@@ -207,16 +207,16 @@ public class StorePlatformLoginServiceImpl extends ServiceImpl<StoreUserMapper,
     public JSONObject getExpirationTime(Integer storeId) throws Exception {
         try {
             JSONObject jsonObject = new JSONObject();
-            jsonObject.put("expirationTime", 0);
-            jsonObject.put("foodLicenceExpirationTime", 0);
+            jsonObject.put("expirationTime", 1);
+            jsonObject.put("foodLicenceExpirationTime", 1);
 
             StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
             if (storeInfo != null) {
-                if (storeInfo.getExpirationTime().compareTo(new Date()) > 0) {
-                    jsonObject.put("expirationTime", 1);
+                if (storeInfo.getExpirationTime().compareTo(new Date()) < 0) {
+                    jsonObject.put("expirationTime", 0);
                 }
-                if (storeInfo.getFoodLicenceExpirationTime().compareTo(new Date()) > 0) {
-                    jsonObject.put("foodLicenceExpirationTime", 1);
+                if (storeInfo.getFoodLicenceExpirationTime().compareTo(new Date()) < 0) {
+                    jsonObject.put("foodLicenceExpirationTime", 0);
                 }
             }
             return jsonObject;

+ 20 - 1
alien-store/src/main/java/shop/alien/store/controller/AliController.java

@@ -179,7 +179,6 @@ public class AliController {
         return R.fail("验证码校验失败");
     }
 
-
     @ApiOperation("银行卡核验")
     @ApiOperationSupport(order = 5)
     @ApiImplicitParams({@ApiImplicitParam(name = "name", value = "姓名", dataType = "String", paramType = "query", required = true),
@@ -378,4 +377,24 @@ public class AliController {
             return R.fail("OCR识别异常:"+e.getMessage());
         }
     }
+    /**
+     * 调用OCR识别接口
+     */
+    @ApiOperation("调用OCR识别接口")
+    @ApiOperationSupport(order = 17)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "imageUrls", value = "图片文件", dataType = "File", paramType = "query", required = true),
+            @ApiImplicitParam(name = "ocrType", value = "OCR识别类型", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "storeId", value = "店铺ID", dataType = "String", paramType = "query", required = false),
+            @ApiImplicitParam(name = "userId", value = "用户ID", dataType = "String", paramType = "query", required = false),
+            @ApiImplicitParam(name = "storeUserId", value = "店铺用户ID", dataType = "String", paramType = "query", required = false)
+    })
+    @PostMapping("/ocrRequestUrl")
+    public R ocrRequestUrl(@RequestBody Map<String, String> params) {
+        try {
+            return aliApi.ocrRequestParams(params);
+        } catch (Exception e) {
+            return R.fail(e.getMessage());
+        }
+    }
 }

+ 14 - 0
alien-store/src/main/java/shop/alien/store/service/LifeUserStoreService.java

@@ -110,6 +110,8 @@ public class LifeUserStoreService {
             Map<String, List<Map<String, Object>>> avgPriceMap = lifeUserOrderMapper.allStoreAvgPrice().stream().collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
             // 获取所有店铺的打卡次数
             List<Map<Integer, Integer>> storeClockInCountList = storeClockInService.getStoreClockInCount();
+            // 获取所有店铺打卡次数(有图片并且设置为可见的)
+            List<Map<Integer, Integer>> storeClockInCountMapList = storeClockInService.getStoreClockInWithCanLookCount();
             // 遍历所有门店信息,构造返回结果
             for (StoreInfoVo store : storeInfoVoList) {
 
@@ -204,10 +206,22 @@ public class LifeUserStoreService {
                         storeMap.put("storeClockInCount", b.get("count"));
                     }
                 });
+
+                storeClockInCountMapList.forEach(b -> {
+                    Integer storeId = b.get("storeId");
+                    if (Objects.equals(storeId, store.getId())) {
+                        storeMap.put("storeClockInCountWithCanLook", b.get("count"));
+                    }
+                });
+
                 // 如果未找到打卡次数,则设置为0
                 if (null == storeMap.get("storeClockInCount")) {
                     storeMap.put("storeClockInCount", 0);
                 }
+                // 如果未找到打卡次数(有图片并且设置为可见的),则设置为0
+                if (null == storeMap.get("storeClockInCountWithCanLook")) {
+                    storeMap.put("storeClockInCountWithCanLook", 0);
+                }
                 // 将当前门店的信息添加到返回结果列表中
                 returnMaps.add(storeMap);
             }

+ 96 - 0
alien-store/src/main/java/shop/alien/store/service/OcrImageUploadService.java

@@ -0,0 +1,96 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.store.OcrImageUpload;
+
+import java.util.List;
+
+/**
+ * OCR图片上传记录服务接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+public interface OcrImageUploadService extends IService<OcrImageUpload> {
+
+    /**
+     * 保存OCR图片上传记录
+     *
+     * @param ocrImageUpload OCR图片上传记录
+     * @return 是否保存成功
+     */
+    boolean saveOcrImageUpload(OcrImageUpload ocrImageUpload);
+
+    /**
+     * 根据ID查询OCR图片上传记录
+     *
+     * @param id 主键ID
+     * @return OCR图片上传记录
+     */
+    OcrImageUpload getById(Integer id);
+
+    /**
+     * 根据用户ID查询OCR图片上传记录列表
+     *
+     * @param userId 用户ID
+     * @return OCR图片上传记录列表
+     */
+    List<OcrImageUpload> getByUserId(String userId);
+
+    /**
+     * 根据店铺ID查询OCR图片上传记录列表
+     *
+     * @param storeId 店铺ID
+     * @return OCR图片上传记录列表
+     */
+    List<OcrImageUpload> getByStoreId(String storeId);
+
+    /**
+     * 根据用户ID和店铺ID查询OCR图片上传记录列表
+     *
+     * @param userId  用户ID
+     * @param storeId 店铺ID
+     * @return OCR图片上传记录列表
+     */
+    List<OcrImageUpload> getByUserIdAndStoreId(String userId, String storeId);
+
+    /**
+     * 根据OCR类型查询OCR图片上传记录列表
+     *
+     * @param ocrType OCR识别类型
+     * @return OCR图片上传记录列表
+     */
+    List<OcrImageUpload> getByOcrType(String ocrType);
+
+    /**
+     * 分页查询OCR图片上传记录
+     *
+     * @param page     分页参数
+     * @param userId   用户ID(可选)
+     * @param storeId  店铺ID(可选)
+     * @param ocrType  OCR类型(可选)
+     * @return 分页结果
+     */
+    IPage<OcrImageUpload> getPage(Page<OcrImageUpload> page, String userId, String storeId, String ocrType);
+
+    /**
+     * 更新OCR识别结果
+     *
+     * @param id         主键ID
+     * @param ocrResult  OCR识别结果
+     * @param ocrType    OCR识别类型
+     * @return 是否更新成功
+     */
+    boolean updateOcrResult(Integer id, String ocrResult, String ocrType);
+
+    /**
+     * 根据ID删除OCR图片上传记录
+     *
+     * @param id 主键ID
+     * @return 是否删除成功
+     */
+    boolean deleteById(Integer id);
+}
+

+ 6 - 0
alien-store/src/main/java/shop/alien/store/service/StoreClockInService.java

@@ -29,4 +29,10 @@ public interface StoreClockInService extends IService<StoreClockIn> {
     int setImg(int id, String img);
 
     List<Map<Integer, Integer>> getStoreClockInCount();
+    /**
+     * 获取所有店铺打卡次数(有图片并且设置为可见的)
+     *
+     * @return map
+     */
+    List<Map<Integer, Integer>> getStoreClockInWithCanLookCount();
 }

+ 2 - 2
alien-store/src/main/java/shop/alien/store/service/impl/LawyerUserServiceImpl.java

@@ -126,8 +126,8 @@ public class LawyerUserServiceImpl extends ServiceImpl<LawyerUserMapper, LawyerU
         result.put("education", lawyer.getEducationBackground() != null ? lawyer.getEducationBackground() : "");
         result.put("credentials", new ArrayList<>());  // TODO: 需要查询资质证书
         result.put("caseCount", lawyer.getServiceCount() != null ? lawyer.getServiceCount() : 0);
-        // 评分:服务评分已经是0-5分,直接转换为Double类型
-        result.put("rating", lawyer.getServiceScore() != null ? lawyer.getServiceScore().doubleValue() : 0.0);
+        // 评分:服务评分已经是0-5分(保留一位小数),直接使用
+        result.put("rating", lawyer.getServiceScore() != null ? lawyer.getServiceScore() : 0.0);
         result.put("reviewCount", lawyer.getGoodReviewCount() != null ?
                 (lawyer.getGoodReviewCount() + (lawyer.getMediumReviewCount() != null ? lawyer.getMediumReviewCount() : 0) +
                  (lawyer.getBadReviewCount() != null ? lawyer.getBadReviewCount() : 0)) : 0);

+ 98 - 0
alien-store/src/main/java/shop/alien/store/service/impl/OcrImageUploadServiceImpl.java

@@ -0,0 +1,98 @@
+package shop.alien.store.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.store.OcrImageUpload;
+import shop.alien.mapper.OcrImageUploadMapper;
+import shop.alien.store.service.OcrImageUploadService;
+
+import java.util.List;
+
+/**
+ * OCR图片上传记录服务实现类
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Service
+@RequiredArgsConstructor
+public class OcrImageUploadServiceImpl extends ServiceImpl<OcrImageUploadMapper, OcrImageUpload> implements OcrImageUploadService {
+
+    private final OcrImageUploadMapper ocrImageUploadMapper;
+
+    @Override
+    public boolean saveOcrImageUpload(OcrImageUpload ocrImageUpload) {
+        return ocrImageUploadMapper.insert(ocrImageUpload) > 0;
+    }
+
+    @Override
+    public OcrImageUpload getById(Integer id) {
+        return ocrImageUploadMapper.selectById(id);
+    }
+
+    @Override
+    public List<OcrImageUpload> getByUserId(String userId) {
+        LambdaQueryWrapper<OcrImageUpload> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(OcrImageUpload::getUserId, userId);
+        queryWrapper.orderByDesc(OcrImageUpload::getCreateTime);
+        return ocrImageUploadMapper.selectList(queryWrapper);
+    }
+
+    @Override
+    public List<OcrImageUpload> getByStoreId(String storeId) {
+        LambdaQueryWrapper<OcrImageUpload> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(OcrImageUpload::getStoreId, storeId);
+        queryWrapper.orderByDesc(OcrImageUpload::getCreateTime);
+        return ocrImageUploadMapper.selectList(queryWrapper);
+    }
+
+    @Override
+    public List<OcrImageUpload> getByUserIdAndStoreId(String userId, String storeId) {
+        LambdaQueryWrapper<OcrImageUpload> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StringUtils.isNotEmpty(userId), OcrImageUpload::getUserId, userId);
+        queryWrapper.eq(StringUtils.isNotEmpty(storeId), OcrImageUpload::getStoreId, storeId);
+        queryWrapper.orderByDesc(OcrImageUpload::getCreateTime);
+        return ocrImageUploadMapper.selectList(queryWrapper);
+    }
+
+    @Override
+    public List<OcrImageUpload> getByOcrType(String ocrType) {
+        LambdaQueryWrapper<OcrImageUpload> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(OcrImageUpload::getOcrType, ocrType);
+        queryWrapper.orderByDesc(OcrImageUpload::getCreateTime);
+        return ocrImageUploadMapper.selectList(queryWrapper);
+    }
+
+    @Override
+    public IPage<OcrImageUpload> getPage(Page<OcrImageUpload> page, String userId, String storeId, String ocrType) {
+        LambdaQueryWrapper<OcrImageUpload> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StringUtils.isNotEmpty(userId), OcrImageUpload::getUserId, userId);
+        queryWrapper.eq(StringUtils.isNotEmpty(storeId), OcrImageUpload::getStoreId, storeId);
+        queryWrapper.eq(StringUtils.isNotEmpty(ocrType), OcrImageUpload::getOcrType, ocrType);
+        queryWrapper.orderByDesc(OcrImageUpload::getCreateTime);
+        return ocrImageUploadMapper.selectPage(page, queryWrapper);
+    }
+
+    @Override
+    public boolean updateOcrResult(Integer id, String ocrResult, String ocrType) {
+        LambdaUpdateWrapper<OcrImageUpload> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(OcrImageUpload::getId, id);
+        updateWrapper.set(OcrImageUpload::getOcrResult, ocrResult);
+        if (StringUtils.isNotEmpty(ocrType)) {
+            updateWrapper.set(OcrImageUpload::getOcrType, ocrType);
+        }
+        return ocrImageUploadMapper.update(null, updateWrapper) > 0;
+    }
+
+    @Override
+    public boolean deleteById(Integer id) {
+        return ocrImageUploadMapper.deleteById(id) > 0;
+    }
+}
+

+ 10 - 0
alien-store/src/main/java/shop/alien/store/service/impl/StoreClockInServiceImpl.java

@@ -214,4 +214,14 @@ public class StoreClockInServiceImpl extends ServiceImpl<StoreClockInMapper, Sto
     public List<Map<Integer, Integer>> getStoreClockInCount() {
         return storeClockInMapper.getStoreClockInCount();
     }
+
+    /**
+     * 获取所有店铺打卡次数(有图片并且设置为可见的)
+     *
+     * @return map
+     */
+    @Override
+    public List<Map<Integer, Integer>> getStoreClockInWithCanLookCount() {
+        return storeClockInMapper.getStoreClockInWithCanLookCount();
+    }
 }

+ 15 - 10
alien-store/src/main/java/shop/alien/store/util/ali/AliApi.java

@@ -18,16 +18,8 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 import org.springframework.web.multipart.MultipartFile;
 import shop.alien.entity.result.R;
-import shop.alien.entity.store.LifeUser;
-import shop.alien.entity.store.StoreAliPayErrorLog;
-import shop.alien.entity.store.StoreAliPayLog;
-import shop.alien.entity.store.StoreAliPayRefundLog;
-import shop.alien.entity.store.StoreUser;
-import shop.alien.store.service.LifeUserService;
-import shop.alien.store.service.StoreAliPayErrorLogService;
-import shop.alien.store.service.StoreAliPayLogService;
-import shop.alien.store.service.StoreAliPayRefundLogService;
-import shop.alien.store.service.StoreUserService;
+import shop.alien.entity.store.*;
+import shop.alien.store.service.*;
 import shop.alien.store.util.ali.ocr.OcrStrategy;
 import shop.alien.store.util.ali.ocr.OcrStrategyFactory;
 import shop.alien.util.common.RandomCreateUtil;
@@ -39,6 +31,7 @@ import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Base64;
 import java.util.Date;
+import java.util.Map;
 
 /**
  * 支付宝相关组件
@@ -779,6 +772,18 @@ public class AliApi {
     }
 
     /**
+     * 支付宝OCR识别
+     *
+     * @return OCR识别结果
+     * @throws Exception 识别异常
+     */
+    public R ocrRequestParams(Map<String, String> params) throws Exception {
+        OcrStrategy strategy = ocrStrategyFactory.getStrategy(params.get("ocrType"));
+        return strategy.recognizeParams(params);
+    }
+
+
+    /**
      * 支付宝OCR识别(Base64方式,使用策略工厂模式)
      * 目前没用w
      * @param imageFile 图片文件

+ 15 - 1
alien-store/src/main/java/shop/alien/store/util/ali/ocr/AbstractOcrStrategy.java

@@ -3,7 +3,10 @@ package shop.alien.store.util.ali.ocr;
 import com.aliyun.ocr_api20210707.Client;
 import com.aliyun.tea.TeaException;
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import shop.alien.entity.store.OcrImageUpload;
+import shop.alien.store.service.OcrImageUploadService;
 
 /**
  * OCR策略抽象基类
@@ -23,7 +26,10 @@ public abstract class AbstractOcrStrategy implements OcrStrategy {
     
     @Value("${ali.ocr.endpoint:ocr-api.cn-hangzhou.aliyuncs.com}")
     protected String endpoint;
-    
+
+    @Autowired
+    protected OcrImageUploadService ocrImageUploadService;
+
     /**
      * 创建OCR客户端
      * 
@@ -91,5 +97,13 @@ public abstract class AbstractOcrStrategy implements OcrStrategy {
             handleOcrException(teaException, errorMessage);
         }
     }
+
+    public void saveOcrImage(OcrImageUpload ocrImageUpload) {
+        // 保存OCR识别结果到数据库
+        boolean save = ocrImageUploadService.save(ocrImageUpload);
+        if (!save) {
+            log.error("保存OCR识别结果失败: {}", ocrImageUpload);
+        }
+    }
 }
 

+ 19 - 0
alien-store/src/main/java/shop/alien/store/util/ali/ocr/OcrStrategy.java

@@ -1,6 +1,9 @@
 package shop.alien.store.util.ali.ocr;
 
 import shop.alien.entity.result.R;
+import shop.alien.entity.store.OcrImageUpload;
+
+import java.util.Map;
 
 /**
  * OCR识别策略接口
@@ -29,6 +32,15 @@ public interface OcrStrategy {
     R recognizeUrl(String imageUrl) throws Exception;
 
     /**
+     * 执行OCR识别(参数方式)
+     *
+     * @param params 识别参数
+     * @return OCR识别结果(JSON格式)
+     * @throws Exception 识别异常
+     */
+    R recognizeParams(Map<String, String> params) throws Exception;
+
+    /**
      * 执行OCR识别(Base64方式)
      *
      * @param imageBase64 图片Base64编码
@@ -37,6 +49,13 @@ public interface OcrStrategy {
      */
     R recognizeByBase64(String imageBase64) throws Exception;
 
+     /**
+     * 保存OCR识别结果
+     *
+     * @param ocrImageUpload OCR识别结果上传实体
+     */
+    void saveOcrImage(OcrImageUpload ocrImageUpload);
+
     /**
      * 获取策略类型字符串
      *

+ 44 - 3
alien-store/src/main/java/shop/alien/store/util/ali/ocr/strategy/BusinessLicenseOcrStrategy.java

@@ -1,21 +1,23 @@
 package shop.alien.store.util.ali.ocr.strategy;
 
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.aliyun.ocr_api20210707.Client;
-import com.aliyun.ocr_api20210707.models.RecognizeBusinessLicenseRequest;
-import com.aliyun.ocr_api20210707.models.RecognizeBusinessLicenseResponse;
-import com.aliyun.ocr_api20210707.models.RecognizeBusinessLicenseResponseBody;
+import com.aliyun.ocr_api20210707.models.*;
 import com.aliyun.tea.TeaException;
 import com.aliyun.teautil.models.RuntimeOptions;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 import shop.alien.entity.result.R;
+import shop.alien.entity.store.OcrImageUpload;
 import shop.alien.entity.store.StoreImg;
 import shop.alien.store.service.StoreImgService;
 import shop.alien.store.util.ali.ocr.AbstractOcrStrategy;
 import shop.alien.util.common.constant.OcrTypeEnum;
 
+import java.util.Map;
+
 /**
  * 营业执照OCR识别策略
  *
@@ -67,6 +69,45 @@ public class BusinessLicenseOcrStrategy extends AbstractOcrStrategy {
     }
 
     @Override
+    public R recognizeParams(Map<String, String> params) throws Exception {
+        String[] imageUrls = params.get("imageUrls").split(",");
+        JSONArray resultArray = new JSONArray();
+        for (String imageUrl : imageUrls) {
+            Client client = createOcrClient();
+            RecognizeBusinessLicenseRequest request = new RecognizeBusinessLicenseRequest()
+                    .setUrl(imageUrl); // 默认识别正面,可根据需要修改为 "back" 识别反面
+            try {
+                RecognizeBusinessLicenseResponse response = client.recognizeBusinessLicenseWithOptions(
+                        request, new RuntimeOptions());
+                RecognizeBusinessLicenseResponseBody body = response.getBody();
+
+                if (body == null || body.getData() == null) {
+                    throw new Exception("OCR识别返回结果为空");
+                }
+                JSONObject jsonObject = JSONObject.parseObject(body.getData());
+                log.info("营业执照OCR识别成功: {}", jsonObject.getJSONObject("data"));
+                // 保存OCR图片上传记录
+                OcrImageUpload ocrImageUpload = new OcrImageUpload();
+                ocrImageUpload.setUserId(params.get("userId"));
+                ocrImageUpload.setStoreId(params.get("storeId"));
+                ocrImageUpload.setStoreUserId(params.get("storeUserId"));
+                ocrImageUpload.setImageUrl(imageUrl);
+                ocrImageUpload.setOcrResult(jsonObject.getJSONObject("data").toJSONString());
+                ocrImageUpload.setOcrType(OcrTypeEnum.ID_CARD.getCode());
+                super.saveOcrImage(ocrImageUpload);
+                resultArray.add(jsonObject.getJSONObject("data"));
+            } catch (TeaException error) {
+                handleOcrException(error, "营业执照识别失败");
+                return R.fail("营业执照识别失败");
+            } catch (Exception error) {
+                handleOcrException(error, "营业执照识别异常");
+                return R.fail("营业执照识别异常");
+            }
+        }
+        return R.data(resultArray);
+    }
+
+    @Override
     public R recognizeByBase64(String imageBase64) throws Exception {
         Client client = createOcrClient();
         // 将Base64字符串转换为字节数组,然后创建InputStream

+ 43 - 0
alien-store/src/main/java/shop/alien/store/util/ali/ocr/strategy/FoodManageLicenseOcrStrategy.java

@@ -1,5 +1,6 @@
 package shop.alien.store.util.ali.ocr.strategy;
 
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.aliyun.ocr_api20210707.Client;
 import com.aliyun.ocr_api20210707.models.*;
@@ -9,11 +10,14 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 import shop.alien.entity.result.R;
+import shop.alien.entity.store.OcrImageUpload;
 import shop.alien.entity.store.StoreImg;
 import shop.alien.store.service.StoreImgService;
 import shop.alien.store.util.ali.ocr.AbstractOcrStrategy;
 import shop.alien.util.common.constant.OcrTypeEnum;
 
+import java.util.Map;
+
 /**
  * 食品经营许可证OCR识别策略
  *
@@ -65,6 +69,45 @@ public class FoodManageLicenseOcrStrategy extends AbstractOcrStrategy {
     }
 
     @Override
+    public R recognizeParams(Map<String, String> params) throws Exception {
+        String[] imageUrls = params.get("imageUrls").split(",");
+        JSONArray resultArray = new JSONArray();
+        for (String imageUrl : imageUrls) {
+            Client client = createOcrClient();
+            RecognizeFoodManageLicenseRequest request = new RecognizeFoodManageLicenseRequest()
+                    .setUrl(imageUrl); // 默认识别正面,可根据需要修改为 "back" 识别反面
+            try {
+                RecognizeFoodManageLicenseResponse response = client.recognizeFoodManageLicenseWithOptions(
+                        request, new RuntimeOptions());
+                RecognizeFoodManageLicenseResponseBody body = response.getBody();
+
+                if (body == null || body.getData() == null) {
+                    throw new Exception("OCR识别返回结果为空");
+                }
+                JSONObject jsonObject = JSONObject.parseObject(body.getData());
+                log.info("食品经营许可证OCR识别成功: {}", jsonObject.getJSONObject("data"));
+                // 保存OCR图片上传记录
+                OcrImageUpload ocrImageUpload = new OcrImageUpload();
+                ocrImageUpload.setUserId(params.get("userId"));
+                ocrImageUpload.setStoreId(params.get("storeId"));
+                ocrImageUpload.setStoreUserId(params.get("storeUserId"));
+                ocrImageUpload.setImageUrl(imageUrl);
+                ocrImageUpload.setOcrResult(jsonObject.getJSONObject("data").toJSONString());
+                ocrImageUpload.setOcrType(OcrTypeEnum.ID_CARD.getCode());
+                super.saveOcrImage(ocrImageUpload);
+                resultArray.add(jsonObject.getJSONObject("data"));
+            } catch (TeaException error) {
+                handleOcrException(error, "食品经营许可证识别失败");
+                return R.fail("食品经营许可证识别失败");
+            } catch (Exception error) {
+                handleOcrException(error, "食品经营许可证识别异常");
+                return R.fail("食品经营许可证识别异常");
+            }
+        }
+        return R.data(resultArray);
+    }
+
+    @Override
     public R recognizeByBase64(String imageBase64) throws Exception {
         Client client = createOcrClient();
         // 将Base64字符串转换为字节数组,然后创建InputStream

+ 49 - 1
alien-store/src/main/java/shop/alien/store/util/ali/ocr/strategy/IdCardOcrStrategy.java

@@ -1,19 +1,26 @@
 package shop.alien.store.util.ali.ocr.strategy;
 
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.aliyun.ocr_api20210707.Client;
-import com.aliyun.ocr_api20210707.models.*;
+import com.aliyun.ocr_api20210707.models.RecognizeIdcardRequest;
+import com.aliyun.ocr_api20210707.models.RecognizeIdcardResponse;
+import com.aliyun.ocr_api20210707.models.RecognizeIdcardResponseBody;
 import com.aliyun.tea.TeaException;
 import com.aliyun.teautil.models.RuntimeOptions;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
 import shop.alien.entity.result.R;
+import shop.alien.entity.store.OcrImageUpload;
 import shop.alien.entity.store.StoreImg;
 import shop.alien.store.service.StoreImgService;
 import shop.alien.store.util.ali.ocr.AbstractOcrStrategy;
 import shop.alien.util.common.constant.OcrTypeEnum;
 
+import java.util.Date;
+import java.util.Map;
+
 /**
  * 身份证OCR识别策略
  *
@@ -65,6 +72,47 @@ public class IdCardOcrStrategy extends AbstractOcrStrategy {
     }
 
     @Override
+    public R recognizeParams(Map<String, String> params) throws Exception {
+        String[] imageUrls = params.get("imageUrls").split(",");
+        JSONArray resultArray = new JSONArray();
+        for (String imageUrl : imageUrls) {
+            Client client = createOcrClient();
+            RecognizeIdcardRequest request = new RecognizeIdcardRequest()
+                    .setUrl(imageUrl); // 默认识别正面,可根据需要修改为 "back" 识别反面
+            try {
+                RecognizeIdcardResponse response = client.recognizeIdcardWithOptions(
+                        request, new RuntimeOptions());
+                RecognizeIdcardResponseBody body = response.getBody();
+
+                if (body == null || body.getData() == null) {
+                    throw new Exception("OCR识别返回结果为空");
+                }
+                JSONObject jsonObject = JSONObject.parseObject(body.getData());
+                log.info("身份证OCR识别成功: {}", jsonObject.getJSONObject("data"));
+                // 保存OCR图片上传记录
+                OcrImageUpload ocrImageUpload = new OcrImageUpload();
+                ocrImageUpload.setUserId(params.get("userId"));
+                ocrImageUpload.setStoreId(params.get("storeId"));
+                ocrImageUpload.setStoreUserId(params.get("storeUserId"));
+                ocrImageUpload.setImageUrl(imageUrl);
+                ocrImageUpload.setOcrResult(jsonObject.getJSONObject("data").toJSONString());
+                ocrImageUpload.setOcrType(OcrTypeEnum.ID_CARD.getCode());
+                ocrImageUpload.setCreateTime(new Date());
+                ocrImageUpload.setUpdateTime(new Date());
+                super.saveOcrImage(ocrImageUpload);
+                resultArray.add(jsonObject.getJSONObject("data"));
+            } catch (TeaException error) {
+                handleOcrException(error, "身份证识别失败");
+                return R.fail("身份证识别失败");
+            } catch (Exception error) {
+                handleOcrException(error, "身份证识别异常");
+                return R.fail("身份证识别异常");
+            }
+        }
+        return R.data(resultArray);
+    }
+
+    @Override
     public R recognizeByBase64(String imageBase64) throws Exception {
         Client client = createOcrClient();
         // 将Base64字符串转换为字节数组,然后创建InputStream