Parcourir la source

商家pc端 分权限 第一笔提交

liudongzhi il y a 3 mois
Parent
commit
b9e611d445
25 fichiers modifiés avec 2019 ajouts et 335 suppressions
  1. 115 0
      alien-entity/src/main/java/shop/alien/entity/store/StorePlatformMenu.java
  2. 82 0
      alien-entity/src/main/java/shop/alien/entity/store/StorePlatformRole.java
  3. 44 0
      alien-entity/src/main/java/shop/alien/entity/store/StorePlatformRoleMenu.java
  4. 44 0
      alien-entity/src/main/java/shop/alien/entity/store/StorePlatformUserRole.java
  5. 19 2
      alien-entity/src/main/java/shop/alien/entity/store/StoreUser.java
  6. 1 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/OrderRevenueVO.java
  7. 45 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/RolePermissionVo.java
  8. 33 0
      alien-entity/src/main/java/shop/alien/entity/store/vo/StorePlatformRoleVo.java
  9. 17 0
      alien-entity/src/main/java/shop/alien/mapper/StorePlatformMenuMapper.java
  10. 17 0
      alien-entity/src/main/java/shop/alien/mapper/StorePlatformRoleMapper.java
  11. 17 0
      alien-entity/src/main/java/shop/alien/mapper/StorePlatformRoleMenuMapper.java
  12. 17 0
      alien-entity/src/main/java/shop/alien/mapper/StorePlatformUserRoleMapper.java
  13. 105 67
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformMenuController.java
  14. 193 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformRoleController.java
  15. 137 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformRoleMenuController.java
  16. 111 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformUserRoleController.java
  17. 46 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/dto/CreateRoleDto.java
  18. 49 36
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/StorePlatformMenuService.java
  19. 75 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/StorePlatformRoleMenuService.java
  20. 112 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/StorePlatformRoleService.java
  21. 58 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/StorePlatformUserRoleService.java
  22. 162 230
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformMenuServiceImpl.java
  23. 191 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformRoleMenuServiceImpl.java
  24. 248 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformRoleServiceImpl.java
  25. 81 0
      alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformUserRoleServiceImpl.java

+ 115 - 0
alien-entity/src/main/java/shop/alien/entity/store/StorePlatformMenu.java

@@ -0,0 +1,115 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 商家PC菜单权限表
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude
+@TableName("store_platform_menu")
+@ApiModel(value = "StorePlatformMenu对象", description = "商家PC菜单权限表")
+public class StorePlatformMenu implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "菜单ID")
+    @TableId(value = "menu_id", type = IdType.AUTO)
+    private Long menuId;
+
+    @ApiModelProperty(value = "菜单名称")
+    @TableField("menu_name")
+    private String menuName;
+
+    @ApiModelProperty(value = "父菜单ID(0表示根菜单)")
+    @TableField("parent_id")
+    private Long parentId;
+
+    @ApiModelProperty(value = "菜单类型(M目录 C菜单 F按钮)")
+    @TableField("menu_type")
+    private String menuType;
+
+    @ApiModelProperty(value = "显示顺序")
+    @TableField("menu_sort")
+    private Integer menuSort;
+
+    @ApiModelProperty(value = "菜单层级(1一级菜单 2二级菜单 3三级菜单)")
+    @TableField("level")
+    private Integer level;
+
+    @ApiModelProperty(value = "路由地址")
+    @TableField("path")
+    private String path;
+
+    @ApiModelProperty(value = "组件路径")
+    @TableField("component")
+    private String component;
+
+    @ApiModelProperty(value = "权限标识(如:sys:user:list)")
+    @TableField("perms")
+    private String perms;
+
+    @ApiModelProperty(value = "菜单图标")
+    @TableField("icon")
+    private String icon;
+
+    @ApiModelProperty(value = "菜单状态(0正常 1停用)")
+    @TableField("status")
+    private String status;
+
+    @ApiModelProperty(value = "是否显示(0显示 1隐藏)")
+    @TableField("visible")
+    private String visible;
+
+    @ApiModelProperty(value = "是否为外链(0是 1否)")
+    @TableField("is_frame")
+    private String isFrame;
+
+    @ApiModelProperty(value = "是否缓存(0缓存 1不缓存)")
+    @TableField("is_cache")
+    private String isCache;
+
+    @ApiModelProperty(value = "删除标志(0存在 2删除)")
+    @TableField("del_flag")
+    @TableLogic(value = "0", delval = "2")
+    private String delFlag;
+
+    @ApiModelProperty(value = "创建者")
+    @TableField("create_by")
+    private String createBy;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "更新者")
+    @TableField("update_by")
+    private String updateBy;
+
+    @ApiModelProperty(value = "更新时间")
+    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "备注")
+    @TableField("remark")
+    private String remark;
+
+    @ApiModelProperty(value = "子菜单列表(用于树形结构)")
+    @TableField(exist = false)
+    private List<StorePlatformMenu> children;
+}
+

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

@@ -0,0 +1,82 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 平台角色信息表
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude
+@TableName("store_platform_role")
+@ApiModel(value = "StorePlatformRole对象", description = "平台角色信息表")
+public class StorePlatformRole implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "角色ID")
+    @TableId(value = "role_id", type = IdType.AUTO)
+    private Long roleId;
+
+    @ApiModelProperty(value = "店铺ID")
+    @TableField("store_id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "角色名称")
+    @TableField("role_name")
+    private String roleName;
+
+    @ApiModelProperty(value = "显示顺序")
+    @TableField("role_sort")
+    private Integer roleSort;
+
+    @ApiModelProperty(value = "角色状态(0正常 1停用)")
+    @TableField("status")
+    private String status;
+
+    @ApiModelProperty(value = "删除标志(0代表存在 2代表删除)")
+    @TableField("del_flag")
+    @TableLogic(value = "0", delval = "2")
+    private String delFlag;
+
+    @ApiModelProperty(value = "创建者")
+    @TableField("create_by")
+    private String createBy;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "更新者")
+    @TableField("update_by")
+    private String updateBy;
+
+    @ApiModelProperty(value = "更新时间")
+    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "备注")
+    @TableField("remark")
+    private String remark;
+
+    @ApiModelProperty(value = "描述")
+    @TableField("description")
+    private String description;
+
+    @ApiModelProperty(value = "英文角色名称")
+    @TableField("role_name_en")
+    private String roleNameEn;
+}
+

+ 44 - 0
alien-entity/src/main/java/shop/alien/entity/store/StorePlatformRoleMenu.java

@@ -0,0 +1,44 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 角色菜单关联表
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude
+@TableName("store_platform_role_menu")
+@ApiModel(value = "StorePlatformRoleMenu对象", description = "角色菜单关联表")
+public class StorePlatformRoleMenu implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "角色ID")
+    @TableField("role_id")
+    private Long roleId;
+
+    @ApiModelProperty(value = "菜单ID")
+    @TableField("menu_id")
+    private Long menuId;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+}
+

+ 44 - 0
alien-entity/src/main/java/shop/alien/entity/store/StorePlatformUserRole.java

@@ -0,0 +1,44 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 用户角色关联表
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude
+@TableName("store_platform_user_role")
+@ApiModel(value = "StorePlatformUserRole对象", description = "用户角色关联表")
+public class StorePlatformUserRole implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Long id;
+
+    @ApiModelProperty(value = "用户ID(关联life_sys.id)")
+    @TableField("user_id")
+    private Integer userId;
+
+    @ApiModelProperty(value = "角色ID(关联store_platform_role.role_id)")
+    @TableField("role_id")
+    private Long roleId;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+}
+

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

@@ -10,6 +10,7 @@ import lombok.Data;
 import shop.alien.util.encryption.EncryptTypeHandler;
 
 import java.util.Date;
+import java.util.List;
 
 /**
  * 二期-门店用户
@@ -31,7 +32,7 @@ public class StoreUser extends Model<StoreUser> {
         this.money = money;
     }
 
-    @ApiModelProperty(value = "主键")
+    @ApiModelProperty(value = "主键(主账号Id)")
     @TableId(value = "id", type = IdType.AUTO)
     private Integer id;
 
@@ -64,7 +65,7 @@ public class StoreUser extends Model<StoreUser> {
     @TableField("money")
     private Integer money;
 
-    @ApiModelProperty(value = "用户状态")
+    @ApiModelProperty(value = "用户状态,0:启用 1:禁用")
     @TableField("status")
     private Integer status;
 
@@ -136,4 +137,20 @@ public class StoreUser extends Model<StoreUser> {
     private String jianjie;
     @TableField(exist = false)
     private String moneyStr;
+    @ApiModelProperty(value = "账号类型,1:主账号,2:子账号")
+    @TableField("account_type")
+    private  Integer accountType;
+    @ApiModelProperty(value = "子账号Id")
+    @TableField("sub_account_id")
+    private Integer subAccountId;
+    @TableField(exist = false)
+    private Integer storeUserParentAccount;
+    @TableField(exist = false)
+    @ApiModelProperty(value = "子账号数量")
+    private Integer childAccountCount;
+    @ApiModelProperty(value = "子账号联系方式列表")
+    @TableField(exist = false)
+    private List<String> childPhoneNumbers;
+
+
 }

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

@@ -46,3 +46,4 @@ public class OrderRevenueVO implements Serializable {
 
 
 
+

+ 45 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/RolePermissionVo.java

@@ -0,0 +1,45 @@
+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 java.util.List;
+
+/**
+ * 角色权限VO(用于展示权限层级结构)
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude
+@ApiModel(value = "RolePermissionVo对象", description = "角色权限VO(用于展示权限层级结构)")
+public class RolePermissionVo {
+
+    @ApiModelProperty(value = "菜单ID")
+    private Long menuId;
+
+    @ApiModelProperty(value = "菜单名称")
+    private String menuName;
+
+    @ApiModelProperty(value = "父菜单ID")
+    private Long parentId;
+
+    @ApiModelProperty(value = "菜单层级(1一级菜单 2二级菜单 3三级菜单)")
+    private Integer level;
+
+    @ApiModelProperty(value = "菜单类型(M目录 C菜单 F按钮)")
+    private String menuType;
+
+    @ApiModelProperty(value = "显示顺序")
+    private Integer menuSort;
+
+    @ApiModelProperty(value = "权限标识")
+    private String perms;
+
+    @ApiModelProperty(value = "子权限列表")
+    private List<RolePermissionVo> children;
+}
+

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

@@ -0,0 +1,33 @@
+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 lombok.EqualsAndHashCode;
+import shop.alien.entity.store.StorePlatformRole;
+
+import java.util.List;
+
+/**
+ * 平台角色信息VO(包含关联统计)
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@JsonInclude
+@ApiModel(value = "StorePlatformRoleVo对象", description = "平台角色信息VO(包含关联统计)")
+public class StorePlatformRoleVo extends StorePlatformRole {
+
+    @ApiModelProperty(value = "关联子账号数量")
+    private Integer subAccountCount;
+
+    @ApiModelProperty(value = "关联权限数量")
+    private Integer permissionCount;
+
+    @ApiModelProperty(value = "权限列表(树形结构)")
+    private List<RolePermissionVo> permissions;
+}
+

+ 17 - 0
alien-entity/src/main/java/shop/alien/mapper/StorePlatformMenuMapper.java

@@ -0,0 +1,17 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.StorePlatformMenu;
+
+/**
+ * 商家PC菜单权限表 Mapper 接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Mapper
+public interface StorePlatformMenuMapper extends BaseMapper<StorePlatformMenu> {
+
+}
+

+ 17 - 0
alien-entity/src/main/java/shop/alien/mapper/StorePlatformRoleMapper.java

@@ -0,0 +1,17 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.StorePlatformRole;
+
+/**
+ * 平台角色信息表 Mapper 接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Mapper
+public interface StorePlatformRoleMapper extends BaseMapper<StorePlatformRole> {
+
+}
+

+ 17 - 0
alien-entity/src/main/java/shop/alien/mapper/StorePlatformRoleMenuMapper.java

@@ -0,0 +1,17 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.StorePlatformRoleMenu;
+
+/**
+ * 角色菜单关联表 Mapper 接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Mapper
+public interface StorePlatformRoleMenuMapper extends BaseMapper<StorePlatformRoleMenu> {
+
+}
+

+ 17 - 0
alien-entity/src/main/java/shop/alien/mapper/StorePlatformUserRoleMapper.java

@@ -0,0 +1,17 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.StorePlatformUserRole;
+
+/**
+ * 用户角色关联表 Mapper 接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Mapper
+public interface StorePlatformUserRoleMapper extends BaseMapper<StorePlatformUserRole> {
+
+}
+

+ 105 - 67
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformMenuController.java

@@ -1,119 +1,157 @@
 package shop.alien.storeplatform.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.StoreMenu;
-import shop.alien.entity.store.vo.StoreMenuVo;
+import shop.alien.entity.store.StorePlatformMenu;
 import shop.alien.storeplatform.service.StorePlatformMenuService;
 
 import java.util.List;
 
 /**
- * 二期-门店菜单Controller
+ * 商家PC菜单权限表 前端控制器
  *
- * @author ssk
- * @since 2024-12-05
+ * @author system
+ * @since 2025-01-XX
  */
 @Slf4j
