如何通过 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低代码应用平台体验

Like (0)
汤乾华's avatar汤乾华数式员工
Previous 2024年4月2日 pm6:59
Next 2024年4月6日 pm3:19

相关推荐

  • 【前端】登录页面扩展点

    登录页面扩展点 场景 1: 登录之前需要二次确认框2: 前端默认的错误提示允许被修改3: 后端返回的错误提示允许被修改4: 登录后跳转到自定义的页面 方案 前端默认错误可枚举 errorMessages: { loginEmpty: '用户名不能为空', passwordEmpty: '密码不能为空', picCodeEmpty: '图形验证码不能为空', phoneEmpty: '手机号不能为空', verificationCodeEmpty: '验证码不能为空', picCodeError: '图形验证码错误', inputVerificationCodeAlign: '请重新输入验证码' } 登录按钮添加拓展点beforeClick、afterClick 代码 新增一个ts文件,继承平台默认的LoginPageWidget @SPI.ClassFactory(RouterWidget.Token({ widget: 'Login' })) export class CustomLoginPageWidget extends LoginPageWidget { constructor() { super(); // 修改前端默认的错误文案 this.errorMessages.loginEmpty = '登录用户名不能为空'; } /** * 用来处理点击「登录」之前的事件,可以做二次确定或者其他的逻辑 * 只有return true,才会继续往下执行 */ public beforeClick(): Promise<Boolean | null | undefined> { return new Promise((resolve) => { Modal.confirm({ title: '提示', content: '是否登录?', onOk: () => { resolve(true); } }); }); } /** * * @param result 后端接口返回的数据 * * 用来处理「登录」接口调用后的逻辑,可以修改后端返回的错误文案,也可以自定义 * * 只有return true,才会执行默认的跳转事件 */ public afterClick(result): Promise<any | null | undefined> { // if(result.redirect) { // 自定义跳转 //return false //} if (result.errorCode === 20060023) { result.errorMsg = '手机号不对,请联系管理员'; } return result; } }

    2023年11月1日
    1.4K00
  • 【界面设计器】自定义字段组件实战——表格字段组合展示

    阅读之前 此文章为实战教程,已假定你熟悉了【界面设计器】较为完整的【自定义组件】相关内容。 如果在阅读过程中出现的部分概念无法理解,请自行学习相关内容。【前端】文章目录 业务背景 表格中的一列使用多个字段组合展示。 演示内容:表格中存在两列,【编码】和【基础信息】。将【名称】、【创建时间】、【更新时间】在【基础信息】一列展示。 业务分析及实现思路 从需求来看,我们需要实现一个【组合列】组件,并且该组件允许在【表格】视图中使用。由于【组合列】本身也是一个字段,因此这里需要选择需要组合字段中的其中一个字段作为组件切换的基础字段,比如我们可以选择【名称】字段作为基础字段。 在【组合列】组件的属性面板中,我们需要再自定义一个【组合列配置】组件,用来选择需要将哪些字段进行组合,以及为每个组合提供一些基础配置。 这里需要理解一个基本概念,即【组合列】的属性面板是【组合列配置】的【执行页面】。所有组件的属性面板在【执行页面】时都是【表单】视图。 因此我们可以实现一个【组合列配置】组件,并且该组件允许在【表单】视图中使用。其业务类型使用【文本】,我们在保存配置数据时,可以使用JSON数据结构来存储复杂结构。(这里的实现思路并非是最符合协议设定的,但可以满足绝大多数组件场景) 在【组合列配置】组件中,我们可以允许用户添加/移除组合,并且每个组合有两个属性,【标题】和【字段】。 准备工作 此处你应该已经在某个业务模型下,可以完整执行当前模型的全部【增删改查】操作。 业务模型定义 (以下仅展示本文章用到的模型字段,忽略其他无关字段。) 名称 API名称 业务类型 是否多值 长度(单值长度) 编码 code 文本 否 128 名称 name 文本 否 128 创建时间 createDate 日期时间 否 – 更新时间 updateDate 日期时间 否 – 实现页面效果展示 表格视图 创建组件、元件 准备工作完成后,我们需要根据【业务背景】确定【组件】以及【元件】相关信息,并在【界面设计器】中进行创建。 以下操作过程将省略详细步骤,仅展示可能需要确认的关键页面。 创建组合列组件 创建组合列元件 创建组合列配置组件 创建组合列配置元件 设计组合列元件属性面板 创建compositeConfig字段,并切换至【组合配置】组件。 设计组合列配置元件属性面板 启动SDK工程进行组件基本功能开发 PS:这里由于我们创建了两个组件,因此,将SDK分开下载后,然后将组合列配置SDK中的演示代码(kunlun-plugin/src)移动到组合列SDK中,在同一工程中进行开发,最后只需将相关JS文件和CSS文件上传到组合列组件中即可,组合列配置组件可以不进行上传。这里需要注意的是,上传多个包含相同组件功能的JS文件和CSS文件可能在运行时导致无法正常替换、冲突等问题。 (npm相关操作请自行查看SDK工程中内置的README.MD) 开发步骤参考 打开【表格】视图,将【名称】字段的组件切换为【组合列】组件。 在属性面板中看到【组合列配置】组件,并优先实现【组合列配置】组件。这里的属性面板就是【组合列配置】对应的【执行页面】。 当【组合列配置】组件可以按照预先设计的数据结构正确保存compositeConfig属性时,可以在【组合列】组件中的props定义中直接获取该属性,接下来就可以进行【组合列】组件的开发。 代码实现参考 工程结构 typing.ts export interface CompositeConfig { key: string; label?: string; field?: string; value?: string; } CompositeColumnConfig.vue <template> <div class="composite-column-config"> <oio-form v-for="item in list" :data="item" :key="item.key"> <oio-form-item label="标题" name="label"> <oio-input v-model:value="item.label" /> </oio-form-item> <oio-form-item label="字段" name="field"> <a-select class="oio-select" dropdownClassName="oio-select-dropdown" v-model:value="item.field" :options="fields" /> </oio-form-item> <oio-button type="link" @click="() => removeItem(item)">移除</oio-button> </oio-form> <oio-button type="primary" block @click="addItem">添加</oio-button> </div> </template> <script lang="ts"> import { uniqueKeyGenerator } from '@kunlun/dependencies'; import { WidgetInstance } from '@kunlun/ui-designer-dependencies'; import { OioButton, OioForm, OioFormItem, OioInput } from '@kunlun/vue-ui-antd'; import { Select as ASelect } from 'ant-design-vue'; import { computed, defineComponent, PropType, ref, watch } from 'vue'; import { CompositeConfig } from '../../typing'; export default defineComponent({ name: 'CompositeColumnConfig', components: { OioForm, OioFormItem, OioInput, OioButton, ASelect }, props: { currentInstance: { type:…

    2023年11月1日
    1.7K00
  • OioProvider详解

    OioProvider OioProvider是平台的初始化入口。 示例入口 main.ts import { VueOioProvider } from '@kunlun/dependencies'; VueOioProvider(); 网络请求/响应配置 http 平台统一使用apollo作为统一的http请求发起服务,并使用GraphQL协议作为前后端协议。 参考文档: apollo-client graphql 配置方式 VueOioProvider({ http?: OioHttpConfig }); OioHttpConfig /** * OioHttp配置 */ export interface OioHttpConfig { /** * base url */ url: string; /** * 拦截器配置 */ interceptor?: Partial<InterceptorOptions>; /** * 中间件配置(优先于拦截器) */ middleware?: NetworkMiddlewareHandler | NetworkMiddlewareHandler[]; } 内置拦截器可选项 InterceptorOptions /** * 拦截器可选项 */ export interface InterceptorOptions { /** * 网络错误拦截器 */ networkError: NetworkInterceptor; /** * 请求成功拦截器 (success) */ requestSuccess: NetworkInterceptor; /** * 重定向拦截器 (success) */ actionRedirect: NetworkInterceptor; /** * 登录重定向拦截器 (error) */ loginRedirect: NetworkInterceptor; /** * 请求错误拦截器 (error) */ requestError: NetworkInterceptor; /** * MessageHub拦截器 (success/error) */ messageHub: NetworkInterceptor; /** * 前置拦截器 */ beforeInterceptors: NetworkInterceptor | NetworkInterceptor[]; /** * 后置拦截器 */ afterInterceptors: NetworkInterceptor | NetworkInterceptor[]; } 内置拦截器执行顺序: beforeInterceptors:前置拦截器 networkError:网络错误 actionRedirect:重定向 requestSuccess 请求成功 loginRedirect:登录重定向 requestError:请求错误 messageHub:MessageHub afterInterceptors:后置拦截器 NetworkInterceptor /** * <h3>网络请求拦截器</h3> * <ul> * <li>拦截器将按照注册顺序依次执行</li> * <li>当任何一个拦截器返回false时,将中断拦截器执行</li> * <li>内置拦截器总是优先于自定义拦截器执行</li> * </ul> * */ export interface NetworkInterceptor { /** * 成功拦截 * @param response 响应结果 */ success?(response: IResponseResult): ReturnPromise<boolean>; /** * 错误拦截 * @param response 响应结果 */ error?(response: IResponseErrorResult): ReturnPromise<boolean>; } 自定义路由配置 router 配置方式 VueOioProvider({ router?: RouterPath[]…

    2023年11月6日
    2.2K00
  • oio-drawer抽屉

    屏幕边缘滑出的浮层面板。 何时使用 抽屉从父窗体边缘滑入,覆盖住部分父窗体内容。用户在抽屉内操作时不必离开当前任务,操作完成后,可以平滑地回到原任务。 当需要一个附加的面板来控制父窗体内容,这个面板在需要时呼出。比如,控制界面展示样式,往界面中添加内容。 当需要在当前任务流中插入临时任务,创建或预览附加内容。比如展示协议条款,创建子对象。 API 参数 说明 类型 默认值 版本 class 对话框外层容器的类名 string – closable 是否显示左上角的关闭按钮 boolean true closeIcon 自定义关闭图标 VNode | slot destroyOnClose 关闭时销毁 Drawer 里的子元素 boolean false footer 抽屉的页脚 VNode | slot – getTriggerContainer 指定 Drawer 挂载的 HTML 节点 HTMLElement | () => HTMLElement | Selectors ‘body’ height 高度, 在 placement 为 top 或 bottom 时使用 string | number keyboard 是否支持键盘 esc 关闭 boolean true mask 是否展示遮罩 Boolean true maskClosable 点击蒙层是否允许关闭 boolean true placement 抽屉的方向 ‘top’ | ‘right’ | ‘bottom’ | ‘left’ ‘right’ style 可用于设置 Drawer 最外层容器的样式,和 drawerStyle 的区别是作用节点包括 mask CSSProperties – title 标题 string | slot – visible(v-model:visible) Drawer 是否可见 boolean – width 宽度 string | number 378 zIndex 设置 Drawer 的 z-index Number 1000 cancelCallback 点击遮罩层或右上角叉或取消按钮的回调, return true则关闭弹窗 function(e) enterCallback 点击确定回调 function(e)

    2023年12月18日
    1.5K00
  • 环境运行时Jar版本控制

    环境运行时Jar版本控制 前景 为了避免基于低代码定义产生的元数据错乱。因此产生了运行时Jar版本检查功能。 现象 如果当前运行时依赖的Ja版本低于已安装版本,启动时会有如下类似信息提示: 解决 按照提示升级依赖Jar版本 通过启动参数 -PgoBack=true 强制覆盖安装当前运行时版本 java -jar 方式 java -jar xxx.jar -PgoBack=true [其他参数] mvn spring-boot run 方式 mvn clean compile spring-boot:run -Dspring-boot.run.arguments=”-PgoBack=true [其他参数]”

    2025年3月10日
    1.8K00

Leave a Reply

Please Login to Comment