userIdList;
+
+}
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/dto/UserRoleSaveDTO.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/dto/UserRoleSaveDTO.java
new file mode 100644
index 0000000..799acd0
--- /dev/null
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/dto/UserRoleSaveDTO.java
@@ -0,0 +1,47 @@
+package com.ningdatech.pmapi.sys.entity.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.*;
+import lombok.experimental.Accessors;
+
+import javax.validation.constraints.NotNull;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ *
+ * 实体类
+ * 角色分配
+ * 账号角色绑定
+ *
+ *
+ * @author PoffyZhang
+ */
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+@Accessors(chain = true)
+@ToString(callSuper = true)
+@EqualsAndHashCode(callSuper = false)
+@Builder
+@ApiModel(value = "UserRoleSaveDTO", description = "角色分配 账号角色绑定")
+public class UserRoleSaveDTO implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 角色ID
+ * #c_role
+ */
+ @ApiModelProperty(value = "角色ID")
+ @NotNull(message = "请选择角色")
+ private Long roleId;
+ /**
+ * 用户ID
+ * #c_user
+ */
+ @ApiModelProperty(value = "用户ID")
+ private List userIdList;
+
+}
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/enumeration/AuthorizeType.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/enumeration/AuthorizeType.java
new file mode 100644
index 0000000..01da87e
--- /dev/null
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/enumeration/AuthorizeType.java
@@ -0,0 +1,60 @@
+package com.ningdatech.pmapi.sys.entity.enumeration;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+import java.util.stream.Stream;
+
+/**
+ *
+ * 实体注释中生成的类型枚举
+ * 角色的资源
+ *
+ *
+ * @author PoffyZhang
+ * @since 2022-09-30
+ */
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+@ApiModel(value = "AuthorizeType", description = "权限类型-枚举")
+public enum AuthorizeType {
+
+ /**
+ * MENU="菜单"
+ */
+ MENU("菜单"),
+ DATA("数据"),
+ /**
+ * RESOURCE="资源"
+ */
+ RESOURCE("资源");
+
+ @ApiModelProperty(value = "描述")
+ private String desc;
+
+
+ /**
+ * 根据当前枚举的name匹配
+ */
+ public static AuthorizeType match(String val, AuthorizeType def) {
+ return Stream.of(values()).parallel().filter(item -> item.name().equalsIgnoreCase(val)).findAny().orElse(def);
+ }
+
+ public static AuthorizeType get(String val) {
+ return match(val, null);
+ }
+
+ public boolean eq(AuthorizeType val) {
+ return val != null && getCode().equals(val.name());
+ }
+
+ @ApiModelProperty(value = "编码", allowableValues = "MENU,RESOURCE", example = "MENU")
+ public String getCode() {
+ return this.name();
+ }
+
+}
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/enumeration/DataScopeEnum.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/enumeration/DataScopeEnum.java
new file mode 100644
index 0000000..1843fce
--- /dev/null
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/enumeration/DataScopeEnum.java
@@ -0,0 +1,31 @@
+package com.ningdatech.pmapi.sys.entity.enumeration;
+
+import lombok.Getter;
+
+/**
+ *
+ * DataScopeEnum
+ *
+ *
+ * @author WendyYang
+ * @since 15:59 2023/1/28
+ */
+@Getter
+public enum DataScopeEnum {
+
+ /**
+ * 数据权限可见范围
+ */
+ CURRENT_ORG("本单位", 1),
+ CURRENT_AND_SUB_ORG("本单位及下属单位", 2),
+ CURRENT_REGION("当前区域", 3),
+ CURRENT_CITY("全市", 4);
+
+ private final String desc;
+ private final Integer code;
+
+ DataScopeEnum(String desc, Integer code) {
+ this.code = code;
+ this.desc = desc;
+ }
+}
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/enumeration/MenuTypeEnum.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/enumeration/MenuTypeEnum.java
new file mode 100644
index 0000000..2e24913
--- /dev/null
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/enumeration/MenuTypeEnum.java
@@ -0,0 +1,57 @@
+package com.ningdatech.pmapi.sys.entity.enumeration;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 资源类型
+ *
+ * @author PoffyZhang
+ */
+@Getter
+@AllArgsConstructor
+@NoArgsConstructor
+@ApiModel(value = "MenuTypeEnum", description = "资源类型-枚举")
+public enum MenuTypeEnum {
+ /**
+ * 菜单
+ */
+ MENU(0, "菜单"),
+
+ /**
+ * 按钮
+ */
+ BUTTON(1, "按钮");
+
+ /**
+ * 资源类型
+ */
+ private Integer code;
+
+ /**
+ * 资源描述
+ */
+ private String desc;
+
+ public String getDesc() {
+ return desc;
+ }
+
+ public void setDesc(String desc) {
+ this.desc = desc;
+ }
+
+ @ApiModelProperty(value = "编码", allowableValues = "0,1", example = "0")
+ public Integer getCode() {
+ return this.code;
+ }
+
+
+ public boolean eq(String val) {
+ return this.name().equals(val);
+ }
+
+}
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/vo/MenuResourceTreeVO.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/vo/MenuResourceTreeVO.java
new file mode 100644
index 0000000..0eb7b07
--- /dev/null
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/vo/MenuResourceTreeVO.java
@@ -0,0 +1,35 @@
+package com.ningdatech.pmapi.sys.entity.vo;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ningdatech.pmapi.sys.entity.enumeration.AuthorizeType;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.ToString;
+
+import javax.validation.constraints.Size;
+
+import static com.baomidou.mybatisplus.annotation.SqlCondition.LIKE;
+
+/**
+ * menuList
+ * 菜单资源树
+ *
+ * @author PoffyZhang
+ */
+@Data
+@ToString(callSuper = true)
+public class MenuResourceTreeVO {
+
+ private AuthorizeType type;
+ private String code;
+ private String icon;
+ private Boolean isDef;
+ /**
+ * 描述
+ */
+ @ApiModelProperty(value = "描述")
+ @Size(max = 200, message = "描述长度不能超过200")
+ @TableField(value = "describe_", condition = LIKE)
+ private String describe;
+
+}
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/vo/MenuRoleVO.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/vo/MenuRoleVO.java
new file mode 100644
index 0000000..e7b4990
--- /dev/null
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/vo/MenuRoleVO.java
@@ -0,0 +1,78 @@
+package com.ningdatech.pmapi.sys.entity.vo;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ningdatech.pmapi.common.model.entity.MenuTreeEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.*;
+import lombok.experimental.Accessors;
+
+/**
+ *
+ * 实体类
+ * 菜单
+ *
+ *
+ * @author PoffyZhang
+ * @since 2022-9-30
+ */
+@Data
+@NoArgsConstructor
+@ToString(callSuper = true)
+@EqualsAndHashCode(callSuper = true)
+@Accessors(chain = true)
+@ApiModel(value = "RoleMenuVO", description = "菜单")
+@AllArgsConstructor
+public class MenuRoleVO extends MenuTreeEntity {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 权限"
+ */
+ @ApiModelProperty(value = "权限")
+ private String permission;
+ /**
+ * 类型;[0-菜单 1-目录 2-按钮]
+ */
+ @ApiModelProperty(value = "类型")
+ private Integer type;
+
+ /**
+ * 组件
+ */
+ @ApiModelProperty(value = "组件")
+ private String component;
+
+ /**
+ * 菜单图标
+ */
+ @ApiModelProperty(value = "菜单图标")
+ private String icon;
+
+ /**
+ * 是否隐藏
+ */
+ @ApiModelProperty(value = "是否隐藏")
+ private Integer hidden;
+
+ /**
+ * 是否有权限
+ */
+ @ApiModelProperty(value = "是否有权限 0没有 1有")
+ private Integer hasPermission = 0;
+
+ /**
+ * activeMenu
+ */
+ @ApiModelProperty(value = "activeMenu")
+ private String activeMenu;
+
+ /**
+ * 跳转
+ */
+ @ApiModelProperty(value = "跳转")
+ @TableField(value = "redirect")
+ private String redirect;
+
+}
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/vo/MenuVO.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/vo/MenuVO.java
new file mode 100644
index 0000000..83ad8bd
--- /dev/null
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/vo/MenuVO.java
@@ -0,0 +1,70 @@
+package com.ningdatech.pmapi.sys.entity.vo;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.*;
+import lombok.experimental.Accessors;
+
+/**
+ *
+ * 实体类
+ * 菜单
+ *
+ *
+ * @author PoffyZhang
+ * @since 2022-9-30
+ */
+@Data
+@NoArgsConstructor
+@ToString(callSuper = true)
+@Accessors(chain = true)
+@ApiModel(value = "MenuVO", description = "菜单")
+@AllArgsConstructor
+@Builder
+public class MenuVO {
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 权限"
+ */
+ @ApiModelProperty(value = "权限")
+ private String permission;
+ /**
+ * 类型;[0-菜单 1按钮]
+ */
+ @ApiModelProperty(value = "类型")
+ private Integer type;
+
+ /**
+ * 组件
+ */
+ @ApiModelProperty(value = "组件")
+ private String component;
+
+ /**
+ * 菜单图标
+ */
+ @ApiModelProperty(value = "菜单图标")
+ private String icon;
+
+ /**
+ * 子菜单数目
+ */
+ @ApiModelProperty(value = "是否隐藏")
+ private Integer hidden;
+
+ /**
+ * activeMenu
+ */
+ @ApiModelProperty(value = "activeMenu")
+ private String activeMenu;
+
+ /**
+ * 跳转
+ */
+ @ApiModelProperty(value = "跳转")
+ @TableField(value = "redirect")
+ private String redirect;
+}
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/vo/RoleVO.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/vo/RoleVO.java
new file mode 100644
index 0000000..9945b7c
--- /dev/null
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/entity/vo/RoleVO.java
@@ -0,0 +1,57 @@
+package com.ningdatech.pmapi.sys.entity.vo;
+
+import com.ningdatech.pmapi.sys.entity.BaseEntity;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.*;
+import lombok.experimental.Accessors;
+
+import java.util.List;
+
+/**
+ *
+ * 实体类
+ * 角色
+ *
+ *
+ * @author PoffyZhang
+ * @since 2022-09-30
+ */
+@Data
+@NoArgsConstructor
+@ToString(callSuper = true)
+@EqualsAndHashCode(callSuper = true)
+@Accessors(chain = true)
+@ApiModel(value = "Role", description = "角色")
+@AllArgsConstructor
+@Builder
+public class RoleVO extends BaseEntity {
+
+ private Long id;
+
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 名称
+ */
+ @ApiModelProperty(value = "名称")
+ private String name;
+
+ /**
+ * 描述
+ */
+ @ApiModelProperty(value = "描述")
+ private String describe;
+
+ /**
+ * 数据范围
+ */
+ @ApiModelProperty(value = "数据范围 1全部 2本区域 3本区域以及下区域 4本公司")
+ private Integer dataScope;
+
+ /**
+ * 菜单
+ */
+ @ApiModelProperty(value = "菜单")
+ private List menu;
+}
diff --git a/pmapi/src/main/java/com/ningdatech/pmapi/sys/manage/MenuManage.java b/pmapi/src/main/java/com/ningdatech/pmapi/sys/manage/MenuManage.java
new file mode 100644
index 0000000..3307485
--- /dev/null
+++ b/pmapi/src/main/java/com/ningdatech/pmapi/sys/manage/MenuManage.java
@@ -0,0 +1,44 @@
+package com.ningdatech.pmapi.sys.manage;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.ningdatech.basic.util.CollUtils;
+import com.ningdatech.pmapi.common.utils.TreeUtil;
+import com.ningdatech.pmapi.sys.entity.Menu;
+import com.ningdatech.pmapi.sys.entity.RoleMenu;
+import com.ningdatech.pmapi.sys.entity.vo.MenuRoleVO;
+import com.ningdatech.pmapi.sys.service.IRoleMenuService;
+import com.ningdatech.pmapi.user.security.auth.model.UserInfoDetails;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Component;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ *
+ * MenuManage - 菜单管理业务层
+ *
+ *
+ * @author WendyYang
+ * @since 14:23 2023/1/28
+ */
+@Component
+@RequiredArgsConstructor
+public class MenuManage {
+
+ private final IRoleMenuService roleMenuService;
+
+ public List buildUserMenu(List