如何通过 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

相关推荐

  • 弹窗或抽屉表单视图rootRecord获取不到对应的数据

    在平台默认的实现中,rootRecord 代表的是根视图的数据。比如,在表格页面点击按钮打开了弹窗,弹窗里面包含一个表单视图,但是该视图获取 rootRecord 却是最外层的视图数据。 如果期望 rootRecord 数据是弹窗的视图数据,需要手动修改表单的 rootRecord。下面的代码演示了如何重写 rootData 以确保其数据是弹窗的数据: @SPI.ClassFactory( BaseElementWidget.Token({ viewType: ViewType.Form, widget: 'MyCustomFormWidgetFormWidget' }) ) export class MyCustomFormWidgetFormWidget extends FormWidget { @Widget.Reactive() @Widget.Provide() public get rootData(): any[] | undefined { return this.activeRecords; } } 上述代码重写了 rootData,这样就可以确保 rootData 的数据是弹窗的数据。 接下来就是注册: registerLayout( ` <view type="FORM"> <element widget="actionBar" slot="actionBar" slotSupport="action"> <xslot name="actions" slotSupport="action" /> </element> <element widget="MyCustomFormWidgetFormWidget" slot="form"> <xslot name="fields" slotSupport="pack,field" /> </element> </view> `, { viewType: ViewType.Form, model: '弹窗模型', viewName: '弹窗视图名称' } )

    2023年11月13日
    1.7K00
  • 打开弹窗的action,传入默认的查询条件不生效

    场景 form视图中的action,点击后打开table的弹窗的,xml中配置的filter,但是table查询的时候没有带上查询条件: <action name=”action_name” label=”打开tabel弹窗视图” filter=”id==${activeRecord.id}” /> 解决方案 将xml中的activeRecord修改成openerRecord即可。 <action name=”action_name” label=”打开tabel弹窗视图” filter=”id==${openerRecord.id}” />

    2023年11月1日
    1.5K00
  • 自定义mutation时出现校验不过时,如何排查

    场景描述 用户在自定义接口提供给前端调用时 @Action(displayName = "注册", bindingType = ViewTypeEnum.CUSTOM) public BaseResponse register(UserZhgl data) { //…逻辑 return result; } import java.io.Serializable; public class BaseResponse implements Serializable { private String code; private String msg; public BaseResponse() { } public BaseResponse(String code, String msg) { this.code = code; this.msg = msg; } public String getCode() { return code; } public void setCode(String code) { this.code = code; } public String getMsg() { return msg; } public void setMsg(String msg) { this.msg = msg; } } gql执行时出现报错 { "errors":[ { "message":"Validation error of type SubSelectionNotAllowed: Sub selection not allowed on leaf type Object of field register @ 'zhglMutation/register'", "locations":[ { "line":3, "column":3 } ], "extensions":{ "classification":"ValidationError" } } ] } 解决方案 1.返回对象不为空时,对象必须是模型,否则无法解析返回参数2.前端调用GQL异常时,可以用Insomnia工具对GQL进行测试,根据错误提示对GQL进行修改和排查3.GQL正常情况下,执行以后可根据后端日志进行错误排查

    2023年11月1日
    1.6K00
  • 移动端5.0.x启动、打包代码报错

    在5.0.x版本中,移动端mobile-base包是源码开放的,所以项目在启动的时候可能会报错,请按照下面的步骤修改。 打开boot工程中的package.json "dependencies"中添加 "lodash-es": "4.17.21" "devDependencies"中添加 "@types/lodash-es": "4.17.12" 在main.ts中删除 import '@kunlun/vue-mobile-base/dist/kunlun-vue-mobile-base.css'

    2024年7月17日
    1.7K00
  • 集成开放-开放接口如何鉴权加密

    使用前提 已经阅读过文档【oinone 7天从入门到精通】的6.2章节-集成平台 已经依赖了内置模块集成平台eip boot启动工程pom.xml新增jar依赖 <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-eip2-core</artifactId> </dependency> <dependency> <groupId>pro.shushi.pamirs.core</groupId> <artifactId>pamirs-eip2-view</artifactId> </dependency> 配置文件application.yml新增启动依赖模块 pamirs: boot: modules: – eip eip: open-api: enabled: true route: # 开放接口访问IP,开放外网可以配置为0.0.0.0 host: 127.0.0.1 # 开放接口访问端口 port: 8094 # 认证Token加密的AES密钥 aes-key: NxDZUddmvdu3QQpd5jIww2skNx6U0w0uOAXj3NUCLu8= 一、新增开放接口示例代码 开放接口类定义 package pro.shushi.pamirs.demo.api.open; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; @Fun(TestOpenApiModelService.FUN_NAMESPACE) public interface TestOpenApiModelService { String FUN_NAMESPACE = "demo.open.TestOpenApiModelService"; @Function TestOpenApiModel queryById(Long id); } 开放接口实现类 package pro.shushi.pamirs.demo.core.open; import org.apache.camel.ExtendedExchange; import org.springframework.stereotype.Component; import pro.shushi.pamirs.core.common.SuperMap; import pro.shushi.pamirs.demo.api.open.TestEipConfig; import pro.shushi.pamirs.demo.api.open.TestOpenApiModel; import pro.shushi.pamirs.demo.api.open.TestOpenApiModelService; import pro.shushi.pamirs.demo.api.open.TestOpenApiResponse; import pro.shushi.pamirs.eip.api.IEipContext; import pro.shushi.pamirs.eip.api.annotation.Open; import pro.shushi.pamirs.eip.api.constant.EipFunctionConstant; import pro.shushi.pamirs.eip.api.enmu.EipExpEnumerate; import pro.shushi.pamirs.eip.api.entity.openapi.OpenEipResult; import pro.shushi.pamirs.meta.annotation.Fun; import pro.shushi.pamirs.meta.annotation.Function; import pro.shushi.pamirs.meta.common.exception.PamirsException; import java.util.Optional; @Fun(TestOpenApiModelService.FUN_NAMESPACE) @Component public class TestOpenApiModelServiceImpl implements TestOpenApiModelService { @Override @Function public TestOpenApiModel queryById(Long id) { return new TestOpenApiModel().queryById(id); } @Function @Open @Open.Advanced( authenticationProcessorFun = EipFunctionConstant.DEFAULT_AUTHENTICATION_PROCESSOR_FUN, authenticationProcessorNamespace = EipFunctionConstant.FUNCTION_NAMESPACE ) public OpenEipResult<TestOpenApiResponse> queryById4Open(IEipContext<SuperMap> context , ExtendedExchange exchange) { String id = Optional.ofNullable(String.valueOf(context.getInterfaceContext().getIteration("id"))).orElse(""); TestOpenApiModel temp = queryById(Long.valueOf(id)); TestOpenApiResponse response = new TestOpenApiResponse(); if(temp != null ) { response.setAge(temp.getAge()); response.setId(temp.getId()); response.setName(temp.getName()); }else{ response.setAge(1); response.setId(1L); response.setName("oinone eip test"); } OpenEipResult<TestOpenApiResponse> result = new OpenEipResult<TestOpenApiResponse>(response); return result; } @Function @Open(config = TestEipConfig.class,path = "error") @Open.Advanced( httpMethod = "post", authenticationProcessorFun = EipFunctionConstant.DEFAULT_AUTHENTICATION_PROCESSOR_FUN, authenticationProcessorNamespace…

    2024年7月25日
    1.3K00

Leave a Reply

登录后才能评论