Commit f10eb982 by 姜雷

模块化数据首页

parent f975903e
<template>
<div class="Dashboard-DataCard">
<div class="Dashboard-SearchBar">
<search-item label="运营商">
<operator-select
v-model.trim="operatorFilters.operatorId"
@input="changeConsumeOperatorHandle"
/>
</search-item>
<el-radio-group class="Dashboard-Radio">
<el-radio class="Dashboard-Radio-item">本日</el-radio>
<el-radio class="Dashboard-Radio-item">本月</el-radio>
<el-radio class="Dashboard-Radio-item">本年</el-radio>
</el-radio-group>
</div>
<CampusRankChart
:data="campusRankList"
:changeCampusHandle="changeCampusHandle"
/>
</div>
</template>
<script>
import CampusRankChart from './CampusRankChart';
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'CampusRank',
components: { CampusRankChart },
data() {
return {
operatorFilters: {
operatorId: undefined,
},
};
},
computed: {
...mapGetters('Dashboard', ['campusRankList']),
},
methods: {
...mapActions('Dashboard', ['fetchConsumeList']),
changeCampusHandle(data) {
let operateId = this.operatorFilters.operateId;
let year = this.operatorFilters.year;
let month = this.operatorFilters.month;
this.fetchConsumeList({
year: year ? year : null,
month: month ? month : null,
operateId: operateId ? operateId : null,
areaId: data.areaId,
updatePercentList: true,
});
},
changeConsumeOperatorHandle(val) {
if (val && this.operatorFilters.year) {
let month = this.operatorFilters.month;
this.fetchConsumeList({
year: this.operatorFilters.year,
month: month ? month : null,
operateId: val,
});
}
},
},
};
</script>
<template>
<div class="CampusRank">
<div id="CampusRank"></div>
<div class="CampusRank-title">截至到{{ today }},前十校区消费汇总数据</div>
</div>
</template>
......@@ -167,6 +166,7 @@ export default {
.CampusRank-title {
font-size: 16px;
text-align: center;
padding-bottom: 12px;
}
}
</style>
<template>
<div class="Dashboard-DataCard">
<div class="Dashboard-SearchBar">
<search-item label="运营商">
<operator-select v-model.trim="customerFilter.operatorId" />
</search-item>
<search-item label="区域">
<area-select
v-model.trim="customerFilter.areaId"
type="user"
/>
</search-item>
<el-radio-group class="Dashboard-Radio">
<el-radio class="Dashboard-Radio-item">本日</el-radio>
<el-radio class="Dashboard-Radio-item">本月</el-radio>
<el-radio class="Dashboard-Radio-item">本年</el-radio>
</el-radio-group>
</div>
<div class="Dashboard-title">会员消费数据</div>
</div>
</template>
<script>
export default {
name: 'CustomerConsumption',
data() {
return {
customerFilter: {},
};
},
};
</script>
<template>
<div id='ActiveUserByMonth'></div>
</template>
<script>
import G2 from '@antv/g2';
import chartMixin from '../chartMixin';
export default {
name: '',
};
</script>
<template>
<div
class="CustomerFeedback"
@mousewheel.stop=""
>
<div class="Dashboard-SearchBar">
<div class="CustomerFeedbackTitle">
<span class="CustomerFeedback-icon"><img src="@/assets/images/dashboard/feedback.jpg"></span>
<span class="CustomerFeedback-text">反馈未处理-</span>
<span class="red">49条</span>
</div>
</div>
<div class="CustomerFeedback-List">
<div
class="CustomerFeedback-Item"
v-for="(item, index) in 10"
:key="index"
>
<span class="CustomerFeedback-ItemNum">12条</span>
<span class="CustomerFeedback-ItemName">成都师范学院</span>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'CustomerFeedback',
};
</script>
<style lang="scss">
@import '@/assets/styles/variables.scss';
.CustomerFeedback {
display: flex;
flex-direction: column;
.CustomerFeedbackTitle {
width: 100%;
display: flex;
align-items: center;
padding: 0 20px;
line-height: 34px;
font-size: 18px;
.CustomerFeedback-icon {
width: 27px;
height: 27px;
}
.CustomerFeedback-text {
margin-left: 10px;
margin-right: 5px;
}
.red {
color: #ff0000;
}
}
.CustomerFeedback-List {
flex: 1;
overflow-y: auto;
}
.CustomerFeedback-Item {
display: flex;
align-items: center;
height: 60px;
font-size: 18px;
.CustomerFeedback-ItemNum {
width: 70px;
margin-right: 22px;
text-align: right;
color: #ff0000;
}
.CustomerFeedback-ItemName {
flex: 1;
padding-right: 20px;
line-height: 28px;
}
}
}
@media screen and (max-width: $bigScreenWidth) {
.CustomerFeedback {
.CustomerFeedback-Item {
height: 40px;
font-size: 14px;
.CustomerFeedback-ItemNum {
width: 70px;
margin-right: 22px;
}
.CustomerFeedback-ItemName {
padding-right: 20px;
line-height: 28px;
}
}
}
}
</style>
<template>
<div id='ActiveUserByMonth'></div>
</template>
<script>
import G2 from '@antv/g2';
import chartMixin from '../chartMixin';
export default {
name: '',
};
</script>
<template>
<div class="Dashboard-DataCard">
<div class="Dashboard-SearchBar">
<search-item label="运营商">
<operator-select v-model.trim="customerFilter.operatorId" />
</search-item>
<el-radio-group class="Dashboard-Radio">
<el-radio class="Dashboard-Radio-item">本日</el-radio>
<el-radio class="Dashboard-Radio-item">本月</el-radio>
<el-radio class="Dashboard-Radio-item">本年</el-radio>
</el-radio-group>
</div>
<div class="Dashboard-title">会员充值数据</div>
<Chart />
</div>
</template>
<script>
import Chart from './chart';
export default {
name: 'CustomerRechange',
components: {
Chart,
},
data() {
return {
customerFilter: {},
};
},
};
</script>
<template>
<div id='CustomerRechangeChart'></div>
</template>
<script>
import G2 from '@antv/g2';
import chartMixin from '../chartMixin';
export default {
name: 'CustomerRechangeChart',
mixins: [chartMixin],
data() {
let totle = this.data.reduce((count, item) => count + item.count, 0);
return {
totle: totle,
percentDom: null,
serviceNameDom: null,
SelectedDataIndex: null,
};
},
mounted() {
this.initChart();
},
methods: {
initChart() {
this.totle = this.data.reduce((count, item) => count + item.count, 0);
this.chart = new G2.Chart({
container: 'CustomerRechangeChart',
forceFit: true,
height: this.height,
padding: [0, 130, 0, 0],
});
this.chart.source(this.data);
this.chart.coord('theta', {
radius: 0.75,
innerRadius: 0.6,
});
this.chart.tooltip(false);
// 图例
this.chart.legend({
position: 'right-center',
marker: 'square',
useHtml: true,
containerTpl: `
<div class="g2-legend">
<ul class="g2-legend-list" style="list-style-type:none;margin:0;padding:0;"></ul>
</div>`,
itemTpl: (value, color, checked, index) => {
const obj = this.data[index];
checked = checked ? 'checked' : 'unChecked';
return `
<li
class="g2-legend-list-item item-${index} ${checked}"
data-value="${value}"
data-color=${color}
style="cursor: pointer;font-size:14px;"
>
<i
class="g2-legend-marker"
style="display:inline-block;margin-right:10px;background-color:${color};"
></i>
<span class="g2-legend-text">${value}: </span>
<span>${obj.count}</span>
</li>
`;
},
'g2-legend': {
width: '130px',
// left: '-20px',
},
'g2-legend-list-item': {
height: '22px',
color: '#333',
},
'g2-legend-marker': {
width: '10px',
height: '5px',
borderRadius: 'none',
},
});
// 坐标系及着色
this.chartGeom = this.chart
.intervalStack()
.position('count')
.color('serviceName', ['#4e82fb', '#fb774e', '#ffc934', '#41bf52']);
// 辅助元素
this.chart.guide().html({
position: ['50%', '50%'],
html: `<div style="color:#333;font-size:20px;text-align: center;">
<span class="SeviceRatio-percent">0.00</span>%<br>
<span class="SeviceRatio-serviceName" style="font-size:16px;"></span>
</div>`,
alignX: 'middle',
alignY: 'middle',
});
this.chart.render();
// this.chart.on('interval:click', this.clickHandle);
},
},
};
</script>
<template>
<div class="Dashboard-Row Dashboard-DataCard">
<div class="Dashboard-SearchBar">
<search-item label="年份">
<el-date-picker
v-model.trim="campusFilters.year"
@change="changeReportYearHandle"
type="year"
value-format="yyyy"
placeholder="请选择"
>
</el-date-picker>
</search-item>
<search-item label="校区">
<area-select
v-model.trim="campusFilters.areaId"
@change="changeReportAreaHandle"
type="user"
/>
</search-item>
</div>
<div class="Dashboard-CampusData">
<div class="Dashboard-CampusItem">
<div class="Dashboard-title">{{ reportYear }}年每月注册数据</div>
<RegisterByMonth :data="registePerMonth"></RegisterByMonth>
</div>
<div class="Dashboard-CampusItem">
<div class="Dashboard-title">
{{ reportYear }}{{ reportMonth }}月注册数据
</div>
<RegisterByDay :data="registePerDay" />
</div>
<div class="Dashboard-CampusItem">
<div class="Dashboard-title">{{ reportYear }}年每月活跃数据</div>
<ActiveUserByMonth :data="activeUser" />
</div>
</div>
</div>
</template>
<script>
import { mapGetters, mapActions } from 'vuex';
import RegisterByMonth from './components/RegisterByMonth';
import RegisterByDay from './components/RegisterByDay';
import ActiveUserByMonth from './components/ActiveUserByMonth';
export default {
name: 'CustomerRegister',
components: {
RegisterByMonth,
RegisterByDay,
ActiveUserByMonth,
},
data() {
return {
campusFilters: {},
};
},
computed: {
...mapGetters('Dashboard', [
'reportYear',
'reportMonth',
'registePerDay',
'registePerMonth',
'activeUser',
]),
},
methods: {
...mapActions('Dashboard', ['fetchReportList']),
changeReportYearHandle(val) {
if (val) {
let areaId = this.campusFilters.areaId;
this.fetchReportList({
year: val,
areaId: areaId ? areaId : null,
});
}
},
changeReportAreaHandle(val) {
if (val && this.campusFilters.year) {
this.fetchReportList({
year: this.campusFilters.year,
areaId: val,
});
}
},
},
};
</script>
......@@ -4,7 +4,7 @@
<script>
import G2 from '@antv/g2';
import chartMixin from '../chartMixin';
import chartMixin from '../../chartMixin';
export default {
name: 'ActiveUserByMonth',
......
......@@ -4,7 +4,7 @@
<script>
import G2 from '@antv/g2';
import chartMixin from '../chartMixin';
import chartMixin from '../../chartMixin';
export default {
name: 'RegisterByDay',
......
......@@ -3,7 +3,7 @@
</template>
<script>
import G2 from '@antv/g2';
import chartMixin from '../chartMixin';
import chartMixin from '../../chartMixin';
export default {
name: 'RegisterByMonth',
......
<template>
<div>
<div class="Dashboard">
<div class="Dashboard-DataCard">
<div class="Dashboard-SearchBar">
<search-item label="年份">
<el-date-picker
v-model.trim="campusFilters.year"
@change="changeReportYearHandle"
type="year"
value-format="yyyy"
placeholder="请选择"
>
</el-date-picker>
</search-item>
<search-item label="校区">
<area-select
v-model.trim="campusFilters.areaId"
@change="changeReportAreaHandle"
type="user"
/>
</search-item>
<div class="Dashboard-Row Dashboard-CustomerData">
<CustomerRechange class="Dashboard-DataCard" />
<CustomerConsumption class="Dashboard-DataCard" />
<CustomerFeedback class="Dashboard-DataCard" />
</div>
<div class="Dashboard-CampusData">
<div class="Dashboard-CampusItem">
<div class="Dashboard-title">{{ reportYear }}年每月注册数据</div>
<RegisterByMonth :data="registePerMonth"></RegisterByMonth>
</div>
<div class="Dashboard-CampusItem">
<div class="Dashboard-title">
{{ reportYear }}{{ reportMonth }}月注册数据
</div>
<RegisterByDay :data="registePerDay" />
</div>
<div class="Dashboard-CampusItem">
<div class="Dashboard-title">{{ reportYear }}年每月活跃数据</div>
<ActiveUserByMonth :data="activeUser" />
</div>
</div>
</div>
<div class="Dashboard-OperatorData">
<div class="Dashboard-DataCard">
<div class="Dashboard-SearchBar">
<search-item label="年份">
<el-date-picker
v-model.trim="operatorFilters.year"
@change="changeConsumeYearHandle"
type="year"
value-format="yyyy"
placeholder="请选择"
></el-date-picker>
</search-item>
<search-item label="月份">
<el-date-picker
v-model.trim="operatorFilters.month"
@change="changeConsumeMouthHandle"
type="month"
value-format="MM"
format="MM"
:picker-options="monthRange"
placeholder="请选择"
></el-date-picker>
</search-item>
<search-item label="运营商">
<operator-select
v-model.trim="operatorFilters.operatorId"
@input="changeConsumeOperatorHandle"
/>
</search-item>
</div>
<CampusRank
:data="campusRankList"
:changeCampusHandle="changeCampusHandle"
/>
</div>
<div class="Dashboard-DataCard">
<div class="Dashboard-title">
<div class="Dashboard-title-icon service">
<img src="@/assets/images/dashboard/icon_zhanbi@2x.png" />
</div>
<div class="Dashboard-title-text">各服务消费占比</div>
<div class="Dashboard-title-top">TOP1</div>
</div>
<SeviceRatio
:data="seviceRatioList"
:changeServiceHandle="changeServiceHandle"
/>
</div>
<div class="Dashboard-DataCard">
<div class="Dashboard-title">
<div class="Dashboard-title-icon equipment">
<img src="@/assets/images/dashboard/icon_paiming@2x.png" />
</div>
<div class="Dashboard-title-text">各设备消费排名</div>
<div class="Dashboard-title-top">TOP1-5</div>
</div>
<EquipmentList :data="consumeHardVos" />
<div class="Dashboard-Row Dashboard-OperatorData">
<CampusRank class="Dashboard-DataCard" />
<SeviceRatio class="Dashboard-DataCard" />
<EquipmentList class="Dashboard-DataCard" />
</div>
<CustomerRegister class="Dashboard-Row Dashboard-DataCard" />
</div>
</div>
</template>
<script>
import { mapActions, mapGetters } from 'vuex';
import RegisterByMonth from './components/RegisterByMonth';
import RegisterByDay from './components/RegisterByDay';
import SeviceRatio from './components/SeviceRatio';
import CampusRank from './components/CampusRank';
import ActiveUserByMonth from './components/ActiveUserByMonth';
import EquipmentList from './components/EquipmentList';
import CustomerRegister from './CustomerRegister/CustomerRegister';
import SeviceRatio from './SeviceRatio/SeviceRatio';
import CampusRank from './CampusRank/CampusRank';
import EquipmentList from './EquipmentList/EquipmentList';
import CustomerRechange from './CustomerRechange/CustomerRechange';
import CustomerConsumption from './CustomerConsumption/CustomerConsumption';
import CustomerFeedback from './CustomerFeedback/CustomerFeedback';
export default {
name: 'Dashboard',
components: {
RegisterByMonth,
RegisterByDay,
ActiveUserByMonth,
CustomerRegister,
CustomerRechange,
CustomerConsumption,
CustomerFeedback,
SeviceRatio,
CampusRank,
EquipmentList,
},
data() {
return {
campusFilters: {
year: undefined,
areaId: undefined,
},
operatorFilters: {
year: undefined,
month: undefined,
operateId: undefined,
},
monthRange: {
disabledDate: time => {
return this.operatorFilters.year
? time.getTime() < new Date(this.operatorFilters.year) ||
time.getTime() > new Date(this.operatorFilters.year + '-12-31')
: true;
},
},
};
},
computed: {
...mapGetters('Dashboard', [
'reportYear',
'reportMonth',
'registePerDay',
'registePerMonth',
'activeUser',
'campusRankList',
'seviceRatioList',
'consumeHardVos',
]),
},
created() {
this.initData();
},
......@@ -165,78 +51,6 @@ export default {
this.fetchConsumeList();
this.fetchTitleList();
},
changeReportYearHandle(val) {
if (val) {
let areaId = this.campusFilters.areaId;
this.fetchReportList({
year: val,
areaId: areaId ? areaId : null,
});
}
},
changeReportAreaHandle(val) {
if (val && this.campusFilters.year) {
this.fetchReportList({
year: this.campusFilters.year,
areaId: val,
});
}
},
changeConsumeYearHandle(val) {
if (val) {
let month = this.operatorFilters.month;
let operateId = this.operatorFilters.operateId;
this.fetchConsumeList({
year: val,
month: month ? month : null,
operateId: operateId ? operateId : null,
});
}
},
changeConsumeMouthHandle(val) {
if (val && this.operatorFilters.year) {
let operateId = this.operatorFilters.operateId;
this.fetchConsumeList({
year: this.operatorFilters.year,
month: val,
operateId: operateId ? operateId : null,
});
}
},
changeConsumeOperatorHandle(val) {
if (val && this.operatorFilters.year) {
let month = this.operatorFilters.month;
this.fetchConsumeList({
year: this.operatorFilters.year,
month: month ? month : null,
operateId: val,
});
}
},
changeCampusHandle(data) {
let operateId = this.operatorFilters.operateId;
let year = this.operatorFilters.year;
let month = this.operatorFilters.month;
this.fetchConsumeList({
year: year ? year : null,
month: month ? month : null,
operateId: operateId ? operateId : null,
areaId: data.areaId,
updatePercentList: true,
});
},
changeServiceHandle(data) {
let operateId = this.operatorFilters.operateId;
let year = this.operatorFilters.year;
let month = this.operatorFilters.month;
this.fetchConsumeList({
year: year ? year : null,
month: month ? month : null,
operateId: operateId ? operateId : null,
serviceId: data.serviceId,
updateEuipmentList: true,
});
},
},
};
</script>
......@@ -244,19 +58,28 @@ export default {
<style lang="scss">
@import '@/assets/styles/variables.scss';
.Dashboard {
display: flex;
flex-direction: column;
width: 100%;
height: 100%;
background-color: #eee;
padding: 0 34px;
padding: 0 34px 38px;
overflow-y: scroll;
.Dashboard-Row {
height: calc(50% + (38px / 2 - 8px));
margin-top: 8px;
overflow: hidden;
}
.Dashboard-title {
font-size: 20px;
color: #333;
font-weight: 700;
}
.Dashboard-DataCard {
margin-top: 12px;
background-color: #fff;
border-radius: 8px;
margin-right: 8px;
&:last-child {
margin-right: 0;
}
}
.Dashboard-SearchBar {
display: flex;
......@@ -274,11 +97,51 @@ export default {
.filter-item-label {
width: auto;
}
.Dashboard-Radio {
display: flex;
align-items: center;
justify-self: flex-end;
.Dashboard-Radio-item {
margin: 0 10px;
}
}
}
.Dashboard-CustomerData {
display: flex;
.Dashboard-SearchBar {
justify-content: space-between;
border-bottom: 1px solid #f1f1f1;
.filter-item {
margin: 0 0 0 10px;
}
}
.Dashboard-DataCard {
flex: 2;
&:nth-child(2) {
flex: 2.3;
}
&:last-child {
flex: 1.2;
}
}
.Dashboard-title {
position: relative;
padding: 20px 0 0;
margin: 0 20px;
}
.Dashboard-title::before {
content: '';
position: absolute;
bottom: -12px;
left: 0;
width: 32px;
height: 4px;
background-color: #4e82fb;
}
}
.Dashboard-CampusData {
display: flex;
padding: 0 15px;
.Dashboard-title {
position: relative;
}
......@@ -299,15 +162,14 @@ export default {
}
}
.Dashboard-OperatorData {
flex: 1;
// flex: 1;
display: flex;
padding-bottom: 12px;
// padding-bottom: 12px;
// height: 400px;
.Dashboard-SearchBar {
align-items: center;
justify-content: center;
justify-content: space-around;
padding: 0;
min-width: 480px;
height: 70px;
border-bottom: 1px solid #f1f1f1;
.filter-item {
......@@ -346,7 +208,6 @@ export default {
flex: 2;
&:nth-child(2) {
flex: 1.5;
margin: 12px 12px 0;
}
}
}
......
<template>
<div class="Dashboard-DataCard">
<div class="Dashboard-title">
<div class="Dashboard-title-icon equipment">
<img src="@/assets/images/dashboard/icon_paiming@2x.png" />
</div>
<div class="Dashboard-title-text">各设备消费排名</div>
<el-radio-group v-model="showTopFive">
<el-radio-button :label="true">前五名</el-radio-button>
<el-radio-button :label="false">后五名</el-radio-button>
</el-radio-group>
</div>
<EquipmentListChart :data="consumeHardVos" />
</div>
</template>
<script>
import EquipmentListChart from './EquipmentListChart';
import { mapGetters, mapActions } from 'vuex';
export default {
name: 'EquipmentList',
components: {
EquipmentListChart,
},
data() {
return {
showTopFive: true,
};
},
computed: {
...mapGetters('Dashboard', ['consumeHardVos']),
},
methods: {
...mapActions('Dashboard', ['fetchConsumeList']),
},
};
</script>
<template>
<div class="Dashboard-DataCard">
<div class="Dashboard-title">
<div class="Dashboard-title-icon service">
<img src="@/assets/images/dashboard/icon_zhanbi@2x.png" />
</div>
<div class="Dashboard-title-text">各服务消费占比</div>
<div class="Dashboard-title-top">TOP1</div>
</div>
<SeviceRatioChart
:data="seviceRatioList"
:changeServiceHandle="changeServiceHandle"
/>
</div>
</template>
<script>
import SeviceRatioChart from './SeviceRatioChart';
import { mapActions, mapGetters } from 'vuex';
export default {
name: 'SeviceRatio',
components: { SeviceRatioChart },
data() {
return {};
},
computed: {
...mapGetters('Dashboard', ['seviceRatioList']),
},
methods: {
...mapActions('Dashboard', ['fetchConsumeList']),
changeServiceHandle(data) {
let operateId = this.operatorFilters.operateId;
let year = this.operatorFilters.year;
let month = this.operatorFilters.month;
this.fetchConsumeList({
year: year ? year : null,
month: month ? month : null,
operateId: operateId ? operateId : null,
serviceId: data.serviceId,
updateEuipmentList: true,
});
},
},
};
</script>
......@@ -103,7 +103,7 @@ export default {
alignY: 'middle',
});
this.chart.render();
this.chart.on('plotclick', this.clickHandle);
this.chart.on('interval:click', this.clickHandle);
},
updateData() {
if (this.data.length) {
......@@ -148,5 +148,6 @@ export default {
.SeviceRatio-title {
font-size: 16px;
text-align: center;
padding-bottom: 12px;
}
</style>
......@@ -21,7 +21,7 @@ export default {
const innerWidth = window.innerWidth;
const innerHeight = window.innerHeight;
if (innerWidth < 1600) {
this.height = (innerHeight - 250) / 2;
this.height = (innerHeight - 270) / 2;
}
this.initData();
},
......
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