角色(Role)定义编写指南¶
目标:Agent 直接生成/修改 workspace 角色定义,并正确配置授权与用户绑定。知识以本文为准。不写原理;不依赖外链。
术语:平台 RBAC;角色挂在软件(Application)下,不是企业域实体。用户通过「用户-部门-角色」三元组绑定角色(运行库),角色本体在设计态 workspace 文件。
产出物一览¶
| 部分 | 落盘/库表 | 形态 |
|---|---|---|
| 角色定义 | role/{角色名}.role |
JAXB XML 根 role;id 为根属性 |
| 授权 | 同文件 <permissions> CDATA |
JSON 数组字符串 |
| 用户绑定 | **不**在 .role 内 |
运行库 T_USER_DEPARTMENT_ROLE_SET |
路径相对 storage/workspace。角色是**扁平单文件**(非目录);与 .module/.form 不同。
新建最低配置:
- 目录已存在:
{软件}.application/role/ - 写
{name}.role:id、name、parentId=软件 id、roleNo(软件内唯一)、status=1 - (推荐)至少一个
defaultRole=true的有效角色,便于新建用户自动挂上 - (按需)写
permissions;可先空,之后直接改文件补写 - (部署)企业域绑定软件;用户在
T_USER_DEPARTMENT_ROLE_SET中分配角色
约定:
- JAXB;根
role;id在 根属性;长文本/permissions 用 CDATA - 文件名 =
name={name}.role;同软件role/下不重名 parentId= 软件 id;applicationid建议写且 = 软件 id(部分旧样例可缺,靠路径归属)name勿含/%\(落盘时会被替换为=47/=37/=92)- **勿**把角色放到
module/下;角色永远在应用级role/ - 历史脚本里
INSERT INTO t_role/domainid:当前架构已失效;角色不在 DB 表,在 workspace 文件
1. 心智模型¶
企业域 Domain
├─ BIND_APPLICATIONS → 软件 id 列表(前台候选集)
└─ 用户 User
└─ T_USER_DEPARTMENT_ROLE_SET(userId, departmentId, roleId)
│
▼
软件 Application(activated + type)
└─ role/*.role(status、permissions)
├─ 菜单 ResourceVO(permissionType public|private)
├─ 表单 Form(同上)
└─ 视图 View(同上)
权限层(配置 + 角色):
| 层 | 决定什么 | 角色参与方式 |
|---|---|---|
| 软件可见 | 前台软件列表是否出现 | 非 SYSTEM:用户须有该 app 下 status=1 角色 |
| 菜单可见 | PC/移动菜单是否显示 | permissionType=public 全体可见;private 须 role.permissions 含该菜单 |
| 表单/视图打开与操作 | 打开、详情、编辑、各 activity | public 全通过;private 须对应 operation 在 permissions |
| 字段/流程节点 | 隐藏只读等 | 主要靠表单/流程脚本与节点字段权限;不全靠 .role |
| 数据范围 | 查得到哪些文档 | 视图过滤/auth 字段/脚本;不全靠 .role |
permissionType(菜单/表单/视图):
| 值 | 含义 |
|---|---|
public |
对该资源授权 UI 视为已勾选;运行时不强制查 role.permissions |
private |
须在角色 permissions 中显式授权相关 operationId 才有权 |
设计器逻辑:public 或未选 roleId → checked=true;否则 PermissionUtil.isExist(role, operationId)。
产品文档注:表单/视图需先设为「角色可查看」(即 private),授权界面才有意义;系统默认多为 public。
2. Role 属性 → .role XML¶
属性表¶
| 属性 | XML | 类型 | 默认 | 说明 |
|---|---|---|---|---|
id |
根属性 | string | 须生成 | __ + 短 UUID;用户绑定、permissions 缓存键用 |
name |
子元素 | string | — | 必填;文件名;同应用内唯一 |
parentId |
子元素 | string | — | = 软件 id |
applicationid |
子元素 | string | 建议 = 软件 id;须手写;部分旧样例可缺 | |
roleNo |
子元素 | string | — | 必填(设计态校验);同应用内唯一;脚本常用 |
status |
子元素 | int | 1 |
1=有效 STATUS_VALID;0=失效 STATUS_INVALID |
defaultRole |
子元素 | bool | true=系统默认角色;新建用户可自动挂上 |
|
sortId |
子元素 | string | 可选;时间序字符串即可 | |
orderNo |
子元素 | int | 0 |
列表排序;越小越前 |
permissions |
子元素 CDATA | string | 可省略 | JSON 数组;见 §3 |
description |
子元素 CDATA | string | 基类描述 | |
remark |
子元素 CDATA | string | 基类备注;少用 | |
uri / path |
— | — | 推导 | 不进 XML;路径 = …/role/{name}.role |
status¶
| 值 | 常量 | 效果 |
|---|---|---|
1 |
STATUS_VALID | 计入前台软件可见、流程选人等 |
0 |
STATUS_INVALID | 视为无效;有绑定也不当有效角色 |
defaultRole¶
true:该软件下的「默认角色」集合的成员(可多个)- 触发场景:新建用户时若尚无任何
UserDepartmentRoleSet,会把域已绑定软件的全部defaultRole=true角色挂到用户默认部门 - 微信/钉钉/飞书同步用户时也会拉默认角色
- 前台可见软件**不**要求 defaultRole,只需任意有效角色
roleNo¶
- 设计态创建/更新:name 与 roleNo 均不能空,且同应用内不与其它角色冲突
- 脚本:
USERCENTER.getRoleByRoleNo(roleno, applicationid)、getRoleProcess().find… - 建议稳定短编号(
001、T003);KM 固定编号见 §8
id 生成¶
统一规则:__ + 短 UUID。示例:__MpEzTToulqZtNEFisw6。须全局/库内不冲突。KM 固定 id 见 §8。
设计态校验文案(失败条件)¶
| 条件 | 含义 |
|---|---|
| name 空 | 请输入名称 |
| roleNo 空 | 请输入角色编号 |
| 同应用其它角色 name 相同 | 名称已存在 |
| 同应用其它角色 roleNo 相同 | 编号已存在 |
改字段直接改 XML;改 name 须同步改文件名。
3. permissions JSON¶
存字符串(CDATA),解析为数组。每项对应一个 Permission:
[
{
"operationCode": 1002,
"operationId": "资源或操作id",
"resId": "资源id",
"resName": "菜单|打开|详情|编辑|按钮名",
"resType": 2,
"roleId": "",
"type": 1
}
]
| 字段 | 类型 | 说明 |
|---|---|---|
resId |
string | 资源 id:菜单 id / 表单 id / 视图 id |
operationId |
string | 操作 id:菜单时常 =resId;打开时常 =表单/视图 id;按钮 =activity id;详情/编辑见下 |
operationCode |
int | 操作码,见下表 |
resType |
int | 资源类型,见下表 |
resName |
string | 显示名(菜单/打开/详情/编辑/activity.name) |
type |
int | 1=TYPE_ALLOW 允许;2=TYPE_FORBID 禁止(授权写入通常为 1) |
roleId |
string | 可选;样例常 "";运行校验主键用外层 role.id |
运行时鉴权键(缓存):{roleId}_{resId}_{operationId}_{operationCode} → 命中即有权。
resType¶
| 值 | 常量 | 含义 |
|---|---|---|
0 |
VIEW_TYPE | 视图 |
1 |
FORM_TYPE | 表单 |
2 |
MENU_TYPE | 菜单(PC .menu / 移动 .mobilemenu 同源 ResourceVO) |
3 |
FORM_FIELD_TYPE | 表单字段(字段级授权少见落盘) |
4 |
FOLDER_TYPE | 文件夹(文件系统类资源) |
operationCode(常用)¶
| 值 | 常量 | 典型 resName |
用法 |
|---|---|---|---|
1000 |
ALL | 所有操作 | |
1001 |
MENU_VISIABLE | 菜单可视(历史) | |
1002 |
MENU_INVISIBLE | 菜单 |
菜单授权写入实际用此码 + type=ALLOW;历史命名勿按字面「不可视」理解 |
1011–1014 |
FORMFIELD_* | 字段只读/修改/隐藏/禁用 | |
1021–1031 |
FOLDER_/FILE_ | 文件夹/文件操作 | |
1032 |
FORM_VIEW_ALLOW_OPEN | 打开 |
表单/视图允许打开;operationId=resId=表单或视图 id |
1033 |
VIEW_ALLOW_DETAIL | 详情 |
视图详情;创建时传入的 operationId 可为 {viewId}_1033,落盘后常归一为 viewId |
1034 |
VIEW_ALLOW_EDIT | 编辑 |
视图编辑;同上 {viewId}_1034 |
| 其它 | activity.getType() | 按钮名 | 表单/视图工具栏 activity;operationId=activity.id,operationCode=activity 类型码 |
三种授权形状(照抄生成)¶
菜单可见(PC/移动相同形状):
{
"operationCode": 1002,
"operationId": "{menuId}",
"resId": "{menuId}",
"resName": "菜单",
"resType": 2,
"roleId": "",
"type": 1
}
表单/视图「打开」:
{
"operationCode": 1032,
"operationId": "{formOrViewId}",
"resId": "{formOrViewId}",
"resName": "打开",
"resType": 0,
"type": 1
}
resType:视图=0,表单=1。
表单/视图 activity 按钮:
{
"operationCode": "{activity.type 整数}",
"operationId": "{activityId}",
"resId": "{formOrViewId}",
"resName": "{activity.name}",
"resType": 0或1,
"type": 1
}
改某一 resId 的授权时:删掉该 resId 下全部旧项再写入新列表,勿与碎片混写。
新建空角色可省略整个 <permissions>;省略 = 无显式授权(仅能靠资源 public 与软件级可见)。
4. 用户绑定(运行库,非 workspace)¶
表:T_USER_DEPARTMENT_ROLE_SET
| 列 | 说明 |
|---|---|
ID |
UUID |
USERID |
用户 id |
DEPARTMENTID |
部门 id |
ROLEID |
角色 id(= .role 的 id) |
要点:
- 多对多:一用户多角色;一角色多用户;绑定总带部门维度
- 管理端:域 → 软件 →「角色添加」→ 选用户;或用户编辑里设部门及角色
- 写
.role不会创建绑定;仅文件不够前台可见 - 用户必须有默认部门 + 角色才能正常用软件(产品手册要求)
- 改角色
status→0/ 删除角色文件后,旧 ROLEID 行可能残留——运行时按 role 查不到或 status 无效则失效
脚本侧(运行期):
user.getRoles()/role.getUsers()/USERCENTER.getUsersByRoleId/getAllRoles/findRoleByName/getRoleByRoleNoUserProcess.addUserToRole(userids, roleid)- 勿再用过时的
t_roleINSERT 当创建角色手段
5. 前台软件可见(与角色交汇)¶
条件(同时):
- 企业域
BIND_APPLICATIONS含该软件 id - 软件
activated=true - 若
type != SYSTEM_TYPE(2):用户角色集合中存在status==1且role.applicationid==app.id type==SYSTEM_TYPE:跳过角色检查
仅写 workspace 不会改域绑定。SYSTEM 例:admintools、部分 km。
6. XML 骨架¶
最小有效角色(无授权)¶
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<role id="__roleAdmin000000001">
<name>管理员</name>
<parentId>__a1b2c3d4e5f6g7h8i9j</parentId>
<applicationid>__a1b2c3d4e5f6g7h8i9j</applicationid>
<roleNo>001</roleNo>
<status>1</status>
<defaultRole>true</defaultRole>
<orderNo>0</orderNo>
</role>
路径:/{软件名}.application/role/管理员.role
带菜单 + 打开授权¶
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<role id="__793Hn9xULfelm6SsiyX">
<name>系统管理员</name>
<parentId>__hDwZZTLdvTMp871Uf3J</parentId>
<applicationid>__hDwZZTLdvTMp871Uf3J</applicationid>
<roleNo>T003</roleNo>
<status>1</status>
<defaultRole>false</defaultRole>
<sortId>169218477679300000</sortId>
<orderNo>0</orderNo>
<permissions><![CDATA[[
{"operationCode":1002,"operationId":"__menuId001","resId":"__menuId001","resName":"菜单","resType":2,"roleId":"","type":1},
{"operationCode":1032,"operationId":"__formId001","resId":"__formId001","resName":"打开","resType":1,"type":1},
{"operationCode":1032,"operationId":"__viewId001","resId":"__viewId001","resName":"打开","resType":0,"type":1}
]]]></permissions>
</role>
员工默认角色(常见)¶
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<role id="__roleStaff000000002">
<name>员工</name>
<parentId>__a1b2c3d4e5f6g7h8i9j</parentId>
<applicationid>__a1b2c3d4e5f6g7h8i9j</applicationid>
<roleNo>002</roleNo>
<status>1</status>
<defaultRole>true</defaultRole>
<orderNo>10</orderNo>
</role>
7. KM / 固定角色 id(特例)¶
RoleConstant(知识管理等):
| 级别 | LEVEL | 固定 role id | roleNo |
|---|---|---|---|
| 普通员工 | 0 | KMNORMALROLEID |
0001 |
| 部门管理员 | 10 | KMDEPTADMINROLEID |
0010 |
| 超级管理员 | 100 | KMSUPERADMINROLEID |
0100 |
样例 km.application/role/员工.role 使用 id=KMNORMALROLEID、parentId=KMAPPID。常规业务软件不要复用这些固定 id。
8. iScript / 运行 API 速查¶
RoleVO 常用:getId / getName / getRoleNo / getApplicationid / getPermission() / getUsers() / getUsersByDomain(domainId)
RoleProcess:doViewByName(name, applicationId) / getRolesByApplication(applicationId) / queryByUser(userId) / doUpdate / doRemove
USERCENTER:
getAllRoles()→ 当前软件角色集findRoleByName(name)/getRoleIdByName(name)getRoleByRoleNo(roleno, applicationid)getUsersByRoleId(roleid)/getUsersByDptIdAndRoleId(dptid, roleid)
WebUser:getRoles() / getRoleById(roleid)
流程选人常过滤 Role.STATUS_VALID。
9. 命名与 id¶
| 规则 | 要求 |
|---|---|
| name | 非空;同应用 role/ 唯一;作文件名 |
| roleNo | 非空;同应用唯一 |
| id | 全局不与其它设计态对象冲突 |
| 重命名 | 改文件名 + <name>;已绑定用户靠 id 仍有效 |
| 危险字符 | 避免 / % \ |
10. 新建清单(Agent)¶
1. 确认软件 id(读 {软件}.application 根属性 id)与 activated
2. 生成 roleId;定 name、roleNo(查现有 role/ 不冲突)
3. 写 role/{name}.role:parentId=applicationid=软件id,status=1
4. 若需新用户自动拥有:defaultRole=true(可与管理员角色并存多个默认)
5. 资源若保持 permissionType=public:可不写 permissions
6. 资源为 private:按 §3 写入菜单/打开/activity 项(resId/operationId 必须真实存在)
7. 部署:域 BIND_APPLICATIONS;T_USER_DEPARTMENT_ROLE_SET 绑用户
与软件新建配合¶
常规业务软件推荐同时具备:默认数据源 + 至少一个 status=1 角色(常 defaultRole=true 的「员工」或「管理员」)。详见软件技能;细节以本文为准。
11. 校验与常见错误¶
| 问题 | 处理 |
|---|---|
| 角色名称/编号已存在 | 换 name 或 roleNo |
| 角色名称/编号不能为空 | 两字段都写 |
| 前台看不到软件 | 查域绑定、activated、用户是否绑了该 app 有效角色、type |
| 菜单偶发不可见 | 菜单是否 private;permissions 是否含 menuId + code 1002 |
| 表单打不开 | form private 且缺 1032 打开项;或缺对应 activity 授权 |
| permissions 不生效 | JSON 非法;缓存未刷新;roleId/resId/operationId/code 四元组不匹配 |
| 根元素错误 | 必须 role 小写 |
| id 写成子元素 | 必须 <role id="…"> |
| 文件放进 module | 移到 …/role/ |
| 用 SQL 插 t_role | 无效;改写 .role 文件 |
| defaultRole 期望「仅一个」 | 实现允许多个默认角色,都会挂给新用户 |
12. 与其它技能边界¶
| 内容 | 本文 | 其它 |
|---|---|---|
.role 字段、permissions、用户绑定、RBAC 鉴权形状 |
✓ | |
| 软件目录、域绑定、activated、type | 交汇说明 | APPLICATION_SKILL |
| 模块路径 | 角色不在模块内 | MODULE_SKILL |
| 表单/视图 permissionType、activity | 授权消费方 | FORM_SKILL / VIEW_SKILL |
| 菜单 ResourceVO 文件 | 仅引用 id | 菜单相关手册/后续 skill |
| 字段脚本隐藏只读、流程节点字段权限 | 概要 | 表单/流程文档 |
生成业务包时:先软件+数据源+角色,再模块/表单/视图;需要细粒度访问时再写 permissions 或保持资源 public。