YGG-CLI-7-监控页面的设计与开发

一个文笔一般,想到哪是哪的唯心论前端小白。

🧠 - 简介

所谓监控页面,其实主要还是和图表相关内容的处理。为此我做了一个组件,专门用来回显图表数据的。

效果图如下:

如图所示,它是一个卡片组件,头部显示的话可以切换图表类型,如果不显示头部就是一个简单的chart的引用。

👁️ - 分析

得益于前面的表单和表格组件,我依旧使用了 component 的方案来实现chart组件的开发。

🫀 - 拆解

首先要定义一下入参的数据格式,所有类型的图表都是这个数据结构:

ts 复制代码
const data = [
  {
    name: 'zhangsan',
    data: [
      12, 13, 18, 20, 30, 40, 50
    ],
    xAxis: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  {
    name: 'lisi',
    data: [
      112, 13, 18, 20, 310, 40, 59
    ],
    xAxis: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  {
    name: 'wangwu',
    data: [
      112, 13, 18, 20, 310, 40, 59
    ],
    xAxis: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
]

如上所示,这是三条数据,分别对应三个人的:zhangsan、lisi、wangwu。每条数据的x周都是周一到周日,data中存放每天的数据。

另外为了保证页面好看应该有一个 chartConfig,里面存放一些常见的配置。

💪 - 落实

vue 复制代码
<template>
  <div class="chart-card">
    <div
      v-if="!noHeader"
      class="chart-card-head"
    >
      <div class="chart-card-head-title">
        <span>{{ title }}</span>

        <el-dropdown @command="handleCommand">
          <span class="el-dropdown-link">
            <el-icon>
              <More />
            </el-icon>
          </span>
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item command="line">
                折线图
              </el-dropdown-item>
              <el-dropdown-item command="bar">
                柱状图
              </el-dropdown-item>
              <el-dropdown-item command="radar">
                雷达图
              </el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
      </div>
    </div>
    <div
      :id="chartId"
      class="chart-card-content"
    />
  </div>
</template>

<script lang="ts" setup>

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * @Name: ChartCard
 * @Author: 
 * @Email: 14559@163.com
 * @Date: 2023-11-30 19:07
 * @Introduce: --
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

import { More } from '@element-plus/icons-vue'
import { onMounted, onUnmounted, toRefs } from 'vue';
import {
  ChartType,
} from './utils';

import useChart from './useChart'
const chartId = 'chart_' + parseInt(Math.random() * 10 * 1024 * 1024 + '')
const {initChart} = useChart(chartId)

const props = defineProps<{
  title: string
  noHeader?: boolean
  defaultType?: ChartType
}>()

const data = [
  {
    name: 'zhangsan',
    data: [
      12, 13, 18, 20, 30, 40, 50
    ],
    xAxis: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  {
    name: 'lisi',
    data: [
      112, 13, 18, 20, 310, 40, 59
    ],
    xAxis: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
  {
    name: 'wangwu',
    data: [
      112, 13, 18, 20, 310, 40, 59
    ],
    xAxis: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
  },
]

const { title, defaultType, noHeader } = toRefs(props)

let chart;

const handleCommand = (v: ChartType) => {
  initChart(v, data)
}

onMounted(() => {
  initChart(defaultType!.value || 'line', data)
})

</script>

<style lang="scss" scoped>
.chart-card {

  $cl: var(--el-border-color);

  height: 100%;
  width: 100%;
  box-shadow: 3px 3px 6px $cl;
  border: 1px solid $cl;

  display: flex;
  flex-direction: column;

  .chart-card-head-title {
    display: flex;
    justify-content: space-between;

    height: 40px;
    border-bottom: 1px solid $cl;

    span {
      line-height: 40px;
      padding: 0 10px;
    }
  }

  .chart-card-content {
    flex-grow: 1;
    width: 100%;
    height: 100%;
    padding: 10px;
    box-sizing: border-box;
  }
}
</style>

这其实是个中间版本,需要把

html 复制代码
<div
  :id="chartId"
  class="chart-card-content"
/>

部分替换成 component,但是这里很明显没有。

核心其实是一个转换器,通过配置和数据生成 echartOptions。

ts 复制代码
export type OptionDataType = {name: string, data: number[], xAxis: string[]}[]
export type LegendType = {
  type?:string
  bottom?: number
  data: string[]}
export type ChartType = 'line' | 'bar' | 'radar'
export type ClearChart = undefined | (() => void);

export const initChartOptions = (type: ChartType, data: OptionDataType) => {

  const legend:LegendType = {
    type: 'scroll',
    bottom: 10,
    data: data.map(item => item.name)
  }
  const title = {}

  if(['bar', 'line'].includes(type)){
    return {
      title,
      legend,
  
      xAxis: {
        type: 'category',
        data: [...data[0].xAxis]
      },
  
      yAxis: {
        type: 'value'
      },
  
      series: [...data.map(item => ({
        name: item.name,
        type: type,
        data: item.data,
      }))]
    }
  }

  if(['radar'].includes(type)){
    return {
      title,
      legend,

      radar:{
        shape: 'circle',
        indicator: [
          ...legend.data.map(item => ({name: item}))
        ]
      },

      series: [
        {
          name: legend.data.join(' vs '),
          type: type,

          data: [
            ...data.map(item => ({
              name: item.name,
              value: item.data
            }))
          ]
        }
      ]
    }
  }
}

设计上通过这个转换器,是可以适配多种图表框架的,不局限于 echart。

🛀 - 总结

本篇后续会再更新,到时候再细说吧。

系列文章:

  1. 脚手架开发
  2. 模板项目初始化
  3. 模板项目开发规范与设计思路
  4. layout设计与开发
  5. login 设计与开发
  6. CURD页面的设计与开发
  7. 监控页面的设计与开发
  8. 富文本编辑器的使用与页面设开发设计
  9. 主题切换的设计与开发并页面
  10. 水印切换的设计与开发
  11. 全屏与取消全屏
  12. 开发提效之一键生成模块(页面)
相关推荐
百万蹄蹄向前冲43 分钟前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5811 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路1 小时前
GeoTools 读取影像元数据
前端
ssshooter2 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
你的人类朋友2 小时前
【Node.js】什么是Node.js
javascript·后端·node.js
Jerry3 小时前
Jetpack Compose 中的状态
前端
dae bal3 小时前
关于RSA和AES加密
前端·vue.js
柳杉4 小时前
使用three.js搭建3d隧道监测-2
前端·javascript·数据可视化
lynn8570_blog4 小时前
低端设备加载webp ANR
前端·算法
LKAI.4 小时前
传统方式部署(RuoYi-Cloud)微服务
java·linux·前端·后端·微服务·node.js·ruoyi