-@Api(tags = {"商户平台-门店菜单"})
-@ApiSort(4)
+@Api(tags = {"平台-菜单管理"})
+@ApiSort(1)
 @CrossOrigin
 @RestController
-@RequestMapping("/menu")
+@RequestMapping("/platform/menu")
 @RequiredArgsConstructor
 public class StorePlatformMenuController {
 
-    private final StorePlatformMenuService storeMenuService;
+    private final StorePlatformMenuService storePlatformMenuService;
 
-    @ApiOperation("获取门店菜单")
+    @ApiOperation("分页查询菜单列表")
     @ApiOperationSupport(order = 1)
     @ApiImplicitParams({
-            @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 = "Integer", paramType = "query")
+            @ApiImplicitParam(name = "page", value = "页码", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "size", value = "页容", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "menuName", value = "菜单名称(支持模糊查询)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "menuType", value = "菜单类型(M目录 C菜单 F按钮)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "status", value = "菜单状态(0正常 1停用)", dataType = "String", paramType = "query")
     })
-    @GetMapping("/getMenuByStoreId")
-    public R<List<StoreMenuVo>> getMenuByStoreId(Integer storeId, Integer dishType, String phoneId) {
-        log.info("StoreRecommendController.getByStoreId?id={}&dishType={}&phoneId={}", storeId, dishType, phoneId);
-        return R.data(storeMenuService.getStoreMenu(storeId, dishType, phoneId));
+    @GetMapping("/getMenuPage")
+    public R<IPage<StorePlatformMenu>> getMenuPage(
+            @RequestParam(name = "page", defaultValue = "1") int page,
+            @RequestParam(name = "size", defaultValue = "10") int size,
+            @RequestParam(value = "menuName", required = false) String menuName,
+            @RequestParam(value = "menuType", required = false) String menuType,
+            @RequestParam(value = "status", required = false) String status) {
+        log.info("StorePlatformMenuController.getMenuPage?page={}, size={}, menuName={}, menuType={}, status={}", 
+                page, size, menuName, menuType, status);
+        IPage<StorePlatformMenu> menuPage = storePlatformMenuService.getMenuPage(page, size, menuName, menuType, status);
+        return R.data(menuPage);
     }
 
-    @ApiOperation("新增或修改门店菜单")
+    @ApiOperation("根据ID查询菜单详情")
     @ApiOperationSupport(order = 2)
-    @PostMapping("/saveOrUpdate")
-    public R<String> saveOrUpdate(@RequestBody StoreMenuVo storeMenuVo) {
-        log.info("StoreRecommendController.saveOrUpdateMenu?storeMenu={}", storeMenuVo);
-        return storeMenuService.saveOrUpdateMenus(storeMenuVo);
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "menuId", value = "菜单ID", dataType = "Long", paramType = "query", required = true)
+    })
+    @GetMapping("/getMenuById")
+    public R<StorePlatformMenu> getMenuById(@RequestParam("menuId") Long menuId) {
+        log.info("StorePlatformMenuController.getMenuById?menuId={}", menuId);
+        StorePlatformMenu menu = storePlatformMenuService.getMenuById(menuId);
+        if (menu == null) {
+            return R.fail("未找到该菜单信息");
+        }
+        return R.data(menu);
     }
 
-    @ApiOperation(value = "删除门店菜单")
+    @ApiOperation("新增菜单")
     @ApiOperationSupport(order = 3)
-    @GetMapping("/delete")
-    public R<String> delete(@RequestParam(value = "ids") List<Integer> ids, @RequestParam(value = "dishType") int dishType) {
-        log.info("StoreRecommendController.delete?ids={}", ids);
-        return storeMenuService.deleteMenu(ids, dishType);
+    @PostMapping("/saveMenu")
+    public R<String> saveMenu(@RequestBody StorePlatformMenu menu) {
+        log.info("StorePlatformMenuController.saveMenu?menu={}", menu);
+        boolean result = storePlatformMenuService.saveMenu(menu);
+        if (result) {
+            return R.success("新增成功");
+        }
+        return R.fail("新增失败");
     }
 
-    @ApiOperation("获取菜品详情")
+    @ApiOperation("修改菜单")
     @ApiOperationSupport(order = 4)
-    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "菜品id", dataType = "Integer", paramType = "query")})
-    @GetMapping("/getMenuInfo")
-    public R<StoreMenuVo> getMenuInfo(Integer id) {
-        log.info("StoreRecommendController.getMenuInfo?id={}", id);
-        return R.data(storeMenuService.getMenuInfo(id));
+    @PostMapping("/updateMenu")
+    public R<String> updateMenu(@RequestBody StorePlatformMenu menu) {
+        log.info("StorePlatformMenuController.updateMenu?menu={}", menu);
+        boolean result = storePlatformMenuService.updateMenu(menu);
+        if (result) {
+            return R.success("修改成功");
+        }
+        return R.fail("修改失败");
     }
 
-    @ApiOperation("菜品排序")
+    @ApiOperation("删除菜单")
     @ApiOperationSupport(order = 5)
-    @PostMapping("/getSortMenuInfo")
-    public R<Boolean> getSortMenuInfo(@RequestBody StoreMenuVo storeMenuVo) {
-        log.info("StoreRecommendController.getSortMenuInfo?storeMenuVo={}", storeMenuVo);
-        Boolean flag = false;
-        flag = storeMenuService.getSortMenuInfo(storeMenuVo);
-        if (flag) {
-            return R.success("已更新排序");
-        } else {
-            return R.fail("排序失败");
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "menuId", value = "菜单ID", dataType = "Long", paramType = "query", required = true)
+    })
+    @DeleteMapping("/deleteMenu")
+    public R<String> deleteMenu(@RequestParam("menuId") Long menuId) {
+        log.info("StorePlatformMenuController.deleteMenu?menuId={}", menuId);
+        boolean result = storePlatformMenuService.deleteMenu(menuId);
+        if (result) {
+            return R.success("删除成功");
         }
+        return R.fail("删除失败");
     }
 
-    @ApiOperation("保存菜品排序")
+    @ApiOperation("修改菜单状态")
     @ApiOperationSupport(order = 6)
-    @PostMapping("/saveMenuSort")
-    public R<Boolean> saveMenuSort(@RequestBody List<StoreMenu> storeMenuList) {
-        log.info("StoreRecommendController.saveMenuSort?storeMenuList={}", storeMenuList);
-        Boolean flag = false;
-        flag = storeMenuService.saveMenuSort(storeMenuList);
-        if (flag) {
-            return R.success("已更新排序");
-        } else {
-            return R.fail("排序失败");
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "menuId", value = "菜单ID", dataType = "Long", paramType = "query", required = true),
+            @ApiImplicitParam(name = "status", value = "菜单状态(0正常 1停用)", dataType = "String", paramType = "query", required = true)
+    })
+    @PutMapping("/updateStatus")
+    public R<String> updateStatus(
+            @RequestParam("menuId") Long menuId,
+            @RequestParam("status") String status) {
+        log.info("StorePlatformMenuController.updateStatus?menuId={}, status={}", menuId, status);
+        boolean result = storePlatformMenuService.updateStatus(menuId, status);
+        if (result) {
+            return R.success("操作成功");
         }
+        return R.fail("操作失败");
     }
 
-    @ApiOperation("获取门店菜品推荐数量")
+    @ApiOperation("查询所有正常状态的菜单列表(树形结构)")
     @ApiOperationSupport(order = 7)
+    @GetMapping("/getMenuTree")
+    public R<List<StorePlatformMenu>> getMenuTree() {
+        log.info("StorePlatformMenuController.getMenuTree");
+        List<StorePlatformMenu> menus = storePlatformMenuService.getMenuTree();
+        return R.data(menus);
+    }
+
+    @ApiOperation("根据父菜单ID查询子菜单列表")
+    @ApiOperationSupport(order = 8)
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "storeId", value = "门店id", dataType = "Integer", paramType = "query", required = true)
+            @ApiImplicitParam(name = "parentId", value = "父菜单ID", dataType = "Long", paramType = "query", required = true)
     })
