1. 安裝npm i rc-upload(官網(wǎng)https://www.npmjs.com/package/rc-upload)
2. 使用
引入import RcUpload from 'rc-upload'
interface FileUploadProps {
name?: string // 上傳的字段文件名
action?: string // 上傳的路徑
className?: string // 樣式類名
style?: object // 行內(nèi)樣式
multiple?:boolean // 是否多選
accept?:string // 允許上傳的類型
size?:number // 限制的大小
params?: any // 上傳的時(shí)候的參數(shù)
successChange?: Function // 成功之后
mobxGlobal?: any
}
interface FileUploadState {
accept: string
fileSize: number
filename: string
errmsg: string
errurl: string
visible: boolean
progressPercent: number
}
@inject('mobxGlobal')
export default class FileUpload extends RootComponent<FileUploadProps, FileUploadState> {
basicModel: React.RefObject<BasicModal>
constructor (props:any) {
super(props)
const { accept, size, name } = this.props
this.state = {
accept: accept || '.xlsx,.xls', // '.xlsx,.xls'
fileSize: size || 10,
filename: name || 'file',
errmsg: '',
errurl: '',
visible: false,
progressPercent: 0
}
this.basicModel = React.createRef()
}
/**
* 組件銷毀之前 對(duì) state 的狀態(tài)做出處理
*/
componentWillUnmount () {
this.setState = (state, callback) => {}
}
// 開始上傳文件:實(shí)際不會(huì)進(jìn)行上傳的
onStart = (file:any) => {
// 文件開始上傳
}
onProgress = (file:any) => {
// console.log(file)
}
/** 導(dǎo)出之后的下載 */
showModel = (url:string, msg:string) => {
this.setState({
errmsg: msg,
errurl: url
})
this.handleModal(1) // 正常導(dǎo)入的錯(cuò)誤的信息
}
onSuccess = (res: any, file: any) => {
let { successChange } = this.props
if (successChange) {
successChange(res)
} else {
const { errNum, errMessage, excelUrl, successNum } = res.data
if (errNum > 0) {
this.showModel(excelUrl, errMessage)
} else if (errNum < 1 && successNum > 0) {
this.$message.success('導(dǎo)入成功!')
} else {
this.$message.error('導(dǎo)入失??!')
}
}
}
onError = (err:any, flg:boolean) => {
const { code, msg } = err
this.error(msg || err)
// if (flg) {
// if (code === 401) {
// this.error(msg)
// } else {
// this.error('文件格式不正確!')
// }
// } else {
// this.error(err)
// }
}
/* 文件上傳的 檢查 */
beforeUpload = (file:any, fileList:any) => {
const { accept, fileSize } = this.state
const { size, name } = file
let a = '文件上傳出錯(cuò)'
return new Promise((resolve, reject) => {
// 對(duì)文件的信息進(jìn)行 類型判斷
let index = name.lastIndexOf('.')
let typeArry = accept.split(',')
let suffer = (name as string).substring(index, name.length)
if (typeArry.indexOf(suffer) < 0) {
a = '請(qǐng)上傳正確的文件'
this.$message.error(a)
reject(a)
}
if ((size / 1024 / 1024) > fileSize) { // 對(duì)文件進(jìn)行 大小判斷
a = `上傳文件的大小不能超過(guò)${fileSize}M`
this.$message.warning(a)
reject(a)
}
resolve(file)
})
}
// /* 自定義的文件上傳, 默認(rèn)的不傳,直接成功 */
// customRequest = (request:any) => {
// const { action, file, filename, fileSize, data, onProgress, onSuccess, onError } = request
// let formData = new FormData()
// let params = this.props.params
// // 創(chuàng)建對(duì)象的信息
// formData.append(filename, file, file.name)
// if (params) {
// for (const key in params) {
// formData.append(key, params[key])
// }
// }
// this.setState({ visible: true, progressPercent: 0 })
// let time:any = setInterval(() => {
// let { progressPercent } = this.state
// if (progressPercent >= 80) {
// clearInterval(time)
// } else {
// progressPercent += 8
// }
// this.setState({ progressPercent })
// }, 1000)
// this.axios.upload({
// method: 'post',
// url: action,
// data: formData
// // onUploadProgress: (progressEvent:any) => {
// // if (progressEvent.lengthComputable) {
// // this.onUploadProgressLoading(progressEvent)
// // }
// // }
// }).then((res:any) => {
// const { code, data, msg } = res.data
// if (code === 200) {
// onSuccess(res.data, file)
// } else {
// onError(res.data, true)
// }
// }).catch((err:any) => {
// onError(err, false)
// }).finally(() => {
// this.setState({ visible: false, progressPercent: 100 })
// })
// }
/* 自定義的文件上傳, 默認(rèn)的不傳,直接成功 */
customRequest = (request:any) => {
const { action, file, filename, fileSize, data, onProgress, onSuccess, onError } = request
const { mobxGlobal: { setTaskNum } } = this.props
let formData = new FormData()
let params = this.props.params
// 創(chuàng)建對(duì)象的信息
formData.append(filename, file, file.name)
if (params) {
for (const key in params) {
formData.append(key, params[key])
}
}
this.axios.upload({
method: 'post',
url: action,
data: formData
}).then((res:any) => {
let { data, code, msg } = res.data
if (code === 200) {
this.warning('數(shù)據(jù)正在導(dǎo)入中,請(qǐng)至任務(wù)管理查看報(bào)表!')
this.axios.request(this.api.count).then(({ code, data }) => {
if (code === 200) {
let { sun } = data
sun = sun > 99 ? '99+' : sun
this.props.mobxGlobal.setTaskNum(sun)
}
})
} else {
this.warning(`${msg[0]}`)
}
}).finally(() => {
this.setState({ visible: false, progressPercent: 100 })
})
}
/* 打開彈窗: 錯(cuò)誤的小消息存在 */
handleModal = (num: number = 0) => {
const { handleOk, handleCancel } = this.basicModel.current as BasicModal
num === 0 ? handleCancel() : handleOk()
}
/** 下載數(shù)據(jù) */
dowloadFile = (url:string) => {
let link = document.createElement('a')
link.style.display = 'none'
link.href = url
document.body.appendChild(link)
link.click()
this.handleModal(0)
this.$message.success('下載成功!')
}
/** 上傳的進(jìn)度 */
// onUploadProgressLoading = ({ total, loaded }:any) => {
// let progressPercent:number = (total / loaded) * 100
// let visible:boolean = true
// this.setState({ visible, progressPercent })
// }
render () {
const { multiple, action, name, style } = this.props
const { filename, accept, errmsg, errurl, visible, progressPercent } = this.state
const config = {
action: action,
name: filename,
accept: accept, // 默認(rèn)上傳的是圖片
multiple: multiple, // 多選
onStart: this.onStart, // 開始上傳文件
onProgress: this.onProgress, // 進(jìn)度回調(diào),僅適用于現(xiàn)代瀏覽器
onSuccess: this.onSuccess, // 成功回調(diào)
onError: this.onError, // 錯(cuò)誤回調(diào)
beforeUpload: this.beforeUpload, // 上傳前的驗(yàn)證
customRequest: this.customRequest // 提供默認(rèn)xhr行為的替代以進(jìn)行其他自定義
}
return (
<div className="upload-file-content" style={style}>
<RcUpload {...config}>
{this.props.children}
</RcUpload>
<Modal title="" closable={false} footer={null} visible={visible}>
<div className="upload-progress">
<p>正在導(dǎo)入,請(qǐng)稍等...</p>
<Progress strokeColor={{
to: '#24C8EA',
from: '#2B8FF9'
}}
status="active" percent={progressPercent} />
</div>
</Modal>
<BasicModal ref={this.basicModel} title="提示">
<Row>
<Col span={7} style={{ textAlign: 'center' }}><img src={js}></img></Col>
<Col span={17} className="error-col">{errmsg}</Col>
</Row>
<Row>
<div className="import-error">
<p>出錯(cuò)原因可能為:</p>
<p>1.數(shù)據(jù)不完整(必填項(xiàng)為空);</p>
<p>2.字段格式不正確(如導(dǎo)入數(shù)據(jù)中的“項(xiàng)目”為系統(tǒng)內(nèi)沒(méi)有的項(xiàng)目名稱等);</p>
<p>3.與原數(shù)據(jù)沖突(如導(dǎo)入的員工相關(guān)記錄在系統(tǒng)中已存在)。</p>
</div>
</Row>
<Row>
<Button type="primary" onClick={() => (this.dowloadFile(errurl))}>下載出錯(cuò)數(shù)據(jù)</Button>
</Row>
</BasicModal>
</div>
)
}
}
該文件主要用于后臺(tái)管理系統(tǒng)的導(dǎo)入功能