前端自定义左树右表中的树

在 oinone 平台中,提供了默认的左树右表的视图,用户可以通过界面设计器配置,默认的树视图不一定满足所有需求,尤其当需要自定义功能或复杂的交互时,我们可以通过自定义视图来实现更灵活的展现。

本文将带你一步步了解如何自定义左树右表视图中的树组件。

自定义树视图

1. 使用界面设计器配置视图

首先,我们需要通过界面设计器生成基础的左树右表视图。界面设计器允许用户根据不同需求进行拖拽配置,快速创建可视化界面。

配置完视图之后,我们可以重写左侧的树组件。Oinone 的默认树组件是 TableSearchTreeWidget,通过自定义的方式,我们可以实现更高级的功能。

2. 重写 TableSearchTreeWidget

import { BaseElementWidget, SPI, TableSearchTreeWidget, ViewType } from '@kunlun/dependencies';
import CustomTableSearchTree from './CustomTableSearchTree.vue';

@SPI.ClassFactory(
  BaseElementWidget.Token({
    viewType: [ViewType.Table, ViewType.Form],
    widget: 'tree',
    model: 'resource.k2.Model0000000100' // 改成自己的模型
  })
)
export class CustomTableSearchTreeWidget extends TableSearchTreeWidget {
  public initialize(props) {
    super.initialize(props);
    this.setComponent(CustomTableSearchTree);
    return this;
  }
}

3. 定义 Vue 树组件

接下来,我们来实现 CustomTableSearchTree.vue 组件。这个组件将处理树的数据加载、节点选中等逻辑。你可以根据项目的需要修改其中的交互逻辑或 UI 设计。

<template>
  <a-tree :load-data="onLoadData" :tree-data="treeData" @select="onSelected" />
</template>
<script lang="ts">
import { OioTreeNode, TreeUtils } from '@kunlun/dependencies';
import { computed, defineComponent } from 'vue';

export default defineComponent({
  props: {
    rootNode: {
      type: Object
    },
    loadData: {
      type: Function,
      required: true
    },
    onSelected: {
      type: Function,
      required: true
    }
  },
  setup(props) {
    // // 计算树的数据源,使用 TreeUtils 处理
    const treeData = computed(() => {
      return TreeUtils.fillLoadMoreAction([...(props.rootNode?.children || [])]);
    });

    // 异步加载子节点
    const onLoadData = async (node) => {
      return await props.loadData(node.dataRef);
    };

    // 处理节点选中事件
    const onSelected = (
      selectedKeys: string[],
      e: { nativeEvent: PointerEvent; node: { dataRef: OioTreeNode }; selected: boolean }
    ) => {
      props.onSelected?.(e.node.dataRef, e.selected);
    };

    return {
      treeData,

      onLoadData,
      onSelected
    };
  }
});
</script>

4. 自定义 UI

如果你希望修改树组件的 UI,比如调整样式或交互方式,可以在 CustomTableSearchTree.vue 文件中根据需要进行调整。通过这个自定义组件,你可以灵活地控制树的外观和行为,满足具体的业务需求。

默认选择第一条数据

有时在使用树结构时,我们希望页面加载后默认选中第一条数据。为此,我们可以监听 treeData 的变化,并在数据加载完成时,自动触发选中第一条记录的操作。

const stop = watch(
  () => treeData.value.length,
  async (len) => {
    if (!len) {
      return;
    }

    // 选中树中的第一条记录
    selectedKeys.value = [treeData.value[0].key];
    props.onSelected?.(treeData.value[0].value.metadata, true);
    stop(); // 停止监听
  },
  {
    immediate: true
  }
);

表格的新建按钮,获取选中的树节点

在树组件中,我们希望右侧的表格的上方的 新建按钮 点击的时候,可以获取当前树的 ID 作为条件传递给后端。那么这个时候,我们需要通过自定义 action 的方式来实现。

可以参考这篇文章

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

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

Like (0)
汤乾华's avatar汤乾华数式员工
Previous 2024年10月18日 am9:37
Next 2024年10月21日 pm3:41

