import React from 'react'; import { Select, Modal, Table, Row, Col, Tag, Form, message, notification } from 'antd'; import { connect } from 'dva'; import { getToken } from '../../utils/token'; import config from '@/webPublic/one_stop_public/config'; import QueryItem from '../QueryItem'; import styles from '../Ability.css'; import FormdataWrapper from '../../utils/object-to-formdata-custom'; import ButtonDiy from '../ButtonDiy/ButtonDiy'; import { nameSpan, nameSpan3, nameSpan2 } from './config'; const Option = Select.Option; const FormItem = Form.Item; @connect(({ cms, loading }) => ({ cms, loading: loading.models.cms, })) @Form.create() export default class StatisticsInfo extends React.Component { constructor(props) { super(props); this.state = { exportLoading: false, visiable: false, queryVisiable: false, groupVisiable: false, sortVisiable: false, currentQueryKey: null, currentGroupKey: null, orderVisiable: false, currentOrderKey: null, querys: [], orders: [], groups: [], gs: [], os: [], qs: [], x: null, y: null, z: null, currentKey: null, XxX: null, mockData: [], mockXZData: [], targetKeys: [], sourceSelectedKeys: [], targetSelectedKeys: [], infos: {}, columns: [], dataSource: [], flag: false, }; } onSelectChange = (sourceSelectedKeys, targetSelectedKeys) => { this.setState({ sourceSelectedKeys, targetSelectedKeys }); }; deleteQuery = (i) => { const querys = this.state.querys; querys.splice(i, 1); this.setState({ querys }); }; deleteOrder = (i) => { const orders = this.state.orders; orders.splice(i, 1); this.setState({ orders }); }; deleteGroup = (i) => { const groups = this.state.groups; groups.splice(i, 1); this.setState( { groups: [...groups], }, () => { this.finish(); }, ); }; open = () => { const { dispatch } = this.props; dispatch({ type: 'DataObj/getExportInfo', payload: { objId: this.props.objId, }, callback: (infos) => { const filterXZKeys = this.props.filterXZKeys; const mockData = []; const mockXZData = []; const qs = []; const gs = []; const os = []; for (var key in infos) { const x = infos[key]; mockData.push({ key: x.field, title: x.name, chosen: false, hql: x.hql, }); if (filterXZKeys != null) { if (filterXZKeys.includes(key)) { mockXZData.push({ key: x.field, title: x.name, chosen: false, hql: x.hql, }); } } else { mockXZData.push({ key: x.field, title: x.name, chosen: false, hql: x.hql, }); } if (x.canQuery) { qs.push(x); } if (x.canGroup) { gs.push(x); } if (x.canOrder) { os.push(x); } } this.setState({ mockData, mockXZData, infos, visiable: true, qs, gs, os, }); }, }); }; onCancle = () => { this.setState({ visiable: false }); }; handleChange = (targetKeys, direction, moveKeys) => { this.setState({ targetKeys }); }; okOrder = () => { const orders = this.state.orders; orders.push(this.state.infos[this.state.currentOrderKey]); this.setState({ orders, orderVisiable: false, currentOrderKey: null }); }; okGroup = () => { const groups = this.state.groups; if (!this.state.currentGroupKey) { message.warning('请选择一个聚合条件'); return false; } groups.push(this.state.infos[this.state.currentGroupKey]); this.setState( { groups, groupVisiable: false, currentGroupKey: null, }, () => { this.finish(); }, ); }; addQuery = () => { this.setState({ queryVisiable: true }); }; okQuery = () => { if (!this.state.currentQueryKey) { message.warning('请选择一个查询条件'); return false; } const querys = this.state.querys; querys.push(this.state.infos[this.state.currentQueryKey]); this.setState({ querys, queryVisiable: false, currentQueryKey: null }); }; finish = () => { const { dispatch, objId } = this.props; const { x, y, z, infos, XxX, currentKey, groups } = this.state; if (x == null) { message.warning('请选择第一统计项'); return; } if (y == null) { message.warning('请选择行数据'); return; } this.props.form.validateFields((err, fieldsValue) => { if (err) return; const qqs = this.props.mustQuerys || []; const ggs = []; for (var key in fieldsValue) { var xx = key.indexOf('__'); let kk = key.substr(xx + 2); qqs.push({ notes: this.state.infos[kk].notes, hql: this.state.infos[kk].hql, c: this.state.infos[kk].type, x: fieldsValue[key].stringX, v: fieldsValue[key].string, }); } if (groups.length === 0) { message.warning('请至少选择一个聚合条件'); return; } for (var i = 0; i < groups.length; i++) { ggs.push({ hql: groups[i].hql }); } const tx = infos[x]; const ty = infos[y]; var ttx; var tty; var ttz; if (tx.notes) { if (tx.notes.indexOf('com.') == -1) { ttx = infos[x].hql.replace('.id', '.dictName'); } else { ttx = infos[x].hql; } } else { ttx = infos[x].hql; } if (ty.notes) { if (ty.notes.indexOf('com.') == -1) { tty = infos[y].hql.replace('.id', '.dictName'); } else { tty = infos[y].hql; } } else { tty = infos[y].hql; } if (z != null) { const tz = infos[z]; if (tz && tz.notes) { if (tz.notes.indexOf('com.') == -1) { ttz = infos[z].hql.replace('.id', '.dictName'); } else { ttz = infos[z].hql; } } else { ttz = infos[z].hql; } } dispatch({ type: 'DataObj/getStatistics', payload: { x: ttx, y: tty, z: ttz, objId, xXx: XxX, hql: currentKey && infos[currentKey] ? infos[currentKey].hql : null, querys: JSON.stringify(qqs), groups: JSON.stringify(ggs), }, callback: (data) => { this.setState({ dataSource: data.dataSource, columns: data.columns }); }, }); }); }; downloadFile(url, params) { this.setState({ exportLoading: true }); fetch(url, { method: 'POST', body: FormdataWrapper(params), }) .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 : '导出文件') + '.xlsx'; a.href = url; a.download = filename; a.click(); window.URL.revokeObjectURL(url); a = null; } else { notification.error({ message: `文件导出错误`, description: data.errMsg, }); } }) .catch((err) => { notification.error({ message: `网络请求超时`, }); }) .finally(() => { this.setState({ exportLoading: false }); }); } export = () => { const { dispatch, objId } = this.props; const { x, y, z, infos, XxX, currentKey, groups } = this.state; if (x == null) { message.warning('请选择第一统计项'); return; } if (y == null) { message.warning('请选择行数据'); return; } this.props.form.validateFields((err, fieldsValue) => { if (err) return; const qqs = this.props.mustQuerys || []; const ggs = []; for (var key in fieldsValue) { var xx = key.indexOf('__'); let kk = key.substr(xx + 2); qqs.push({ notes: this.state.infos[kk].notes, hql: this.state.infos[kk].hql, c: this.state.infos[kk].type, x: fieldsValue[key].stringX, v: fieldsValue[key].string, }); } if (groups.length === 0) { message.warning('请至少选择一个聚合条件'); return; } for (var i = 0; i < groups.length; i++) { ggs.push({ hql: groups[i].hql }); } const tx = infos[x]; const ty = infos[y]; var ttx; var tty; var ttz; if (tx.notes) { if (tx.notes.indexOf('com.') == -1) { ttx = infos[x].hql.replace('.id', '.dictName'); } else { ttx = infos[x].hql; } } else { ttx = infos[x].hql; } if (ty.notes) { if (ty.notes.indexOf('com.') == -1) { tty = infos[y].hql.replace('.id', '.dictName'); } else { tty = infos[y].hql; } } else { tty = infos[y].hql; } if (z != null) { const tz = infos[z]; if (tz && tz.notes) { if (tz.notes.indexOf('com.') == -1) { ttz = infos[z].hql.replace('.id', '.dictName'); } else { ttz = infos[z].hql; } } else { ttz = infos[z].hql; } } const param = { x: ttx, y: tty, z: ttz, objId, xXx: XxX, hql: currentKey && infos[currentKey] ? infos[currentKey].hql : null, querys: JSON.stringify(qqs), groups: JSON.stringify(ggs), }; let downloadUrl = config.httpServer + '/DataObjApi/exportStatistics?'; const token = getToken() != null && getToken() != 'null' ? getToken() : '0000'; downloadUrl = `${downloadUrl}token=${token}`; this.downloadFile(downloadUrl, param); }); }; cancelGroup = () => { this.setState({ currentGroupKey: null, groupVisiable: false }); }; cancelQuery = () => { this.setState({ currentQueryKey: null, queryVisiable: false }); }; cancelOrder = () => { this.setState({ currentOrderKey: null, orderVisiable: false }); }; selectOrder = (e) => { this.setState({ currentOrderKey: e }); }; selectQuery = (e) => { this.setState({ currentQueryKey: e, flag: !this.state.flag }); }; selectGroup = (e) => { this.setState({ currentGroupKey: e, flag: !this.state.flag }); }; changeX = (x) => { this.setState( { x, flag: !this.state.flag, }, () => { this.finish(); }, ); }; changeY = (y) => { this.setState( { y, flag: !this.state.flag, }, () => { this.finish(); }, ); }; changeZ = (z) => { this.setState({ z, flag: !this.state.flag }); }; cancelZ = () => { this.setState({ z: null, flag: !this.state.flag }); }; selectXxX = (XxX) => { this.setState({ XxX, flag: !this.state.flag }); }; selectCurrentKey = (currentKey) => { this.setState({ currentKey, XxX: null, flag: !this.state.flag }); }; cancelCurrentKey = () => { this.setState({ currentKey: null, XxX: null, flag: !this.state.flag }); }; componentDidMount() { // this.open(); } pageConfig = (item = 0) => { const { querys, groups, currentKey, XxX, infos, mockData, mockXZData, qs, gs, x, y, z, currentQueryKey, currentGroupKey, } = this.state; let xxxs = []; if (currentKey != null) { if ( infos[currentKey].type == 'java.lang.Integer' || infos[currentKey].type == 'java.lang.Double' || infos[currentKey].type == 'java.lang.Long' ) { xxxs = [ { label: '数量', value: 'count' }, { label: '最大值', value: 'max' }, { label: '最小值', value: 'min', }, { label: '平均值', value: 'avg' }, { label: '求和', value: 'sum' }, ]; } else { xxxs = [{ label: '数量', value: 'count' }]; } } let optionQs = []; for (let item of qs) { let add = true; for (let i = 0; i < querys.length; i++) { if (querys[i].field === item.field) { add = false; break; } } if (add) { optionQs.push(item); } } let optionGs = []; for (let item of gs) { let add = true; for (let i = 0; i < groups.length; i++) { if (groups[i].field === item.field) { add = false; break; } } if (add) { optionGs.push(item); } } const config = [ { required: true, selectConfig: [ { name: '第一统计项', value: x, onChange: this.changeX, options: mockXZData, optionKey: 'key', optionName: 'title', }, ], }, { required: false, selectConfig: [ { name: '第二统计项', value: z, onChange: this.changeZ, options: mockXZData, optionKey: 'key', optionName: 'title', }, ], buttonConfig: [ { name: '取消', handleClick: this.cancelZ, className: 'defaultRed', key: 'cancel', }, ], }, { required: true, selectConfig: [ { name: '行数据', value: y, onChange: this.changeY, options: mockData, optionKey: 'key', optionName: 'title', }, ], }, { required: false, selectConfig: [ { name: '统计指标', value: currentKey, onChange: this.selectCurrentKey, options: mockData, optionKey: 'key', optionName: 'title', }, { name: '', value: XxX, onChange: this.selectXxX, options: xxxs, optionKey: 'value', optionName: 'label', }, ], buttonConfig: [ { name: '取消', handleClick: this.cancelCurrentKey, className: 'defaultRed', key: 'cancel', }, ], }, { required: false, selectConfig: [ { name: '查询条件', value: currentQueryKey, onChange: this.selectQuery, options: optionQs, optionKey: 'field', optionName: 'name', }, ], buttonConfig: [ { name: '确定', handleClick: this.okQuery, className: 'defaultBlue', key: 'confirm', }, { name: '取消', handleClick: this.cancelQuery, className: 'defaultRed', key: 'cancel', }, ], }, { required: false, selectConfig: [ { name: '聚合条件', value: currentGroupKey, onChange: this.selectGroup, options: optionGs, optionKey: 'field', optionName: 'name', }, ], buttonConfig: [ { name: '确定', handleClick: this.okGroup, className: 'defaultBlue', key: 'confirm', }, { name: '取消', handleClick: this.cancelGroup, className: 'defaultRed', key: 'cancel', }, ], }, ]; return config[item]; }; selectDom = (item) => { const config = this.pageConfig(item); return ( <Row> {config.selectConfig.map((selectConfigItem, dataIndex) => { const nameSpanThis = dataIndex > 0 ? nameSpan2 : nameSpan; return ( <Col span={4} style={{ paddingLeft: '15px' }} key={dataIndex}> <FormItem label={selectConfigItem.name} required={config.required || false} colon={false} labelCol={{ xl: nameSpanThis.small, xxl: nameSpanThis.big, }} wrapperCol={{ xl: 24 - nameSpanThis.small, xxl: 24 - nameSpanThis.big, }}> <Select style={{ width: '100%' }} onChange={selectConfigItem.onChange} value={selectConfigItem.value}> {selectConfigItem.options.map((r) => { return ( <Option key={r[selectConfigItem.optionKey]} value={r[selectConfigItem.optionKey]}> {r[selectConfigItem.optionName]} </Option> ); })} </Select> </FormItem> </Col> ); })} {typeof config.buttonConfig !== 'undefined' && config.buttonConfig.length ? config.buttonConfig.map((buttonDs) => { return ( <Col span={1} key={buttonDs.key} style={{ paddingLeft: '15px' }}> <FormItem colon={false} labelCol={{ xl: nameSpan.small, xxl: nameSpan.big, }} wrapperCol={{ xl: 24 - nameSpan.small, xxl: 24 - nameSpan.big, }}> <ButtonDiy name={buttonDs.name} type="default" className={buttonDs.className} handleClick={buttonDs.handleClick} /> </FormItem> </Col> ); }) : null} </Row> ); }; render() { const { form, loading } = this.props; const { visiable, querys, groups, exportLoading, infos, columns, dataSource, x, y, z, } = this.state; const loadingxxx = loading || exportLoading; let columnsTemp = columns; if (columnsTemp.length > 0) { if (z == null) { columnsTemp[0].title = ( <div className={styles.out2} style={{ fontSize: 14 }}> <span className={styles.title1}>{infos[x] ? infos[x].name : ''}</span>{' '} <span className={styles.title3}>{infos[y] ? infos[y].name : ''}</span> </div> ); columnsTemp[0].width = 200; } else { columnsTemp[0].title = ( <div className={styles.out} style={{ fontSize: 14 }}> <span className={styles.title1}>{infos[x] ? infos[x].name : ''}</span>{' '} <span className={styles.title2}>{infos[z] ? infos[z].name : ''}</span>{' '} <span className={styles.title3}>{infos[y] ? infos[y].name : ''}</span> </div> ); columnsTemp[0].width = 200; } } return ( <span> {/* 暂时屏蔽 */} <ButtonDiy name="自定义统计" type="default" className="defaultBlue" handleClick={this.open} /> <div id="downloadDiv" style={{ display: 'none' }} /> <Modal width={'95%'} maskClosable={false} destroyOnClose title="自定义统计" visible={visiable} footer={null} onCancel={this.onCancle}> {this.selectDom(0)} {/*第一统计项*/} {this.selectDom(1)} {/*第二统计项*/} {this.selectDom(2)} {/*行数据*/} {this.selectDom(3)} {/*统计指标*/} {this.selectDom(4)} {/*查询条件*/} <div style={{ textAlign: 'left', paddingLeft: '25px', }}> {querys.map((r, i) => ( <FormItem key={i} labelCol={{ xl: nameSpan3.small, xxl: nameSpan3.big, }} wrapperCol={{ xl: 24 - nameSpan3.small, xxl: 24 - nameSpan3.big, }} label={r.name}> {form.getFieldDecorator(i + 'q__', { initialValue: { stringX: '=' }, rules: [ { validator: (rule, value, callback) => { var errors = []; if (value == null) { errors.push(new Error('请输入查询值!', rule.field)); } else { if ( value.stringX !== 'IS NOT NULL' && value.stringX !== 'IS NULL' && value.string == null ) { errors.push(new Error('请输入查询值!', rule.field)); } } callback(errors); }, }, ], })(<QueryItem obj={r} deleteQuery={this.deleteQuery.bind(this, i)} />)} </FormItem> ))} </div> {this.selectDom(5)} {/*聚合条件*/} <Row style={{ textAlign: 'left', paddingLeft: '80px', paddingTop: '8px', }}> {groups.map((r, i) => ( <Tag closable={true} key={i + r.field} onClose={this.deleteGroup.bind(this, i)}> {'按' + r.name + '聚合'} </Tag> ))} </Row> <Row style={{ paddingTop: '20px' }}> <Col span={24} style={{ textAlign: 'left' }}> <ButtonDiy handleClick={this.finish} name={'查询'} loading={loadingxxx} /> <ButtonDiy handleClick={this.export} name={'导出'} loading={loadingxxx} /> </Col> <Col span={24} style={{ overFlow: 'auto', minHeight: '500px', }}> <Table size="small" bordered dataSource={dataSource} rowKey={'col0'} columns={columnsTemp} scroll={{ x: 'max-content' }} pagination={false} /> </Col> </Row> </Modal> </span> ); } }