【界面设计器】树下拉/级联

阅读之前

你应该:

名词解释

  • 字段组件:为字段提供交互能力的组件,一个字段对应一个组件。
  • 关联关系字段:在模型中与其他模型建立关联关系的字段。
  • 可选项:选择组件使用的具体选项,可以是静态的,也可以是动态的。
  • 选中:用户在使用选择组件时,针对某一选项标记或提取这一选项。

概述

本章内容主要是对【界面设计器】左树右表内容中提及的字段相关内容的补充,并非完整教程,有不清楚的地方可以交替阅读进行理解。

场景

沿用【界面设计器】左树右表中的两个场景。

我们可以做出这些优化:

将【商品类目】的【上级类目】组件改为【级联】组件。其第1级为【商品类目】,使用自关联依次展开。

将【部门】的【上级部门】组件改为【树下拉】组件。其第1级为【公司】,第2级为【部门】,【部门】使用自关联依次展开。

PS:本章不提供任何步骤介绍,请根据场景内容自行探索。

扩展知识

具备选择行为的组件

常用的选择组件可以进行一些基本的划分。

从可选数量来看
  • 单选:只能选一个值。
  • 多选:可以选择多个值。
从业务类型来看
  • 枚举(Enum):通过数据字典提供可选项。
  • 布尔(Boolean):可以看作一个特殊的枚举,其可选范围只有
  • 一对一(O2O)多对一(M2O)对一(X2O)类型仅支持单选,通过关联模型的数据源提供可选项。
  • 一对多(O2M)以及多对多(M2M)对多(X2M)类型仅支持多选,通过关联模型的数据源提供可选项。
从交互形态来看
  • 单选框(Radio)
  • 多选框(Checkbox)
  • 下拉选择(Select)
  • 树下拉(TreeSelect)
  • 级联(Cascader)

其中,树下拉(TreeSelect)级联(Cascader)组件要求数据源可以构成树结构,因此通常使用这两个字段组件的都是关联关系字段

下拉选择(Select)

在介绍树下拉/级联之前,我们有必要先了解一下在关联关系字段中使用下拉选择(Select)这一字段组件的表现情况。

根据关联关系字段对应的关联模型,我们可以获得其组件所需的可选项,在用户进行选中后,该组件将获得一个选项值,并且在表单提交、计算公式等被使用。

通常情况下,我们通过queryPage接口获取分页后的可选项列表,再通过点击/滚动方式获得其他页的可选项供用户选择。

树下拉(TreeSelect)/级联(Cascader)

与上述介绍的下拉选择(Select)不同点在于,其可选项是通过【联动关系】配置进行获取的,它并不要求直接获取到真正可以被选择的可选项,而是通过树结构依次展开的。用户可选择的可选项一定是与关联关系字段对应的关联模型相同的树节点。对于无法选择的节点,其主要作用在于将数据进行划分,以便于用户进行选择。

由于树节点具备特殊性,无法直接使用平台的任何一个模型。因此树结构被定义在UiTreeNode模型中,该模型是描述树结构的基本模型,其提供了多个接口为树结构的查询提供了基本能力。

通常情况下,在创建页面,我们通过UiTreeNode模型的fetchChildren接口依次获取其子节点。在编辑页面,我们通过fetchAllreverselyQueryreverselyQueryWithSize这三个接口获取回填的数据,根据不同情况进行调用。虽然使用来不同的接口,但最终都会使用当前模型的queryPage接口获取数据。

Oinone社区 作者:oinone原创文章,如若转载,请注明出处:https://doc.oinone.top/install/64.html

访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验

(0)
oinone的头像oinone
上一篇 2023年6月20日 pm4:07
下一篇 2023年11月2日 pm1:58

