Explorar el Código

Merge remote-tracking branch 'origin/dev' into dev

panzhilin hace 1 semana
padre
commit
7ba455e127
Se han modificado 30 ficheros con 1336 adiciones y 322 borrados
  1. 12 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreClockIn.java
  2. 1 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreComment.java
  3. 5 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreDictionary.java
  4. 1 1
      alien-entity/src/main/java/shop/alien/entity/store/StoreImg.java
  5. 10 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreInfo.java
  6. 3 0
      alien-entity/src/main/java/shop/alien/entity/store/dto/PayStatusRequest.java
  7. 3 3
      alien-entity/src/main/java/shop/alien/entity/store/excelVo/BusinessSectionExcelVo.java
  8. 5 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/LawyerConsultationOrderVO.java
  9. 33 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreCommentCountVo.java
  10. 7 1
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreInfoVo.java
  11. 32 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreThreeLevelStructureVo.java
  12. 1 0
      alien-entity/src/main/java/shop/alien/mapper/LawyerConsultationOrderMapper.java
  13. 176 0
      alien-entity/src/main/java/shop/alien/mapper/LifeCouponMapper.java
  14. 8 3
      alien-entity/src/main/java/shop/alien/mapper/StoreInfoMapper.java
  15. 249 134
      alien-job/src/main/java/shop/alien/job/store/AiTagJob.java
  16. 17 0
      alien-store/src/main/java/shop/alien/store/controller/LifeCouponController.java
  17. 11 0
      alien-store/src/main/java/shop/alien/store/controller/StoreCommentController.java
  18. 93 7
      alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java
  19. 7 5
      alien-store/src/main/java/shop/alien/store/controller/StoreMenuController.java
  20. 7 2
      alien-store/src/main/java/shop/alien/store/service/LifeCouponService.java
  21. 9 0
      alien-store/src/main/java/shop/alien/store/service/StoreCommentService.java
  22. 29 5
      alien-store/src/main/java/shop/alien/store/service/StoreInfoService.java
  23. 1 1
      alien-store/src/main/java/shop/alien/store/service/StoreMenuService.java
  24. 4 0
      alien-store/src/main/java/shop/alien/store/service/impl/LawyerConsultationOrderServiceImpl.java
  25. 5 0
      alien-store/src/main/java/shop/alien/store/service/impl/LifeCouponServiceImpl.java
  26. 4 2
      alien-store/src/main/java/shop/alien/store/service/impl/LifeDiscountCouponServiceImpl.java
  27. 97 78
      alien-store/src/main/java/shop/alien/store/service/impl/PlatformBusinessSectionServiceImpl.java
  28. 51 0
      alien-store/src/main/java/shop/alien/store/service/impl/StoreCommentServiceImpl.java
  29. 436 78
      alien-store/src/main/java/shop/alien/store/service/impl/StoreInfoServiceImpl.java
  30. 19 2
      alien-store/src/main/java/shop/alien/store/service/impl/StoreMenuServiceImpl.java

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