-    @GetMapping("/getMenuCountByStoreId")
-    public R<StoreMenuVo> getMenuCountByStoreId(Integer storeId) {
-        log.info("StoreRecommendController.getMenuCountByStoreId?id={}", storeId);
-        return R.data(storeMenuService.getMenuCountByStoreId(storeId));
+    @GetMapping("/getMenusByParentId")
+    public R<List<StorePlatformMenu>> getMenusByParentId(@RequestParam("parentId") Long parentId) {
+        log.info("StorePlatformMenuController.getMenusByParentId?parentId={}", parentId);
+        List<StorePlatformMenu> menus = storePlatformMenuService.getMenusByParentId(parentId);
+        return R.data(menus);
     }
 
-    @ApiOperation("获取用户对该菜品是否点赞")
-    @ApiOperationSupport(order = 8)
+    @ApiOperation("根据层级查询菜单列表")
+    @ApiOperationSupport(order = 9)
     @ApiImplicitParams({
-            @ApiImplicitParam(name = "userId", value = "用户id", dataType = "String", paramType = "query", required = true),
-            @ApiImplicitParam(name = "menuId", value = "菜品id", dataType = "Integer", paramType = "query", required = true)
+            @ApiImplicitParam(name = "level", value = "菜单层级(1一级菜单 2二级菜单 3三级菜单)", dataType = "int", paramType = "query", required = true)
     })
-    @GetMapping("/getMenuLikeStatus")
-    public R<Boolean> getMenuLikeStatus(String userId, Integer menuId) {
-        log.info("StoreRecommendController.getMenuLikeStatus?userId={}&menuId={}", userId, menuId);
-        return R.data(storeMenuService.getMenuLikeStatus(userId, menuId));
+    @GetMapping("/getMenusByLevel")
+    public R<List<StorePlatformMenu>> getMenusByLevel(@RequestParam("level") Integer level) {
+        log.info("StorePlatformMenuController.getMenusByLevel?level={}", level);
+        List<StorePlatformMenu> menus = storePlatformMenuService.getMenusByLevel(level);
+        return R.data(menus);
     }
 }

+ 193 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformRoleController.java

@@ -0,0 +1,193 @@
+package shop.alien.storeplatform.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.StorePlatformRole;
+import shop.alien.entity.store.vo.StorePlatformRoleVo;
+import shop.alien.storeplatform.dto.CreateRoleDto;
+import shop.alien.storeplatform.service.StorePlatformRoleService;
+
+import java.util.List;
+
+/**
+ * 平台角色信息表 前端控制器
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Api(tags = {"平台-角色管理"})
+@ApiSort(1)
+@CrossOrigin
+@RestController
+@RequestMapping("/platform/role")
+@RequiredArgsConstructor
+public class StorePlatformRoleController {
+
+    private final StorePlatformRoleService storePlatformRoleService;
+
+    @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 = "int", paramType = "query", required = false),
+            @ApiImplicitParam(name = "roleName", value = "角色名称(支持模糊查询)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "description", value = "角色描述(支持模糊查询)", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "status", value = "角色状态(0正常 1停用)", dataType = "String", paramType = "query")
+    })
+    @GetMapping("/getRolePage")
+    public R<IPage<StorePlatformRoleVo>> getRolePage(
+            @RequestParam(name = "page", defaultValue = "1") int page,
+            @RequestParam(name = "size", defaultValue = "10") int size,
+            @RequestParam(value = "storeId", required = true) Integer storeId,
+            @RequestParam(value = "roleName", required = false) String roleName,
+            @RequestParam(value = "description", required = false) String description,
+            @RequestParam(value = "status", required = false) String status) {
+        log.info("StorePlatformRoleController.getRolePage?page={}, size={}, storeId={}, roleName={}, description={}, status={}", 
+                page, size, storeId, roleName, description, status);
+        IPage<StorePlatformRoleVo> rolePage = storePlatformRoleService.getRolePageWithStats(page, size, storeId, roleName, description, status);
+        return R.data(rolePage);
+    }
+
+    @ApiOperation("根据ID查询角色详情")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "roleId", value = "角色ID", dataType = "Long", paramType = "query", required = true)
+    })
+    @GetMapping("/getRoleById")
+    public R<StorePlatformRole> getRoleById(@RequestParam("roleId") Long roleId) {
+        log.info("StorePlatformRoleController.getRoleById?roleId={}", roleId);
+        StorePlatformRole role = storePlatformRoleService.getRoleById(roleId);
+        if (role == null) {
+            return R.fail("未找到该角色信息");
+        }
+        return R.data(role);
+    }
+
+    @ApiOperation("新增角色")
+    @ApiOperationSupport(order = 3)
+    @PostMapping("/saveRole")
+    public R<String> saveRole(@RequestBody StorePlatformRole role) {
+        log.info("StorePlatformRoleController.saveRole?role={}", role);
+        // 检查角色名称是否已存在(同一店铺内不能重复)
+        if (storePlatformRoleService.checkRoleNameExists(role.getStoreId(), role.getRoleName(), null)) {
+            return R.fail("已有名称不允许重复添加");
+        }
+        boolean result = storePlatformRoleService.saveRole(role);
+        if (result) {
+            return R.success("新增成功");
+        }
+        return R.fail("新增失败");
+    }
+
+    @ApiOperation("创建角色(包含权限分配)")
+    @ApiOperationSupport(order = 3)
+    @PostMapping("/createRole")
+    public R<String> createRole(@RequestBody CreateRoleDto createRoleDto) {
+        log.info("StorePlatformRoleController.createRole?storeId={}, roleName={}, menuIds={}", 
+                createRoleDto.getStoreId(), createRoleDto.getRoleName(), createRoleDto.getMenuIds());
+        
+        // 检查角色名称是否已存在(同一店铺内不能重复)
+        if (storePlatformRoleService.checkRoleNameExists(createRoleDto.getStoreId(), createRoleDto.getRoleName(), null)) {
+            return R.fail("已有名称不允许重复添加");
+        }
+        
+        // 构建角色对象
+        StorePlatformRole role = new StorePlatformRole();
+        role.setStoreId(createRoleDto.getStoreId());
+        role.setRoleName(createRoleDto.getRoleName());
+        role.setRoleSort(createRoleDto.getRoleSort());
+        role.setStatus(createRoleDto.getStatus());
+        role.setDescription(createRoleDto.getDescription());
+        role.setRoleNameEn(createRoleDto.getRoleNameEn());
+        role.setRemark(createRoleDto.getRemark());
+        
+        // 创建角色并分配权限
+        boolean result = storePlatformRoleService.createRoleWithMenus(role, createRoleDto.getMenuIds());
+        if (result) {
+            return R.success("创建成功");
+        }
+        return R.fail("创建失败");
+    }
+
+    @ApiOperation("修改角色")
+    @ApiOperationSupport(order = 4)
+    @PostMapping("/updateRole")
+    public R<String> updateRole(@RequestBody StorePlatformRole role) {
+        log.info("StorePlatformRoleController.updateRole?role={}", role);
+        boolean result = storePlatformRoleService.updateRole(role);
+        if (result) {
+            return R.success("修改成功");
+        }
+        return R.fail("修改失败");
+    }
+
+    @ApiOperation("删除角色")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "roleId", value = "角色ID", dataType = "Long", paramType = "query", required = true)
+    })
+    @DeleteMapping("/deleteRole")
+    public R<String> deleteRole(@RequestParam("roleId") Long roleId) {
+        log.info("StorePlatformRoleController.deleteRole?roleId={}", roleId);
+        boolean result = storePlatformRoleService.deleteRole(roleId);
+        if (result) {
+            return R.success("删除成功");
+        }
+        return R.fail("删除失败");
+    }
+
+    @ApiOperation("修改角色状态")
+    @ApiOperationSupport(order = 6)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "roleId", value = "角色ID", dataType = "Long", paramType = "query", required = true),
+            @ApiImplicitParam(name = "status", value = "角色状态(0正常 1停用)", dataType = "String", paramType = "query", required = true)
+    })
+    @PutMapping("/updateStatus")
+    public R<String> updateStatus(
+            @RequestParam("roleId") Long roleId,
+            @RequestParam("status") String status) {
+        log.info("StorePlatformRoleController.updateStatus?roleId={}, status={}", roleId, status);
+        boolean result = storePlatformRoleService.updateStatus(roleId, status);
+        if (result) {
+            return R.success("操作成功");
+        }
+        return R.fail("操作失败");
+    }
+
+    @ApiOperation("查询所有正常状态的角色列表")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "店铺ID", dataType = "int", paramType = "query", required = false)
+    })
+    @GetMapping("/getAllNormalRoles")
+    public R<List<StorePlatformRole>> getAllNormalRoles(
+            @RequestParam(value = "storeId", required = false) Integer storeId) {
+        log.info("StorePlatformRoleController.getAllNormalRoles?storeId={}", storeId);
+        List<StorePlatformRole> roles = storePlatformRoleService.getAllNormalRoles(storeId);
+        return R.data(roles);
+    }
+
+    @ApiOperation("检查角色名称是否已存在")
+    @ApiOperationSupport(order = 8)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "店铺ID", dataType = "int", paramType = "query", required = false),
+            @ApiImplicitParam(name = "roleName", value = "角色名称", dataType = "String", paramType = "query", required = true),
+            @ApiImplicitParam(name = "excludeRoleId", value = "排除的角色ID(用于更新时排除自己)", dataType = "Long", paramType = "query", required = false)
+    })
+    @GetMapping("/checkRoleNameExists")
+    public R<Boolean> checkRoleNameExists(
+            @RequestParam(value = "storeId", required = false) Integer storeId,
+            @RequestParam("roleName") String roleName,
+            @RequestParam(value = "excludeRoleId", required = false) Long excludeRoleId) {
+        log.info("StorePlatformRoleController.checkRoleNameExists?storeId={}, roleName={}, excludeRoleId={}", storeId, roleName, excludeRoleId);
+        boolean exists = storePlatformRoleService.checkRoleNameExists(storeId, roleName, excludeRoleId);
+        return R.data(exists);
+    }
+}
+

+ 137 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformRoleMenuController.java

@@ -0,0 +1,137 @@
+package shop.alien.storeplatform.controller;
+
+import io.swagger.annotations.*;
+import lombok.Data;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.storeplatform.service.StorePlatformRoleMenuService;
+
+import java.util.List;
+
+/**
+ * 角色菜单关联表 前端控制器
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Api(tags = {"平台-角色菜单关联管理"})
+@ApiSort(1)
+@CrossOrigin
+@RestController
+@RequestMapping("/platform/role-menu")
+@RequiredArgsConstructor
+public class StorePlatformRoleMenuController {
+
+    private final StorePlatformRoleMenuService storePlatformRoleMenuService;
+
+    @ApiOperation("根据角色ID查询菜单ID列表")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "roleId", value = "角色ID", dataType = "Long", paramType = "query", required = true)
+    })
+    @GetMapping("/getMenuIdsByRoleId")
+    public R<List<Long>> getMenuIdsByRoleId(@RequestParam("roleId") Long roleId) {
+        log.info("StorePlatformRoleMenuController.getMenuIdsByRoleId?roleId={}", roleId);
+        List<Long> menuIds = storePlatformRoleMenuService.getMenuIdsByRoleId(roleId);
+        return R.data(menuIds);
+    }
+
+    @ApiOperation("根据菜单ID查询角色ID列表")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "menuId", value = "菜单ID", dataType = "Long", paramType = "query", required = true)
+    })
+    @GetMapping("/getRoleIdsByMenuId")
+    public R<List<Long>> getRoleIdsByMenuId(@RequestParam("menuId") Long menuId) {
+        log.info("StorePlatformRoleMenuController.getRoleIdsByMenuId?menuId={}", menuId);
+        List<Long> roleIds = storePlatformRoleMenuService.getRoleIdsByMenuId(menuId);
+        return R.data(roleIds);
+    }
+
+    @ApiOperation("为角色分配菜单")
+    @ApiOperationSupport(order = 3)
+    @PostMapping("/assignMenus")
+    public R<String> assignMenus(@RequestBody AssignMenusDto assignMenusDto) {
+        log.info("StorePlatformRoleMenuController.assignMenus?roleId={}, menuIds={}", 
+                assignMenusDto.getRoleId(), assignMenusDto.getMenuIds());
+        boolean result = storePlatformRoleMenuService.assignMenus(assignMenusDto.getRoleId(), assignMenusDto.getMenuIds());
+        if (result) {
+            return R.success("分配成功");
+        }
+        return R.fail("分配失败");
+    }
+
+    @ApiOperation("移除角色的所有菜单")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "roleId", value = "角色ID", dataType = "Long", paramType = "query", required = true)
+    })
+    @DeleteMapping("/removeAllMenus")
+    public R<String> removeAllMenus(@RequestParam("roleId") Long roleId) {
+        log.info("StorePlatformRoleMenuController.removeAllMenus?roleId={}", roleId);
+        boolean result = storePlatformRoleMenuService.removeAllMenus(roleId);
+        if (result) {
+            return R.success("移除成功");
+        }
+        return R.fail("移除失败");
+    }
+
+    @ApiOperation("为角色添加单个菜单")
+    @ApiOperationSupport(order = 5)
+    @PostMapping("/addMenu")
+    public R<String> addMenu(@RequestBody AddMenuDto addMenuDto) {
+        log.info("StorePlatformRoleMenuController.addMenu?roleId={}, menuId={}", 
+                addMenuDto.getRoleId(), addMenuDto.getMenuId());
+        boolean result = storePlatformRoleMenuService.addMenu(addMenuDto.getRoleId(), addMenuDto.getMenuId());
+        if (result) {
+            return R.success("添加成功");
+        }
+        return R.fail("添加失败");
+    }
+
+    @ApiOperation("移除角色的单个菜单")
+    @ApiOperationSupport(order = 6)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "roleId", value = "角色ID", dataType = "Long", paramType = "query", required = true),
+            @ApiImplicitParam(name = "menuId", value = "菜单ID", dataType = "Long", paramType = "query", required = true)
+    })
+    @DeleteMapping("/removeMenu")
+    public R<String> removeMenu(@RequestParam("roleId") Long roleId, @RequestParam("menuId") Long menuId) {
+        log.info("StorePlatformRoleMenuController.removeMenu?roleId={}, menuId={}", roleId, menuId);
+        boolean result = storePlatformRoleMenuService.removeMenu(roleId, menuId);
+        if (result) {
+            return R.success("移除成功");
+        }
+        return R.fail("移除失败");
+    }
+
+    /**
+     * 分配菜单请求DTO
+     */
+    @Data
+    @ApiModel(value = "AssignMenusDto", description = "分配菜单请求参数")
+    static class AssignMenusDto {
+        @ApiModelProperty(value = "角色ID", required = true)
+        private Long roleId;
+
+        @ApiModelProperty(value = "菜单ID列表", required = true)
+        private List<Long> menuIds;
+    }
+
+    /**
+     * 添加菜单请求DTO
+     */
+    @Data
+    @ApiModel(value = "AddMenuDto", description = "添加菜单请求参数")
+    static class AddMenuDto {
+        @ApiModelProperty(value = "角色ID", required = true)
+        private Long roleId;
+
+        @ApiModelProperty(value = "菜单ID", required = true)
+        private Long menuId;
+    }
+}
+

