效果图

当前图片中,上方是自定义的视图,下方是动态的表单视图
代码
步骤拆分:
1: 通过注册 layout 的方式先自定义视图,把自己的业务逻辑写完
2: 在对应的 vue 文件里面定义一个插槽,用来放置动态的表单视图
3: 在组件挂在的时候,创建动态视图
1: 注册 layout
// registry.ts
import { registerLayout, ViewType } from '@kunlun/dependencies';
registerLayout(
  `<view type="FORM">
    <element widget="actionBar" slot="actionBar" slotSupport="action">
        <xslot name="actions" slotSupport="action" />
    </element>
    <element widget="CustomViewWidget"></element>
</view>`,
  {
    model: '模型编码',
    actionName: '动作名称',
    viewType: ViewType.Form
  }
);2: vue 里面定义 slot
<!--CustomView.vue -->
<template>
  <div>
    <h1>这是自定义的视图</h1>
    <img
      src="https://pamirs.oss-cn-hangzhou.aliyuncs.com/oinone/static/images/login_bg_left.jpg"
      height="400"
      width="2600"
      alt=""
    />
    <h1>下面设计器配置的动态视图</h1>
    <slot name="dynamicView"></slot>
  </div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
});
</script>3: 组件挂载的时候,创建动态视图
// CustomViewWidget.ts
import {
  SPI,
  BaseElementWidget,
  ViewType,
  ViewCache,
  Widget,
  MetadataViewWidget,
  BaseView,
  TableView,
  FormView,
  FormWidget,
  registerLayout,
  DetailView,
  DetailWidget,
  isRelation2MField,
  customQuery,
  FormFieldWidget
} from '@kunlun/dependencies';
import CustomView from './CustomView.vue';
import { delay } from 'lodash-es';
@SPI.ClassFactory(
  BaseElementWidget.Token({
    viewType: ViewType.Form,
    widget: 'CustomViewWidget'
  })
)
export class CustomViewWidgetWidget extends BaseElementWidget {
  public initialize(props) {
    super.initialize(props);
    this.setComponent(CustomView);
    return this;
  }
  /**
   * 定义一个属性,用来存储动态视图
   */
  private metadataViewWidget: MetadataViewWidget | undefined;
  /**
   * 获取动态视图的数据
   */
  @Widget.Method()
  private getWidgetData() {
    const children = this.metadataViewWidget?.getChildrenInstance() as BaseView[];
    const child = children[0];
    if (child) {
      return child instanceof TableView ? child.getCurrentDataSource() : child.getCurrentActiveRecords();
    }
    return null;
  }
  /**
   * 触发表单校验
   */
  @Widget.Method()
  private async executeValidate() {
    const children = this.metadataViewWidget?.getChildrenInstance() as BaseView[];
    const child = children[0];
    if (child && child instanceof FormView) {
      const formWidget = child.getChildrenInstance().find((chi) => chi instanceof FormWidget) as FormWidget;
      // 校验
      const rst = await formWidget?.validator();
      return rst;
    }
    return true;
  }
  /**
   * 加载表单视图中字段表格的数据
   */
    private reloadFormX2MFieldData(widget: BaseView, rootData) {
    const formWidget = widget.getChildrenWidget().find((w) => w instanceof FormWidget) as FormWidget;
    if (formWidget) {
      const x2mWidgets = formWidget.getFieldWidgets(true).filter((v) => isRelation2MField(v.field)) as any[];
      for (const widget of x2mWidgets) {
        widget.mountedProcess?.();
        (widget as FormFieldWidget)?.reloadRootData(rootData);
      }
    }
  }
  /**
   * 加载详情视图中字段表格的数据
   */
  private reloadDetailViewData(widget: DetailView, data: any) {
    const detailWidget = widget.getChildrenWidget().find((w) => w instanceof DetailWidget) as DetailWidget;
    if (detailWidget) {
      // 加载详情页数据
      detailWidget.reloadActiveRecords(data);
      // 获取详情页的2M关系字段组件
      const x2mWidgets = detailWidget.getFieldWidgets(true).filter((v) => isRelation2MField(v.field)) as any[];
      for (const widget of x2mWidgets) {
        if (widget.refreshValueProcess) {
          widget.isDataSourceProvider = true;
          widget.refreshValueProcess?.();
        }
      }
    }
  }
  /**
   * 初始化的时候,创建动态视图
   */
  mounted() {
    this.createFormWidget();
  }
  public async createFormWidget() {
    this.load(async () => {
      // 如果视图已经存在,那么先销毁,防止多次创建
      if (this.metadataViewWidget) {
        this.metadataViewWidget.dispose();
        this.metadataViewWidget = undefined;
      }
      // 根据 模型编码 + 视图名称获取设计器配置的视图
      const view = await ViewCache.get(
        'resource.k2.Model0000000100', // 模型编码
        '创建跟编辑_FORM_uiViewf927f2785d3c4394a6c26898df2e8c87' // 视图名称
      );
      if (view) {
        /**
         * 调用 this.createWidget创建对应的视图
         * 第一个参数是代表的是视图对应的widget
         * 第二个参数是创建好的视图需要放在哪个插槽里面,对应vue文件里面的slot
         *   如果vue文件里面写的是 <slot name="dynamicView"></slot>, 那么这个参数就是 'dynamicView'
         *   如果vue文件里面写的是 <slot name='customName'></slot>, 那么这个参数就是 'customName'
         *
         * 第三个参数是视图需要的属性配置
         */
        this.metadataViewWidget = this.createWidget(MetadataViewWidget, 'dynamicView', {
          metadataHandle: this.metadataHandle,
          rootHandle: this.rootHandle,
          internal: true,
          inline: true,
          automatic: true
        });
        // 初始化上下文
        this.metadataViewWidget.initContextByView(view);
        this.forceUpdate();
        // 视图对应的数据源,这里的数据理论上需要通过调用接口获取
        const data = {} as any;
        // const data = await customQuery('resource.k2.Model0000000100', {argumentName: 'query', name: 'queryOne'}, {id: 123}) as any
        delay(async () => {
          const children = this.metadataViewWidget?.getChildrenInstance() as BaseView[];
         if (children.length) {
            const child = children[0]
            // 如果当前视图是表格
            if (child instanceof TableView) {
              await child.refreshCallChaining?.syncCall();
            }  else if (child instanceof DetailView) {  // 如果当前视图是详情
              this.reloadDetailViewData(child, data);
            } else {
                // 如果当前视图是表单
              child.setViewMode(ViewMode.Create);
              child.setCurrentActiveRecords(data);
              this.reloadFormX2MFieldData(child, data);
            }
          }
        }, 100);
      }
    });
  }
}
Oinone社区 作者:汤乾华原创文章,如若转载,请注明出处:https://doc.oinone.top/api-sdk/20763.html
访问Oinone官网:https://www.oinone.top获取数式Oinone低代码应用平台体验
 
                
