Commit 324e8658 authored by 刘松's avatar 刘松

export to xlsx

parent 4b3c4b84
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
import XLSX from 'xlsx'
import { saveAs } from 'file-saver'
function s2ab (s) {
const buf = new ArrayBuffer(s.length)
const view = new Uint8Array(buf)
for (let i = 0; i !== s.length; ++i) view[i] = s.charCodeAt(i) & 0xFF
return buf
}
export default function json2xlsx (json, {sheetName = 'sheet1', filename = 'statistics.xlsx'} = {}) {
const wb = {
SheetNames: [],
Sheets: {},
Props: {
Title: '小云蜂巢数据统计',
Author: '小云蜂巢'
}
}
const ws = XLSX.utils.json_to_sheet(json)
XLSX.utils.book_append_sheet(wb, ws, sheetName)
const wbout = XLSX.write(wb, {
bookType: 'xlsx',
bookSST: false,
type: 'binary'
})
saveAs(new Blob([s2ab(wbout)], { type: 'application/octet-stream' }), filename)
}
...@@ -3,7 +3,9 @@ const connect = require('react-redux').connect; ...@@ -3,7 +3,9 @@ const connect = require('react-redux').connect;
const actions = require('../../js/actions'); const actions = require('../../js/actions');
const moment = require('moment'); const moment = require('moment');
import { Table, Icon, DatePicker, Alert, Row, Col, Spin} from 'antd'; import json2xlsx from '../../js/json2xlsx';
import { Table, Icon, DatePicker, Alert, Row, Col, Spin, Button} from 'antd';
const { RangePicker } = DatePicker; const { RangePicker } = DatePicker;
class DashBoard extends React.Component{ class DashBoard extends React.Component{
...@@ -23,6 +25,57 @@ class DashBoard extends React.Component{ ...@@ -23,6 +25,57 @@ class DashBoard extends React.Component{
this.props.dispatch(actions.getMainData(data)); this.props.dispatch(actions.getMainData(data));
} }
exportData(){
let data = [];
let userResult = this.props.data.users;
let upstreamResult = this.props.data.upstreams;
let userCount = this.props.data.userCount;
let upCount = this.props.data.upCount;
let map = {};
for(let i = 0; i < userResult.length; i++){
let item = userResult[i]['_id'];
let _id = item ? item['year'] + (item['month'] <= 9 ? '0'+item['month'] : item['month']) + (item['day'] <= 9 ? '0'+item['day'] : item['day']) : 'unkown';
map[_id] = map[_id] || {};
map[_id]['user'] = userResult[i]['count']
}
for(let i = 0; i < upstreamResult.length; i++){
let item = upstreamResult[i]['_id'];
let _id = item ? item['year'] + (item['month'] <= 9 ? '0'+item['month'] : item['month']) + (item['day'] <= 9 ? '0'+item['day'] : item['day']) : 'unkown';
map[_id] = map[_id] || {};
map[_id]['upstream'] = upstreamResult[i]['count']
}
let range = this.props.data.range;
var start = range[0];
var end = range[1];
let ranges = [];
ranges.push(moment(start,'YYYYMMDD'));
ranges.push(moment(end,'YYYYMMDD'));
data = [];
let leng = Math.ceil( (moment(end).endOf('day').format('x') - moment(start).startOf('day').format('x')) / 86400000 );
let uptonowUser = userCount;
let uptonowUp = upCount;
for(let i = 0;i<leng;i++){
var temp = moment(start).add(i, 'day').startOf('day').format('YYYYMMDD');
let useradd = (map[temp] ? map[temp]['user']||0 : 0 );
uptonowUser += useradd;
let upstreamadd = (map[temp] ? map[temp]['upstream']||0 : 0 );
uptonowUp += upstreamadd;
data.push({
'日期':temp,
'用户新增':useradd,
'用户合计':uptonowUser,
'账号新增':upstreamadd,
'账号合计':uptonowUp
});
}
json2xlsx(data,{sheetName:"基础数据", filename : '基础数据'+moment().format('YYYYMMDD')+'.xlsx'});
}
render(){ render(){
const columns = [ const columns = [
{ {
...@@ -157,6 +210,9 @@ class DashBoard extends React.Component{ ...@@ -157,6 +210,9 @@ class DashBoard extends React.Component{
</Col> </Col>
</Row> </Row>
<RangePicker onChange={ this.onChange.bind(this) } value={ ranges } format={'YYYYMMDD'} style={{margin:'10px 0px'}}/> <RangePicker onChange={ this.onChange.bind(this) } value={ ranges } format={'YYYYMMDD'} style={{margin:'10px 0px'}}/>
<Button type="primary" icon="poweroff" onClick={ this.exportData.bind(this) } style={{ float:'right',margin:'10px 0px'}}>
导出数据
</Button>
<Spin spinning= { this.props.data.status == 'pending' }> <Spin spinning= { this.props.data.status == 'pending' }>
<Table columns={columns} dataSource = { data } size="middle" bordered/> <Table columns={columns} dataSource = { data } size="middle" bordered/>
</Spin> </Spin>
......
...@@ -3,8 +3,9 @@ const connect = require('react-redux').connect; ...@@ -3,8 +3,9 @@ const connect = require('react-redux').connect;
const actions = require('../../js/actions'); const actions = require('../../js/actions');
const types = require('../../js/actions/actionTypes'); const types = require('../../js/actions/actionTypes');
const moment = require('moment'); const moment = require('moment');
import json2xlsx from '../../js/json2xlsx';
import { Table, Spin} from 'antd'; import { Table, Spin, Button} from 'antd';
class Detail extends React.Component{ class Detail extends React.Component{
constructor(props){ constructor(props){
...@@ -13,7 +14,7 @@ class Detail extends React.Component{ ...@@ -13,7 +14,7 @@ class Detail extends React.Component{
} }
componentDidMount (){ componentDidMount (){
let limit = 30; let limit = 100;
let skip = 0; let skip = 0;
//await this.props.dispatch({status:'pending',type:types.DETAILDATA}); //await this.props.dispatch({status:'pending',type:types.DETAILDATA});
this.props.dispatch(actions.getDetailData({limit,skip})); this.props.dispatch(actions.getDetailData({limit,skip}));
...@@ -22,7 +23,52 @@ class Detail extends React.Component{ ...@@ -22,7 +23,52 @@ class Detail extends React.Component{
handleTableChange (pagination, filters, sorter) { handleTableChange (pagination, filters, sorter) {
const pager = this.props.data.detail.pagination; const pager = this.props.data.detail.pagination;
pager.current = pagination.current; pager.current = pagination.current;
this.props.dispatch(actions.getDetailData({limit: 30,skip: parseInt(pager.current)-1 })); this.props.dispatch(actions.getDetailData({limit: 100,skip: parseInt(pager.current)-1 }));
}
exportData(){
let pluginMap = {
'publish-baijia':'百家助手',
'publish-netease':'网易助手'
}
let users = this.props.data.detail ? this.props.data.detail.users : [];
let upstreams = this.props.data.detail ? this.props.data.detail.upstreams : [];
let auths = this.props.data.detail ? this.props.data.detail.auths : [];
let unbindhistorys = this.props.data.detail ? this.props.data.detail.unbindhistorys : 0;
let upMap = {};
let authMap = {};
let unbindhistorysMap = {};
let data = [];
for(let i = 0;i < upstreams.length; i++){
let id = upstreams[i]['_id']['creater'];
upMap[id] = upstreams[i]['count'];
}
for(let i = 0;i < auths.length; i++){
let id = auths[i]['userId'];
if(authMap[id]) authMap[id].push(auths[i]);
else authMap[id] = [auths[i]];
}
for(let i = 0;i < unbindhistorys.length; i++){
let id = unbindhistorys[i]['_id']['userId'];
unbindhistorysMap[id] = unbindhistorys[i]['count'];
}
for(let i = 0;i < users.length; i++){
let item = users[i];
let charges = ['-'];
if(authMap[item['_id']]) charges = authMap[ item['_id'] ].map( x => pluginMap[x.plugin] + ':' + x.times );
data.push({
'用户名' : item['username'] || '-',
'手机号' : item['phone'] || '-',
'账户数量' : upMap[ item['_id'] ] || 0,
'解绑记录':unbindhistorysMap[item['_id']] || 0,
'充值记录':charges.join(','),
'注册时间' : moment(item['createdAt']).format('YYYY/MM/DD HH:mm:ss')
})
}
json2xlsx(data,{sheetName:"详细数据", filename :'详细数据'+moment().format('YYYYMMDD')+'.xlsx'});
} }
render(){ render(){
...@@ -114,6 +160,9 @@ class Detail extends React.Component{ ...@@ -114,6 +160,9 @@ class Detail extends React.Component{
} }
return ( return (
<Spin spinning= { this.props.data.status == 'pending' }> <Spin spinning= { this.props.data.status == 'pending' }>
<Button type="primary" icon="poweroff" onClick={ this.exportData.bind(this) } style={{margin:'10px 0px'}}>
导出数据
</Button>
<Table columns={columns} dataSource = { data } pagination={ this.props.data.detail.pagination } size="middle" onChange = { this.handleTableChange.bind(this) } bordered/> <Table columns={columns} dataSource = { data } pagination={ this.props.data.detail.pagination } size="middle" onChange = { this.handleTableChange.bind(this) } bordered/>
</Spin> </Spin>
) )
......
'use strict'; 'use strict';
module.exports = require('./config.default.js');
try { \ No newline at end of file
module.exports = require('./config_current.js');
} catch (err) {
module.exports = require('./config.default.js');
}
\ No newline at end of file
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
"es6-promise": "^4.0.5", "es6-promise": "^4.0.5",
"eslint-plugin-react": "^7.1.0", "eslint-plugin-react": "^7.1.0",
"express": "^4.14.1", "express": "^4.14.1",
"file-saver": "^1.3.3",
"jquery": "^3.2.1", "jquery": "^3.2.1",
"js-cookie": "^2.1.4", "js-cookie": "^2.1.4",
"lodash": "^4.17.4", "lodash": "^4.17.4",
...@@ -36,7 +37,8 @@ ...@@ -36,7 +37,8 @@
"redux-sequence-action": "^0.2.1", "redux-sequence-action": "^0.2.1",
"redux-thunk": "^2.2.0", "redux-thunk": "^2.2.0",
"request": "^2.81.0", "request": "^2.81.0",
"request-promise": "^4.2.1" "request-promise": "^4.2.1",
"xlsx": "^0.11.3"
}, },
"devDependencies": { "devDependencies": {
"babel-core": "^6.4.5", "babel-core": "^6.4.5",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment