【界面设计器】自定义字段组件基础

阅读之前

本文档属于高阶实战文档,已假定你了解了所有必读文档中的全部内容,并了解过界面设计器的一些基本操作。

如果在阅读过程中出现的部分概念无法理解,请自行学习相关内容。【前端】文章目录

概述

平台提供的字段组件(以下简称组件)是通过SPI机制进行查找并最终渲染在页面中。虽然平台内置了众多组件,但无法避免的是,对于业务场景复杂多变的实际情况下,我们无法完全提供所有组件。

面对这样的困境,我们提供了外部注册组件的方式。在之前文章中,我们了解到组件注册后需要应用到页面中,需要配合DSL才能实现。其实,在平台中还提供了一种SAAS化的组件注册方式,配合界面设计器的设计能力,可以将组件在设计器页面中引入,从而更近一步的满足不同的业务场景。

通过界面设计器可以创建自定义组件,并为组件添加对应的元件。

界面设计器可以为元件设计其在指定视图下的属性面板,在页面设计时,可以使用该属性面板为元件设置相关属性。

在界面设计器的设计页面中拖入的组件,将通过SPI机制获取到一个唯一的元件,并渲染在页面中,提供给业务使用。

界面设计器-组件管理

名词解释

  • 页面设计:使用界面设计器设计页面的页面。
  • 属性面板设计:使用界面设计器设计属性面板的页面。
  • 设计页面:页面设计和属性面板设计的统称。
  • 组件库:展示在设计页面左侧的全部可拖拽组件。
  • 组件:在组件库中可拖拽的最小单元。
  • 元件:一个组件中的具体实现,是组件的最小单元。
  • 属性面板:展示在设计页面右侧的元件属性。
页面设计

image.png

属性面板设计

image.png

组件管理入口

进入界面设计器后,可通过上方标签页切换至【组件】管理页面。

image.png

创建第一个组件

点击【添加组件】,在弹窗中输入组件名称【文本输入框】后,点击【确定】。

image.png

image.png

创建第一个元件

点击【组件卡片】或点击【管理元件】按钮进入【元件】管理页面。

image.png

点击【添加元件】,可以看到如下【创建元件】弹窗。

image.png

表单字段解释
  • 元件名称:显示名称,仅在管理页面做展示使用。
  • API名称:SPI中的widget属性。
  • 支持字段业务类型:SPI中的ttype属性。
  • 支持多值:SPI中的multi属性。
  • 支持视图类型:SPI中的viewType属性。
  • 元件描述:元件功能描述内容,仅在管理页面做展示使用。

填入以下内容,并点击【确定】。

image.png

image.png

设计元件属性面板

点击【元件卡片】或点击【设计元件属性】按钮进入【属性面板设计】页面。

image.png

从【模型】中搜索【标题】,将【标题】和【隐藏标题】拖放至设计区域。如果想实现的相对美观,可以额外添加【分组】组件拖放至设计区域,并修改标题为【基础】,如下图所示。

image.png

点击【发布】按钮进行页面的发布。

至此,我们设计了第一个元件属性面板,接下来,我们需要在页面设计中使用这个组件。

在页面中使用【文本输入框】

由于我们之前选择的支持的视图类型是【表单】,因此我们在【表单】页面进行接下来的操作,此处略去创建视图的过程。

从【模型】中将【名称】拖放至设计区域。并通过点击【切换】按钮切换至我们的组件【文本输入框】,并且将标题改为【这是文本输入框组件】查看其展示效果。

image.png

image.png

属性变化

在组件切换后,属性面板发生了变化,原有属性会根据当前属性面板中现有字段进行【裁剪】,相同属性名称(字段)的值会被保留,其他属性值会被丢弃。

由于我们并没有在当前属性面板添加【宽度】属性,因此原有属性的宽度被丢弃,组件会自动变成默认【宽度】,默认宽度为1

组件变化

由于我们并没有在【低无一体】中上传对应元件的代码实现,因此展示了默认的【单行文本】组件,目前组件的展示效果不会发生变化。

组件可切换规则

只有【组件】中包含与【当前选中字段】匹配的【元件】,才会将对应【组件】的名称展示在【可切换列表】中。

【当前选中字段】中包含了如下三个属性,这三个属性和【创建元件】时设置的属性一一对应。

(右侧属性面板切换至字段后,可查看当前选中字段的相关元数据信息。)

  • 所在视图类型:根据字段在视图中的位置进行推断,当前所在位置为【表单】。当【支持视图类型】包含【表单】时条件成立。
  • 字段业务类型:文本。当【支持字段业务类型】包含【文本】时条件成立。
  • 是否多值:否。当【支持多值】相同时条件成立。

使用低无一体为组件上传代码实现

进入【组件】管理页面,点击【低无一体】,打开【低无一体】弹窗。