+ 111 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/controller/StorePlatformUserRoleController.java

@@ -0,0 +1,111 @@
+package shop.alien.storeplatform.controller;
+
+import io.swagger.annotations.*;
+import lombok.Data;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.storeplatform.service.StorePlatformUserRoleService;
+
+import java.util.List;
+
+/**
+ * 用户角色关联表 前端控制器
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Api(tags = {"平台-用户角色关联管理"})
+@ApiSort(1)
+@CrossOrigin
+@RestController
+@RequestMapping("/platform/user-role")
+@RequiredArgsConstructor
+public class StorePlatformUserRoleController {
+
+    private final StorePlatformUserRoleService storePlatformUserRoleService;
+
+    @ApiOperation("根据用户ID查询角色ID列表")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "userId", value = "用户ID", dataType = "int", paramType = "query", required = true)
+    })
+    @GetMapping("/getRoleIdsByUserId")
+    public R<List<Long>> getRoleIdsByUserId(@RequestParam("userId") Integer userId) {
+        log.info("StorePlatformUserRoleController.getRoleIdsByUserId?userId={}", userId);
+        List<Long> roleIds = storePlatformUserRoleService.getRoleIdsByUserId(userId);
+        return R.data(roleIds);
+    }
+
+    @ApiOperation("根据角色ID查询用户ID列表")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "roleId", value = "角色ID", dataType = "Long", paramType = "query", required = true)
+    })
+    @GetMapping("/getUserIdsByRoleId")
+    public R<List<Integer>> getUserIdsByRoleId(@RequestParam("roleId") Long roleId) {
+        log.info("StorePlatformUserRoleController.getUserIdsByRoleId?roleId={}", roleId);
+        List<Integer> userIds = storePlatformUserRoleService.getUserIdsByRoleId(roleId);
+        return R.data(userIds);
+    }
+
+    @ApiOperation("为用户分配角色")
+    @ApiOperationSupport(order = 3)
+    @PostMapping("/assignRoles")
+    public R<String> assignRoles(@RequestBody AssignRolesDto assignRolesDto) {
+        log.info("StorePlatformUserRoleController.assignRoles?userId={}, roleIds={}", 
+                assignRolesDto.getUserId(), assignRolesDto.getRoleIds());
+        boolean result = storePlatformUserRoleService.assignRoles(assignRolesDto.getUserId(), assignRolesDto.getRoleIds());
+        if (result) {
+            return R.success("分配成功");
+        }
+        return R.fail("分配失败");
+    }
+
+    @ApiOperation("移除用户的所有角色")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "userId", value = "用户ID", dataType = "int", paramType = "query", required = true)
+    })
+    @DeleteMapping("/removeAllRoles")
+    public R<String> removeAllRoles(@RequestParam("userId") Integer userId) {
+        log.info("StorePlatformUserRoleController.removeAllRoles?userId={}", userId);
+        boolean result = storePlatformUserRoleService.removeAllRoles(userId);
+        if (result) {
+            return R.success("移除成功");
+        }
+        return R.fail("移除失败");
+    }
+
+    @ApiOperation("移除用户的指定角色")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "userId", value = "用户ID", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "roleId", value = "角色ID", dataType = "Long", paramType = "query", required = true)
+    })
+    @DeleteMapping("/removeRole")
+    public R<String> removeRole(@RequestParam("userId") Integer userId, @RequestParam("roleId") Long roleId) {
+        log.info("StorePlatformUserRoleController.removeRole?userId={}, roleId={}", userId, roleId);
+        boolean result = storePlatformUserRoleService.removeRole(userId, roleId);
+        if (result) {
+            return R.success("移除成功");
+        }
+        return R.fail("移除失败");
+    }
+
+    /**
+     * 分配角色请求DTO
+     */
+    @Data
+    @ApiModel(value = "AssignRolesDto", description = "分配角色请求参数")
+    static class AssignRolesDto {
+        @ApiModelProperty(value = "用户ID", required = true)
+        private Integer userId;
+
+        @ApiModelProperty(value = "角色ID列表", required = true)
+        private List<Long> roleIds;
+    }
+}
+

+ 46 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/dto/CreateRoleDto.java

@@ -0,0 +1,46 @@
+package shop.alien.storeplatform.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 创建角色请求DTO
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@ApiModel(value = "CreateRoleDto", description = "创建角色请求参数")
+public class CreateRoleDto {
+
+    @ApiModelProperty(value = "店铺ID", required = true)
+    private Integer storeId;
+
+    @ApiModelProperty(value = "角色名称", required = true)
+    private String roleName;
+
+    @ApiModelProperty(value = "角色类型")
+    private String roleType;
+
+    @ApiModelProperty(value = "显示顺序")
+    private Integer roleSort;
+
+    @ApiModelProperty(value = "角色状态(0正常 1停用)")
+    private String status;
+
+    @ApiModelProperty(value = "角色描述")
+    private String description;
+
+    @ApiModelProperty(value = "英文角色名称")
+    private String roleNameEn;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @ApiModelProperty(value = "菜单权限ID列表(子账号权限)", required = true)
+    private List<Long> menuIds;
+}
+

+ 49 - 36
alien-store-platform/src/main/java/shop/alien/storeplatform/service/StorePlatformMenuService.java

@@ -1,79 +1,92 @@
 package shop.alien.storeplatform.service;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
-import shop.alien.entity.result.R;
-import shop.alien.entity.store.StoreMenu;
-import shop.alien.entity.store.vo.StoreMenuVo;
+import shop.alien.entity.store.StorePlatformMenu;
 
 import java.util.List;
 
 /**
- * 二期-门店推荐 服务类
+ * 商家PC菜单权限表 服务类
  *
- * @author ssk
- * @since 2024-12-05
+ * @author system
+ * @since 2025-01-XX
  */
-public interface StorePlatformMenuService extends IService<StoreMenu> {
+public interface StorePlatformMenuService extends IService<StorePlatformMenu> {
 
     /**
-     * 获取门店菜单
+     * 分页查询菜单列表
      *
-     * @param storeId  门店id
-     * @param dishType 菜品类型, 0:菜单, 1:推荐
-     * @param phoneId  消息标识
-     * @return list
+     * @param page     页码
+     * @param size     页容
+     * @param menuName 菜单名称(支持模糊查询)
+     * @param menuType 菜单类型(M目录 C菜单 F按钮)
+     * @param status   菜单状态(0正常 1停用)
+     * @return IPage<StorePlatformMenu>
      */
-    List<StoreMenuVo> getStoreMenu(Integer storeId, Integer dishType, String phoneId);
+    IPage<StorePlatformMenu> getMenuPage(int page, int size, String menuName, String menuType, String status);
 
     /**
-     * 获取菜品详情
+     * 根据ID查询菜单详情
      *
-     * @param id 菜品id
-     * @return StoreMenuVo
+     * @param menuId 菜单ID
+     * @return StorePlatformMenu
      */
-    StoreMenuVo getMenuInfo(Integer id);
+    StorePlatformMenu getMenuById(Long menuId);
 
     /**
-     * 新增或修改门店菜单
+     * 新增菜单
      *
+     * @param menu 菜单信息
+     * @return 是否成功
      */
-    R<String> saveOrUpdateMenu(StoreMenu storeMenu);
+    boolean saveMenu(StorePlatformMenu menu);
 
     /**
-     * 新增或修改门店菜单
+     * 修改菜单
      *
+     * @param menu 菜单信息
+     * @return 是否成功
      */
-    R<String> saveOrUpdateMenus(StoreMenuVo storeMenuVo);
+    boolean updateMenu(StorePlatformMenu menu);
 
     /**
+     * 删除菜单(逻辑删除)
      *
-     * 菜品排序
+     * @param menuId 菜单ID
+     * @return 是否成功
      */
-    Boolean getSortMenuInfo(StoreMenuVo storeMenuVo);
+    boolean deleteMenu(Long menuId);
 
     /**
+     * 修改菜单状态
      *
-     * 保存菜品排序
+     * @param menuId 菜单ID
+     * @param status 菜单状态(0正常 1停用)
+     * @return 是否成功
      */
-    Boolean saveMenuSort(List<StoreMenu> storeMenuList);
+    boolean updateStatus(Long menuId, String status);
 
     /**
+     * 查询所有正常状态的菜单列表(树形结构)
      *
-     * 删除门店菜单
+     * @return List<StorePlatformMenu>
      */
-    R deleteMenu(List<Integer> ids, int dishType);
+    List<StorePlatformMenu> getMenuTree();
 
-
-
-    StoreMenuVo getMenuCountByStoreId(int storeId);
+    /**
+     * 根据父菜单ID查询子菜单列表
+     *
+     * @param parentId 父菜单ID
+     * @return List<StorePlatformMenu>
+     */
+    List<StorePlatformMenu> getMenusByParentId(Long parentId);
 
     /**
-     * 获取用户对该菜品是否点赞
+     * 根据层级查询菜单列表
      *
-     * @param userId  用户id
-     * @param menuId 菜品id
-     * @return boolean
+     * @param level 菜单层级(1一级菜单 2二级菜单 3三级菜单)
+     * @return List<StorePlatformMenu>
      */
-    boolean getMenuLikeStatus(String userId, Integer menuId);
+    List<StorePlatformMenu> getMenusByLevel(Integer level);
 }
-

+ 75 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/StorePlatformRoleMenuService.java

@@ -0,0 +1,75 @@
+package shop.alien.storeplatform.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.store.StorePlatformRoleMenu;
+
+import java.util.List;
+
+/**
+ * 角色菜单关联表 服务类
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+public interface StorePlatformRoleMenuService extends IService<StorePlatformRoleMenu> {
+
+    /**
+     * 根据角色ID查询菜单ID列表
+     *
+     * @param roleId 角色ID
+     * @return 菜单ID列表
+     */
+    List<Long> getMenuIdsByRoleId(Long roleId);
+
+    /**
+     * 根据菜单ID查询角色ID列表
+     *
+     * @param menuId 菜单ID
+     * @return 角色ID列表
+     */
+    List<Long> getRoleIdsByMenuId(Long menuId);
+
+    /**
+     * 为角色分配菜单
+     *
+     * @param roleId  角色ID
+     * @param menuIds 菜单ID列表
+     * @return 是否成功
+     */
+    boolean assignMenus(Long roleId, List<Long> menuIds);
+
+    /**
+     * 移除角色的所有菜单
+     *
+     * @param roleId 角色ID
+     * @return 是否成功
+     */
+    boolean removeAllMenus(Long roleId);
+
+    /**
+     * 为角色添加单个菜单
+     *
+     * @param roleId 角色ID
+     * @param menuId 菜单ID
+     * @return 是否成功
+     */
+    boolean addMenu(Long roleId, Long menuId);
+
+    /**
+     * 移除角色的单个菜单
+     *
+     * @param roleId 角色ID
+     * @param menuId 菜单ID
+     * @return 是否成功
+     */
+    boolean removeMenu(Long roleId, Long menuId);
+
+    /**
+     * 根据角色ID获取权限树形结构
+     *
+     * @param roleId 角色ID
+     * @return 权限树形结构列表
+     */
+    List<shop.alien.entity.store.vo.RolePermissionVo> getRolePermissionTree(Long roleId);
+}
+

