likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 1

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

🧠 - 简介

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

效果图如下:

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

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

👁️ - 分析

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

🫀 - 拆解

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

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,里面存放一些常见的配置。

💪 - 落实

<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>

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

<div
  :id="chartId"
  class="chart-card-content"
/>

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

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

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. 开发提效之一键生成模块(页面)