阅读之前
你应该:
- 熟悉模型的增删改查相关内容。【界面设计器】模型增删改查基础
名词解释
- 主体:在视图中提供数据源的主要组件,并且所有
动作
都围绕着该主体展开。 - 一级搜索:在
表格视图
中,上方直观可见的搜索区,为表格
提供筛选功能。 - 二级搜索:与一级搜索不同的是,其搜索条件是通过某些组件的行为追加到一级搜索条件之上的筛选功能。
概述
平台中对于左树右表提供了两种类型的展示形式。
在表格视图
中的左树右表
,是以表格
为主体,树组件
为表格提供了二级搜索
功能。选中树节点时将对表格
追加节点的搜索条件,并重新执行查询。
在树视图
中,是以树
为主体,其展开的视图可以是表格
、表单
、详情
等其他视图。
PS:不论是树、级联这些视图组件,还是树选择、级联这些字段组件,其配置数据结构的方式是不尽相同的。唯一的区别在于最终到达的目标模型来源不同。
场景1
为了方便接下来的描述,我们需要先构建一个基本的业务场景,这个场景中包含【商品】和【商品类目】两个模型。
在【商品】的表格
左侧添加【商品类目】树,选择某个商品类目后,可以根据商品类目进行筛选,查询所属类目下的全部商品。
其中【商品类目】使用【卡片级联】的展示方式进行管理。
其模型定义如下:
商品(Item)
名称 | API名称 | 业务类型 | 是否多值 | 长度(单值长度) | 关联模型 | 关联字段 | |
---|---|---|---|---|---|---|---|
ID | id | 整数 | 否 | - | - | - | - |
编码 | code | 文本 | 否 | 128 | - | - | - |
名称 | name | 文本 | 否 | 128 | - | - | |
所属类目 | category | 多对一 | 否 | - | 商品类目(ItemCategory) | categoryId - id | |
所属类目ID | categoryId | 整数 | 否 | - | - | - |
商品类目(ItemCategory)
名称 | API名称 | 业务类型 | 是否多值 | 长度(单值长度) | 关联模型 | 关联字段 | |
---|---|---|---|---|---|---|---|
ID | id | 整数 | 否 | 128 | - | - | |
编码 | code | 文本 | 否 | 128 | - | - | - |
名称 | name | 文本 | 否 | 128 | - | - | |
上级类目 | parent | 多对一 | 是 | - | 商品类目(ItemCategory) | parentId - id | |
上级类目ID | parentId | 整数 | 否 | - | - | - |
PS:实际业务场景中,【商品类目】通常使用编码
进行关联,即parentCode - code
;不仅如此,通常还会添加treeCode
字段,以此来实现高效查询当前节点的所有子节点的能力。在演示模型中,我们不必关注这些内容。
创建【商品】视图
设置联动关系
这里我们需要配置的是【商品类目】的树结构,因此,在【第1级关联】中的模型选择【商品类目】。
在【商品类目】中是通过【上级类目】进行的自关联,因此,在【第1级关联】中的【自关联关系字段】选择【上级类目】。
在选中【商品类目】节点后,需要对右侧表格发起查询。其筛选条件是通过【商品】中的【所属类目】进行筛选的。因此,在【第1级关联】中的【表格关联关系字段】选择【所属类目】。那么,在表格发起查询前,会根据【所属类目】字段的关联关系配置自动添加筛选条件。
配置如下图所示:
创建【商品类目】视图
设置联动关系
这里我们需要配置的是【商品类目】的树结构(级联只是树结构的另一种表现形式)
细心的同学可能发现这里没有【表格关联关系字段】,因此,我们仅需配置【自关联关系字段】即可。
配置如下图所示:
为【商品类目】添加增删改查基础功能
与表格视图不同的是,行内动作区
被放在了第一个卡片
中的动作区
,其他配置方式完全一致。
在这里需要理解的是,一个树节点对应的是表格中的一行。
【商品类目】使用展开视图进行编辑(可选)
打开【支持展开视图】开关,并设置展开视图。这里我们用表单
视图进行编辑操作。
和其他表单
一样,我们将必要的字段和动作拖入对应区域即可。
由于展开视图只会在选中
节点时出现,因此我们仅需提供更新
功能即可。
这里需要注意:
提交动作
默认打开了【返回上一页】的功能,在当前场景中,更新
动作提交数据后,没有上一页需要返回,因此需要关闭【返回上一页】的开关。提交动作
默认打开了【刷新当前视图】的功能,在当前场景中,更新
按钮处于【展开视图】中,仅刷新当前视图是不够的,当数据发生变更时,我们需要将级联组件一并刷新,因此需要打开【刷新主视图】的开关。
PS:【编辑】动作和【展开视图编辑】功能是重复的,在使用时应该只选择其中一种。
【商品类目】限制仅支持四级,并为每一个卡片添加标题(可选)
移除【第1级关联】中的【自关联关系字段】,依次添加2、3、4级关联,选择【商品类目】模型,将自动选中【层级关联关系字段】为【上级类目】,并输入每一级关联的标题即可。
这里需要注意的是,在【第1级关联】中需要添加筛选条件,使其只能查询到根节点。
PS:这里的限制仅为交互上的限制,在创建/更新时,如果可以在服务端限制上级类目
的选择,以及数据提交时的校验,效果更佳。
【商品类目】的【创建/编辑】使用弹窗打开(可选)
有时我们希望用户在页面中的操作尽可能的流畅,在表单规模较小的情况下,我们也可以使用【弹窗/抽屉】这类交互来优化用户体验。
小贴士:
- 弹窗打开的方式提供三种页面设计模式,绑定已有页面、使用新页面、复制已有页面。
- 使用新页面和复制已有页面的方式只能进行一次性的视图设计,无法进行复用。
- 使用绑定已有页面的方式可以使得视图进行复用,但复用的视图也只能同步弹窗的内容部分,弹窗底部的动作仅会在创建动作时复制一次。
- 跳转动作的打开方式以及页面设计模式等属于元数据信息,无法通过属性面板进行修改,因此只能通过重新创建新动作的方式进行修改。
- 鉴于业务的复杂和多变,通常情况下我们只采用【绑定已有页面】的方式为弹窗设计内容部分。这样在交互发生变更时,可以更好的适应变化。
场景2
为了方便接下来的描述,我们需要再构建一个基本的业务场景,这个场景中包含【公司】和【部门】两个模型。
【公司】模型的管理能力使用标准的【增删改查】视图。(此处不进行演示)
在【部门】的表格
左侧添加【公司】-【部门】树,在选择某个公司后,可以根据所属公司进行筛选,查询所属公司下的全部部门。在选择某个部门后,可以根据上级部门进行筛选,查询该部门下的子部门(不包含子部门的子部门)。
PS:如这里要求查询该部门下的全部子部门,需要服务端配合。
其模型定义如下:
公司(Company)
名称 | API名称 | 业务类型 | 是否多值 | 长度(单值长度) | 关联模型 | 关联字段 | |
---|---|---|---|---|---|---|---|
ID | id | 整数 | 否 | - | - | - | - |
编码 | code | 文本 | 否 | 128 | - | - | - |
名称 | name | 文本 | 否 | 128 | - | - |
部门(Department)
名称 | API名称 | 业务类型 | 是否多值 | 长度(单值长度) | 关联模型 | 关联字段 | |
---|---|---|---|---|---|---|---|
ID | id | 整数 | 否 | 128 | - | - | |
编码 | code | 文本 | 否 | 128 | - | - | - |
所属公司 | company | 多对一 | 是 | - | 公司(Company) | companyId - id | |
所属公司ID | companyId | 整数 | 否 | - | - | - | |
上级部门 | parent | 多对一 | 是 | - | 部门(Department) | parentId - id | |
上级部门ID | parentId | 整数 | 否 | - | - | - |
创建【部门】视图
设置联动关系
这里我们需要配置的是【公司】-【部门】的树结构,因此,在【第1级关联】中的模型选择【公司】,在【第2级关联】中的模型选择【部门】。
在【第2级关联】中的【层级关联关系字段】默认会选择一个可用字段,这里我们是通过【部门】中的【所属公司】进行关联的。
在【部门】中是通过【上级部门】进行的自关联,因此,在【第2级关联】中的【自关联关系字段】选择【上级部门】。
在选中【公司】节点后,需要对右侧表格发起查询。其筛选条件是通过【部门】中的【所属公司】进行筛选的。因此,在【第1级关联】中的【表格关联关系字段】选择【所属公司】。那么,在表格发起查询前,会根据【所属公司】字段的关联关系配置自动添加筛选条件。
在选中【部门】节点后,同样需要对右侧表格发起查询。其筛选条件是通过【部门】中的【上级部门】进行筛选的。因此,在【第2级关联】中的【表格关联关系字段】选择【上级部门】。那么,在表格发起查询前,会根据【上级部门】字段的关联关系配置自动添加筛选条件。
配置如下图所示:
树/级联配置详解
在体验过树/级联
配置之后,我们需要具体的介绍每个配置在树构建时的作用,以便于理解一系列类似组件的配置。
配置解释
- 模型:当前层级的模型。
- 数据标题:树节点展示标题。
- 筛选条件:当设置【自关联关系字段】时,会根据【自关联关系字段】的关联关系自动添加筛选条件,此时如果配置了筛选条件,将进行追加。当未设置【自关联关系字段】时,为查询单层级树节点的筛选条件。
- 自关联关系字段:通过字段配置以及所在层级自动添加筛选条件用于查询下级节点的一种方式。
- 层级关联关系字段:通过字段配置将当前层级与上一层级进行关联,自动添加筛选条件用于查询下级节点的一种方式。
- 表格关联关系字段:在树节点选中时,通过字段配置自动添加筛选条件用于表格查询。
名词解释
- 树(Tree):一种数据结构,用于描述一组具备
父子
关系的数据。 - 节点(TreeNode):对于树中的每一个节点存储必要属性的对象。主要包括
唯一标识(key)
、数据(value)
、父(parent)
、子(children)
以及层级(level)
等属性。 - 根节点:没有父节点的节点。
- 父节点:相对于子节点而言的节点。
- 子节点:相对于父节点而言的节点。
- 当前节点:用户行为触发时所操作的对于节点。
- 选中节点:通过当前节点中的某些配置为
数据提供者
追加筛选条件,并让数据提供者
执行刷新
操作。 - 展开节点:通过当前节点中的某些配置查询该节点的子节点。
树的层级配置
在配置面板,我们可以看到有第x级关联
这样的分组。每一个分组中的全部配置都对应了树的一个层级所需的配置。
但需要理解的是,这里的层级并不是指运行时看到的树的真实层级,而是指配置时所需的层级。
比如:通过设置【自关联关系字段】,我们可以在这配置的一层级中,在运行时展开多个层级,直到无法查询到自关联的子节点为止。
自关联关系字段影响查询下级节点
在未配置【自关联关系字段】时,我们在运行时查询第一层树节点(通常也称为根节点)时,其查询条件可以表示为:
rsql: [${筛选条件}]
当配置了【自关联关系字段】时,我们在运行时查询第一层树节点时,其查询条件可以表示为:
rsql: parentId =isnull= true [and ${筛选条件}]
展开查询第二层树节点时,其查询条件可以表示为:
rsql: parentId == ${parent.id} [and ${筛选条件}]
PS:这里的parentId
泛指【自关联关系字段】的relationFields
属性,而不是固定的某个字段。当存在多个时,将通过and
连接。这里的parent.id
泛指上级节点中的对应的【自关联关系字段】的referenceFields
属性。
字段的关联关系属性
类型定义:(这里仅展示必要的元数据类型定义)
export interface RuntimeRelationField {
/**
* 是否关系存储
*/
relationStore: boolean;
/**
* 关联模型编码
*/
references: string;
/**
* 关系字段(在当前模型中的字段)
*/
relationFields: string[];
/**
* 关联字段(在关联模型中的字段)
*/
referenceFields: string[];
}
export type RuntimeO2OField = RuntimeRelationField;
export interface RuntimeO2MField extends RuntimeRelationField {
/**
* 限制数量
*/
limit?: number | string;
}
export type RuntimeM2OField = RuntimeRelationField;
export interface RuntimeM2MField extends RuntimeRelationField {
/**
* 多对多中间模型编码
*/
through: string;
/**
* 多对多中间模型关系字段(与关系字段对应)
*/
throughRelationFields: string[];
/**
* 多对多中间模型关联字段(与关联字段对应)
*/
throughReferenceFields: string[];
/**
* 限制数量
*/
limit?: string | number;
}
在一对一(O2O)
、多对一(M2O)
以及一对多(O2M)
这三种类型的关联关系字段中,relationFields
和referenceFields
总是长度相等,且相同索引位置的字段总是配对的。
在多对多(M2M)
这种类型的关联关系字段中,relationFields
和throughRelationFields
总是长度相等,且相同索引位置的字段总是配对的,,referenceFields
和throughReferenceFields
总是长度相等,且相同索引位置的字段总是配对的。
其中relationFields
表示当前模型中的字段,referenceFields
表示关联模型中的字段。throughRelationFields
表示在中间模型中与当前模型字段对应的字段,throughReferenceFields
表示在中间模型中与关联模型字段对应的字段。
层级关联关系字段影响查询下级节点
从【第2级关联】开始,需要配置【层级关联关系字段】,将其与上一层级进行关联。
这里需要注意的是,如果【第1级关联】使用了【自关联关系字段】进行自关联,那么只有当无法通过自关联条件查询到子节点时,会自动转换为使用【层级关联关系字段】查询当前节点的子节点。
其查询条件可以表示为:
rsql: parentId == ${parent.id} [and ${筛选条件}]
PS:这里的parentId
泛指【层级关联关系字段】的relationFields
属性,而不是固定的某个字段。当存在多个时,将通过and
连接。这里的parent.id
泛指上级节点中的对应的【层级关联关系字段】的referenceFields
属性。
构成完整关联关系*
在配置【联动关系】时,我们必然需要一些条件来规定一种怎样的配置才能在运行时
正常运行。下面将介绍构成完整关联关系的一些基本条件和限制。
最终到达的目标模型
为了构建完整的关联关系,并且可以在业务使用中可以正常运行,我们对【联动关系】的配置进行了基础的限制。最终到达的目标模型就是保障配置有效性的基础。
在不同的视图
或组件
中,最终到达的目标模型也有所区别。下面列举了目前现有的几种情况。
-
在
表格视图
中的左树右表
,其最终到达的模型为表格
对应的模型,也就是当前视图模型。其要求最后一级关联
必须通过【表格关联关系字段】与表格建立关联关系。 -
在
树视图
中,其最终到达的模型为树
对应的模型,也就是当前视图模型。其要求最后一级关联
中的【模型】必须是该模型。 -
在
字段
的树下拉
和级联
组件中,其最终到达的模型为字段
对应的关联模型,也就是字段的references
对应的模型。其要求最后一级关联
中的【模型】必须是该模型。
PS:一般而言,未构成完整关联关系
的提示都是由于最终到达的目标模型限制引起的。
层级关联关系的模型限制
平台中的模型元数据定义了模型的拓扑结构,模型与模型之间通过关联关系字段产生联系,然后形成模型的拓扑结构。在这个基础上,每一层级的模型也就有了可选范围。
在【第1级关联】中的【模型】可以选择任意模型。
从【第2级关联】开始,可选的【模型】就有了限制。其只能选择与上一级关联的模型可以通过关联关系字段关联的模型。由于元数据定义的模型的拓扑结构过于复杂,我们无法通过适当的条件进行筛选。因此,在用户交互上我们并没有限制这一点,这就要求用户明确需要构建一个怎样的树结构,并根据树结构进行合理的配置。
PS:当模型选择错误时,【层级关联关系字段】未选择的情况,也是未构成完整关联关系
的情况之一。
层级关联关系的字段限制
由于字段的关联关系具有方向性,在四种关联关系类型中,具备明确方向性的类型为一对多(O2M)
和多对一(M2O)
,在子节点的查询时,我们假定节点展开一定是向多
的一方进行展开的。因此,【层级关联关系字段】也只能使用这两种关联关系类型的字段。
在其他两种关联关系类型中,我们无法确定其展开的方向,也就无法提供自动化的查询机制。
元数据模型的拓扑结构复杂性(扩展内容,仅作了解即可)
- 模型继承:模型存在扩展继承、代理继承等继承方式,那么当前模型就不仅仅是这一个模型,包括它的全部父模型和子模型。
- 单向关联:当模型是通过单向关联到当前模型时,我们不仅需要从当前模型出发查找一些对应的模型外,还需要从其他模型出发查找一些与当前模型关联的模型。
由于这些复杂性共同导致最终筛选的结果集和所有模型的结果集几乎一致,其在便于用户选择的需求下表现的并不好,因此我们放弃了筛选。
选择和配置的一般步骤
- 明确业务需求,需要构建一个怎样的
树结构
。 - 确定
最终到达的目标模型
。 - 定义模型元数据,以符合业务需求。
- 确定展示主体是
表格
还是树
,分别选择不同的视图。(字段组件可跳过) - 确定从什么模型开始选择,最终可以通过
层级关联关系字段
到达最终目标模型的。
Oinone社区 作者:nation原创文章,如若转载,请注明出处:https://doc.oinone.top/designer/uidesigner/63.html
访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验