/**
* @file modules/dashboard/Index
* @author sun
*/
import _ from 'lodash';
import moment from 'moment';
import echarts from 'echarts';
import 'echarts/lib/component/legendScroll';
import {Row, Col, Card, DatePicker, Table, message, Divider} from 'antd';
import {components, utils} from 'baidu-acu-react-common';
import {OverviewItem} from 'constants/constants';
import './Index.less';
const RangePicker = DatePicker.RangePicker;
const {toDate} = utils.timeUtil;
const legendData = OverviewItem.toArray().map(d => d.text);
const legendUnit = OverviewItem.toArray().map(d => d.unit);
const legend = OverviewItem.toArray().map(d => d.legend);
const legendStr = OverviewItem.toArray().map(d => d.value);
const legendvalue = OverviewItem.toArray().map(d => d.legendvalue);
const initSelected = {'请求量': false, '展现量': false, '点击量': false, '展现率': false,
'点击率': false, '收入': false, 'CPM': true, 'CPC': true};
/* globals React */
export default class HomePage extends React.Component {
state = {
rangePickerValue: [],
statis: {
imp: {today: 0, yesterday: 0, lastSevenDays: 0},
cost: {},
plan: {},
app: {},
slot: {},
strategy: {},
cpm: {}
},
impData: {
request: []
},
topData: {
app: [],
plan: [],
adx: []
},
selected: initSelected,
legValue: ['CPM', 'CPC'],
yAxisValue: [{}, {}, {}]
}
componentDidMount() {
// this.loadSystem();
this.loadStat();
this.loadYaxis();
this.selectDate(0, 6);
}
loadStat = () => {
const {actions} = this.props;
actions.getHomeStat({}).then(res => {
this.setState({statis: res});
});
}
loadYaxis() {
const {legValue} = this.state;
let yAxisValue = [{
name: legendUnit[legendData.indexOf(legValue[0])],
position: 'left',
splitLine: {show: false},
nameTextStyle: {
color: ['#118DEE']
},
axisLine: {
lineStyle: {
color: '#118DEE'
}
},
type: 'value'
},
{name: legendUnit[legendData.indexOf(legValue[1])],
splitLine: {show: false},
nameTextStyle: {
color: ['#5FB333']
},
axisLine: {
lineStyle: {
color: '#5FB333'
}
},
position: 'right',
type: 'value'
}, {}];
this.setState({yAxisValue});
}
loadchartDaily() {
const _this = this;
const actions = this.props.actions;
const {rangePickerValue} = this.state;
const topParam = {
startTime: toDate(rangePickerValue[0]),
endTime: toDate(rangePickerValue[1])
};
actions.getHomeImp(topParam).then(chartDaily => {
let chartDom = document.getElementById('chart-main');
let myChart = echarts.init(chartDom);
let title = '';
window.onresize = function () {
myChart.resize();
};
myChart.on('legendselectchanged', function (params) {
title = '';
let {selected, name} = params;
// 改变title
// this.props.chart
let {legValue} = _this.state;
if (legValue.indexOf(name) === -1) {
legValue.push(name);
}
if (legValue.length > 2) {
selected[legValue[0]] = false;
legValue = [legValue[1], legValue[2]];
}
if (legValue.length === 2) {
selected[legValue[0]] = true;
selected[legValue[1]] = true;
}
legValue.map(d => {
// 将选中的加入到title中去
let i = legendData.indexOf(d);
let value = (chartDaily[legendvalue[i]]) || 0;
let unit = legendUnit[i];
title += legend[i] + ':' + (unit === '元' ? '¥' : '') + (unit === '次' ? value : value.toFixed(2))
+ unit + ',';
});
_this.setState({title, selected, legValue}, () => {
_this.loadYaxis();
});
});
});
}
loadTop() {
const actions = this.props.actions;
const {rangePickerValue} = this.state;
const topParam = {
startTime: toDate(rangePickerValue[0]),
endTime: toDate(rangePickerValue[1])
};
actions.getHomeTop(topParam).then(res => {
res.app = this.addIndex(res.app);
res.plan = this.addIndex(res.plan);
res.adx = this.addIndex(res.adx);
this.setState({topData: res});
});
}
getTimeDistance(bd = 0, ed = 0) {
const begin = moment().subtract(bd, 'day').toDate();
const end = moment().subtract(ed, 'day').endOf('day').toDate();
begin.setHours(0, 0, 0, 0);
end.setHours(24, 0, 0, 0);
return [moment(end), moment(begin)];
}
selectDate = (bd, ed) => {
this.setState({
rangePickerValue: this.getTimeDistance(bd, ed)
}, () => {
this.loadchartDaily();
this.loadTop();
});
};
handleRangePickerChange = rangePickerValue => {
if (!rangePickerValue[1]) {
rangePickerValue[1] = rangePickerValue[0];
}
this.setState({
rangePickerValue
}, () => {
// 时间变化时,重新加载图表
this.loadchartDaily();
this.loadTop();
});
}
formatNumber(param) {
return parseFloat(param).toFixed(2);
}
initChartData(chartDaily) {
const _this = this;
if (chartDaily.request) {
let result = {
date: chartDaily.request.map(d => d.date)
};
_.each(legendStr, function (val) {
result[val] = [];
const value = chartDaily[val];
const len = value.length;
for (let i = 0; i < len; i++) {
result[val][i] = Number(_this.formatNumber(value[i].value));
}
});
return result;
}
}
initTopTable(name) {
const columns = [
{
title: '排名',
dataIndex: 'index',
key: 'index',
render(item) {
if (item === 1) {
return ();
}
if (item === 2) {
return ();
}
if (item === 3) {
return ();
}
return 'NO.' + item;
}
},
{
title: name,
dataIndex: 'name',
key: 'name'
},
{
title: '收入',
dataIndex: 'cost',
key: 'cost',
render(item) {
return Math.floor(item * 100) / 100;
}
},
{
title: '占比',
dataIndex: 'percent',
key: 'percent',
render(item) {
return item.toFixed(2) + '%';
}
}
];
return columns;
}
addIndex(data) {
if (data) {
data.map(function (item, index) {
item.index = index + 1;
});
return data;
}
}
formatParam(param, init) {
if (param) {
return param.toFixed(2);
}
return init;
}
disabledDate = current => current && current > moment().endOf('day');
render() {
const {topData, statis, selected, legValue, yAxisValue} = this.state;
const chartDaily = this.props.chart || {};
let {title} = this.state;
const initDara = this.initChartData(chartDaily);
const {date} = initDara || {};
const {app, plan, adx} = topData;
// const date = request.map(d => d.date);
let seriesData = [];
let color = [];
legendData.map(d => {
let datas = initDara ? initDara[legendStr[legendData.indexOf(d)]] : [];
let index = legValue.indexOf(d);
seriesData.push({
name: d,
type: 'line',
yAxisIndex: index === -1 ? 2 : index,
data: legValue.indexOf(d) > -1 ? datas : [],
lineStyle: {
normal: {
color: d === legValue[0] ? '#118DEE' : '#5FB333'
}
},
smooth: true
});
color.push(d === legValue[0] ? '#118DEE' : '#5FB333');
});
// 基于准备好的dom,初始化ECharts实例
let chartDom = document.getElementById('chart-main');
let cpmValue = chartDaily.cpmSum || 0;
let cpcValue = chartDaily.cpcSum || 0;
let titleInit = '平均CPM:¥' + cpmValue.toFixed(2) + '元,平均CPC:¥' + cpcValue.toFixed(2) + '元';
if (title === undefined) {
title = titleInit;
}
let title1 = title.split(',')[0].split(':');
let title2 = title.split(',')[1].split(':');
let titleHtml = (
{title1[0]}:
{title1[1]}
{title2[0]}:
{title2[1]}
);
// 更换组件为echarts
// 根据选中选中的图例, 更换Y轴
if (chartDom) {
const myChart = echarts.init(chartDom);
let options = {
grid: [
{
left: '10%',
right: '8%',
bottom: 100
}
],
dataZoom: [{
type: 'slider',
bottom: 40
}],
color,
xAxis: [{
// x轴数据
data: date,
type: 'category',
// x轴两边留白策略 默认为true,不留白
boundaryGap: false
}],
yAxis: yAxisValue,
tooltip: {
trigger: 'axis',
axisPointer: {
lineStyle: {
color: '#108cee'
}
},
position(pt) {
return [pt[0], '10%'];
},
backgroundColor: '#fff',
textStyle: {
color: '#333'
},
enterable: false,
extraCssText: 'border-radius:0;'
+ 'padding:0;'
+ 'background-color:rgba(255,255,255,.95);'
+ 'box-shadow:3px 3px 9px 3px rgba(16,140,238,.3);',
formatter(params, ticket, callback) {
let axisLabel = '';
const domArray = _.map(params, item => {
const {axisValue, data, seriesName, seriesIndex} = item;
const value = /\./g.test(data) ? data.toFixed(2) : data;
const unit = legendUnit[legendData.indexOf(seriesName)];
axisLabel = new Date(axisValue).toLocaleDateString();
return `
${seriesName}:
${value}${unit}
`;
});
let domdata = '';
for (let dom of domArray) {
domdata += ' ' + dom + ' ';
}
return `
- ${axisLabel} 详情
-
${domdata}
`;
/* eslint-enable */
}
},
legend: {
type: 'scroll',
bottom: 10,
data: legendData,
selected: selected
},
series: seriesData
};
myChart.clear();
myChart.setOption(options);
}
// top数据 SITE,IDEA,PROV
const appColums = this.initTopTable('站点/APP');
const planColums = this.initTopTable('广告订单');
const adxColums = this.initTopTable('广告平台');
return (
{statis.imp.today || 0}
今日展现量
昨日: {statis.imp.yesterday || 0}
7日平均: {statis.imp.lastSevenDays || 0}
¥{this.formatParam(statis.cost.today, '0.00')}
今日收入
昨日: ¥{this.formatParam(statis.cost.yesterday, '0.00')}
7日平均: ¥{this.formatParam(statis.cost.lastSevenDays, '0.00')}
¥ {this.formatParam(statis.cpm.today, '0.00')}
今日CPM
昨日: ¥{this.formatParam(statis.cpm.yesterday, '0.00')}
7日平均: ¥{this.formatParam(statis.cpm.lastSevenDays, '0.00')}
{statis.slot.enabled}/{statis.slot.total}
启用的广告位数量/总量
{statis.plan.enabled}/{statis.plan.total}
进行中的订单数量/总量
{statis.app.enabled}/{statis.app.total}
启用的流量源数量/总量
{statis.strategy.enabled}/{statis.strategy.total}
进行中的投放数量/总量
{titleHtml}
流量源收入排行
;
广告订单收入排行
;
广告平台收入排行
);
}
}
css
/**
* @file cluster列表样式配置
* @author Chen Bo ([email protected])
*/
.nomargin {
margin-left: 0 !important;
margin-right:0 !important;
}
.message-center {
text-align: center
}
svg {
color: #2f9df6;
fill: currentColor;
}
.orange {
color: #EA2E2E;
}
.green {
color: #5EB432;
}
.bill-info {
cursor:pointer;
}
dt {
background-color: #1694f3;
padding: 5px 10px;
color: #fff;
font-size: 12px;
margin-bottom: 0;
}
dd {
padding: 5px 10px;
color: #666;
max-height: 200px;
overflow: auto;
div {
margin: 0 -10px;
padding: 0 10px;
min-width: 100px;
overflow: hidden;
font-size: 12px;
}
strong {
color: #108cee;
}
}
.sum {
margin-left: 20%
}
.statistic-item-none-wrap {
display: inline-block;
margin: 10px;
width: 17%;
font-size: 18px;
line-height: 18px;
padding-left: 2%;
div {
margin: 10px 0;
}
.description {
font-size: 9px;
}
}
.statistic-item {
display: inline-block;
margin: 10px;
font-size: 18px;
width: 17%;
line-height: 18px;
border-left: 1px solid #E5E5E5;
padding-left: 2%;
div {
margin: 10px 0;
}
.description {
font-size: 9px;
}
}
.bill-info {
cursor:pointer; // 鼠标悬浮时显示为手指
font-size: 22px;
}
.started-plan, .all-plan, .started-unit, .all-unit, .started-idea, .all-idea, .passed-audit, .all-audit:hover {
cursor:pointer;
}
.rank-first {
background: url('/static/img/top1.svg');
}
.rank-second {
background-image: url('/static/img/top2.svg');
width: 10px;
height: 10px;
}
.rank-third {
background: url('/static/img/top3.svg');
}
.chart-date {
font-size: 12px;
color: #108CEE;
line-height: 20px;
padding: 20px 30px;
}
#chart-main {
text-align: center
}
.x-date-chart-legend {
background: #FFFFFF;
border: 1px solid #E5E5E5;
.chart-date {
font-size: 12px;
color: #108CEE;
line-height: 20px;
padding: 20px 30px;
border-bottom: 1px solid #E5E5E5;
}
.chart-legend {
padding: 20px 30px;
font-size: 18px;
}
.charts {
padding: 0 30px 20px 30px;
border-bottom: 1px solid #E5E5E5;
.chart-content {
position: relative;
.chart-no-date {
font-size: 18px;
position: absolute;
top: 30%;
left: 45%
}
}
}
}
.top-item-title {
border-left: 4px solid #108CEE;
padding-left: 14px;
margin: 0 0 20px 0;
font-size: 16px;
color: #333333;
line-height: 16px;
}
页面效果