Skip to main content

全局动作与动作配置面板扩充

本文介绍如何自定义通用动作和通用动作配置面板,并结合相关示例进行阐述说明,具体如下

注册自定义动作到 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 或以上)。