岗位与gbs权限。

dev
huwei 2026-07-22 10:17:11 +08:00
parent 5855307c46
commit acff00864b
5 changed files with 255 additions and 0 deletions

View File

@ -0,0 +1,8 @@
-- 岗位表增加 GBS 角色关联字段
-- 执行库业务库org_position 所在库)
-- 日期2026-07-212026-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`;

View File

@ -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` |

View File

@ -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;
}

View File

@ -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;
}

View File

@ -0,0 +1,50 @@
package org.qinan.safetyeval.client.enums;
/**
* GBS
* <p>
* 使
* <ul>
* <li> GBS GBS code/name</li>
* <li></li>
* <li></li>
* </ul>
* </p>
*
*
* <pre>
* EVAL_ORG_ADMIN("xxx", "安评机构管理员");
* </pre>
*/
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;
}
}