فهرست منبع

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

fcw 1 هفته پیش
والد
کامیت
91c10010ca
35فایلهای تغییر یافته به همراه2113 افزوده شده و 210 حذف شده
  1. 6 0
      alien-entity/pom.xml
  2. 103 0
      alien-entity/src/main/java/shop/alien/entity/store/DrinkInfo.java
  3. 1 1
      alien-entity/src/main/java/shop/alien/entity/store/StoreImg.java
  4. 4 1
      alien-entity/src/main/java/shop/alien/entity/store/StoreInfo.java
  5. 1 1
      alien-entity/src/main/java/shop/alien/entity/store/StoreMenu.java
  6. 11 0
      alien-entity/src/main/java/shop/alien/entity/store/StoreStaffConfig.java
  7. 13 1
      alien-entity/src/main/java/shop/alien/entity/store/dto/StoreInfoDto.java
  8. 66 0
      alien-entity/src/main/java/shop/alien/entity/store/dto/deserializer/StringToListDeserializer.java
  9. 82 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/DrinkInfoVo.java
  10. 3 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StoreUserVo.java
  11. 1 1
      alien-entity/src/main/java/shop/alien/entity/storePlatform/StoreOperationalActivity.java
  12. 14 0
      alien-entity/src/main/java/shop/alien/mapper/DrinkInfoMapper.java
  13. 9 5
      alien-entity/src/main/java/shop/alien/mapper/LifeFansMapper.java
  14. 1 1
      alien-entity/src/main/java/shop/alien/mapper/StoreMenuMapper.java
  15. 34 0
      alien-entity/src/main/resources/mapper/DrinkInfoMapper.xml
  16. 1 0
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerClientConsultationOrderServiceImpl.java
  17. 1 1
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/LawyerConsultationOrderServiceImpl.java
  18. 4 1
      alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderExpirationServiceImpl.java
  19. 1 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformLoginServiceImpl.java
  20. 4 2
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformRenovationServiceImpl.java
  21. 190 0
      alien-store/src/main/java/shop/alien/store/controller/DrinkInfoController.java
  22. 99 0
      alien-store/src/main/java/shop/alien/store/controller/OperationalActivityController.java
  23. 23 6
      alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java
  24. 1 1
      alien-store/src/main/java/shop/alien/store/controller/StoreMenuController.java
  25. 20 0
      alien-store/src/main/java/shop/alien/store/controller/StoreStaffConfigController.java
  26. 141 0
      alien-store/src/main/java/shop/alien/store/service/DrinkInfoService.java
  27. 44 0
      alien-store/src/main/java/shop/alien/store/service/OperationalActivityService.java
  28. 80 49
      alien-store/src/main/java/shop/alien/store/service/StoreInfoService.java
  29. 4 2
      alien-store/src/main/java/shop/alien/store/service/StoreOfficialAlbumService.java
  30. 18 0
      alien-store/src/main/java/shop/alien/store/service/StoreStaffConfigService.java
  31. 260 0
      alien-store/src/main/java/shop/alien/store/service/impl/DrinkInfoServiceImpl.java
  32. 256 0
      alien-store/src/main/java/shop/alien/store/service/impl/OperationalActivityServiceImpl.java
  33. 551 130
      alien-store/src/main/java/shop/alien/store/service/impl/StoreInfoServiceImpl.java
  34. 1 1
      alien-store/src/main/java/shop/alien/store/service/impl/StoreMenuServiceImpl.java
  35. 65 6
      alien-store/src/main/java/shop/alien/store/service/impl/StoreStaffConfigServiceImpl.java

+ 6 - 0
alien-entity/pom.xml

@@ -83,6 +83,12 @@
             <scope>compile</scope>
         </dependency>
 
+        <!-- Jackson for JSON deserialization -->
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 103 - 0
alien-entity/src/main/java/shop/alien/entity/store/DrinkInfo.java

@@ -0,0 +1,103 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 二期-酒水餐食信息
+ *
+ * @author ssk
+ * @since 2025-05-14
+ */
+@Data
+@JsonInclude
+@TableName("drink_info")
+@ApiModel(value = "DrinkInfo对象", description = "酒水餐食信息")
+public class DrinkInfo  {
+
+    @ApiModelProperty(value = "主键")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "类型(枚举值:酒水/餐食)")
+    @TableField("type")
+    private String type;
+
+    @ApiModelProperty(value = "名称")
+    @TableField("name")
+    private String name;
+
+    @ApiModelProperty(value = "售价")
+    @TableField("price")
+    private BigDecimal price;
+
+    @ApiModelProperty(value = "成本价")
+    @TableField("cost_price")
+    private BigDecimal costPrice;
+
+    @ApiModelProperty(value = "酒精度")
+    @TableField("alcohol_volume")
+    private BigDecimal alcoholVolume;
+
+    @ApiModelProperty(value = "图片")
+    @TableField("pic_url")
+    private String picUrl;
+
+    @ApiModelProperty(value = "分类")
+    @TableField("category")
+    private String category;
+
+    @ApiModelProperty(value = "口味")
+    @TableField("flavor")
+    private String flavor;
+
+    @ApiModelProperty(value = "描述")
+    @TableField("description")
+    private String description;
+
+    @ApiModelProperty(value = "排序")
+    @TableField("sort")
+    private Integer sort;
+
+    @ApiModelProperty(value = "是否推荐 0:否 1:是")
+    @TableField("is_recommended")
+    private Integer isRecommended;
+
+    @ApiModelProperty(value = "状态 0:下架 1:上架")
+    @TableField("status")
+    private Integer status;
+
+    @ApiModelProperty(value = "门店ID")
+    @TableField("store_id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "创建人ID")
+    @TableField("create_user_id")
+    private Integer createUserId;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "create_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField("update_user_id")
+    private Integer updateUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "update_time", fill = FieldFill.UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
+
+    @ApiModelProperty(value = "是否删除 0:未删除 1:已删除")
+    @TableField("is_deleted")
+    @TableLogic
+    private Integer isDeleted;
+}

+ 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:洗浴设施及服务图片 30 酒水")
+    @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.食品经营许可证审核后类型 26.运营活动活动标题图 27.运营活动活动详情图 28.运动设施 29.洗浴设施及服务 30.酒水 31.娱乐经营许可证 32.娱乐经营许可证审核前")
     @TableField("img_type")
     private Integer imgType;
 

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

