大致流程是:

main组件{
		卡片组件
		折线图组件
}
main组件包含了折线图的所有数据(4种),
当卡片组件点击时通过$emit调用父组件中的方法切换折线图的数据种类达到切换的效果,
折线图组件种包含了折线图的各种基本数据,以及x轴坐标号,
折线图加载以后,查询数据,存入标号。。调用父组件方法,传输查询到的数据,将数据放进数据区;记得在初始化的时候把初始化组件放进请求里,不然初始化的时候请求还没回来,数据还没有被改变。x坐标初始化就读取了空数据

入口:

<template>
  <div class="dashboard-editor-container">
    <github-corner class="github-corner" />
    <line-chart v-if="false" @handlePushLineChartData="handlePushLineChartData" />
    <panel-group @handleSetLineChartData="handleSetLineChartData" />
    <el-row style="background:#ffffff;padding:16px 16px 0;margin-bottom:32px;">
      <line-chart :chart-data="lineChartData" />
    </el-row>
    <el-row :gutter="32">
      <el-col :xs="24" :sm="24" :lg="8">
        <div class="chart-wrapper">
          <raddar-chart />
        </div>
      </el-col>
      <el-col :xs="24" :sm="24" :lg="8">
        <div class="chart-wrapper">
          <pie-chart />
        </div>
      </el-col>
      <el-col :xs="24" :sm="24" :lg="8">
        <div class="chart-wrapper">
          <bar-chart />
        </div>
      </el-col>
    </el-row>

    <el-row :gutter="8">
      <el-col :xs="{span: 24}" :sm="{span: 24}" :md="{span: 24}" :lg="{span: 12}" :xl="{span: 12}" style="padding-right:8px;margin-bottom:30px;">
        <transaction-table />
      </el-col>
      <el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;">
        <todo-list />
      </el-col>
      <el-col :xs="{span: 24}" :sm="{span: 12}" :md="{span: 12}" :lg="{span: 6}" :xl="{span: 6}" style="margin-bottom:30px;">
        <box-card />
      </el-col>
    </el-row>
  </div>
</template>

<script>
// import GithubCorner from '@/components/GithubCorner'
import PanelGroup from './components/PanelGroup'
import LineChart from './components/LineChart'
import RaddarChart from './components/RaddarChart'
import PieChart from './components/PieChart'
import BarChart from './components/BarChart'
// import TransactionTable from './components/TransactionTable'
// import TodoList from './components/TodoList'
// import BoxCard from './components/BoxCard'

const lineChartData = {
  // 多个可选项,选中哪个就展示哪个里面的数组为折线图效果
  userTotalDayOfMonth: {
    expectedData: [],
    actualData: [1, 2, 3, 1, 2, 3, 1, 1, 1, 1]
  },
  newUserDayOfMonth: {
    expectedData: [],
    actualData: []
  },
  activeDayOfMonth: {
    expectedData: [],
    actualData: []
  },
  serverRequestDayOfMonth: {
    expectedData: [],
    actualData: []
  }
}

export default {
  name: 'DashboardAdmin',
  components: {
    // GithubCorner,
    PanelGroup,
    LineChart,
    RaddarChart,
    PieChart,
    BarChart
    // TransactionTable
    // TodoList
    // BoxCard
  },
  data() {
    return {
      // 这里默认展示第一个数据
      lineChartData: lineChartData.userTotalDayOfMonth,
      // 预置一个号数
      maxDay: 0
    }
  },
  created() {
    // 初始化数据查询

  },
  methods: {
    // 调用变化线型图,给4个数据卡片调用的,卡片调用的时候就加载卡片传过来的数据
    handleSetLineChartData(type) {
      console.log('折线图切换被子组件调用')
      // 根据子集的调用切换对应的数据,
      this.lineChartData = lineChartData[type]
    },
    handlePushLineChartData(data) {
      console.log('折线图收到子组件传来的数据')
      this.userTotalDayOfMonth = data.userTotalDayOfMonth
      this.newUserDayOfMonth = data.newUserDayOfMonth
      this.activeDayOfMonth = data.activeDayOfMonth
      this.serverRequestDayOfMonth = data.serverRequestDayOfMonth
    }
  }
}
</script>

<style lang="scss" scoped>
.dashboard-editor-container {
  padding: 32px;
  background-color: rgb(240, 242, 245);
  position: relative;

  .github-corner {
    position: absolute;
    top: 0;
    border: 0;
    right: 0;
  }

  .chart-wrapper {
    background: #fff;
    padding: 16px 16px 0;
    margin-bottom: 32px;
  }
}

@media (max-width:1024px) {
  .chart-wrapper {
    padding: 8px;
  }
}
</style>

折线图LineChart:

