全局动作与动作配置面板扩充
本文介绍如何自定义通用动作和通用动作配置面板,并结合相关示例进行阐述说明,具体如下
注册自定义动作到 amis
amis 包使用 registerAction 方法进行动作注册,用法如下:
registerAction('my-custom-action', new H5ScanQRCodeAction());
第一个参数为动作全局唯一 key,与 amis 中的已有动作名称不可重复。注:已有的事件动作名称参考 ActionObject 定义
第二个参数为 amis 中动作基类 RendererAction 的实例,其中 run 方法就是动作执行函数。
以【二维码扫描】通用动作进行举例:
import {Html5Qrcode} from 'html5-qrcode';
import {ListenerAction, ListenerContext, registerAction, RendererAction} from 'amis-core';
import {RendererEvent} from 'amis-core';
// 动作定义
interface H5ScanQRCodeActionDS extends ListenerAction {
  actionType: 'h5-scan-qrcode';
  args: {
      [propName: string]: any;
  };
}
/**
 * 用户自定义动作逻辑部分《二维码扫描逻辑》
 */
export function scanQRCode(): Promise<{
  result: string;
}> {
  return new Promise((resolve, reject) => {
    try {
      let reader = document.getElementById('qr-reader');
      let container = document.getElementById('qr-container');
      if (reader == null) {
        container = document.createElement('div');
        container.style.height = '100%';
        container.style.width = '100%';
        container.style.float = 'left';
        container.style.position = 'absolute';
        container.style.top = '0';
        container.style.left = '0';
        container.style.zIndex = '9999';
        container.setAttribute('id', 'qr-container');
        reader = document.createElement('div');
        reader.setAttribute('id', 'qr-reader');
        container.append(reader);
        document.body.append(container);
      }
      const wHeight = window.innerHeight;
      const wWidth = window.innerWidth;
      const size = Math.round(Math.min(wHeight, wWidth) * 0.8);
      let scaner = new Html5Qrcode('qr-reader', true);
      let stop = () => {
        container?.remove();
        scaner.stop();
      };
      scaner
        .start(
          {facingMode: 'user'},
          {
            fps: 10,
            qrbox: {width: size, height: size},
            aspectRatio: wWidth / wHeight
          },
          decodedText => {
            stop();
            resolve({
              result: decodedText
            });
          },
          error => {
            console.log(error);
          }
        )
        .catch(e => {
          try {
            stop();
          } catch (e) {}
          if (/NotAllowedError/.test(e)) {
            reject('请授权摄像头使用权限,否则无法进行扫码!');
            return;
          }
          reject(e);
        });
      // setTimeout(() => {
      //   scaner.stop();
      //   container?.remove();
      // }, 10000);
    } catch (e) {
      reject(e);
    }
  });
}
/**
 * 动作实现
 */