@@ -86,6 +86,7 @@ public class StoreInfo {
 
     @ApiModelProperty(value = "到期时间")
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    @TableField("expiration_time")
     private Date expirationTime;
 
     @ApiModelProperty(value = "门店坐标")
@@ -243,11 +244,13 @@ public class StoreInfo {
     @TableField("business_classify_name")
     private String businessClassifyName;
 
+
+
     @ApiModelProperty(value = "是否提供餐食")
     @TableField("meals_flag")
     private Integer  mealsFlag;
 
-    @ApiModelProperty(value = "娱乐经营许可证状态 字典 foodLicenceStatus")
+    @ApiModelProperty(value = "娱乐经营许可证状态")
     @TableField("entertainment_licence_status")
     private Integer entertainmentLicenceStatus;
 

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

@@ -94,7 +94,7 @@ public class StoreMenu {
     private String description;
 
     @ApiModelProperty(value = "酒精度")
-    @TableField("alcoholVolume")
+    @TableField("alcohol_volume")
     private String alcoholVolume;
 
     @ApiModelProperty(value = "分类")

+ 11 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreStaffConfig.java

@@ -7,6 +7,7 @@ import com.fasterxml.jackson.annotation.JsonInclude;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
+import lombok.EqualsAndHashCode;
 
 import java.util.Date;
 
@@ -16,6 +17,7 @@ import java.util.Date;
  * @Description: 员工管理
  */
 @Data
+@EqualsAndHashCode(callSuper = false)
 @JsonInclude
 @TableName("store_staff_config")
 @ApiModel(value = "StoreStaffConfig对象", description = "员工管理")
@@ -89,4 +91,13 @@ public class StoreStaffConfig extends Model<StoreStaffConfig> {
     @ApiModelProperty(value = "修改人ID")
     @TableField("updated_user_id")
     private Integer updatedUserId;
+
+    @ApiModelProperty(value = "置顶状态, 0:未置顶, 1:已置顶")
+    @TableField("top_status")
+    private Integer topStatus;
+
+    @ApiModelProperty(value = "置顶时间")
+    @TableField("top_time")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date topTime;
 }

+ 13 - 1
alien-entity/src/main/java/shop/alien/entity/store/dto/StoreInfoDto.java

@@ -3,11 +3,13 @@ package shop.alien.entity.store.dto;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 import shop.alien.entity.store.StoreBusinessInfo;
+import shop.alien.entity.store.dto.deserializer.StringToListDeserializer;
 
 import java.util.Date;
 import java.util.List;
@@ -112,12 +114,14 @@ public class StoreInfoDto {
     private String businessTypeValue;
 
     @ApiModelProperty(value = "经营种类集合")
+    @JsonDeserialize(using = StringToListDeserializer.class)
     private List<String> businessTypesList;
 
     @ApiModelProperty(value = "经营板块id(词典表 键为 business_section)")
     private Integer businessSection;
 
     @ApiModelProperty(value = "经营种类ids")
+    @JsonDeserialize(using = StringToListDeserializer.class)
     private List<String> businessTypes;
 
     @ApiModelProperty(value = "经营种类名称s")
@@ -127,9 +131,11 @@ public class StoreInfoDto {
     private String userAccount;
 
     @ApiModelProperty(value = "营业执照图片地址")
+    @JsonDeserialize(using = StringToListDeserializer.class)
     private List<String> businessLicenseAddress;
 
     @ApiModelProperty(value = "合同图片地址")
+    @JsonDeserialize(using = StringToListDeserializer.class)
     private List<String> contractImageList;
 
     @ApiModelProperty(value = "经营许可证图片地址")
@@ -181,13 +187,14 @@ public class StoreInfoDto {
     private Date foodLicenceExpirationTime;
 
     @ApiModelProperty(value = "分类id(词典表 键为 business_classify)(多个ID用逗号拼接)")
+    @JsonDeserialize(using = StringToListDeserializer.class)
     private List<String> businessClassify;
 
     @ApiModelProperty(value = "分类名称")
     private String businessClassifyName;
 
     @ApiModelProperty(value = "是否提供餐食")
-    private Integer  mealsFlag;
+    private Integer mealsFlag;
 
     @ApiModelProperty(value = "娱乐经营许可证图片地址")
     private String entertainmentLicenceUrl;
@@ -205,4 +212,9 @@ public class StoreInfoDto {
     @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
     @DateTimeFormat(pattern = "yyyy-MM-dd")
     private Date entertainmentLicenceExpirationTime;
+
+//    @ApiModelProperty(value = "分类id(词典表 键为 business_classify)(多个ID用逗号拼接)")
+//    @JsonDeserialize(using = StringToListDeserializer.class)
+//    private List<String> businessClassify;
+
 }

+ 66 - 0
alien-entity/src/main/java/shop/alien/entity/store/dto/deserializer/StringToListDeserializer.java

@@ -0,0 +1,66 @@
+package shop.alien.entity.store.dto.deserializer;
+
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 自定义反序列化器:将字符串或数组转换为List<String>
+ * 支持以下格式:
+ * - 字符串:"0" 或 "1,2,3"
+ * - 数组:["1", "2", "3"]
+ * - null:返回空列表
+ */
+public class StringToListDeserializer extends JsonDeserializer<List<String>> {
+
+    @Override
+    public List<String> deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
+        JsonNode node = p.getCodec().readTree(p);
+        
+        if (node == null || node.isNull()) {
+            return new ArrayList<>();
+        }
+        
+        List<String> result = new ArrayList<>();
+        
+        // 如果是数组
+        if (node.isArray()) {
+            for (JsonNode item : node) {
+                if (item != null && !item.isNull()) {
+                    result.add(item.asText());
+                }
+            }
+        } 
+        // 如果是字符串
+        else if (node.isTextual()) {
+            String value = node.asText();
+            if (value != null && !value.trim().isEmpty()) {
+                // 如果是逗号分隔的字符串,则分割
+                if (value.contains(",")) {
+                    String[] parts = value.split(",");
+                    for (String part : parts) {
+                        String trimmed = part.trim();
+                        if (!trimmed.isEmpty()) {
+                            result.add(trimmed);
+                        }
+                    }
+                } else {
+                    // 单个值
+                    result.add(value.trim());
+                }
+            }
+        }
+        // 如果是数字,转换为字符串
+        else if (node.isNumber()) {
+            result.add(node.asText());
+        }
+        
+        return result;
+    }
+}
+

+ 82 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/DrinkInfoVo.java

@@ -0,0 +1,82 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 酒水餐食信息表 VO
+ *
+ * @author ssk
+ * @since 2025-06-13
+ */
+@Data
+@ApiModel(value = "DrinkInfoVo", description = "酒水餐食信息表视图对象")
+public class DrinkInfoVo {
+
+    @ApiModelProperty(value = "主键ID")
+    private Integer id;
+
+    @ApiModelProperty(value = "类型(枚举值:酒水/餐食)")
+    private String type;
+
+    @ApiModelProperty(value = "商品名称")
+    private String name;
+
+    @ApiModelProperty(value = "商品价格")
+    private BigDecimal price;
+
+    @ApiModelProperty(value = "商品成本价")
+    private BigDecimal costPrice;
+
+    @ApiModelProperty(value = "商品分类")
+    private String category;
+
+    @ApiModelProperty(value = "酒精度数")
+    private BigDecimal alcoholVolume;
+
+    @ApiModelProperty(value = "商品图片")
+    private String picUrl;
+
+    @ApiModelProperty(value = "商品描述")
+    private String description;
+
+    @ApiModelProperty(value = "商品口味")
+    private String flavor;
+
+    @ApiModelProperty(value = "门店ID")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "门店名称")
+    private String storeName;
+
+    @ApiModelProperty(value = "是否推荐(0:否, 1:是)")
+    private Integer isRecommended;
+
+    @ApiModelProperty(value = "状态(0:下架, 1:上架)")
+    private Integer status;
+
+    @ApiModelProperty(value = "排序值")
+    private Integer sort;
+
+    @ApiModelProperty(value = "是否删除(0:否, 1:是)")
+    private Integer isDeleted;
+
+    @ApiModelProperty(value = "创建人ID")
+    private Integer createUserId;
+
+    @ApiModelProperty(value = "创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+
+    @ApiModelProperty(value = "更新人ID")
+    private Integer updateUserId;
+
+    @ApiModelProperty(value = "更新时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updateTime;
+}

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

@@ -39,4 +39,7 @@ public class StoreUserVo extends StoreUser {
 
     @ApiModelProperty(value = "手机号")
     private String phone;
+
+    @ApiModelProperty(value = "是否提供餐食")
+    private Integer mealsFlag;
 }

+ 1 - 1
alien-entity/src/main/java/shop/alien/entity/storePlatform/StoreOperationalActivity.java

@@ -67,7 +67,7 @@ public class StoreOperationalActivity {
     @TableField("coupon_quantity")
     private Integer couponQuantity;
 
-    @ApiModelProperty(value = "状态:0-禁用, 1-启用")
+    @ApiModelProperty(value = "状态:1-待审核, 2-未开始, 3-审核拒绝, 4-已售罄, 5-进行中, 6-已下架, 7-已结束")
     @TableField("status")
     private Integer status;
 

+ 14 - 0
alien-entity/src/main/java/shop/alien/mapper/DrinkInfoMapper.java

@@ -0,0 +1,14 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import shop.alien.entity.store.DrinkInfo;
+
+/**
+ * 酒水餐食信息表 Mapper 接口
+ *
+ * @author ssk
+ * @since 2025-06-13
+ */
+public interface DrinkInfoMapper extends BaseMapper<DrinkInfo> {
+
+}

+ 9 - 5
alien-entity/src/main/java/shop/alien/mapper/LifeFansMapper.java

@@ -15,7 +15,8 @@ import java.util.List;
 @Mapper
 public interface LifeFansMapper extends BaseMapper<LifeFans> {
 
-    @Select("select foll.*,lb.id blackListid, if(isnull(fans.id), 0, 1) isFollowMe, 1 as isFollowThis,  " +
+    @Select("select MAX(foll.id) id, MAX(foll.name) name, MAX(foll.image) image, foll.phoneId, MAX(foll.blurb) blurb, MAX(foll.blockedType) blockedType, MAX(foll.blockedId) blockedId, MAX(foll.username) username, MAX(foll.accountBlurb) accountBlurb, " +
+            "  MAX(lb.id) blackListid, MAX(if(isnull(fans.id), 0, 1)) isFollowMe, 1 as isFollowThis,  " +
             "  (select count(1) from life_fans where fans_id= foll.phoneId and delete_flag =0) followNum, " +
             "  (select count(1) from life_fans where followed_id= foll.phoneId and delete_flag =0) fansNum from ( " +
             "    with follow as (   " +
@@ -63,7 +64,8 @@ public interface LifeFansMapper extends BaseMapper<LifeFans> {
             "left join life_fans fans on fans.fans_id = foll.phoneId and fans.followed_id = #{fansId} and fans.delete_flag = 0 ")
     List<LifeFansVo> getMyFollowedAll(@Param("fansId") String fansId);
 
-    @Select("select foll.*,lb.id blackListid, if(isnull(fans.id), 0, 1) isFollowThis, 1 as isFollowMe, " +
+    @Select("select MAX(foll.id) id, MAX(foll.name) name, MAX(foll.image) image, foll.phoneId, MAX(foll.blurb) blurb, MAX(foll.blockedType) blockedType, MAX(foll.blockedId) blockedId, " +
+            "  MAX(lb.id) blackListid, MAX(if(isnull(fans.id), 0, 1)) isFollowThis, 1 as isFollowMe, " +
             "    (select count(1) from life_fans fans2 where fans2.followed_id = foll.phoneId and fans2.delete_flag = 0) fansNum, " +
             "    (select count(1) from life_fans fans3 where fans3.fans_id = foll.phoneId and fans3.delete_flag = 0) followNum " +
             "from ( " +
@@ -169,7 +171,8 @@ public interface LifeFansMapper extends BaseMapper<LifeFans> {
             "${ew.customSqlSegment}")
     IPage<LifeFansVo> getMyStoreFans(IPage<LifeFansVo> iPage, @Param("fansId") String fansId, @Param(Constants.WRAPPER) QueryWrapper<LifeFansVo> wrapper);
 
-    @Select("select foll.*, if(isnull(fans.id), 0, 1) isFollowThis, 1 as isFollowMe, " +
+    @Select("select MAX(foll.id) id, MAX(foll.name) name, MAX(foll.image) image, foll.phoneId, MAX(foll.blurb) blurb, " +
+            "  MAX(if(isnull(fans.id), 0, 1)) isFollowThis, 1 as isFollowMe, " +
             "       (select count(1) from life_fans fans2 where fans2.followed_id = foll.phoneId and fans2.delete_flag = 0) fansNum, " +
             "       (select count(1) from life_fans fans3 where fans3.fans_id = foll.phoneId and fans3.delete_flag = 0) followNum " +
             " from ( " +
@@ -187,7 +190,8 @@ public interface LifeFansMapper extends BaseMapper<LifeFans> {
             "${ew.customSqlSegment} ")
     IPage<LifeFansVo> getMyUserFans(IPage<LifeFansVo> iPage, @Param("fansId") String fansId, @Param(Constants.WRAPPER) QueryWrapper<LifeFansVo> wrapper);
 
-    @Select("select foll.*, lb.id blackListid, 1 as isFollowThis, 1 as isFollowMe, " +
+    @Select("select MAX(foll.id) id, MAX(foll.name) name, MAX(foll.image) image, foll.phoneId, MAX(foll.blurb) blurb, MAX(foll.blockedType) blockedType, MAX(foll.blockedId) blockedId, MAX(foll.username) username, MAX(foll.accountBlurb) accountBlurb, " +
+            "  MAX(lb.id) blackListid, 1 as isFollowThis, 1 as isFollowMe, " +
             "       (select count(1) from life_fans fans2 where fans2.followed_id = foll.phoneId and fans2.delete_flag = 0) fansNum, " +
             "       (select count(1) from life_fans fans3 where fans3.fans_id = foll.phoneId and fans3.delete_flag = 0) followNum " +
             "from ( " +
@@ -213,7 +217,7 @@ public interface LifeFansMapper extends BaseMapper<LifeFans> {
             "${ew.customSqlSegment} ")
     IPage<LifeFansVo> getMutualAttention(IPage<LifeFansVo> iPage, @Param("fansId") String fansId, @Param("blockerType") String blockerType, @Param("blockerId") String blockerId, @Param(Constants.WRAPPER) QueryWrapper<LifeFansVo> wrapper);
 
-    @Select("select foll.*, 1 as isFollowThis, 1 as isFollowMe, " +
+    @Select("select MAX(foll.id) id, MAX(foll.name) name, MAX(foll.image) image, foll.phoneId, MAX(foll.blurb) blurb, 1 as isFollowThis, 1 as isFollowMe, " +
             "       (select count(1) from life_fans fans2 where fans2.followed_id = foll.phoneId and fans2.delete_flag = 0) fansNum, " +
             "       (select count(1) from life_fans fans3 where fans3.fans_id = foll.phoneId and fans3.delete_flag = 0) followNum " +
             "from ( " +

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

@@ -31,7 +31,7 @@ public interface StoreMenuMapper extends BaseMapper<StoreMenu> {
             "and a.store_id = #{storeId} " +
             "and (if(#{dishType} is null, 1 = 1, a.dish_type = #{dishType})) " +
             "and (if(#{dishMenuType} is null, 1 = 1, a.dish_menu_type = #{dishMenuType}))")
-    List<StoreMenuVo> getStoreMenuList(@Param("storeId") Integer storeId, @Param("dishType") Integer dishType, @Param("dishMenuType") Integer dishMenuType);
+    List<StoreMenuVo> getStoreMenuInfoList(@Param("storeId") Integer storeId, @Param("dishType") Integer dishType, @Param("dishMenuType") Integer dishMenuType);
 
     /**
      * 获取菜单

+ 34 - 0
alien-entity/src/main/resources/mapper/DrinkInfoMapper.xml

@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="shop.alien.mapper.DrinkInfoMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="shop.alien.entity.store.DrinkInfo">
+        <id column="id" property="id" />
+        <result column="type" property="type" />
+        <result column="name" property="name" />
+        <result column="price" property="price" />
+        <result column="cost_price" property="costPrice" />
+        <result column="category" property="category" />
+        <result column="alcohol_volume" property="alcoholVolume" />
+        <result column="pic_url" property="picUrl" />
+        <result column="description" property="description" />
+        <result column="flavor" property="flavor" />
+        <result column="store_id" property="storeId" />
+        <result column="is_recommended" property="isRecommended" />
+        <result column="status" property="status" />
+        <result column="sort" property="sort" />
+        <result column="is_deleted" property="isDeleted" />
+        <result column="create_user_id" property="createUserId" />
+        <result column="create_time" property="createTime" />
+        <result column="update_user_id" property="updateUserId" />
+        <result column="update_time" property="updateTime" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, type, name, price, cost_price, category, alcohol_volume, pic_url, description, flavor, store_id, 
+        is_recommended, status, sort, is_deleted, create_user_id, create_time, update_user_id, update_time
+    </sql>
+
+</mapper>

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

@@ -1031,6 +1031,7 @@ public class LawyerClientConsultationOrderServiceImpl extends ServiceImpl<Lawyer
                     .set(LawyerConsultationOrder::getOrderStatus, LawyerStatusEnum.REFUNDED.getStatus())
                     .set(LawyerConsultationOrder::getApplyRefundStatus, REFUND_STATUS_AGREED)
                     .set(LawyerConsultationOrder::getApplyRefundProcessTime, processTime)
+                    .set(LawyerConsultationOrder::getApplyRefundTime, processTime)
                     .set(LawyerConsultationOrder::getUpdatedTime, processTime);
 
             int updateCount = consultationOrderMapper.update(null, updateWrapper);

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

@@ -1715,7 +1715,7 @@ public class LawyerConsultationOrderServiceImpl extends ServiceImpl<LawyerConsul
             LifeNotice lifeNotice = new LifeNotice();
             lifeNotice.setSenderId(SYSTEM_SENDER_ID);
             lifeNotice.setBusinessId(order.getId());
-            lifeNotice.setTitle("退款申请通知");
+            lifeNotice.setTitle("申请退款通知");
 
             // 获取申请人接收ID
             String receiverId = getClientReceiverId(clientUserId);

+ 4 - 1
alien-lawyer/src/main/java/shop/alien/lawyer/service/impl/OrderExpirationServiceImpl.java

@@ -29,6 +29,7 @@ import shop.alien.util.common.constant.PaymentEnum;
 import javax.annotation.PostConstruct;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -176,7 +177,7 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
                     //退款到账通知
                     LifeNotice lifeNotice2 = buildUserLifeNotice(order, "退款到账通知", "您的编号为" + orderNo + "的订单,订单金额已原路返还至您的支付渠道,请查收。");
                     WebSocketVo webSocketVo2 = buildWebSocketVo(lifeNotice2);
-                    lifeNotice2.setCreatedTime(DateUtils.calcMinute(lifeNotice2.getCreatedTime(), 2));
+                    lifeNotice2.setCreatedTime(DateUtils.calcMinute(new Date(), 2));
 
                     lifeNoticeMapper.insert(lifeNotice2);
                     webSocketProcess.sendMessage(lifeNotice2.getReceiverId(), JSONObject.from(webSocketVo2).toJSONString());
@@ -186,6 +187,7 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
                     LawyerConsultationOrder update = new LawyerConsultationOrder();
                     update.setId(order.getId());
                     update.setOrderStatus(5);
+                    update.setApplyRefundTime(new Date());
                     orderMapper.updateById( update);
                 }
             }
@@ -233,6 +235,7 @@ public class OrderExpirationServiceImpl implements OrderExpirationService, Comma
                     update.setId(order.getId());
                     update.setOrderStatus(5);
                     update.setApplyRefundStatus("4");
+                    update.setApplyRefundTime(new Date());
                     orderMapper.updateById(update);
                 }
             }

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

@@ -140,6 +140,7 @@ public class StorePlatformLoginServiceImpl extends ServiceImpl<StoreUserMapper,
             if (storeInfo != null) {
                 storeUserVo.setBusinessSection(storeInfo.getBusinessSection());
                 storeUserVo.setBusinessTypesName(storeInfo.getBusinessTypesName());
+                storeUserVo.setMealsFlag(storeInfo.getMealsFlag());
             }
             return R.data(storeUserVo);
         } catch (Exception e) {

+ 4 - 2
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformRenovationServiceImpl.java

@@ -64,8 +64,10 @@ public class StorePlatformRenovationServiceImpl extends ServiceImpl<StoreInfoMap
         StoreInfo storeInfo = storeInfoMapper.selectById(id);
         StoreMainInfoVo storeMainInfoVo = storeInfoMapper.getStoreInfo(id);
         SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
-        String expirationDate = sdf.format(storeMainInfoVo.getExpirationTime());
-        storeMainInfoVo.setExpirationDate(expirationDate);
+        if (storeMainInfoVo.getExpirationTime() != null) {
+            String expirationDate = sdf.format(storeMainInfoVo.getExpirationTime());
+            storeMainInfoVo.setExpirationDate(expirationDate);
+        }
         //审核通过给前台反显未提交
         if (storeMainInfoVo.getRenewContractStatus() == 1) {
             storeMainInfoVo.setRenewContractStatus(0);

+ 190 - 0
alien-store/src/main/java/shop/alien/store/controller/DrinkInfoController.java

@@ -0,0 +1,190 @@
+package shop.alien.store.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.DrinkInfo;
+import shop.alien.entity.store.vo.DrinkInfoVo;
+import shop.alien.store.service.DrinkInfoService;
+
+import java.util.List;
+
+/**
+ * 酒水餐食信息表Controller
+ *
+ * @author ssk
+ * @since 2025-06-13
+ */
+@Slf4j
+@Api(tags = {"酒水餐食管理"})
+@ApiSort(1)
+@CrossOrigin
+@RestController
+@RequestMapping("/store/drink")
+@RequiredArgsConstructor
+public class DrinkInfoController {
+
+    private final DrinkInfoService drinkInfoService;
+
+    @ApiOperation("分页查询酒水餐食列表")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "page", value = "页码", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "size", value = "页容", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "type", value = "类型(枚举值:酒水/餐食)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "category", value = "分类", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "name", value = "名称关键词", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "createUserId", value = "创建人ID(只查询自己创建的)", dataType = "Integer", paramType = "query")
+    })
+    @GetMapping("/page")
+    public R<IPage<DrinkInfoVo>> getDrinkInfoPage(
+            @RequestParam("page") int page,
+            @RequestParam("size") int size,
+            @RequestParam(value = "storeId", required = false) Integer storeId,
+            @RequestParam(value = "type", required = false) String type,
+            @RequestParam(value = "category", required = false) String category,
+            @RequestParam(value = "name", required = false) String name,
+            @RequestParam(value = "createUserId", required = false) Integer createUserId) {
+        log.info("DrinkInfoController.getDrinkInfoPage?page={}, size={}, storeId={}, type={}, category={}, name={}, createUserId={}", 
+                page, size, storeId, type, category, name, createUserId);
+        IPage<DrinkInfoVo> drinkInfoPage = drinkInfoService.getDrinkInfoPage(page, size, storeId, type, category, name, createUserId);
+        return R.data(drinkInfoPage);
+    }
+
+    @ApiOperation("根据ID查询酒水餐食详情")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "Integer", paramType = "path", required = true)
+    })
+    @GetMapping("/{id}")
+    public R<DrinkInfoVo> getDrinkInfoById(@PathVariable("id") Integer id) {
+        log.info("DrinkInfoController.getDrinkInfoById?id={}", id);
+        DrinkInfoVo drinkInfoVo = drinkInfoService.getDrinkInfoById(id);
+        if (drinkInfoVo == null) {
+            return R.fail("未找到该酒水餐食信息");
+        }
+        return R.data(drinkInfoVo);
+    }
+
+    @ApiOperation("新增酒水餐食")
+    @ApiOperationSupport(order = 3)
+    @PostMapping
+    public R<String> saveDrinkInfo(@RequestBody DrinkInfo drinkInfo) {
+        log.info("DrinkInfoController.saveDrinkInfo?drinkInfo={}", drinkInfo);
+        boolean result = drinkInfoService.saveDrinkInfo(drinkInfo);
+        if (result) {
+            return R.success("新增成功");
+        }
+        return R.fail("新增失败");
+    }
+
+    @ApiOperation("修改酒水餐食")
+    @ApiOperationSupport(order = 4)
+    @PutMapping
+    public R<String> updateDrinkInfo(@RequestBody DrinkInfo drinkInfo) {
+        log.info("DrinkInfoController.updateDrinkInfo?drinkInfo={}", drinkInfo);
+        boolean result = drinkInfoService.updateDrinkInfo(drinkInfo);
+        if (result) {
+            return R.success("修改成功");
+        }
+        return R.fail("修改失败");
+    }
+
+    @ApiOperation("删除酒水餐食")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "Integer", paramType = "path", required = true)
+    })
+    @DeleteMapping("/{id}")
+    public R<String> deleteDrinkInfo(@PathVariable("id") Integer id) {
+        log.info("DrinkInfoController.deleteDrinkInfo?id={}", id);
+        boolean result = drinkInfoService.deleteDrinkInfo(id);
+        if (result) {
+            return R.success("删除成功");
+        }
+        return R.fail("删除失败");
+    }
+
+    @ApiOperation("设置酒水餐食推荐")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "Integer", paramType = "path", required = true),
+            @ApiImplicitParam(name = "isRecommended", value = "是否推荐(0:否, 1:是)", dataType = "Integer", paramType = "query", required = true)
+    })
+    @PutMapping("/{id}/recommended")
+    public R<String> updateIsRecommended(
+            @PathVariable("id") Integer id,
+            @RequestParam("isRecommended") Integer isRecommended) {
+        log.info("DrinkInfoController.updateIsRecommended?id={}, isRecommended={}", id, isRecommended);
+        boolean result = drinkInfoService.updateIsRecommended(id, isRecommended);
+        if (result) {
+            return R.success("操作成功");
+        }
+        return R.fail("操作失败");
+    }
+
+    @ApiOperation("更新酒水餐食排序")
+    @ApiOperationSupport(order = 8)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键ID", dataType = "Integer", paramType = "path", required = true),
+            @ApiImplicitParam(name = "sort", value = "排序值", dataType = "Integer", paramType = "query", required = true)
+    })
+    @PutMapping("/{id}/sort")
+    public R<String> updateSort(
+            @PathVariable("id") Integer id,
+            @RequestParam("sort") Integer sort) {
+        log.info("DrinkInfoController.updateSort?id={}, sort={}", id, sort);
+        boolean result = drinkInfoService.updateSort(id, sort);
+        if (result) {
+            return R.success("操作成功");
+        }
+        return R.fail("操作失败");
+    }
+
+    @ApiOperation("根据门店ID查询所有酒水餐食")
+    @ApiOperationSupport(order = 9)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "type", value = "类型(枚举值:酒水/餐食)", dataType = "String", paramType = "query")
+    })
+    @GetMapping("/listByStoreId")
+    public R<List<DrinkInfoVo>> getDrinkInfoListByStoreId(
+            @RequestParam("storeId") Integer storeId,
+            @RequestParam(value = "type", required = false) String type) {
+        log.info("DrinkInfoController.getDrinkInfoListByStoreId?storeId={}, type={}", storeId, type);
+        List<DrinkInfoVo> drinkInfoList = drinkInfoService.getDrinkInfoListByStoreId(storeId, type);
+        return R.data(drinkInfoList);
+    }
+
+    @ApiOperation("查询推荐酒水餐食列表")
+    @ApiOperationSupport(order = 10)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "createUserId", value = "创建人ID(只查询自己创建的)", dataType = "Integer", paramType = "query")
+    })
+    @GetMapping("/recommended")
+    public R<List<DrinkInfoVo>> getRecommendedList(
+            @RequestParam(value = "storeId", required = false) Integer storeId,
+            @RequestParam(value = "createUserId", required = false) Integer createUserId) {
+        log.info("DrinkInfoController.getRecommendedList?storeId={}, createUserId={}", storeId, createUserId);
+        List<DrinkInfoVo> drinkInfoList = drinkInfoService.getRecommendedList(storeId, createUserId);
+        return R.data(drinkInfoList);
+    }
+
+    @ApiOperation("批量更新酒水餐食排序")
+    @ApiOperationSupport(order = 11)
+    @PostMapping("/batchSort")
+    public R<String> batchUpdateSort(@RequestBody List<DrinkInfo> drinkInfoList) {
+        log.info("DrinkInfoController.batchUpdateSort?size={}", drinkInfoList.size());
+        boolean result = drinkInfoService.batchUpdateSort(drinkInfoList);
+        if (result) {
+            return R.success("批量更新排序成功");
+        }
+        return R.fail("批量更新排序失败");
+    }
+
+}