image.png

image.png

按照步骤,在【生成SDK】后,可以【下载模板工程】。在本地进行npm相关操作后,会在packages/kunlun-plugin目录下生成dist目录。在dist目录中,会有对应的kunlun-sdk.umd.js文件,使用【上传JS文件】进行上传。如果工程中包含了css,使用【上传CSS文件】进行上传。上传完成后点击【确定】进行保存。

PS:在模板工程中,我们提供了最简化的Hello World示例,即使不添加任何代码也可以看到组件的具体效果,为了方便演示,我们暂时不介绍代码实现的相关内容,仅需直接上传对应js文件,看到效果即可。如果遇到相关问题,请点击查看【前端】低无一体部署常见问题

image.png

image.png

结语

至此,我们已经完整体验了从【创建组件】到【属性面板设计】再到【使用组件】以及【实现组件】的全部流程。

通过这一流程我们不难发现,【自定义组件】并非仅仅用于【页面设计】,在【属性面板设计】时,我们同样可以使用【自定义组件】来设计【自定义组件】的属性面板。这样便形成了一个完整的设计闭环,使得开发者可以更大程度的发挥自身创造力,开发出符合业务需求的【自定义组件】。

Oinone社区 作者:数式-海波原创文章,如若转载,请注明出处:https://doc.oinone.top/frontend/53.html

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

Like (0)
数式-海波's avatar数式-海波数式管理员
Previous 2023年6月20日 pm4:07
Next 2023年11月2日 pm1:58

