From acff00864b919d3bcf03283eb2204df28f12ba9d Mon Sep 17 00:00:00 2001 From: huwei <3313749341@qq.com> Date: Wed, 22 Jul 2026 10:17:11 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B2=97=E4=BD=8D=E4=B8=8Egbs=E6=9D=83?= =?UTF-8?q?=E9=99=90=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/db/alter-org-position-gbs-role.sql | 8 + docs/gbs/岗位与GBS角色关联说明.md | 148 ++++++++++++++++++ .../safetyeval/client/co/GbsRoleOptionCO.java | 20 +++ .../dto/OrgPositionAssignGbsRoleCmd.java | 29 ++++ .../safetyeval/client/enums/GbsRoleEnum.java | 50 ++++++ 5 files changed, 255 insertions(+) create mode 100644 docs/db/alter-org-position-gbs-role.sql create mode 100644 docs/gbs/岗位与GBS角色关联说明.md create mode 100644 safety-eval-client/src/main/java/org/qinan/safetyeval/client/co/GbsRoleOptionCO.java create mode 100644 safety-eval-client/src/main/java/org/qinan/safetyeval/client/dto/OrgPositionAssignGbsRoleCmd.java create mode 100644 safety-eval-client/src/main/java/org/qinan/safetyeval/client/enums/GbsRoleEnum.java diff --git a/docs/db/alter-org-position-gbs-role.sql b/docs/db/alter-org-position-gbs-role.sql new file mode 100644 index 0000000..bc3506f --- /dev/null +++ b/docs/db/alter-org-position-gbs-role.sql @@ -0,0 +1,8 @@ +-- 岗位表增加 GBS 角色关联字段 +-- 执行库:业务库(org_position 所在库) +-- 日期:2026-07-21(2026-07-22 补充 gbs_role_id) + +ALTER TABLE `org_position` + ADD COLUMN `gbs_role_id` bigint DEFAULT NULL COMMENT '关联GBS角色ID' AFTER `duty_desc`, + ADD COLUMN `gbs_role_code` varchar(64) DEFAULT NULL COMMENT '关联GBS角色编码' AFTER `gbs_role_id`, + ADD COLUMN `gbs_role_name` varchar(100) DEFAULT NULL COMMENT '关联GBS角色名称' AFTER `gbs_role_code`; diff --git a/docs/gbs/岗位与GBS角色关联说明.md b/docs/gbs/岗位与GBS角色关联说明.md new file mode 100644 index 0000000..f08e834 --- /dev/null +++ b/docs/gbs/岗位与GBS角色关联说明.md @@ -0,0 +1,148 @@ +# 业务系统岗位与 GBS 角色关联说明 + +## 1. 背景与包含关系 + +安全评价业务系统运行在 **GBS 底座**之上,权限能力形成包含关系: + +- GBS 负责统一身份、菜单/功能权限与角色控制,权限边界更大; +- 业务系统维护自身的组织机构(部门、岗位、人员); +- 业务系统不能绕过 GBS 自行做底座级功能授权,因此通过 **岗位 ↔ GBS 角色** 关联,在岗位变更时同步更新人员在 GBS 侧的角色。 + +```mermaid +flowchart TB + subgraph GBS["GBS 底座(权限超集)"] + GBS_AUTH[身份认证] + GBS_ROLE[角色权限] + GBS_MENU[功能/菜单授权] + end + + subgraph BIZ["安全评价业务系统(子集)"] + DEPT[部门] + POST[岗位] + PERSON[人员] + POST -->|关联| GBS_ROLE_REF[gbs_role_code / gbs_role_name] + PERSON -->|隶属| POST + end + + BIZ -->|运行于| GBS + PERSON -->|同步角色| GBS_ROLE + POST_GBS_LINK[岗位-角色关联] --> POST + POST_GBS_LINK --> GBS_ROLE_REF +``` + +## 2. 硬性约束 + +1. **存在硬编码角色权限的业务逻辑时**,必须先在 GBS 创建对应角色,再在本系统 `GbsRoleEnum` 中登记;业务代码只从枚举取值,禁止散落硬编码角色码字符串。 +2. **业务系统通过岗位与 GBS 角色关联**;当岗位重新分配 GBS 角色、岗位编辑且已有 GBS 角色关联且岗位下存在人员、或人员岗位发生变更且新岗位已关联 GBS 角色时,触发对人员 GBS 角色的更新(覆盖式 `updateUserRole`)。 +3. GBS `UserFacade` **当前无批量改角色接口**,实现上优先探测批量能力;若无则 **依次** 调用 `gbsUserFacadeClient.updateUserRole`(封装为 `updateUserRolesSequentially`)。 + +## 3. 数据模型 + +表 `org_position` 新增字段: + +| 字段 | 类型 | 说明 | +|------|------|------| +| `gbs_role_id` | bigint | 关联 GBS 角色ID | +| `gbs_role_code` | varchar(64) | 关联 GBS 角色编码 | +| `gbs_role_name` | varchar(100) | 关联 GBS 角色名称(展示用) | + +MySQL(全量): + +```sql +ALTER TABLE `org_position` + ADD COLUMN `gbs_role_id` bigint DEFAULT NULL COMMENT '关联GBS角色ID' AFTER `duty_desc`, + ADD COLUMN `gbs_role_code` varchar(64) DEFAULT NULL COMMENT '关联GBS角色编码' AFTER `gbs_role_id`, + ADD COLUMN `gbs_role_name` varchar(100) DEFAULT NULL COMMENT '关联GBS角色名称' AFTER `gbs_role_code`; +``` + +若此前已加过 code/name,仅补 ID:`docs/db/alter-org-position-gbs-role-id.sql`。 + +人员与岗位关系:`org_personnel.post_id` = `org_position.id`;人员主键与 GBS 用户 id 一致(创建人员时写入 GBS)。 + +## 4. 接口 + +| 方法 | 路径 | 说明 | +|------|------|------| +| POST | `/safetyEval/org-position/assign-gbs-role` | 为岗位分配 GBS 角色,并同步岗位下人员 | +| GET | `/safetyEval/org-position/gbs-roles` | 拉取 GBS 角色列表(下拉) | +| POST | `/safetyEval/org-position/modify` | 原编辑接口;若岗位已有 GBS 角色且有人员,则同步人员角色 | + +分配入参 `OrgPositionAssignGbsRoleCmd`:`id`、`gbsRoleId`、`gbsRoleCode`、`gbsRoleName`(可选,空则尝试按 code 反查名称)。 + +## 5. 业务流程 + +### 5.1 分配角色 + +```mermaid +sequenceDiagram + participant UI as 部门岗位页 + participant API as OrgPositionController + participant EXE as OrgPositionExecutor + participant DB as org_position / org_personnel + participant GBS as GbsUserFacadeClient + + UI->>API: POST /assign-gbs-role + API->>EXE: assignGbsRole(cmd) + EXE->>DB: 更新岗位 gbs_role_* + EXE->>DB: listByPostId(positionId) + alt 岗位下存在人员 + loop 每人(无批量接口) + EXE->>GBS: updateUserRole(roleCodes=[code]) + end + end + EXE-->>UI: 岗位 CO(含角色) +``` + +### 5.2 编辑岗位时同步 + +```mermaid +flowchart TD + A[POST /modify 编辑岗位] --> B[保存岗位基本信息] + B --> C{岗位是否已关联 gbs_role_code?} + C -->|否| Z[结束] + C -->|是| D{岗位下是否有人员?} + D -->|否| Z + D -->|是| E[依次 updateUserRole] + E --> Z +``` + +### 5.4 人员新增时角色 + +```mermaid +flowchart TD + A[新增人员] --> B{是否选择岗位?} + B -->|否| D[创建 GBS 用户:默认 auth.roleId.org] + B -->|是| C{岗位是否有 gbs_role_id / gbs_role_code?} + C -->|是| E[创建 GBS 用户:同时传入 roleId + roleCode] + C -->|否| D +``` + +### 5.3 硬编码角色使用约定 + +```mermaid +flowchart LR + NEED[业务需要固定角色判断] --> CREATE[先在 GBS 创建角色] + CREATE --> ENUM[登记到 GbsRoleEnum] + ENUM --> CODE[业务从枚举 getCode/getName] + CODE --> LOGIC[开展业务逻辑] +``` + +## 6. 前端使用流程 + +路径:`/safetyEval/container/EnterpriseInfo/DepartmentPosition` + +1. 选择左侧部门,查看岗位列表(含「GBS角色」列)。 +2. 行操作点击「分配角色」。 +3. 弹窗从 `/gbs-roles` 加载下拉,选择后提交 `/assign-gbs-role`。 +4. 若该岗位已有人员,后端依次更新其 GBS 角色后返回成功。 + +## 7. 关键代码索引 + +| 层级 | 位置 | +|------|------| +| 枚举 | `client/enums/GbsRoleEnum` | +| API | `OrgPositionApi#assignGbsRole` / `#listGbsRoles` | +| 执行 | `OrgPositionExecutor` | +| GBS 用户 | `GbsUserFacadeClient#updateUserRole` / `#updateUserRolesSequentially` | +| GBS 角色 | `GbsRoleFacadeClient#listRoles` | +| 前端 | `DepartmentPosition` + `api/orgPosition` | diff --git a/safety-eval-client/src/main/java/org/qinan/safetyeval/client/co/GbsRoleOptionCO.java b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/co/GbsRoleOptionCO.java new file mode 100644 index 0000000..c692ef5 --- /dev/null +++ b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/co/GbsRoleOptionCO.java @@ -0,0 +1,20 @@ +package org.qinan.safetyeval.client.co; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * GBS 角色简要 CO(供岗位分配角色下拉) + */ +@Data +public class GbsRoleOptionCO { + + @ApiModelProperty(value = "角色编码", example = "f3efa93b2639429687dc7e4175500a74") + private String roleCode; + + @ApiModelProperty(value = "角色名称", example = "test02") + private String roleName; + + @ApiModelProperty(value = "角色ID") + private Long roleId; +} diff --git a/safety-eval-client/src/main/java/org/qinan/safetyeval/client/dto/OrgPositionAssignGbsRoleCmd.java b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/dto/OrgPositionAssignGbsRoleCmd.java new file mode 100644 index 0000000..7d3cc33 --- /dev/null +++ b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/dto/OrgPositionAssignGbsRoleCmd.java @@ -0,0 +1,29 @@ +package org.qinan.safetyeval.client.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; + +/** + * 岗位分配 GBS 角色命令 + */ +@Data +public class OrgPositionAssignGbsRoleCmd { + + @NotNull(message = "岗位ID不能为空") + @ApiModelProperty(value = "岗位ID", required = true) + private Long id; + + @NotNull(message = "GBS角色ID不能为空") + @ApiModelProperty(value = "GBS角色ID", required = true, example = "2069671307598893058") + private Long gbsRoleId; + + @NotBlank(message = "GBS角色编码不能为空") + @ApiModelProperty(value = "GBS角色编码", required = true, example = "f3efa93b2639429687dc7e4175500a74") + private String gbsRoleCode; + + @ApiModelProperty(value = "GBS角色名称", example = "test02") + private String gbsRoleName; +} diff --git a/safety-eval-client/src/main/java/org/qinan/safetyeval/client/enums/GbsRoleEnum.java b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/enums/GbsRoleEnum.java new file mode 100644 index 0000000..e3e8e0a --- /dev/null +++ b/safety-eval-client/src/main/java/org/qinan/safetyeval/client/enums/GbsRoleEnum.java @@ -0,0 +1,50 @@ +package org.qinan.safetyeval.client.enums; + +/** + * GBS 角色枚举(业务硬编码角色时必须从此枚举取值)。 + *
+ * 使用约定: + *
+ * EVAL_ORG_ADMIN("xxx", "安评机构管理员");
+ *
+ */
+public enum GbsRoleEnum {
+
+ ;
+
+ private final String code;
+ private final String name;
+
+ GbsRoleEnum(String code, String name) {
+ this.code = code;
+ this.name = name;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public static GbsRoleEnum ofCode(String code) {
+ if (code == null) {
+ return null;
+ }
+ for (GbsRoleEnum item : values()) {
+ if (code.equals(item.code)) {
+ return item;
+ }
+ }
+ return null;
+ }
+}