Merge pull request #3568 from gooolh/feat-input-image-event

feat: input-image 事件动作补充
This commit is contained in:
hsm-lv 2022-02-18 11:23:18 +08:00 committed by GitHub
commit e5b44cef2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 156 additions and 31 deletions

View File

@ -1,3 +1,38 @@
const getEventDesc = eventName => {
return {
actions: [
{
actionType: 'toast',
msgType: 'info',
msg: `派发${eventName}事件`
}
]
};
};
const change = {
actions: [
{
actionType: 'dialog',
args: {
val: '${event.data.file}'
},
dialog: {
title: `派发change事件`,
data: {
val: '${val}'
},
body: [
{
type: 'tpl',
tpl: '${val|json}'
}
]
}
}
]
};
export default {
type: 'page',
title: '上传类组件事件',
@ -39,7 +74,55 @@ export default {
type: 'input-file',
id: 'clear-input-file',
name: 'file',
multiple: true
multiple: true,
onEvent: {
change,
remove: getEventDesc('remove'),
success: getEventDesc('success'),
fail: getEventDesc('fail')
}
}
]
}
]
},
{
type: 'form',
debug: true,
api: '/api/mock2/form/saveForm',
body: [
{
type: 'group',
body: [
{
name: 'trigger2',
id: 'trigger2',
type: 'action',
label: 'clear触发器',
level: 'primary',
onEvent: {
click: {
actions: [
{
actionType: 'clear',
componentId: 'clear-input-image',
description: '点击清除数据'
}
]
}
}
},
{
type: 'input-image',
id: 'clear-input-image',
name: 'file',
multiple: true,
onEvent: {
change,
remove: getEventDesc('remove'),
success: getEventDesc('success'),
fail: getEventDesc('fail')
}
}
]
}

View File

@ -5,7 +5,7 @@ import isPlainObject from 'lodash/isPlainObject';
// @ts-ignore
import mapLimit from 'async/mapLimit';
import ImageControl from './InputImage';
import {Payload, ApiObject, ApiString, Action} from '../../types';
import {Payload, ApiObject, ApiString} from '../../types';
import {filter} from '../../utils/tpl';
import Alert from '../../components/Alert2';
import {qsstringify, createObject, guid, isEmpty} from '../../utils/helper';
@ -509,7 +509,6 @@ export default class FileControl extends React.Component<FileProps, FileState> {
}
}
);
// 添加文件触发
this.dispatchEvent('change');
}
@ -711,7 +710,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
uploading: false
},
() => {
this.onChange(!!this.resolve);
this.onChange(!!this.resolve, false);
if (this.resolve) {
this.resolve(
@ -796,7 +795,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
},
onProgress
)
.then(ret => {
.then(async ret => {
if ((ret.status && (ret as any).status !== '0') || !ret.data) {
throw new Error(ret.msg || __('File.errorRetry'));
}
@ -805,7 +804,10 @@ export default class FileControl extends React.Component<FileProps, FileState> {
let value =
(ret.data as any).value || (ret.data as any).url || ret.data;
this.dispatchEvent('success', file);
const dispatcher = await this.dispatchEvent('success', file);
if (dispatcher?.prevented) {
return;
}
cb(null, file, {
...(isPlainObject(ret.data) ? ret.data : null),
value: value,
@ -813,8 +815,11 @@ export default class FileControl extends React.Component<FileProps, FileState> {
id: file.id
});
})
.catch(error => {
this.dispatchEvent('fail', file);
.catch(async error => {
const dispatcher = await this.dispatchEvent('fail', {file, error});
if (dispatcher?.prevented) {
return;
}
cb(error.message || __('File.errorRetry'), file);
});
}
@ -823,7 +828,10 @@ export default class FileControl extends React.Component<FileProps, FileState> {
const files = this.state.files.concat();
const removeFile = files[index];
// 触发移出文件事件
await this.dispatchEvent('remove', removeFile);
const dispatcher = await this.dispatchEvent('remove', removeFile);
if (dispatcher?.prevented) {
return;
}
this.removeFileCanelExecutor(file, true);
files.splice(index, 1);
@ -838,7 +846,6 @@ export default class FileControl extends React.Component<FileProps, FileState> {
},
isUploading ? this.tick : this.onChange
);
this.dispatchEvent('change');
}
clearError() {
@ -847,7 +854,7 @@ export default class FileControl extends React.Component<FileProps, FileState> {
});
}
onChange(changeImmediately?: boolean) {
async onChange(changeImmediately?: boolean, isFileChange = true) {
const {
multiple,
onChange,
@ -881,6 +888,12 @@ export default class FileControl extends React.Component<FileProps, FileState> {
} else {
value = typeof resetValue === 'undefined' ? '' : resetValue;
}
if (isFileChange) {
const dispatcher = await this.dispatchEvent('change');
if (dispatcher?.prevented) {
return;
}
}
onChange((this.emitValue = value), undefined, changeImmediately);
this.syncAutoFill();
@ -1188,19 +1201,15 @@ export default class FileControl extends React.Component<FileProps, FileState> {
}
}
async dispatchEvent(
e: string,
data?: Array<FileX | FileValue> | FileX | FileValue
) {
async dispatchEvent(e: string, data?: Record<string, any>) {
const {dispatchEvent} = this.props;
data = data ? data : this.state.files;
return dispatchEvent(e, createObject(this.props.data, data));
}
doAction(action: Action, data: object, throwErrors: boolean = false): any {
if (action.actionType === 'clear') {
this.setState({files: []});
}
data = data || this.state.files;
return dispatchEvent(
e,
createObject(this.props.data, {
file: data
})
);
}
render() {

View File

@ -689,7 +689,7 @@ export default class ImageControl extends React.Component<
locked: false
},
() => {
this.onChange(!!this.resolve);
this.onChange(!!this.resolve, false);
if (this.resolve) {
this.resolve(
@ -704,9 +704,12 @@ export default class ImageControl extends React.Component<
}
}
removeFile(file: FileValue, index: number) {
async removeFile(file: FileValue, index: number) {
const files = this.files.concat();
const dispatcher = await this.dispatchEvent('remove', file);
if (dispatcher?.prevented) {
return;
}
this.removeFileCanelExecutor(file, true);
files.splice(index, 1);
@ -756,7 +759,7 @@ export default class ImageControl extends React.Component<
});
}
onChange(changeImmediately?: boolean) {
async onChange(changeImmediately?: boolean, isFileChange = true) {
const {
multiple,
onChange,
@ -789,6 +792,12 @@ export default class ImageControl extends React.Component<
? newValue[valueField || 'value']
: newValue;
}
if (isFileChange) {
const dispatcher = await this.dispatchEvent('change');
if (dispatcher?.prevented) {
return;
}
}
onChange((this.emitValue = newValue || ''), undefined, changeImmediately);
this.syncAutoFill();
@ -973,6 +982,7 @@ export default class ImageControl extends React.Component<
}
}
);
this.dispatchEvent('change');
}
sendFile(
@ -987,7 +997,7 @@ export default class ImageControl extends React.Component<
}
const image = new Image();
image.onload = () => {
image.onload = async () => {
const width = image.width;
const height = image.height;
let error = '';
@ -1024,6 +1034,10 @@ export default class ImageControl extends React.Component<
if (error) {
file.state = 'invalid';
const dispatcher = await this.dispatchEvent('fail', {file, error});
if (dispatcher?.prevented) {
return;
}
cb(error, file);
} else {
this._upload(file, cb, onProgress);
@ -1033,13 +1047,13 @@ export default class ImageControl extends React.Component<
}
_upload(
file: Blob,
file: FileX,
cb: (error: null | string, file: Blob, obj?: FileValue) => void,
onProgress: (progress: number) => void
) {
const __ = this.props.translate;
this._send(file, this.props.receiver as string, {}, onProgress)
.then((ret: Payload) => {
.then(async (ret: Payload) => {
if (ret.status && (ret as any).status !== '0') {
throw new Error(ret.msg || __('File.errorRetry'));
}
@ -1050,9 +1064,22 @@ export default class ImageControl extends React.Component<
};
obj.value = obj.value || obj.url;
const dispatcher = await this.dispatchEvent('success', obj);
if (dispatcher?.prevented) {
return;
}
cb(null, file, obj);
})
.catch(error => cb(error.message || __('File.errorRetry'), file));
.catch(async error => {
const dispatcher = await this.dispatchEvent('fail', {
file,
error
});
if (dispatcher?.prevented) {
return;
}
cb(error.message || __('File.errorRetry'), file);
});
}
async _send(
@ -1206,6 +1233,12 @@ export default class ImageControl extends React.Component<
}
}
async dispatchEvent(e: string, data?: Record<string, any>) {
const {dispatchEvent} = this.props;
data = data ? data : this.state.files;
return dispatchEvent(e, createObject(this.props.data, {file: data}));
}
render() {
const {
className,