相关推荐

  • GraphQL请求详解(v4)

    阅读之前 什么是GraphQL? Oinone官方解读GraphQL入门 可视化请求工具 insomnia下载 概述 (以下内容简称GQL) 众所周知,平台的所有功能都是通过一系列元数据定义来驱动的,而GQL作为服务端和客户端交互协议,其重要性不言而喻。下面会从以下几个方面介绍GQL在平台中是如何运作的: 服务端定义元数据生成GQL对应的schema 通过HttpClient发起一个GQL请求 通过window.open使用GET方式发起一个GQL请求 客户端泛化调用任意API服务 客户端通过运行时上下文RuntimeContext发起GQL请求 准备工作 在开始介绍GQL之前,我们需要定义一个可以被GQL请求的服务端函数,以此来介绍我们的相关内容。(对服务端不感兴趣的同学可以跳过代码部分) DemoModel.java @Model.model(DemoModel.MODEL_MODEL) @Model(displayName = "演示模型", labelFields = {"name"}) public class DemoModel extends IdModel { private static final long serialVersionUID = -7211802945795866154L; public static final String MODEL_MODEL = "demo.DemoModel"; @Field(displayName = "名称") private String name; @Field(displayName = "是否启用") private Boolean isEnabled; } DemoModelAction.java @Model.model(DemoModel.MODEL_MODEL) public class DemoModelAction { @Action(displayName = "启用") public DemoModel enable(DemoModel data) { data.setIsEnabled(true); data.updateById(); return data; } @Action(displayName = "禁用") public DemoModel disable(DemoModel data) { data.setIsEnabled(false); data.updateById(); return data; } } 上面的java代码定义了演示模型的字段和动作: 字段 field id:ID 整数 Integer name:名称 字符串 String isEnabled:是否启用 布尔 Boolean 动作 action enable:启用 提交动作 ServerAction disable:禁用 提交动作 ServerAction 服务端定义元数据生成GQL对应的schema 模型和字段 type DemoModel { id: Long name: String isEnabled: Boolean } 动作 type DemoModelInput { id: Long name: String isEnabled: Boolean } type DemoModelQuery { queryOne(query: DemoModelInput): DemoModel …… } type DemoModelMutation { enable(data: DemoModelInput): DemoModel disable(data: DemoModelInput): DemoModel …… } PS:平台内置了多种Query和Mutation定义,通过模型继承关系将自动生成,无需手动定义。比如Query定义包括queryOne、queryPage等;Mutation定义包括create、update等。特殊情况下,默认逻辑无法满足时,服务端通常采用函数重载的方式进行替换,客户端则无需关心。 生成规则 type DemoModel:通过模型编码demo.DemoModel取.分隔后的最后一位,并转换为大驼峰格式。字段与声明类型一致。 type DemoModelInput:动作入参定义,未做特殊声明的情况下与模型定义一致。 type DemoModelQuery和type DemoModelMutation:Query和Mutation为固定后缀,分别生成动作相关类型。当函数类型为QUERY时,使用Query后缀,其他情况使用Mutation后缀。 (此处仅做简单解释,详细生成规则过于复杂,客户端无需关心) Query类型的GQL示例 query { demoModelQuery { queryOne(query: { id: ${id} }) { id name isEnabled } } } Mutation类型的GQL示例 mutation…

    2023年11月1日
    2.6K00
  • 左树右表默认选择第一行

    import { BaseElementWidget, Widget, SPI, ViewType, TableSearchTreeWidget } from '@kunlun/dependencies'; @SPI.ClassFactory( BaseElementWidget.Token({ viewType: ViewType.Table, widget: 'tree', model: '改成当前视图的模型' }) ) export class CustomTableSearchTreeWidget extends TableSearchTreeWidget { protected hasExe = false; @Widget.Watch('rootNode.children.length') protected watchRootNode(len) { if (len && !this.hasExe) { this.hasExe = true; const firstChild = this.rootNode?.children?.[0]; if (firstChild) { this.onNodeSelected(firstChild); this.selectedKeys = [firstChild.key]; } } } }

    2024年11月26日
    1.5K00
  • 表格如何支持表尾合计计算

    介绍 可以通过扩展TableWidget.ts实现 示例代码 import { BaseElementWidget, DslDefinitionType, SPI, TableWidget, ViewType, Widget } from '@kunlun/dependencies'; @SPI.ClassFactory( BaseElementWidget.Token({ type: ViewType.Table, widget: 'table', model: 'resource.k2.Model0000000109', viewName: '移动端品牌_TABLE_0000000000021513' }) ) export class FooterStatisticsTable extends TableWidget { public initialize(props) { if (props.template) { props.template?.widgets?.forEach((a) => { if (a.dslNodeType === DslDefinitionType.FIELD && this.statisticsFieldList.includes(a.name)) { a.statistics = true; } }); } super.initialize(props); return this; } // 需要表尾做合并的字段名称 public statisticsFieldList = ['fansNum']; @Widget.Reactive() protected get showFooter(): boolean | undefined { return true; } } 效果预览

    2024年10月14日
    2.2K00
  • 表单页如何在服务端动作点击后让整个表单都处于loading状态

    介绍 在业务场景中,有时候由于提交的数据很多,导致服务端动作耗时较长,为了保证这个过程中表单内的字段不再能被编辑,我们可以通过自定义能力将整个表单区域处于loading状态 自定义动作组件代码 import { ActionType, ActionWidget, BaseElementViewWidget, BaseView, ClickResult, ServerActionWidget, SPI, Widget } from '@kunlun/dependencies'; @SPI.ClassFactory(ActionWidget.Token({ actionType: ActionType.Server })) class LoadingServerActionWidget extends ServerActionWidget { protected async clickAction(): Promise<ClickResult> { const baseView = Widget.select(this.rootHandle) as unknown as BaseView; if (!baseView) { return super.clickAction(); } const baseViewWidget = baseView.getChildrenInstance().find((a) => a instanceof BaseElementViewWidget) as unknown as BaseElementViewWidget; if (!baseViewWidget) { return super.clickAction(); } return new Promise((resolve, reject) => { try { baseViewWidget.load(async () => { const res = await super.clickAction(); resolve(res); }); } catch (e) { reject(false); } }); } } 本案例知识点 BaseElementWidget提供了load方法将继承了该class的元素渲染的区域做整体loading交互,等入参的函数处理完成后恢复正常状态,其实所有继承了ActionWidget的组件也提供了这个能力让按钮在执行函数中的时候处于loading状态, 每个组件都有一个全局唯一的handle值,所在根视图的rootHandle,组件可以用this.rootHandle通过Widget.Select方法查找到所在的根视图组件,从视图的实例化子元素里可以查找到具体的业务类型视图组件,如详情页的DetailWidget、表单页的FormWidget、表格页的TableWidget,拿到这些实例后就可以操作里面的属性和方法了

    2024年5月29日
    2.1K00
  • oio-button 按钮

    主按钮:用于主行动点,一个操作区域只能有一个主按钮。 默认按钮:用于没有主次之分的一组行动点。 虚线按钮:常用于添加操作。 文本按钮:用于最次级的行动点。 链接按钮:一般用于链接,即导航至某位置。 以及四种状态属性与上面配合使用。 危险:删除/移动/修改权限等危险操作,一般需要二次确认。 禁用:行动点不可用的时候,一般需要文案解释。 加载中:用于异步操作等待反馈的时候,也可以避免多次提交。 API 按钮的属性说明如下: 属性 说明 类型 默认值 版本 block 将按钮宽度调整为其父宽度的选项 boolean false disabled 按钮失效状态 boolean false icon 设置按钮的图标类型 v-slot – loading 设置按钮载入状态 boolean | { delay: number } false type 设置按钮类型 primary | ghost | dashed | link | text | default default 事件 事件名称 说明 回调参数 版本 click 点击按钮时的回调 (event) => void 支持原生 button 的其他所有属性。

    2023年12月18日
    92500

Leave a Reply

Please Login to Comment