rk
12 小时以前 609a1931953b2298016bd2b0d6b410666b5ad7b9
admin/src/views/data.vue
@@ -8,9 +8,9 @@
          <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>
@@ -32,12 +32,12 @@
              <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>
@@ -55,12 +55,12 @@
              <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>
@@ -73,19 +73,16 @@
<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
@@ -97,6 +94,7 @@
      this.initDonutChart()
      this.initPieChart()
    })
    this.loadDashboard()
    window.addEventListener('resize', this.handleResize)
  },
  beforeDestroy () {
@@ -108,21 +106,42 @@
  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,
@@ -138,22 +157,33 @@
        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',
@@ -175,16 +205,32 @@
            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',
@@ -206,17 +252,34 @@
            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)
      })
    }
  }
}
@@ -239,7 +302,7 @@
.stat-card {
  flex: 1;
  background: #e8f0fe;
  background: #eff6ff;
  border-radius: 8px;
  padding: 20px 24px;
}