<template>
  <div :class="className" :style="{height:height,width:width}" />
</template>

<script>
import echarts from 'echarts'
require('echarts/theme/macarons') // echarts theme
import resize from './mixins/resize'
import { getLineChartApi } from '@/api/dataStatistics/data-statistics'

export default {
  mixins: [resize],
  props: {
    className: {
      type: String,
      default: 'chart'
    },
    width: {
      type: String,
      default: '100%'
    },
    height: {
      type: String,
      default: '350px'
    },
    autoResize: {
      type: Boolean,
      default: true
    },
    chartData: {
      type: Object,
      required: true
    }
  },
  data() {
    return {
      chart: null,
      daySize: []
    }
  },
  watch: {
    chartData: {
      deep: true,
      handler(val) {
        console.log('Panel组件点击卡片时触发Line组件调用x轴初始化')
        this.setOptions(val)
      }
    }
  },
  created() {
    console.log('created')
  },
  activated() {
    console.log('activated')
    this.getLineChar()
  },
  mounted() {
    console.log('mounted')
    // 等待一切加载完成后调用初始化方法
    this.$nextTick(() => {
      console.log('mounted')
      this.getLineChar()
      // this.initChart()
    })
  },
  beforeDestroy() {
    console.log('beforeDestroy')
    if (!this.chart) {
      return
    }
    this.chart.dispose()
    this.chart = null
  },
  methods: {
    handlePushLineChartData(data) {
      this.$emit('handlePushLineChartData', data)
    },
    // 获取当前月份数据
    getLineChar() {
      getLineChartApi(new Date().getTime()).then(response => {
        this.daySize = response.data.daySize
        this.initChart()
        console.log(response)
        this.handlePushLineChartData(response.data)
      })
    },
    initChart() {
      console.log('初始化方法')
      this.chart = echarts.init(this.$el, 'macarons')
      this.setOptions(this.chartData)
    },
    setOptions({ expectedData, actualData } = {}) {
      console.log('x轴分区被初始化')
      this.chart.setOption({
        xAxis: {
          // data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
          // 线表的x轴分区
          data: this.daySize,
          boundaryGap: false,
          axisTick: {
            show: false
          }
        },
        grid: {
          left: 10,
          right: 10,
          bottom: 20,
          top: 30,
          containLabel: true
        },
        tooltip: {
          trigger: 'axis',
          axisPointer: {
            type: 'cross'
          },
          padding: [5, 10]
        },
        yAxis: {
          axisTick: {
            show: false
          }
        },
        legend: {
          data: ['expected', 'actual']
        },
        // 图表描述
        series: [{
          name: 'expected', itemStyle: {
            normal: {
              color: '#ff00aa',
              lineStyle: {
                color: '#ff0015',
                width: 2
              }
            }
          },
          // 柔性过过渡
          smooth: true,
          type: 'line',
          data: expectedData,
          animationDuration: 2800,
          animationEasing: 'cubicInOut'
        },
        {
          name: 'actual',
          smooth: true,
          type: 'line',
          itemStyle: {
            normal: {
              color: '#3888fa',
              lineStyle: {
                color: '#3888fa',
                width: 2
              },
              areaStyle: {
                color: '#f3f8ff'
              }
            }
          },
          data: actualData,
          animationDuration: 2800,
          animationEasing: 'quadraticOut'
        }]
      })
    }
  }
}
</script>

数据卡片PanelGroup:

<template>
  <el-row :gutter="40" class="panel-group">
    <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
      <div class="card-panel" @click="handleSetLineChartData('userTotal')">
        <div class="card-panel-icon-wrapper icon-people">
          <svg-icon icon-class="peoples" class-name="card-panel-icon" />
        </div>
        <div class="card-panel-description">
          <div class="card-panel-text">
            User Total
          </div>
          <!--数字动态增加效果由于组件存在数字过大数字加载不完的BUG,这边使用-10000,由于数字负数会导致错误,所以使用三元运算计算合适字符-->
          <count-to :start-val="panelGroup.totalUser<10000?0:panelGroup.totalUser-10000" :end-val="panelGroup.totalUser" :duration="3000" class="card-panel-num" />
        </div>
      </div>
    </el-col>
    <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
      <div class="card-panel" @click="handleSetLineChartData('newUserToday')">
        <div class="card-panel-icon-wrapper icon-message">
          <svg-icon icon-class="user" class-name="card-panel-icon" />
        </div>
        <div class="card-panel-description">
          <div class="card-panel-text">
            New User Today
          </div>
          <count-to :start-val="panelGroup.newUserToday<10000?0:panelGroup.newUserToday-10000" :end-val="panelGroup.newUserToday" :duration="3000" class="card-panel-num" />
        </div>
      </div>
    </el-col>
    <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
      <div class="card-panel" @click="handleSetLineChartData('activeToday')">
        <div class="card-panel-icon-wrapper icon-money">
          <svg-icon icon-class="star" class-name="card-panel-icon" />
        </div>
        <div class="card-panel-description">
          <div class="card-panel-text">
            Active Today
          </div>
          <count-to :start-val="panelGroup.activeToday<10000?0:panelGroup.activeToday-10000" :end-val="panelGroup.activeToday" :duration="3000" class="card-panel-num" />
        </div>
      </div>
    </el-col>
    <el-col :xs="12" :sm="12" :lg="6" class="card-panel-col">
      <div class="card-panel" @click="handleSetLineChartData('serverTodayRequest')">
        <div class="card-panel-icon-wrapper icon-shopping">
          <svg-icon icon-class="international" class-name="card-panel-icon" />
        </div>
        <div class="card-panel-description">
          <div class="card-panel-text">
            Server Today Request
          </div>
          <count-to :start-val="panelGroup.todayRequest<10000?0:panelGroup.todayRequest-10000" :end-val="panelGroup.todayRequest" :duration="3000" class="card-panel-num" />
        </div>
      </div>
    </el-col>
  </el-row>