+ 99 - 0
alien-store/src/main/java/shop/alien/store/controller/OperationalActivityController.java

@@ -0,0 +1,99 @@
+package shop.alien.store.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.storePlatform.vo.StoreOperationalActivityVO;
+import shop.alien.store.service.OperationalActivityService;
+
+/**
+ * 运营活动管理控制器
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+@Slf4j
+@Api(tags = {"商家端-运营活动管理"})
+@ApiSort(10)
+@CrossOrigin
+@RestController
+@RequestMapping("/operationalActivity")
+@RequiredArgsConstructor
+public class OperationalActivityController {
+
+    private final OperationalActivityService activityService;
+
+    @ApiOperation("根据活动ID获取详情")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParam(name = "id", value = "活动ID", dataTypeClass = Integer.class, paramType = "path", required = true)
+    @GetMapping("/detail/{id}")
+    public R<StoreOperationalActivityVO> getActivityDetailById(@PathVariable("id") Integer id) {
+        log.info("OperationalActivityController.getActivityDetailById: id={}", id);
+        try {
+            StoreOperationalActivityVO result = activityService.getActivityDetailById(id);
+            return R.data(result);
+        } catch (IllegalArgumentException e) {
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("OperationalActivityController.getActivityDetailById ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("分页查看运营活动列表")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "商户ID", dataTypeClass = Integer.class, paramType = "query"),
+            @ApiImplicitParam(name = "storeName", value = "商户名称(模糊)", dataTypeClass = String.class, paramType = "query"),
+            @ApiImplicitParam(name = "pageNum", value = "当前页", dataTypeClass = Integer.class, paramType = "query"),
+            @ApiImplicitParam(name = "pageSize", value = "每页数量", dataTypeClass = Integer.class, paramType = "query")
+    })
+    @GetMapping("/detail")
+    public R<IPage<StoreOperationalActivityVO>> pageActivityDetail(
+            @RequestParam(value = "storeId", required = false) Integer storeId,
+            @RequestParam(value = "storeName", required = false) String storeName,
+            @RequestParam(value = "pageNum", required = false) Integer pageNum,
+            @RequestParam(value = "pageSize", required = false) Integer pageSize) {
+        log.info("OperationalActivityController.pageActivityDetail storeId={}, storeName={}, pageNum={}, pageSize={}", storeId, storeName, pageNum, pageSize);
+        try {
+            IPage<StoreOperationalActivityVO> result = activityService.pageActivityDetail(storeId, storeName, pageNum, pageSize);
+            return R.data(result);
+        } catch (IllegalArgumentException e) {
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("OperationalActivityController.pageActivityDetail ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+    @ApiOperation("运营活动审核处理")
+    @ApiOperationSupport(order = 6)
+    @PostMapping("/audit")
+    public R<String> auditActivity(
+            @RequestParam("id") Integer id,
+            @RequestParam("status") Integer status,
+            @RequestParam(value = "approvalComments", required = false) String approvalComments) {
+        log.info("OperationalActivityController.auditActivity: id={}, status={}, approvalComments={}", id, status, approvalComments);
+        if (id == null) {
+            return R.fail("活动ID不能为空");
+        }
+        if (status == null) {
+            return R.fail("审核状态不能为空");
+        }
+        try {
+            int result = activityService.auditActivity(id, status, approvalComments);
+            if (result > 0) {
+                return R.success("审核处理成功");
+            }
+            return R.fail("审核处理失败");
+        } catch (Exception e) {
+            log.error("OperationalActivityController.auditActivity ERROR: {}", e.getMessage(), e);
+            return R.fail(e.getMessage());
+        }
+    }
+
+}
+

+ 23 - 6
alien-store/src/main/java/shop/alien/store/controller/StoreInfoController.java

@@ -101,6 +101,7 @@ public class StoreInfoController {
         return R.fail("失败");
     }
 
+
     @ApiOperation("新增门店草稿")
     @ApiOperationSupport(order = 3)
     @PostMapping("/saveStoreInfoDraft")
@@ -1050,7 +1051,28 @@ public class StoreInfoController {
             return R.fail("获取推荐店铺失败,请稍后重试");
         }
     }
-
+    /**
+     * 根据business_classify字段获取字典表数据实现UI图中的功能
+     * RESTful风格:GET /store/info/business-classifies
+     * 返回扁平化的分类列表,用于多选分类功能
+     *
+     * @param parentId 父分类ID(可选),如果提供则只返回该父分类下的子分类
+     * @return R<List<StoreDictionaryVo>> 分类列表(扁平化,仅子分类)
+     */
+    @ApiOperation("获取店铺分类信息)")
+    @ApiOperationSupport(order = 19)
+    @GetMapping("/business-classifies")
+    public R<List<StoreDictionaryVo>> getBusinessClassifyData(
+            @RequestParam(value = "parentId", required = false) Integer parentId) {
+        log.info("StoreInfoController.getBusinessClassifyData?parentId={}", parentId);
+        try {
+            List<StoreDictionaryVo> result = storeInfoService.getBusinessClassifyData(parentId);
+            return R.data(result);
+        } catch (Exception e) {
+            log.error("获取business_classify分类数据异常", e);
+            return R.fail("获取分类数据失败,请稍后重试");
+        }
+    }
 
 
     @ApiOperation(value = "获取banner图详情")