相关推荐

  • 【工作流】流程扩展自定义函数示例代码汇总

    目录 1. 流程节点审批人函数2. 审批开始前执行函数3. 填写执行前执行函数4. 待办操作提交后执行函数5. 审批操作数据函数6. 自定义通知人函数 1. 流程节点审批人函数 包含转交、抄送、加签、填写、通知人自定义函数当平台默认提供的审批人选择无法满足个性化的业务需求时,我们可以通过自定义函数处理审批人的生成逻辑 1.1 编写自定义审批人函数 @Function(openLevel = {FunctionOpenEnum.API}) @Function.Advanced(type = FunctionTypeEnum.QUERY, displayName = "报销单-证明人-审批", category = CUSTOM_DESIGNER) public List<NodePerson> bizZmrApprovePerson(List<NodePerson> nodePersonList, NodeModel nodeModel, WorkflowContext workflowContext) { List<NodePerson> newNodePersonList = new ArrayList<>(); String nodeModelId = nodeModel.getId(); Object nodeData = workflowContext.get(nodeModelId); BuissModel inputBuissModel = JsonUtils.parseObject(JsonUtils.toJSONString(nodeData), BUISSMODEL_TR); BuissModel buissModel = new BuissModel().setId(inputBuissModel.getId()).queryById(); buissModel.fieldQuery(BuissModel::getZmEmployee); BxEmployee zmEmployee = buissModel.getZmEmployee(); if (zmEmployee == null) { log.error("报销单ID:{},名称:{}, 获取证明人为空", buissModel.getId(), buissModel.getName()); return newNodePersonList; } NodePersonUser personUser = new NodePersonUser(); List<NodePersonUser> nodePersonUsers = new ArrayList<>(); NodePerson person = new NodePerson(); person.setId(zmEmployee.getBindingUserId() + ""); person.setType(NodePersonTypeEnum.USER); personUser.setUserId(zmEmployee.getBindingUserId()); nodePersonUsers.add(personUser); person.setNodePersonUsers(nodePersonUsers); newNodePersonList.add(person); return newNodePersonList; } 1.2 流程设计器的审批节点设置自定义函数 2.审批开始前执行函数 使用场景:在流程执行到审批或填写节点任务初始化后,任务尚未开始,需要在初始化任务做一些自定义逻辑处理时,使用该扩展执行时间:执行节点是在审批或填写待办任务初始化之后,审批或填写结果执行之前,执行该扩展 /** * 审批节点初始化完成,执行前置函数 * @param approvalNode * @param context * @param taskInstance */ @Function(name = "approvalCustomStartFun",openLevel = FunctionOpenEnum.API) @Function.Advanced(type= FunctionTypeEnum.QUERY,displayName = "审批执行前置处理",category = FunctionCategoryEnum.CUSTOM_DESIGNER ) public void approvalCustomStartFun(ApprovalNode approvalNode, WorkflowContext context, WorkflowTaskInstance taskInstance) { // TODO: 2024/2/23 可以根据结果自己处理业务逻辑 } 3.填写执行前执行函数 /** * 填写执行前置处理 */ @Function(name = "writeCustomStartFun", openLevel = FunctionOpenEnum.API) @Function.Advanced(type = FunctionTypeEnum.QUERY, displayName = "填写执行前置处理", category = FunctionCategoryEnum.CUSTOM_DESIGNER) public void writeCustomStartFun(WorkflowTaskInstance taskInstance, WriteNode writeNode, WorkflowContext context) { System.out.println("填写执行前置处理"); } 4. 待办操作提交后执行函数 使用场景:在审批或填写的待办任务在操作任务时,需要额外执行一些逻辑,比如当前人提交操作以后需要更新更当前人操作相关的数据库记录,执行时间:执行节点是在保存待办任务之后,异步执行审批或填写结果之前,执行该扩展 /** * 转交操作后置函数,再流程设计器中审批和填写节点中…

    2023年12月4日
    1.2K00
  • Oinone License 许可证使用常见问题

    如何获取许可证? 联系数式运维人员获取许可证。(以下内容全部使用表示许可证文件路径) subject:授权主体名称 license.lic:许可证文件 不同许可证类别有什么不同? 许可证类型 LicenseType 限制功能 适用环境 研发授权 DEVELOP 1.每次安装时效1天,超时后无法正常访问设计器相关功能2.限制CPU和主板序列号或限制许可证使用人数3.不能用于容器启动4.有页面水印 开发环境(开发人员本地启动业务工程时使用该授权) 伙伴授权 TRIAL 1.无安装时效限制2.无部署环境限制3.有页面水印 非生产环境(测试环境、预发环境等使用该授权) 客户授权 BUSINESS 1.无安装时效限制2.仅能部署一套生产环境3.无页面水印 生产环境 PS: 一套环境是指共用Base库的所有JVM称为一套环境。 如何配置许可证? 在yaml中配置许可证 单个许可证配置 pamirs: license: subject: <subject> path: <license.lic> 多个许可证配置 pamirs: license: subject: <subject> path: – <license1.lic> – <license2.lic> pamirs.license.path可以是相对路径、绝对路径以及URL路径。 在Program Arguments中配置许可证 java -jar -Psubject=<subject> -Plicense=<license1.lic> -Plicense=<license1.lic> <boot.jar> 如何在开发中安装许可证? 将许可证放入后端运行时工作目录中即可。(一般为idea项目根目录) 如何在物理机生产环境安装许可证? 将许可证放入与jar包平级目录中即可。 如何在docker环境中安装许可证? 在docker运行时目录添加挂载卷映射,并在yaml中配置对应的路径即可。 如何获取CPU序列号和主板序列号 在Linux环境中使用dmidecode命令 # 获取CPU序列号 dmidecode -s system-serial-number # CPU序列号 7*****1 # 获取主板序列号 dmidecode -s baseboard-serial-number # 主板序列号 ..CN*******V01Y7. # 获取系统UUID dmidecode -s system-uuid # 系统UUID 4c4xxxxx-xxxx-xxxx-xxxx-xxxxxxxx5831 在Mac环境中使用system_profiler命令 # 获取CPU序列号 system_profiler SPHardwareDataType | grep 'Serial Number' | awk -F ':' '{print $2}' # CPU序列号 C02******03Y # 获取主板序列号 system_profiler SPHardwareDataType | grep 'Hardware UUID' | awk -F ':' '{print $2}' # 主板序列号 1AAxxxxx-xxxx-xxxx-xxxx-xxxxxxxxF0FC 在Windows环境中使用wmic命令 # 获取CPU序列号 wmic cpu get processorid # CPU序列号 BFExxxxxxxxxx6A3 # 获取主板序列号 wmic baseboard get serialnumber # 主板序列号 PFxxxxBY # 获取系统UUID wmic csproduct get uuid # 系统UUID D0Exxxxx-xxxx-xxxx-xxxx-xxxxxxxx78B8 在Linux环境出现dmidecode命令执行失败该如何处理? 1. 命令未找到,可使用如下方式尝试安装 # debian (eg: Ubuntu) apt-get install dmidecode # rpm (eg: Fedora/CentOS/RedHat) yum install dmidecode 2. 无权限执行命令,尝试切换当前执行用户或为当前用户提高执行权限 在docker环境出现证书安装失败该如何处理? 1. 由于docke环境非物理环境,不支持CPU序列号和主板序列号校验,尝试更换许可证。 2. 检查许可证在镜像中的位置是否与配置文件中一致。 许可证安装失败该如何处理? 1. 日志出现License installation failed.信息 PS:对JDK版本依赖的问题已在5.0.0版本以上得到完整解决,此问题仅会出现在低版本的平台版本中。 请检查jdk版本是否高于1.8_221以上。 如无法升级jdk版本的环境下,请点击下载 jce_policy-8.zip 并按照如下步骤进行操作:…

    2024年6月19日
    2.9K00
  • 数据可视化-项目中如何引用图表、报表、大屏

    依赖包 在业务工程的pom中增加数据可视化运行的依赖包 参考文档 如何添加数据可视化运行时依赖 数据可视化设计图表、报表和数据大屏 在数据可视化中设计好业务合适的图表,并且发布以后,在界面设计器中可以嵌入该图表同样处理的还有报表 在界面设计器中在页面中透出图表、报表和数据大屏 设置图表,选择已经对应的图表 可在表单以及详情的页面中嵌入对应的图表、报表和数据大屏 更新图表、报表和数据大屏 修改图表以后,需要更新发布,对应业务页面上才会更新最新的图表

    2024年5月18日
    1.2K00
  • 数据可视化的导入导出

    目录 依赖包安装GraphQL的工具登录gql导出生成json文件子业务工程中导入示例代码 简介 通过调用导出接口,将设计器的设计数据与元数据打包导出到文件中。提供了download/export两类接口。 依赖包 <dependency> <groupId>pro.shushi.pamirs.metadata.manager</groupId> <artifactId>pamirs-metadata-manager</artifactId> </dependency> 安装GraphQL的工具 下载官网地址:https://github.com/Kong/insomnia/releases 登录gql 示例调用代码 mutation { pamirsUserTransientMutation { login(user: { login: "admin", password: "admin" }) { needRedirect broken errorMsg errorCode errorField } } } 导出生成json文件 执行GraphQL,直接返回导出数据。适用于通过浏览器直接下载文件。 全部导出 请求示例: mutation { dataDesignerExportReqMutation { export(data: { fileName: "datavi_data" }) { jsonUrl } } } 指定图表导出 请求示例: mutation { dataDesignerExportReqMutation { export(data: { chartCode: "CT00000000002000", fileName: "datavi_data" }) { jsonUrl } } } 对应chartCode为图表的编码code,可通过查询数据库来获得 指定报表导出 请求示例: mutation { dataDesignerExportReqMutation { export(data: { reportCode: "RP00001000", fileName: "datavi_data" }) { jsonUrl } } } 对应reportCode为报表的编码code,可通过查询数据库来获得 指定业务大屏导出 请求示例: mutation { dataDesignerExportReqMutation { export(data: { screenCode: "DS00001000", fileName: "datavi_data" }) { jsonUrl } } } 对应screenCode为数据大屏的编码code,可通过查询数据库来获得 业务工程中导入示例代码 导入元数据示例代码 @Slf4j @Order(Integer.MAX_VALUE-1) @Component public class DemoModuleAppInstall implements MetaDataEditor, LifecycleCompletedAllInit { //流程设计器导出的页面元数据json private static final String INSTALL_DATAVI_META_PATH = "install/datavi_data.json"; @Override public void edit(AppLifecycleCommand command, Map<String, Meta> metaMap) { if(StringUtils.isBlank(INSTALL_DATAVI_META_PATH)) return; log.info("开始安装-元数据"); try { InitializationUtil util = InitializationUtil.get(metaMap, DemoModule.MODULE_MODULE, DemoModule.MODULE_NAME); if (null != util) { // 设计器的元数据 if(StringUtils.isNotBlank(INSTALL_DATAVI_META_PATH)) { log.info("开始安装图表元数据"); DesignerInstallHelper.mateInitialization(util, INSTALL_DATAVI_META_PATH, DemoModule.MODULE_MODULE, DemoModule.MODULE_NAME); } } } catch (Exception e) { log.error("图表设计器元数据导入异常", e); } } @Override public void process(AppLifecycleCommand command, Map<String, ModuleDefinition>…

    2024年5月16日
    1.6K00
  • 数据可视化-如何自定义查询数据方法

    场景 根据测试商品,汇总数据通过测试统计商品透出到数据可视化图表数据; 统计商品类目的最大库存以及平均售价信息 测试商品模型 @Model.model(DemoItem.MODEL_MODEL) @Model(displayName = "测试商品", labelFields = "name") @Model.Code(sequence = "SEQ", prefix = "IT", size = 8) public class DemoItem extends CodeModel { private static final long serialVersionUID = -5104390780952631397L; public static final String MODEL_MODEL = "demo.DemoItem"; @Field.String @Field(displayName = "商品名称") private String name; @Field.Html @Field(displayName = "商品描述") private String description; @Field.Money(D=2) @Field(displayName = "商品价格") private BigDecimal itemPrice; @Field.Integer @Field(displayName = "商品库存") private Long inventoryQuantity; …. 测试商品统计 @Model.model(DemoItemStatistics.MODEL_MODEL) @Model(displayName = "测试商品统计", labelFields = "name") public class DemoItemStatistics extends IdModel { private static final long serialVersionUID = 5626273740800455515L; public static final String MODEL_MODEL = "demo.DemoItemStatistics"; @Field.String @Field(displayName = "类目名称") private String categoryName; @Field.Integer @Field(displayName = "商品库存") private Long inventoryQuantity; @Field.Money @Field(displayName = "商品价格") private BigDecimal itemPrice; } 自定义商品类目统计数据 【注意】 图表设计器能获取到的接口需指定:category = FunctionCategoryEnum.QUERY_PAGE,且出参和入参类型要与本示例一致 @Function.Advanced(type = FunctionTypeEnum.QUERY, displayName = "商品统计列表", category = FunctionCategoryEnum.QUERY_PAGE) @Function.fun(FunctionConstants.queryPage) @Function(openLevel = {FunctionOpenEnum.LOCAL, FunctionOpenEnum.REMOTE, FunctionOpenEnum.API}) public Pagination<DemoItemStatistics> queryPage(Pagination<DemoItemStatistics> page, IWrapper<DemoItemStatistics> queryWrapper) { List<DemoItemStatistics> list = new ArrayList<>(); List<DemoItem> items = demoItemService.queryListByWrapper(Pops.<DemoItem>lambdaQuery() .from(DemoItem.MODEL_MODEL) .eq(DemoItem::getStatus, ItemStatusEnum.ACTIVE)); if(CollectionUtils.isEmpty(items)) return page; Map<Long, List<DemoItem>> itemMap = items.stream().collect(Collectors.groupingBy(DemoItem::getCategoryId)); for (Map.Entry<Long, List<DemoItem>> longListEntry : itemMap.entrySet()) { long categoryId = longListEntry.getKey(); List<DemoItem> demoItems =…

    2024年5月18日
    1.0K00

Leave a Reply

登录后才能评论