[amis-saas-8098] [amis-saas-8099] 支持防抖 & 支持阻止冒泡

Change-Id: Idba11cc838b4bf612b384c468ff35646f63b3d8e
This commit is contained in:
pianruijie 2022-12-01 16:51:29 +08:00
parent 107c51d074
commit 5711c16101
3 changed files with 172 additions and 23 deletions

View File

@ -280,22 +280,18 @@ export default class ActionDialog extends React.Component<ActionDialogProp> {
className: 'action-panel-title', className: 'action-panel-title',
visibleOn: 'data.actionType' visibleOn: 'data.actionType'
}, },
/*
{ {
name: 'expression', name: 'stopPropagation',
title: '', label: '阻断条件',
type: 'input-formula', type: 'ae-expressionFormulaControl',
variableMode: 'tabs', evalMode: true,
inputMode: 'input-group',
variables: '${variables}', variables: '${variables}',
className: 'action-exec-on',
label: '执行条件',
mode: 'horizontal', mode: 'horizontal',
size: 'lg', size: 'lg',
placeholder: '默认执行该动作', visibleOn: 'data.actionType',
visibleOn: 'data.actionType' description:
'满足条件时,将会阻断当前事件的后续动作的执行'
}, },
*/
{ {
name: 'expression', name: 'expression',
label: '执行条件', label: '执行条件',

View File

@ -2,7 +2,14 @@ import React from 'react';
import {findDOMNode} from 'react-dom'; import {findDOMNode} from 'react-dom';
import cx from 'classnames'; import cx from 'classnames';
import Sortable from 'sortablejs'; import Sortable from 'sortablejs';
import {DataSchema, FormItem, Button, Icon, TooltipWrapper} from 'amis'; import {
DataSchema,
FormItem,
Button,
Icon,
TooltipWrapper,
render as amisRender
} from 'amis';
import cloneDeep from 'lodash/cloneDeep'; import cloneDeep from 'lodash/cloneDeep';
import {FormControlProps, autobind, findTree} from 'amis-core'; import {FormControlProps, autobind, findTree} from 'amis-core';
import ActionDialog from './action-config-dialog'; import ActionDialog from './action-config-dialog';
@ -58,6 +65,17 @@ interface EventControlProps extends FormControlProps {
owner?: string; // 组件标识 owner?: string; // 组件标识
} }
interface EventDialogData {
eventName: string;
eventLabel: string;
isBroadcast: boolean;
debounceConfig?: {
open: boolean;
wait?: number;
};
[propName: string]: any;
}
interface EventControlState { interface EventControlState {
onEvent: ActionEventConfig; onEvent: ActionEventConfig;
events: RendererPluginEvent[]; events: RendererPluginEvent[];
@ -65,6 +83,8 @@ interface EventControlState {
[prop: string]: boolean; [prop: string]: boolean;
}; };
showAcionDialog: boolean; showAcionDialog: boolean;
showEventDialog: boolean;
eventDialogData?: EventDialogData;
actionData: actionData:
| { | {
eventKey: string; eventKey: string;
@ -114,6 +134,7 @@ export class EventControl extends React.Component<
events: pluginEvents, events: pluginEvents,
eventPanelActive, eventPanelActive,
showAcionDialog: false, showAcionDialog: false,
showEventDialog: false,
actionData: undefined, actionData: undefined,
type: 'add' type: 'add'
}; };
@ -163,7 +184,6 @@ export class EventControl extends React.Component<
weight: 0, weight: 0,
actions: [] actions: []
}; };
this.setState({ this.setState({
onEvent: onEvent onEvent: onEvent
}); });
@ -171,6 +191,52 @@ export class EventControl extends React.Component<
onChange && onChange(onEvent); onChange && onChange(onEvent);
} }
activeEventDialog(eventInfo: EventDialogData) {
if (!eventInfo.debounce) {
// 防抖配置的默认值
eventInfo.debounce = {
open: false,
wait: 100
};
} else {
eventInfo.debounce = {
open: true,
...eventInfo.debounce
};
}
this.setState({
eventDialogData: eventInfo,
showEventDialog: true
});
}
eventDialogSubmit(formData: any) {
const {onChange} = this.props;
const {eventName, debounce = {}} = formData;
let onEvent = {
...this.state.onEvent
};
let eventConfig = onEvent[`${eventName}`];
if (!debounce.open) {
delete eventConfig.debounce;
} else {
eventConfig = {
...eventConfig,
debounce: {
wait: debounce.wait
}
};
}
onEvent[`${eventName}`] = {
...eventConfig
};
this.setState({
onEvent,
showEventDialog: false
});
onChange && onChange(onEvent);
}
delEvent(event: string) { delEvent(event: string) {
const {onChange} = this.props; const {onChange} = this.props;
let onEvent = { let onEvent = {
@ -203,8 +269,8 @@ export class EventControl extends React.Component<
activeConfig[event] = true; activeConfig[event] = true;
if (config.actionType) { if (config.actionType) {
onEventConfig[event] = { onEventConfig[event] = {
actions: onEventConfig[event].actions.concat(config), ...onEventConfig[event],
weight: onEvent[event].weight actions: onEventConfig[event].actions.concat(config)
}; };
} }
@ -299,6 +365,7 @@ export class EventControl extends React.Component<
weight: onEvent[event].weight weight: onEvent[event].weight
}; };
onEventConfig[event] = { onEventConfig[event] = {
...onEvent[event],
actions: onEvent[event].actions.map((item, actionIndex) => { actions: onEvent[event].actions.map((item, actionIndex) => {
return actionIndex === index return actionIndex === index
? typeof config === 'string' ? typeof config === 'string'
@ -308,8 +375,7 @@ export class EventControl extends React.Component<
} }
: config : config
: item; : item;
}), })
weight: onEvent[event].weight
}; };
this.setState({ this.setState({
onEvent: onEventConfig onEvent: onEventConfig
@ -647,12 +713,14 @@ export class EventControl extends React.Component<
events, events,
eventPanelActive, eventPanelActive,
showAcionDialog, showAcionDialog,
showEventDialog,
type, type,
actionData actionData,
eventDialogData
} = this.state; } = this.state;
const enventSnapshot = cloneDeep(onEvent); const eventSnapshot = cloneDeep(onEvent);
const {showOldEntry} = this.props; const {showOldEntry} = this.props;
const eventKeys = Object.keys(enventSnapshot); const eventKeys = Object.keys(eventSnapshot);
return ( return (
<div className="ae-event-control"> <div className="ae-event-control">
<header <header
@ -706,7 +774,7 @@ export class EventControl extends React.Component<
'event-item-header': true, 'event-item-header': true,
'no-bd-btm': 'no-bd-btm':
!( !(
enventSnapshot[eventKey].actions?.length && eventSnapshot[eventKey].actions?.length &&
eventPanelActive[eventKey] eventPanelActive[eventKey]
) && !getEventStrongDesc(events, eventKey) ) && !getEventStrongDesc(events, eventKey)
})} })}
@ -742,6 +810,16 @@ export class EventControl extends React.Component<
<div onClick={this.delEvent.bind(this, eventKey)}> <div onClick={this.delEvent.bind(this, eventKey)}>
<Icon className="icon" icon="delete-bold-btn" /> <Icon className="icon" icon="delete-bold-btn" />
</div> </div>
<div
onClick={this.activeEventDialog.bind(this, {
eventName: eventKey,
eventLabel:
getEventLabel(events, eventKey) || eventKey,
...eventSnapshot[eventKey]
})}
>
<Icon className="icon" icon="edit-full-btn" />
</div>
<div <div
onClick={this.toggleActivePanel.bind(this, eventKey)} onClick={this.toggleActivePanel.bind(this, eventKey)}
> >
@ -764,10 +842,10 @@ export class EventControl extends React.Component<
className: 'event-item-desc' className: 'event-item-desc'
}) })
: null} : null}
{enventSnapshot[eventKey].actions.length && {eventSnapshot[eventKey].actions.length &&
eventPanelActive[eventKey] ? ( eventPanelActive[eventKey] ? (
<ul className="item-content"> <ul className="item-content">
{enventSnapshot[eventKey].actions.map( {eventSnapshot[eventKey].actions.map(
(action, actionIndex) => { (action, actionIndex) => {
return ( return (
<li <li
@ -845,6 +923,78 @@ export class EventControl extends React.Component<
</div> </div>
)} )}
</ul> </ul>
{showEventDialog
? amisRender(
{
type: 'dialog',
title: `${eventDialogData?.eventLabel}-事件配置`,
showCloseButton: false,
body: [
{
type: 'form',
title: '表单',
data: {
'&': '$$'
},
mode: 'horizontal',
horizontal: {
left: 3,
right: 9
},
body: [
{
label: '设置触发频率',
type: 'switch',
name: 'debounce.open',
description:
'设置触发频率后,单位时间内多次触发事件只会执行最后一次'
},
{
label: '触发频率',
required: true,
hiddenOn: '!debounce.open',
name: 'debounce.wait',
suffix: 'ms',
max: 10000,
min: 0,
type: 'input-number'
}
],
onSubmit: this.eventDialogSubmit.bind(this)
}
],
actions: [
{
type: 'button',
label: '取消',
onEvent: {
click: {
actions: [
{
actionType: 'custom',
script: () => {
this.setState({
showEventDialog: false
});
}
}
]
}
}
},
{
type: 'button',
actionType: 'confirm',
label: '确认',
primary: true
}
]
},
{
data: eventDialogData
}
)
: null}
<ActionDialog <ActionDialog
show={showAcionDialog} show={showAcionDialog}
type={type} type={type}

View File

@ -10,6 +10,9 @@ export interface ActionEventConfig {
weight?: number; // 权重 weight?: number; // 权重
actions: ActionConfig[]; // 执行的动作集 actions: ActionConfig[]; // 执行的动作集
__isBroadcast?: boolean; // 区分一下广播事件 __isBroadcast?: boolean; // 区分一下广播事件
debounce?: {
wait: number;
};
}; };
} }