export class H5ScanQRCodeAction implements RendererAction {
  // run 方法执行自定义动作
  async run(
    action: OpenWechatProgramListenerAction, // 当前动作和动作参数
    renderer: ListenerContext,
    event: RendererEvent<any>, // 当前事件对象,其中包含 data,
    contextData?: any
  ) {
    const toast = event.context.env.notify;
    // 部分参数传入可能是表达式而不是常量,因此要用解析一遍
    // const appId = this.resolveExpOrValue<string>(appId, event.data);
    // 建议全局共用,从当前数据上下文中进行表达式结果计算
    // resolveExpOrValue<T>(expression: string | T, data: any): T {
    //   if (isPureVariable(expression)) {
    //     return resolveVariableAndFilter(expression, createObject(data), '|raw') as T;
    //   }
    //   return expression as T;
    // }
    try {
      const result = await scanQRCode();
      // 返回动作执行后的数据,可以在下一个动作中被使用
      event.setData(result);
    } catch (e) {
      toast('error', '扫码失败,' + (e.message || e));
      console.log('error', '扫码失败,' + (e.message || e));
      throw e;
    }
  }
}
// 注册自定义动作
registerAction('h5-scan-qrcode', new H5ScanQRCodeAction());
注册动作配置面板到 amis-editor
amis-editor 中使用 registerActionPanel 进行动作配置面板注册,具体用法如下:
registerActionPanel('open-wechat-program', ActionPanel);
第一个参数为动作全局唯一 key,与 amis 中的已有动作名称不可重复。注:已有的事件动作名称参考 ActionObject 定义 第二个参数为 amis-editr 中定义的 ActionPanel,具体如下
// 动作声明
export interface RendererPluginAction {
  actionType?: string; // 动作名称value
  actionLabel?: string; // 动作名称label
  description?: string; // 动作描述
  schema?: any; // 动作配置schema
  supportComponents?: string[] | string; // 如果schema中包含选择组件,可以指定该动作支持的组件类型,用于组件数树过滤
  innerArgs?: string[]; // 动作专属配置参数,主要是为了区分特性字段和附加参数
  descDetail?: (info: any, context: any, props: any) => string | JSX.Element; // 动作详细描述
  outputVarDataSchema?: any | any[]; // 动作出参的结构定义
  actions?: SubRendererPluginAction[]; // 分支动作(配置面板包含多种动作的情况)
  children?: RendererPluginAction[]; // 子类型,for动作树
}
// ActionPanel 动作配置面板声明
type ActionPanel = Omit<RendererPluginAction, 'actionType' | 'actionLabel'> & {
  label: string; // 配置面板名称
  tag: string; // 配置面板分类
};
// 动作配置面板示例
import React from 'react';
import {registerActionPanel, getArgsWrapper} from 'amis-editor';
import {defaultValue, getSchemaTpl} from 'amis-editor-core';
registerActionPanel('h5-scan-qrcode', {
  label: '扫描二维码',
  tag: '全局',
  description:
    '只需简单地将手机摄像头对准二维码图片,轻轻一扫,便能迅速完成信息的识别与读取。这一便捷的操作方式,不仅极大地节省了时间,还提升了效率,让我们的生活和工作变得更加轻松与智能。',
  descDetail: (info: any) => {
    return <div>二维码扫描</div>;
  },
  schema: () => [
    {
      type: 'select',
      name: 'type',
      mode: 'horizontal',
      value: 'qrCode',
      size: 'lg',
      options: [
        {
          label: '二维码',
          value: 'qrCode'
        },
        {
          label: '条形码',
          value: 'barCode'
        },
        {
          label: '翻译',
          value: 'translators'
        },
        {
          label: '拍照识物',
          value: 'photoIdentification'
        }
      ],
      label: '选择扫描类型'
    },
    // 支持公式表达式的多行文本框
    getSchemaTpl('tplFormulaControl', {
      label: '扫码提示信息',
      name: 'value',
      clearable: true,
      mode: 'horizontal',
      placeholder: '请输入参数值',
      variables: '${variables}',
      size: 'lg',
      header: '配置参数值'
    })
  ]
});
| 属性名称 | 描述 | 类型 | 必填 | 图例说明 | 
| description | 对应的动作面板是填写 | string | 可选 |   | 
| descDetail | 动作的详细描述,方便用户识别,在配置面板右侧动作列表中展示 | string | 可选 | |
| label | 动作名称,在通用动作弹窗中左侧展示 | string | 必填 |   | 
| tag | 动作分组,在通用动作弹窗左侧分组中展示 | string | 必填 | |
| schema | 支持shema或者方法返回schema,具体如下schema说明 | object | ()=> Schema | 可选 | |
| supportComponents | 支持的组件类型,用于组件树过滤 | string[] | string | 可选 |   | 
| actions | 分支动作,一个动作中包含多个分支动作,如组件展示态动作 | SubRendererPluginAction[] | 可选 |   | 
| outputVarDataSchema | 动作出参的数据结构 | any | any[] | 可选 | 
schema 属性说明 schema 主要控制通用动作面板基本设置的,用户主要通过 schema 配置来完成自定义通用动作配置面板的需求,schema 支持两种类型
- 直接返回 schema,具体 schema 配置参考 amis 文档
- 通过方法返回 schema:(manage)=> Schema,用户可通过 manage 获取编辑器相关的属性参数,具体参考编辑器 manager 定义文档
示例
普通 react 自定义组件对接 amis 事件动作见示例;
vue 自定义组件无需设置 ScopedContext,amis-widget 会自动设置 ScopedContext,只需补充 doAction 方法,见示例(需确保 amis-widget 版本为 3.0.9 或以上)。