| | |
| | | <span v-if="card.prefix" class="stat-prefix">{{ card.prefix }}</span> |
| | | {{ card.value }} |
| | | </div> |
| | | <div class="stat-sub"> |
| | | <span>昨日 {{ card.yesterday }}</span> |
| | | <span>今日 {{ card.today }}</span> |
| | | <div class="stat-sub" v-if="card.label !== '车辆总数'"> |
| | | <span>昨日 {{ card.label === '本月收益' ? '¥' : ''}}{{ card.yesterday }}</span> |
| | | <span>今日 {{ card.label === '本月收益' ? '¥' : ''}}{{ card.today }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <el-button |
| | | :type="vehicleType === 'bicycle' ? 'primary' : 'default'" |
| | | size="mini" |
| | | @click="vehicleType = 'bicycle'" |
| | | @click="switchVehicleType('bicycle')" |
| | | >自行车</el-button> |
| | | <el-button |
| | | :type="vehicleType === 'electric' ? 'primary' : 'default'" |
| | | size="mini" |
| | | @click="vehicleType = 'electric'" |
| | | @click="switchVehicleType('electric')" |
| | | >电动车</el-button> |
| | | </el-button-group> |
| | | </div> |
| | |
| | | <el-button |
| | | :type="salesPeriod === 'month' ? 'primary' : 'default'" |
| | | size="mini" |
| | | @click="salesPeriod = 'month'" |
| | | @click="switchSalesPeriod('month')" |
| | | >本月</el-button> |
| | | <el-button |
| | | :type="salesPeriod === 'year' ? 'primary' : 'default'" |
| | | size="mini" |
| | | @click="salesPeriod = 'year'" |
| | | @click="switchSalesPeriod('year')" |
| | | >本年</el-button> |
| | | </el-button-group> |
| | | </div> |
| | |
| | | |
| | | <script> |
| | | import * as echarts from 'echarts' |
| | | |
| | | import { dashboard, packageSourceStat, bikeUsageStat, incomeStat30 } from '@/api/business/report.js' |
| | | export default { |
| | | data () { |
| | | return { |
| | | statCards: [ |
| | | { label: '本月收益', prefix: '¥', value: '32242.34', yesterday: '24243.23', today: '235.34' }, |
| | | { label: '本月订单', value: '2849', yesterday: '345', today: '243' }, |
| | | { label: '在客户数', value: '243', yesterday: '23', today: '12' }, |
| | | { label: '车辆总数', value: '243', yesterday: '在线 240', today: '离线 3' } |
| | | ], |
| | | statCards: [], |
| | | vehicleType: 'bicycle', |
| | | vehicleTotal: 142, |
| | | vehicleTotal: 0, |
| | | bikeUsageData: null, |
| | | salesPeriod: 'month', |
| | | packageSourceData: null, |
| | | barChart: null, |
| | | donutChart: null, |
| | | pieChart: null |
| | |
| | | this.initDonutChart() |
| | | this.initPieChart() |
| | | }) |
| | | this.loadDashboard() |
| | | window.addEventListener('resize', this.handleResize) |
| | | }, |
| | | beforeDestroy () { |
| | |
| | | methods: { |
| | | initBarChart () { |
| | | const chart = echarts.init(this.$refs.barChart) |
| | | const data = [111, 227, 147, 163, 178, 200, 126] |
| | | const dates = ['6-15', '6-16', '6-17', '6-18', '6-19', '6-20', '6-21'] |
| | | incomeStat30({}).then(res => { |
| | | const data = res.dailyList || [] |
| | | const dates = data.map(item => { |
| | | const d = item.date.split('-') |
| | | return `${d[1]}-${d[2]}` |
| | | }) |
| | | const incomes = data.map(item => item.income) |
| | | chart.setOption({ |
| | | tooltip: { trigger: 'axis' }, |
| | | legend: { |
| | | data: ['收入'], |
| | | bottom: 0 |
| | | bottom: 50 |
| | | }, |
| | | grid: { |
| | | left: 10, |
| | | right: 10, |
| | | top: 20, |
| | | bottom: 40, |
| | | bottom: 80, |
| | | containLabel: true |
| | | }, |
| | | dataZoom: [ |
| | | { |
| | | type: 'inside', |
| | | xAxisIndex: 0, |
| | | start: 0, |
| | | end: 100 |
| | | }, |
| | | { |
| | | type: 'slider', |
| | | xAxisIndex: 0, |
| | | start: 0, |
| | | end: 100, |
| | | bottom: 20, |
| | | height: 20 |
| | | } |
| | | ], |
| | | xAxis: { |
| | | type: 'category', |
| | | data: dates, |
| | |
| | | series: [{ |
| | | name: '收入', |
| | | type: 'bar', |
| | | barWidth: 30, |
| | | barWidth: '60%', |
| | | itemStyle: { color: '#5B8FF9' }, |
| | | label: { |
| | | show: true, |
| | | position: 'top', |
| | | color: '#5B8FF9', |
| | | fontSize: 11 |
| | | }, |
| | | data: data |
| | | data: incomes |
| | | }] |
| | | }) |
| | | }).catch(e => { |
| | | this.$tip.apiFailed(e) |
| | | }) |
| | | this.barChart = chart |
| | | }, |
| | | initDonutChart () { |
| | | const chart = echarts.init(this.$refs.donutChart) |
| | | chart.setOption({ |
| | | this.donutChart = chart |
| | | bikeUsageStat({}).then(res => { |
| | | this.bikeUsageData = res |
| | | this.updateDonutChart() |
| | | }).catch(e => { |
| | | this.$tip.apiFailed(e) |
| | | }) |
| | | }, |
| | | updateDonutChart () { |
| | | if (!this.bikeUsageData || !this.donutChart) return |
| | | const isBicycle = this.vehicleType === 'bicycle' |
| | | const idle = isBicycle ? this.bikeUsageData.bikeIdle || 0 : this.bikeUsageData.eleBikeIdle || 0 |
| | | const inUse = isBicycle ? this.bikeUsageData.bikeInUse || 0 : this.bikeUsageData.eleBikeInUse || 0 |
| | | this.vehicleTotal = idle + inUse |
| | | this.donutChart.setOption({ |
| | | tooltip: { trigger: 'item' }, |
| | | legend: { |
| | | orient: 'horizontal', |
| | |
| | | fontSize: 12 |
| | | }, |
| | | data: [ |
| | | { value: 60, name: '空闲', itemStyle: { color: '#73C0DE' } }, |
| | | { value: 180, name: '使用中', itemStyle: { color: '#5B8FF9' } } |
| | | { value: idle, name: '空闲', itemStyle: { color: '#73C0DE' } }, |
| | | { value: inUse, name: '使用中', itemStyle: { color: '#5B8FF9' } } |
| | | ] |
| | | }] |
| | | }) |
| | | this.donutChart = chart |
| | | }, |
| | | switchVehicleType (type) { |
| | | this.vehicleType = type |
| | | this.updateDonutChart() |
| | | }, |
| | | initPieChart () { |
| | | const chart = echarts.init(this.$refs.pieChart) |
| | | chart.setOption({ |
| | | this.pieChart = chart |
| | | packageSourceStat({}).then(res => { |
| | | this.packageSourceData = res |
| | | this.updatePieChart() |
| | | }).catch(e => { |
| | | this.$tip.apiFailed(e) |
| | | }) |
| | | }, |
| | | updatePieChart () { |
| | | if (!this.packageSourceData || !this.pieChart) return |
| | | const data = this.salesPeriod === 'month' ? this.packageSourceData.month : this.packageSourceData.year |
| | | const douyinCount = data ? (data.douyinCount || 0) : 0 |
| | | const miniCount = data ? (data.miniCount || 0) : 0 |
| | | this.pieChart.setOption({ |
| | | tooltip: { trigger: 'item' }, |
| | | legend: { |
| | | orient: 'horizontal', |
| | |
| | | fontSize: 12 |
| | | }, |
| | | data: [ |
| | | { value: 130, name: '抖音团购', itemStyle: { color: '#73C0DE' } }, |
| | | { value: 100, name: '小程序销售', itemStyle: { color: '#5B8FF9' } } |
| | | { value: douyinCount, name: '抖音团购', itemStyle: { color: '#73C0DE' } }, |
| | | { value: miniCount, name: '小程序销售', itemStyle: { color: '#5B8FF9' } } |
| | | ] |
| | | }] |
| | | }) |
| | | this.pieChart = chart |
| | | }, |
| | | switchSalesPeriod (period) { |
| | | this.salesPeriod = period |
| | | this.updatePieChart() |
| | | }, |
| | | handleResize () { |
| | | if (this.barChart) this.barChart.resize() |
| | | if (this.donutChart) this.donutChart.resize() |
| | | if (this.pieChart) this.pieChart.resize() |
| | | }, |
| | | loadDashboard () { |
| | | dashboard({}).then(res => { |
| | | if (res) { |
| | | this.statCards = [ |
| | | { label: '本月收益', prefix: '¥', value: res.monthIncome || 0, yesterday: res.yesterdayIncome || 0, today: res.todayIncome || 0 }, |
| | | { label: '本月订单', value: res.monthOrderCount || 0, yesterday: res.yesterdayOrderCount || 0, today: res.todayOrderCount || 0 }, |
| | | { label: '在客户数', value: res.totalMemberCount || 0, yesterday: res.yesterdayNewMember || 0, today: res.todayNewMember || 0 }, |
| | | { label: '车辆总数', value: res.totalBikeCount || 0, yesterday: '', today: '' } |
| | | ] |
| | | } |
| | | }).catch(e => { |
| | | this.$tip.apiFailed(e) |
| | | }) |
| | | } |
| | | } |
| | | } |
| | |
| | | |
| | | .stat-card { |
| | | flex: 1; |
| | | background: #e8f0fe; |
| | | background: #eff6ff; |
| | | border-radius: 8px; |
| | | padding: 20px 24px; |
| | | } |