相关推荐

  • 前端自定义请求入门版

    在开发过程中,为了满足业务场景、增加灵活性,前端自定义请求不可避免。下面将会从——自定义 mask、自定义表格(表单等)、自定义字段三个实际场景的角度,介绍自定义请求。这篇文章把请求都写在了 ts 中,这样便于继承重写,如果不习惯 ts 的写法,把请求写在 vue 里也是可以的。 1. 自定义 mask mask 组件通常会有一个特点:在不同页面不同模型或不同应用下都展示,与业务模型无关,且往往只需要请求一次。同时可能有精确控制请求体大小的需求,这就很适合采取手写 GraphQL 的方式。 例如,我要重写顶部 mask 中的用户组件,展示用户信息。这个请求就只需请求一次,而且不需要复用,就很适合手写 GraphQL。 这里继承平台的用户组件,然后在代码中写死 GraphQL 发起请求。但是 GraphQL 语句怎么拼呢?我们可以去默认页面,打开浏览器控制台,找到相应的请求,把 GraphQL 语句复制出来,这里复制下默认的用户请求。 http.query 参数的构造、相应结果的获取都能从请求中得到。可以看到我这里精简了请求,只取了用户名。 TS import { SPI, UserWidget, MaskWidget, Widget, http } from '@kunlun/dependencies'; import Test from './Test.vue'; @SPI.ClassFactory(MaskWidget.Token({ widget: 'user' })) export class TestWidget extends UserWidget { public initialize(props) { super.initialize(props); this.setComponent(Test); return this; } // 添加响应式注解,这样能在 vue 中接受到 ts 中的变量 @Widget.Reactive() public testUserInfo: { pamirsUser: { name: string } } | undefined; public async queryUser() { const query = ` { topBarUserBlockQuery { construct(data: {}) { pamirsUser { name } } } } `; const result = await http.query('user', query); this.testUserInfo = result.data['topBarUserBlockQuery']['construct'] as { pamirsUser: { name: string } }; } public mounted() { this.queryUser(); } } VUE <template> <div class="Test"> {{ testUserInfo }} </div> </template> <script lang="ts"> import { defineComponent } from 'vue'; export default defineComponent({ name: 'Test', props: ['testUserInfo'] }); </script> 效果如下: 2. 自定义表格(表单)等视图元素组件 2-1. 自定义表格 2-1-1. 自定义表格自动获取数据 Oinone 提供了前端组件的默认实现。所以生成默认页面的时候,请求数据都是通的,可以看到表格、表单、表单里的字段等组件数据都是能回填的。所以这里继承平台的表格组件,就有了平台表格自动获取数据的能力。 TS import { BaseElementWidget, SPI, TABLE_WIDGET, TableWidget, ViewType } from '@kunlun/dependencies'; import Test from './Test.vue'; @SPI.ClassFactory( BaseElementWidget.Token({ viewType: ViewType.Table, widget:…

    2025年4月17日
    83800
  • 【前端】移动端工程结构最佳实践(v4/v5)

    阅读之前 你应该: 了解node与npm相关内容 了解lerna包管理工具的相关内容 官方文档 了解git仓库的相关内容 了解rollup的相关内容 工程结构包示例 Vue项目结构包下载-v4.7.xVue项目结构包下载-v5.2.x 工程结构详解 工程结构 ├── packages │   ├── kunlun-mobile-boot │   │   ├── package.json │   │   ├── public │   │   │   ├── favicon.ico │   │   │   └── index.html │   │   ├── src │   │   │   ├── main.ts │   │   │   └── shim-vue.d.ts │   │   ├── tsconfig.json │   │   └── vue.config.js │   ├── kunlun-module-mobile-demo │   │   ├── scripts │   │   │   ├── postpublish.js │   │   │   └── prepublish-only.js │   │   ├── src │   │   │   ├── index.ts │   │   │   └── shim-vue.d.ts │   │   ├── index.ts │   │   ├── package.json │   │   ├── rollup.config.js │   │   └── tsconfig.json │   └── kunlun-modules-mobile-demo │   ├── scripts │   │   ├── build.config.js │   │   ├── postpublish.js │   │   └── prepublish-only.js │   ├── packages │   │   ├── module-demo1 │   │   │   ├── index.ts │   │   │   ├── package.json │   │   │   ├── rollup.config.js │   │   │   └── src │   │   │   ├── index.ts │   │   │   └── shim-vue.d.ts │   │   ├── module-demo2 │   │   │   ├── index.ts │   │   │   ├── package.json │   │   │   ├── rollup.config.js │   │   │  …

    前端 2023年11月1日
    2.2K00
  • 自定义视图部分区域渲染设计器的配置

    自定义视图与界面设计器配置对接 在日常开发中,我们经常会遇到自定义视图的需求。自定义视图不仅需要与平台机制结合,还要实现与界面设计器中配置的字段和动作的无缝对接。本文将介绍如何将自定义视图与界面设计器中配置的字段和动作的无缝对接,实现字段和动作的渲染。 用大白话来讲就是:当前页面一部分是自定义的,一部分是设计器生成的 代码地址 目录 自定义表单视图与字段、动作的结合 自定义表格视图与字段、动作的结合 自定义表单视图与字段、动作的结合 首先需要在界面设计器配置好对应界面,虽然配置的页面样式跟期望展示的 UI 的不一样,但是数据的分发、汇总以及动作的交互也是一致的,所以我们可以通过自定义的方式替换这个页面的 UI,但是数据以及动作,是完全可以通过平台的能力获取的。 注册表单对应的 SPI // CustomFormWidget.ts import CustomForm from './CustomForm.vue'; @SPI.ClassFactory( BaseElementWidget.Token({ viewType: ViewType.Form, widget: 'CustomFormWidget' }) ) export class CustomFormWidget extends FormWidget { public initialize(props: BaseElementObjectViewWidgetProps): this { super.initialize(props); this.setComponent(CustomForm); return this; } } <!– CustomForm.vue –> <template> <div class="custom-form-container"> <div class="custom-form-tip">自定义视图</div> </div> </template> <script lang="ts"> import { DslRender, DslRenderDefinition, PropRecordHelper } from '@kunlun/dependencies'; import { createVNode, defineComponent, onMounted, PropType, ref, VNode } from 'vue'; export default defineComponent({ inheritAttrs: false, props: { formData: { type: Object as PropType<Record<string, any>>, default: () => ({}) } } }); </script> 在上述的代码中,我们继承的是 FormWidget,那么这个页面会自动发起对应的请求,所有的数据都在 formData 中。 表单视图渲染动作 在最开始我们讲到过,当前页面是在界面设计器配置过,所有在CustomFormWidget里面是可以拿到当前页面配置的元数据信息,所以我们可以拿到界面设计器配置的字段跟动作 /// CustomFormWidget.ts @Widget.Method() protected renderActionVNodes() { // 从dsl中获取actionBar,actionBar里面包含了界面设计器配置的动作 const actionBar = this.metadataRuntimeContext.viewDsl?.widgets.find((w) => w.slot === 'actionBar'); if (actionBar) { // actionBar.widgets 就是界面设计器配置的动作,借助平台提供的DslRender.render方法,将对应的dsl转换成VNode return actionBar.widgets.map((w, index) => DslRender.render({ …w, __index: index }) ); } return null; } 因为 renderActionVNodes 方法返回的是 VNode,所以我们必须借助 vue 的 render 函数才能渲染。 <!– ActionRender.vue –> <script lang="ts"> import { defineComponent } from 'vue'; export default defineComponent({ inheritAttrs: false, props: { renderActionVNodes: { type: Function, required: true } }, render() { return this.renderActionVNodes(); } });…

    2024年9月12日
    1.7K01
  • 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
  • 自定义的复杂字段配置透出字段

    学习这篇文章之前,需要先学会使用在界面设计器自定义一个前端组件,如果您还不会,可以先看这篇文章 默认情况下,当开前端发人员自定义了一个复杂字段,比如M2O、O2M、M2M的字段,那么Graphql查询的时候,只会查询id跟name这两个字段,如果还想查询字段的字段,那么可以通过配置化的方式来处理 1: 在界面设计器的组件区域中新增对应的字段 2: 设计元件,在模型区域中搜索选项字段列表,拖到设计区域,然后保存 3: 去对应的设计页面,刷新下页面,选中对应的字段,可以看到右侧有选项字段列表4: 输入期望Graphql查询字段,保存发布

    2023年11月9日
    2.5K00

Leave a Reply

Please Login to Comment