第四十七节:驾驶舱大屏 ECharts 图表集成

第四十七节:驾驶舱大屏 ECharts 图表集成

🎯本节目标

  1. 安装 echarts 依赖
  2. 在驾驶舱页面封装图表容器,实现自适应(窗口缩放自动重绘)
  3. 对接 mock 大屏统计接口,渲染数字指标卡片 + 柱状图 + 饼图
  4. 处理页面销毁,释放 echarts 实例,防止内存泄漏

步骤 1:安装 echarts

复制代码
pnpm add echarts

步骤 2:修改 cockpit.vue 完整代码

复制代码
<template>
  <div class="cockpit-wrap">
    <!-- 返回后台按钮 -->
    <el-button class="back-btn" @click="backAdmin">返回管理后台</el-button>
    <h1 class="title">驾驶舱 · 数据大屏</h1>

    <!-- 顶部指标卡片 -->
    <div class="card-row">
      <div class="stat-card">
        <div class="label">用户总数</div>
        <div class="num">{{ statData.userTotal }}</div>
      </div>
      <div class="stat-card">
        <div class="label">资讯总数</div>
        <div class="num">{{ statData.newsTotal }}</div>
      </div>
      <div class="stat-card">
        <div class="label">部门数量</div>
        <div class="num">{{ statData.deptTotal }}</div>
      </div>
      <div class="stat-card">
        <div class="label">在线用户</div>
        <div class="num">{{ statData.onlineUser }}</div>
      </div>
    </div>

    <!-- 图表行 -->
    <div class="chart-row">
      <div class="chart-item">
        <div ref="barRef" class="chart"></div>
      </div>
      <div class="chart-item">
        <div ref="pieRef" class="chart"></div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch } from 'vue'
import { useRouter } from 'vue-router'
import * as echarts from 'echarts'
import axios from '@/api/request'

const router = useRouter()
const barRef = ref(null)
const pieRef = ref(null)
let barChart = null
let pieChart = null

// 统计数据
const statData = ref({
  userTotal: 0,
  newsTotal: 0,
  deptTotal: 0,
  onlineUser: 0
})

// 返回后台
const backAdmin = () => {
  router.push('/dashboard/dashboard')
}

// 获取大屏统计接口
const getCockpitStat = async () => {
  const res = await axios.get('/cockpit/getStat')
  if(res.code === 200) {
    statData.value = res.data
    renderChart()
  }
}

// 渲染图表
const renderChart = () => {
  // 柱状图
  barChart = echarts.init(barRef.value)
  barChart.setOption({
    title: { text: '月度用户增长', textStyle:{color:'#fff'} },
    tooltip: {},
    xAxis: {
      type: 'category',
      data: ['1月','2月','3月','4月','5月','6月'],
      axisLine:{lineStyle:{color:'#506688'}}
    },
    yAxis: {
      type: 'value',
      axisLine:{lineStyle:{color:'#506688'}},
      splitLine:{lineStyle:{color:'#273b60'}}
    },
    series: [{
      data: [80,120,95,160,210,240],
      type: 'bar',
      color: '#00bfff'
    }]
  })

  // 饼图
  pieChart = echarts.init(pieRef.value)
  pieChart.setOption({
    title: { text: '部门人员分布', textStyle:{color:'#fff'} },
    tooltip: {},
    series: [{
      type: 'pie',
      radius: '60%',
      data: [
        {value: 85, name:'研发部'},
        {value: 42, name:'运营部'},
        {value: 26, name:'市场部'},
        {value: 18, name:'行政部'}
      ]
    }]
  })
}

// 窗口大小变化自适应
const resizeHandler = () => {
  barChart?.resize()
  pieChart?.resize()
}

onMounted(() => {
  getCockpitStat()
  window.addEventListener('resize', resizeHandler)
})

// 销毁释放实例,防止内存泄漏
onUnmounted(() => {
  window.removeEventListener('resize', resizeHandler)
  barChart?.dispose()
  pieChart?.dispose()
})
</script>

<style scoped>
.cockpit-wrap {
  width: 100vw;
  height: 100vh;
  box-sizing: border-box;
  padding:20px;
  background-color: #091b39;
  color:#fff;
}
.back-btn {
  position: absolute;
  top:12px;
  right:20px;
  z-index:99;
}
.title {
  text-align:center;
  font-size:28px;
  margin:10px 0 30px;
}
.card-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap:16px;
  margin-bottom:20px;
}
.stat-card {
  background: rgba(30, 60, 110, 0.6);
  padding:20px;
  border-radius:8px;
  text-align:center;
}
.stat-card .label {
  font-size:16px;
  color:#a0b8e3;
}
.stat-card .num {
  font-size:32px;
  font-weight:bold;
  margin-top:8px;
}
.chart-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap:20px;
  height: calc(100% - 220px);
}
.chart-item {
  background: rgba(30, 60, 110, 0.6);
  border-radius:8px;
  padding:16px;
}
.chart {
  width:100%;
  height:100%;
}
</style>

步骤 3:确认 mock 接口(之前写的)

复制代码
'/cockpit/getStat' : () => {
  return {
    code:200,
    data:{
      userTotal: 1256,
      newsTotal: 89,
      deptTotal:12,
      onlineUser:36
    }
  }
}

✅测试清单

  1. 点击驾驶舱跳转,页面加载出 4 个统计卡片
  2. 柱状图、饼图正常渲染,深色大屏风格
  3. 浏览器窗口缩放,图表自动适配大小
  4. 点击返回管理后台,回到工作台,页面销毁 echarts 实例,无内存泄漏
相关推荐
Software攻城狮1 小时前
【React 学习方向(项目上手注意点)】
前端
林太白2 小时前
js-var和let以及const区别
前端·面试
看谷秀2 小时前
arkts-10 实战
前端·arkts
范小兵2 小时前
# DevEco CLI实战:鸿蒙App「至客」从0开发到正式上架
前端·harmonyos
梦醒沉醉2 小时前
7、表达日期和时间(前朝遗老Date)
javascript
半生过往2 小时前
前端工程师学习智能体开发(一)
前端·学习·状态模式
白雾茫茫丶2 小时前
Vibecoding 一个主题切换动画库:13 种揭幕方式
前端·vue.js·react.js
计算机魔术师2 小时前
谷歌宣布 TPU 互联架构支持 100 万芯片规模,电力供应成 AI 基建核心瓶颈
前端
雪芽蓝域zzs2 小时前
第四十九节:TagsView 右键菜单(带三角箭头)给每个 tag 增加**鼠标右键菜单**(右键标签弹出:关闭、关闭其他、关闭全部)
前端·javascript·vue.js