@@ -83,6 +83,18 @@ public class StoreClockIn extends Model<StoreClockIn> {
     @TableField(value = "updated_user_id", fill = FieldFill.INSERT_UPDATE)
     private Integer updatedUserId;
 
+    @ApiModelProperty(value = "是否审核(未审核:0,审核中:1,审核完成:2)")
+    @TableField("check_flag")
+    private Integer checkFlag;
+
+    @ApiModelProperty(value = "AI审核结果查询id")
+    @TableField("ai_task_id")
+    private String aiTaskId;
+
+    @ApiModelProperty(value = "审核失败原因")
+    @TableField("reason")
+    private String reason;
+
 
     @Override
     protected Serializable pkVal() {

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

@@ -20,6 +20,7 @@ import java.util.Date;
 @Data
 @JsonInclude
 @EqualsAndHashCode(callSuper = false)
+@TableName("store_comment")
 @ApiModel(value = "StoreComment对象", description = "评论表")
 public class StoreComment extends Model<StoreComment> {
 

+ 5 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreDictionary.java

@@ -84,6 +84,11 @@ public class StoreDictionary extends Model<StoreDictionary> {
     @TableField("hidden")
     private Integer hidden;
 
+    @ApiModelProperty(value = "排序ID")
+    @TableField("sort_id")
+    private Integer sortId;
+
+
     @Override
     protected Serializable pkVal() {
         return this.id;

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

@@ -30,7 +30,7 @@ public class StoreImg extends Model<StoreImg> {
     @TableField("store_id")
     private Integer storeId;
 
-    @ApiModelProperty(value = "图片类型, 0:其他, 1:入口图, 2:相册, 3:菜品, 4:环境, 5:价目表, 6:推荐菜, 7:菜单, 8:用户评论, 9:商家申诉,10:商家头像,11:店铺轮播图,12:联名卡图片,13:动态折扣, 14:套餐图片,15:合同照片,17:打卡广场小人图片 18: 商品发布图片 19:二手商品与用户举报图片,20头图单图模式,21头图多图模式 , 22续签合同,23,二手商品记录图片类型, 24 食品经营许可证审核前状态 25.食品经营许可证审核后状态, 28:运动器材设施图片, 29:洗浴设施及服务图片")
+    @ApiModelProperty(value = "图片类型, 0:其他, 1:入口图, 2:相册, 3:菜品, 4:环境, 5:价目表, 6:推荐菜, 7:菜单, 8:用户评论, 9:商家申诉,10:商家头像,11:店铺轮播图,12:联名卡图片,13:动态折扣, 14:套餐图片,15:合同照片,17:打卡广场小人图片 18: 商品发布图片 19:二手商品与用户举报图片,20头图单图模式,21头图多图模式 , 22续签合同,23,二手商品记录图片类型, 24 食品经营许可证审核前状态 25.食品经营许可证审核后状态, 28:运动器材设施图片, 29:洗浴设施及服务图片 30 酒水")
     @TableField("img_type")
     private Integer imgType;
 

+ 10 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreInfo.java

@@ -234,4 +234,14 @@ public class StoreInfo {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     @TableField("update_renew_contract_time")
     private Date  updateRenewContractTime;
+
+    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)(多个ID用逗号拼接)")
+    @TableField("business_classify")
+    private String businessClassify;
+
+    @ApiModelProperty(value = "分类名称")
+    @TableField("business_classify_name")
+    private String businessClassifyName;
+
+
 }

+ 3 - 0
alien-entity/src/main/java/shop/alien/entity/store/dto/PayStatusRequest.java

@@ -26,5 +26,8 @@ public class PayStatusRequest implements Serializable {
 
     @ApiModelProperty(value = "订单状态, 0:待支付,1.待接单 2:进行中, 3:已完成, 4:已取消,5.已退款")
     private Integer orderStatus;
+
+    @ApiModelProperty(value = "支付宝或VX的str")
+    private String orderStr;
 }
 

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

@@ -17,15 +17,15 @@ import shop.alien.entity.store.excelVo.util.ExcelHeader;
 @ApiModel(value = "BusinessSectionExcelVo对象", description = "经营版块Excel导入导出对象")
 public class BusinessSectionExcelVo {
 
-    @ExcelHeader("一级分类名称")
+    @ExcelHeader("经营板块")
     @ApiModelProperty(value = "一级分类名称(必填,如果二级和三级为空,则创建一级分类)")
     private String firstLevelName;
 
-    @ExcelHeader("二级分类名称")
+    @ExcelHeader("经营种类")
     @ApiModelProperty(value = "二级分类名称(可选,如果三级为空,则创建二级分类)")
     private String secondLevelName;
 
-    @ExcelHeader("三级分类名称")
+    @ExcelHeader("分类")
     @ApiModelProperty(value = "三级分类名称(可选,如果填写则创建三级分类)")
     private String thirdLevelName;
 

+ 5 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/LawyerConsultationOrderVO.java

@@ -233,5 +233,10 @@ public class LawyerConsultationOrderVO implements Serializable {
 
     @ApiModelProperty(value = "举报处理结果")
     private  String reportResult;
+
+    @ApiModelProperty(value = "支付方式 1支付宝 2微信")
+    @TableField("pay_type")
+    private  String payType;
+
 }
 

+ 33 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreCommentCountVo.java

@@ -0,0 +1,33 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * 评价计数VO
+ *
+ * @author ssk
+ * @version 1.0
+ * @date 2025/12/01
+ */
+@Data
+@JsonInclude
+public class StoreCommentCountVo {
+
+    @ApiModelProperty(value = "全部评价数")
+    private Integer totalCount;
+
+    @ApiModelProperty(value = "有图评价数")
+    private Integer imageCount;
+
+    @ApiModelProperty(value = "好评数")
+    private Integer goodCount;
+
+    @ApiModelProperty(value = "中评数")
+    private Integer midCount;
+
+    @ApiModelProperty(value = "差评数")
+    private Integer badCount;
+}
+

+ 7 - 1
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreInfoVo.java

@@ -216,8 +216,14 @@ public class StoreInfoVo extends StoreInfo {
     private Integer dynamicsNum;
 
     @ApiModelProperty(value = "推荐列表距离(米)")
-    private double distance3;
+    private String distance3;
 
     @ApiModelProperty(value = "店铺头图(多图列表)")
     private List<String> storeAlbumUrlList;
+
+    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)(多个ID用逗号拼接)")
+    private String businessClassify;
+
+    @ApiModelProperty(value = "分类名称")
+    private String businessClassifyName;
 }

+ 32 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StoreThreeLevelStructureVo.java

@@ -0,0 +1,32 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import shop.alien.entity.store.StoreDictionary;
+
+import java.util.List;
+
+/**
+ * 门店三级分类结构VO
+ *
+ * @author ssk
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude
+@ApiModel(value = "StoreThreeLevelStructureVo对象", description = "门店三级分类结构")
+public class StoreThreeLevelStructureVo {
+
+    @ApiModelProperty(value = "门店ID")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "门店名称")
+    private String storeName;
+
+    @ApiModelProperty(value = "三级分类树状结构")
+    private List<StoreDictionary> threeLevelStructure;
+
+}
+

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

@@ -395,6 +395,7 @@ public interface LawyerConsultationOrderMapper extends BaseMapper<LawyerConsulta
             "        lco.alipay_no,\n" +
             "        lco.order_str,\n" +
             "        lco.apply_refund_status,\n" +
+            "        lco.pay_type,\n" +
             "        CASE\n" +
             "        WHEN EXISTS (SELECT 1 FROM lawyer_order_review lor WHERE lor.order_id = lco.id) THEN '1'\n" +
             "        ELSE '2'\n" +

+ 176 - 0
alien-entity/src/main/java/shop/alien/mapper/LifeCouponMapper.java

@@ -80,4 +80,180 @@ public interface LifeCouponMapper extends BaseMapper<LifeCoupon> {
             @Param("buyCount") int buyCount,
             @Param("soldOutStatus") int soldOutStatus
     );
+
+    /**
+     * 查询代金券详情(连表查询商铺信息)
+     *
+     * @param id 代金券ID
+     * @return LifeCouponVo
+     */
+    @Select("SELECT " +
+            "lc.id, " +
+            "lc.data_type, " +
+            "lc.buy_use_start_time, " +
+            "lc.buy_use_end_time, " +
+            "lc.use_festival, " +
+            "lc.coupon_code, " +
+            "lc.name, " +
+            "lc.store_id, " +
+            "lc.price, " +
+            "lc.offprice, " +
+            "lc.expiration_date, " +
+            "lc.start_date, " +
+            "lc.end_date, " +
+            "lc.unused_date, " +
+            "lc.single_qty, " +
+            "lc.buy_limit, " +
+            "lc.stock_qty, " +
+            "lc.use_rule, " +
+            "lc.min_use_peoples, " +
+            "lc.max_use_peoples, " +
+            "lc.dietary_preferences, " +
+            "lc.cooking_methods, " +
+            "lc.applicable_rule, " +
+            "lc.status, " +
+            "lc.image_path, " +
+            "lc.store_service, " +
+            "lc.fapiao_info, " +
+            "lc.type, " +
+            "lc.approval_comments, " +
+            "lc.open_price_protection, " +
+            "lc.price_below, " +
+            "lc.coupon_comp, " +
+            "lc.coupon_comp_date, " +
+            "lc.rate_score, " +
+            "lc.discount_tag, " +
+            "lc.discount_tag_name, " +
+            "lc.delete_flag, " +
+            "lc.status_delete_flag, " +
+            "lc.created_time, " +
+            "lc.created_user_id, " +
+            "lc.updated_time, " +
+            "lc.updated_user_id, " +
+            "lc.store_type, " +
+            "lc.sale_time_str_type, " +
+            "lc.sale_time_end_type, " +
+            "lc.purchase_limit_code, " +
+            "lc.original_price, " +
+            "lc.discounted_price, " +
+            "lc.business_types, " +
+            "lc.housing_type, " +
+            "lc.room_type, " +
+            "lc.room_type_code, " +
+            "lc.kitchen_xq, " +
+            "lc.bathroom_xq, " +
+            "lc.living_room, " +
+            "lc.location_of_the_property, " +
+            "lc.total_area, " +
+            "lc.entertainment_facilities_code, " +
+            "lc.entertainment_facilities, " +
+            "lc.convenience_facilities_code, " +
+            "lc.convenience_facilities, " +
+            "lc.bathroom_facilities_code, " +
+            "lc.bathroom_facilities, " +
+            "lc.bath_products_code, " +
+            "lc.bath_products, " +
+            "lc.service_code, " +
+            "lc.service, " +
+            "lc.safety_code, " +
+            "lc.safety, " +
+            "lc.reservation_instructions, " +
+            "lc.in_time, " +
+            "lc.out_time, " +
+            "lc.deposit_flag, " +
+            "lc.deposit_amount, " +
+            "lc.children_flag, " +
+            "lc.children_description, " +
+            "lc.pet_flag, " +
+            "lc.extra_bed_flag, " +
+            "lc.bed_price, " +
+            "lc.invoice_info, " +
+            "lc.invoice_instructions, " +
+            "lc.cancellation_policy_type, " +
+            "lc.cancellation_policy, " +
+            "lc.Cancellation_instructions, " +
+            "lc.insured_price, " +
+            "lc.validity_period_type, " +
+            "lc.box_type_code, " +
+            "lc.box_type, " +
+            "lc.snacks_code, " +
+            "lc.snacks, " +
+            "lc.available_duration, " +
+            "lc.write_off_type, " +
+            "lc.write_off, " +
+            "lc.refund_rules_type, " +
+            "lc.refund_rules, " +
+            "lc.refund_instructions, " +
+            "lc.edit_rules_code, " +
+            "lc.edit_rules, " +
+            "lc.edit_instructions, " +
+            "lc.tangchi_code, " +
+            "lc.tangchi, " +
+            "lc.sweat_sauna_code, " +
+            "lc.sweat_sauna, " +
+            "lc.pictures_and_text, " +
+            "lc.supplement, " +
+            "lc.unavailable_date_type, " +
+            "lc.reservation_rules, " +
+            "lc.applicable_num, " +
+            "lc.other_rules, " +
+            "lc.sales_type, " +
+            "lc.massage_technique_code, " +
+            "lc.massage_technique, " +
+            "lc.massage_area_code, " +
+            "lc.massage_area, " +
+            "lc.massage_tools_code, " +
+            "lc.massage_tools, " +
+            "lc.compress_tools_code, " +
+            "lc.compress_tools, " +
+            "lc.class_format_code, " +
+            "lc.class_format, " +
+            "lc.class_duration_code, " +
+            "lc.class_duration, " +
+            "lc.class_num_code, " +
+            "lc.class_num, " +
+            "lc.applicable_parts_code, " +
+            "lc.applicable_parts, " +
+            "lc.hygiene_code, " +
+            "lc.hygiene, " +
+            "lc.foundation_code, " +
+            "lc.foundation, " +
+            "lc.bathroom_code, " +
+            "lc.bathroom, " +
+            "lc.kitchen_code, " +
+            "lc.kitchen, " +
+            "lc.validity_period_yh_type, " +
+            "lc.validity_period_yh, " +
+            "lc.course_validity_period_code, " +
+            "lc.course_validity_period, " +
+            "lc.uploaded_picList, " +
+            "lc.validity_period, " +
+            "lc.stacking_type, " +
+            "lc.general_type, " +
+            "lc.single_can_use, " +
+            "lc.apply_type, " +
+            "lc.apply_desc, " +
+            "lc.expiration_type, " +
+            "lc.unused_type, " +
+            "lc.house_type, " +
+            "lc.house_type_b, " +
+            "lc.house_type_l, " +
+            "lc.house_type_k, " +
+            "lc.house_type_t, " +
+            "lc.sale_time_str, " +
+            "lc.sale_time_end, " +
+            "lc.unavai_lable_date, " +
+            "lc.room_type_str, " +
+            "lc.time_range, " +
+            "lc.cancellation_policy_str, " +
+            "lc.validity_periodyh_str, " +
+            "si.store_name, " +
+            "si.store_address, " +
+            "si.store_tel AS phone, " +
+            "si.business_status, " +
+            "si.store_status " +
+            "FROM life_coupon lc " +
+            "LEFT JOIN store_info si ON si.id = lc.store_id AND si.delete_flag = 0 " +
+            "WHERE lc.id = #{id} AND lc.delete_flag = 0")
+    LifeCouponVo getNewCouponDetail(@Param("id") String id);
 }

+ 8 - 3
alien-entity/src/main/java/shop/alien/mapper/StoreInfoMapper.java

@@ -135,6 +135,7 @@ public interface StoreInfoMapper extends BaseMapper<StoreInfo> {
      * 更多推荐(用户端)
      *
      * @param queryWrapper 查询条件
+     * @param position 经纬度位置(格式:经度,纬度)
      * @return List<StoreInfoVo>
      */
     @Select("select a.*, img.img_url entranceImage,img1.img_url foodLicenceImageUrl,b.name store_contact, b.phone store_phone, b.id_card idCard, b.password, c.dict_detail store_status_str, d.dict_detail business_status_str, e.dict_detail store_type_str,  " +
@@ -142,7 +143,8 @@ public interface StoreInfoMapper extends BaseMapper<StoreInfo> {
             " select ifnull(round(avg(score), 1), 0) " +
             " from store_evaluation eval " +
             " where eval.store_id = a.id and eval.delete_flag = 0 " +
-            ") score " +
+            ") score, " +
+            "ROUND(ST_Distance_Sphere(ST_GeomFromText(CONCAT('POINT(', REPLACE(#{position}, ',', ' '), ')' )), ST_GeomFromText(CONCAT('POINT(', REPLACE(a.store_position, ',', ' '), ')' ))), 0) distance3 " +
             "from store_info a " +
             "left join store_user b on a.id = b.store_id and a.delete_flag = 0 and b.delete_flag = 0 " +
             "left join store_img img on img.store_id = a.id and img.img_type = 1 and img.delete_flag = 0 " +
@@ -150,6 +152,9 @@ public interface StoreInfoMapper extends BaseMapper<StoreInfo> {
             "left join store_dictionary c on a.store_status = c.dict_id and c.type_name = 'storeState' and c.delete_flag = 0 " +
             "left join store_dictionary d on a.business_status = d.dict_id and d.type_name = 'businessStatus' and d.delete_flag = 0 " +
             "left join store_dictionary e on e.type_name = 'storeType' and e.dict_id = a.store_type and e.delete_flag = 0 " +
-            "${ew.customSqlSegment}")
-    List<StoreInfoVo> getMoreRecommendedStores(@Param(Constants.WRAPPER) QueryWrapper<StoreInfoVo> queryWrapper);
+            "${ew.customSqlSegment} " +
+            "and a.store_position is not null and a.store_position != '' " +
+            "and ROUND(ST_Distance_Sphere(ST_GeomFromText(CONCAT('POINT(', REPLACE(#{position}, ',', ' '), ')' )), ST_GeomFromText(CONCAT('POINT(', REPLACE(a.store_position, ',', ' '), ')' ))) / 1000, 2) <= 1 " +
+            "order by distance3 asc limit 20")
+    List<StoreInfoVo> getMoreRecommendedStores(@Param(Constants.WRAPPER) QueryWrapper<StoreInfoVo> queryWrapper, @Param("position") String position);
 }

+ 249 - 134
alien-job/src/main/java/shop/alien/job/store/AiTagJob.java

@@ -46,6 +46,8 @@ public class AiTagJob {
 
     private final LifeUserDynamicsMapper lifeUserDynamicsMapper;
 
+    private final StoreClockInMapper storeClockInMapper;
+
     // 第三方接口地址 获取所有标签主表信息
     @Value("${third-party-tag.base-url}")
     private String tagMainUrl;
@@ -589,9 +591,39 @@ public class AiTagJob {
                 "mp4", "mov", "mkv", "avi", "flv", "wmv", "mpeg", "mpg", "webm"
         ));
 
-        for (LifeUserDynamics lifeUserDynamic : lifeUserDynamics) {
-            String imagePath = lifeUserDynamic.getImagePath();
+        log.info("登录Ai服务获取token..." + loginUrl);
+        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+        formData.add("username", userName);
+        formData.add("password", passWord);
+
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
+        ResponseEntity<String> postForEntity = null;
+        try {
+            log.info("请求Ai服务登录接口===================>");
+            postForEntity = restTemplate.postForEntity(loginUrl, requestEntity, String.class);
+        } catch (Exception e) {
+            log.error("请求AI服务登录接口失败", e);
+        }
+        HttpHeaders aiHeaders = new HttpHeaders();
+        if (postForEntity != null && postForEntity.getStatusCodeValue() == 200) {
+            log.info("请求Ai服务登录成功 postForEntity.getBody()\t" + postForEntity.getBody());
+            String responseBody = postForEntity.getBody();
+            JSONObject jsonObject = JSONObject.parseObject(responseBody);
+            if (jsonObject != null) {
+                JSONObject dataJson = jsonObject.getJSONObject("data");
+                String accessToken = dataJson.getString("access_token");
 
+                aiHeaders.setContentType(MediaType.APPLICATION_JSON);
+                aiHeaders.set("Authorization", "Bearer " + accessToken);
+            }
+        }
+
+        List<StoreClockIn> storeClockIns = storeClockInMapper.selectList(new LambdaQueryWrapper<StoreClockIn>()
+                .eq(StoreClockIn::getDeleteFlag, 0).eq(StoreClockIn::getCheckFlag, 0));
+        for (StoreClockIn storeClockIn : storeClockIns) {
+            String imagePath = storeClockIn.getImgUrl() != null ? storeClockIn.getImgUrl() : "";
             List<String> imageList = new ArrayList<>();
             List<String> videoList = new ArrayList<>();
             // 按分隔符拆分路径数组(处理连续分隔符如 ",," 产生的空字符串)
@@ -613,79 +645,117 @@ public class AiTagJob {
                 } else if (VIDEO_SUFFIXES.contains(suffix)) {
                     videoList.add(trimmedPath);
                 }
-                // 对每一条动态逐条申请 token 并提交,避免批量失败导致重试逻辑复杂化
+            }
+            // 对每一条动态逐条申请 token 并提交,避免批量失败导致重试逻辑复杂化
+            try {
+                Map<String, Object> jsonBody = new HashMap<>();
+                // text/img/video 三种维度一起传入 AI,便于一次完成合规审查
+                jsonBody.put("text", storeClockIn.getContent());
+                jsonBody.put("image_urls", imageList);
+                jsonBody.put("video_urls", videoList);
+
+                HttpEntity<Map<String, Object>> request = new HttpEntity<>(jsonBody, aiHeaders);
+                ResponseEntity<String> response = null;
                 try {
-                    log.info("登录Ai服务获取token..." + loginUrl);
-                    MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
-                    formData.add("username", userName);
-                    formData.add("password", passWord);
-
-                    HttpHeaders headers = new HttpHeaders();
-                    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
-                    HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
-                    ResponseEntity<String> postForEntity = null;
-                    try {
-                        log.info("请求Ai服务登录接口===================>");
-                        postForEntity = restTemplate.postForEntity(loginUrl, requestEntity, String.class);
-                    } catch (Exception e) {
-                        log.error("请求AI服务登录接口失败", e);
+                    response = restTemplate.postForEntity(contentComplianceUrl, request, String.class);
+                    if (response.getStatusCodeValue() != 200) {
+                        log.error("AI内容审核接口调用失败 http状态:" + response.getStatusCode());
+                    }
+                    JSONObject responseNode = JSONObject.parseObject(response.getBody());
+                    if (responseNode == null) {
+                        log.error("AI接口调用失败,响应内容为空");
+                    }
+                    Integer code = null;
+                    if (responseNode != null) {
+                        code = responseNode.getInteger("code");
+                        if (code == 200) {
+                            JSONObject dataNode = JSONObject.from(responseNode.get("data"));
+                            // 审核发起后仅标记 checkFlag=1 并保存任务号,等待回调或后续轮询更新
+                            StoreClockIn clockIn = new StoreClockIn();
+                            clockIn.setId(storeClockIn.getId());
+                            clockIn.setCheckFlag(1);
+                            clockIn.setAiTaskId(dataNode.get("task_id").toString());
+                            storeClockInMapper.updateById(clockIn);
+                            log.info("动态审核成功,AI返回内容: {}", response.getBody());
+                            XxlJobHelper.handleSuccess("动态内容审核任务执行成功");
+                        }
+                    } else {
+                        log.error("AI接口调用失败,错误码: " + code);
                     }
+                } catch (Exception e) {
+                    log.error("调用AI内容审核接口失败", e);
+                }
+            } catch (RuntimeException ex) {
+                XxlJobHelper.handleFail("动态内容审核任务执行失败:" + ex.getMessage());
+                return R.fail("动态内容审核任务执行失败:" + ex.getMessage());
+            }
+        }
 
-                    if (postForEntity != null && postForEntity.getStatusCodeValue() == 200) {
-                        log.info("请求Ai服务登录成功 postForEntity.getBody()\t" + postForEntity.getBody());
-                        String responseBody = postForEntity.getBody();
-                        JSONObject jsonObject = JSONObject.parseObject(responseBody);
-                        if (jsonObject != null) {
-                            JSONObject dataJson = jsonObject.getJSONObject("data");
-                            String accessToken = dataJson.getString("access_token");
-
-                            HttpHeaders aiHeaders = new HttpHeaders();
-                            aiHeaders.setContentType(MediaType.APPLICATION_JSON);
-                            aiHeaders.set("Authorization", "Bearer " + accessToken);
-
-                            Map<String, Object> jsonBody = new HashMap<>();
-                            // text/img/video 三种维度一起传入 AI,便于一次完成合规审查
-                            jsonBody.put("text", lifeUserDynamic.getContext());
-                            jsonBody.put("image_urls", imageList);
-                            jsonBody.put("video_urls", videoList);
-
-                            HttpEntity<Map<String, Object>> request = new HttpEntity<>(jsonBody, aiHeaders);
-                            ResponseEntity<String> response = null;
-                            try {
-                                response = restTemplate.postForEntity(contentComplianceUrl, request, String.class);
-                                if (response.getStatusCodeValue() != 200) {
-                                    log.error("AI内容审核接口调用失败 http状态:" + response.getStatusCode());
-                                }
-                                JSONObject responseNode = JSONObject.parseObject(response.getBody());
-                                if (responseNode == null) {
-                                    log.error("AI接口调用失败,响应内容为空");
-                                }
-                                Integer code = null;
-                                if (responseNode != null) {
-                                    code = responseNode.getInteger("code");
-                                    if(code==200) {
-                                        JSONObject dataNode = JSONObject.from(responseNode.get("data"));
-                                        // 审核发起后仅标记 checkFlag=1 并保存任务号,等待回调或后续轮询更新
-                                        LifeUserDynamics dynamics = new LifeUserDynamics();
-                                        dynamics.setId(lifeUserDynamic.getId());
-                                        dynamics.setCheckFlag(1);
-                                        dynamics.setAiTaskId(dataNode.get("task_id").toString());
-                                        lifeUserDynamicsMapper.updateById(dynamics);
-                                        log.info("动态审核成功,AI返回内容: {}", response.getBody());
-                                        XxlJobHelper.handleSuccess("动态内容审核任务执行成功");
-                                    }
-                                }else {
-                                    log.error("AI接口调用失败,错误码: " + code);
-                                }
-                            } catch (Exception e) {
-                                log.error("调用AI内容审核接口失败", e);
-                            }
+        for (LifeUserDynamics lifeUserDynamic : lifeUserDynamics) {
+            String imagePath = lifeUserDynamic.getImagePath();
+            List<String> imageList = new ArrayList<>();
+            List<String> videoList = new ArrayList<>();
+            // 按分隔符拆分路径数组(处理连续分隔符如 ",," 产生的空字符串)
+            String[] allPaths = imagePath.split(",");
+            for (String path : allPaths) {
+                // 去除路径前后空格(避免 " a.jpg " 这类情况)
+                String trimmedPath = path.trim();
+                if (trimmedPath.isEmpty()) {
+                    continue; // 跳过空路径
+                }
+                // 获取文件后缀(忽略大小写)
+                // 找到最后一个 "." 的位置
+                int lastDotIndex = trimmedPath.lastIndexOf('.');
+                // 截取后缀(从 "." 后一位到结尾)
+                String suffix = trimmedPath.substring(lastDotIndex + 1);
+                // 分类添加到对应列表
+                if (IMAGE_SUFFIXES.contains(suffix)) {
+                    imageList.add(trimmedPath);
+                } else if (VIDEO_SUFFIXES.contains(suffix)) {
+                    videoList.add(trimmedPath);
+                }
+            }
+            try {
+                Map<String, Object> jsonBody = new HashMap<>();
+                // text/img/video 三种维度一起传入 AI,便于一次完成合规审查
+                jsonBody.put("text", lifeUserDynamic.getContext());
+                jsonBody.put("image_urls", imageList);
+                jsonBody.put("video_urls", videoList);
+
+                HttpEntity<Map<String, Object>> request = new HttpEntity<>(jsonBody, aiHeaders);
+                ResponseEntity<String> response = null;
+                try {
+                    response = restTemplate.postForEntity(contentComplianceUrl, request, String.class);
+                    if (response.getStatusCodeValue() != 200) {
+                        log.error("AI内容审核接口调用失败 http状态:" + response.getStatusCode());
+                    }
+                    JSONObject responseNode = JSONObject.parseObject(response.getBody());
+                    if (responseNode == null) {
+                        log.error("AI接口调用失败,响应内容为空");
+                    }
+                    Integer code = null;
+                    if (responseNode != null) {
+                        code = responseNode.getInteger("code");
+                        if (code == 200) {
+                            JSONObject dataNode = JSONObject.from(responseNode.get("data"));
+                            // 审核发起后仅标记 checkFlag=1 并保存任务号,等待回调或后续轮询更新
+                            LifeUserDynamics dynamics = new LifeUserDynamics();
+                            dynamics.setId(lifeUserDynamic.getId());
+                            dynamics.setCheckFlag(1);
+                            dynamics.setAiTaskId(dataNode.get("task_id").toString());
+                            lifeUserDynamicsMapper.updateById(dynamics);
+                            log.info("动态审核成功,AI返回内容: {}", response.getBody());
+                            XxlJobHelper.handleSuccess("动态内容审核任务执行成功");
                         }
+                    } else {
+                        log.error("AI接口调用失败,错误码: " + code);
                     }
-                } catch (RuntimeException ex) {
-                    XxlJobHelper.handleFail("动态内容审核任务执行失败:" + ex.getMessage());
-                    return R.fail("动态内容审核任务执行失败:" + ex.getMessage());
+                } catch (Exception e) {
+                    log.error("调用AI内容审核接口失败", e);
                 }
+            } catch (RuntimeException ex) {
+                XxlJobHelper.handleFail("动态内容审核任务执行失败:" + ex.getMessage());
+                return R.fail("动态内容审核任务执行失败:" + ex.getMessage());
             }
         }
         return R.success("动态内容审核任务执行成功");
@@ -698,82 +768,127 @@ public class AiTagJob {
     public R<String> getCheckTask() {
         List<LifeUserDynamics> lifeUserDynamics = lifeUserDynamicsMapper.selectList(new LambdaQueryWrapper<LifeUserDynamics>()
                 .eq(LifeUserDynamics::getCheckFlag, 1).eq(LifeUserDynamics::getDeleteFlag, 0));
+        log.info("登录Ai服务获取token..." + loginUrl);
+        MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
+        formData.add("username", userName);
+        formData.add("password", passWord);
 
-        for (LifeUserDynamics lifeUserDynamic : lifeUserDynamics) {
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
+        ResponseEntity<String> postForEntity = null;
+        try {
+            log.info("请求Ai服务登录接口===================>");
+            postForEntity = restTemplate.postForEntity(loginUrl, requestEntity, String.class);
+        } catch (Exception e) {
+            log.error("请求AI服务登录接口失败", e);
+        }
+        RestTemplate restTemplateWithAuth = new RestTemplate();
+        if (postForEntity != null && postForEntity.getStatusCodeValue() == 200) {
+            log.info("请求Ai服务登录成功 postForEntity.getBody()\t" + postForEntity.getBody());
+            String responseBody = postForEntity.getBody();
+            JSONObject jsonObject = JSONObject.parseObject(responseBody);
+            if (jsonObject != null) {
+                JSONObject dataJson = jsonObject.getJSONObject("data");
+                String accessToken = dataJson.getString("access_token");
+                List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
+                interceptors.add((request, body, execution) -> {
+                    request.getHeaders().set("Authorization", "Bearer " + accessToken);
+                    return execution.execute(request, body);
+                });
+                restTemplateWithAuth.setInterceptors(interceptors);
+            }
+        }
+
+        List<StoreClockIn> storeClockIns = storeClockInMapper.selectList(new LambdaQueryWrapper<StoreClockIn>().eq(StoreClockIn::getCheckFlag, 1));
+        for (StoreClockIn storeClockIn : storeClockIns) {
             // 针对已提交且未删除的动态轮询查询结果
             try {
-                log.info("登录Ai服务获取token..." + loginUrl);
-                MultiValueMap<String, String> formData = new LinkedMultiValueMap<>();
-                formData.add("username", userName);
-                formData.add("password", passWord);
-
-                HttpHeaders headers = new HttpHeaders();
-                headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
-                HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(formData, headers);
-                ResponseEntity<String> postForEntity = null;
+                ResponseEntity<String> response = null;
                 try {
-                    log.info("请求Ai服务登录接口===================>");
-                    postForEntity = restTemplate.postForEntity(loginUrl, requestEntity, String.class);
+                    response = restTemplateWithAuth.getForEntity(getResultUrl + "?task_id=" + storeClockIn.getAiTaskId(), String.class);
+                    if (response.getStatusCodeValue() != 200) {
+                        log.error("AI内容审核结果获取接口调用失败 http状态:" + response.getStatusCode());
+                    }
+                    JSONObject responseNode = JSONObject.parseObject(response.getBody());
+                    if (responseNode == null) {
+                        log.error("AI接口调用失败,响应内容为空");
+                    }
+                    Integer code = null;
+                    if (responseNode != null) {
+                        code = responseNode.getInteger("code");
+                        if (code == 200) {
+                            JSONObject dataNode = JSONObject.from(responseNode.get("data"));
+                            StoreClockIn clockIn = new StoreClockIn();
+                            clockIn.setId(storeClockIn.getId());
+                            if ("completed".equals(dataNode.get("status"))) {
+                                if (!(boolean) dataNode.get("is_compliant")) {
+                                    // 只要 AI 判定不合规,立即禁用动态并记录原因
+                                    clockIn.setDeleteFlag(1);
+                                    clockIn.setReason(String.valueOf(dataNode.get("failure_reason")));
+                                }
+                                clockIn.setCheckFlag(2);
+                                storeClockInMapper.updateById(clockIn);
+                                if (!(boolean) dataNode.get("is_compliant")) {
+                                    storeClockInMapper.deleteById(clockIn);
+                                }
+                                log.info("动态审核结果获取成功,AI返回内容: {}", response.getBody());
+                                XxlJobHelper.handleSuccess("动态内容审核任务结果获取执行成功");
+                            } else {
+                                log.info("动态审核未完成,AI返回内容: {}", response.getBody());
+                            }
+                        } else {
+                            log.error("AI接口调用失败,错误码: " + code);
+                        }
+                    }
                 } catch (Exception e) {
-                    log.error("请求AI服务登录接口失败", e);
+                    log.error("调用AI内容审核结果获取接口失败", e);
                 }
+            } catch (RuntimeException ex) {
+                XxlJobHelper.handleFail("动态内容审核任务结果获取执行失败:" + ex.getMessage());
+                return R.fail("动态内容审核任务结果获取执行失败:" + ex.getMessage());
+            }
+        }
 
-                if (postForEntity != null && postForEntity.getStatusCodeValue() == 200) {
-                    log.info("请求Ai服务登录成功 postForEntity.getBody()\t" + postForEntity.getBody());
-                    String responseBody = postForEntity.getBody();
-                    JSONObject jsonObject = JSONObject.parseObject(responseBody);
-                    if (jsonObject != null) {
-                        JSONObject dataJson = jsonObject.getJSONObject("data");
-                        String accessToken = dataJson.getString("access_token");
-
-                        // 创建带拦截器的RestTemplate
-                        // 使用拦截器统一追加 Authorization,避免每次手动设置 header
-                        RestTemplate restTemplateWithAuth = new RestTemplate();
-                        List<ClientHttpRequestInterceptor> interceptors = new ArrayList<>();
-                        interceptors.add((request, body, execution) -> {
-                            request.getHeaders().set("Authorization", "Bearer " + accessToken);
-                            return execution.execute(request, body);
-                        });
-                        restTemplateWithAuth.setInterceptors(interceptors);
-
-                        ResponseEntity<String> response = null;
-                        try {
-                            response = restTemplateWithAuth.getForEntity(getResultUrl + "?task_id="+lifeUserDynamic.getAiTaskId(), String.class);
-                            if (response.getStatusCodeValue() != 200) {
-                                log.error("AI内容审核结果获取接口调用失败 http状态:" + response.getStatusCode());
-                            }
-                            JSONObject responseNode = JSONObject.parseObject(response.getBody());
-                            if (responseNode == null) {
-                                log.error("AI接口调用失败,响应内容为空");
-                            }
-                            Integer code = null;
-                            if (responseNode != null) {
-                                code = responseNode.getInteger("code");
-                                if(code==200) {
-                                    JSONObject dataNode = JSONObject.from(responseNode.get("data"));
-                                    LifeUserDynamics dynamics = new LifeUserDynamics();
-                                    if ("completed".equals(dataNode.get("status"))) {
-                                        if (!(boolean) dataNode.get("is_compliant")) {
-                                            // 只要 AI 判定不合规,立即禁用动态并记录原因
-                                            dynamics.setId(lifeUserDynamic.getId());
-                                            dynamics.setEnableStatus(1);
-                                            dynamics.setReason(String.valueOf(dataNode.get("failure_reason")));
-                                        }
-                                        dynamics.setCheckFlag(2);
-                                        lifeUserDynamicsMapper.updateById(dynamics);
-                                        log.info("动态审核结果获取成功,AI返回内容: {}", response.getBody());
-                                        XxlJobHelper.handleSuccess("动态内容审核任务结果获取执行成功");
-                                    } else {
-                                        log.info("动态审核未完成,AI返回内容: {}", response.getBody());
-                                    }
-                                } else {
-                                    log.error("AI接口调用失败,错误码: " + code);
+        for (LifeUserDynamics lifeUserDynamic : lifeUserDynamics) {
+            // 针对已提交且未删除的动态轮询查询结果
+            try {
+                ResponseEntity<String> response = null;
+                try {
+                    response = restTemplateWithAuth.getForEntity(getResultUrl + "?task_id=" + lifeUserDynamic.getAiTaskId(), String.class);
+                    if (response.getStatusCodeValue() != 200) {
+                        log.error("AI内容审核结果获取接口调用失败 http状态:" + response.getStatusCode());
+                    }
+                    JSONObject responseNode = JSONObject.parseObject(response.getBody());
+                    if (responseNode == null) {
+                        log.error("AI接口调用失败,响应内容为空");
+                    }
+                    Integer code = null;
+                    if (responseNode != null) {
+                        code = responseNode.getInteger("code");
+                        if (code == 200) {
+                            JSONObject dataNode = JSONObject.from(responseNode.get("data"));
+                            LifeUserDynamics dynamics = new LifeUserDynamics();
+                            dynamics.setId(lifeUserDynamic.getId());
+                            if ("completed".equals(dataNode.get("status"))) {
+                                if (!(boolean) dataNode.get("is_compliant")) {
+                                    // 只要 AI 判定不合规,立即禁用动态并记录原因
+                                    dynamics.setEnableStatus(1);
+                                    dynamics.setReason(String.valueOf(dataNode.get("failure_reason")));
                                 }
+                                dynamics.setCheckFlag(2);
+                                lifeUserDynamicsMapper.updateById(dynamics);
+                                log.info("动态审核结果获取成功,AI返回内容: {}", response.getBody());
+                                XxlJobHelper.handleSuccess("动态内容审核任务结果获取执行成功");
+                            } else {
+                                log.info("动态审核未完成,AI返回内容: {}", response.getBody());
                             }
-                        } catch (Exception e) {
-                            log.error("调用AI内容审核结果获取接口失败", e);
+                        } else {
+                            log.error("AI接口调用失败,错误码: " + code);
                         }
                     }
+                } catch (Exception e) {
+                    log.error("调用AI内容审核结果获取接口失败", e);
                 }
             } catch (RuntimeException ex) {
                 XxlJobHelper.handleFail("动态内容审核任务结果获取执行失败:" + ex.getMessage());

+ 17 - 0
alien-store/src/main/java/shop/alien/store/controller/LifeCouponController.java

@@ -10,6 +10,7 @@ import shop.alien.entity.result.R;
 import shop.alien.entity.store.EssentialHolidayComparison;
 import shop.alien.entity.store.LifeCoupon;
 import shop.alien.entity.store.vo.LifeCouponStatusVo;
+import shop.alien.entity.store.vo.LifeCouponVo;
 import shop.alien.store.service.LifeCouponService;
 
 import java.util.Map;
@@ -78,6 +79,22 @@ public class LifeCouponController {
         return R.data(lifeCouponService.getOne(objectLambdaQueryWrapper));
     }
 
+    @ApiOperation("代金卷详情")
+    @GetMapping("/getNewCouponDetail")
+    private R<LifeCouponVo> getNewCouponDetail(@RequestParam("id") String id) {
+        log.info("LifeCouponController.getNewCouponDetail?id={}", id);
+        try {
+            LifeCouponVo lifeCouponVo = lifeCouponService.getNewCouponDetail(id);
+            if (lifeCouponVo == null) {
+                return R.fail("代金券不存在或已删除");
+            }
+            return R.data(lifeCouponVo);
+        } catch (Exception e) {
+            log.error("LifeCouponController.getNewCouponDetail ERROR Msg={}", e.getMessage(), e);
+            return R.fail("查询失败");
+        }
+    }
+
     @ApiOperation("旧 核销订单")
     @ApiImplicitParams({@ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query", required = true), @ApiImplicitParam(name = "quanCode", value = "券码", dataType = "Integer", paramType = "query", required = true)})
     @GetMapping("/verify")

+ 11 - 0
alien-store/src/main/java/shop/alien/store/controller/StoreCommentController.java

@@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartRequest;
 import shop.alien.entity.result.R;
 import shop.alien.entity.store.vo.LifeUserOrderCommentVo;
+import shop.alien.entity.store.vo.StoreCommentCountVo;
 import shop.alien.entity.store.vo.StoreCommentVo;
 import shop.alien.entity.store.vo.StoreCommitPercentVo;
 import shop.alien.store.service.StoreCommentService;
@@ -154,4 +155,14 @@ public class StoreCommentController {
         log.info("StoreCommentController.getCommentOrderPage?pageNum={}&pageSize={}&type={}&userId={}", pageNum, pageSize, type, userId);
         return R.data(storeCommentService.getCommentOrderPage(pageNum, pageSize, type, userId));
     }
+
+    @ApiOperation("获取店铺评价计数统计")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getAppraiseCount")
+    public R<StoreCommentCountVo> getAppraiseCount(@RequestParam("storeId") Integer storeId) {
+        log.info("StoreCommentController.getAppraiseCount?storeId={}", storeId);
+        return R.data(storeCommentService.getAppraiseCount(storeId));
+    }
 }

+ 93 - 7
alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java

@@ -792,13 +792,13 @@ public class StoreInfoController {
     @ApiImplicitParams({
             @ApiImplicitParam(name = "lon", value = "经度", dataType = "double", paramType = "query", required = true),
             @ApiImplicitParam(name = "lat", value = "纬度", dataType = "double", paramType = "query", required = true),
-            @ApiImplicitParam(name = "category", value = "一级分类", dataType = "int", paramType = "query", required = true),
-            @ApiImplicitParam(name = "subCategory", value = "二级分类", dataType = "int", paramType = "query"),
-            @ApiImplicitParam(name = "threeCategory", value = "二级分类", dataType = "int", paramType = "query")
+            @ApiImplicitParam(name = "businessSection", value = "经营板块", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "businessTypes", value = "经营分类", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "businessClassify", value = "分类", dataType = "String", paramType = "query")
     })
-    public R<List<StoreInfoVo>> getMoreRecommendedStores(Double lon , Double lat, int category, int subCategory, int threeCategory) {
-        log.info("StoreInfoController.getMoreRecommendedStores?lon={},lat={},category={},subCategory={}", lon,lat, subCategory, threeCategory);
-        return R.data(storeInfoService.getMoreRecommendedStores(lon,lat, category, subCategory, threeCategory));
+    public R<List<StoreInfoVo>> getMoreRecommendedStores(Double lon , Double lat, String businessSection, String businessTypes, String businessClassify) {
+        log.info("StoreInfoController.getMoreRecommendedStores?lon={},lat={},businessSection={},businessTypes={},businessClassify={}", lon,lat, businessSection, businessTypes, businessClassify);
+        return R.data(storeInfoService.getMoreRecommendedStores(lon,lat, businessSection, businessTypes, businessClassify));
 
     }
     /**
@@ -820,7 +820,7 @@ public class StoreInfoController {
             @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Double", paramType = "query", required = true),
             @ApiImplicitParam(name = "distance", value = "距离范围(单位:公里)", dataType = "Double", paramType = "query"),
             @ApiImplicitParam(name = "sortType", value = "排序模式(1:智能排序,2:好评优先,3:距离优先)", dataType = "int", paramType = "query"),
-            @ApiImplicitParam(name = "businessType", value = "店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,酒吧=14)", dataType = "int", paramType = "query"),
+            @ApiImplicitParam(name = "businessType", value = "店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,酒吧=11)", dataType = "int", paramType = "query"),
             @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true),
             @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "int", paramType = "query", required = true)
     })
@@ -903,4 +903,90 @@ public class StoreInfoController {
             return R.fail("获取分类数据失败,请稍后重试");
         }
     }
+
+    /**
+     * 获取休闲娱乐分类数据(主分类和子分类)
+     * 根据图片需求,返回层级结构的分类数据
+     *getAllBusinessSection
+     * @return R<List<StoreDictionary>> 分类列表,包含主分类和子分类
+     */
+
+
+    @ApiOperation("获取所有经营板块以及子类")
+    @ApiOperationSupport(order = 18)
+    @GetMapping("/getAllBusinessSection")
+    public R<List<StoreDictionary>> queryBusinessSectionTree() {
+        log.info("platformBusinessSection.queryBusinessSectionTree");
+
+        try {
+            List<StoreDictionary> result = storeInfoService.getAllBusinessSection();
+            return R.data(result);
+        }catch (Exception e){
+            log.error("获取休闲娱乐分类数据异常", e);
+            return R.fail("获取分类数据失败,请稍后重试");
+        }
+
+    }
+
+    /**
+     * 获取门店下三级分类结构
+     */
+    @ApiOperation("获取门店下三级分类结构")
+    @ApiOperationSupport(order = 19)
+    @GetMapping("/getStoreThreeLevelStructure")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    public R<StoreThreeLevelStructureVo> getStoreThreeLevelStructure(@RequestParam("storeId") Integer storeId){
+        log.info("StoreInfoController.getStoreThreeLevelStructure?storeId={}", storeId);
+        try {
+            StoreThreeLevelStructureVo result = storeInfoService.getStoreThreeLevelStructure(storeId);
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("StoreInfoController.getStoreThreeLevelStructure ERROR Msg={}", e.getMessage(), e);
+            return R.fail("查询失败");
+        }
+    }
+
+    /**
+     * 你可能还喜欢(推荐店铺)
+     * 根据一级分类、二级分类、三级分类进行店铺筛选
+     * 筛选顺序:先三级,然后二级,最后一级
+     *
+     * @param businessSection 一级分类(经营板块)
+     * @param businessTypes 二级分类(经营种类)
+     * @param businessClassify 三级分类(分类)
+     * @param lon 经度
+     * @param lat 纬度
+     * @return R<List<StoreInfoVo>> 店铺信息列表
+     */
+    @ApiOperation("你可能还喜欢(推荐店铺)")
+    @ApiOperationSupport(order = 19)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "businessSection", value = "一级分类(经营板块)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "businessTypes", value = "二级分类(经营种类)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "businessClassify", value = "三级分类(分类)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "lon", value = "经度", dataType = "Double", paramType = "query"),
+            @ApiImplicitParam(name = "lat", value = "纬度", dataType = "Double", paramType = "query")
+    })
+    @GetMapping("/getRecommendedStores")
+    public R<List<StoreInfoVo>> getRecommendedStores(
+            @RequestParam(value = "businessSection", required = true) String businessSection,
+            @RequestParam(value = "businessTypes", required = false) String businessTypes,
+            @RequestParam(value = "businessClassify", required = false) String businessClassify,
+            @RequestParam(value = "lon", required = false) Double lon,
+            @RequestParam(value = "lat", required = false) Double lat) {
+        log.info("StoreInfoController.getRecommendedStores?businessSection={},businessTypes={},businessClassify={},lon={},lat={}", 
+                businessSection, businessTypes, businessClassify, lon, lat);
+        try {
+            List<StoreInfoVo> result = storeInfoService.getRecommendedStores(businessSection, businessTypes, businessClassify, lon, lat);
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("获取推荐店铺异常", e);
+            return R.fail("获取推荐店铺失败,请稍后重试");
+        }
+    }
+
+
+
 }

+ 7 - 5
alien-store/src/main/java/shop/alien/store/controller/StoreMenuController.java

@@ -154,7 +154,7 @@ public class StoreMenuController {
     public R<Map<String, Object>> getClientMenuByStoreId(
             @RequestParam(value = "storeId", required = true) Integer storeId,
             @RequestParam(value = "dishType", required = false) Integer dishType,
-            @RequestParam(value = "phoneId", required = false) String phoneId,
+            @RequestParam(value = "phoneId", required = true) String phoneId,
             @RequestParam(value = "dishMenuType", required = false) Integer dishMenuType) {
         // 记录请求入参
         log.info("获取用户端菜单,入参:storeId={}, dishType={}, phoneId={}, dishMenuType={}", 
@@ -186,10 +186,12 @@ public class StoreMenuController {
 
     @ApiOperation("获取门店菜单详情(用户端)")
     @ApiOperationSupport(order = 4)
-    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "菜单ID", dataType = "Integer", paramType = "query")})
+    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "菜单ID", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "phoneId", value = "用户手机号", dataType = "String", paramType = "query")})
     @GetMapping("/getClientMenuInfoById")
-    public R<StoreMenuVo> getClientMenuInfoById(Integer id) {
-        log.info("StoreRecommendController.getClientMenuInfoById?id={}", id);
-        return R.data(storeMenuService.getClientMenuInfoById(id));
+    public R<StoreMenuVo> getClientMenuInfoById(@RequestParam(value = "id", required = true) Integer id,
+                                                @RequestParam(value = "phoneId", required = true) String phoneId) {
+        log.info("StoreRecommendController.getClientMenuInfoById?id={},phoneId={}", id, phoneId);
+        return R.data(storeMenuService.getClientMenuInfoById(id, phoneId));
     }
 }

+ 7 - 2
alien-store/src/main/java/shop/alien/store/service/LifeCouponService.java

@@ -2,9 +2,7 @@ package shop.alien.store.service;
 
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
-import org.springframework.web.bind.annotation.RequestParam;
 import shop.alien.entity.result.R;
-import org.springframework.web.bind.annotation.RequestParam;
 import shop.alien.entity.store.EssentialHolidayComparison;
 import shop.alien.entity.store.LifeCoupon;
 import shop.alien.entity.store.vo.LifeCouponStatusVo;
@@ -56,4 +54,11 @@ public interface LifeCouponService extends IService<LifeCoupon> {
      * @return
      */
     R<String> orderVerify(String orderCode);
+
+    /**
+     * 获取代金券详情(包含商铺信息)
+     * @param id 代金券ID
+     * @return LifeCouponVo
+     */
+    shop.alien.entity.store.vo.LifeCouponVo getNewCouponDetail(String id);
 }

+ 9 - 0
alien-store/src/main/java/shop/alien/store/service/StoreCommentService.java

@@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import org.springframework.web.multipart.MultipartRequest;
 import shop.alien.entity.store.StoreComment;
 import shop.alien.entity.store.vo.LifeUserOrderCommentVo;
+import shop.alien.entity.store.vo.StoreCommentCountVo;
 import shop.alien.entity.store.vo.StoreCommentVo;
 import shop.alien.entity.store.vo.StoreCommitPercentVo;
 
@@ -104,4 +105,12 @@ public interface StoreCommentService extends IService<StoreComment> {
      */
     IPage<LifeUserOrderCommentVo> getCommentOrderPage(Integer pageNum, Integer pageSize, Integer type, String userId);
 
+    /**
+     * 获取店铺评价计数统计
+     *
+     * @param storeId 门店id
+     * @return StoreCommentCountVo
+     */
+    StoreCommentCountVo getAppraiseCount(Integer storeId);
+
 }

+ 29 - 5
alien-store/src/main/java/shop/alien/store/service/StoreInfoService.java

@@ -4,10 +4,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.multipart.MultipartRequest;
-import shop.alien.entity.store.StoreBusinessInfo;
-import shop.alien.entity.store.StoreImg;
-import shop.alien.entity.store.StoreInfo;
-import shop.alien.entity.store.StoreInfoDraft;
+import shop.alien.entity.store.*;
 import shop.alien.entity.store.dto.StoreInfoDto;
 import shop.alien.entity.store.vo.*;
 
@@ -291,7 +288,7 @@ public interface StoreInfoService extends IService<StoreInfo> {
 
      * @return IPage<StoreInfoVo>
      */
-    List<StoreInfoVo> getMoreRecommendedStores(Double lon , Double lat, int category, int subcategory, int threeCategory);
+    List<StoreInfoVo> getMoreRecommendedStores(Double lon , Double lat, String businessSection, String businessTypes, String businessClassify);
 
 
     /**
@@ -311,6 +308,7 @@ public interface StoreInfoService extends IService<StoreInfo> {
      * @param distance    距离范围(单位:公里)
      * @param sortType    排序模式(1:智能排序,2:好评优先,3:距离优先)
      * @param businessType 店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,酒吧需要查询字典表),可选
+     * @param categoryId  分类ID(二级或三级分类的dictId,从getAllBusinessSection接口获取),可选
      * @param pageNum     页码
      * @param pageSize    页容
      * @return IPage<StoreInfoVo> 分页的门店信息列表
@@ -329,4 +327,30 @@ public interface StoreInfoService extends IService<StoreInfo> {
      * @return List<StoreDictionaryVo> 分类列表,包含主分类和子分类
      */
     List<StoreDictionaryVo> getLeisureEntertainmentCategories();
+
+
+    List<StoreDictionary> getAllBusinessSection();
+
+    /**
+     * 获取门店下三级分类结构
+     * 根据门店ID查询该门店的经营板块、经营种类和分类的三级结构
+     *
+     * @param storeId 门店ID
+     * @return StoreThreeLevelStructureVo 包含门店信息和三级分类树形结构
+     */
+    StoreThreeLevelStructureVo getStoreThreeLevelStructure(Integer storeId);
+
+    /**
+     * 你可能还喜欢(推荐店铺)
+     * 根据一级分类、二级分类、三级分类进行店铺筛选
+     * 筛选顺序:先三级,然后二级,最后一级
+     *
+     * @param businessSection 一级分类(经营板块)
+     * @param businessTypes 二级分类(经营种类)
+     * @param businessClassify 三级分类(分类)
+     * @param lon 经度
+     * @param lat 纬度
+     * @return List<StoreInfoVo> 店铺信息列表
+     */
+    List<StoreInfoVo> getRecommendedStores(String businessSection, String businessTypes, String businessClassify, Double lon, Double lat);
 }

+ 1 - 1
alien-store/src/main/java/shop/alien/store/service/StoreMenuService.java

@@ -103,6 +103,6 @@ public interface StoreMenuService extends IService<StoreMenu> {
      * @param id 菜品id
      * @return StoreMenuVo
      */
-    StoreMenuVo getClientMenuInfoById(Integer id);
+    StoreMenuVo getClientMenuInfoById(Integer id, String phoneId);
 }
 

+ 4 - 0
alien-store/src/main/java/shop/alien/store/service/impl/LawyerConsultationOrderServiceImpl.java

@@ -537,6 +537,10 @@ public class LawyerConsultationOrderServiceImpl extends ServiceImpl<LawyerConsul
                 request.getOrderNumber(), request.getPaymentStatus(), request.getOrderStatus());
 
         LawyerConsultationOrderDto order = new LawyerConsultationOrderDto();
+
+        if (null != request.getOrderStr()){
+            order.setOrderStr(request.getOrderStr());
+        }
         order.setOrderNumber(request.getOrderNumber());
         order.setPaymentStatus(request.getPaymentStatus());
         order.setOrderStatus(request.getOrderStatus());

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

@@ -702,4 +702,9 @@ public class LifeCouponServiceImpl extends ServiceImpl<LifeCouponMapper, LifeCou
         return R.success("效验通过");
     }
 
+    @Override
+    public shop.alien.entity.store.vo.LifeCouponVo getNewCouponDetail(String id) {
+        return lifeCouponMapper.getNewCouponDetail(id);
+    }
+
 }

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

@@ -347,8 +347,10 @@ public class LifeDiscountCouponServiceImpl extends ServiceImpl<LifeDiscountCoupo
         try{
             LocalDateTime now = LocalDateTime.now();
             //根据店铺id查询该店铺的优惠券,状态是开启领取的券
-            List<LifeDiscountCoupon> lifeDiscountCoupons = lifeDiscountCouponMapper.selectList(new LambdaQueryWrapper<LifeDiscountCoupon>().eq(LifeDiscountCoupon::getStoreId, storeId).eq(LifeDiscountCoupon::getGetStatus, "1") //还有库存
-                    .ge(LifeDiscountCoupon::getEndGetDate, LocalDate.now()).orderByDesc(LifeDiscountCoupon::getCreatedTime));
+            List<LifeDiscountCoupon> lifeDiscountCoupons = lifeDiscountCouponMapper.selectList(new LambdaQueryWrapper<LifeDiscountCoupon>()
+                    .eq(LifeDiscountCoupon::getStoreId, storeId).eq(LifeDiscountCoupon::getGetStatus, "1") //还有库存
+                    .ge(LifeDiscountCoupon::getEndGetDate, LocalDate.now())
+                    .orderByDesc(LifeDiscountCoupon::getAttentionCanReceived));
             //根据优惠券列表查询该优惠券是否领取过
             for (LifeDiscountCoupon lifeDiscountCoupon : lifeDiscountCoupons) {
                 LifeDiscountCouponVo lifeDiscountCouponVo = new LifeDiscountCouponVo();

+ 97 - 78
alien-store/src/main/java/shop/alien/store/service/impl/PlatformBusinessSectionServiceImpl.java

@@ -52,9 +52,9 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
     public List<StoreDictionary> queryBusinessSectionTree() {
         // 查询所有经营种类数据
         LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(StoreDictionary::getTypeName, "business_section");
+        queryWrapper.in(StoreDictionary::getTypeName, "business_section","business_type","business_classify");
         queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
-        queryWrapper.orderByAsc(StoreDictionary::getDictId);
+        queryWrapper.orderByAsc(StoreDictionary::getSortId);
         List<StoreDictionary> storeDictionaryList = storeDictionaryMapper.selectList(queryWrapper);
 
         // 构建三级树形结构
@@ -122,7 +122,7 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
         }
 
         // 设置固定字段
-        storeDictionary.setTypeName("business_section");
+//        storeDictionary.setTypeName("business_section");
 //        storeDictionary.setTypeDetail("经营板块");
         storeDictionary.setDeleteFlag(0);
         storeDictionary.setCreatedTime(new Date());
@@ -137,7 +137,7 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
         // 如果是二级或三级,验证父节点是否存在
         if (parentId != 0) {
             StoreDictionary parent = storeDictionaryMapper.selectById(parentId);
-            if (parent == null || !"business_section".equals(parent.getTypeName()) || parent.getDeleteFlag() == 1) {
+            if (parent == null || parent.getDeleteFlag() == 1) {
                 throw new IllegalArgumentException("父节点不存在或已删除");
             }
         }
@@ -147,6 +147,10 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
         int nextDictId = (maxDictId == null ? 0 : Integer.parseInt(maxDictId)) + 1;
         storeDictionary.setDictId(String.valueOf(nextDictId));
 
+        // 生成 sort_id
+        Integer maxSortId = getMaxSortIdByParentId(parentId);
+        storeDictionary.setSortId(maxSortId == null ? 1 : maxSortId + 1);
+
         // 保存
         return this.save(storeDictionary);
     }
@@ -202,8 +206,8 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
         // 标准化parentId用于比较(null转为0)
         Integer normalizedParentId = (parentId == null) ? 0 : parentId;
         Integer normalizedExistingParentId = (existingParentId == null) ? 0 : existingParentId;
-        String oldDictId = existing.getDictId();
-        String newDictId = storeDictionary.getDictId();
+        Integer oldSortId = existing.getSortId();
+        Integer newSortId = storeDictionary.getSortId();
         boolean parentIdChanged = !normalizedParentId.equals(normalizedExistingParentId);
         
         // 判断是否修改了关键字段(parent_id)
@@ -221,41 +225,41 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
         if (parentIdChanged) {
             if (parentId != 0) {
                 StoreDictionary parent = storeDictionaryMapper.selectById(parentId);
-                if (parent == null || !"business_section".equals(parent.getTypeName()) || parent.getDeleteFlag() == 1) {
+                if (parent == null || parent.getDeleteFlag() == 1) {
                     throw new IllegalArgumentException("父节点不存在或已删除");
                 }
             }
             
-            // 如果用户指定了新位置(newDictId不为空),使用用户指定的位置
+            // 如果用户指定了新位置(newSortId不为空),使用用户指定的位置
             // 否则,使用新节点下的最大+1
-            if (StringUtils.isBlank(newDictId)) {
-                String maxDictId = getMaxDictIdByParentId(parentId);
-                int nextDictId = (maxDictId == null ? 0 : Integer.parseInt(maxDictId)) + 1;
-                newDictId = String.valueOf(nextDictId);
-                storeDictionary.setDictId(newDictId);
+            if (newSortId == null) {
+                Integer maxSortId = getMaxSortIdByParentId(parentId);
+                int nextSortId = (maxSortId == null ? 1 : maxSortId) + 1;
+                newSortId = nextSortId;
+                storeDictionary.setSortId(newSortId);
             }
             
             // 原节点下,原位置之后的记录需要前移(dictId - 1)
-            adjustSortOrderForMoveOut(existing.getId(), normalizedExistingParentId, oldDictId);
+            adjustSortOrderForMoveOut(existing.getId(), normalizedExistingParentId, oldSortId);
             
             // 新节点下,如果指定了新位置,需要调整新节点下的排序
-            if (StringUtils.isNotBlank(newDictId)) {
+            if (newSortId != null) {
                 try {
-                    int newOrder = Integer.parseInt(newDictId);
-                    String maxDictId = getMaxDictIdByParentId(parentId);
-                    int maxOrder = (maxDictId == null ? 0 : Integer.parseInt(maxDictId));
+                    int newOrder = newSortId;
+                    Integer maxSortId = getMaxSortIdByParentId(parentId);
+                    int maxOrder = (maxSortId == null ? 0 : maxSortId);
                     // 如果新位置不是最大+1,需要调整新节点下的排序
                     if (newOrder <= maxOrder) {
-                        adjustSortOrderForMoveIn(existing.getId(), normalizedParentId, newDictId);
+                        adjustSortOrderForMoveIn(existing.getId(), normalizedParentId, newSortId);
                     }
                 } catch (NumberFormatException e) {
-                    log.warn("无法解析新dictId: {}", newDictId, e);
+                    log.warn("无法解析新sortId: {}", newSortId, e);
                 }
             }
         }
 
         // 设置固定字段
-        storeDictionary.setTypeName("business_section");
+//        storeDictionary.setTypeName("business_section");
         // 如果没有指定删除标记,保持原有值;如果指定了,使用新值
         Integer oldHidden = existing.getHidden();
         Integer newHidden = storeDictionary.getHidden() == null ? oldHidden : storeDictionary.getHidden();
@@ -268,11 +272,11 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
         // 处理排序逻辑:如果 parentId 没有改变,但 dictId 改变了,需要调整同级其他记录的排序
         if (!parentIdChanged) {
             // 如果 dictId 为空,保持原有值
-            if (StringUtils.isBlank(newDictId)) {
-                storeDictionary.setDictId(oldDictId);
-            } else if (!newDictId.equals(oldDictId)) {
+            if (newSortId == null) {
+                storeDictionary.setSortId(oldSortId);
+            } else if (!newSortId.equals(oldSortId)) {
                 // 调整同级其他记录的排序
-                adjustSortOrder(existing.getId(), normalizedParentId, oldDictId, newDictId);
+                adjustSortOrder(existing.getId(), normalizedParentId, oldSortId, newSortId);
             }
         }
 
@@ -297,7 +301,7 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
      */
     private boolean hasUndeletedChildren(Integer parentId) {
         LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(StoreDictionary::getTypeName, "business_section");
+        queryWrapper.in(StoreDictionary::getTypeName, "business_section","business_type","business_classify");;
         queryWrapper.eq(StoreDictionary::getParentId, parentId);
         queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
         queryWrapper.last("LIMIT 1");
@@ -320,7 +324,7 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
         
         // 查询所有未删除的子节点
         LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(StoreDictionary::getTypeName, "business_section");
+        queryWrapper.in(StoreDictionary::getTypeName, "business_section","business_type","business_classify");
         queryWrapper.eq(StoreDictionary::getParentId, parentId);
         queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
         
@@ -350,7 +354,7 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
      */
     private String getMaxDictIdByParentId(Integer parentId) {
         LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(StoreDictionary::getTypeName, "business_section");
+        queryWrapper.in(StoreDictionary::getTypeName, "business_section","business_type","business_classify");;
         queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
         
         if (parentId == null || parentId == 0) {
@@ -368,19 +372,44 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
     }
 
     /**
+     * 根据parentId获取最大的sortId
+     *
+     * @param parentId 父节点ID
+     * @return 最大的sortId,如果不存在则返回null
+     */
+    private Integer getMaxSortIdByParentId(Integer parentId) {
+        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.in(StoreDictionary::getTypeName, "business_section","business_type","business_classify");;
+        queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
+        
+        if (parentId == null || parentId == 0) {
+            queryWrapper.and(wrapper -> wrapper.isNull(StoreDictionary::getParentId)
+                    .or().eq(StoreDictionary::getParentId, 0));
+        } else {
+            queryWrapper.eq(StoreDictionary::getParentId, parentId);
+        }
+        
+        queryWrapper.orderByDesc(StoreDictionary::getSortId);
+        queryWrapper.last("LIMIT 1");
+        
+        StoreDictionary maxDict = storeDictionaryMapper.selectOne(queryWrapper);
+        return maxDict != null && maxDict.getSortId() != null ? maxDict.getSortId() : null;
+    }
+
+    /**
      * 调整排序:当记录的dictId改变时,调整同级其他记录的排序
      * 上升则顺推:如果新dictId < 原dictId,将原dictId到新dictId之间的记录的dictId都+1
      * 下降则顺升:如果新dictId > 原dictId,将原dictId到新dictId之间的记录的dictId都-1
      *
      * @param currentId 当前记录ID
      * @param parentId 父节点ID
-     * @param oldDictId 原dictId
-     * @param newDictId 新dictId
+     * @param oldSortId 原sortId
+     * @param newSortId 新sortId
      */
-    private void adjustSortOrder(Integer currentId, Integer parentId, String oldDictId, String newDictId) {
+    private void adjustSortOrder(Integer currentId, Integer parentId, Integer oldSortId, Integer newSortId) {
         try {
-            int oldOrder = Integer.parseInt(oldDictId);
-            int newOrder = Integer.parseInt(newDictId);
+            int oldOrder = oldSortId;
+            int newOrder = newSortId;
             
             // 如果排序没有改变,直接返回
             if (oldOrder == newOrder) {
@@ -389,7 +418,7 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
             
             // 查询同级所有记录(排除当前记录)
             LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
-            queryWrapper.eq(StoreDictionary::getTypeName, "business_section");
+            queryWrapper.in(StoreDictionary::getTypeName, "business_section","business_type","business_classify");;
             queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
             queryWrapper.ne(StoreDictionary::getId, currentId);
             
@@ -411,14 +440,14 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
                 // 将新dictId到原dictId之间的记录的dictId都+1
                 for (StoreDictionary sibling : siblings) {
                     try {
-                        int siblingOrder = Integer.parseInt(sibling.getDictId());
+                        int siblingOrder = sibling.getSortId();
                         if (siblingOrder >= newOrder && siblingOrder < oldOrder) {
-                            sibling.setDictId(String.valueOf(siblingOrder + 1));
+                            sibling.setSortId(siblingOrder + 1);
                             sibling.setUpdatedTime(new Date());
                             storeDictionaryMapper.updateById(sibling);
                         }
                     } catch (NumberFormatException e) {
-                        log.warn("无法解析dictId: {}", sibling.getDictId(), e);
+                        log.warn("无法解析sortId: {}", sibling.getSortId(), e);
                     }
                 }
             } 
@@ -427,19 +456,19 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
                 // 将原dictId到新dictId之间的记录的dictId都-1
                 for (StoreDictionary sibling : siblings) {
                     try {
-                        int siblingOrder = Integer.parseInt(sibling.getDictId());
+                        int siblingOrder = sibling.getSortId();
                         if (siblingOrder > oldOrder && siblingOrder <= newOrder) {
-                            sibling.setDictId(String.valueOf(siblingOrder - 1));
+                            sibling.setSortId(siblingOrder - 1);
                             sibling.setUpdatedTime(new Date());
                             storeDictionaryMapper.updateById(sibling);
                         }
                     } catch (NumberFormatException e) {
-                        log.warn("无法解析dictId: {}", sibling.getDictId(), e);
+                        log.warn("无法解析sortId: {}", sibling.getSortId(), e);
                     }
                 }
             }
         } catch (NumberFormatException e) {
-            log.error("调整排序失败,dictId格式错误: oldDictId={}, newDictId={}", oldDictId, newDictId, e);
+            log.error("调整排序失败,sortId格式错误: oldSortId={}, newSortId={}", oldSortId, newSortId, e);
         } catch (Exception e) {
             log.error("调整排序失败", e);
         }
@@ -450,15 +479,15 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
      *
      * @param currentId 当前记录ID
      * @param oldParentId 原父节点ID
-     * @param oldDictId 原dictId
+     * @param oldSortId 原sortId
      */
-    private void adjustSortOrderForMoveOut(Integer currentId, Integer oldParentId, String oldDictId) {
+    private void adjustSortOrderForMoveOut(Integer currentId, Integer oldParentId, Integer oldSortId) {
         try {
-            int oldOrder = Integer.parseInt(oldDictId);
+            int oldOrder = oldSortId;
             
             // 查询原节点同级所有记录(排除当前记录)
             LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
-            queryWrapper.eq(StoreDictionary::getTypeName, "business_section");
+            queryWrapper.in(StoreDictionary::getTypeName, "business_section","business_type","business_classify");;
             queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
             queryWrapper.ne(StoreDictionary::getId, currentId);
             
@@ -478,18 +507,18 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
             // 原位置之后的记录需要前移(dictId - 1)
             for (StoreDictionary sibling : siblings) {
                 try {
-                    int siblingOrder = Integer.parseInt(sibling.getDictId());
+                    int siblingOrder = sibling.getSortId();
                     if (siblingOrder > oldOrder) {
-                        sibling.setDictId(String.valueOf(siblingOrder - 1));
+                        sibling.setSortId(siblingOrder - 1);
                         sibling.setUpdatedTime(new Date());
                         storeDictionaryMapper.updateById(sibling);
                     }
                 } catch (NumberFormatException e) {
-                    log.warn("无法解析dictId: {}", sibling.getDictId(), e);
+                    log.warn("无法解析sortId: {}", sibling.getSortId(), e);
                 }
             }
         } catch (NumberFormatException e) {
-            log.error("移出节点排序调整失败,dictId格式错误: oldDictId={}", oldDictId, e);
+            log.error("移出节点排序调整失败,sortId格式错误: oldSortId={}", oldSortId, e);
         } catch (Exception e) {
             log.error("移出节点排序调整失败", e);
         }
@@ -500,15 +529,15 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
      *
      * @param currentId 当前记录ID
      * @param newParentId 新父节点ID
-     * @param newDictId 新dictId
+     * @param newSortId 新sortId
      */
-    private void adjustSortOrderForMoveIn(Integer currentId, Integer newParentId, String newDictId) {
+    private void adjustSortOrderForMoveIn(Integer currentId, Integer newParentId, Integer newSortId) {
         try {
-            int newOrder = Integer.parseInt(newDictId);
+            int newOrder = newSortId;
             
             // 查询新节点同级所有记录(排除当前记录)
             LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
-            queryWrapper.eq(StoreDictionary::getTypeName, "business_section");
+            queryWrapper.in(StoreDictionary::getTypeName, "business_section","business_type","business_classify");;
             queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
             queryWrapper.ne(StoreDictionary::getId, currentId);
             
@@ -528,9 +557,9 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
             // 新位置之后的记录需要后移(dictId + 1)
             for (StoreDictionary sibling : siblings) {
                 try {
-                    int siblingOrder = Integer.parseInt(sibling.getDictId());
+                    int siblingOrder = sibling.getSortId();
                     if (siblingOrder >= newOrder) {
-                        sibling.setDictId(String.valueOf(siblingOrder + 1));
+                        sibling.setSortId(siblingOrder + 1);
                         sibling.setUpdatedTime(new Date());
                         storeDictionaryMapper.updateById(sibling);
                     }
@@ -539,7 +568,7 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
                 }
             }
         } catch (NumberFormatException e) {
-            log.error("移入节点排序调整失败,dictId格式错误: newDictId={}", newDictId, e);
+            log.error("移入节点排序调整失败,sortId格式错误: newSortId={}", newSortId, e);
         } catch (Exception e) {
             log.error("移入节点排序调整失败", e);
         }
@@ -733,7 +762,7 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
                                      int level, String hidden, List<String> errorMessages, int rowIndex) {
         try {
             // 查找或创建一级分类
-            StoreDictionary firstLevel = findOrCreateLevel(firstLevelName, 0, 0, hidden);
+            StoreDictionary firstLevel = findOrCreateLevel(firstLevelName, null, 0, hidden);
             if (firstLevel == null) {
                 throw new IllegalArgumentException("创建一级分类失败");
             }
@@ -769,7 +798,7 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
     private StoreDictionary findOrCreateLevel(String dictDetail, Integer parentId, int expectedLevel, String hidden) {
         // 查找是否存在
         LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(StoreDictionary::getTypeName, "business_section");
+        queryWrapper.in(StoreDictionary::getTypeName, "business_section","business_type","business_classify");;
         queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
         queryWrapper.eq(StoreDictionary::getDictDetail, dictDetail);
 
@@ -788,40 +817,30 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
 
         // 创建新分类
         StoreDictionary newDict = new StoreDictionary();
-        newDict.setTypeName("business_section");
         newDict.setDictDetail(dictDetail);
         // 一级为经营版块 ,二级为经营种类,三级为分类
         if (expectedLevel == 0) {
             newDict.setTypeDetail("经营板块");
+            newDict.setTypeName("business_section");
         } else if (expectedLevel == 1) {
             newDict.setTypeDetail("经营种类");
+            newDict.setTypeName("business_type");
         } else if (expectedLevel == 2) {
             newDict.setTypeDetail("分类");
+            newDict.setTypeName("business_classify");
         }
-        newDict.setParentId(parentId == null ? 0 : parentId);
+        newDict.setParentId(parentId == null ? null : parentId);
         newDict.setHidden(StringUtils.isNotBlank(hidden) && hidden.equals("隐藏") ? 1 : 0);
         newDict.setDeleteFlag(0);
         newDict.setCreatedTime(new Date());
 
         // 生成 dict_id
         String maxDictId = getMaxDictIdByParentId(newDict.getParentId());
-        /*int nextDictId;
-        if (StringUtils.isNotBlank(sortOrder) && expectedLevel == 1) {
-            try {
-                nextDictId = Integer.parseInt(sortOrder);
-                // 如果指定的排序已存在,需要调整
-                String existingDictId = getDictIdByParentIdAndOrder(newDict.getParentId(), nextDictId);
-                if (existingDictId != null) {
-                    // 使用最大+1
-                    nextDictId = (maxDictId == null ? 0 : Integer.parseInt(maxDictId)) + 1;
-                }
-            } catch (NumberFormatException e) {
-                nextDictId = (maxDictId == null ? 0 : Integer.parseInt(maxDictId)) + 1;
-            }
-        } else {
-            nextDictId = (maxDictId == null ? 0 : Integer.parseInt(maxDictId)) + 1;
-        }*/
         newDict.setDictId(String.valueOf(maxDictId == null ? 1 : Integer.parseInt(maxDictId) + 1));
+        
+        // 生成 sort_id
+        Integer maxSortId = getMaxSortIdByParentId(newDict.getParentId());
+        newDict.setSortId(maxSortId == null ? 1 : maxSortId + 1);
 
         boolean saved = this.save(newDict);
         return saved ? newDict : null;
@@ -836,7 +855,7 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
      */
     private String getDictIdByParentIdAndOrder(Integer parentId, int order) {
         LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.eq(StoreDictionary::getTypeName, "business_section");
+        queryWrapper.in(StoreDictionary::getTypeName, "business_section","business_type","business_classify");;
         queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
         queryWrapper.eq(StoreDictionary::getDictId, String.valueOf(order));
         
@@ -848,7 +867,7 @@ public class PlatformBusinessSectionServiceImpl extends ServiceImpl<StoreDiction
         }
         
         StoreDictionary dict = storeDictionaryMapper.selectOne(queryWrapper);
-        return dict != null ? dict.getDictId() : null;
+        return dict != null ? dict.getSortId().toString() : null;
     }
 
     /**

+ 51 - 0
alien-store/src/main/java/shop/alien/store/service/impl/StoreCommentServiceImpl.java

@@ -815,4 +815,55 @@ public class StoreCommentServiceImpl extends ServiceImpl<StoreCommentMapper, Sto
         }
         return commentOrderPage;
     }
+
+    /**
+     * 获取店铺评价计数统计
+     *
+     * @param storeId 门店id
+     * @return StoreCommentCountVo
+     */
+    @Override
+    public StoreCommentCountVo getAppraiseCount(Integer storeId) {
+        StoreCommentCountVo countVo = new StoreCommentCountVo();
+
+        // 查询条件:只统计当前门店、根评论(reply_id为null)、未删除的评论
+        LambdaQueryWrapper<StoreComment> totalWrapper = buildBaseStoreCommentWrapper(storeId);
+        countVo.setTotalCount(storeCommentMapper.selectCount(totalWrapper));
+
+        // 2. 有图评论数(img_id不为空且不为空字符串)
+        LambdaQueryWrapper<StoreComment> imageWrapper = buildBaseStoreCommentWrapper(storeId);
+        imageWrapper.isNotNull(StoreComment::getImgId)
+                .apply("img_id != ''");
+        countVo.setImageCount(storeCommentMapper.selectCount(imageWrapper));
+
+        // 3. 好评数(score >= 4.5)
+        LambdaQueryWrapper<StoreComment> goodWrapper = buildBaseStoreCommentWrapper(storeId);
+        goodWrapper.ge(StoreComment::getScore, 4.5);
+        countVo.setGoodCount(storeCommentMapper.selectCount(goodWrapper));
+
+        // 4. 中评数(score >= 3 && score <= 4)
+        LambdaQueryWrapper<StoreComment> midWrapper = buildBaseStoreCommentWrapper(storeId);
+        midWrapper.ge(StoreComment::getScore, 3.0)
+                .le(StoreComment::getScore, 4.0);
+        countVo.setMidCount(storeCommentMapper.selectCount(midWrapper));
+
+        // 5. 差评数(score >= 0.5 && score <= 2.5)
+        LambdaQueryWrapper<StoreComment> badWrapper = buildBaseStoreCommentWrapper(storeId);
+        badWrapper.ge(StoreComment::getScore, 0.5)
+                .le(StoreComment::getScore, 2.5);
+        countVo.setBadCount(storeCommentMapper.selectCount(badWrapper));
+
+        return countVo;
+    }
+
+    /**
+     * 构建当前门店根评论的查询条件
+     */
+    private LambdaQueryWrapper<StoreComment> buildBaseStoreCommentWrapper(Integer storeId) {
+        return new LambdaQueryWrapper<StoreComment>()
+                .eq(StoreComment::getStoreId, storeId)
+                .gt(StoreComment::getScore,0 )
+                .eq(StoreComment::getBusinessType, 5)
+                .eq(StoreComment::getDeleteFlag, 0);
+    }
 }

+ 436 - 78
alien-store/src/main/java/shop/alien/store/service/impl/StoreInfoServiceImpl.java

@@ -381,6 +381,7 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
         } else if (CommonConstant.FOOD_LICENCE_NOT_EXPIRED_STATUS.equals(foodLicenceWhetherExpiredStatus)) {//经营许可证筛选状态 2 查询食品经营许可证未到期 距离到期时间大于30天以上
             queryWrapper.gt("a.food_licence_expiration_time", nowDay.plusDays(31));
         }
+        //查出所有店铺
         IPage<StoreInfoVo> storeInfoVoPage = storeInfoMapper.getStoreInfoVoPage(iPage, queryWrapper);
         List<StoreInfoVo> records = storeInfoVoPage.getRecords();
         if (!records.isEmpty()) {
@@ -957,8 +958,12 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
 
     @Override
     public List<StoreDictionaryVo> getBusinessSectionTypes(String parentId) {
-        StoreDictionary businessSection = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getTypeName, "business_section").eq(StoreDictionary::getDictId, parentId));
-        List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(new LambdaQueryWrapper<StoreDictionary>().eq(StoreDictionary::getParentId, businessSection.getId()));
+        StoreDictionary businessSection = storeDictionaryMapper.selectOne(new LambdaQueryWrapper<StoreDictionary>()
+                .eq(StoreDictionary::getTypeName, "business_section")
+                .eq(StoreDictionary::getDictId, parentId)
+                .isNull(StoreDictionary::getParentId));
+        List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(new LambdaQueryWrapper<StoreDictionary>()
+                .eq(StoreDictionary::getParentId, businessSection.getId()));
         List<StoreDictionaryVo> voList = new ArrayList<>();
         for (StoreDictionary storeDictionary : storeDictionaries) {
             StoreDictionaryVo vo = new StoreDictionaryVo();
@@ -2479,7 +2484,7 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
         } else {
             // 如果没有指定businessType,则查询所有四种类型的店铺
             // 需要查询字典表获取所有四种类型的dictId
-            List<String> storeTypeNames = Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足");
+            List<String> storeTypeNames = Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足");
             List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(
                     new LambdaQueryWrapper<StoreDictionary>()
                             .eq(StoreDictionary::getTypeName, "business_section")
@@ -2487,28 +2492,18 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
                             .eq(StoreDictionary::getDeleteFlag, 0)
             );
             
-            // 构建business_section的ID列表
-            List<Integer> businessSectionIds = new ArrayList<>();
-            businessSectionIds.add(3); // KTV
-            businessSectionIds.add(4); // 洗浴汗蒸
-            businessSectionIds.add(5); // 按摩足浴
-            businessSectionIds.add(14);// 酒吧
-            
-            // 添加从字典表查询到的其他类型(如酒吧)
-            if (!CollectionUtils.isEmpty(storeDictionaries)) {
-                for (StoreDictionary dict : storeDictionaries) {
-                    if (StringUtils.isNotEmpty(dict.getDictId())) {
+            List<Integer> businessSectionIds = storeDictionaries.stream()
+                    .filter(dict -> StringUtils.isNotEmpty(dict.getDictId()))
+                    .map(StoreDictionary::getDictId)
+                    .map(dictId -> {
                         try {
-                            Integer dictId = Integer.parseInt(dict.getDictId());
-                            if (!businessSectionIds.contains(dictId)) {
-                                businessSectionIds.add(dictId);
-                            }
+                            return Integer.parseInt(dictId);
                         } catch (NumberFormatException e) {
-                            // 忽略非数字的dictId
+                            return null;
                         }
-                    }
-                }
-            }
+                    })
+                    .filter(Objects::nonNull)
+                    .collect(Collectors.toList());
             
             // 使用business_section字段进行筛选
             queryWrapper.in("a.business_section", businessSectionIds);
@@ -2896,9 +2891,15 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
      * @return IPage<StoreInfoVo>
      */
     @Override
-    public List<StoreInfoVo> getMoreRecommendedStores(Double lon , Double lat, int category, int subcategory, int threeCategory) {
+    public List<StoreInfoVo> getMoreRecommendedStores(Double lon , Double lat, String businessSection, String businessTypes, String businessClassify) {
+        // 参数校验
+        if (lon == null || lat == null) {
+            log.warn("获取更多推荐店铺失败,经纬度为空");
+            return Collections.emptyList();
+        }
+        
         QueryWrapper<StoreInfoVo> queryWrapper = new QueryWrapper<>();
-        queryWrapper.eq("a.delete_flag", 0).eq("b.delete_flag", 0).orderByDesc("a.created_time");
+        queryWrapper.eq("a.delete_flag", 0).eq("b.delete_flag", 0);
         //如果查询未过期
         // 获取当前时刻
         Date currentDate = new Date();
@@ -2912,7 +2913,36 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
         // 加上 30 天
         calendar.add(Calendar.DAY_OF_MONTH, 30);
 
-        List<StoreInfoVo> storeInfoVoList = storeInfoMapper.getMoreRecommendedStores(queryWrapper);
+        // 构建一级分类
+        if(StringUtils.isNotEmpty(businessSection)){
+            queryWrapper.eq("a.business_section", businessSection);
+            // 构建二级分类
+            if(StringUtils.isNotEmpty(businessTypes)){
+                queryWrapper.eq("a.business_types", businessTypes);
+                // 构建三级分类
+                if(StringUtils.isNotEmpty(businessClassify)){
+                    // 解析businessClassify参数(格式:1,2,3)
+                    String[] classifyArray = businessClassify.split(",");
+                    // 使用FIND_IN_SET函数检查数据库字段是否包含参数中的任何一个值
+                    queryWrapper.and(wrapper -> {
+                        for (int i = 0; i < classifyArray.length; i++) {
+                            String classify = classifyArray[i].trim();
+                            if (StringUtils.isNotEmpty(classify)) {
+                                if (i == 0) {
+                                    wrapper.apply("FIND_IN_SET({0}, a.business_classify) > 0", classify);
+                                } else {
+                                    wrapper.or().apply("FIND_IN_SET({0}, a.business_classify) > 0", classify);
+                                }
+                            }
+                        }
+                    });
+                }
+            }
+        }
+
+        // 构建position参数(格式:经度,纬度)
+        String position = lon + "," + lat;
+        List<StoreInfoVo> storeInfoVoList = storeInfoMapper.getMoreRecommendedStores(queryWrapper, position);
         if (CollectionUtils.isEmpty(storeInfoVoList)) {
             return Collections.emptyList();
         }
@@ -2925,10 +2955,11 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
 
 
         // 计算平均分和评价
-        Map<Object, List<Map<String, Object>>> avgScoreMap = new HashMap<>();
+        Map<String, List<Map<String, Object>>> avgScoreMap = new HashMap<>();
         Map<Integer, List<StoreComment>> commentMap = new HashMap<>();
 
-        avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream().collect(Collectors.groupingBy(o -> o.get("store_id")));
+        // 注意:需要将store_id转换为String类型,与后续containsKey判断保持一致
+        avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream().collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
         commentMap = storeCommentMapper.selectList(new QueryWrapper<StoreComment>().eq("business_type", "5").eq("delete_flag", 0)).stream().collect(Collectors.groupingBy(StoreComment::getStoreId));
 
 
@@ -2982,65 +3013,211 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
             }
 
         }
-        if (lon == null || lat == null) {
-            log.warn("获取更多推荐店铺失败,经纬度为空");
-            return Collections.emptyList();
-        }
-
-        return filterStoresWithinDistance(storeInfoVoList, lon, lat);
+        
+        // SQL已经实现了距离过滤和排序,直接返回结果
+        return storeInfoVoList;
     }
 
     /**
-     * 根据距离过滤并排序店铺列表
+     * 你可能还喜欢(推荐店铺)
+     * 根据一级分类、二级分类、三级分类进行店铺筛选
+     * 筛选顺序:先三级,然后二级,最后一级
      *
-     * @param storeInfoVoList 原始店铺列表
-     * @param lon             用户经度
-     * @param lat             用户纬度
-     * @return 距离范围内的店铺列表
+     * @param businessSection 一级分类(经营板块)
+     * @param businessTypes 二级分类(经营种类)
+     * @param businessClassify 三级分类(分类)
+     * @param lon 经度
+     * @param lat 纬度
+     * @return List<StoreInfoVo> 店铺信息列表
      */
-    private List<StoreInfoVo> filterStoresWithinDistance(List<StoreInfoVo> storeInfoVoList, double lon, double lat) {
-        List<StoreInfoVo> filteredList = storeInfoVoList.stream()
-                .filter(store -> isWithinDistance(store, lon, lat, StoreInfoServiceImpl.DEFAULT_DISTANCE_METER))
-                .sorted(Comparator.comparingDouble(StoreInfoVo::getDistance3))
-                .collect(Collectors.toList());
-
-        if (log.isInfoEnabled()) {
-            log.info("距离筛选完成,原始店铺数量={},筛选后店铺数量={},筛选距离={}米",
-                    storeInfoVoList.size(), filteredList.size(), StoreInfoServiceImpl.DEFAULT_DISTANCE_METER);
+    @Override
+    public List<StoreInfoVo> getRecommendedStores(String businessSection, String businessTypes, String businessClassify, Double lon, Double lat) {
+        log.info("StoreInfoServiceImpl.getRecommendedStores?businessSection={},businessTypes={},businessClassify={},lon={},lat={}", 
+                businessSection, businessTypes, businessClassify, lon, lat);
+        
+        QueryWrapper<StoreInfoVo> queryWrapper = new QueryWrapper<>();
+        // 基础条件:未删除、已启用
+        queryWrapper.eq("a.delete_flag", 0)
+                .eq("b.delete_flag", 0)
+                .ne("a.business_status", 99) // 过滤永久关门的店铺
+                .ne("a.store_status", 0); // 过滤禁用的店铺
+        
+        // 按照三级->二级->一级的顺序筛选
+        
+        // 1. 先按三级分类(business_classify)筛选
+        if (StringUtils.isNotEmpty(businessClassify)) {
+            // 解析businessClassify参数(格式:1,2,3)
+            String[] classifyArray = businessClassify.split(",");
+            // 使用FIND_IN_SET函数检查数据库字段是否包含参数中的任何一个值
+            queryWrapper.and(wrapper -> {
+                for (int i = 0; i < classifyArray.length; i++) {
+                    String classify = classifyArray[i].trim();
+                    if (StringUtils.isNotEmpty(classify)) {
+                        if (i == 0) {
+                            wrapper.apply("FIND_IN_SET({0}, a.business_classify) > 0", classify);
+                        } else {
+                            wrapper.or().apply("FIND_IN_SET({0}, a.business_classify) > 0", classify);
+                        }
+                    }
+                }
+            });
         }
-        return filteredList;
-    }
-
-    /**
-     * 判断店铺是否在指定距离范围内
-     *
-     * @param store       店铺信息
-     * @param lon         用户经度
-     * @param lat         用户纬度
-     * @param maxDistance 最大距离(米)
-     * @return true 表示在范围内
-     */
-    private boolean isWithinDistance(StoreInfoVo store, double lon, double lat, int maxDistance) {
-        if (StringUtils.isEmpty(store.getStorePosition())) {
-            return false;
+        
+        // 2. 然后按二级分类(business_types)筛选
+        if (StringUtils.isNotEmpty(businessTypes)) {
+            // business_types可能是逗号分隔的字符串,使用FIND_IN_SET处理
+            String[] typesArray = businessTypes.split(",");
+            queryWrapper.and(wrapper -> {
+                for (int i = 0; i < typesArray.length; i++) {
+                    String type = typesArray[i].trim();
+                    if (StringUtils.isNotEmpty(type)) {
+                        if (i == 0) {
+                            wrapper.apply("FIND_IN_SET({0}, a.business_types) > 0", type);
+                        } else {
+                            wrapper.or().apply("FIND_IN_SET({0}, a.business_types) > 0", type);
+                        }
+                    }
+                }
+            });
         }
-
-        String[] positionArray = store.getStorePosition().split(",");
-        if (positionArray.length != 2) {
-            log.warn("店铺坐标格式异常,storeId={},storePosition={}", store.getId(), store.getStorePosition());
-            return false;
+        
+        // 3. 最后按一级分类(business_section)筛选
+        if (StringUtils.isNotEmpty(businessSection)) {
+            try {
+                Integer sectionId = Integer.parseInt(businessSection.trim());
+                queryWrapper.eq("a.business_section", sectionId);
+            } catch (NumberFormatException e) {
+                log.warn("一级分类参数格式错误: {}", businessSection);
+            }
         }
-
-        try {
-            double storeLon = Double.parseDouble(positionArray[0].trim());
-            double storeLat = Double.parseDouble(positionArray[1].trim());
-            double distanceMeters = DistanceUtil.haversineCalculateDistance(lon, lat, storeLon, storeLat) * 1000;
-            store.setDistance3(distanceMeters);
-            return distanceMeters <= maxDistance;
-        } catch (NumberFormatException ex) {
-            log.warn("店铺坐标解析失败,storeId={},storePosition={},error={}", store.getId(), store.getStorePosition(), ex.getMessage());
-            return false;
+        
+        // 查询店铺列表
+        List<StoreInfoVo> storeInfoVoList;
+        if (lon != null && lat != null) {
+            // 如果提供了经纬度,使用带距离计算的查询方法
+            String position = lon + "," + lat;
+            queryWrapper.isNotNull("a.store_position")
+                    .ne("a.store_position", "");
+            // 按距离排序
+            queryWrapper.orderByAsc("dist");
+            storeInfoVoList = storeInfoMapper.getStoreInfoVoListNew(queryWrapper, position);
+        } else {
+            // 如果没有提供经纬度,使用普通查询方法
+            queryWrapper.orderByDesc("a.created_time");
+            storeInfoVoList = storeInfoMapper.getStoreInfoVoList(queryWrapper);
         }
+        
+        if (CollectionUtils.isEmpty(storeInfoVoList)) {
+            return Collections.emptyList();
+        }
+        
+        // 处理店铺信息,设置评分等
+        // 提前查询所有需要的字典数据
+        List<StoreInfoVo> collect = storeInfoVoList.stream()
+                .filter(record -> StringUtils.isNotEmpty(record.getStoreType()))
+                .collect(Collectors.toList());
+        Set<String> allTypes = collect.stream()
+                .map(StoreInfoVo::getStoreType)
+                .flatMap(type -> Arrays.stream(type.split(",")))
+                .collect(Collectors.toSet());
+        
+        List<StoreDictionary> storeDictionaries = storeDictionaryMapper.selectList(
+                new LambdaQueryWrapper<StoreDictionary>()
+                        .eq(StoreDictionary::getTypeName, "storeType")
+                        .isNull(StoreDictionary::getParentId)
+                        .in(!allTypes.isEmpty(), StoreDictionary::getDictId, allTypes));
+        Map<String, String> typeMap = storeDictionaries.stream()
+                .collect(Collectors.toMap(StoreDictionary::getDictId, StoreDictionary::getDictDetail));
+        
+        // 计算平均分和评价
+        Map<String, List<Map<String, Object>>> avgScoreMap = new HashMap<>();
+        Map<Integer, List<StoreComment>> commentMap = new HashMap<>();
+        
+        avgScoreMap = storeEvaluationMapper.allStoreAvgScore().stream()
+                .collect(Collectors.groupingBy(o -> o.get("store_id").toString()));
+        commentMap = storeCommentMapper.selectList(
+                new QueryWrapper<StoreComment>()
+                        .eq("business_type", "5")
+                        .eq("delete_flag", 0))
+                .stream()
+                .collect(Collectors.groupingBy(StoreComment::getStoreId));
+        
+        for (StoreInfoVo record : storeInfoVoList) {
+            // 处理类型
+            if (StringUtils.isNotEmpty(record.getStoreType())) {
+                String[] types = record.getStoreType().split(",");
+                List<String> typeDetails = Arrays.stream(types)
+                        .map(typeMap::get)
+                        .filter(Objects::nonNull)
+                        .collect(Collectors.toList());
+                record.setStoreTypeStr(String.join(",", typeDetails));
+                record.setStoreTypeList(Arrays.asList(types));
+            }
+            
+            // 处理经纬度
+            if (StringUtils.isNotEmpty(record.getStorePosition())) {
+                String[] split = record.getStorePosition().split(",");
+                if (split.length >= 2) {
+                    record.setStorePositionLongitude(split[0]);
+                    record.setStorePositionLatitude(split[1]);
+                }
+            }
+            
+            // 如果提供了经纬度,处理距离信息
+            if (lon != null && lat != null && StringUtils.isNotEmpty(record.getStorePosition())) {
+                try {
+                    // 手动计算距离(单位:公里)
+                    String[] positionArray = record.getStorePosition().split(",");
+                    if (positionArray.length >= 2) {
+                        double storeLon = Double.parseDouble(positionArray[0].trim());
+                        double storeLat = Double.parseDouble(positionArray[1].trim());
+                        // 计算距离(单位:公里)
+                        double distanceKm = DistanceUtil.haversineCalculateDistance(lon, lat, storeLon, storeLat);
+                        record.setDistance(distanceKm);
+                    }
+                } catch (Exception e) {
+                    log.warn("计算店铺距离失败,storeId={},error={}", record.getId(), e.getMessage());
+                }
+            }
+            
+            // 处理到期状态
+            Date expirationTime = record.getExpirationTime();
+            if (expirationTime != null) {
+                Date currentDate = new Date();
+                Calendar now = Calendar.getInstance();
+                Date nowCurrentDate = now.getTime();
+                now.add(Calendar.DAY_OF_YEAR, 30);
+                Date thirtyDaysLater = now.getTime();
+                
+                if (expirationTime.after(currentDate)) {
+                    record.setExpiredState("0");
+                    if ((expirationTime.after(nowCurrentDate) || expirationTime.equals(nowCurrentDate)) 
+                            && expirationTime.before(thirtyDaysLater)) {
+                        record.setExpiredState("1");
+                    }
+                } else {
+                    record.setExpiredState("2");
+                }
+                
+                LocalDate nowLocal = LocalDate.now();
+                LocalDate expDate = expirationTime.toInstant()
+                        .atZone(ZoneId.systemDefault())
+                        .toLocalDate();
+                long daysToExpire = ChronoUnit.DAYS.between(nowLocal, expDate);
+                record.setDaysToExpire(daysToExpire);
+            }
+            
+            // 设置店铺得分和总评论数
+            if (avgScoreMap.containsKey(String.valueOf(record.getId()))) {
+                record.setAvgScore(String.valueOf(
+                        avgScoreMap.get(String.valueOf(record.getId())).get(0).get("avg_score")));
+            }
+            if (commentMap.containsKey(record.getId())) {
+                record.setTotalNum(String.valueOf(commentMap.get(record.getId()).size()));
+            }
+        }
+        
+        return storeInfoVoList;
     }
 
     @Override
@@ -3362,7 +3539,7 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
     @Override
     public List<StoreDictionaryVo> getLeisureEntertainmentCategories() {
         // 定义四种主分类名称
-        List<String> mainCategoryNames = Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足");
+        List<String> mainCategoryNames = Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足");
 
         // 查询所有主分类(business_section类型)
         List<StoreDictionary> allMainCategories = storeDictionaryMapper.selectList(
@@ -3396,6 +3573,7 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
                     new LambdaQueryWrapper<StoreDictionary>()
                             .in(StoreDictionary::getParentId, mainCategoryIds)
                             .eq(StoreDictionary::getDeleteFlag, 0)
+                           .in(StoreDictionary::getTypeName, "business_section","business_type","business_classify")
             );
 
             // 按parentId分组
@@ -3424,4 +3602,184 @@ public class StoreInfoServiceImpl extends ServiceImpl<StoreInfoMapper, StoreInfo
 
         return result;
     }
+
+    @Override
+    public List<StoreDictionary> getAllBusinessSection() {
+        // 查询所有经营种类数据
+        LambdaQueryWrapper<StoreDictionary> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.in(StoreDictionary::getTypeName, "business_section","business_type","business_classify");
+        queryWrapper.eq(StoreDictionary::getDeleteFlag, 0);
+        queryWrapper.orderByAsc(StoreDictionary::getSortId);
+        List<StoreDictionary> storeDictionaryList = storeDictionaryMapper.selectList(queryWrapper);
+
+        // 构建三级树形结构
+        return buildTreeOptimized(storeDictionaryList);
+    }
+
+    /**
+     * 构建树形结构(优化版)
+     *
+     * @param flatList 扁平列表
+     * @return 树形结构列表
+     */
+    private List<StoreDictionary> buildTreeOptimized(List<StoreDictionary> flatList) {
+        if (flatList == null || flatList.isEmpty()) {
+            return new ArrayList<>();
+        }
+
+        // 创建三个存储结构
+        Map<Integer, StoreDictionary> nodeMap = new HashMap<>();  // ID到节点的映射
+        Map<Integer, List<StoreDictionary>> parentChildMap = new HashMap<>();  // 父ID到子节点列表的映射
+        List<StoreDictionary> result = new ArrayList<>();  // 结果列表
+
+        // 填充nodeMap和parentChildMap
+        for (StoreDictionary entity : flatList) {
+            Integer id = entity.getId();
+            Integer parentId = entity.getParentId();
+
+            // 存入节点映射
+            nodeMap.put(id, entity);
+
+            // 初始化子节点列表
+            entity.setStoreDictionaryList(new ArrayList<>());
+
+            // 如果是根节点(parentId为null或0),直接添加到结果
+            if (parentId == null || parentId == 0) {
+                result.add(entity);
+            } else {
+                // 否则,记录父子关系
+                parentChildMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(entity);
+            }
+        }
+
+        // 建立父子关系
+        for (StoreDictionary entity : flatList) {
+            Integer id = entity.getId();
+            if (parentChildMap.containsKey(id)) {
+                entity.getStoreDictionaryList().addAll(parentChildMap.get(id));
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public StoreThreeLevelStructureVo getStoreThreeLevelStructure(Integer storeId) {
+        // 1. 根据门店ID查询门店信息
+        StoreInfo storeInfo = storeInfoMapper.selectById(storeId);
+        if (storeInfo == null) {
+            log.warn("门店不存在,storeId={}", storeId);
+            StoreThreeLevelStructureVo vo = new StoreThreeLevelStructureVo();
+            vo.setStoreId(storeId);
+            vo.setStoreName(null);
+            vo.setThreeLevelStructure(new ArrayList<>());
+            return vo;
+        }
+
+        // 2. 获取门店表里的三级分类信息
+        Integer businessSection = storeInfo.getBusinessSection(); // 一级:经营板块ID
+        String businessTypes = storeInfo.getBusinessTypes(); // 二级:经营种类IDs(逗号分隔,fine_food类型)
+        String businessClassify = storeInfo.getBusinessClassify(); // 三级:分类IDs(逗号分隔)
+
+        // 3. 查询一级分类(business_section - 经营板块)
+        // business_section存储的是dictId(字符串),需要转换为String
+        List<StoreDictionary> allDicts = new ArrayList<>();
+        StoreDictionary firstLevelDict = null;
+        if (businessSection != null) {
+            firstLevelDict = storeDictionaryMapper.selectOne(
+                    new LambdaQueryWrapper<StoreDictionary>()
+                            .eq(StoreDictionary::getDictId, String.valueOf(businessSection))
+                            .eq(StoreDictionary::getTypeName, "business_section")
+                            .eq(StoreDictionary::getDeleteFlag, 0)
+            );
+            if (firstLevelDict != null) {
+                allDicts.add(firstLevelDict);
+                log.debug("查询到一级分类: id={}, dictId={}, dictDetail={}", 
+                        firstLevelDict.getId(), firstLevelDict.getDictId(), firstLevelDict.getDictDetail());
+            } else {
+                log.warn("未查询到一级分类,businessSection={}", businessSection);
+            }
+        }
+
+        // 4. 查询二级分类(business_type - 根据门店表里的business_types字段,存储的是dictId)
+        List<StoreDictionary> secondLevelDicts = new ArrayList<>();
+        if (StringUtils.isNotEmpty(businessTypes) && firstLevelDict != null) {
+            // 解析二级分类dictId列表(business_types存储的是dictId字符串)
+            String[] typeDictIds = businessTypes.split(",");
+            List<String> typeDictIdList = new ArrayList<>();
+            for (String typeDictId : typeDictIds) {
+                if (StringUtils.isNotEmpty(typeDictId.trim())) {
+                    typeDictIdList.add(typeDictId.trim());
+                }
+            }
+
+            // 查询二级分类,需要满足:
+            // 1. dict_id 在门店配置的经营种类dictId列表中
+            // 2. type_name = "business_type"
+            // 3. parent_id = 一级分类的id(不是dictId)
+            if (!typeDictIdList.isEmpty() && firstLevelDict != null) {
+                LambdaQueryWrapper<StoreDictionary> secondLevelWrapper = new LambdaQueryWrapper<>();
+                secondLevelWrapper.in(StoreDictionary::getDictId, typeDictIdList);
+                secondLevelWrapper.eq(StoreDictionary::getTypeName, "business_type");
+                secondLevelWrapper.eq(StoreDictionary::getParentId, firstLevelDict.getId());
+                secondLevelWrapper.eq(StoreDictionary::getDeleteFlag, 0);
+//                secondLevelWrapper.orderByAsc(StoreDictionary::getSortId);
+                secondLevelDicts = storeDictionaryMapper.selectList(secondLevelWrapper);
+                allDicts.addAll(secondLevelDicts);
+                log.debug("查询到二级分类数量: {}, dictIds={}", secondLevelDicts.size(), typeDictIdList);
+            } else {
+                log.warn("无法查询二级分类: typeDictIdList为空或一级分类不存在, typeDictIdList={}, firstLevelDict={}", 
+                        typeDictIdList, firstLevelDict != null ? firstLevelDict.getId() : null);
+            }
+        }
+
+        // 5. 查询三级分类(business_classify - 根据门店表里的business_classify字段,存储的是dictId)
+        if (!secondLevelDicts.isEmpty() && StringUtils.isNotEmpty(businessClassify)) {
+            // 解析三级分类dictId列表(business_classify存储的是dictId字符串)
+            String[] classifyDictIds = businessClassify.split(",");
+            List<String> classifyDictIdList = new ArrayList<>();
+            for (String classifyDictId : classifyDictIds) {
+                if (StringUtils.isNotEmpty(classifyDictId.trim())) {
+                    classifyDictIdList.add(classifyDictId.trim());
+                }
+            }
+
+            // 查询三级分类,需要满足:
+            // 1. dict_id 在门店配置的分类dictId列表中
+            // 2. parent_id 在二级分类的id列表中(不是dictId)
+            // 3. type_name = "business_classify"
+            if (!classifyDictIdList.isEmpty() && !secondLevelDicts.isEmpty()) {
+                Set<Integer> secondLevelIds = secondLevelDicts.stream()
+                        .map(StoreDictionary::getId)
+                        .collect(Collectors.toSet());
+
+                List<StoreDictionary> thirdLevelDicts = storeDictionaryMapper.selectList(
+                        new LambdaQueryWrapper<StoreDictionary>()
+                                .in(StoreDictionary::getDictId, classifyDictIdList)
+                                .in(StoreDictionary::getParentId, secondLevelIds)
+                                .eq(StoreDictionary::getTypeName, "business_classify")
+                                .eq(StoreDictionary::getDeleteFlag, 0)
+//                                .orderByAsc(StoreDictionary::getSortId)
+                );
+                allDicts.addAll(thirdLevelDicts);
+                log.debug("查询到三级分类数量: {}, dictIds={}, parentIds={}", 
+                        thirdLevelDicts.size(), classifyDictIdList, secondLevelIds);
+            } else {
+                log.warn("无法查询三级分类: classifyDictIdList为空或二级分类为空, classifyDictIdList={}, secondLevelDicts.size={}", 
+                        classifyDictIdList, secondLevelDicts.size());
+            }
+        }
+
+        // 6. 构建树形结构(根据parent_id关系组装)
+        List<StoreDictionary> treeStructure = buildTreeOptimized(allDicts);
+
+        // 7. 构建返回对象
+        StoreThreeLevelStructureVo vo = new StoreThreeLevelStructureVo();
+        vo.setStoreId(storeInfo.getId());
+        vo.setStoreName(storeInfo.getStoreName());
+        vo.setThreeLevelStructure(treeStructure);
+        
+        return vo;
+    }
+
 }

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

@@ -471,6 +471,7 @@ public class StoreMenuServiceImpl extends ServiceImpl<StoreMenuMapper, StoreMenu
         // 批量查询点赞记录
         LambdaQueryWrapper<LifeLikeRecord> likeQuery = new LambdaQueryWrapper<>();
         likeQuery.eq(LifeLikeRecord::getDianzanId, phoneId)
+                .eq(LifeLikeRecord::getDeleteFlag, 0)
                 .in(LifeLikeRecord::getHuifuId, menuIdStrSet);
         List<LifeLikeRecord> likeRecordList = lifeLikeRecordMapper.selectList(likeQuery);
         
@@ -506,7 +507,23 @@ public class StoreMenuServiceImpl extends ServiceImpl<StoreMenuMapper, StoreMenu
      * @return StoreMenuVo
      */
     @Override
-    public StoreMenuVo getClientMenuInfoById(Integer id) {
-        return storeMenuMapper.getClientMenuInfoById(id);
+    public StoreMenuVo getClientMenuInfoById(Integer id, String phoneId) {
+        StoreMenuVo storeMenuVo = storeMenuMapper.getClientMenuInfoById(id);
+        if(StringUtils.isNotEmpty(phoneId)){
+            // 批量查询点赞记录
+            LambdaQueryWrapper<LifeLikeRecord> likeQuery = new LambdaQueryWrapper<>();
+            likeQuery.eq(LifeLikeRecord::getDianzanId, phoneId)
+                    .eq(LifeLikeRecord::getDeleteFlag, 0)
+                    .eq(LifeLikeRecord::getHuifuId, storeMenuVo.getId());
+           int likeCount = lifeLikeRecordMapper.selectCount(likeQuery);
+           if(likeCount > 0){
+               storeMenuVo.setIsLike(1);
+           }
+        } else {
+            storeMenuVo.setLikeCount(0);
+            storeMenuVo.setIsLike(0);
+        }
+
+        return storeMenuVo;
     }
 }