刘翔宇-旅管家 3 years ago
parent 011d8cf7f6
commit 5de5036c0b

@ -15,3 +15,12 @@ export function getChartsData(params) {
params: params params: params
}) })
} }
export function getChartsHome(params) {
return request({
url: '/api/admin/chart/home',
method: 'get',
params: params
})
}

@ -1,60 +1,114 @@
<template> <template>
<el-row :gutter="40" class="panel-group"> <div>
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> <div class="boxlist">
<div class="card-panel"> <div class="box box1">
<div class="card-panel-icon-wrapper icon-people"> <div class="boxtitle">
<svg-icon icon-class="peoples" class-name="card-panel-icon" /> <span>营业统计</span>
<i class="el-icon-data-line statIcon"></i>
</div> </div>
<div class="card-panel-description"> <div class="bline"></div>
<div class="card-panel-text"> <div class="boxcontentsubtitle">服务金额</div>
欢迎回来 <div class="boxcontent">
</div> <div class="boxcontentitem">
<div class="card-panel-text" style="color: #001528;"> <div class="boxcontentitem-big">
管理员 {{totaldata.business.server_money_total}}
</div>
<div style="display: flex;justify-content: space-around;">
<div class="boxcontentitem-small">
<span>{{totaldata.business.nurse_money_total}}</span>
<span>护工金额</span>
</div>
<div class="boxcontentitem-small">
<span>{{totaldata.business.remain_money_total}}</span>
<span>留存金额</span>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</el-col>
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> <div class="box box2">
<div class="card-panel" @click="handleRoute('box')"> <div class="boxtitle">
<div class="card-panel-icon-wrapper icon-message">
<svg-icon icon-class="toolbox" class-name="card-panel-icon" /> <span>人效统计</span>
<i class="el-icon-user statIcon"></i>
</div> </div>
<div class="card-panel-description"> <div class="bline"></div>
<div class="card-panel-text"> <div class="boxcontentsubtitle">总服务时长</div>
工具箱 <div class="boxcontent">
<div class="boxcontentitem">
<div class="boxcontentitem-big">
{{totaldata.person_efficiency.server_time_total}}
分钟
</div>
<div style="display: flex;justify-content: space-around;">
<div class="boxcontentitem-small">
<span>{{totaldata.person_efficiency.expect}}</span>
<span> 照护人员数</span>
</div>
<div class="boxcontentitem-small">
<span>{{totaldata.person_efficiency.act}} </span>
<span>天数</span>
</div>
</div>
</div> </div>
<count-to :start-val="0" :end-val="countsData.client_count" :duration="3000" class="card-panel-num" />
</div> </div>
</div> </div>
</el-col>
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> <div class="box box3">
<div class="card-panel" @click="handleRoute('tool')"> <div class="boxtitle">
<div class="card-panel-icon-wrapper icon-money"> <span>客户统计</span>
<svg-icon icon-class="tool" class-name="card-panel-icon" /> <i class="el-icon-s-custom statIcon"></i>
</div> </div>
<div class="card-panel-description"> <div class="bline"></div>
<div class="card-panel-text"> <div class="boxcontentsubtitle">活跃客户</div>
工具 <div class="boxcontent">
<div class="boxcontentitem">
<div class="boxcontentitem-big">
{{totaldata.customer.active}}
</div>
<div style="display: flex;justify-content: space-around;">
<div class="boxcontentitem-small">
<span>{{totaldata.customer.add}}</span>
<span>新增</span>
</div>
<div class="boxcontentitem-small">
<span>{{totaldata.customer.wash}}</span>
<span>流失</span>
</div>
</div>
</div> </div>
<count-to :start-val="0" :end-val="countsData.tool_count" :duration="3200" class="card-panel-num" />
</div> </div>
</div> </div>
</el-col>
<el-col :xs="12" :sm="12" :lg="6" class="card-panel-col"> <div class="box box4">
<div class="card-panel" @click="handleRoute('user')"> <div class="boxtitle">
<div class="card-panel-icon-wrapper icon-shopping">
<svg-icon icon-class="user-group" class-name="card-panel-icon" /> <span>订单统计</span>
<i class="el-icon-document statIcon"></i>
</div> </div>
<div class="card-panel-description"> <div class="bline"></div>
<div class="card-panel-text"> <div class="boxcontentsubtitle">服务订单</div>
工具箱用户 <div class="boxcontent">
<div class="boxcontentitem">
<div class="boxcontentitem-big">{{totaldata.order.server_total}}
</div>
<div style="display: flex;justify-content: space-around;">
<div class="boxcontentitem-small">
<span>{{totaldata.order.cycle_total}}</span>
<span>周期性订单</span>
</div>
<div class="boxcontentitem-small">
<span>{{totaldata.order.unit_total}}</span>
<span>单次订单</span>
</div>
</div>
</div> </div>
<count-to :start-val="0" :end-val="countsData.user_count" :duration="3600" class="card-panel-num" />
</div> </div>
</div> </div>
</el-col> </div>
</el-row> </div>
</template> </template>
<script> <script>
@ -64,6 +118,32 @@
props: { props: {
countsData: { countsData: {
type: Object type: Object
},
totaldata: {
type: Object,
default: {
"business": {
"server_money_total": 0,
"nurse_money_total": 0,
"remain_money_total": 0
},
"person_efficiency": {
"server_time_total": "0",
"expect": 0,
"act": 0
},
"customer": {
"active": 0,
"add": 0,
"wash": 0
},
"order": {
"server_total": 0,
"cycle_total": 0,
"unit_total": 0
},
}
} }
}, },
components: { components: {
@ -72,71 +152,245 @@
methods: { methods: {
handleRoute(type) { handleRoute(type) {
this.$emit('handleRoute', type) this.$emit('handleRoute', type)
},
toCaculateper(f1, f2) {
return ((f1 / (f2 == 0 ? 1 : f2)) * 100).toFixed(2) + "%"
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.boxlist {
display: flex;
}
.statIcon {
font-size: 24px;
}
.index_icon {
position: absolute;
top: 1.25rem;
right: 1.25rem;
width: 3.5625rem;
}
.index_bg {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
}
.boxcontentitem-small {
font-size: 16px;
display: flex;
flex-direction: column;
}
.box {
position: relative;
width: 33%;
margin-left: 0.5%;
margin-right: 0.5%;
margin-bottom: 2.375rem;
box-shadow: 0px 8px 15px 0px rgba(212, 84, 32, 0.3100);
border-radius: 8px;
box-sizing: border-box;
opacity: 0.8;
padding: 1.25rem 0;
.boxcontentsubtitle {
color: #FFFFFF;
text-align: center;
display: flex;
justify-content: center;
font-size: 1.0625rem;
margin-top: 1.25rem;
}
.boxfooter {
font-size: 1.0625rem;
font-family: Source Han Sans CN;
font-weight: 400;
color: #FFFFFF;
display: flex;
justify-content: center;
}
.boxtitle {
font-size: 20px;
font-family: Source Han Sans CN;
font-weight: 400;
color: #FFFFFF;
padding: 0 1.25rem;
display: flex;
justify-content: space-between;
align-items: center;
}
.boxcontent {
display: flex;
//justify-content: space-around;
align-items: center;
.boxline {
width: 1px;
height: 4.0625rem;
background: #FFFFFF00;
opacity: 0.3;
margin-left: 2.0625rem;
margin-right: 2.0625rem;
}
.boxcontentitem {
display: flex;
flex-direction: column;
font-size: 19px;
font-family: Source Han Sans CN;
font-weight: 400;
color: #FFFFFF;
text-align: center;
min-width: 100%;
.boxcontentitem-big {
font-size: 2.625rem;
font-family: Arial;
font-weight: 400;
color: #FFFFFF;
}
}
}
}
.box1 {
background: linear-gradient(134deg, #D1AC7B, #DFC69C);
.boxcline {
width: 100%;
background: #DFC69C;
height: 0.125rem;
margin-top: 1.25rem;
margin-bottom: 1.25rem;
}
}
.bline {
background: linear-gradient(to right, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0) 60%);
height: 0.25rem;
width: 100%;
margin-top: 1.25rem;
}
.box2 {
background: linear-gradient(134deg, #9193BC, #B7B9D4);
.boxcline {
width: 100%;
background: #B7B9D4;
height: 0.125rem;
margin-top: 1.25rem;
margin-bottom: 1.25rem;
}
}
.box3 {
background: linear-gradient(-55deg, #F6A868, #F4C59E);
.boxcline {
width: 100%;
background: #F4C59E;
height: 0.125rem;
margin-top: 1.25rem;
margin-bottom: 1.25rem;
}
}
.box4 {
background: linear-gradient(-55deg, #64A48E, #9ECABB);
.boxcline {
width: 100%;
background: #9ECABB;
height: 0.125rem;
margin-top: 1.25rem;
margin-bottom: 1.25rem;
}
}
.panel-group { .panel-group {
margin-top: 18px; // margin-top: 18px;
margin-left: -2% !important;
margin-right: -3% !important;
.card-panel-col { .card-panel-col {
margin: 0 2%;
margin-bottom: 32px; margin-bottom: 32px;
} }
.card-panel { .card-panel {
height: 108px; height: 130px;
cursor: pointer; cursor: pointer;
font-size: 12px; font-size: 12px;
position: relative; position: relative;
overflow: hidden; overflow: hidden;
color: #666; color: #666;
background: #fff; text-align: center;
box-shadow: 4px 4px 40px rgba(0, 0, 0, .05); // background: #fff;
border-color: rgba(0, 0, 0, .05); // box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
// border-color: rgba(0, 0, 0, .05);
&:hover { &:hover {
.card-panel-icon-wrapper { .card-panel-icon-wrapper {
color: #fff; color: #fff;
} }
.icon-people { // .icon-people {
background: #40c9c6; // background: #40c9c6;
} // }
.icon-message { // .icon-message {
background: #36a3f7; // background: #36a3f7;
} // }
.icon-money { // .icon-money {
background: #f4516c; // background: #f4516c;
} // }
.icon-shopping { // .icon-shopping {
background: #34bfa3 // background: #34bfa3
} // }
} }
.icon-people { .icon-people {
color: #40c9c6; color: #fff;
} }
.icon-message { .icon-message {
color: #36a3f7; color: #fff;
} }
.icon-money { .icon-money {
color: #f4516c; color: #fff;
} }
.icon-shopping { .icon-shopping {
color: #34bfa3 color: #fff
} }
.card-panel-icon-wrapper { .card-panel-icon-wrapper {
float: left; float: right;
margin: 14px 0 0 14px; margin: 22px 0 0 14px;
padding: 16px; padding: 16px;
transition: all 0.38s ease-out; transition: all 0.38s ease-out;
border-radius: 6px; border-radius: 6px;
@ -144,20 +398,26 @@
.card-panel-icon { .card-panel-icon {
float: left; float: left;
font-size: 48px; font-size: 42px;
} }
.card-panel-description { .card-panel-description {
float: right; // float: right;
font-weight: bold; font-weight: bold;
margin: 26px; margin: 16px 12px;
margin-left: 0px;
.card-panel-text { .card-panel-text {
line-height: 18px; line-height: 25px;
color: rgba(0, 0, 0, 0.45); color: rgb(255, 255, 255);
font-size: 16px; font-size: 26px;
margin-bottom: 12px; margin-bottom: 20px;
width: 70%;
text-align: left;
}
p {
text-align: left;
font-size: 19px;
} }
.card-panel-num { .card-panel-num {

@ -1,312 +1,307 @@
<template> <template>
<div> <div>
<div class="statistics">
<el-card> <div class="statistics">
<template v-slot:header> <panel-group :totaldata="list" />
<i class="el-icon-data-line"></i> </div>
<span class="statistics-title">营业统计</span>
</template> <div class="chart">
<div class="statistics-content"> <div class="chartItem" style="margin-right: 1%;">
<div class="statistics-content-top"> <div class="chartItemTitle">营业与收入</div>
<div class="statistics-content-top__num">40.5</div> <div id="col-chart"></div>
<div class="statistics-content-top__name">服务金额</div> </div>
</div> <div class="chartItem" style="margin-left: 1%;">
<div class="statistics-content-bottom"> <div class="chartItemTitle">客户与订单</div>
<div class="statistics-content-bottom-left"> <div id="line-chart"></div>
<div class="statistics-content-bottom-left__num">26.9</div> </div>
<div class="statistics-content-bottom-left__name">护工金额</div> </div>
</div> </div>
<div class="statistics-content-bottom-right"> </template>
<div class="statistics-content-bottom-right__num">13.6</div>
<div class="statistics-content-bottom-right__name">留存金额</div> <script>
</div> import echarts from "echarts"
</div> import PanelGroup from './components/PanelGroup'
</div> import {
</el-card> getChartsHome
} from "../../api/dashboard.js"
<el-card>
<template v-slot:header> export default {
<i class="el-icon-user"></i> components: {
<span class="statistics-title">人效统计</span> PanelGroup
</template> },
<div class="statistics-content"> data() {
<div class="statistics-content-top"> return {
<div class="statistics-content-top__num">120</div> col: '',
<div class="statistics-content-top__name">照护人员</div> line: '',
</div> business_data: [],
<div class="statistics-content-bottom"> collect_data: [],
<div class="statistics-content-bottom-left"> list: {},
<div class="statistics-content-bottom-left__num">8小时/</div> customerArr: [],
<div class="statistics-content-bottom-left__name">预期照护时长</div> orderArr: [],
</div> chartData: {},
<div class="statistics-content-bottom-right"> }
<div class="statistics-content-bottom-right__num">6.3小时/</div> },
<div class="statistics-content-bottom-right__name">人均照护时长</div> watch: {
</div> chartData(val, newval) {
</div> if (newval){
</div> this.init();
</el-card> }
}
<el-card> },
<template v-slot:header> methods: {
<i class="el-icon-s-custom"></i> async loadData() {
<span class="statistics-title">客户统计</span> await getChartsHome().then((res) => {
</template> console.log(res);
<div class="statistics-content"> this.list = res.list;
<div class="statistics-content-top"> this.chartData = res;
<div class="statistics-content-top__num">800</div> let _business_data = [];
<div class="statistics-content-top__name">活跃客户</div> let _collect_data = [];
</div> res.business_data.map(item => {
<div class="statistics-content-bottom"> _business_data.push(item.server_money_total)
<div class="statistics-content-bottom-left"> _collect_data.push(item.collect_money)
<div class="statistics-content-bottom-left__num">100</div> })
<div class="statistics-content-bottom-left__name">新增</div> this.business_data = _business_data;
</div> this.collect_data = _collect_data;
<div class="statistics-content-bottom-right"> let _customerArr = [];
<div class="statistics-content-bottom-right__num">20</div> let _orderArr = [];
<div class="statistics-content-bottom-right__name">流失</div>
</div> res.order_data.map(item => {
</div> _customerArr.push(item.active_customer)
</div> _orderArr.push(item.order_total)
</el-card> })
this.customerArr = _customerArr;
<el-card> this.orderArr = _orderArr;
<template v-slot:header> }).catch()
<i class="el-icon-document"></i> },
<span class="statistics-title">订单统计</span> init() {
</template> this.col = echarts.init(document.getElementById('col-chart'))
<div class="statistics-content"> this.col.setOption({
<div class="statistics-content-top"> title: {
<div class="statistics-content-top__num">500</div> text: ''
<div class="statistics-content-top __name">服务订单</div> },
</div> tooltip: {
<div class="statistics-content-bottom"> trigger: 'axis',
<div class="statistics-content-bottom-left"> axisPointer: {
<div class="statistics-content-bottom-left__num">450</div> type: 'shadow'
<div class="statistics-content-bottom-left__name">周期性订单</div> },
</div> position: 'bottom'
<div class="statistics-content-bottom-right"> },
<div class="statistics-content-bottom-right__num">50</div> legend: {},
<div class="statistics-content-bottom-right__name">单次订单</div> grid: {
</div> left: '3%',
</div> right: '4%',
</div> bottom: '3%',
</el-card> containLabel: true
</div> },
yAxis: {
<div class="chart"> type: 'value',
<div id="col-chart"></div> boundaryGap: [0, 0.01]
<div id="line-chart"></div> },
</div> xAxis: {
</div> type: 'category',
</template> data: ['第一周', '第二周', '第三周', '第四周']
},
<script> series: [{
import echarts from "echarts" name: '服务金额',
type: 'bar',
export default { data: this.business_data,
components: {}, itemStyle: {
data() { normal: {
return { color: 'rgb(42,182,252)'
col:'', },
line:'' },
} },
}, {
methods: { name: '收款',
init() { type: 'bar',
this.col = echarts.init(document.getElementById('col-chart')) data: this.collect_data,
this.col.setOption({ itemStyle: {
title: { normal: {
text: '' color: 'rgb(34,228,255)'
}, },
tooltip: { },
trigger: 'axis', }
axisPointer: { ]
type: 'shadow' })
},
position:'bottom' this.line = echarts.init(document.getElementById('line-chart'))
}, this.line.setOption({
legend: {}, title: {
grid: { text: ''
left: '3%', },
right: '4%', tooltip: {
bottom: '3%', trigger: 'axis'
containLabel: true },
}, legend: {
yAxis: { data: ['活跃客户', '服务订单']
type: 'value', },
boundaryGap: [0, 0.01] grid: {
}, left: '3%',
xAxis: { right: '6%',
type: 'category', bottom: '3%',
data: ['第一周', '第二周', '第三周', '第四周'] containLabel: true
}, },
series: [ toolbox: {
{
name: '服务金额', },
type: 'bar', xAxis: {
data: [18203, 23489, 29034, 104970], type: 'category',
itemStyle: { boundaryGap: false,
normal: { data: ['第一周', '第二周', '第三周', '第四周']
color: 'rgb(42,182,252)' },
}, yAxis: {
}, type: 'value',
}, },
{ series: [{
name: '收款', name: '活跃客户',
type: 'bar', type: 'line',
data: [19325, 23438, 31000, 121594], stack: 'Total',
itemStyle: { data: this.customerArr,
normal: { itemStyle: {
color: 'rgb(34,228,255)' normal: {
}, color: 'rgb(42,182,252)'
}, },
} },
] },
}) {
name: '服务订单',
this.line = echarts.init(document.getElementById('line-chart')) type: 'line',
this.line.setOption({ stack: 'Total',
title: { data: this.orderArr,
text: '' itemStyle: {
}, normal: {
tooltip: { color: 'rgb(34,228,255)'
trigger: 'axis' },
}, },
legend: { }
data: ['活跃客户', '服务订单'] ]
}, })
grid: { }
left: '3%', },
right: '6%', created() {
bottom: '3%',
containLabel: true this.loadData();
}, },
toolbox: { mounted() {
},
xAxis: { //this.init()
type: 'category',
boundaryGap: false, window.onresize = () => {
data: ['第一周', '第二周', '第三周', '第四周'] this.col.resize()
}, this.line.resize()
yAxis: { }
type: 'value',
}, },
series: [ destroyed() {
{ window.onresize = null
name: '活跃客户', }
type: 'line', }
stack: 'Total', </script>
data: [120, 132, 101, 134],
itemStyle: { <style lang="scss" scoped>
normal: { .statistics {
color: 'rgb(42,182,252)' display: flex;
},
}, margin-top: 20px;
},
{ &-title {
name: '服务订单',
type: 'line', padding-left: 6px;
stack: 'Total', }
data: [220, 182, 191, 234],
itemStyle: { &-content {
normal: { text-align: center;
color: 'rgb(34,228,255)' font-size: 13px;
},
}, &-top {
}
] &__num {
}) font-weight: 600;
} }
},
mounted() { &__name {
this.init() font-size: 10px;
color: rgb(140, 140, 140);
window.onresize = () => { }
this.col.resize() }
this.line.resize()
} &-bottom {
}, display: flex;
destroyed() { justify-content: space-between;
window.onresize = null
} &-left {
}
</script> &__num {
font-weight: 600;
<style lang="scss" scoped> }
.statistics{
display: flex; &__name {
font-size: 10px;
margin-top: 20px; color: rgb(140, 140, 140);
&-title{ }
}
padding-left: 6px;
} &-right {
&-content{
text-align: center; &__num {
font-size: 13px; font-weight: 600;
&-top{ }
&__num{ &__name {
font-weight: 600; font-size: 10px;
} color: rgb(140, 140, 140);
&__name{ }
font-size: 10px; }
color: rgb(140,140,140); }
} }
}
&-bottom{ &>div {
display: flex; flex: 1;
justify-content: space-between; margin-right: 20px;
&-left{ &:last-child {
margin-right: 0;
&__num{ }
font-weight: 600; }
} }
&__name{
font-size: 10px; .chart {
color: rgb(140,140,140); display: flex;
}
} margin-top: 20px;
&-right{
&__num{ .chartItem {
font-weight: 600;
} width: 49%;
&__name{
font-size: 10px; .chartItemTitle {
color: rgb(140,140,140); font-size: 16px;
} margin-bottom: 20px;
} }
}
} #col-chart {
&>div{ background: #fff;
flex: 1; border-radius: 10px;
margin-right: 20px; flex: 1;
margin-right: 20px;
&:last-child{ padding: 20px;
margin-right: 0; box-sizing: border-box;
} min-height: 400px;
} width: 100%;
} }
.chart{
display: flex; #line-chart {
background: #fff;
margin-top: 50px; border-radius: 10px;
#col-chart { flex: 1;
background: #fff; padding: 20px;
border-radius: 10px; box-sizing: border-box;
flex: 1; min-height: 400px;
height: 300px; }
margin-right: 30px; }
}
#line-chart {
background: #fff; }
border-radius: 10px;
flex: 1;
height: 300px;
}
}
</style> </style>

Loading…
Cancel
Save