@@ -1147,9 +1169,4 @@ public class StoreInfoController {
     }
 
 
-
-
-
-
-
 }

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

@@ -149,7 +149,7 @@ public class StoreMenuController {
             @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query", required = true),
             @ApiImplicitParam(name = "dishType", value = "菜品类型, 0:(推荐+非推荐), 1:推荐", dataType = "Integer", paramType = "query"),
             @ApiImplicitParam(name = "phoneId", value = "用户手机号", dataType = "String", paramType = "query"),
-            @ApiImplicitParam(name = "dishMenuType", value = "菜单类型:1-菜,2-酒水", dataType = "Integer", paramType = "query")
+            @ApiImplicitParam(name = "dishMenuType", value = "菜单类型:1-菜,2-酒,不传就是菜+酒(页面叫酒", dataType = "Integer", paramType = "query")
     })
     @GetMapping("/getClientMenuByStoreId")
     public R<Map<String, Object>> getClientMenuByStoreId(

+ 20 - 0
alien-store/src/main/java/shop/alien/store/controller/StoreStaffConfigController.java

@@ -78,6 +78,26 @@ public class StoreStaffConfigController {
         return R.data(s);
     }
 
+    @ApiOperation("删除员工")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "主键id", dataType = "Integer", paramType = "query", required = true)})
+    @GetMapping("/deleteStaffConfig")
+    public R<Integer> deleteStaffConfig(Integer id) {
+        log.info("StoreStaffConfigController.deleteStaffConfig?id={}", id);
+        return R.data(storeStaffConfigService.deleteStaffConfig(id));
+    }
+
+    @ApiOperation("置顶员工")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "主键id", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "topStatus", value = "置顶状态 0-取消置顶, 1-置顶", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/setTopStatus")
+    public R<Integer> setTopStatus(Integer id, Integer topStatus) {
+        log.info("StoreStaffConfigController.setTopStatus?id={},topStatus={}", id, topStatus);
+        return R.data(storeStaffConfigService.setTopStatus(id, topStatus));
+    }
     /**
      * 员工列表查询接口(用户端)
      *

+ 141 - 0
alien-store/src/main/java/shop/alien/store/service/DrinkInfoService.java

@@ -0,0 +1,141 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.store.DrinkInfo;
+import shop.alien.entity.store.vo.DrinkInfoVo;
+
+import java.util.List;
+
+/**
+ * 酒水餐食信息表 服务类
+ *
+ * @author ssk
+ * @since 2025-06-13
+ */
+public interface DrinkInfoService extends IService<DrinkInfo> {
+
+    /**
+     * 分页查询酒水餐食列表
+     *
+     * @param page         页码
+     * @param size         页容
+     * @param storeId      门店ID
+     * @param type         类型(枚举值:酒水/餐食)
+     * @param category     分类
+     * @param name         名称关键词
+     * @param createUserId 创建人ID(只查询指定用户创建的)
+     * @return IPage<DrinkInfoVo>
+     */
+    IPage<DrinkInfoVo> getDrinkInfoPage(int page, int size, Integer storeId, String type, String category, String name, Integer createUserId);
+
+    /**
+     * 根据ID查询酒水餐食详情
+     *
+     * @param id 主键ID
+     * @return DrinkInfoVo
+     */
+    DrinkInfoVo getDrinkInfoById(Integer id);
+
+    /**
+     * 新增酒水餐食
+     *
+     * @param drinkInfo 酒水餐食信息
+     * @return boolean
+     */
+    boolean saveDrinkInfo(DrinkInfo drinkInfo);
+
+    /**
+     * 修改酒水餐食
+     *
+     * @param drinkInfo 酒水餐食信息
+     * @return boolean
+     */
+    boolean updateDrinkInfo(DrinkInfo drinkInfo);
+
+    /**
+     * 删除酒水餐食(软删除)
+     *
+     * @param id 主键ID
+     * @return boolean
+     */
+    boolean deleteDrinkInfo(Integer id);
+
+    /**
+     * 上下架酒水餐食
+     *
+     * @param id     主键ID
+     * @param status 状态(0:下架, 1:上架)
+     * @return boolean
+     */
+    boolean updateStatus(Integer id, Integer status);
+
+    /**
+     * 设置酒水餐食推荐
+     *
+     * @param id            主键ID
+     * @param isRecommended 是否推荐(0:否, 1:是)
+     * @return boolean
+     */
+    boolean updateIsRecommended(Integer id, Integer isRecommended);
+
+    /**
+     * 更新酒水餐食排序
+     *
+     * @param id   主键ID
+     * @param sort 排序值
+     * @return boolean
+     */
+    boolean updateSort(Integer id, Integer sort);
+
+    /**
+     * 根据门店ID查询所有酒水餐食
+     *
+     * @param storeId 门店ID
+     * @param type    类型(枚举值:酒水/餐食)
+     * @return List<DrinkInfoVo>
+     */
+    List<DrinkInfoVo> getDrinkInfoListByStoreId(Integer storeId, String type);
+
+    /**
+     * 查询推荐酒水餐食列表
+     *
+     * @param storeId      门店ID
+     * @param createUserId 创建人ID(只查询指定用户创建的)
+     * @return List<DrinkInfoVo>
+     */
+    List<DrinkInfoVo> getRecommendedList(Integer storeId, Integer createUserId);
+
+    /**
+     * 批量更新酒水餐食排序
+     *
+     * @param drinkInfoList 酒水餐食列表(包含id和sort字段)
+     * @return boolean
+     */
+    boolean batchUpdateSort(List<DrinkInfo> drinkInfoList);
+
+    /**
+     * 获取酒水餐食类型统计
+     *
+     * @param storeId 门店ID
+     * @return Map<String, Long> 类型统计信息
+     */
+    java.util.Map<String, Long> getStatistics(Integer storeId);
+
+    /**
+     * 批量删除酒水餐食
+     *
+     * @param ids 主键ID列表
+     * @return boolean
+     */
+    boolean batchDelete(List<Integer> ids);
+
+    /**
+     * 批量上下架
+     *
+     * @param ids    主键ID列表
+     * @param status 状态(0:下架, 1:上架)
+     * @return boolean
+     */
+    boolean batchUpdateStatus(List<Integer> ids, Integer status);
+}

