如何通过 Oineone 平台自定义视图

在 Oineone 平台上,自定义视图允许用户替换默认提供的页面布局,以使用自定义页面。本文将指导您如何利用 Oineone 提供的 API 来实现这一点。

默认视图介绍

Oineone 平台提供了多种默认视图,包括:

  • 表单视图
  • 表格视图
  • 表格视图 (左树右表)
  • 详情视图
  • 画廊视图
  • 树视图

每种视图都有其标准的 layout。自定义视图实际上是替换这些默认 layout 的过程。

默认的表单视图 layout

<view type="FORM">
  <element widget="actionBar" slot="actionBar" slotSupport="action">
    <xslot name="actions" slotSupport="action" />
  </element>
  <element widget="form" slot="form">
    <xslot name="fields" slotSupport="pack,field" />
  </element>
</view>

内嵌的的表单视图 layout

<view type="FORM">
  <element widget="form" slot="form">
    <xslot name="fields" slotSupport="pack,field" />
  </element>
</view>

默认的表格

<view type="TABLE">
  <pack widget="group">
    <view type="SEARCH">
      <element widget="search" slot="search" slotSupport="field" />
    </view>
  </pack>
  <pack widget="group" slot="tableGroup">
    <element widget="actionBar" slot="actionBar" slotSupport="action">
      <xslot name="actions" slotSupport="action" />
    </element>
    <element widget="table" slot="table" slotSupport="field">
      <element widget="expandColumn" slot="expandRow" />
      <xslot name="fields" slotSupport="field" />
      <element widget="rowActions" slot="rowActions" slotSupport="action" />
    </element>
  </pack>
</view>

内嵌的的表格

<view type="TABLE">
    <view type="SEARCH">
        <element widget="search" slot="search" slotSupport="field" />
    </view>
    <element widget="actionBar" slot="actionBar" slotSupport="action">
        <xslot name="actions" slotSupport="action" />
    </element>
    <element widget="table" slot="table">
        <element widget="expandColumn" slot="expandRow" />
        <xslot name="fields" slotSupport="field" />
        <element widget="rowActions" slot="rowActions" />
    </element>
</view>

左树右表

<view type="table">
  <pack title="" widget="group">
    <view type="search">
      <element slot="search" widget="search"/>
    </view>
  </pack>
  <pack title="" widget="group">
    <pack widget="row" wrap="false">
      <pack widget="col" width="257">
        <pack title="" widget="group">
          <pack widget="col">
            <element slot="tree" widget="tree"/>
          </pack>
        </pack>
      </pack>
      <pack mode="full" widget="col">
        <pack widget="row">
          <element justify="START" slot="actionBar" widget="actionBar"/>
          <element slot="table" widget="table">
            <element slot="expandRow" widget="expandColumn"/>
            <element slot="rowActions" widget="rowActions"/>
          </element>
        </pack>
      </pack>
    </pack>
  </pack>
</view>

默认详情视图

<view type="DETAIL">
    <element widget="actionBar" slot="actionBar" slotSupport="action">
        <xslot name="actions" slotSupport="action" />
    </element>
    <element widget="detail" slot="detail">
        <xslot name="fields" slotSupport="pack,field" />
    </element>
</view>

内嵌的详情视图

<view type="DETAIL">
    <element widget="detail" slot="detail">
        <xslot name="fields" slotSupport="pack,field" />
    </element>