</template>

<script>
import CountTo from 'vue-count-to'
import { getPanelGroupApi } from '@/api/dataStatistics/data-statistics.js'

export default {
  components: {
    CountTo
  },
  data: function() {
    return {
      panelGroup: {
        totalUser: 0,
        newUserToday: 0,
        activeToday: 0,
        todayRequest: 0
      }
    }
  },
  created() {
    // 页面初始化钩子
    this.getPanelGroup()
  },
  activated() {
    // 组件刷新钩子,由于组件被调用时不会触发初始化钩子,这里添加一个刷新的函数
    this.getPanelGroup()
  },
  methods: {
    handleSetLineChartData(type) {
      // 调用父组件的指定方法,传入参数
      this.$emit('handleSetLineChartData', type)
    },
    // 获取4个基本数据
    getPanelGroup() {
      getPanelGroupApi().then(response => {
        this.alertMsg(response)
        this.panelGroup.totalUser = response.data.totalUser
        this.panelGroup.activeToday = response.data.activeToday
        this.panelGroup.newUserToday = response.data.newUserToday
        this.panelGroup.todayRequest = response.data.todayRequest
      })
    },
    // 根据响应体弹窗
    alertMsg(response) {
      const { flag, message } = response
      // 预置一个响应消息类型
      let msgType
      // 根据响应类型动态设置窗体样式
      if (flag) {
        msgType = 'success'
      } else {
        msgType = 'error'
      }
      // 响应消息弹窗展示
      this.$message({
        message: message,
        type: msgType
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.panel-group {
  margin-top: 18px;

  .card-panel-col {
    margin-bottom: 32px;
  }

  .card-panel {
    height: 108px;
    cursor: pointer;
    font-size: 12px;
    position: relative;
    overflow: hidden;
    color: #666;
    background: #fff;
    box-shadow: 4px 4px 40px rgba(0, 0, 0, .05);
    border-color: rgba(0, 0, 0, .05);

    &:hover {
      .card-panel-icon-wrapper {
        color: #ffffff;
      }

      .icon-people {
        background: #40c9c6;
      }

      .icon-message {
        background: #11b41d;
      }

      .icon-money {
        background: #f3a85f;
      }

      .icon-shopping {
        background: #2ea2ff
      }
    }

    .icon-people {
      color: #40c9c6;
    }

    .icon-message {
      color: #11b41d;
    }

    .icon-money {
      color: #f3a85f;
    }

    .icon-shopping {
      color: #2ea2ff
    }

    .card-panel-icon-wrapper {
      float: left;
      margin: 14px 0 0 14px;
      padding: 16px;
      transition: all 0.38s ease-out;
      border-radius: 6px;
    }

    .card-panel-icon {
      float: left;
      font-size: 48px;
    }

    .card-panel-description {
      float: right;
      font-weight: bold;
      margin: 26px;
      margin-left: 0px;

      //
      .card-panel-text {
        line-height: 18px;
        color: rgba(0, 0, 0, 0.45);
        font-size: 16px;
        margin-bottom: 12px;
      }
      //字体大小
      .card-panel-num {
        font-size: 20px;
      }
    }
  }
}

@media (max-width:550px) {
  .card-panel-description {
    display: none;
  }

  .card-panel-icon-wrapper {
    float: none !important;
    width: 100%;
    height: 100%;
    margin: 0 !important;

    .svg-icon {
      display: block;
      margin: 14px auto !important;
      float: none !important;
    }
  }
}
</style>
Logo

前往低代码交流专区

更多推荐