diff --git a/pom.xml b/pom.xml
index 3e03bd2f..b49a1d6c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -17,6 +17,7 @@
tyr-api
tyr-server
+ tyr-client
diff --git a/tyr-client/pom.xml b/tyr-client/pom.xml
new file mode 100644
index 00000000..3af6d9e1
--- /dev/null
+++ b/tyr-client/pom.xml
@@ -0,0 +1,28 @@
+
+
+ 4.0.0
+
+
+ tyr
+ cn.axzo.tyr
+ ${revision}
+ ../pom.xml
+
+
+ tyr-client
+ jar
+ tyr-client
+
+
+
+ cn.axzo.framework
+ axzo-consumer-spring-cloud-starter
+
+
+
+ cn.axzo.foundation
+ common-lib
+ 2.0.0-SNAPSHOT
+
+
+
diff --git a/tyr-client/src/main/java/cn/axzo/tyr/feign/api/RoleApi.java b/tyr-client/src/main/java/cn/axzo/tyr/feign/api/RoleApi.java
new file mode 100644
index 00000000..866e97cc
--- /dev/null
+++ b/tyr-client/src/main/java/cn/axzo/tyr/feign/api/RoleApi.java
@@ -0,0 +1,17 @@
+package cn.axzo.tyr.feign.api;
+
+import cn.axzo.foundation.result.ApiResult;
+import cn.axzo.tyr.feign.req.ListRoleReq;
+import cn.axzo.tyr.feign.resp.RoleResp;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+
+import java.util.List;
+
+@FeignClient(name = "tyr", url = "${axzo.service.tyr:http://tyr:8080}")
+public interface RoleApi {
+
+ @PostMapping("/api/role/list")
+ ApiResult> list(@RequestBody ListRoleReq req);
+}
diff --git a/tyr-client/src/main/java/cn/axzo/tyr/feign/enums/FeatureResourceTypeEnum.java b/tyr-client/src/main/java/cn/axzo/tyr/feign/enums/FeatureResourceTypeEnum.java
new file mode 100644
index 00000000..c273676b
--- /dev/null
+++ b/tyr-client/src/main/java/cn/axzo/tyr/feign/enums/FeatureResourceTypeEnum.java
@@ -0,0 +1,31 @@
+package cn.axzo.tyr.feign.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+/**
+ * 功能资源类型
+ *
+ * @version V1.0
+ * @author: ZhanSiHu
+ * @date: 2024/4/3 11:35
+ */
+@Getter
+@AllArgsConstructor
+public enum FeatureResourceTypeEnum {
+
+ MENU(1, "菜单"),
+ PAGE(2, "页面"),
+ APP_ENTRY(3, "应用入口"),
+ COMPONENT(4, "组件"),
+ ROOT(5, "ROOT"),
+ GROUP(6, "分组"),
+ // 用户pc端菜单直接的分割分组线
+ MENU_PARTITION_GROUP(7, "菜单分割分组"),
+ ;
+
+ private final Integer code;
+
+ private final String desc;
+}
diff --git a/tyr-client/src/main/java/cn/axzo/tyr/feign/enums/RolePermissionTagEnum.java b/tyr-client/src/main/java/cn/axzo/tyr/feign/enums/RolePermissionTagEnum.java
new file mode 100644
index 00000000..9e16c19c
--- /dev/null
+++ b/tyr-client/src/main/java/cn/axzo/tyr/feign/enums/RolePermissionTagEnum.java
@@ -0,0 +1,16 @@
+package cn.axzo.tyr.feign.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+
+@Getter
+@AllArgsConstructor
+public enum RolePermissionTagEnum {
+
+ JOINED("在职"),
+ LEAVE("离场"),
+ ;
+
+ private final String desc;
+}
diff --git a/tyr-client/src/main/java/cn/axzo/tyr/feign/enums/RoleTypeEnum.java b/tyr-client/src/main/java/cn/axzo/tyr/feign/enums/RoleTypeEnum.java
new file mode 100644
index 00000000..ab94b5de
--- /dev/null
+++ b/tyr-client/src/main/java/cn/axzo/tyr/feign/enums/RoleTypeEnum.java
@@ -0,0 +1,24 @@
+package cn.axzo.tyr.feign.enums;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author tanjie@axzo.cn
+ * @date 2023/9/13 16:35
+ */
+@Getter
+@AllArgsConstructor
+public enum RoleTypeEnum {
+
+ //角色类型:common 自定义角色 super_admin超级管理员(禁止删除) admin子管理员(禁止删除) init初始化内置角色 auto_own自定义角色(禁止删除)<承载向用户单独分配的自定义权限>
+ COMMON("common", "自定义角色",false),
+ SUPER_ADMIN("super_admin", "超级管理员",true),
+ ADMIN("admin", "子管理员",true),
+ INIT("init", "初始化内置角色-标准角色",false),
+ AUTO_OWN("auto_own", "虚拟角色(自定义权限使用)",false);
+
+ private final String value;
+ private final String desc;
+ private final boolean isAdmin;
+}
diff --git a/tyr-client/src/main/java/cn/axzo/tyr/feign/req/ListRoleReq.java b/tyr-client/src/main/java/cn/axzo/tyr/feign/req/ListRoleReq.java
new file mode 100644
index 00000000..c678e149
--- /dev/null
+++ b/tyr-client/src/main/java/cn/axzo/tyr/feign/req/ListRoleReq.java
@@ -0,0 +1,146 @@
+package cn.axzo.tyr.feign.req;
+
+import cn.axzo.tyr.feign.enums.RolePermissionTagEnum;
+import cn.axzo.tyr.feign.enums.RoleTypeEnum;
+import cn.axzo.tyr.feign.enums.FeatureResourceTypeEnum;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.List;
+import java.util.Set;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class ListRoleReq {
+
+ /**
+ * 角色id
+ */
+ private Set roleIds;
+
+ /**
+ * 租户类型
+ */
+ private Integer workspaceType;
+
+ /**
+ * 是否显示
+ */
+ private Boolean isDisplay;
+
+ /**
+ * 角色权限码
+ */
+ private String roleCode;
+
+ /**
+ * 租户id
+ */
+ private Set workspaceIds;
+
+ /**
+ * 单位id
+ */
+ private Set ouIds;
+
+ /**
+ * 是否启用
+ */
+ private Boolean enabled;
+
+ /**
+ * 角色类型:RoleTypeEnum
+ * super_admin:超级管理员
+ * admin:管理员
+ * init:初始化内置角色-标准角色
+ * auto_own:虚拟角色(自定义权限使用)
+ * common:自定义角色
+ */
+ private Set roleTypes;
+
+ /**
+ * 是否需要角色下的权限信息
+ */
+ private Boolean needPermission;
+
+ /**
+ * 根据权限标签去过滤角色对应的权限,
+ * 只有在needPermission = true时才生效
+ */
+ private Set permissionTags;
+
+ /**
+ * 是否需要角色对应的角色分组信息
+ */
+ private Boolean needRoleGroup;
+
+ /**
+ * 是否需要角色对应的用户信息
+ */
+ private Boolean needRoleUser;
+
+
+ private Boolean needPermissionRelation;
+
+ /**
+ * 是否需要预设角色,因为预设角色的workspaceId和ouId为-1
+ */
+ private Boolean needPresetRole;
+
+ /**
+ * 查询菜单树节点类型
+ */
+ private List featureResourceTypes;
+
+ /**
+ * 新旧权限点,needPermissionRelation = true时最好带上,因为新旧权限点会有冲突的情况发生
+ */
+ private Integer type;
+
+ /**
+ * 端,查询权限点时,会根据端过滤,增加效率,目前只有CMS端的新版本才冗余了端
+ */
+ private String terminal;
+
+ /**
+ * workspaceId和ouId配对查询
+ * 例如:((workspaceId = ## and ouId = ##) or (workspaceId = ## and ouId = ##))
+ */
+ private List workspaceOuPairs;
+
+ /**
+ * 角色权限码
+ */
+ private Set roleCodes;
+
+ /**
+ * 角色分组code
+ */
+ private Set roleGroupCodes;
+
+ /**
+ * 协同关系类型
+ * 1:总包 2:建设单位 3:监理单位 4:劳务分包 5:专业分包 6:OMS通用 7:企业通用 8:企业内班组 9:项目内班组
+ */
+ private Set cooperateShipTypes;
+
+ @Data
+ @Builder
+ @NoArgsConstructor
+ @AllArgsConstructor
+ public static class WorkspaceOuPair {
+ /**
+ * 租户id
+ */
+ private Long workspaceId;
+
+ /**
+ * 单位id
+ */
+ private Long ouId;
+ }
+}
diff --git a/tyr-client/src/main/java/cn/axzo/tyr/feign/resp/RoleGroupResp.java b/tyr-client/src/main/java/cn/axzo/tyr/feign/resp/RoleGroupResp.java
new file mode 100644
index 00000000..597ee1ce
--- /dev/null
+++ b/tyr-client/src/main/java/cn/axzo/tyr/feign/resp/RoleGroupResp.java
@@ -0,0 +1,15 @@
+package cn.axzo.tyr.feign.resp;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RoleGroupResp {
+
+ private Long id;
+}
diff --git a/tyr-client/src/main/java/cn/axzo/tyr/feign/resp/RolePermissionResp.java b/tyr-client/src/main/java/cn/axzo/tyr/feign/resp/RolePermissionResp.java
new file mode 100644
index 00000000..f1619fb9
--- /dev/null
+++ b/tyr-client/src/main/java/cn/axzo/tyr/feign/resp/RolePermissionResp.java
@@ -0,0 +1,15 @@
+package cn.axzo.tyr.feign.resp;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RolePermissionResp {
+
+ private Long id;
+}
diff --git a/tyr-client/src/main/java/cn/axzo/tyr/feign/resp/RoleResp.java b/tyr-client/src/main/java/cn/axzo/tyr/feign/resp/RoleResp.java
new file mode 100644
index 00000000..ee4b9842
--- /dev/null
+++ b/tyr-client/src/main/java/cn/axzo/tyr/feign/resp/RoleResp.java
@@ -0,0 +1,107 @@
+package cn.axzo.tyr.feign.resp;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+import java.util.List;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RoleResp {
+
+ /**
+ * 角色id
+ */
+ private Long roleId;
+
+ /**
+ * 角色编码
+ */
+ private String roleCode;
+
+ /**
+ * 角色名称
+ */
+ private String name;
+
+ /**
+ * 角色描述
+ */
+ private String description;
+
+ /**
+ * 角色类型:common 普通角色 super_admin超级管理员(禁止删除) admin子管理员(禁止删除) init初始化内置角色
+ * @See cn.axzo.tyr.model.enums.RoleTypeEnum
+ */
+ private String roleType;
+
+ /**
+ * 角色所属租户id,预设角色的workspaceId <= 0
+ */
+ private Long workspaceId;
+
+ /**
+ * 角色所属单位id,预设角色的ouId <= 0
+ */
+ private Long ouId;
+
+ /**
+ * 协同关系类型
+ * 1:总包 2:建设单位 3:监理单位 4:劳务分包 5:专业分包 6:OMS通用 7:企业通用 8:企业内班组 9:项目内班组
+ */
+ private Integer cooperateShipType;
+
+ /**
+ * 创建者
+ */
+ private Long createBy;
+
+ /**
+ * 更新者
+ */
+ private Long updateBy;
+
+ /**
+ * 是否显示
+ */
+ private Boolean isDisplay;
+ /**
+ * 是否启用
+ */
+ private Boolean enabled;
+
+ /**
+ * 排序
+ */
+ private Integer sort;
+
+ /**
+ * 添加时间
+ */
+ private Date createAt;
+
+ /**
+ * 更新时间
+ */
+ private Date updateAt;
+
+ /**
+ * 角色所属分组
+ */
+ private RoleGroupResp roleGroup;
+
+ /**
+ * 角色权限
+ */
+ private List rolePermissions;
+
+ /**
+ * 角色对应的人员信息
+ */
+ private List roleUsers;
+}
diff --git a/tyr-client/src/main/java/cn/axzo/tyr/feign/resp/RoleUserResp.java b/tyr-client/src/main/java/cn/axzo/tyr/feign/resp/RoleUserResp.java
new file mode 100644
index 00000000..fcc92ebb
--- /dev/null
+++ b/tyr-client/src/main/java/cn/axzo/tyr/feign/resp/RoleUserResp.java
@@ -0,0 +1,15 @@
+package cn.axzo.tyr.feign.resp;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class RoleUserResp {
+
+ private Long id;
+}
diff --git a/tyr-client/src/main/resources/META-INF/spring.factories b/tyr-client/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..902097fe
--- /dev/null
+++ b/tyr-client/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+cn.axzo.tyr.client.config.TyrClientAutoConfiguration
\ No newline at end of file
diff --git a/tyr-server/pom.xml b/tyr-server/pom.xml
index 4b79e636..926c1779 100644
--- a/tyr-server/pom.xml
+++ b/tyr-server/pom.xml
@@ -156,6 +156,11 @@
braum-api
1.0.0-SNAPSHOT
+
+ cn.axzo.tyr
+ tyr-client
+ 2.0.0-SNAPSHOT
+
diff --git a/tyr-server/src/main/java/cn/axzo/tyr/server/controller/v2/RoleController.java b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/v2/RoleController.java
new file mode 100644
index 00000000..0e2d8728
--- /dev/null
+++ b/tyr-server/src/main/java/cn/axzo/tyr/server/controller/v2/RoleController.java
@@ -0,0 +1,35 @@
+package cn.axzo.tyr.server.controller.v2;
+
+import cn.axzo.foundation.result.ApiResult;
+import cn.axzo.tyr.client.model.res.SaasRoleRes;
+import cn.axzo.tyr.feign.api.RoleApi;
+import cn.axzo.tyr.feign.req.ListRoleReq;
+import cn.axzo.tyr.feign.resp.RoleResp;
+import cn.axzo.tyr.server.service.RoleService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Slf4j
+@RestController
+public class RoleController implements RoleApi {
+
+ @Autowired
+ private RoleService roleService;
+
+ @Override
+ public ApiResult> list(ListRoleReq req) {
+ List list = roleService.list(cn.axzo.tyr.client.model.req.ListRoleReq.builder().build());
+ return ApiResult.success(list.stream()
+ .map(e -> {
+ RoleResp result = RoleResp.builder().build();
+ BeanUtils.copyProperties(e, result);
+ return result;
+ })
+ .collect(Collectors.toList()));
+ }
+}