import React from 'react'; import ReactDOM from 'react-dom'; import { Select, Button, Modal, Input, Table, Row, Col, Tag, Form, message ,notification } from 'antd'; import { connect } from 'dva'; import { getToken } from '../utils/token' import config from '../config/config'; import QueryItem from './QueryItem'; import OrderItem from './OrderItem'; import styles from './Ability.css'; import FormdataWrapper from '../utils/object-to-formdata-custom'; import ButtonDiy from './ButtonDiy/ButtonDiy'; const Option = Select.Option; const nameSpan = { small: 9, big: 7, }; const nameSpan2 = { small: 0, big: 0, }; const nameSpan3 = { small: 3, big: 2, }; var keyX = 1; function swapArray(arr, index1, index2) { arr[index1] = arr.splice(index2, 1, arr[index1])[0]; return arr; } 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, groupVisiable: 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); this.setState({ querys }); }; deleteOrder = (i) => { const orders = this.state.orders; orders.splice(i); this.setState({ orders }); }; deleteGroup = (i) => { const groups = this.state.groups; groups.splice(i); this.setState( { 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 }); }; addOrder = () => { this.setState({ orderVisiable: true }); }; 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(); }); }; addGroup = () => { this.setState({ groupVisiable: true }); }; 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.error('请选择第一统计项'); return; } if (y == null) { message.error('请选择行数据'); 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.error('请至少选择一个聚合条件'); 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.error('请选择第一统计项'); return; } if (y == null) { message.error('请选择行数据'); 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.error('请至少选择一个聚合条件'); 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 { visiable, queryVisiable, querys, groups, currentKey, XxX, infos, mockData, mockXZData, columns, dataSource, qs, os, gs, x, y, z, currentQueryKey, currentGroupKey, groupVisiable, } = 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, currentKey, XxX,exportLoading, infos, mockData, columns, dataSource, qs, os, gs, x, y, z, currentQueryKey, currentGroupKey, groupVisiable, } = 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; } } 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' }]; } } return ( <span> {/* 暂时屏蔽 */} <ButtonDiy name='自定义统计' type='default' className='defaultBlue' handleClick={this.open} /> <div id='downloadDiv' style={{ display: 'none' }}> </div> <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} onChange={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}/> {/* <Button type="primary" onClick={this.finish}> 查询 </Button> <Button type="primary" onClick={this.finish}> 导出 </Button> 结果:*/} </Col> <Col span={24}> <Table size="small" bordered dataSource={dataSource} rowKey={'col0'} columns={columnsTemp} pagination={false} /> {/*{columns.length > 0 ?*/} {/*<Table size="small"*/} {/*bordered*/} {/*dataSource={dataSource}*/} {/*columns={columnsTemp}*/} {/*pagination={false} /> : ''}*/} </Col> </Row> </Modal> </span> ); } }