import * as React from 'react'; import { BasicConfig, BasicContainer, BasicContainerPropsInterface, } from '../../render/core/Container/types'; import {Upload, Icon, message, Modal} from '@native-ads/antd'; import {UploadChangeParam, UploadProps} from '@native-ads/antd/lib/upload'; import componentLoader from '../../render/util/componentLoader'; import {SET_FORM_ITEM_PAYLOAD} from '../../render/core/Form/actions'; import * as _ from 'lodash'; import Button from '@native-ads/antd/lib/button/button'; export class UploadConfig extends BasicConfig { /** * Upload的数据模型Key */ name: string; /** * 上传的地址 */ action: string; /** * 上传所需参数 */ data?: object; /** * 上传数据格式的限制 */ uploadType?: string[]; /** * 上传大小的限制 */ uploadSize?: number; /** * 上传数量的限制 */ uploadNum?: number; /** * 上传图片的宽度限制 */ uploadWidth?: number; /** * 上传图片的高度限制 */ uploadHeight?: number; /** * 上传列表的内建样式 */ listType?: 'text' | 'picture' | 'picture-card' ; /** * 自定义类 */ className?: string; /** * 自定义样式 */ style?: React.CSSProperties; } export class UploadPropsInterface extends BasicContainerPropsInterface { info: UploadConfig; /** * 更新表单元素的属性 */ $setFormItem: (payload: Partial) => void; } export class UploadStateInterface { previewVisible: boolean; previewImage: string; } export class AbstractUpload extends BasicContainer { constructor(props: UploadPropsInterface) { super(props); this.state = { previewVisible: false, previewImage: '', }; } handleCancel = () => this.setState({previewVisible: false}); handlePreview = (file: any) => { this.setState({ previewImage: file.url || file.thumbUrl, previewVisible: true, }); } getBase64 (img: any, callback: Function) { const reader = new FileReader(); reader.addEventListener('load', () => callback(reader.result)); reader.readAsDataURL(img); } validateType (content: UploadChangeParam, uploadType: string[]) { const file = content.file; let validateType: boolean; if (uploadType.length > 0) { validateType = uploadType.indexOf(file.type) > -1; } else { validateType = true; } return validateType; } validateSize (content: UploadChangeParam, uploadSize: number) { const file = content.file; let validateSize = file.size < uploadSize * 1024; return validateSize; } handleChange = (content: UploadChangeParam, uploadType: string[], uploadSize: number, uploadWidth?: number, uploadHeight?: number) => { const fileList = content.fileList; const file = content.file; const info = this.props.info; if (info.name && this.props.$setData) { this.props.$setData(info.name, fileList); } if (content.file.status === 'done') { // 上传后验证 // 验证类型 let validateTypeStatus = this.validateType(content, uploadType); if (!validateTypeStatus) { message.error('You can only upload ' + uploadType.join(',') + ' file!'); } // 验证大小 let validateSizeStatus = this.validateSize(content, uploadSize); if (!validateSizeStatus) { message.error('File must smaller than ' + uploadSize + 'KB!'); } // 验证尺寸 if (!_.isNil(uploadWidth) && !_.isNil(uploadHeight)) { // 如果需要验证尺寸 // 获取图片文件 this.getBase64(content.file.originFileObj, (thumbUrl: any) => { let validateWidthHeightStatus: boolean = true; let img = new Image(); img.onload = () => { const width = img.width; const height = img.height; if (width > uploadWidth || height > uploadHeight) { validateWidthHeightStatus = false; } if (!validateWidthHeightStatus) { message.error('Image must smaller than ' + uploadWidth + 'x' + uploadHeight); } const valid = validateTypeStatus && validateSizeStatus && validateWidthHeightStatus; fileList.map((item) => { if (item.uid === file.uid) { Object.assign(item, { 'validateTypeStatus': validateTypeStatus, 'validateSizeStatus': validateSizeStatus, 'validateWidthHeightStatus': validateWidthHeightStatus, }); if (file.response) { file.url = file.response.url; } if (!valid) { item.status = 'error'; } } }); // 验证之后更新状态 if (info.name && this.props.$setData) { this.props.$setData(info.name, fileList); } // 表单验证 if (this.props.$setFormItem) { this.props.$setFormItem({ formItemName: info.name, valid: valid, status: valid ? 'success' : 'error', }); } }; img.src = thumbUrl; }); } else { // 如果不需要验证尺寸 const valid = validateTypeStatus && validateSizeStatus; fileList.map((item) => { if (item.uid === file.uid) { Object.assign(item, { 'validateTypeStatus': validateTypeStatus, 'validateSizeStatus': validateSizeStatus, }); if (file.response) { file.url = file.response.url; } if (!valid) { item.status = 'error'; } } }); // 验证之后更新状态 if (info.name && this.props.$setData) { this.props.$setData(info.name, fileList); } // 表单验证 if (this.props.$setFormItem) { this.props.$setFormItem({ formItemName: info.name, valid: valid, status: valid ? 'success' : 'error', }); } } } if (content.file.status === 'removed') { // 删除之后验证表单 let validStatus: boolean = false; if (fileList.length > 0) { const validList = fileList.map((item: any) => { if (item.validateWidthHeight) { return item.validateWidthHeightStatus && item.validateSizeStatus && item.validateTypeStatus; } else { return item.validateSizeStatus && item.validateTypeStatus; } }); validStatus = validList.reduce((pre: boolean, next: boolean) => { return pre && next; }); } if (this.props.$setFormItem) { this.props.$setFormItem({ formItemName: info.name, valid: validStatus, status: validStatus ? 'success' : 'error' }); } } if (content.file.status === 'error') { // 表单验证 message.error('Upload fail'); if (this.props.$setFormItem) { this.props.$setFormItem({ formItemName: info.name, valid: false, status: 'error' }); } } } private mapUploadOptions(info: UploadConfig): UploadProps { return { className: info.className, style: info.style, listType: info.listType }; } render() { let info = this.getPropsInfo(this.props.info); const uploadProps = this.mapUploadOptions(info); if (!info.name) { return
name property is required for Upload Element
; } if (!this.isUnderContainerEnv()) { return
Upload component should be under container component
; } let value = this.getValueFromDataStore(info.name) || []; const {previewVisible, previewImage} = this.state; const action = info.action; const data = info.data || {}; const uploadType = info.uploadType || []; const uploadSize = info.uploadSize || 500; const uploadNum = info.uploadNum || 3; const uploadWidth = info.uploadWidth; const uploadHeight = info.uploadHeight; let modalElement: React.ReactNode; let uploadButton: React.ReactNode; if (info.listType === 'picture-card') { // 图片类型的上传格式 // 图片预览框 modalElement = ( example ); // 图片上传按钮 uploadButton = (
上传
); } let buttonElement: React.ReactNode; if (info.listType === 'text') { // 文本、视频类型的上传格式 // 上传按钮 buttonElement = ( ); } return (
{ this.handleChange(content, uploadType, uploadSize, uploadWidth, uploadHeight); }} > {value.length >= uploadNum ? null : uploadButton} {buttonElement} {modalElement}
); } } componentLoader.addComponent('upload', AbstractUpload, UploadPropsInterface);