自定义的「视图、字段」调用界面设计器配置的按钮(包含权限控制)

我们在业务开发中,经常会遇到自定义的视图或字段。有时候期望点击某一块区域的时候,打开一个弹窗或者是跳转新页面亦或者是执行服务端动作(调接口),但是希望这个动作是界面设计器拖拽进来的。

这篇文章详细的讲解了自定义的视图、字段怎么执行界面设计器拖出来的按钮。

自定义视图

1: 先设计一个页面,把对应的动作拖拽进来,可以不需要配置字段
数式Oinone低代码-自定义的「视图、字段」调用界面设计器配置的按钮
2: 将该页面绑定菜单

3: 自定义对应的页面

当我们自定义视图的时候,首先会注册一个视图,下面是我自定义的一个表单视图

registerLayout(
  `<view type="FORM">
    <element widget="actionBar" slot="actionBar">
        <xslot name="actions" />
    </element>
    <element widget="MyWidget" slot="form">
        <xslot name="fields" />
    </element>
</view>`,
  {
    moduleName: 'ys0328',
    model: 'ys0328.k2.Model0000000453',
    actionName: 'MenuuiMenu78ec23b054314ff5a12b4fe95fe4d7b5',
    viewType: ViewType.Form
  }
);

我自定义了一个叫做MyWidget的 element,下面是对应的ts代码

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

这是对应的 vue 文件: MyVue.vue

<template>
  <div @click="onClick">点击执行动作</div>
</template>

<script lang="ts">
  import { defineComponent } from 'vue';

  export default defineComponent({
    props: ['onClick']
  });
</script>

这个时候,我希望点击的时候,执行 onClick,会执行对应的动作,这时只需要在对应的 ts 文件中写对应的代码逻辑即可:

@SPI.ClassFactory(BaseElementWidget.Token({ widget: 'MyWidget' }))
export class MyWidgetManageWidget extends BaseElementWidget {
  // 获取当前页面所有的按钮
  @Widget.Reactive()
  public get modelActions() {
    return this.metadataRuntimeContext.model.modelActions || []
  }

  // 用来解析上下文表达式的,如果不需要,可以删除
  public executeCustomExpression<T>(
    parameters: Partial<ExpressionRunParam>,
    expression: string,
    errorValue?: T
  ): T | string | undefined {
    const scene = this.scene;
    return Expression.run(
      {
        activeRecords: parameters.activeRecords,
        rootRecord: parameters.rootRecord,
        openerRecord: parameters.openerRecord,
        scene: parameters.scene || scene,
        activeRecord: parameters.activeRecord
      } as ExpressionRunParam,
      expression,
      errorValue
    );
  }

  // 点击事件
  @Widget.Method()
  public onClick() {
    // 找到对应的按钮
    const action = this.modelActions.find((a) => a.label === '动作的显示名称');

     /**
    * 如果是服务端动作,就执行 executeServerAction
    */
    // executeServerAction(action, 参数对象) // 第二个参数是调用对应的接口传递的参数

 /**
    * 如果是跳转动作,就执行 executeViewAction
    */
    executeViewAction(action);

    /**
    * 如果跳转动作打开的视图需要通过id去查询数据,可以这样配置, 一般用于打开编辑、详情页
    */
    // executeViewAction(action, undefined, undefined, {id: 'xxxx'});

    /**
    * 如果跳转动作打开的视图需要需要额外的上下文参数,可以这样配置
    */
    // const _action = {
    //   ...action,
    //   context: {
    //     ...(action.context || {}),
    //     name: '123',
    //     code: '232'
    //   }
    // } as RuntimeViewAction
    // executeViewAction(_action, undefined, undefined, {id: 'xxxx'});

     /**
    * 如果跳转动作打开的视图需要上下文参数是在配置在对应动作上面,可以这样去解析上下文表达式
    */
    // const context = action.context || {}
    // const context = (action as RuntimeViewAction).context || {}
    // const parseContext = {}
    // const data = {} // 这是自己的数据源

    // Object.entries(context).forEach(([key, value]) => {
    //   if(typeof value === 'string') {
    //     parseContext[key] = this.executeCustomExpression({activeRecord: data, rootRecord: data,openerRecord: data}, value)
    //   }
    // })
    // executeViewAction({
    //   ...action,
    //   context:parseContext
    // } as RuntimeViewAction, undefined, undefined, {id: 'xxxx'});
  }

  public initialize(props: BaseElementWidgetProps): this {
    super.initialize(props);
    this.setComponent(MyVue);
    return this;
  }
}

以上我们就完成的自定义的视图如何触发界面设计器拖拽出来的按钮。

这是页面运行时的效果图

数式Oinone低代码-自定义的「视图、字段」调用界面设计器配置的按钮

数式Oinone低代码-自定义的「视图、字段」调用界面设计器配置的按钮

自定义字段

先自定义对应的字段,下面是我自定义的字段

@SPI.ClassFactory(
  BaseFieldWidget.Token({
    viewType: ViewType.Form,
    ttype: ModelFieldType.String,
    widget: 'MyField'
  })
)
export class MyFieldWidget extends FormFieldWidget {
  // 获取当前页面所有的按钮
  @Widget.Reactive()
  public get modelActions() {
    return this.metadataRuntimeContext.model.modelActions || []
  }

  // 点击事件
  @Widget.Method()
  public onClick() {
    // 找到对应的按钮
    const action = this.modelActions.find((a) => a.label === '点击打开弹窗');

    // 执行按钮
    executeViewAction(action as any);
  }

