修改右键菜单、创建新节点

This commit is contained in:
Qiubo Huang 2026-02-09 21:34:29 +08:00
parent de98e82461
commit eaad38508c
2 changed files with 32 additions and 24 deletions

View File

@ -10,26 +10,38 @@ node:节点表:
id
int
AUTO_INCREMENT PRIMARY KEY
自增、主键
uuid
节点标识
VARCHAR(36)
type
code
编号
VARCHAR(150)
按照节点级别编号一级节点的编号为000,001,002,003,004;二级节点的编号为001000,001001,001002,001003这4个编号表明节点都是编号001的子节点
node_type
类型
VARCHAR(50)
以下之一product scenario, product definition, product target, attribute, function, system, component
VARCHAR(10)
以下之一:folder、docfolder下允许添加folder和doc节点doc节点只能作为文档编辑其下不能添加节点
owner_id
所有者id
int
用户表id
外键,用户表id
title
标题
parent_id
父节点ID
int
为0表示1级节点
sort_order
排序权重
越小越靠前
create_time
创建时间
TIMESTAMP
time
hierarchy
层次
@ -40,9 +52,37 @@ product target及子树3
attribute, function及子树4
system及子树5
component及子树6
说明预先创建树形结构一级节点product scenario, product definition, product target, attribute, function, system, component赋好层次的值。在创建子节点时继承父节点的层次值。
projects及创建的子树不包括branch的子树0
content
内容
node_relation: 节点关系表
存储富文本文档的内容
last_change
最后修改时间
time
last_change_by
最后修改人id
int
ref_id
引用的文档节点id
外键本表的id
task_type
分工类型
varchar(15)
以下之一project、standards。MainTree下的结点均为standardsProjects下的结点均为project
source_type
文档来源类型
varchar(10)
如果ref_id不为空则为以下之一map, clone
map_version
map的版本id
int
外键docVersion表的id如果source_type为map才有值
docVersion文档版本表
字段名
含义
类型
@ -50,38 +90,67 @@ node_relation: 节点关系表
id
int
AUTO_INCREMENT PRIMARY KEY
parent_id
父节点ID
自增、主键
doc_id
文档节点id
int
node表id为0表示1级节点
child_id
子节点ID
int
node表id
sort_order
排序权重
外键node表的id
version
版本号
varchar(20)
xxx.yyy.zzz形式xxx为public的大版本、yyy为release的小版本、zzz为review的微版本分别从1开始编号
越小越靠前
relation_type
关系类型
VARCHAR(20)
direct直接子节点reference引用节点。DEFAULT 'direct'
操作:
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、节点的右键菜单
1根节点没有"添加同级节点"
2node_type为doc的节点没有"添加下级节点"(文档下不能添加子节点)
3ref_id不为空的节点没有"edit"(即不能编辑引用自其它文档的文档)
4node_type为folder的节点没有"copy to"、"clone to"和"map to"这三个操作仅针对文档。task_type为standards的节点没有"map to"projects树下的文档才可map
5hierarchy为0的节点以及node_type为doc的节点没有"branch to"(hierarchy大于0的节点包括maintree里的节点或者从maintree里branch到projects的节点)
4、创建节点添加同级节点、添加下级节点界面如下
界面上输入title、node_type、owner从用户列表里选择在保存时自动生成id、uuid、sort_order、create_time获取parent_id、继承父节点的hierarchy、task_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菜单
node_type为doc的节点如果有其它节点的ref_id指向自己则提示"有其它文档由本文档clone或map不能删除"。如果存在外键指向自己,则提示"存在外键约束,不能删除"。
node_type为folder的节点如果以该节点为根的子树上存在文档则提示"请先删除子树上的文档,才能删除本文件夹"。
7、copy to菜单复制节点
选中一个doc节点点击copy to时弹出界面要求选择maintree或projects里的一个folder节点需要检查操作人员是否对该节点有write权限点击确认即执行copy操作。
copy将在数据库中添加新记录其中
parent_id为目标folder节点的id。
code根据parent folder的code添加3位生成规则见"创建新节点"。
owner_id、task_type、hierarchy与parent folder的owner_id、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操作。
clone将在数据库中添加新记录其中
parent_id为目标folder节点的id。
code根据parent folder的code添加3位生成规则见"创建新节点"。
owner_id、task_type、hierarchy与parent folder的owner_id、task_type、hierarchy相同
id、uuid、sort_order添加为最后一个节点根据规则生成。
如果选中doc节点的ref_id为空则新记录的ref_id为该doc的idsource_type为clonemap_version为空如果选中doc节点的ref_id不为空则新记录的ref_id复制该doc的ref_idsource_type为clonemap_version为空
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权限点击确认即执行复制操作。
复制将在数据库中添加新记录,需要逐层添加,先添加被复制子树的根节点,再添加它的子孙节点。
其中根节点复制到目标folder的下面。对于根节点
parent_id为目标folder节点的id。
code根据parent folder的code添加3位生成规则见"创建新节点"。
owner_id、task_type与parent folder的owner_id、task_type相同
id、uuid、sort_order添加为最后一个节点、create_time为当前时间根据规则生成。
字段node_type、hierarchy、title、content、last_change、last_change_by、ref_id、source_type、map_version从选中的doc节点复制。
以下每层节点在复制时注意它的parent folder为复制过来的那个parentid为新创建的。code也根据新的parent folder的code添加3位。其它复制规则同上。
8、map to菜单
确保同一父节点下,同一子节点不会重复添加:
UNIQUE KEY uk_parent_child (parent_id, child_id),
说明:
1.分离 nodes 和 node_relations的原因
支持DAG结构一个节点只能是一个父节点的direct子节点但可以是多个父节点的reference子节点。如果存在reference子节点那么不允许删除direct子节点。
2、sort_order的作用
支持调整显示顺序sort_order小的显示在前。在界面上允许拖拽调整顺序拖拽不能改变父节点。

