import React, { Fragment } from 'react'; import { Button, Steps, Upload, Icon, Tabs, Table } from 'antd'; import styles from './ImportUtil.less'; import ButtonDiy from './ButtonDiy/ButtonDiy'; import { getToken } from '../utils/token'; import FormdataWrapper from '../utils/object-to-formdata-custom'; import config from '@/webPublic/one_stop_public/config'; import { connect } from 'dva'; import { getMessage, getModal } from '@/webPublic/one_stop_public/utils/utils'; import { giveFilePostDataInfoForTrue } from '@/webPublic/one_stop_public/Base16'; const Modal = getModal(); const message = getMessage(); const Step = Steps.Step; const TabPane = Tabs.TabPane; const exportExcel = CLIENT_TYPE == 'mobile' ? null : require('xlsx-oc').exportExcel; let tempCallback = () => { }; @connect(({ DataObj, loading }) => ({ DataObj, loading: loading.models.DataObj, })) export default class ImportUtil extends React.PureComponent { constructor(props) { super(props); tempCallback = this.props.callback; // const exportTemplateUrl = encodeURI( // `${config.httpServer}/DataObjApi/importTemplateDownload?objId=${this.props.objId}&name=${ // props.fileName // }`, // ); this.state = { ch: false, currentKey: '1', visible: false, current: 0, isShow: true, filekey: '', sucData: [], errData: [], column: [], confirmLoading: false, // exportTemplateUrl, isNextDisabled: false, }; } showModal = () => { this.setState({ sucData: [], errData: [], column: [], current: 0, isShow: true, isNextDisabled: false, filekey: '', visible: true, }); }; handleOk = (e) => { this.setState({ visible: false, }); }; handleCancel = (e) => { this.setState({ visible: false, }); }; next() { const current = this.state.current + 1; if (current === 2) { this.setState({ current: current, isShow: false, }); if (this.state.errData.lenth > 0) { message.error('请检查数据'); return; } else { this.import(); } } if (current === 3) { console.log('current === 3'); this.setState({ current: current, isShow: true, }, () => { if (tempCallback && typeof tempCallback === 'function') { tempCallback(); tempCallback = null; } }); } } prev() { const current = this.state.current - 1; this.setState({ current }); } import() { const { dispatch, importParams, importConfig } = this.props; dispatch({ type: 'DataObj/importExecute', payload: { ...(importParams || {}), cacheKey: this.state.filekey, objId: this.props.objId, }, callback: (res) => { this.next(); message.success('导入成功'); this.setState({ current: 3, isShow: true, visible: false, }); // if (typeof tempCallback === 'function') { // tempCallback(); // tempCallback = null; // } }, }); } getCachKey = (filePath) => { const { dispatch, importParams, importConfig } = this.props; dispatch({ type: 'DataObj/importAnalyse', payload: { ...(importParams || {}), isLocal: false, filePath, importConfig: importConfig ? JSON.stringify(importConfig) : null, objId: this.props.objId, }, callback: (res) => { this.setState({ filekey: res.cacheKey, }); this.queryFile(res.cacheKey); }, }); }; queryFile = (cacheKey) => { const { dispatch, importParams } = this.props; dispatch({ type: 'DataObj/importDataQuery', payload: { ...(importParams || {}), cacheKey, objId: this.props.objId, }, callback: (res) => { this.setState({ current: 1, isShow: false, sucData: res.pass, errData: res.noPass, column: res.column, }); if (res.noPass && res.noPass.length == 0) { if (res.pass.length == 0) { message.error('当前没有验证成功的数据,无法导入。'); this.setState({ currentKey: '1', ch: !this.state.ch, isNextDisabled: true, }); } else { message.success('所有数据验证通过,请确认后点击下一步。'); this.setState({ currentKey: '2', ch: !this.state.ch, isNextDisabled: false, }); } } else { message.error('当前存在未验证通过的数据,请按错误提示检测更正导入文件'); this.setState({ currentKey: '1', ch: !this.state.ch, isNextDisabled: true, }); } }, }); }; changePane = (activeKey) => { this.setState({ currentKey: activeKey }); }; exportError = (column, dataSource) => { if (exportExcel == null) { message.info('当前终端暂不支持此功能'); return; } var _headers = []; for (var i = 0; i < column.length; i++) { _headers.push({ k: column[i].dataIndex, v: column[i].title }); } for (var j = 0; j < dataSource.length; j++) { dataSource[j].index = j + 1; } exportExcel(_headers, dataSource); }; downloadFile = () => { this.setState({ confirmLoading: true }); const { objId, fileName, importParams, importConfig } = this.props; const params = { ...importParams, importConfig: importConfig ? JSON.stringify(importConfig) : null, objId, fileName, }; let url = `${config.httpServer}/DataObjApi/importTemplateDownload`; let newParams = giveFilePostDataInfoForTrue(params, url); if(newParams && newParams.datas){ newParams.datas.token = getToken(); } fetch(newParams.url, { method: 'POST', body: FormdataWrapper(newParams.datas), }) .then((res) => { if (res.status != '200') { return res.json(); } else { return res.blob(); } }) .then((data) => { if (data instanceof Blob) { let a = document.createElement('a'); let url = window.URL.createObjectURL(data); let filename = (this.props.fileName ? this.props.fileName : '导入模板.') + (this.props.ext || 'xlsx'); a.href = url; a.download = filename; a.click(); window.URL.revokeObjectURL(url); a = null; } else { message.error(`文件导出错误`); } }) .catch((err) => { message.error(`网络请求超时`); }) .finally(() => { this.setState({ confirmLoading: false }); }); }; render() { const props = { name: 'file', action: config.uploadUrl, headers: { Authorization: `bearer ${getToken()}`, }, data: { token: getToken(), }, accept: '.xlsx', showUploadList: false, onChange: (info) => { if (info.file.status !== 'uploading') { } if (info.file.status === 'done') { message.success(`${info.file.name} 上传成功`); let x = info.file.response; this.getCachKey(x); } else if (info.file.status === 'error') { message.error(`${info.file.name} 上传失败`); } }, }; const steps = [ { title: '上传Excel', }, { title: '验证数据', }, { title: '数据导入', }, { title: '导入完成', }, ]; const { current } = this.state; const { name } = this.props; const column1 = this.state.column ? [ { title: '序号', dataIndex: 'index', fixed: 'left', width: 50, render: (v, r, i) => i + 1, }, ...this.state.column, ] : []; let column2 = this.state.column ? [...this.state.column] : []; if (column1.length > 1) { column1[1].render = (val) => <span style={{ color: 'red' }}>{val}</span>; } if (column2) { let xuhao = column2.find((g) => g.dataIndex === '序号'); if (!xuhao) { column2.unshift({ title: '序号', fixed: 'left', width: 50, render: (v, r, i) => i + 1, dataIndex: '序号', }); } } const btn = { name: name || '批量导入', type: 'default', className: 'defaultBlue', ...(this.props.btn ? this.props.btn : {}), }; return ( <span> <ButtonDiy {...btn} handleClick={this.showModal} /> <Modal visible={this.state.visible} onOk={this.handleOk} maskClosable={false} destroyOnClose onCancel={this.handleCancel} title={null} footer={null} width={'80%'}> <div className={styles.nomal}> <p className={styles.import}>EXCEL导入向导</p> <div style={{ margin: 'auto 23px' }}> <Steps current={current}> {steps.map((item) => ( <Step key={item.title} title={item.title} /> ))} </Steps> <div className='steps-content'>{steps[this.state.current].content}</div> <div className={styles.button}> {this.state.current < steps.length - 1 && this.state.current !== 0 && ( <ButtonDiy name={this.state.current == 3 ? '确认导入' : '下一步'} type='primary' disabled={this.state.current != 3 && this.state.isNextDisabled} // className='primaryBlue' handleClick={() => this.next()} /> )} {this.state.current > 0 && ( <ButtonDiy style={{ marginLeft: 8 }} name='上一步' className='defaultBlue' handleClick={() => this.prev()} /> )} </div> </div> <div className={styles.tip}> <p className={styles.tipContent}> <span>欢迎使用EXCEL导入向导,首先请您上传需要导入的EXCEL文件。</span> <span> 点击“选择文件”选择您要导入的EXCEL文件,点击“开始上传”将其上传到服务器上,点击“清空队列”清空当前上传文件队列。 </span> </p> </div> {this.state.isShow ? ( <div className={styles.buttonDown}> <Upload {...props}> <Button> <Icon type='upload' /> 点击上传 </Button> </Upload> <ButtonDiy name={'下载模板'} type='primary' // className='primaryBlue' handleClick={() => this.downloadFile()} loading={this.state.confirmLoading} /> </div> ) : ( <Upload {...props}> <Button> <Icon type='upload' /> 重新上传 </Button> </Upload> )} {this.state.isShow ? ( <div className={styles.attentionItem}> <p>导入事项</p> <p>1. 导入操作一次只能上传 1 个EXCEL文件。</p> <p>2. 导入文件最大文件大小上传 1 GB。</p> <p>3. 只能上传EXCEL文件(XLS, XLSX) 默认支持EXCEL 2003和EXCEL 2007。</p> <p>4. 请将EXCEL文件的所有单元格格式设置为“文本”格式</p> </div> ) : ( <div className={styles.error} style={{ marginTop: 20 }}> <Tabs activeKey={this.state.currentKey} key={this.state.ch} onChange={this.changePane} type='card'> {this.state.errData && this.state.errData.length == 0 ? ( '' ) : ( <TabPane tab={<span style={{ color: 'red' }}>验证错误列表</span>} key='1'> <Button style={{ marginTop: 5, marginBottom: 5 }} type='danger' onClick={this.exportError.bind(this, column1, this.state.errData)}> 导出错误信息 </Button> <Table columns={column1} size='small' style={{ overflow: 'auto' }} dataSource={this.state.errData} bordered={true} scroll={{ x: 'max-content' }} /> </TabPane> )} <TabPane tab={<span style={{ color: 'green' }}>验证成功列表</span>} key='2'> <Button style={{ marginTop: 5, marginBottom: 5 }} type='primary' onClick={this.exportError.bind(this, column2, this.state.sucData)}> 导出正确信息 </Button> <Table columns={column2} size='small' style={{ overflow: 'auto' }} dataSource={this.state.sucData} bordered={true} scroll={{ x: 'max-content' }} /> </TabPane> </Tabs> </div> )} </div> </Modal> </span> ); } }