第四十七节:驾驶舱大屏 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 实例,无内存泄漏
相关推荐
2501_944521595 小时前
Ramda 跨端三方库仓颉适配全流程
开发语言·javascript·flutter·php
Ken_11156 小时前
小体积附件下载正常,大附件下载异常
javascript
变与不变8067 小时前
jQuery怎么使用
前端·javascript
神膘护体小月半7 小时前
flex 布局的 order 属性
前端·css
paopaokaka_luck7 小时前
流浪动物救助与收养系统(DeepSeek AI对话、 ECharts多维分析、救助流程衔接、领养与回访衔接、 捐赠确认与公示、志愿者协作)
java·前端·javascript·人工智能·mysql·echarts·推荐算法
仰望.7 小时前
vue 表格组件 vxe-table 树表格懒加载支持拖拽排序的详细用法
前端·javascript·vue.js·vxe-table
前端 贾公子7 小时前
vite-plugin-uni-manifest 升级指南
前端
小码哥_常7 小时前
iPhone 用户传了张 HEIC,我的前端崩了
前端
小码哥_常7 小时前
你发的原图可能暴露你家地址——聊聊图片 EXIF 隐私
前端
java1234_小锋8 小时前
【技术专题】CSS3 网页技术 - CSS3 优先级
前端·css·css3