  public initialize(props: BaseElementWidgetProps): this {
    super.initialize(props);
    this.setComponent(MyVue);
    return this;
  }
}
<template>
  <div @click="onClick">点击字段打开弹窗</div>
</template>

<script lang="ts">
  import { defineComponent } from 'vue';

  export default defineComponent({
    props: ['onClick']
  });
</script>

其实不管是自定义的视图还是字段,里面执行动作的写法其实是一样的。

权限控制

如果当前系统用到了权限,那么我们在执行 action 时,需要判断当前 action 是否存在,因为当用户没有该 action 权限的时候,前端是获取不到对应的 action。

@Widget.Reactive()
public get hasMyAction() {
  return this.metadataRuntimeContext.model.modelActions.find(a => a.name === 'myAction')
}
<template> <div @click="onClick" v-if="hasMyAction">点击打开弹窗</div> </template>template

我们只需要定义一个计算属性,用来处理当前 action 是否存在,最后在 vue 模版里面使用 v-if 来控制是否显示。

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

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

Like (0)
汤乾华's avatar汤乾华数式员工
Previous 2023年11月8日 am10:59
Next 2023年11月8日 pm5:05

相关推荐

  • 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.6K00
  • 前端元数据介绍

    模型 属性名 类型 描述 id string 模型id model string 模型编码 name string 技术名称 modelFields RuntimeModelField[] 模型字段 modelActions RuntimeAction[] 模型动作 type ModelType 模型类型 module string 模块编码 moduleName string 模块名称 moduleDefinition RuntimeModule 模块定义 pks string[] 主键 uniques string[][] 唯一键 indexes string[][] 索引 sorting string 排序 label string 显示标题 labelFields string[] 标题字段 模型字段 属性名 类型 描述 model string 模型编码 modelName string 模型名称 data string 属性名称 name string API名称 ttype ModelFieldType 字段业务类型 multi boolean (可选) 是否多值 store boolean 是否存储 displayName string (可选) 字段显示名称 label string (可选) 字段页面显示名称(优先于displayName) required boolean | string (可选) 必填规则 readonly boolean | string (可选) 只读规则 invisible boolean | string (可选) 隐藏规则 disabled boolean | string (可选) 禁用规则 字段业务类型 字段类型 值 描述 String ‘STRING’ 文本 Text ‘TEXT’ 多行文本 HTML ‘HTML’ 富文本 Phone ‘PHONE’ 手机 Email ‘EMAIL’ 邮箱 Integer ‘INTEGER’ 整数 Long ‘LONG’ 长整型 Float ‘FLOAT’ 浮点数 Currency ‘MONEY’ 金额 DateTime ‘DATETIME’ 时间日期 Date ‘DATE’ 日期 Time ‘TIME’ 时间 Year ‘YEAR’ 年份 Boolean ‘BOOLEAN’ 布尔型 Enum ‘ENUM’ 数据字典 Map ‘MAP’ 键值对 Related ‘RELATED’ 引用类型 OneToOne ‘O2O’ 一对一 OneToMany ‘O2M’ 一对多 ManyToOne ‘M2O’ 多对一 ManyToMany ‘M2M’ 多对多 模型动作 属性名 类型 描述 name string…

    2024年9月21日
    2.3K00
  • 「前端」 获取当前用户信息以及语言

    概述 TopBarService 是用于管理用户信息和多语言配置的工具类,提供以下核心功能: 用户信息查询(含缓存机制) 当前语言状态获取 可用语言列表查询 语言切换操作 快速开始 // 基础使用示例 import { TopBarService } from '@kunlun/dependencies'; // 获取用户信息(自动缓存) const userInfo = await TopBarService.getUserInfo(); // 获取当前语言配置 const currentLang = await TopBarService.getCurrentLang(); // 查询支持的语言列表 const languages = await TopBarService.queryLanguageList(); // 激活指定语言 await TopBarService.activeLang('zh_CN'); API 详解 方法功能说明 方法名称 描述 参数 返回值 ​getUserInfo 获取当前用户信息(自动缓存) 无 用户信息对象 ​queryUserInfo 强制获取最新用户信息 无 最新用户信息对象 ​getCurrentLang 获取当前激活的语言配置 无 语言配置对象 / undefined ​queryLanguageList 获取所有可用语言列表 无 语言列表数组 ​activeLang 激活指定语言 语言 ID (string) 更新后的语言配置对象

    2025年3月21日
    2.2K00
  • oio-spin 加载中

    用于页面和区块的加载中状态。 何时使用 页面局部处于等待异步数据或正在渲染过程时,合适的加载动效会有效缓解用户的焦虑。 API 参数 说明 类型 默认值 版本 delay 延迟显示加载效果的时间(防止闪烁) number (毫秒) – loading 是否为加载中状态 boolean true wrapperClassName 包装器的类属性 string –

    2023年12月18日
    1.6K00
  • 自定义组件之手动渲染任意视图(v4)

    private metadataViewWidget: MetadataViewWidget | null | undefined; private async renderCustomView(model: string, viewName: string, slotName?: string) { const view = await ViewCache.get(model, viewName); if (!view) { return; } if (this.metadataViewWidget) { this.metadataViewWidget.dispose(); this.metadataViewWidget = null; } const metadataViewWidget = this.createWidget(MetadataViewWidget, slotName, { metadataHandle: this.metadataHandle, rootHandle: this.rootHandle, internal: true, inline: true, automatic: true }); this.metadataViewWidget = metadataViewWidget; metadataViewWidget.initContextByView(view); this.forceUpdate(); }

    2025年3月6日
    2.1K00

Leave a Reply

Please Login to Comment