mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-30 02:48:55 +08:00
feat:action 支持设置提交后倒计时 (#1607)
This commit is contained in:
parent
696c3e4dc4
commit
f25fbbf41e
@ -319,6 +319,34 @@ icon 也可以是 url 地址,比如
|
||||
| feedback | `DialogObject` | - | 如果 ajax 类型的,当 ajax 返回正常后,还能接着弹出一个 dialog 做其他交互。返回的数据可用于这个 dialog 中。格式可参考[Dialog](./Dialog.md) |
|
||||
| messages | `object` | - | `success`:ajax 操作成功后提示,可以不指定,不指定时以 api 返回为准。`failed`:ajax 操作失败提示。 |
|
||||
|
||||
### 倒计时
|
||||
|
||||
主要用于发验证码的场景,通过设置倒计时 `countDown`(单位是秒),让点击按钮后禁用一段时间:
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "form",
|
||||
"controls": [
|
||||
{
|
||||
"name": "phone",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"label": "手机号",
|
||||
"addOn": {
|
||||
"label": "发送验证码",
|
||||
"type": "button",
|
||||
"countDown": 60,
|
||||
"countDownTpl": "${timeLeft} 秒后重发",
|
||||
"actionType": "ajax",
|
||||
"api": "https://3xsw4ap8wah59.cfc-execute.bj.baidubce.com/api/amis-mock/mock2/form/saveForm?phone=${phone}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
同时还能通过 `countDownTpl` 来控制显示的文本,其中 `${timeLeft}` 变量是剩余时间。
|
||||
|
||||
## 跳转链接
|
||||
|
||||
### 单页跳转
|
||||
|
@ -1,6 +1,7 @@
|
||||
import {register} from '../locale';
|
||||
|
||||
register('en-US', {
|
||||
'Action.countDown': 'Wait for ${timeLeft}s',
|
||||
'Alert.info': 'System Info',
|
||||
'asc': 'Asc',
|
||||
'cancel': 'Cancel',
|
||||
|
@ -1,6 +1,7 @@
|
||||
import {register} from '../locale';
|
||||
|
||||
register('zh-CN', {
|
||||
'Action.countDown': '请等待 ${timeLeft} 秒',
|
||||
'Alert.info': '系统消息',
|
||||
'asc': '正序',
|
||||
'cancel': '取消',
|
||||
|
@ -99,6 +99,16 @@ export interface ButtonSchema extends BaseSchema {
|
||||
* 可以指定让谁来触发这个动作。
|
||||
*/
|
||||
target?: string;
|
||||
|
||||
/**
|
||||
* 点击后的禁止倒计时(秒)
|
||||
*/
|
||||
countDown?: number;
|
||||
|
||||
/**
|
||||
* 倒计时文字自定义
|
||||
*/
|
||||
countDownTpl?: string;
|
||||
}
|
||||
|
||||
export interface AjaxActionSchema extends ButtonSchema {
|
||||
@ -324,19 +334,53 @@ export interface ActionProps
|
||||
|
||||
const allowedType = ['button', 'submit', 'reset'];
|
||||
|
||||
export class Action extends React.Component<ActionProps> {
|
||||
interface ActionState {
|
||||
inCountDown: boolean; // 是否在倒计时
|
||||
countDownEnd: number; // 倒计时结束的精确时间
|
||||
timeLeft: number; // 倒计时剩余时间
|
||||
}
|
||||
|
||||
export class Action extends React.Component<ActionProps, ActionState> {
|
||||
static defaultProps = {
|
||||
type: 'button' as 'button',
|
||||
componentClass: 'button' as React.ReactType,
|
||||
tooltipPlacement: 'bottom' as 'bottom',
|
||||
activeClassName: 'is-active'
|
||||
activeClassName: 'is-active',
|
||||
countDownTpl: 'Action.countDown',
|
||||
countDown: 0
|
||||
};
|
||||
|
||||
state: ActionState = {
|
||||
inCountDown: false,
|
||||
countDownEnd: 0,
|
||||
timeLeft: 0
|
||||
};
|
||||
|
||||
localStorageKey: string;
|
||||
|
||||
dom: any;
|
||||
|
||||
constructor(props: ActionProps) {
|
||||
super(props);
|
||||
this.localStorageKey = 'amis-countdownend-' + (this.props.name || '');
|
||||
const countDownEnd = parseInt(
|
||||
localStorage.getItem(this.localStorageKey) || '0'
|
||||
);
|
||||
if (countDownEnd && this.props.countDown) {
|
||||
if (Date.now() < countDownEnd) {
|
||||
this.state = {
|
||||
inCountDown: true,
|
||||
countDownEnd,
|
||||
timeLeft: Math.floor((countDownEnd - Date.now()) / 1000)
|
||||
};
|
||||
this.handleCountDown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleAction(e: React.MouseEvent<any>) {
|
||||
const {onAction, onClick, disabled} = this.props;
|
||||
const {onAction, onClick, disabled, countDown} = this.props;
|
||||
|
||||
const result: any = onClick && onClick(e, this.props);
|
||||
|
||||
@ -347,18 +391,51 @@ export class Action extends React.Component<ActionProps> {
|
||||
e.preventDefault();
|
||||
const action = pick(this.props, ActionProps) as ActionSchema;
|
||||
onAction(e, action);
|
||||
|
||||
if (countDown) {
|
||||
const countDownEnd = Date.now() + countDown * 1000;
|
||||
this.setState({
|
||||
countDownEnd: countDownEnd,
|
||||
inCountDown: true,
|
||||
timeLeft: countDown
|
||||
});
|
||||
|
||||
localStorage.setItem(this.localStorageKey, String(countDownEnd));
|
||||
|
||||
setTimeout(() => {
|
||||
this.handleCountDown();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleCountDown() {
|
||||
// setTimeout 一般会晚于 1s,经过几十次后就不准了,所以使用真实时间进行 diff
|
||||
const timeLeft = Math.floor((this.state.countDownEnd - Date.now()) / 1000);
|
||||
if (timeLeft <= 0) {
|
||||
this.setState({
|
||||
inCountDown: false,
|
||||
timeLeft: timeLeft
|
||||
});
|
||||
} else {
|
||||
this.setState({
|
||||
timeLeft: timeLeft
|
||||
});
|
||||
setTimeout(() => {
|
||||
this.handleCountDown();
|
||||
}, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
type,
|
||||
label,
|
||||
icon,
|
||||
iconClassName,
|
||||
primary,
|
||||
size,
|
||||
level,
|
||||
disabled,
|
||||
countDownTpl,
|
||||
block,
|
||||
className,
|
||||
componentClass,
|
||||
@ -368,6 +445,7 @@ export class Action extends React.Component<ActionProps> {
|
||||
actionType,
|
||||
link,
|
||||
data,
|
||||
translate: __,
|
||||
activeClassName,
|
||||
isCurrentUrl,
|
||||
isMenuItem,
|
||||
@ -377,12 +455,23 @@ export class Action extends React.Component<ActionProps> {
|
||||
classnames: cx
|
||||
} = this.props;
|
||||
|
||||
let label = this.props.label;
|
||||
let disabled = this.props.disabled;
|
||||
let isActive = !!active;
|
||||
|
||||
if (actionType === 'link' && !isActive && link && isCurrentUrl) {
|
||||
isActive = isCurrentUrl(link);
|
||||
}
|
||||
|
||||
// 倒计时
|
||||
if (this.state.inCountDown) {
|
||||
label = filterContents(__(countDownTpl), {
|
||||
...data,
|
||||
timeLeft: this.state.timeLeft
|
||||
}) as string;
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
const iconElement = generateIcon(cx, icon, 'Button-icon', iconClassName);
|
||||
|
||||
return isMenuItem ? (
|
||||
|
Loading…
Reference in New Issue
Block a user