Merge branch 'master' of http://106.15.36.190:3000/DKJ/MID
This commit is contained in:
commit
394cb3cc18
|
|
@ -0,0 +1,553 @@
|
|||
节点权限设计说明(支持两棵树 + 子节点操作 + 全局 tree 规则)
|
||||
|
||||
本说明基于当前的权限表设计约束:
|
||||
|
||||
- 有两棵树:`standards` 和 `projects`。
|
||||
- 只有 **Allow**(允许)权限,没有 Deny,也没有继承。
|
||||
- 使用一张表 `node_permission` 管理权限,支持 6 类主体:
|
||||
|
||||
- 用户:`user`
|
||||
- 用户组:`group`
|
||||
- 角色:`role`
|
||||
- 所有人:`everyone`
|
||||
- 父节点的 owner:`parent_owner`
|
||||
- 子树根节点的 owner:`root_owner`
|
||||
|
||||
---
|
||||
|
||||
### 一、`node_permission` 表字段定义
|
||||
|
||||
```sql
|
||||
CREATE TABLE node_permission (
|
||||
id BIGINT PRIMARY KEY AUTO_INCREMENT,
|
||||
|
||||
-- 树维度:
|
||||
-- 'standards' : 只对 standards 生效
|
||||
-- 'projects' : 只对 projects 生效
|
||||
-- NULL : 两棵树都生效(全局规则)
|
||||
tree VARCHAR(32) NULL,
|
||||
|
||||
-- 节点维度:
|
||||
-- NULL : 默认权限(作用范围由 tree 决定)
|
||||
-- > 0 : 某个具体节点的专属权限
|
||||
node_id BIGINT NULL,
|
||||
|
||||
-- 主体类型:
|
||||
-- user : 用户(user.id)
|
||||
-- group : 用户组(group.id)
|
||||
-- role : 角色(如 super/sAdmin/pAdmin)
|
||||
-- everyone : 所有人
|
||||
-- parent_owner : 父节点的 owner
|
||||
-- root_owner : 当前子树根节点的 owner
|
||||
principal_type ENUM(
|
||||
'user',
|
||||
'group',
|
||||
'role',
|
||||
'everyone',
|
||||
'parent_owner',
|
||||
'root_owner'
|
||||
) NOT NULL,
|
||||
|
||||
-- 主体标识:
|
||||
-- user/group : 对应 id 的字符串
|
||||
-- role : 角色 code
|
||||
-- everyone / parent_owner / root_owner : 固定为 NULL
|
||||
principal_key VARCHAR(64) NULL,
|
||||
|
||||
-- 节点自身权限
|
||||
can_list_children TINYINT(1) NOT NULL DEFAULT 0,
|
||||
can_add_child_folder TINYINT(1) NOT NULL DEFAULT 0,
|
||||
can_add_child_doc TINYINT(1) NOT NULL DEFAULT 0,
|
||||
can_delete_node TINYINT(1) NOT NULL DEFAULT 0,
|
||||
can_edit_node TINYINT(1) NOT NULL DEFAULT 0,
|
||||
|
||||
-- 文档内容权限
|
||||
can_read_doc TINYINT(1) NOT NULL DEFAULT 0,
|
||||
can_edit_doc TINYINT(1) NOT NULL DEFAULT 0,
|
||||
can_delete_doc TINYINT(1) NOT NULL DEFAULT 0,
|
||||
|
||||
-- 子节点操作权限
|
||||
can_delete_child_node TINYINT(1) NOT NULL DEFAULT 0,
|
||||
can_edit_child_node TINYINT(1) NOT NULL DEFAULT 0,
|
||||
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
-- 同一 (tree, node_id, principal_type, principal_key) 只允许一条
|
||||
UNIQUE KEY uk_tree_node_principal (tree, node_id, principal_type, principal_key),
|
||||
KEY idx_node (node_id),
|
||||
KEY idx_principal (principal_type, principal_key)
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、`node_permission` 关键字段语义
|
||||
|
||||
这里只说明与鉴权相关的字段
|
||||
|
||||
- **节点维度**
|
||||
|
||||
- `node_id`:
|
||||
- `NULL`:表示“**默认权限**”,作用范围由 `tree` 决定:
|
||||
- `tree = 'standards'`:只对 standards 全部节点生效;
|
||||
- `tree = 'projects'`:只对 projects 全部节点生效;
|
||||
- `tree IS NULL`:对两棵树全部节点生效。
|
||||
- `> 0`:表示“**某个具体节点的专属权限**”,此时 `tree` 应等于该节点所属树。
|
||||
- **主体(Principal)维度**
|
||||
|
||||
- `principal_type`:`'user' | 'group' | 'role' | 'everyone' | 'parent_owner' | 'root_owner'`
|
||||
- `principal_key`:根据principal_type确定其含义
|
||||
- `user`:对应用户表 `user.id` 的字符串形式(如 `'12'`)
|
||||
- `group`:对应用户组表 `group.id` 的字符串形式
|
||||
- `role`:角色编码(如 `'super'`、`'sAdmin'`、`'pAdmin'`)
|
||||
- `everyone`:固定为 `NULL`
|
||||
- `parent_owner`:固定为 `NULL`
|
||||
- `root_owner`:固定为 `NULL`
|
||||
- **节点自身权限字段**
|
||||
|
||||
- `can_list_children`:是否可展开节点、列出子节点。
|
||||
- `can_add_child_folder`:是否可在该节点下新增文件夹(`node_type='folder'`)。
|
||||
- `can_add_child_doc`:是否可在该节点下新增文档(`node_type='doc'`)。
|
||||
- `can_delete_node`:是否可删除该节点本身。
|
||||
- `can_edit_node`:是否可修改该节点本身的元数据(名称、排序、owner 等)。
|
||||
- **文档内容权限字段**
|
||||
|
||||
- `can_read_doc`:是否可读取文档内容。
|
||||
- `can_edit_doc`:是否可编辑文档内容。
|
||||
- `can_delete_doc`:是否可删除文档节点。
|
||||
- **对子节点操作权限字段**
|
||||
|
||||
- `can_delete_child_node`:是否有权删除“该节点的直接子节点”。
|
||||
- `can_edit_child_node`:是否有权修改“该节点的直接子节点”的元数据(如 name、owner)。
|
||||
|
||||
**唯一约束建议:**
|
||||
|
||||
- `(tree, node_id, principal_type, principal_key)` 唯一。这样:
|
||||
- 对于某棵树上的某个节点 + 某个主体,只会有一条“节点专属”权限记录;
|
||||
- 对于某棵树上的某个主体,只会有一条“默认”规则;
|
||||
- `tree IS NULL AND node_id IS NULL` 的记录则是“两棵树共用的唯一全局默认”。
|
||||
|
||||
---
|
||||
|
||||
## 三、主体集合(Principals)的构造
|
||||
|
||||
鉴权的第一步是,把“当前用户在权限系统里是谁”表达成一个**主体集合**,集合中的每个元素是一个 `(principal_type, principal_key)`。
|
||||
|
||||
设:
|
||||
|
||||
- 当前用户 id 为 `U`;
|
||||
- 当前操作的节点 id 为 `N`;
|
||||
- 当前节点所属的树为 `T`(`'standards'` 或 `'projects'`,可以从 `nodes` 表的字段`tree_type`获得 。
|
||||
|
||||
### 3.1 主体集合的组成
|
||||
|
||||
主体集合 `P` 至少包含以下几类元素:
|
||||
|
||||
1. **用户本身(user)**
|
||||
|
||||
- 元素:`('user', U.toString())`
|
||||
2. **用户所属的所有组(group)**
|
||||
|
||||
- 从 `groupUser` 中查询:`WHERE user_id = U` 得到所有 `group_id`。
|
||||
- 每个组生成一个主体:`('group', groupId.toString())`。
|
||||
3. **用户的角色(role)**
|
||||
|
||||
- `users` 表有一个 `role` 字段(值为 `'super'` / `'sAdmin'` / `'pAdmin'`),可获取到角色。
|
||||
- 生成主体:`('role', roleCode)`。
|
||||
4. **everyone(所有人)**
|
||||
|
||||
- 固定加入:`('everyone', NULL)`。
|
||||
5. **parent_owner(父节点 owner)**
|
||||
|
||||
- 先在 `nodes` 表中拿到当前节点的父节点 id:`parentId`。
|
||||
- 若 `parentId` 大于 0,则再从 `node` 表读出该父节点的 `owner` 字段:
|
||||
- 若 `owner == U`,说明当前用户是父节点的 owner,则加入:`('parent_owner', NULL)`。
|
||||
- 否则不加入 `parent_owner`。
|
||||
6. **root_owner(子树根节点 owner)**
|
||||
|
||||
- 定义一个函数 `isSubtreeRootOwner(N, U)`:
|
||||
- 输入:当前节点 `N`、当前用户 `U`;
|
||||
- 算法:根据节点的`code`(`nodes`表的字段`code`形如`001003002008`,表示该节点的祖先节点的`code`为`001`、`001003`、`001003002`)从数据库select出所有祖先节点的`owner`的`id`,判断当前用户`U`是否其中一员
|
||||
- 输出:true或false。
|
||||
- 在主体构造过程中:
|
||||
- 若`isSubtreeRootOwner(N, U)` 返回`true`,说明当前用户是该子树根节点的 `owner`,则加入:`('root_owner', NULL)`;
|
||||
- 否则不加入 `root_owner`。
|
||||
|
||||
最终,`P` 是一组主体元素(可能包含 user / group / role / everyone / parent_owner / root_owner)。
|
||||
|
||||
---
|
||||
|
||||
## 四、权限记录的分类:默认 vs 节点专属
|
||||
|
||||
在 `node_permission` 中,根据 `tree` 与 `node_id` 组合,可以区分三类规则:
|
||||
|
||||
1. **全局默认规则(对两棵树都生效)**
|
||||
|
||||
- 条件:`tree IS NULL AND node_id IS NULL`。
|
||||
- 语义:对 standards 和 projects 的所有节点都生效。
|
||||
2. **按树的默认规则**
|
||||
|
||||
- 条件:`tree = T AND node_id IS NULL`。
|
||||
- 语义:只对树 `T` 的所有节点生效。
|
||||
3. **节点专属规则**
|
||||
|
||||
- 条件:`tree = T AND node_id = N`。
|
||||
- 语义:只对树 `T` 上的节点 `N` 生效,用来覆盖默认设置。
|
||||
|
||||
> 说明:当存在`node_id > 0` 的规则时,**不使用 `tree IS NULL` 以及`node_id IS NULL` 的记录**,这两个规则仅用于默认规则。
|
||||
|
||||
**优先级规则(同一主体维度):**
|
||||
|
||||
对给定树 `T`、节点 `N`、主体 `(principal_type, principal_key)`,从最具体到最泛化依次为:
|
||||
|
||||
1. 节点专属规则:`tree = T AND node_id = N`;
|
||||
2. 树级默认规则:`tree = T AND node_id IS NULL`;
|
||||
3. 全局默认规则:`tree IS NULL AND node_id IS NULL`;
|
||||
4. 如果以上三类都不存在,则该主体对该节点“没有任何配置”,视为该主体不给任何权限。
|
||||
|
||||
---
|
||||
|
||||
### 五、典型场景下的 `INSERT` 示例
|
||||
|
||||
#### 1. 全局默认 everyone:所有人只能展开树结构
|
||||
|
||||
对 **两棵树所有节点** 生效(`tree IS NULL AND node_id IS NULL`):
|
||||
|
||||
```sql
|
||||
INSERT INTO node_permission (
|
||||
tree, node_id, principal_type, principal_key,
|
||||
can_list_children,
|
||||
can_add_child_folder, can_add_child_doc,
|
||||
can_delete_node, can_edit_node,
|
||||
can_read_doc, can_edit_doc, can_delete_doc,
|
||||
can_delete_child_node, can_edit_child_node
|
||||
) VALUES (
|
||||
NULL, NULL, 'everyone', NULL,
|
||||
1,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0
|
||||
);
|
||||
```
|
||||
|
||||
#### 2. 全局默认 parent_owner:父节点 owner 管理直接子节点
|
||||
|
||||
对两棵树所有节点生效,表达“父节点 owner 默认可以管理直接子节点”和“看子列表”:
|
||||
|
||||
```sql
|
||||
INSERT INTO node_permission (
|
||||
tree, node_id, principal_type, principal_key,
|
||||
can_list_children,
|
||||
can_add_child_folder, can_add_child_doc,
|
||||
can_delete_node, can_edit_node,
|
||||
can_read_doc, can_edit_doc, can_delete_doc,
|
||||
can_delete_child_node, can_edit_child_node
|
||||
) VALUES (
|
||||
NULL, NULL, 'parent_owner', NULL,
|
||||
1,
|
||||
1, 1,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
1, 1 -- 修改直接子节点
|
||||
);
|
||||
```
|
||||
|
||||
#### 3. 全局默认 root_owner:子树根节点 owner 管理整棵子树
|
||||
|
||||
比如项目负责人(子树根的 owner)对整棵子树有较大权限:
|
||||
|
||||
```sql
|
||||
INSERT INTO node_permission (
|
||||
tree, node_id, principal_type, principal_key,
|
||||
can_list_children,
|
||||
can_add_child_folder, can_add_child_doc,
|
||||
can_delete_node, can_edit_node,
|
||||
can_read_doc, can_edit_doc, can_delete_doc,
|
||||
can_delete_child_node, can_edit_child_node
|
||||
) VALUES (
|
||||
NULL, NULL, 'root_owner', NULL,
|
||||
1,
|
||||
1, 1,
|
||||
1, 1,
|
||||
1, 1, 1,
|
||||
1, 1
|
||||
);
|
||||
```
|
||||
|
||||
4. standards 专用默认:技术标准管理员(角色 sAdmin)全权管理 standards
|
||||
|
||||
只对 standards 生效(projects 不受影响):
|
||||
|
||||
```sql
|
||||
INSERT INTO node_permission (
|
||||
tree, node_id, principal_type, principal_key,
|
||||
can_list_children,
|
||||
can_add_child_folder, can_add_child_doc,
|
||||
can_delete_node, can_edit_node,
|
||||
can_read_doc, can_edit_doc, can_delete_doc,
|
||||
can_delete_child_node, can_edit_child_node
|
||||
) VALUES (
|
||||
'standards', NULL, 'role', 'sAdmin',
|
||||
1,
|
||||
1, 1,
|
||||
1, 1,
|
||||
1, 1, 1,
|
||||
1, 1
|
||||
);
|
||||
```
|
||||
|
||||
#### 5. projects 专用默认:项目管理员(角色 pAdmin)管理 projects
|
||||
|
||||
```sql
|
||||
INSERT INTO node_permission (
|
||||
tree, node_id, principal_type, principal_key,
|
||||
can_list_children,
|
||||
can_add_child_folder, can_add_child_doc,
|
||||
can_delete_node, can_edit_node,
|
||||
can_read_doc, can_edit_doc, can_delete_doc,
|
||||
can_delete_child_node, can_edit_child_node
|
||||
) VALUES (
|
||||
'projects', NULL, 'role', 'pAdmin',
|
||||
1,
|
||||
1, 1,
|
||||
1, 1,
|
||||
1, 1, 1,
|
||||
1, 1
|
||||
);
|
||||
```
|
||||
|
||||
#### 6. 超级管理员专用默认:
|
||||
|
||||
```sql
|
||||
INSERT INTO node_permission (
|
||||
tree, node_id, principal_type, principal_key,
|
||||
can_list_children,
|
||||
can_add_child_folder, can_add_child_doc,
|
||||
can_delete_node, can_edit_node,
|
||||
can_read_doc, can_edit_doc, can_delete_doc,
|
||||
can_delete_child_node, can_edit_child_node
|
||||
) VALUES (
|
||||
NULL, NULL, 'role', 'super',
|
||||
1,
|
||||
1, 1,
|
||||
1, 1,
|
||||
1, 1, 1,
|
||||
1, 1
|
||||
);
|
||||
```
|
||||
|
||||
#### 7. 某个敏感节点对 everyone 做节点专属覆盖
|
||||
|
||||
假设节点 id = 123,是一个敏感目录,希望 **everyone 在这个节点上完全没有权限(连展开都不行)**,但其它节点仍按默认规则:
|
||||
|
||||
```sql
|
||||
INSERT INTO node_permission (
|
||||
tree, node_id, principal_type, principal_key,
|
||||
can_list_children,
|
||||
can_add_child_folder, can_add_child_doc,
|
||||
can_delete_node, can_edit_node,
|
||||
can_read_doc, can_edit_doc, can_delete_doc,
|
||||
can_delete_child_node, can_edit_child_node
|
||||
) VALUES (
|
||||
'standards', 123, 'everyone', NULL,
|
||||
0,
|
||||
0, 0,
|
||||
0, 0,
|
||||
0, 0, 0,
|
||||
0, 0
|
||||
);
|
||||
```
|
||||
|
||||
由于这是 `tree='standards' AND node_id=123 AND principal_type='everyone'` 的节点专属记录,会**覆盖**对全局默认 `everyone` 的配置。
|
||||
|
||||
#### 8. 针对某个用户在单节点上授予完全权限
|
||||
|
||||
例如用户 id = 42,在节点 500 上拥有完全权限(不依赖角色/owner):
|
||||
|
||||
```sql
|
||||
INSERT INTO node_permission (
|
||||
tree, node_id, principal_type, principal_key,
|
||||
can_list_children,
|
||||
can_add_child_folder, can_add_child_doc,
|
||||
can_delete_node, can_edit_node,
|
||||
can_read_doc, can_edit_doc, can_delete_doc,
|
||||
can_delete_child_node, can_edit_child_node
|
||||
) VALUES (
|
||||
'projects', 500, 'user', '42',
|
||||
1,
|
||||
1, 1,
|
||||
1, 1,
|
||||
1, 1, 1,
|
||||
1, 1
|
||||
);
|
||||
```
|
||||
|
||||
## 六、计算“对某个节点的有效权限”的通用算法
|
||||
|
||||
我们定义一个抽象的“有效权限对象”,包含所有布尔权限字段:
|
||||
|
||||
- `can_list_children`
|
||||
- `can_add_child_folder`
|
||||
- `can_add_child_doc`
|
||||
- `can_delete_node`
|
||||
- `can_edit_node`
|
||||
- `can_read_doc`
|
||||
- `can_edit_doc`
|
||||
- `can_delete_doc`
|
||||
- `can_delete_child_node`
|
||||
- `can_edit_child_node`
|
||||
|
||||
记这个对象为 `R`,初始时这十个值全部为 `false`。
|
||||
|
||||
### 6.1 输入
|
||||
|
||||
计算函数需要的输入信息:
|
||||
|
||||
- 用户 id:`U`
|
||||
- 节点 id:`N`
|
||||
- 树标识:`T ∈ {'standards', 'projects'}`
|
||||
|
||||
### 6.2 步骤 1:构造主体集合 `P`
|
||||
|
||||
按照第二节“主体集合的构造”的规则,从 `U`、`N`、`node`/`groupUser`/`user` 表中计算出主体集合 `P`。
|
||||
|
||||
结果是若干个 `(principal_type, principal_key)` 的集合,例如:
|
||||
|
||||
- `('user', '12')`
|
||||
- `('group', '3')`
|
||||
- `('role', 'sAdmin')`
|
||||
- `('everyone', NULL)`(如果有一个全局everyone的配置以及对N节点的everyone配置,则只保留N节点自己的everyone配置)
|
||||
- `('parent_owner', NULL)`(如果满足条件)
|
||||
- `('root_owner', NULL)`(如果满足条件)
|
||||
|
||||
### 6.3 步骤 2:读取节点专属权限记录
|
||||
|
||||
在 `node_permission` 表中,查询**当前树 + 当前节点**的所有权限记录:
|
||||
|
||||
- 条件:`tree = T AND node_id = N`
|
||||
|
||||
结果是一组行,每行包含:
|
||||
|
||||
- `principal_type`
|
||||
- `principal_key`
|
||||
- 十个 `can_*` 布尔字段
|
||||
|
||||
这组记录可以在内存中按 `(principal_type, principal_key)` 组织成一个映射结构,后面用来快速查找:
|
||||
|
||||
- 键:某个主体 `(principal_type, principal_key)`
|
||||
- 值:对应的一行权限记录。
|
||||
|
||||
### 6.4 步骤 3:读取默认权限记录(树级 + 全局)
|
||||
|
||||
在 `node_permission` 表中,查询**当前树相关的所有默认权限记录**:
|
||||
|
||||
- 条件:`(tree = T OR tree IS NULL) AND node_id IS NULL`
|
||||
|
||||
这些记录中:
|
||||
|
||||
- `tree = T` 的记录是“树级默认规则”;
|
||||
- `tree IS NULL` 的记录是“全局默认规则”。
|
||||
|
||||
在内存中同样按 `(principal_type, principal_key, tree)` 或类似结构组织,以便后续对同一主体区分“树级默认”和“全局默认”。
|
||||
|
||||
### 6.5 步骤 4:按主体合并权限(带 tree 优先级)
|
||||
|
||||
对主体集合中的每一个主体 `p = (ptype, pkey)` 执行如下逻辑:
|
||||
|
||||
1. **查找节点专属记录**
|
||||
|
||||
- 在“节点专属映射”中查找键 `(ptype, pkey)` 对应的记录。
|
||||
- 若存在,则记为 `row_node`。
|
||||
2. **查找树级默认记录**
|
||||
|
||||
- 在“默认映射”中查找满足:
|
||||
- `principal_type = ptype`
|
||||
- `principal_key = pkey`
|
||||
- `tree = T`
|
||||
- 若存在,则记为 `row_tree_default`。
|
||||
3. **查找全局默认记录**
|
||||
|
||||
- 在“默认映射”中查:
|
||||
- `principal_type = ptype`
|
||||
- `principal_key = pkey`
|
||||
- `tree IS NULL`
|
||||
- 若存在,则记为 `row_global_default`。
|
||||
4. **确定权限**
|
||||
|
||||
- 如果 `row_node`存在用户`U` 的记录:使用 `row_node`中用户`U`的特定权限配置,其它配置全部忽略;
|
||||
- 否则将`row_node`、 `row_tree_default`、`row_global_default`中的所有权限做并集,即只要其中一个赋予了权限,就有该权限,相应地给权限对象R赋值。
|
||||
|
||||
---
|
||||
|
||||
## 七、针对具体操作的鉴权规则
|
||||
|
||||
### 7.1 展开节点 / 查看子节点列表
|
||||
|
||||
**操作:** 展开节点 `N`,列出其直接子节点。
|
||||
|
||||
- 判断方法:
|
||||
- 根据 `U, N, T` 计算一次有效权限 `R`。
|
||||
- 若 `R.can_list_children == true`,则允许展开;否则禁止。
|
||||
|
||||
### 7.2 在节点下创建子文件夹 / 子文档
|
||||
|
||||
**操作:** 在节点 `N` 下创建子节点:
|
||||
|
||||
- 创建文件夹:新子节点 `node_type = 'folder'`。
|
||||
- 创建文档:新子节点 `node_type = 'doc'`。
|
||||
|
||||
**判断方法:**
|
||||
|
||||
- 先对父节点 `N` 计算有效权限 `R`。
|
||||
- 创建文件夹时:
|
||||
- 允许条件:`R.can_add_child_folder == true`。
|
||||
- 创建文档时:
|
||||
- 允许条件:`R.can_add_child_doc == true`。
|
||||
|
||||
### 7.3 修改节点自身(重命名、改 owner 等)
|
||||
|
||||
**操作:** 修改节点 `N` 本身的元数据(名称、owner、排序等)。
|
||||
|
||||
**判断方法:**
|
||||
|
||||
- 对节点 `N` 计算有效权限 `R`。
|
||||
- 允许条件:`R.can_edit_node == true`。
|
||||
|
||||
### 7.4 删除节点自身
|
||||
|
||||
**操作:** 删除节点 `N` 本身。
|
||||
|
||||
**判断方法:**
|
||||
|
||||
- 对节点 `N` 计算有效权限 `R`。
|
||||
- 允许条件:`R.can_delete_node == true`。
|
||||
|
||||
### 7.5 文档内容的读取 / 编辑 / 删除
|
||||
|
||||
假设节点 `N` 是一个文档节点(`node_type = 'doc'`)。
|
||||
|
||||
- **读取文档内容:**
|
||||
|
||||
- 对节点 `N` 计算有效权限 `R`。
|
||||
- 允许条件:`R.can_read_doc == true`。
|
||||
- **编辑文档内容:**
|
||||
|
||||
- 对节点 `N` 计算有效权限 `R`。
|
||||
- 允许条件:`R.can_edit_doc == true`。
|
||||
- **删除文档文档节点:**
|
||||
|
||||
- 对节点 `N` 计算有效权限 `R`。
|
||||
- 允许条件:`R.can_delete_doc == true` 。
|
||||
|
||||
### 7.6 删除子节点
|
||||
|
||||
**操作:** 在父节点 `P` 下,删除一个直接子节点 `C`(`C.parent = P`)。
|
||||
|
||||
- 允许条件:父节点 `P` 上的 `can_delete_child_node== true`;
|
||||
|
||||
### 7.7 修改子节点(name / owner 等)
|
||||
|
||||
**操作:** 在父节点 `P` 下,修改直接子节点 `C` 的元数据(名称、owner 等)。
|
||||
|
||||
- 允许条件:父节点 `P` 上的`can_edit_child_node== true`;
|
||||
526
docs/设计文档.docx
526
docs/设计文档.docx
|
|
@ -1,8 +1,139 @@
|
|||
设计文档
|
||||
树形结构:
|
||||
|
||||
表结构
|
||||
node:节点表:
|
||||
1、表结构:
|
||||
departments:部门表
|
||||
字段名
|
||||
含义
|
||||
类型
|
||||
说明
|
||||
id
|
||||
|
||||
int
|
||||
自增、主键
|
||||
name
|
||||
部门名称
|
||||
varchar(50)
|
||||
|
||||
head
|
||||
部门领导id
|
||||
int
|
||||
外键,用户表id,可为空
|
||||
reviewer
|
||||
部门审核负责人id
|
||||
int
|
||||
外键,用户表id,可为空
|
||||
parent
|
||||
父节点ID
|
||||
int
|
||||
为0表示1级节点。外键,本表id
|
||||
sort_order
|
||||
排序权重
|
||||
int
|
||||
越小越靠前
|
||||
create_time
|
||||
创建时间
|
||||
time
|
||||
|
||||
|
||||
departMember:部门人员表
|
||||
字段名
|
||||
含义
|
||||
类型
|
||||
说明
|
||||
id
|
||||
|
||||
int
|
||||
自增、主键
|
||||
department
|
||||
部门id
|
||||
int
|
||||
外键,部门表的id
|
||||
member
|
||||
人员id
|
||||
int
|
||||
外键,用户表id
|
||||
|
||||
users:用户表
|
||||
字段名
|
||||
含义
|
||||
类型
|
||||
说明
|
||||
id
|
||||
|
||||
int
|
||||
自增、主键
|
||||
username
|
||||
登录账号
|
||||
varchar(40)
|
||||
|
||||
password
|
||||
登录密码
|
||||
varchar(255)
|
||||
密码通过Argon2算法hash的结果
|
||||
number
|
||||
工号
|
||||
varchar(50)
|
||||
|
||||
name
|
||||
姓名
|
||||
varchar(20)
|
||||
|
||||
phone
|
||||
电话号码
|
||||
varchar(20)
|
||||
|
||||
email
|
||||
电子邮箱
|
||||
varchar(40)
|
||||
|
||||
department
|
||||
部门
|
||||
int
|
||||
外键,部门表的id
|
||||
role
|
||||
角色
|
||||
varchar(30)
|
||||
super:超级管理员,拥有所有权限、
|
||||
sAdmin:技术标准管理员,可以管理standards树
|
||||
pAdmin:项目管理员,可以管理projects树
|
||||
user:普通管理员。
|
||||
|
||||
groups:用户组表
|
||||
字段名
|
||||
含义
|
||||
类型
|
||||
说明
|
||||
id
|
||||
|
||||
int
|
||||
自增、主键
|
||||
groupname
|
||||
组名
|
||||
varchar(40)
|
||||
|
||||
description
|
||||
描述
|
||||
varchar(1000)
|
||||
|
||||
|
||||
groupUser:组用户表
|
||||
字段名
|
||||
含义
|
||||
类型
|
||||
说明
|
||||
id
|
||||
|
||||
int
|
||||
自增、主键
|
||||
group_id
|
||||
组id
|
||||
int
|
||||
外键
|
||||
user_id
|
||||
用户id
|
||||
int
|
||||
外键
|
||||
|
||||
nodes:节点表:
|
||||
字段名
|
||||
含义
|
||||
类型
|
||||
|
|
@ -23,21 +154,25 @@ node_type
|
|||
类型
|
||||
VARCHAR(10)
|
||||
以下之一:folder、doc,folder下允许添加folder和doc节点,doc节点只能作为文档编辑(其下不能添加节点)
|
||||
owner_id
|
||||
owner
|
||||
所有者id
|
||||
int
|
||||
外键,用户表id
|
||||
reviewer
|
||||
评审人
|
||||
int
|
||||
外键,用户表id
|
||||
title
|
||||
标题
|
||||
varchar(50)
|
||||
|
||||
|
||||
parent_id
|
||||
parent
|
||||
父节点ID
|
||||
int
|
||||
为0表示1级节点
|
||||
为0表示1级节点。外键,本表id
|
||||
sort_order
|
||||
排序权重
|
||||
|
||||
int
|
||||
越小越靠前
|
||||
create_time
|
||||
创建时间
|
||||
|
|
@ -46,17 +181,22 @@ time
|
|||
hierarchy
|
||||
层次
|
||||
int
|
||||
product scenario及子树:1
|
||||
product definition及子树:2
|
||||
product target及子树:3
|
||||
attribute, function及子树:4
|
||||
system及子树:5
|
||||
component及子树:6
|
||||
product scenario及子树:10
|
||||
product definition及子树:20
|
||||
product target及子树:30
|
||||
attribute及子树:40
|
||||
function及子树:41
|
||||
system及子树:50
|
||||
component及子树:60
|
||||
projects及创建的子树(不包括branch的子树):0
|
||||
content
|
||||
内容
|
||||
|
||||
varchar(10000)
|
||||
存储富文本文档的内容
|
||||
version
|
||||
版本
|
||||
varchar(50)
|
||||
文档的当前版本
|
||||
last_change
|
||||
最后修改时间
|
||||
time
|
||||
|
|
@ -69,18 +209,17 @@ ref_id
|
|||
引用的文档节点id
|
||||
|
||||
外键,本表的id
|
||||
task_type
|
||||
分工类型
|
||||
varchar(15)
|
||||
以下之一:project、standards。MainTree下的结点均为standards,Projects下的结点均为project
|
||||
tree_type
|
||||
所述树
|
||||
varchar(30)
|
||||
以下之一:standards、projects
|
||||
source_type
|
||||
文档来源类型
|
||||
varchar(10)
|
||||
enum
|
||||
如果ref_id不为空,则为以下之一:map, clone
|
||||
map_version
|
||||
map的版本id
|
||||
int
|
||||
外键,docVersion表的id,如果source_type为map才有值
|
||||
说明:
|
||||
1、预先创建树形结构一级节点product scenario, product definition, product target, attribute, function, system, component,赋好层次的值hierarchy。projects的层次值为0。
|
||||
2、sort_order的作用:每个节点下的所有n个子节点的sort_order为从1到n的值。支持调整显示顺序,sort_order小的显示在前。在界面上允许拖拽调整顺序,拖拽的目的地不能改变父节点。
|
||||
|
||||
docVersion:文档版本表
|
||||
字段名
|
||||
|
|
@ -91,65 +230,340 @@ id
|
|||
|
||||
int
|
||||
自增、主键
|
||||
doc_id
|
||||
doc
|
||||
文档节点id
|
||||
int
|
||||
外键,node表的id
|
||||
version
|
||||
版本号
|
||||
varchar(20)
|
||||
xxx.yyy.zzz形式,xxx为public的大版本、yyy为release的小版本、zzz为review的微版本,分别从1开始编号
|
||||
xxx.yyy形式,xxx为release的大版本、yyy为review的小版本
|
||||
owner
|
||||
所有者id
|
||||
int
|
||||
外键,用户表id
|
||||
title
|
||||
标题
|
||||
varchar(50)
|
||||
|
||||
create_time
|
||||
创建时间
|
||||
time
|
||||
创建该版本的时间
|
||||
content
|
||||
内容
|
||||
varchar(10000)
|
||||
|
||||
last_change
|
||||
最后修改时间
|
||||
time
|
||||
|
||||
last_change_by
|
||||
最后修改人id
|
||||
int
|
||||
|
||||
type
|
||||
版本类型
|
||||
enum
|
||||
包含:review、release两种
|
||||
|
||||
docReviewRequest:文档审核请求表
|
||||
字段名
|
||||
含义
|
||||
类型
|
||||
说明
|
||||
id
|
||||
|
||||
int
|
||||
自增、主键
|
||||
doc
|
||||
源文档节点id
|
||||
int
|
||||
外键,node表的id
|
||||
version
|
||||
review针对的版本
|
||||
int
|
||||
外键, docVersion 表的id
|
||||
submitter
|
||||
提交人id
|
||||
int
|
||||
外键,user表的id
|
||||
submit_comment
|
||||
提交时附言
|
||||
varchar(3000)
|
||||
|
||||
submitted_at
|
||||
提交时间
|
||||
time
|
||||
|
||||
reviewer
|
||||
审核人id
|
||||
int
|
||||
外键,user表的id
|
||||
review_comment
|
||||
审核意见
|
||||
varchar(3000)
|
||||
|
||||
review_at
|
||||
审核时间
|
||||
time
|
||||
|
||||
status
|
||||
状态
|
||||
varchar(30)
|
||||
包含: Pending、Approved、Rejected
|
||||
|
||||
docMap:文档map表
|
||||
字段名
|
||||
含义
|
||||
类型
|
||||
说明
|
||||
id
|
||||
|
||||
int
|
||||
自增、主键
|
||||
src_doc
|
||||
源文档节点id
|
||||
int
|
||||
外键,node表的id
|
||||
dest_folder
|
||||
目标文件夹节点id
|
||||
int
|
||||
外键,node表的id
|
||||
dest_doc
|
||||
目标文档节点id
|
||||
int
|
||||
外键,node表的id
|
||||
version
|
||||
map所使用的版本
|
||||
int
|
||||
外键, docVersion 表的id
|
||||
create_time
|
||||
创建时间
|
||||
time
|
||||
|
||||
current_status
|
||||
当前状态
|
||||
varchar(32)
|
||||
包含:
|
||||
pendingReceive : 已发起,等待接收方处理
|
||||
received : 接收方处理中
|
||||
pendingReview : 接收方已提交给其领导评审
|
||||
pendingApprove : 接收方领导已 review 通过,等待部门领导 approve
|
||||
accepted : 部门领导 approve 完成
|
||||
rejected : 驳回
|
||||
cancelled : 撤回
|
||||
update_time
|
||||
最后一次更新时间
|
||||
time
|
||||
|
||||
next_op_user
|
||||
待处理人
|
||||
int
|
||||
外键,user表的id
|
||||
|
||||
docMapHandshake:文档map握手记录表
|
||||
字段名
|
||||
含义
|
||||
类型
|
||||
说明
|
||||
id
|
||||
|
||||
int
|
||||
自增、主键
|
||||
map_id
|
||||
docMap的记录id
|
||||
int
|
||||
外键,docMap表的id
|
||||
action
|
||||
操作
|
||||
varchar(32)
|
||||
本步骤所做的处理,包括:
|
||||
map : 发起 map
|
||||
receive : 接收方确认接收
|
||||
reject : 接收方驳回
|
||||
submitReview : 接收方提交领导审核
|
||||
ReviewPass: 接收方领导 review 通过
|
||||
ReviewReject: 接收方领导驳回
|
||||
ApprovePass : 接收方部门领导 approve通过
|
||||
ApproveReject : 接收方部门领导驳回
|
||||
from_status
|
||||
变更前状态
|
||||
varchar(32)
|
||||
第一次创建时为 NULL
|
||||
to_status
|
||||
变更后状态
|
||||
varchar(32)
|
||||
|
||||
op_user
|
||||
操作人
|
||||
int
|
||||
外键,user表的id
|
||||
comments
|
||||
备注
|
||||
varchar(3000)
|
||||
|
||||
op_time
|
||||
创建时间
|
||||
time
|
||||
|
||||
due_time
|
||||
截止时间
|
||||
time
|
||||
如果状态是received,due_time是本方承诺的处理时间,如果状态是rejected,due_time是希望对方处理的截止时间
|
||||
|
||||
node_permission:节点访问权限表
|
||||
字段名
|
||||
含义
|
||||
类型
|
||||
说明
|
||||
id
|
||||
|
||||
int
|
||||
自增、主键
|
||||
tree
|
||||
树
|
||||
VARCHAR(32)
|
||||
standards : 只对standards生效
|
||||
projects : 只对 projects 生效
|
||||
NULL : 两棵树都生效(全局规则)
|
||||
node
|
||||
节点id
|
||||
int
|
||||
NULL : 默认权限(作用范围由 tree 决定)
|
||||
> 0 : 某个具体节点的专属权限
|
||||
|
||||
principal_type
|
||||
主体类型
|
||||
varchar(30)
|
||||
以下之一: user, group, role, everyone, parent_owner, root_owner
|
||||
principal_key
|
||||
主体标识
|
||||
varchar(30)
|
||||
根据principal_type不同,具有不同的值:user : 用户(user.id)
|
||||
group : 用户组(group.id)
|
||||
role : 角色(如 super/sAdmin/pAdmin)
|
||||
everyone/parent_owner/root_owner:固定为 NULL
|
||||
can_list_children
|
||||
查看子节点列表
|
||||
TINYINT(1)
|
||||
DEFAULT 0,
|
||||
can_add_child_folder
|
||||
在节点下创建文件夹
|
||||
TINYINT(1)
|
||||
DEFAULT 0,
|
||||
can_add_child_doc
|
||||
在节点下创建文档
|
||||
TINYINT(1)
|
||||
DEFAULT 0,
|
||||
can_delete_node
|
||||
删除节点
|
||||
TINYINT(1)
|
||||
DEFAULT 0,
|
||||
can_edit_node
|
||||
修改节点元数据
|
||||
TINYINT(1)
|
||||
DEFAULT 0,
|
||||
can_read_doc
|
||||
读取文档内容
|
||||
TINYINT(1)
|
||||
DEFAULT 0,
|
||||
can_edit_doc
|
||||
修改文档内容
|
||||
TINYINT(1)
|
||||
DEFAULT 0,
|
||||
can_delete_doc
|
||||
删除文档
|
||||
TINYINT(1)
|
||||
DEFAULT 0,
|
||||
can_delete_child_node
|
||||
删除子节点
|
||||
TINYINT(1)
|
||||
DEFAULT 0,
|
||||
can_edit_child_node
|
||||
修改子节点元数据
|
||||
TINYINT(1)
|
||||
DEFAULT 0,
|
||||
update_time
|
||||
修改时间
|
||||
time
|
||||
|
||||
|
||||
操作:
|
||||
1、预先创建树形结构一级节点product scenario, product definition, product target, attribute, function, system, component,赋好层次的值hierarchy。projects的层次值为0。
|
||||
2、sort_order的作用:每个节点下的所有n个子节点的sort_order为从1到n的值。支持调整显示顺序,sort_order小的显示在前。在界面上允许拖拽调整顺序,拖拽的目的地不能改变父节点。
|
||||
3、节点的右键菜单:
|
||||
2、系统功能
|
||||
2.1 管理员功能
|
||||
系统预先创建超级管理员,超级管理员具有全部权限,技术标准管理员可以管理部门、用户和standards树,项目管理员可以管理部门、用户和projects树。
|
||||
2.1.1 管理部门
|
||||
界面分为左右两部分。
|
||||
界面左部为部门,显示为一个树形结构,树根为公司名称,可在树形节点上操作:添加下级部门、添加同级部门、修改。
|
||||
添加新部门时,需要输入部门名称,部门领导、审核负责人可暂时不选择。
|
||||
选中某个部门时,在界面右部显示部门名称、领导及审核负责人,其下为一个表格,显示部门成员。
|
||||
如果一个部门有下级部门,则不能有部门成员,有部门成员则不能有下级部门。
|
||||
2.1.2 创建用户
|
||||
创建用户界面需要输入:用户名、密码、工号、姓名、电话号码、email、部门、角色,其中工号、电话号码、email、部门可为空,密码默认为ABC123.com。
|
||||
如果操作人是超级管理员,角色单选按钮三选一:技术标准管理员、项目管理员、普通管理员。
|
||||
如果操作人是技术标准管理员或项目管理员,角色按钮隐藏,只能为普通管理员。
|
||||
使用 Argon2 进行密码哈希。
|
||||
2.1.3 用户管理
|
||||
可以通过输入工号、姓名、部门进行联合模糊查询,使用表格显示查询结果,表格头可以点击排序(排序时要求从数据库重新查询,不能仅针对该页排序),默认按姓名升序排列。
|
||||
表格第一列为复选框,可以多选进行删除。表格每一行有两个按钮:编辑、删除。
|
||||
2.1.4 用户组管理
|
||||
界面分为左右两部分。
|
||||
界面左部为用户组列表,在列表的上部能根据名称进行查询,有添加、删除、编辑按钮。可以在列表中多选以删除。
|
||||
界面右部为用户列表,包含序号、工号、姓名、电话、email共5列。在用户组列表里选择一行时,右部用户列表显示该组的所有成员。对组里的成员,有添加、删除按钮。
|
||||
2.2 树节点管理
|
||||
2.2.1 树结构介绍:
|
||||
hierarchy=0
|
||||
hierarchy>0
|
||||
hierarchy>0
|
||||
|
||||
总共包含4棵树:Inbox(收件箱)Outbox(发件箱)、Standards(技术标准)、Projects(项目)。
|
||||
(1)根节点没有"添加同级节点"
|
||||
(2)node_type为doc的节点没有"添加下级节点"(文档下不能添加子节点)
|
||||
(3)ref_id不为空的节点没有"edit"(即不能编辑引用自其它文档的文档)
|
||||
(4)node_type为folder的节点没有"copy to"、"clone to"和"map to"(这三个操作仅针对文档)。task_type为standards的节点没有"map to"(projects树下的文档才可map)。
|
||||
(5)hierarchy为0的节点以及node_type为doc的节点没有"branch to"(hierarchy大于0的节点包括maintree里的节点或者从maintree里branch到projects的节点)
|
||||
4、创建节点(添加同级节点、添加下级节点)界面如下:
|
||||
(4)node_type为folder的节点没有"copy to"、"clone to"和"map to"(这三个操作仅针对文档)。字段tree为standards的节点没有"map to"(projects树下的文档才可map)。
|
||||
(5)hierarchy为0的节点以及node_type为doc的节点没有"branch to"(hierarchy大于0的节点包括standards树里的节点或者从standards里branch到projects的节点)
|
||||
2.2.2 创建节点(添加同级节点、添加下级节点)界面如下:
|
||||
|
||||
界面上输入title、node_type、owner(从用户列表里选择),在保存时,自动生成id、uuid、sort_order、create_time,获取parent_id、继承父节点的hierarchy、task_type。
|
||||
界面上输入title、node_type、owner(从用户列表里选择)、reviewer(document类型才有reviewer,从用户列表里选择),在保存时,自动生成id、uuid、sort_order、create_time,获取parent、继承父节点的hierarchy、task_type。content、last_change、last_change_by、ref_id、source_type为空。
|
||||
code生成方法:按照节点级别编号,一级节点的编号为000,001,002,003,004;二级节点的编号为001000,001001,001002,001003,这4个编号表明节点都是编号001的子节点。001的二级节点的编号从001000到001999,如果中间某些code被删除而导致缺失,则在添加了001999后,绕回到001000及之后的缺失编号。说明:000到999不要求连续(删除后可以缺失),不要求排序(大编号在小编号之前也可以)
|
||||
sort_order生成方法:如果是添加下级节点,则新节点的sort_order为已有下级节点最大sort_order加1。如果是添加同级节点,则新节点的sort_order为操作节点的sort_order加1(即添加到操作节点的后面),同一父节点的后面的所有节点sort_order都需要加1。
|
||||
5、edit菜单:只能修改title和owner
|
||||
6、delete菜单:
|
||||
2.2.3 edit菜单
|
||||
只能修改title、owner和reviewer。
|
||||
2.2.4 delete菜单:
|
||||
node_type为doc的节点,如果有其它节点的ref_id指向自己,则提示"有其它文档由本文档clone或map,不能删除"。如果存在外键指向自己,则提示"存在外键约束,不能删除"。
|
||||
node_type为folder的节点,如果以该节点为根的子树上存在文档,则提示"请先删除子树上的文档,才能删除本文件夹"。
|
||||
7、copy to菜单(复制节点):
|
||||
选中一个doc节点,点击copy to时,弹出界面,要求选择maintree或projects里的一个folder节点(需要检查操作人员是否对该节点有write权限),点击确认,即执行copy操作。
|
||||
node_type为folder的节点,如果以该节点为根的子树上存在文档,则提示"请先删除子树上的文档,才能删除本文件夹"。删除文件夹时,需要删除整棵子树。
|
||||
2.2.5 copy to/from菜单(复制节点):
|
||||
选中一个doc节点(要求对该节点有can_read_doc权限),点击右键菜单copy to时,弹出界面,要求选择standards或projects里的一个folder节点(要求对该节点有can_add_child_doc权限),输入owner(默认是所选folder节点的owner)和reviewer,点击确认,即执行copy操作。
|
||||
copy将在数据库中添加新记录,其中:
|
||||
parent_id为目标folder节点的id。
|
||||
parent为目标folder节点的id。
|
||||
code根据parent folder的code添加3位,生成规则见"创建新节点"。
|
||||
owner_id、task_type、hierarchy与parent folder的owner_id、task_type、hierarchy相同
|
||||
task_type、hierarchy与parent folder的task_type、hierarchy相同
|
||||
id、uuid、sort_order(添加为最后一个节点)、create_time(为当前时间)根据规则生成。
|
||||
字段:node_type、title、content、last_change、last_change_by、ref_id、source_type、map_version从选中的doc节点复制。
|
||||
8、clone to菜单(对节点添加引用):
|
||||
选中一个doc节点,点击clone to时,弹出界面,要求选择maintree或projects里的一个folder节点(需要检查操作人员是否对该节点有write权限),点击确认,即执行clone操作。
|
||||
字段:node_type、title、content、last_change、last_change_by、ref_id、source_type从选中的doc节点复制。
|
||||
相应有个copy from菜单,选中一个folder节点(要求对该节点有can_add_child_doc权限),点击右键菜单copy from时,弹出界面,要求选择standards或projects里的一个doc节点(要求对该节点有can_read_doc权限),输入owner(默认是所选folder节点的owner)和reviewer,点击确认,即执行copy操作。
|
||||
2.2.6 clone to/from菜单(对节点添加引用):
|
||||
选中一个doc节点(要求对该节点有can_read_doc权限),点击clone to时,弹出界面,要求选择standards或projects里的一个folder节点(要求对该节点有can_add_child_doc权限),输入owner(默认是所选folder节点的owner),无需reviewer,点击确认,即执行clone操作。
|
||||
clone将在数据库中添加新记录,其中:
|
||||
parent_id为目标folder节点的id。
|
||||
parent为目标folder节点的id。
|
||||
code根据parent folder的code添加3位,生成规则见"创建新节点"。
|
||||
owner_id、task_type、hierarchy与parent folder的owner_id、task_type、hierarchy相同
|
||||
task_type、hierarchy与parent folder的task_type、hierarchy相同
|
||||
id、uuid、sort_order(添加为最后一个节点)根据规则生成。
|
||||
如果选中doc节点的ref_id为空,则新记录的ref_id为该doc的id,source_type为clone,map_version为空;如果选中doc节点的ref_id不为空,则新记录的ref_id复制该doc的ref_id,source_type为clone,map_version为空
|
||||
title、content、last_change、last_change_by为空,在select检索时根据ref_id获取。
|
||||
如果选中doc节点的ref_id为空,则新记录的ref_id为该doc的id,source_type为clone;如果选中doc节点的ref_id不为空,则新记录的ref_id复制该doc的ref_id,source_type为clone
|
||||
reviewer、title、content、last_change、last_change_by为空,在select检索时根据ref_id获取。
|
||||
字段:node_type、create_time从选中的doc节点复制。
|
||||
(疑问:map的节点能否被copy和clone?)
|
||||
9、branch to菜单(复制子树):
|
||||
选中一个folder节点,点击branch to时,弹出界面,要求选择projects里hierarchy为0的一个folder节点(需要检查操作人员是否对该节点有write权限),点击确认,即执行复制操作。
|
||||
相应有个clone from菜单,选中一个folder节点(要求对该节点有can_add_child_doc权限),点击右键菜单clone from时,弹出界面,要求选择standards或projects里的一个doc节点(要求对该节点有can_read_doc权限),输入owner(默认是所选folder节点的owner),无需reviewer,点击确认,即执行copy操作。
|
||||
2.2.7 branch from菜单(复制子树):
|
||||
选中projects树里hierarchy为0的一个folder节点(要求对该节点有can_add_child_doc和can_add_child_folder权限),点击branch from时,弹出界面,在界面左部显示standards和projects树,standards树里的所有节点以及projects里hierarchy>0的所有节点前都有一个复选框,可以选择若干节点,为每个选择的节点指定owner、为每个ref_id为空的文档节点指定reviewer,点击确认,即执行复制操作。
|
||||
复制将在数据库中添加新记录,需要逐层添加,先添加被复制子树的根节点,再添加它的子孙节点。
|
||||
其中根节点复制到目标folder的下面。对于根节点:
|
||||
parent_id为目标folder节点的id。
|
||||
parent为目标folder节点的id。
|
||||
code根据parent folder的code添加3位,生成规则见"创建新节点"。
|
||||
owner_id、task_type与parent folder的owner_id、task_type相同
|
||||
task_type与parent folder的task_type相同。
|
||||
owner、reviewer由界面上获取。
|
||||
id、uuid、sort_order(添加为最后一个节点)、create_time(为当前时间)根据规则生成。
|
||||
字段:node_type、hierarchy、title、content、last_change、last_change_by、ref_id、source_type、map_version从选中的doc节点复制。
|
||||
字段:node_type、hierarchy、title、content、last_change、last_change_by、ref_id、source_type从选中的doc节点复制。
|
||||
以下每层节点在复制时,注意它的parent folder为复制过来的那个parent,id为新创建的。code也根据新的parent folder的code添加3位。其它复制规则同上。
|
||||
8、map to菜单:
|
||||
2.2.8 map to菜单:
|
||||
|
||||
|
||||
|
||||
|
|
@ -947,7 +947,7 @@ const handleAddSibling = () => {
|
|||
console.log('parentNode found:', parentNode)
|
||||
|
||||
// 打开添加节点对话框
|
||||
// 如果没有父节点(Main Tree层级),则使用空字符串作为parentNodeId
|
||||
// 如果没有父节点,则使用空字符串作为parentNodeId
|
||||
addNodeDialog.value = {
|
||||
show: true,
|
||||
mode: 'sibling',
|
||||
|
|
|
|||
Loading…
Reference in New Issue