+ 44 - 0
alien-store/src/main/java/shop/alien/store/service/OperationalActivityService.java

@@ -0,0 +1,44 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import shop.alien.entity.storePlatform.vo.StoreOperationalActivityVO;
+
+/**
+ * 运营活动服务接口
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+public interface OperationalActivityService {
+
+    /**
+     * 审核运营活动
+     *
+     * @param id               活动ID
+     * @param status           审核状态(1通过/0驳回等)
+     * @param approvalComments 驳回原因
+     * @return 更新结果
+     */
+    int auditActivity(Integer id, Integer status, String approvalComments);
+
+    /**
+     * 根据门店条件分页查询运营活动
+     *
+     * @param storeId   门店ID
+     * @param storeName 门店名称(模糊)
+     * @param pageNum   页码
+     * @param pageSize  每页数量
+     * @return 活动分页结果
+     */
+    IPage<StoreOperationalActivityVO> pageActivityDetail(Integer storeId, String storeName, Integer pageNum, Integer pageSize);
+
+    /**
+     * 根据活动ID获取活动详情
+     *
+     * @param id 活动ID
+     * @return 活动详情
+     */
+    StoreOperationalActivityVO getActivityDetailById(Integer id);
+
+}
+

+ 80 - 49
alien-store/src/main/java/shop/alien/store/service/StoreInfoService.java

