ImportUtil.js 9.4 KB
import React, { Fragment } from 'react';
import { Button, Modal, Steps, Upload, Icon, message, Tabs, Table } from 'antd';
import styles from './ImportUtil.less';
import ButtonDiy from '@/baseComponent/ButtonDiy';

import config from '@/config/config';
import { connect } from 'dva';
import { exportExcel } from 'xlsx-oc';
const Step = Steps.Step;

const TabPane = Tabs.TabPane;

@connect(({ DataObj, loading }) => ({
	DataObj,
	loading: loading.models.DataObj,
}))
export default class ImportUtil extends React.PureComponent {
	constructor(props) {
		super(props);

		const exportTemplateUrl = encodeURI(
			`${config.sqlFormsServer}/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: [],

			exportTemplateUrl,

			isNextDisabled: false,
		};
	}

	showModal = () => {
		this.setState({
			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) {
			this.setState({
				current: current,
				isShow: true,
			});
			if (this.props.callback) {
				this.props.callback();
			}
		}
	}

	prev() {
		const current = this.state.current - 1;
		this.setState({ current });
	}

	import() {
		const { dispatch, importParams } = 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 (this.props.callback) {
					this.props.callback();
				}
			},
		});
	}

	getCachKey = (filePath) => {
		const { dispatch, importParams } = this.props;
		dispatch({
			type: 'DataObj/importAnalyse',
			payload: {
				...(importParams || {}),
				isLocal: false,
				filePath,
				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) => {
		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);
	};

	render() {
		const props = {
			name: 'file',
			action: config.sqlFormsServer + '/upload',

			headers: {
				authorization: 'authorization-text',
			},
			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} file upload failed.`);
				}
			},
		};
		const steps = [
			{
				title: '上传Excel',
			},
			{
				title: '验证数据',
			},
			{
				title: '数据导入',
			},
			{
				title: '导入完成',
			},
		];

		const { current } = this.state;
		const { name, loading } = this.props;
		const column1 = this.state.column
			? [
					{
						title: '序号',
						dataIndex: 'index',
						fixed: 'left',
						width: 50,
						render: (v, r, i) => i + 1,
					},
					...this.state.column,
			  ]
			: [];
		var column2 = this.state.column ? [...this.state.column] : [];
		if (column1.length > 1)
			column1[1].render = (val) => <span style={{ color: 'red' }}>{val}</span>;

		column2.splice(0, 1);
		column2 = [{ title: '序号', fixed: 'left', width: 50, render: (v, r, i) => i + 1 }, ...column2];

		return (
			<span>
				<ButtonDiy
					name={name || '批量导入'}
					type="default"
					className="defaultBlue"
					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 style={{ marginRight: '20px' }}>
										<Icon type="upload" />
										点击上传
									</Button>
								</Upload>
								<Button href={this.state.exportTemplateUrl} target="_blank" type="danger">
									下载模板
								</Button>
							</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 2003EXCEL 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}
											/>
										</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}
										/>
									</TabPane>
								</Tabs>
							</div>
						)}
					</div>
				</Modal>
			</span>
		);
	}
}