</view>`

默认的画廊

<view type="GALLERY">
    <view type="SEARCH">
        <element widget="search" slot="search" slotSupport="field" />
    </view>
    <element widget="actionBar" slot="actionBar" slotSupport="action">
        <xslot name="actions" slotSupport="action" />
    </element>
    <element widget="gallery" slot="gallery">
        <element widget="card" slot="card" slotSupport="pack,field" />
    </element>
</view>

默认的树视图

<view type="TREE">
    <pack widget="group">
        <view type="SEARCH">
            <element widget="search" slot="search" slotSupport="field" />
        </view>
    </pack>
    <pack widget="group">
        <element widget="actionBar" slot="actionBar" slotSupport="action">
            <xslot name="actions" slotSupport="action" />
        </element>
        <element widget="card-cascader" slot="tree" slotSupport="nodes,node" />
    </pack>
</view>

上面的layout中,有些视图区分的内嵌,所谓的内嵌其实就是在一个视图中嵌入了另外一个视图,最常见的就是表单页面有个表格,那么这个表格就是内嵌的视图。

视图拆分介绍

如果您学过HTML,那么你应该知道,HTML中,我们可以用<div>来包裹内容,那么Oineone平台中的视图也是这样,只不过,Oineone平台中的视图,并不是一个<div>,而是一个<view>,我们可以一起来拆分下下面的代码。

// 最外层视图,是个表格类型的, 表格里面有两个字节点,
<view type="TABLE">
  // 第一个子节点里面有个搜索视图
  <pack widget="group">
    <view type="SEARCH">
      // 这里渲染的是搜索区域的视图
      <element widget="search" slot="search" slotSupport="field" />
    </view>
  </pack>

  // 第二个子节点里面有两个字节点
  <pack widget="group" slot="tableGroup">
    // 第一个子节点是个action,其实就是动作区域
    <element widget="actionBar" slot="actionBar" slotSupport="action">
      <xslot name="actions" slotSupport="action" />
    </element>

    // 第二个子节点是个table,渲染的是真实的table
    <element widget="table" slot="table" slotSupport="field">
      <element widget="expandColumn" slot="expandRow" />
      <xslot name="fields" slotSupport="field" />
      <element widget="rowActions" slot="rowActions" slotSupport="action" />
    </element>
  </pack>
</view>

如何替换默认视图

<view type="TABLE">
  // 保留搜索
  <pack widget="group">
    <view type="SEARCH">
      <element widget="search" slot="search" slotSupport="field" />
    </view>
  </pack>
  <pack widget="group" slot="tableGroup">
    // 保留动作
    <element widget="actionBar" slot="actionBar" slotSupport="action">
      <xslot name="actions" slotSupport="action" />
    </element>
    // 替换默认的表格
    <element widget="CustomTableWidget"></element>
  </pack>
</view>

然后将这个layout注册到平台中。

registerLayout(
  `<view type="TABLE">
    <pack widget="group">
      <view type="SEARCH">
        <element widget="search" slot="search" slotSupport="field" />
      </view>
    </pack>
    <pack widget="group" slot="tableGroup">
      <element widget="actionBar" slot="actionBar" slotSupport="action">
        <xslot name="actions" slotSupport="action" />
      </element>
      <element widget="CustomTableWidget"></element>
    </pack>
  </view>`,
  {
    model: '对应的模型',
    viewType: ViewType.Detail, // 视图类型
    actionName: '动作名称'
  }
);
// CustomTableWidget.ts

import { BaseElementWidget, SPI } from '@kunlun/dependencies';
import Component from './CustomTableWidget.vue';

@SPI.ClassFactory(BaseElementWidget.Token({ widget: 'CustomTableWidget' }))
export class CustomTableWidget extends BaseElementWidget {
  public initialize(props) {
    super.initialize(props);
    this.setComponent(Component);
    return this;
  }
}

这样一来我们就使用了自己的视图,是不是很简单呢。

注意项

如果您自定义的视图想用使用平台的功能,比如默认发去查询,那么只需要修改继承的类

BaseElementListViewWidget: 包含了默认的queryPage查询跟分页以及搜索的功能,用于list类型的视图

BaseElementObjectViewWidget: 包含了默认的queryOneconstruct方法,用于object类型的视图

总结

通过 Oineone 平台自定义视图,可以极大地增强应用的灵活性和个性化。遵循上述步骤,您可以轻松替换默认视图,实现定制化的用户界面。

Oinone社区 作者:汤乾华原创文章,如若转载,请注明出处:https://doc.oinone.top/frontend/6511.html

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

(0)
汤乾华的头像汤乾华数式员工
上一篇 2024年4月2日 pm6:59
下一篇 2024年4月6日 pm3:19

相关推荐

  • 前端 SPI 注册 + 渲染

    在阅读本篇文章之前,您需要学习以下知识点: 1: TS 结合 Vue 实现动态注册和响应式管理 前端开发者在使用 oinone 平台的时候会发现,不管是自定义字段还是视图,对应的 typescript 都会用到@SPI.ClassFactory(参数),然后在对用的class中重写initialize方法`: @SPI.ClassFactory(参数) export class CustomClass extends xxx { public initialize(props) { super.initialize(props); this.setComponent(FormString); return this; } } 本文将带您熟悉 oinone 前端的 SPI 注册机制以及 TS + Vue 的渲染过程。 不管是自定义字段还是视图@SPI.ClassFactory(参数)都是固定写法,区别在于参数不同,这篇文章里面详细描述了参数的定义。 SPI 注册机制 有自定义过字段、视图经验的开发者可能会发现,字段(表单字段)SPI 注册用的是FormFieldWidget.Token生成对应的参数,视图 SPI 注册用的是BaseElementWidget.Token,那么为什么要这样定义呢? 大家可以想象成现在有一个大的房子,房子里面有很多房间,每个房间都有自己的名字,比如FormFieldWidget就是房间的名字,BaseElementWidget也是房间的名字,这样一来我们就可以根据不同的房间存放不同的东西。 下面给大家展示下伪代码实现: class SPI { static container = new Map<string, WeakMap<object, object>>() static ClassFactory(token) { return (target) => { if(!SPI.container.get(token.type)) { SPI.container.set(token.type, new WeakMap()) } const services = SPI.container.get(token.type) services?.set(token, target) } } } class FormFieldWidget { static Token(options) { return { …options, type: 'Field' } } static Selector(options) { const fieldWidgets = SPI.container.get('Field') if(fieldWidgets) { return fieldWidgets.get(options)! } return null } } @SPI.ClassFactory(FormFieldWidget.Token({ viewType: 'Form', ttype: 'String', widget: 'Input' })) class StringWidget { } // 字段元数据 const fieldMeta = { name: "name", field: "name", mode: 'demo.model', widget: 'Input', ttype: 'String', viewType: 'Form' } // 找到对应的widget const widget = FormFieldWidget.Selector({ viewType: fieldMeta.viewType, ttype: fieldMeta.ttype, widget: fieldMeta.widget, }) 在上述代码中,我们主要是做了这么写事情: 1.SPI class class SPI { static container = new Map<string, WeakMap<object, object>>() } SPI 类是一个静态类,用于管理服务的注册和获取。 container 是一个静态属性,类型是 Map,它的键是字符串,值是 WeakMap。这个结构允许我们为每个服务类型(例如,Field)管理多个服务实例。 2.ClassFactory 方法 static ClassFactory(token) { return (target) => { if…

    2024年9月26日
    1.5K00
  • oio-input 输入框

    代码演示 <oio-input v-model:value="value"></oio-input> API Input 参数 说明 类型 默认值 版本 addonAfter 带标签的 input,设置后置标签 string|slot addonBefore 带标签的 input,设置前置标签 string|slot allowClear 可以点击清除图标删除内容 boolean defaultValue 输入框默认内容 string disabled 是否禁用状态,默认为 false boolean false maxlength 最大长度 number prefix 带有前缀图标的 input slot showCount 是否展示字数 boolean false suffix 带有后缀图标的 input slot type 声明 input 类型,同原生 input 标签的 type 属性,见:MDN(请直接使用 <a-textarea /> 代替 type="textarea")。 string text value(v-model:value) 输入框内容 string Input 事件 事件名称 说明 回调参数 update:value 输入框内容变化时的回调 function(e) pressEnter 按下回车的回调 function(e) Input.Search 代码演示 <oio-input-search v-model:value="value"></oio-input-search> Input.Search 事件 事件名称 说明 回调参数 search 点击搜索或按下回车键时的回调 function(value, event) 其余属性和 Input 一致。

    2023年12月18日
    2.2K00
  • 表格主题配置(v4)

    TableThemeConfig /** * 表格主题配置 */ export interface TableThemeConfig { border: boolean | string; stripe: boolean; isCurrent: boolean; isHover: boolean; /** * 表格列主题配置 */ column: Partial<TableColumnThemeConfig>; } /** * 表格列主题配置 */ export interface TableColumnThemeConfig { /** * <h3>最小宽度</h3> * <ul> * <li>boolean: enabled column width auto compute</li> * <li>number: using css width (default: px)</li> * <li>string: using css width</li> * <li> * object: auto compute width for label by default function * <ul> * <li>min: min min width (default: 120)</li> * <li>max: max min width (default: 432)</li> * <li>chineseWidth: chinese width (default: 14 -> fontSize: 14px)</li> * <li>otherWidth: non chinese width (default: 9 -> fontSize: 14px)</li> * <li>sortableFixWidth: sortable handle width (default: 40)</li> * <li>nonSortableFixWidth: non sortable fix width (default: 22)</li> * </ul> * </li> * <li>function: auto compute width for label by function</li> * </ul> */ minWidth: boolean | number | string | Partial<TableColumnMinWidthComputeConfig> | TableColumnMinWidthComputeFunction; /** * 操作列 */ operation: { /** * 宽度 (default: 165) */ width?: number | string; /** * 最小宽度 (default: 120) */ minWidth?: number | string; }; } export interface TableColumnMinWidthComputeConfig { min: number;…

    2023年11月1日
    1.2K00
  • oio-select 选择器

    API Select props 参数 说明 类型 默认值 版本 allowClear 支持清除 boolean false autofocus 默认获取焦点 boolean false clearIcon 自定义的多选框清空图标 VNode | slot – disabled 是否禁用 boolean false dropdownClassName 下拉菜单的 className 属性 string – dropdownRender 自定义下拉框内容 ({menuNode: VNode, props}) => VNode | v-slot – filterOption 是否根据输入项进行筛选。当其为一个函数时,会接收 inputValue option 两个参数,当 option 符合筛选条件时,应返回 true,反之则返回 false。 boolean | function(inputValue, option) true getTriggerContainer 菜单渲染父节点。默认渲染到 body 上,如果你遇到菜单滚动定位问题,试试修改为滚动的区域,并相对其定位。 function(triggerNode) () => document.body menuItemSelectedIcon 自定义当前选中的条目图标 VNode | slot – options options 数据,如果设置则不需要手动构造 selectOption 节点 array<{value, label, [disabled, key, title]}> [] placeholder 选择框默认文字 string|slot – removeIcon 自定义的多选框清除图标 VNode | slot – suffixIcon 自定义的选择框后缀图标 VNode | slot – value(v-model:value) 指定当前选中的条目 string|string[]|number|number[] – 注意,如果发现下拉菜单跟随页面滚动,或者需要在其他弹层中触发 Select,请尝试使用 getPopupContainer={triggerNode => triggerNode.parentNode} 将下拉弹层渲染节点固定在触发器的父元素中。 事件 事件名称 说明 回调参数 blur 失去焦点的时回调 function change 选中 option,或 input 的 value 变化(combobox 模式下)时,调用此函数 function(value, option:Option/Array<Option>) deselect 取消选中时调用,参数为选中项的 value (或 key) 值,仅在 multiple 或 tags 模式下生效 function(value,option:Option) dropdownVisibleChange 展开下拉菜单的回调 function(open) focus 获得焦点时回调 function inputKeyDown 键盘按下时回调 function mouseenter 鼠标移入时回调 function mouseleave 鼠标移出时回调 function popupScroll 下拉列表滚动时的回调 function search 文本框值变化时回调 function(value: string) select 被选中时调用,参数为选中项的 value (或 key) 值 function(value, option:Option)

    2023年12月18日
    79900
  • 如何增加页面消息通知轮询的间隔或者关闭轮询

    场景 oinone的前端页面默认自带了消息通知功能,在顶部状态栏可以看到消息的查看入口,默认每隔5秒查询一次最新的消息,我们可以通过自定义消息组件增加该间隔或者是关闭轮询 示例代码 修改轮询间隔 import { MaskWidget, NotificationWidget, SPI } from '@kunlun/dependencies'; @SPI.ClassFactory(MaskWidget.Token({ widget: 'notification' })) export class DemoNotificationWidget extends NotificationWidget { /** * 轮询间隔时间,单位: 秒 * @protected */ protected msgDelay = 30000; } 关闭轮询 import { MaskWidget, NotificationWidget, SPI } from '@kunlun/dependencies'; @SPI.ClassFactory(MaskWidget.Token({ widget: 'notification' })) export class DemoNotificationWidget extends NotificationWidget { protected mounted() { super.mounted(); // 清除轮询的定时器 this.msgTimer && clearInterval(this.msgTimer); // 挂载后手动查询一次消息 this.getMsgTotal(); } }

    2024年8月20日
    1.3K00

Leave a Reply

登录后才能评论