@@ -138,6 +138,13 @@ public interface StoreInfoService extends IService<StoreInfo> {
     StoreInfoVo editStoreInfo(StoreInfoDto storeInfoDto);
 
     /**
+     * 新中台web端修改门店及门店用户
+     *
+     * @return ResponseEntity
+     */
+    StoreInfoVo editNewStoreInfo(StoreInfoDto storeInfoDto);
+
+    /**
      * web端删除门店及门店用户
      *
      * @return ResponseEntity
@@ -177,6 +184,11 @@ public interface StoreInfoService extends IService<StoreInfo> {
     StoreInfoVo getStoreDetail(String storeId, String userId, String jingdu, String weidu);
 
     /**
+     * 中台web端查询门店明细
+     */
+    StoreInfoVo getNewStoreDetail(String storeId);
+
+    /**
      * web端审批结果
      */
     void approveStoreInfo(String storeId, Integer approvalStatus, String reason);
@@ -291,6 +303,52 @@ public interface StoreInfoService extends IService<StoreInfo> {
     int foodLicenceType(int id);
 
     /**
+     * 店铺娱乐经营许可证
+     * @param storeImg
+     * @return
+     */
+    int uploadEntertainmentLicence(StoreImg storeImg);
+
+    /**
+     * 获取店铺娱乐经营许可证状态以及店铺状态为审核中合同图片list
+     * @param id
+     * @return
+     */
+    Map<String,Object> getStoreEntertainmentLicenceStatus(int id);
+
+    /**
+     * 娱乐经营许可证审核通过后 图片类型变为审核通过后 img_type26
+     *
+     */
+    int entertainmentLicenceType(int id);
+
+    /**
+     * 获取门店代金券
+     */
+    List<LifeCouponVo> getStoreCouponList(String storeId);
+
+
+    /**
+     * 获取活动banner图
+     */
+    List<StoreImg> getBannerUrl (String storeId);
+    /**
+     * 获取活动banner图
+     */
+
+    List<StoreImg> getBannerUrlInfo(String storeId, Integer businessId);
+
+
+    /**
+     * web-分页查询店铺信息
+     *
+
+     * @return IPage<StoreInfoVo>
+     */
+    List<StoreInfoVo> getMoreRecommendedStores(Double lon , Double lat, String businessSection, String businessTypes, String businessClassify);
+
+
+    /**
      * 根据门店及图片地址查询最新OCR识别数据
      *
      * @param imageUrl 图片URL
@@ -298,9 +356,6 @@ public interface StoreInfoService extends IService<StoreInfo> {
      */
     Map<String, Object> getStoreOcrData(String imageUrl, String merchantName);
 
-    void aiApproveStoreInfo(AiApproveStoreInfo aiApproveStoreInfo);
-
-
     /**
      * 查询四种类型店铺(酒吧、ktv、洗浴汗蒸、按摩足浴)并按距离筛选
      *
@@ -309,14 +364,17 @@ public interface StoreInfoService extends IService<StoreInfo> {
      * @param distance    距离范围(单位:公里)
      * @param sortType    排序模式(1:智能排序,2:好评优先,3:距离优先)
      * @param businessType 店铺类型(KTV=3、洗浴汗蒸=4、按摩足浴=5,酒吧需要查询字典表),可选
-     * @param categoryId 字典表id,根据此id查询经营板块、经营种类、分类并匹配店铺,可选
+     * @param categoryId  分类ID(二级或三级分类的dictId,从getAllBusinessSection接口获取),可选
      * @param pageNum     页码
      * @param pageSize    页容
      * @return IPage<StoreInfoVo> 分页的门店信息列表
      */
     IPage<StoreInfoVo> getSpecialTypeStoresByDistance(Double lon, Double lat, Double distance, Integer sortType, Integer businessType, Integer categoryId, int pageNum, int pageSize);
 
-
+    /**
+     * web端查询门店明细
+     */
+    StoreInfoVo getClientStoreDetail(String storeId, String userId, String jingdu, String weidu);
 
     /**
      * 获取休闲娱乐分类数据(主分类和子分类)
@@ -337,6 +395,14 @@ public interface StoreInfoService extends IService<StoreInfo> {
      */
     List<StoreDictionary> getAllBusinessSection(String businessSection);
 
+    /**
+     * 获取门店下三级分类结构
+     * 根据门店ID查询该门店的经营板块、经营种类和分类的三级结构
+     *
+     * @param storeId 门店ID
+     * @return StoreThreeLevelStructureVo 包含门店信息和三级分类树形结构
+     */
+    StoreThreeLevelStructureVo getStoreThreeLevelStructure(Integer storeId);
 
     /**
      * 你可能还喜欢(推荐店铺)
@@ -352,8 +418,16 @@ public interface StoreInfoService extends IService<StoreInfo> {
      */
     List<StoreInfoVo> getRecommendedStores(String businessSection, String businessTypes, String businessClassify, Double lon, Double lat);
 
+    /**
+     * 获取三级分类数据
+     * 根据二级分类ID获取该分类下的三级分类
+     *
+     * @param parentId 二级分类ID
+     * @return List<StoreDictionaryVo> 三级分类列表
+     */
+    List<StoreDictionaryVo> getBusinessClassifyData(Integer parentId);
 
-
+    void aiApproveStoreInfo(AiApproveStoreInfo aiApproveStoreInfo);
 
 
     /**
@@ -369,47 +443,4 @@ public interface StoreInfoService extends IService<StoreInfo> {
      * @return R<IPage<StoreInfoVo>> 分页的门店信息列表
      */
     IPage<StoreInfoVo> getLifeServicesByDistance(Double lon, Double lat, Double distance, Integer sortType, Integer businessType, Integer categoryId, int pageNum, int pageSize);
-
-    /**
-     * 获取活动banner图
-     */
-    List<StoreImg> getBannerUrl (String storeId);
-    /**
-     * 获取活动详情banner图
-     */
-
-    List<StoreImg> getBannerUrlInfo(String storeId, Integer businessId);
-
-    /**
-     * web-分页查询店铺信息
-     *
-
-     * @return IPage<StoreInfoVo>
-     */
-    List<StoreInfoVo> getMoreRecommendedStores(Double lon , Double lat, String businessSection, String businessTypes, String businessClassify);
-
-
-    /**
-     * web端查询门店明细
-     */
-    StoreInfoVo getClientStoreDetail(String storeId, String userId, String jingdu, String weidu);
-
-    /**
-     * 获取门店代金券
-     */
-    List<LifeCouponVo> getStoreCouponList(String storeId);
-
-    /**
-     * 中台web端查询门店明细
-     */
-    StoreInfoVo getNewStoreDetail(String storeId);
-
-    /**
-     * 新中台web端修改门店及门店用户
-     *
-     * @return ResponseEntity
-     */
-    StoreInfoVo editNewStoreInfo(StoreInfoDto storeInfoDto);
-
-
 }

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

@@ -2,6 +2,8 @@ package shop.alien.store.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
 import shop.alien.entity.store.StoreOfficialAlbum;
+import shop.alien.entity.store.vo.StoreAlbumNameVo;
+import shop.alien.entity.store.vo.StoreOfficialAlbumImgVo;
 import shop.alien.entity.store.vo.StoreOfficialAlbumVo;
 
 import java.util.List;
@@ -25,7 +27,7 @@ public interface StoreOfficialAlbumService extends IService<StoreOfficialAlbum>
      * @param albumName 相册名称,可选。例如:酒水、餐食、环境、全部等。当为null或空字符串时,查询全部
      * @return 图片列表和总数
      */
-    shop.alien.entity.store.vo.StoreOfficialAlbumImgVo getOfficialAlbumImgList(Integer storeId, String albumName);
+    StoreOfficialAlbumImgVo getOfficialAlbumImgList(Integer storeId, String albumName);
 
     /**
      * 获取官方相册名称列表(客户端)
@@ -36,5 +38,5 @@ public interface StoreOfficialAlbumService extends IService<StoreOfficialAlbum>
      * @param storeId 门店ID,必填
      * @return 相册名称列表,包含相册名称和图片数量
      */
-    List<shop.alien.entity.store.vo.StoreAlbumNameVo> getAlbumNameList(Integer storeId);
+    List<StoreAlbumNameVo> getAlbumNameList(Integer storeId);
 }

+ 18 - 0
alien-store/src/main/java/shop/alien/store/service/StoreStaffConfigService.java

@@ -19,6 +19,24 @@ public interface StoreStaffConfigService {
     String staffConfigExport(String status) throws IOException;
 
     /**
+     * 删除员工
+     *
+     * @param id
+     * @return
+     */
+    Integer deleteStaffConfig(Integer id);
+
+    /**
+     * 置顶员工
+     *
+     * @param id 员工ID
+     * @param topStatus 置顶状态 0-未置顶, 1-置顶
+     * @return
+     */
+    Integer setTopStatus(Integer id, Integer topStatus);
+
+
+    /**
      * 员工列表查询
      *
      * @param page    分页页数

+ 260 - 0
alien-store/src/main/java/shop/alien/store/service/impl/DrinkInfoServiceImpl.java

@@ -0,0 +1,260 @@
+package shop.alien.store.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import shop.alien.entity.store.DrinkInfo;
+import shop.alien.entity.store.vo.DrinkInfoVo;
+import shop.alien.mapper.DrinkInfoMapper;
+import shop.alien.store.service.DrinkInfoService;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 酒水餐食信息表 服务实现类
+ *
+ * @author ssk
+ * @since 2025-06-13
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+@Transactional
+public class DrinkInfoServiceImpl extends ServiceImpl<DrinkInfoMapper, DrinkInfo> implements DrinkInfoService {
+
+    private final DrinkInfoMapper drinkInfoMapper;
+
+    @Override
+    public IPage<DrinkInfoVo> getDrinkInfoPage(int page, int size, Integer storeId, String type, String category, String name, Integer createUserId) {
+        LambdaQueryWrapper<DrinkInfo> queryWrapper = new LambdaQueryWrapper<>();
+        // 软删除条件
+        queryWrapper.eq(DrinkInfo::getIsDeleted, 0);
+        // 筛选条件
+        if (createUserId != null) {
+            queryWrapper.eq(DrinkInfo::getCreateUserId, createUserId);
+        }
+        if (storeId != null) {
+            queryWrapper.eq(DrinkInfo::getStoreId, storeId);
+        }
+        if (type != null && !type.isEmpty()) {
+            queryWrapper.eq(DrinkInfo::getType, type);
+        }
+        if (category != null && !category.isEmpty()) {
+            queryWrapper.eq(DrinkInfo::getCategory, category);
+        }
+        if (name != null && !name.isEmpty()) {
+            queryWrapper.like(DrinkInfo::getName, name);
+        }
+        // 按排序和创建时间倒序
+        queryWrapper.orderByAsc(DrinkInfo::getSort);
+        queryWrapper.orderByDesc(DrinkInfo::getCreateTime);
+
+        IPage<DrinkInfo> drinkInfoPage = drinkInfoMapper.selectPage(new Page<>(page, size), queryWrapper);
+        // 转换为Vo
+        IPage<DrinkInfoVo> drinkInfoVoPage = new Page<>(page, size);
+        drinkInfoVoPage.setTotal(drinkInfoPage.getTotal());
+        List<DrinkInfoVo> drinkInfoVoList = drinkInfoPage.getRecords().stream()
+                .map(this::convertToVo)
+                .collect(Collectors.toList());
+        drinkInfoVoPage.setRecords(drinkInfoVoList);
+
+        return drinkInfoVoPage;
+    }
+
+    @Override
+    public DrinkInfoVo getDrinkInfoById(Integer id) {
+        DrinkInfo drinkInfo = drinkInfoMapper.selectById(id);
+        if (drinkInfo == null || drinkInfo.getIsDeleted() == 1) {
+            return null;
+        }
+        return convertToVo(drinkInfo);
+    }
+
+    @Override
+    public boolean saveDrinkInfo(DrinkInfo drinkInfo) {
+        // 设置默认值
+        drinkInfo.setIsDeleted(0);
+        drinkInfo.setStatus(1); // 默认上架
+        drinkInfo.setSort(0); // 默认排序
+        return this.save(drinkInfo);
+    }
+
+    @Override
+    public boolean updateDrinkInfo(DrinkInfo drinkInfo) {
+        return this.updateById(drinkInfo);
+    }
+
+    @Override
+    public boolean deleteDrinkInfo(Integer id) {
+        LambdaUpdateWrapper<DrinkInfo> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(DrinkInfo::getId, id)
+                .set(DrinkInfo::getIsDeleted, 1);
+        return this.update(updateWrapper);
+    }
+
+    @Override
+    public boolean updateStatus(Integer id, Integer status) {
+        LambdaUpdateWrapper<DrinkInfo> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(DrinkInfo::getId, id)
+                .eq(DrinkInfo::getIsDeleted, 0)
+                .set(DrinkInfo::getStatus, status);
+        return this.update(updateWrapper);
+    }
+
+    @Override
+    public boolean updateIsRecommended(Integer id, Integer isRecommended) {
+        LambdaUpdateWrapper<DrinkInfo> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(DrinkInfo::getId, id)
+                .eq(DrinkInfo::getIsDeleted, 0)
+                .set(DrinkInfo::getIsRecommended, isRecommended);
+        return this.update(updateWrapper);
+    }
+
+    @Override
+    public boolean updateSort(Integer id, Integer sort) {
+        LambdaUpdateWrapper<DrinkInfo> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(DrinkInfo::getId, id)
+                .eq(DrinkInfo::getIsDeleted, 0)
+                .set(DrinkInfo::getSort, sort);
+        return this.update(updateWrapper);
+    }
+
+    @Override
+    public List<DrinkInfoVo> getDrinkInfoListByStoreId(Integer storeId, String type) {
+        LambdaQueryWrapper<DrinkInfo> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(DrinkInfo::getStoreId, storeId)
+                .eq(DrinkInfo::getIsDeleted, 0)
+                .eq(DrinkInfo::getStatus, 1); // 只查询上架的
+        if (type != null && !type.isEmpty()) {
+            queryWrapper.eq(DrinkInfo::getType, type);
+        }
+        queryWrapper.orderByAsc(DrinkInfo::getSort);
+        queryWrapper.orderByDesc(DrinkInfo::getCreateTime);
+
+        List<DrinkInfo> drinkInfoList = drinkInfoMapper.selectList(queryWrapper);
+        return drinkInfoList.stream()
+                .map(this::convertToVo)
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<DrinkInfoVo> getRecommendedList(Integer storeId, Integer createUserId) {
+        LambdaQueryWrapper<DrinkInfo> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(DrinkInfo::getIsRecommended, 1)
+                .eq(DrinkInfo::getIsDeleted, 0)
+                .eq(DrinkInfo::getStatus, 1); // 只查询上架的推荐商品
+        
+        // 只查询指定用户创建的商品
+        if (createUserId != null) {
+            queryWrapper.eq(DrinkInfo::getCreateUserId, createUserId);
+        }
+        
+        if (storeId != null) {
+            // 查询指定门店的商品,或者store_id为null的公共商品
+            queryWrapper.and(wrapper -> wrapper.eq(DrinkInfo::getStoreId, storeId));
+        }
+        queryWrapper.orderByAsc(DrinkInfo::getSort);
+        queryWrapper.orderByDesc(DrinkInfo::getCreateTime);
+
+        List<DrinkInfo> drinkInfoList = drinkInfoMapper.selectList(queryWrapper);
+        return drinkInfoList.stream()
+                .map(this::convertToVo)
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public boolean batchUpdateSort(List<DrinkInfo> drinkInfoList) {
+        if (drinkInfoList == null || drinkInfoList.isEmpty()) {
+            return false;
+        }
+        try {
+            for (DrinkInfo drinkInfo : drinkInfoList) {
+                if (drinkInfo.getId() != null && drinkInfo.getSort() != null) {
+                    LambdaUpdateWrapper<DrinkInfo> updateWrapper = new LambdaUpdateWrapper<>();
+                    updateWrapper.eq(DrinkInfo::getId, drinkInfo.getId())
+                            .eq(DrinkInfo::getIsDeleted, 0)
+                            .set(DrinkInfo::getSort, drinkInfo.getSort());
+                    this.update(updateWrapper);
+                }
+            }
+            return true;
+        } catch (Exception e) {
+            log.error("批量更新排序失败", e);
+            return false;
+        }
+    }
+
+    @Override
+    public java.util.Map<String, Long> getStatistics(Integer storeId) {
+        LambdaQueryWrapper<DrinkInfo> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(DrinkInfo::getIsDeleted, 0)
+                .eq(DrinkInfo::getStatus, 1); // 只统计上架的
+        if (storeId != null) {
+            queryWrapper.eq(DrinkInfo::getStoreId, storeId);
+        }
+
+        List<DrinkInfo> allList = drinkInfoMapper.selectList(queryWrapper);
+        
+        java.util.Map<String, Long> statistics = new java.util.HashMap<>();
+        statistics.put("total", (long) allList.size());
+        statistics.put("drink", allList.stream().filter(d -> "酒水".equals(d.getType())).count());
+        statistics.put("food", allList.stream().filter(d -> "餐食".equals(d.getType())).count());
+        statistics.put("recommended", allList.stream().filter(d -> d.getIsRecommended() == 1).count());
+        
+        return statistics;
+    }
+
+    @Override
+    public boolean batchDelete(List<Integer> ids) {
+        if (ids == null || ids.isEmpty()) {
+            return false;
+        }
+        try {
+            for (Integer id : ids) {
+                deleteDrinkInfo(id);
+            }
+            return true;
+        } catch (Exception e) {
+            log.error("批量删除失败", e);
+            return false;
+        }
+    }
+
+    @Override
+    public boolean batchUpdateStatus(List<Integer> ids, Integer status) {
+        if (ids == null || ids.isEmpty()) {
+            return false;
+        }
+        try {
+            for (Integer id : ids) {
+                updateStatus(id, status);
+            }
+            return true;
+        } catch (Exception e) {
+            log.error("批量更新状态失败", e);
+            return false;
+        }
+    }
+
+    /**
+     * 将DrinkInfo转换为DrinkInfoVo
+     *
+     * @param drinkInfo DrinkInfo对象
+     * @return DrinkInfoVo对象
+     */
+    private DrinkInfoVo convertToVo(DrinkInfo drinkInfo) {
+        DrinkInfoVo drinkInfoVo = new DrinkInfoVo();
+        BeanUtils.copyProperties(drinkInfo, drinkInfoVo);
+        // 确保图片字段正确映射
+        drinkInfoVo.setPicUrl(drinkInfo.getPicUrl());
+        return drinkInfoVo;
+    }
+}