View File

@ -670,7 +670,7 @@ const addNodeDialog = ref({
})
//
const nodeTypes = ['product scenario', 'product definition', 'product target', 'attribute', 'function', 'system', 'component']
const nodeTypes = ['folder', 'document']
const initExpanded = (nodes: TreeNode[]) => {
nodes.forEach(node => {
@ -1121,24 +1121,6 @@ defineExpose({
<!-- 右键菜单 -->
<div v-if="contextMenu.show" class="context-menu" :style="{ left: contextMenu.x + 'px', top: contextMenu.y + 'px' }"
@click.stop>
<div class="menu-group">
<div class="menu-item" :class="{ disabled: !isCopyEnabled(contextMenuNode) }"
@click="isCopyEnabled(contextMenuNode) && openOperationDialog('copy')">
<Copy :size="14" />
<span>Copy To...</span>
</div>
<div class="menu-item" :class="{ disabled: !isCloneEnabled(contextMenuNode) }"
@click="isCloneEnabled(contextMenuNode) && openOperationDialog('clone')">
<Database :size="14" />
<span>Clone To...</span>
</div>
<div class="menu-item" :class="{ disabled: !isBranchEnabled(contextMenuNode) }"
@click="isBranchEnabled(contextMenuNode) && openOperationDialog('branch')">
<GitBranch :size="14" />
<span>Branch To...</span>
</div>
</div>
<div class="menu-divider"></div>
<div class="menu-group">
<div class="menu-item" @click="handleAddSibling">
<CornerUpLeft :size="14" />
@ -1148,12 +1130,38 @@ defineExpose({
<CornerDownLeft :size="14" />
<span>添加下级节点</span>
</div>
<div class="menu-item delete" @click="handleDelete">
<Trash2 :size="14" />
<span>edit</span>
</div>
<div class="menu-item delete" @click="handleDelete">
<Trash2 :size="14" />
<span>Delete</span>
</div>
</div>
<div class="menu-divider"></div>
<div class="menu-group">
<div class="menu-item" :class="{ disabled: !isCopyEnabled(contextMenuNode) }"
@click="isCopyEnabled(contextMenuNode) && openOperationDialog('copy')">
<Copy :size="14" />
<span>Copy To...</span>
</div>
<div class="menu-item" :class="{ disabled: !isCloneEnabled(contextMenuNode) }"
@click="isCloneEnabled(contextMenuNode) && openOperationDialog('clone')">
<Database :size="14" />
<span>Clone To...</span>
</div>
<div class="menu-item" :class="{ disabled: !isBranchEnabled(contextMenuNode) }"
@click="isBranchEnabled(contextMenuNode) && openOperationDialog('branch')">
<GitBranch :size="14" />
<span>Branch To...</span>
</div>
<div class="menu-item" :class="{ disabled: !isBranchEnabled(contextMenuNode) }"
@click="isBranchEnabled(contextMenuNode) && openOperationDialog('branch')">
<GitBranch :size="14" />
<span>Map To...</span>
</div>
</div>
<div class="menu-divider"></div>
<div class="menu-item delete" @click="handleDelete">
<Trash2 :size="14" />
<span>Delete</span>
</div>
</div>
<!-- 添加节点对话框 -->