+ 112 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/StorePlatformRoleService.java

@@ -0,0 +1,112 @@
+package shop.alien.storeplatform.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.store.StorePlatformRole;
+import shop.alien.entity.store.vo.StorePlatformRoleVo;
+
+import java.util.List;
+
+/**
+ * 平台角色信息表 服务类
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+public interface StorePlatformRoleService extends IService<StorePlatformRole> {
+
+    /**
+     * 分页查询角色列表
+     *
+     * @param page     页码
+     * @param size     页容
+     * @param storeId  店铺ID
+     * @param roleName 角色名称(支持模糊查询)
+     * @param description 角色描述(支持模糊查询)
+     * @param status   角色状态(0正常 1停用)
+     * @return IPage<StorePlatformRole>
+     */
+    IPage<StorePlatformRole> getRolePage(int page, int size, Integer storeId, String roleName, String description, String status);
+
+    /**
+     * 分页查询角色列表(包含关联统计)
+     *
+     * @param page     页码
+     * @param size     页容
+     * @param storeId  店铺ID
+     * @param roleName 角色名称(支持模糊查询)
+     * @param description 角色描述(支持模糊查询)
+     * @param status   角色状态(0正常 1停用)
+     * @return IPage<StorePlatformRoleVo>
+     */
+    IPage<StorePlatformRoleVo> getRolePageWithStats(int page, int size, Integer storeId, String roleName, String description, String status);
+
+    /**
+     * 根据ID查询角色详情
+     *
+     * @param roleId 角色ID
+     * @return StorePlatformRole
+     */
+    StorePlatformRole getRoleById(Long roleId);
+
+    /**
+     * 新增角色
+     *
+     * @param role 角色信息
+     * @return 是否成功
+     */
+    boolean saveRole(StorePlatformRole role);
+
+    /**
+     * 创建角色(包含权限分配)
+     *
+     * @param role 角色信息
+     * @param menuIds 菜单权限ID列表
+     * @return 是否成功
+     */
+    boolean createRoleWithMenus(StorePlatformRole role, List<Long> menuIds);
+
+    /**
+     * 检查角色名称是否已存在
+     *
+     * @param storeId 店铺ID
+     * @param roleName 角色名称
+     * @param excludeRoleId 排除的角色ID(用于更新时排除自己)
+     * @return 是否存在
+     */
+    boolean checkRoleNameExists(Integer storeId, String roleName, Long excludeRoleId);
+
+    /**
+     * 修改角色
+     *
+     * @param role 角色信息
+     * @return 是否成功
+     */
+    boolean updateRole(StorePlatformRole role);
+
+    /**
+     * 删除角色(逻辑删除)
+     *
+     * @param roleId 角色ID
+     * @return 是否成功
+     */
+    boolean deleteRole(Long roleId);
+
+    /**
+     * 修改角色状态
+     *
+     * @param roleId 角色ID
+     * @param status 角色状态(0正常 1停用)
+     * @return 是否成功
+     */
+    boolean updateStatus(Long roleId, String status);
+
+    /**
+     * 查询所有正常状态的角色列表
+     *
+     * @param storeId 店铺ID
+     * @return List<StorePlatformRole>
+     */
+    List<StorePlatformRole> getAllNormalRoles(Integer storeId);
+}
+

+ 58 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/StorePlatformUserRoleService.java

@@ -0,0 +1,58 @@
+package shop.alien.storeplatform.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.store.StorePlatformUserRole;
+
+import java.util.List;
+
+/**
+ * 用户角色关联表 服务类
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+public interface StorePlatformUserRoleService extends IService<StorePlatformUserRole> {
+
+    /**
+     * 根据用户ID查询角色ID列表
+     *
+     * @param userId 用户ID
+     * @return 角色ID列表
+     */
+    List<Long> getRoleIdsByUserId(Integer userId);
+
+    /**
+     * 根据角色ID查询用户ID列表
+     *
+     * @param roleId 角色ID
+     * @return 用户ID列表
+     */
+    List<Integer> getUserIdsByRoleId(Long roleId);
+
+    /**
+     * 为用户分配角色
+     *
+     * @param userId  用户ID
+     * @param roleIds 角色ID列表
+     * @return 是否成功
+     */
+    boolean assignRoles(Integer userId, List<Long> roleIds);
+
+    /**
+     * 移除用户的所有角色
+     *
+     * @param userId 用户ID
+     * @return 是否成功
+     */
+    boolean removeAllRoles(Integer userId);
+
+    /**
+     * 移除用户的指定角色
+     *
+     * @param userId 用户ID
+     * @param roleId 角色ID
+     * @return 是否成功
+     */
+    boolean removeRole(Integer userId, Long roleId);
+}
+

+ 162 - 230
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformMenuServiceImpl.java

@@ -1,284 +1,216 @@
 package shop.alien.storeplatform.service.impl;
 
-import cn.hutool.core.collection.CollectionUtil;
-import com.alibaba.nacos.common.utils.CollectionUtils;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+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 org.springframework.beans.BeanUtils;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
-import shop.alien.entity.result.R;
-import shop.alien.entity.store.LifeGroupBuyThali;
-import shop.alien.entity.store.LifeLikeRecord;
-import shop.alien.entity.store.StoreImg;
-import shop.alien.entity.store.StoreMenu;
-import shop.alien.entity.store.vo.StoreMenuVo;
-import shop.alien.mapper.LifeGroupBuyThaliMapper;
-import shop.alien.mapper.LifeLikeRecordMapper;
-import shop.alien.mapper.StoreMenuMapper;
-import shop.alien.storeplatform.service.StorePlatformImgService;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import shop.alien.entity.store.StorePlatformMenu;
+import shop.alien.mapper.StorePlatformMenuMapper;
 import shop.alien.storeplatform.service.StorePlatformMenuService;
 
-import java.util.Comparator;
 import java.util.List;
-import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
- * 二期-门店推荐 服务实现类
+ * 商家PC菜单权限表 服务实现类
  *
- * @author ssk
- * @since 2024-12-05
+ * @author system
+ * @since 2025-01-XX
  */
+@Slf4j
 @Service
 @RequiredArgsConstructor