+ 256 - 0
alien-store/src/main/java/shop/alien/store/service/impl/OperationalActivityServiceImpl.java

@@ -0,0 +1,256 @@
+package shop.alien.store.service.impl;
+
+import com.alibaba.excel.util.StringUtils;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.store.LifeDiscountCoupon;
+import shop.alien.entity.store.StoreImg;
+import shop.alien.entity.store.StoreInfo;
+import shop.alien.entity.storePlatform.StoreOperationalActivity;
+import shop.alien.entity.storePlatform.vo.StoreOperationalActivityVO;
+import shop.alien.mapper.LifeDiscountCouponMapper;
+import shop.alien.mapper.StoreImgMapper;
+import shop.alien.mapper.StoreInfoMapper;
+import shop.alien.mapper.storePlantform.StoreOperationalActivityMapper;
+import shop.alien.store.service.OperationalActivityService;
+
+import java.util.*;
+
+/**
+ * 运营活动服务实现类
+ * <p>
+ * 提供运营活动的增删改查功能,包括:
+ * 1. 活动的创建、更新、删除
+ * 2. 活动列表查询、分页查询
+ * 3. 活动状态管理
+ * </p>
+ *
+ * @author system
+ * @since 2025-11-26
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class OperationalActivityServiceImpl implements OperationalActivityService {
+
+    private final StoreOperationalActivityMapper activityMapper;
+
+    private final StoreImgMapper imgMapper;
+
+    private final LifeDiscountCouponMapper lifeDiscountCouponMapper;
+
+    private final StoreInfoMapper storeInfoMapper;
+
+    @Override
+    public int auditActivity(Integer id, Integer status, String approvalComments) {
+        log.info("OperationalActivityServiceImpl.auditActivity: id={}, status={}, approvalComments={}", id, status, approvalComments);
+
+        if (id == null) {
+            throw new IllegalArgumentException("活动ID不能为空");
+        }
+        if (status == null) {
+            throw new IllegalArgumentException("审核状态不能为空");
+        }
+
+        if (!Objects.equals(status, 1) && StringUtils.isBlank(approvalComments)) {
+            throw new IllegalArgumentException("驳回原因不能为空");
+        }
+
+        StoreOperationalActivity update = new StoreOperationalActivity();
+        update.setId(id);
+        if (Objects.equals(status, 1)) {
+            StoreOperationalActivity activity = activityMapper.selectById(id);
+            if (activity == null) {
+                throw new IllegalArgumentException("活动不存在");
+            }
+            update.setStatus(resolveApprovedStatus(activity));
+            update.setApprovalComments(null);
+        } else {
+            update.setStatus(3);
+            update.setApprovalComments(approvalComments);
+        }
+
+        return activityMapper.updateById(update);
+    }
+
+    @Override
+    public IPage<StoreOperationalActivityVO> pageActivityDetail(Integer storeId, String storeName, Integer pageNum, Integer pageSize) {
+        log.info("OperationalActivityServiceImpl.pageActivityDetail: storeId={}, storeName={}, pageNum={}, pageSize={}", storeId, storeName, pageNum, pageSize);
+
+        if (storeId == null && StringUtils.isBlank(storeName)) {
+            throw new IllegalArgumentException("请至少提供商户ID或商户名称");
+        }
+
+        int current = (pageNum == null || pageNum <= 0) ? 1 : pageNum;
+        int size = (pageSize == null || pageSize <= 0) ? 10 : pageSize;
+
+        // 收集门店ID
+        LinkedHashSet<Integer> storeIds = new LinkedHashSet<>();
+        if (storeId != null) {
+            storeIds.add(storeId);
+        }
+        if (StringUtils.isNotBlank(storeName)) {
+            LambdaQueryWrapper<StoreInfo> storeWrapper = new LambdaQueryWrapper<>();
+            storeWrapper.like(StoreInfo::getStoreName, storeName)
+                    .eq(StoreInfo::getDeleteFlag, 0)
+                    .select(StoreInfo::getId, StoreInfo::getStoreName);
+            List<StoreInfo> storeList = storeInfoMapper.selectList(storeWrapper);
+            for (StoreInfo info : storeList) {
+                if (info.getId() != null) {
+                    storeIds.add(info.getId());
+                }
+            }
+        }
+
+        if (storeIds.isEmpty()) {
+            return new Page<>(current, size, 0);
+        }
+
+        LambdaQueryWrapper<StoreOperationalActivity> wrapper = new LambdaQueryWrapper<>();
+        wrapper.in(StoreOperationalActivity::getStoreId, storeIds);
+        wrapper.eq(StoreOperationalActivity::getDeleteFlag, 0);
+        wrapper.orderByDesc(StoreOperationalActivity::getCreatedTime);
+
+        IPage<StoreOperationalActivity> entityPage = activityMapper.selectPage(new Page<>(current, size), wrapper);
+
+        List<StoreOperationalActivityVO> voRecords = new ArrayList<>(entityPage.getRecords().size());
+        Map<Integer, String> storeCache = new LinkedHashMap<>();
+
+        for (StoreOperationalActivity activity : entityPage.getRecords()) {
+            StoreOperationalActivityVO vo = new StoreOperationalActivityVO();
+            BeanUtils.copyProperties(activity, vo);
+            vo.setStatusName(resolveStatusName(activity.getStatus()));
+
+            if (activity.getCouponId() != null) {
+                LifeDiscountCoupon coupon = lifeDiscountCouponMapper.selectById(activity.getCouponId());
+                if (coupon != null) {
+                    vo.setCouponName(coupon.getName());
+                }
+            }
+
+            attachStoreInfo(vo, storeCache);
+            fillActivityImages(vo);
+            voRecords.add(vo);
+        }
+
+        Page<StoreOperationalActivityVO> voPage = new Page<>(entityPage.getCurrent(), entityPage.getSize(), entityPage.getTotal());
+        voPage.setRecords(voRecords);
+        return voPage;
+    }
+
+    @Override
+    public StoreOperationalActivityVO getActivityDetailById(Integer id) {
+        log.info("OperationalActivityServiceImpl.getActivityDetailById: id={}", id);
+
+        if (id == null) {
+            throw new IllegalArgumentException("活动ID不能为空");
+        }
+
+        StoreOperationalActivity activity = activityMapper.selectById(id);
+        if (activity == null) {
+            return null;
+        }
+
+        StoreOperationalActivityVO vo = new StoreOperationalActivityVO();
+        BeanUtils.copyProperties(activity, vo);
+        vo.setStatusName(resolveStatusName(activity.getStatus()));
+
+        if (activity.getCouponId() != null) {
+            LifeDiscountCoupon coupon = lifeDiscountCouponMapper.selectById(activity.getCouponId());
+            if (coupon != null) {
+                vo.setCouponName(coupon.getName());
+            }
+        }
+
+        attachStoreInfo(vo, new LinkedHashMap<>());
+        fillActivityImages(vo);
+        return vo;
+    }
+
+    private int resolveApprovedStatus(StoreOperationalActivity activity) {
+        Date now = new Date();
+        if (activity.getStartTime() == null || activity.getEndTime() == null) {
+            return 2;
+        }
+        if (now.before(activity.getStartTime())) {
+            return 2;
+        }
+        if (!now.after(activity.getEndTime())) {
+            return 5;
+        }
+        return 7;
+    }
+
+    private String resolveStatusName(Integer status) {
+        if (status == null) {
+            return null;
+        }
+        switch (status) {
+            case 1:
+                return "待审核";
+            case 2:
+                return "未开始";
+            case 3:
+                return "审核拒绝";
+            case 4:
+                return "已售罄";
+            case 5:
+                return "进行中";
+            case 6:
+                return "已下架";
+            case 7:
+                return "已结束";
+            default:
+                return null;
+        }
+    }
+
+    private void attachStoreInfo(StoreOperationalActivityVO vo, Map<Integer, String> cache) {
+        if (vo == null || vo.getStoreId() == null) {
+            return;
+        }
+        Integer sid = vo.getStoreId();
+        if (cache != null && cache.containsKey(sid)) {
+            vo.setStoreName(cache.get(sid));
+            return;
+        }
+        StoreInfo storeInfo = storeInfoMapper.selectById(sid);
+        if (storeInfo != null) {
+            vo.setStoreName(storeInfo.getStoreName());
+            if (cache != null) {
+                cache.put(sid, storeInfo.getStoreName());
+            }
+        }
+    }
+
+    private void fillActivityImages(StoreOperationalActivityVO vo) {
+        if (vo == null || vo.getStoreId() == null || vo.getId() == null) {
+            return;
+        }
+        StoreImg titleImg = imgMapper.selectOne(new LambdaQueryWrapper<StoreImg>()
+                .eq(StoreImg::getStoreId, vo.getStoreId())
+                .eq(StoreImg::getBusinessId, vo.getId())
+                .eq(StoreImg::getImgType, 26)
+                .eq(StoreImg::getDeleteFlag, 0));
+        if (titleImg != null) {
+            vo.setActivityTitleImg(titleImg);
+            vo.setActivityTitleImgUrl(titleImg.getImgUrl());
+        }
+
+        StoreImg detailImg = imgMapper.selectOne(new LambdaQueryWrapper<StoreImg>()
+                .eq(StoreImg::getStoreId, vo.getStoreId())
+                .eq(StoreImg::getBusinessId, vo.getId())
+                .eq(StoreImg::getImgType, 27)
+                .eq(StoreImg::getDeleteFlag, 0));
+        if (detailImg != null) {
+            vo.setActivityDetailImg(detailImg);
+            vo.setActivityDetailImgUrl(detailImg.getImgUrl());
+        }
+    }
+}
+

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 551 - 130
alien-store/src/main/java/shop/alien/store/service/impl/StoreInfoServiceImpl.java


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

@@ -83,7 +83,7 @@ public class StoreMenuServiceImpl extends ServiceImpl<StoreMenuMapper, StoreMenu
     public List<StoreMenuVo> getStoreMenu(Integer storeId, Integer dishType, String phoneId, Integer dishMenuType) {
         // 查询菜单列表
         Integer queryDishType = (dishType != null && dishType == 0) ? null : dishType;
-        List<StoreMenuVo> menuList = storeMenuMapper.getStoreMenuList(storeId, queryDishType, dishMenuType);
+        List<StoreMenuVo> menuList = storeMenuMapper.getStoreMenuInfoList(storeId, queryDishType, dishMenuType);
 
         // 如果是推荐菜且有用户标识,批量查询点赞状态
         if (dishType != null && dishType == 1 && StringUtils.isNotEmpty(phoneId)

+ 65 - 6
alien-store/src/main/java/shop/alien/store/service/impl/StoreStaffConfigServiceImpl.java

@@ -1,6 +1,7 @@
 package shop.alien.store.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@@ -51,18 +52,54 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
         IPage<StoreStaffConfig> storePage = new Page<>(page, size);
         QueryWrapper<StoreStaffConfig> queryWrapper = new QueryWrapper<>();
         queryWrapper.like(null != status && !status.isEmpty(), "status", status);
-        queryWrapper.orderByDesc("created_time");
+        // 排序规则:先按置顶状态降序(置顶的在前),再按置顶时间降序,最后按创建时间降序
+        queryWrapper.orderByDesc("top_status", "top_time", "created_time");
         return storeStaffConfigMapper.selectPage(storePage, queryWrapper);
     }
 
     @Override
     public int addOrUpdateStaffConfig(StoreStaffConfig storeStaffConfig) {
-        if (StringUtils.isEmpty(storeStaffConfig.getId().toString())) {
+        // 判断是新增还是更新:id为null或0或负数表示新增
+        // 注意:新增时不应该传入id,如果传入了非0的id,需要先查询是否存在
+        Integer id = storeStaffConfig.getId();
+        
+        if (id == null || id == 0) {
+            // 新增操作:id为null或0
             Date nowDate = new Date(System.currentTimeMillis());
             storeStaffConfig.setCreatedTime(nowDate);
+            // 设置删除标记为0(未删除)- 必须设置,否则可能插入失败
+            if (storeStaffConfig.getDeleteFlag() == null) {
+                storeStaffConfig.setDeleteFlag(0);
+            }
+            // 如果状态为空,设置默认状态为待审核(0)
+            if (StringUtils.isEmpty(storeStaffConfig.getStatus())) {
+                storeStaffConfig.setStatus("0");
+            }
+            // 新增时,确保id为null,让数据库自动生成
+            storeStaffConfig.setId(null);
             return storeStaffConfigMapper.insert(storeStaffConfig);
         } else {
-            return storeStaffConfigMapper.updateById(storeStaffConfig);
+            // 更新操作:id不为null且不为0
+            // 先查询记录是否存在,如果不存在则转为新增
+            StoreStaffConfig existing = storeStaffConfigMapper.selectById(id);
+            if (existing == null) {
+                // 记录不存在,转为新增操作
+                storeStaffConfig.setId(null); // 重置id,让数据库自动生成
+                Date nowDate = new Date(System.currentTimeMillis());
+                storeStaffConfig.setCreatedTime(nowDate);
+                // 设置删除标记为0(未删除)
+                if (storeStaffConfig.getDeleteFlag() == null) {
+                    storeStaffConfig.setDeleteFlag(0);
+                }
+                // 如果状态为空,设置默认状态为待审核(0)
+                if (StringUtils.isEmpty(storeStaffConfig.getStatus())) {
+                    storeStaffConfig.setStatus("0");
+                }
+                return storeStaffConfigMapper.insert(storeStaffConfig);
+            } else {
+                // 记录存在,执行更新
+                return storeStaffConfigMapper.updateById(storeStaffConfig);
+            }
         }
     }
 
@@ -110,6 +147,28 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
         return aliOSSUtil.uploadFile(new File(filePath), "excel/" + fileName + ".xlsx");
     }
 
+    @Override
+    public Integer deleteStaffConfig(Integer id) {
+        // 使用 MyBatis-Plus 的逻辑删除,会自动将 deleteFlag 设置为 1
+        // 因为实体类使用了 @TableLogic 注解
+        return storeStaffConfigMapper.deleteById(id);
+    }
+
+    @Override
+    public Integer setTopStatus(Integer id, Integer topStatus) {
+        if (id == null || topStatus == null) {
+            return 0;
+        }
+        LambdaUpdateWrapper<StoreStaffConfig> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
+        lambdaUpdateWrapper.eq(StoreStaffConfig::getId, id);
+        lambdaUpdateWrapper.set(StoreStaffConfig::getTopStatus, topStatus);
+        if (topStatus == 0) {
+            lambdaUpdateWrapper.set(StoreStaffConfig::getTopTime, null);
+        } else {
+            lambdaUpdateWrapper.set(StoreStaffConfig::getTopTime, new Date());
+        }
+        return storeStaffConfigMapper.update(null, lambdaUpdateWrapper);
+    }
 
     @Override
     public IPage<StoreStaffConfig> queryStaffList(Integer page, Integer size, Integer storeId, String status) {
@@ -120,9 +179,9 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
             queryWrapper.eq("store_id", storeId);
         }
         // 如果状态不为空,则进行精确匹配查询
-        if (StringUtils.isNotEmpty(status)) {
-            queryWrapper.eq("status", status);
-        }
+//        if (StringUtils.isNotEmpty(status)) {
+//            queryWrapper.eq("status", status);
+//        }
         // 只查询未删除的记录
         queryWrapper.eq("delete_flag", 0);
         queryWrapper.orderByDesc("created_time");

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است