-public class StorePlatformMenuServiceImpl extends ServiceImpl<StoreMenuMapper, StoreMenu> implements StorePlatformMenuService {
+@Transactional
+public class StorePlatformMenuServiceImpl extends ServiceImpl<StorePlatformMenuMapper, StorePlatformMenu> implements StorePlatformMenuService {
 
-    private final StoreMenuMapper storeMenuMapper;
+    private final StorePlatformMenuMapper storePlatformMenuMapper;
 
-    private final LifeLikeRecordMapper lifeLikeRecordMapper;
-
-    private final StorePlatformImgService storeImgService;
-
-    private final LifeGroupBuyThaliMapper lifeGroupBuyThaliMapper;
-
-
-    /**
-     * 获取门店菜单
-     *
-     * @param storeId  门店id
-     * @param dishType 菜品类型, 0:菜单, 1:推荐
-     * @param phoneId  消息标识
-     * @return list
-     */
     @Override
-    public List<StoreMenuVo> getStoreMenu(Integer storeId, Integer dishType, String phoneId) {
-
-        if (dishType == 0) {
-            List<StoreMenuVo> collect = storeMenuMapper.getStoreMenuList(storeId, null);
-            return collect.stream().sorted(Comparator.comparing(StoreMenuVo::getSort)).collect(Collectors.toList());
-        } else {
-            List<StoreMenuVo> collect = storeMenuMapper.getStoreMenuList(storeId, dishType);
-            collect.forEach(item -> {
-                if (StringUtils.isNotEmpty(phoneId)) {
-                    LambdaQueryWrapper<LifeLikeRecord> query = new LambdaQueryWrapper<>();
-                    query.eq(LifeLikeRecord::getDianzanId, phoneId).eq(LifeLikeRecord::getHuifuId, item.getId());
-                    Integer i = lifeLikeRecordMapper.selectCount(query);
-                    if (i > 0) {
-                        item.setIsLike(1);
-                    } else {
-                        item.setIsLike(0);
-                    }
-                }
-            });
-            return collect.stream().sorted(Comparator.comparing(StoreMenuVo::getSort)).collect(Collectors.toList());
+    public IPage<StorePlatformMenu> getMenuPage(int page, int size, String menuName, String menuType, String status) {
+        LambdaQueryWrapper<StorePlatformMenu> queryWrapper = new LambdaQueryWrapper<>();
+        
+        // 菜单名称模糊查询
+        if (StringUtils.hasText(menuName)) {
+            queryWrapper.like(StorePlatformMenu::getMenuName, menuName);
+        }
+        // 菜单类型查询
+        if (StringUtils.hasText(menuType)) {
+            queryWrapper.eq(StorePlatformMenu::getMenuType, menuType);
+        }
+        // 菜单状态查询
+        if (StringUtils.hasText(status)) {
+            queryWrapper.eq(StorePlatformMenu::getStatus, status);
         }
+        
+        // 按显示顺序和创建时间排序
+        queryWrapper.orderByAsc(StorePlatformMenu::getMenuSort);
+        queryWrapper.orderByDesc(StorePlatformMenu::getCreatedTime);
+
+        return storePlatformMenuMapper.selectPage(new Page<>(page, size), queryWrapper);
     }
 
-    /**
-     * 获取菜品详情
-     *
-     * @param id 菜品id
-     * @return StoreMenuVo
-     */
     @Override
-    public StoreMenuVo getMenuInfo(Integer id) {
-        return storeMenuMapper.getMenuInfo(id);
+    public StorePlatformMenu getMenuById(Long menuId) {
+        return storePlatformMenuMapper.selectById(menuId);
     }
 
-    /**
-     * 新增或修改门店菜品
-     *
-     * @param storeMenu
-     * @return
-     */
     @Override
-    public R<String> saveOrUpdateMenu(StoreMenu storeMenu) {
-        boolean flag = false;
-        LambdaQueryWrapper<StoreMenu> storeMenuLambdaQueryWrapper = new LambdaQueryWrapper<>();
-        //修改菜品
-        if (storeMenu.getId() != null) {
-            flag = this.updateById(storeMenu);
-            if (!flag) {
-                log.error("菜单修改失败");
-                return R.fail("菜单修改失败");
-            }
-            return R.success("菜单修改成功");
-        } else {//新增菜品
-            if (StringUtils.isEmpty(storeMenu.getDishName())) {
-                return R.fail("请输入菜品名称");
-            }
-            storeMenuLambdaQueryWrapper.eq(StoreMenu::getStoreId, storeMenu.getStoreId());
-            List<StoreMenu> menuList = this.list(storeMenuLambdaQueryWrapper);
-            if (CollectionUtil.isNotEmpty(menuList)) {
-                int maxSort = menuList.stream().map(StoreMenu::getSort).reduce(Integer::max).get();
-                storeMenu.setSort(maxSort + 1);
-            } else {
-                storeMenu.setSort(1);
-            }
-            //保存菜品
-            flag = this.save(storeMenu);
-            if (!flag) {
-                return R.fail("菜品新增失败");
-            }
+    public boolean saveMenu(StorePlatformMenu menu) {
+        // 校验必填字段
+        if (!StringUtils.hasText(menu.getMenuName())) {
+            log.error("菜单名称不能为空");
+            return false;
+        }
+        if (!StringUtils.hasText(menu.getMenuType())) {
+            log.error("菜单类型不能为空");
+            return false;
+        }
+        // 设置默认值
+        if (menu.getMenuSort() == null) {
+            menu.setMenuSort(0);
+        }
+        if (menu.getParentId() == null) {
+            menu.setParentId(0L);
+        }
+        // 自动计算菜单层级
+        if (menu.getLevel() == null) {
+            menu.setLevel(calculateMenuLevel(menu.getParentId()));
+        }
+        if (!StringUtils.hasText(menu.getStatus())) {
+            menu.setStatus("0"); // 默认正常
+        }
+        if (!StringUtils.hasText(menu.getDelFlag())) {
+            menu.setDelFlag("0"); // 默认未删除
+        }
+        if (!StringUtils.hasText(menu.getVisible())) {
+            menu.setVisible("0"); // 默认显示
+        }
+        if (!StringUtils.hasText(menu.getIsFrame())) {
+            menu.setIsFrame("1"); // 默认非外链
+        }
+        if (!StringUtils.hasText(menu.getIsCache())) {
+            menu.setIsCache("0"); // 默认缓存
         }
-        return R.success("新增菜品成功");
+        int result = storePlatformMenuMapper.insert(menu);
+        return result > 0;
     }
 
-    /**
-     * 新增或修改门店菜品new
-     *
-     * @param storeMenuVo
-     * @return
-     */
     @Override
-    public R<String> saveOrUpdateMenus(StoreMenuVo storeMenuVo) {
-        boolean flag = false;
-        LambdaQueryWrapper<StoreMenu> storeMenuLambdaQueryWrapper = new LambdaQueryWrapper<>();
-        int imgId = 0;
-        if (storeMenuVo.getImgId() == null || storeMenuVo.getImgId() == 0) {
-            StoreImg storeImg = new StoreImg();
-            storeImg.setStoreId(storeMenuVo.getStoreId());
-            storeImg.setImgType(7);
-            storeImg.setImgUrl(storeMenuVo.getImgUrl());
-            storeImg.setImgDescription(storeMenuVo.getDishName());
-            storeImgService.saveOrUpdate(storeImg);
-            imgId = storeImg.getId();
-        } else {
-            imgId = storeMenuVo.getImgId();
+    public boolean updateMenu(StorePlatformMenu menu) {
+        if (menu.getMenuId() == null) {
+            log.error("菜单ID不能为空");
+            return false;
         }
 
-        // 封装storeMenu参数
-        StoreMenu storeMenu = new StoreMenu();
-        BeanUtils.copyProperties(storeMenuVo, storeMenu);
-        storeMenu.setImgId(imgId);
+        int result = storePlatformMenuMapper.updateById(menu);
+        return result > 0;
+    }
 
-        //修改菜品
-        if (storeMenu.getId() != null) {
-            flag = this.updateById(storeMenu);
-            if (!flag) {
-                log.error("菜单修改失败");
-                return R.fail("菜单修改失败");
-            }
-            return R.success("菜单修改成功");
-        } else {
-            //新增菜品
-            // 校验菜品参数
-            if (StringUtils.isEmpty(storeMenu.getDishName())) {
-                return R.fail("请输入菜品名称");
-            }
+    @Override
+    public boolean deleteMenu(Long menuId) {
+        // 逻辑删除
+        LambdaUpdateWrapper<StorePlatformMenu> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(StorePlatformMenu::getMenuId, menuId);
+        updateWrapper.set(StorePlatformMenu::getDelFlag, "2"); // 2代表删除
+        
+        int result = storePlatformMenuMapper.update(null, updateWrapper);
+        return result > 0;
+    }
 
-            storeMenuLambdaQueryWrapper.eq(StoreMenu::getStoreId, storeMenu.getStoreId());
-            List<StoreMenu> menuList = this.list(storeMenuLambdaQueryWrapper);
-            if (CollectionUtil.isNotEmpty(menuList)) {
-                int maxSort = menuList.stream().map(StoreMenu::getSort).reduce(Integer::max).get();
-                storeMenu.setSort(maxSort + 1);
-            } else {
-                storeMenu.setSort(1);
-            }
-            //保存菜品
-            flag = this.save(storeMenu);
-            if (!flag) {
-                return R.fail("菜品新增失败");
-            }
+    @Override
+    public boolean updateStatus(Long menuId, String status) {
+        if (menuId == null) {
+            log.error("菜单ID不能为空");
+            return false;
         }
-        return R.success("新增菜品成功");
+        if (!StringUtils.hasText(status)) {
+            log.error("菜单状态不能为空");
+            return false;
+        }
+        
+        LambdaUpdateWrapper<StorePlatformMenu> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(StorePlatformMenu::getMenuId, menuId);
+        updateWrapper.set(StorePlatformMenu::getStatus, status);
+        
+        int result = storePlatformMenuMapper.update(null, updateWrapper);
+        return result > 0;
     }
 
+    @Override
+    public List<StorePlatformMenu> getMenuTree() {
+        // 查询所有未删除的菜单
+        LambdaQueryWrapper<StorePlatformMenu> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformMenu::getDelFlag, "0");
+        queryWrapper.eq(StorePlatformMenu::getStatus, "0"); // 正常状态
+        queryWrapper.orderByAsc(StorePlatformMenu::getMenuSort);
+        List<StorePlatformMenu> allMenus = storePlatformMenuMapper.selectList(queryWrapper);
+        
+
+        return buildMenuTree(allMenus, 0L);
+    }
 
-    /**
-     * 菜品排序信息
-     *
-     * @param storeMenuVo
-     * @return
-     */
     @Override
-    public Boolean getSortMenuInfo(StoreMenuVo storeMenuVo) {
-        boolean flag = false;
-        if (CollectionUtil.isNotEmpty(storeMenuVo.getSortList())) {
-            for (int i = 0; i < storeMenuVo.getSortList().size(); i++) {
-                LambdaQueryWrapper<StoreMenu> lambdaQueryWrapper = new LambdaQueryWrapper();
-                lambdaQueryWrapper.eq(StoreMenu::getId, storeMenuVo.getSortList().get(i).getId());
-                StoreMenu storeMenu = this.getOne(lambdaQueryWrapper);
-                storeMenu.setSort(i + 1);
-                flag = this.updateById(storeMenu);
-            }
-        }
-        return flag;
+    public List<StorePlatformMenu> getMenusByParentId(Long parentId) {
+        LambdaQueryWrapper<StorePlatformMenu> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformMenu::getParentId, parentId);
+        queryWrapper.eq(StorePlatformMenu::getDelFlag, "0");
+        queryWrapper.eq(StorePlatformMenu::getStatus, "0");
+        queryWrapper.orderByAsc(StorePlatformMenu::getMenuSort);
+        
+        return storePlatformMenuMapper.selectList(queryWrapper);
     }
 
     @Override
-    public Boolean saveMenuSort(List<StoreMenu> storeMenuList) {
-        return this.updateBatchById(storeMenuList);
+    public List<StorePlatformMenu> getMenusByLevel(Integer level) {
+        LambdaQueryWrapper<StorePlatformMenu> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformMenu::getLevel, level);
+        queryWrapper.eq(StorePlatformMenu::getDelFlag, "0");
+        queryWrapper.eq(StorePlatformMenu::getStatus, "0");
+        queryWrapper.orderByAsc(StorePlatformMenu::getMenuSort);
+        
+        return storePlatformMenuMapper.selectList(queryWrapper);
     }
 
     /**
-     * 删除菜品或推荐菜 根据类型区分
-     *
-     * @param ids
-     * @param dishType 0:菜品 1:推荐菜
-     * @return
+     * 构建菜单树
      */
-    @Override
-    public R deleteMenu(List<Integer> ids, int dishType) {
-        QueryWrapper<StoreMenu> queryWrapperMenu = new QueryWrapper<>();
-        boolean flag = false;
-        if (dishType == 0) {
-            List<LifeGroupBuyThali> lifeGroupBuyThaliList = lifeGroupBuyThaliMapper.selectList(new LambdaQueryWrapper<LifeGroupBuyThali>().in(LifeGroupBuyThali::getDetailId, ids));
-            if (CollectionUtil.isNotEmpty(lifeGroupBuyThaliList)) {
-                return R.fail("该菜品已被团购套餐引用,不能删除");
-            }
-            flag = this.removeByIds(ids);
-        } else {
-            queryWrapperMenu.in("id", ids);
-            List<StoreMenu> storeMenuList = baseMapper.selectList(queryWrapperMenu);
-            storeMenuList.forEach(item -> {
-                item.setDishType(0);
-                this.updateById(item);
-            });
-            flag = true;
-        }
-        if (!flag) {
-            return R.fail("删除失败");
-        }
-        return R.success("删除成功");
-    }
-    @Override
-    public StoreMenuVo getMenuCountByStoreId(int storeId) {
-        StoreMenuVo storeMenuVo = new StoreMenuVo();
-        LambdaUpdateWrapper<StoreMenu> updateWrapper = new LambdaUpdateWrapper<>();
-        updateWrapper.eq(StoreMenu::getStoreId, storeId);
-        updateWrapper.eq(StoreMenu::getDeleteFlag, 0);
-        List<StoreMenu> storeMenuList = storeMenuMapper.selectList(updateWrapper);
-        if (CollectionUtils.isNotEmpty(storeMenuList)) {
-            storeMenuVo.setMenuCount(storeMenuList.size());
-            Map<Integer, List<StoreMenu>> groupByDishType = storeMenuList.stream()
-                    .collect(Collectors.groupingBy(StoreMenu::getDishType));
-            List<StoreMenu> suggestList = groupByDishType.get(1);
-            if (CollectionUtils.isNotEmpty(suggestList)) {
-                storeMenuVo.setSuggestCount(suggestList.size());
-            } else {
-                storeMenuVo.setSuggestCount(0);
-            }
-        } else {
-            storeMenuVo.setMenuCount(0);
-            storeMenuVo.setSuggestCount(0);
-        }
-        return storeMenuVo;
+    private List<StorePlatformMenu> buildMenuTree(List<StorePlatformMenu> allMenus, Long parentId) {
+        return allMenus.stream()
+                .filter(menu -> parentId.equals(menu.getParentId()))
+                .map(menu -> {
+                    menu.setChildren(buildMenuTree(allMenus, menu.getMenuId()));
+                    return menu;
+                })
+                .collect(Collectors.toList());
     }
 
     /**
-     * 获取用户对该菜品是否点赞
+     * 计算菜单层级
+     * 根据父菜单ID计算当前菜单的层级
      *
-     * @param userId 用户id
-     * @param menuId 菜品id
-     * @return boolean
+     * @param parentId 父菜单ID
+     * @return 菜单层级(1一级菜单 2二级菜单 3三级菜单)
      */
-    @Override
-    public boolean getMenuLikeStatus(String userId, Integer menuId) {
-        return lifeLikeRecordMapper.selectCount(new QueryWrapper<LifeLikeRecord>().eq("dianzan_id", userId).eq("huifu_id", menuId).eq("delete_flag", 0)) > 0;
+    private Integer calculateMenuLevel(Long parentId) {
+        if (parentId == null || parentId == 0L) {
+            return 1; // 一级菜单
+        }
+        // 查询父菜单的层级
+        StorePlatformMenu parentMenu = storePlatformMenuMapper.selectById(parentId);
+        if (parentMenu == null) {
+            return 1; // 如果父菜单不存在,默认为一级菜单
+        }
+        // 父菜单层级 + 1
+        Integer parentLevel = parentMenu.getLevel();
+        if (parentLevel == null) {
+            return 2; // 如果父菜单没有层级信息,默认为二级菜单
+        }
+        return parentLevel + 1;
     }
 }

+ 191 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformRoleMenuServiceImpl.java

@@ -0,0 +1,191 @@
+package shop.alien.storeplatform.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+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.StorePlatformMenu;
+import shop.alien.entity.store.StorePlatformRoleMenu;
+import shop.alien.entity.store.vo.RolePermissionVo;
+import shop.alien.mapper.StorePlatformMenuMapper;
+import shop.alien.mapper.StorePlatformRoleMenuMapper;
+import shop.alien.storeplatform.service.StorePlatformRoleMenuService;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 角色菜单关联表 服务实现类
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+@Transactional
+public class StorePlatformRoleMenuServiceImpl extends ServiceImpl<StorePlatformRoleMenuMapper, StorePlatformRoleMenu> implements StorePlatformRoleMenuService {
+
+    private final StorePlatformRoleMenuMapper storePlatformRoleMenuMapper;
+    private final StorePlatformMenuMapper storePlatformMenuMapper;
+
+    @Override
+    public List<Long> getMenuIdsByRoleId(Long roleId) {
+        LambdaQueryWrapper<StorePlatformRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformRoleMenu::getRoleId, roleId);
+        List<StorePlatformRoleMenu> list = storePlatformRoleMenuMapper.selectList(queryWrapper);
+        return list.stream().map(StorePlatformRoleMenu::getMenuId).collect(Collectors.toList());
+    }
+
+    @Override
+    public List<Long> getRoleIdsByMenuId(Long menuId) {
+        LambdaQueryWrapper<StorePlatformRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformRoleMenu::getMenuId, menuId);
+        List<StorePlatformRoleMenu> list = storePlatformRoleMenuMapper.selectList(queryWrapper);
+        return list.stream().map(StorePlatformRoleMenu::getRoleId).collect(Collectors.toList());
+    }
+
+    @Override
+    public boolean assignMenus(Long roleId, List<Long> menuIds) {
+        if (roleId == null || menuIds == null || menuIds.isEmpty()) {
+            log.error("参数不能为空");
+            return false;
+        }
+        // 先删除角色的所有菜单
+        removeAllMenus(roleId);
+        // 批量插入新菜单
+        List<StorePlatformRoleMenu> roleMenus = menuIds.stream()
+                .map(menuId -> {
+                    StorePlatformRoleMenu roleMenu = new StorePlatformRoleMenu();
+                    roleMenu.setRoleId(roleId);
+                    roleMenu.setMenuId(menuId);
+                    return roleMenu;
+                })
+                .collect(Collectors.toList());
+        return this.saveBatch(roleMenus);
+    }
+
+    @Override
+    public boolean removeAllMenus(Long roleId) {
+        LambdaQueryWrapper<StorePlatformRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformRoleMenu::getRoleId, roleId);
+        return storePlatformRoleMenuMapper.delete(queryWrapper) >= 0;
+    }
+
+    @Override
+    public boolean addMenu(Long roleId, Long menuId) {
+        if (roleId == null || menuId == null) {
+            log.error("参数不能为空");
+            return false;
+        }
+        // 检查是否已存在
+        LambdaQueryWrapper<StorePlatformRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformRoleMenu::getRoleId, roleId)
+                .eq(StorePlatformRoleMenu::getMenuId, menuId);
+        StorePlatformRoleMenu exist = storePlatformRoleMenuMapper.selectOne(queryWrapper);
+        if (exist != null) {
+            log.warn("角色菜单关联已存在,roleId={}, menuId={}", roleId, menuId);
+            return true;
+        }
+        StorePlatformRoleMenu roleMenu = new StorePlatformRoleMenu();
+        roleMenu.setRoleId(roleId);
+        roleMenu.setMenuId(menuId);
+        return storePlatformRoleMenuMapper.insert(roleMenu) > 0;
+    }
+
+    @Override
+    public boolean removeMenu(Long roleId, Long menuId) {
+        LambdaQueryWrapper<StorePlatformRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformRoleMenu::getRoleId, roleId)
+                .eq(StorePlatformRoleMenu::getMenuId, menuId);
+        return storePlatformRoleMenuMapper.delete(queryWrapper) > 0;
+    }
+
+    @Override
+    public List<RolePermissionVo> getRolePermissionTree(Long roleId) {
+        if (roleId == null) {
+            return new ArrayList<>();
+        }
+        
+        // 1. 查询角色拥有的菜单ID列表
+        List<Long> menuIds = getMenuIdsByRoleId(roleId);
+        if (menuIds == null || menuIds.isEmpty()) {
+            return new ArrayList<>();
+        }
+        
+        // 2. 查询这些菜单的详细信息
+        LambdaQueryWrapper<StorePlatformMenu> menuQueryWrapper = new LambdaQueryWrapper<>();
+        menuQueryWrapper.in(StorePlatformMenu::getMenuId, menuIds);
+        menuQueryWrapper.eq(StorePlatformMenu::getDelFlag, "0");
+        menuQueryWrapper.eq(StorePlatformMenu::getStatus, "0");
+        menuQueryWrapper.orderByAsc(StorePlatformMenu::getMenuSort);
+        List<StorePlatformMenu> menus = storePlatformMenuMapper.selectList(menuQueryWrapper);
+        
+        if (menus == null || menus.isEmpty()) {
+            return new ArrayList<>();
+        }
+        
+        // 3. 转换为VO
+        List<RolePermissionVo> permissionVos = menus.stream()
+                .map(menu -> {
+                    RolePermissionVo vo = new RolePermissionVo();
+                    BeanUtils.copyProperties(menu, vo);
+                    return vo;
+                })
+                .collect(Collectors.toList());
+        
+        // 4. 构建树形结构
+        return buildPermissionTree(permissionVos);
+    }
+
+    /**
+     * 构建权限树形结构
+     */
+    private List<RolePermissionVo> buildPermissionTree(List<RolePermissionVo> flatList) {
+        if (flatList == null || flatList.isEmpty()) {
+            return new ArrayList<>();
+        }
+        
+        // 创建映射:ID到节点的映射,父ID到子节点列表的映射
+        Map<Long, RolePermissionVo> nodeMap = new HashMap<>();
+        Map<Long, List<RolePermissionVo>> parentChildMap = new HashMap<>();
+        List<RolePermissionVo> result = new ArrayList<>();
+        
+        // 第一步:建立映射关系
+        for (RolePermissionVo vo : flatList) {
+            Long menuId = vo.getMenuId();
+            Long parentId = vo.getParentId() != null ? vo.getParentId() : 0L;
+            
+            // 存入节点映射
+            nodeMap.put(menuId, vo);
+            
+            // 如果是根节点(parentId为0或null),直接添加到结果
+            if (parentId == null || parentId == 0) {
+                result.add(vo);
+            } else {
+                // 否则,记录父子关系
+                parentChildMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(vo);
+            }
+        }
+        
+        // 第二步:建立父子关系
+        for (RolePermissionVo vo : nodeMap.values()) {
+            Long menuId = vo.getMenuId();
+            if (parentChildMap.containsKey(menuId)) {
+                // 对子节点按排序值排序
+                List<RolePermissionVo> children = parentChildMap.get(menuId);
+                children.sort(Comparator.comparing(RolePermissionVo::getMenuSort, Comparator.nullsLast(Integer::compareTo)));
+                vo.setChildren(children);
+            }
+        }
+        
+        // 对根节点按排序值排序
+        result.sort(Comparator.comparing(RolePermissionVo::getMenuSort, Comparator.nullsLast(Integer::compareTo)));
+        
+        return result;
+    }
+}
+

+ 248 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformRoleServiceImpl.java

@@ -0,0 +1,248 @@
+package shop.alien.storeplatform.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 org.springframework.util.StringUtils;
+import shop.alien.entity.store.StorePlatformRole;
+import shop.alien.entity.store.vo.RolePermissionVo;
+import shop.alien.entity.store.vo.StorePlatformRoleVo;
+import shop.alien.mapper.StorePlatformRoleMapper;
+import shop.alien.storeplatform.service.StorePlatformRoleMenuService;
+import shop.alien.storeplatform.service.StorePlatformRoleService;
+import shop.alien.storeplatform.service.StorePlatformUserRoleService;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 平台角色信息表 服务实现类
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+@Transactional
+public class StorePlatformRoleServiceImpl extends ServiceImpl<StorePlatformRoleMapper, StorePlatformRole> implements StorePlatformRoleService {
+
+    private final StorePlatformRoleMapper storePlatformRoleMapper;
+    private final StorePlatformRoleMenuService storePlatformRoleMenuService;
+    private final StorePlatformUserRoleService storePlatformUserRoleService;
+
+    @Override
+    public IPage<StorePlatformRole> getRolePage(int page, int size, Integer storeId, String roleName, String description, String status) {
+        LambdaQueryWrapper<StorePlatformRole> queryWrapper = new LambdaQueryWrapper<>();
+        
+        // 店铺ID查询
+        if (storeId != null) {
+            queryWrapper.eq(StorePlatformRole::getStoreId, storeId);
+        }
+        
+        // 角色名称模糊查询
+        if (StringUtils.hasText(roleName)) {
+            queryWrapper.like(StorePlatformRole::getRoleName, roleName);
+        }
+        // 角色描述模糊查询
+        if (StringUtils.hasText(description)) {
+            queryWrapper.like(StorePlatformRole::getDescription, description);
+        }
+        
+        // 角色状态查询
+        if (StringUtils.hasText(status)) {
+            queryWrapper.eq(StorePlatformRole::getStatus, status);
+        }
+        
+        // 按显示顺序和创建时间排序
+        queryWrapper.orderByAsc(StorePlatformRole::getRoleSort);
+        queryWrapper.orderByDesc(StorePlatformRole::getCreatedTime);
+
+        return storePlatformRoleMapper.selectPage(new Page<>(page, size), queryWrapper);
+    }
+
+    @Override
+    public StorePlatformRole getRoleById(Long roleId) {
+        return storePlatformRoleMapper.selectById(roleId);
+    }
+
+    @Override
+    public boolean saveRole(StorePlatformRole role) {
+        // 校验必填字段
+        if (!StringUtils.hasText(role.getRoleName())) {
+            log.error("角色名称不能为空");
+            return false;
+        }
+        // 检查角色名称是否已存在(同一店铺内不能重复)
+        if (checkRoleNameExists(role.getStoreId(), role.getRoleName(), null)) {
+            log.error("角色名称已存在:{}", role.getRoleName());
+            return false;
+        }
+        // 设置默认值
+        if (role.getRoleSort() == null) {
+            role.setRoleSort(0);
+        }
+        if (!StringUtils.hasText(role.getStatus())) {
+            role.setStatus("0"); // 默认正常
+        }
+        if (!StringUtils.hasText(role.getDelFlag())) {
+            role.setDelFlag("0"); // 默认未删除
+        }
+        int result = storePlatformRoleMapper.insert(role);
+        return result > 0;
+    }
+
+    @Override
+    public boolean createRoleWithMenus(StorePlatformRole role, List<Long> menuIds) {
+        // 校验必填字段
+        if (!StringUtils.hasText(role.getRoleName())) {
+            log.error("角色名称不能为空");
+            return false;
+        }
+        // 检查角色名称是否已存在(同一店铺内不能重复)
+        if (checkRoleNameExists(role.getStoreId(), role.getRoleName(), null)) {
+            log.error("角色名称已存在,不允许重复添加:{}", role.getRoleName());
+            return false;
+        }
+        // 设置默认值
+        if (role.getRoleSort() == null) {
+            role.setRoleSort(0);
+        }
+        if (!StringUtils.hasText(role.getStatus())) {
+            role.setStatus("0"); // 默认正常
+        }
+        if (!StringUtils.hasText(role.getDelFlag())) {
+            role.setDelFlag("0"); // 默认未删除
+        }
+        // 保存角色
+        int result = storePlatformRoleMapper.insert(role);
+        if (result <= 0) {
+            log.error("保存角色失败");
+            return false;
+        }
+        // 如果有菜单权限,保存到关联表
+        if (menuIds != null && !menuIds.isEmpty()) {
+            boolean assignResult = storePlatformRoleMenuService.assignMenus(role.getRoleId(), menuIds);
+            if (!assignResult) {
+                log.error("分配菜单权限失败,角色ID:{}", role.getRoleId());
+                // 如果分配权限失败,可以考虑回滚角色创建,这里先记录日志
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean checkRoleNameExists(Integer storeId, String roleName, Long excludeRoleId) {
+        if (!StringUtils.hasText(roleName)) {
+            return false;
+        }
+        LambdaQueryWrapper<StorePlatformRole> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformRole::getRoleName, roleName);
+        queryWrapper.eq(StorePlatformRole::getDelFlag, "0"); // 只查询未删除的
+        // 店铺ID查询(同一店铺内角色名称不能重复)
+        if (storeId != null) {
+            queryWrapper.eq(StorePlatformRole::getStoreId, storeId);
+        }
+        // 如果指定了排除的角色ID,则排除该角色
+        if (excludeRoleId != null) {
+            queryWrapper.ne(StorePlatformRole::getRoleId, excludeRoleId);
+        }
+        long count = storePlatformRoleMapper.selectCount(queryWrapper);
+        return count > 0;
+    }
+
+    @Override
+    public boolean updateRole(StorePlatformRole role) {
+        if (role.getRoleId() == null) {
+            log.error("角色ID不能为空");
+            return false;
+        }
+
+        int result = storePlatformRoleMapper.updateById(role);
+        return result > 0;
+    }
+
+    @Override
+    public boolean deleteRole(Long roleId) {
+        // 逻辑删除
+        LambdaUpdateWrapper<StorePlatformRole> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(StorePlatformRole::getRoleId, roleId);
+        updateWrapper.set(StorePlatformRole::getDelFlag, "2"); // 2代表删除
+        
+        int result = storePlatformRoleMapper.update(null, updateWrapper);
+        return result > 0;
+    }
+
+    @Override
+    public boolean updateStatus(Long roleId, String status) {
+        if (roleId == null) {
+            log.error("角色ID不能为空");
+            return false;
+        }
+        if (!StringUtils.hasText(status)) {
+            log.error("角色状态不能为空");
+            return false;
+        }
+        
+        LambdaUpdateWrapper<StorePlatformRole> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(StorePlatformRole::getRoleId, roleId);
+        updateWrapper.set(StorePlatformRole::getStatus, status);
+        
+        int result = storePlatformRoleMapper.update(null, updateWrapper);
+        return result > 0;
+    }
+
+    @Override
+    public List<StorePlatformRole> getAllNormalRoles(Integer storeId) {
+        LambdaQueryWrapper<StorePlatformRole> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformRole::getStatus, "0"); // 正常状态
+        queryWrapper.eq(StorePlatformRole::getDelFlag, "0"); // 未删除
+        // 店铺ID查询
+        if (storeId != null) {
+            queryWrapper.eq(StorePlatformRole::getStoreId, storeId);
+        }
+        queryWrapper.orderByAsc(StorePlatformRole::getRoleSort);
+        
+        return storePlatformRoleMapper.selectList(queryWrapper);
+    }
+
+    @Override
+    public IPage<StorePlatformRoleVo> getRolePageWithStats(int page, int size, Integer storeId, String roleName, String description, String status) {
+        // 先查询角色分页数据
+        IPage<StorePlatformRole> rolePage = getRolePage(page, size, storeId, roleName, description, status);
+        
+        // 转换为VO并填充统计信息
+        IPage<StorePlatformRoleVo> voPage = new Page<>(rolePage.getCurrent(), rolePage.getSize(), rolePage.getTotal());
+        List<StorePlatformRoleVo> voList = rolePage.getRecords().stream()
+                .map(role -> {
+                    StorePlatformRoleVo vo = new StorePlatformRoleVo();
+                    BeanUtils.copyProperties(role, vo);
+                    
+                    // 统计关联子账号数量
+                    List<Integer> userIds = storePlatformUserRoleService.getUserIdsByRoleId(role.getRoleId());
+                    vo.setSubAccountCount(userIds != null ? userIds.size() : 0);
+                    
+                    // 统计关联权限数量
+                    List<Long> menuIds = storePlatformRoleMenuService.getMenuIdsByRoleId(role.getRoleId());
+                    vo.setPermissionCount(menuIds != null ? menuIds.size() : 0);
+                    
+                    // 查询权限树形结构
+//                    List<RolePermissionVo> permissions = storePlatformRoleMenuService.getRolePermissionTree(role.getRoleId());
+//                    vo.setPermissions(permissions);
+                    
+                    return vo;
+                })
+                .collect(Collectors.toList());
+        
+        voPage.setRecords(voList);
+        return voPage;
+    }
+}
+

+ 81 - 0
alien-store-platform/src/main/java/shop/alien/storeplatform/service/impl/StorePlatformUserRoleServiceImpl.java

@@ -0,0 +1,81 @@
+package shop.alien.storeplatform.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import shop.alien.entity.store.StorePlatformUserRole;
+import shop.alien.mapper.StorePlatformUserRoleMapper;
+import shop.alien.storeplatform.service.StorePlatformUserRoleService;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 用户角色关联表 服务实现类
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+@Transactional
+public class StorePlatformUserRoleServiceImpl extends ServiceImpl<StorePlatformUserRoleMapper, StorePlatformUserRole> implements StorePlatformUserRoleService {
+
+    private final StorePlatformUserRoleMapper storePlatformUserRoleMapper;
+
+    @Override
+    public List<Long> getRoleIdsByUserId(Integer userId) {
+        LambdaQueryWrapper<StorePlatformUserRole> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformUserRole::getUserId, userId);
+        List<StorePlatformUserRole> list = storePlatformUserRoleMapper.selectList(queryWrapper);
+        return list.stream().map(StorePlatformUserRole::getRoleId).collect(Collectors.toList());
+    }
+
+    @Override
+    public List<Integer> getUserIdsByRoleId(Long roleId) {
+        LambdaQueryWrapper<StorePlatformUserRole> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformUserRole::getRoleId, roleId);
+        List<StorePlatformUserRole> list = storePlatformUserRoleMapper.selectList(queryWrapper);
+        return list.stream().map(StorePlatformUserRole::getUserId).collect(Collectors.toList());
+    }
+
+    @Override
+    public boolean assignRoles(Integer userId, List<Long> roleIds) {
+        if (userId == null || roleIds == null || roleIds.isEmpty()) {
+            log.error("参数不能为空");
+            return false;
+        }
+        // 先删除用户的所有角色
+        removeAllRoles(userId);
+        // 批量插入新角色
+        List<StorePlatformUserRole> userRoles = roleIds.stream()
+                .map(roleId -> {
+                    StorePlatformUserRole userRole = new StorePlatformUserRole();
+                    userRole.setUserId(userId);
+                    userRole.setRoleId(roleId);
+                    return userRole;
+                })
+                .collect(Collectors.toList());
+        return this.saveBatch(userRoles);
+    }
+
+    @Override
+    public boolean removeAllRoles(Integer userId) {
+        LambdaQueryWrapper<StorePlatformUserRole> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformUserRole::getUserId, userId);
+        return storePlatformUserRoleMapper.delete(queryWrapper) >= 0;
+    }
+
+    @Override
+    public boolean removeRole(Integer userId, Long roleId) {
+        LambdaQueryWrapper<StorePlatformUserRole> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(StorePlatformUserRole::getUserId, userId)
+                .eq(StorePlatformUserRole::getRoleId, roleId);
+        return storePlatformUserRoleMapper.delete(queryWrapper) > 0;
+    }
+}
+