vue-admin-template+Datav实现可视化大屏(亲测可实现)

vue-admin-template+Datav实现可视化大屏
效果图:在这里插入图片描述
在这里插入图片描述

DataV官网链接:http://datav.jiaminghi.com/guide/
vue-admin-template连接:https://github.com/PanJiaChen
在这里插入图片描述
下载基础版本的即可;vue-admin-template的下载配置就不说啦,整好后安装Datav:

npm install @jiaminghi/data-view

然后在vue-admin-template-master\src\main.js文件中注册

import Vue from 'vue'

import 'normalize.css/normalize.css' // A modern alternative to CSS resets

import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import locale from 'element-ui/lib/locale/lang/en' // lang i18n
//引入dataV样式
// 将自动注册所有组件为全局组件
import './assets/common.less'

import dataV from '@jiaminghi/data-view'

Vue.use(dataV)

然后直接写,我是在这个文件下面:vue-admin-template-master\src\views\visualization\index.vue

<template>
    <div class="content bg">
      <!-- 全屏容器 -->
      <dv-full-screen-container>
        <!-- 第一行 -->
        <div class="module_box" style="height: 10vh;">
          <div style="flex: 0 1 30%;">
            <dv-decoration-10 style="width:100%;height:50px;" />
          </div>
          <div style="flex: 0 1 40%;">
            <div style="display: flex;width: 100%;">
              <dv-decoration-8 style="width:300px;height:50px;flex:1;transform: rotateY(180deg);" />
              <dv-decoration-11 style="width:200px;height:60px;flex:1">肉鸡表型数据中心</dv-decoration-11>
              <dv-decoration-8 style="width:300px;height:50px;flex:1" />
            </div>
          </div>
          <div style="flex: 0 1 30%;">
            <dv-decoration-10 style="width: 100%;height:50px;transform: rotateY(180deg);" />
          </div>
        </div>
        <!-- 第二行 -->
        <div class="module_box" style="height:60vh;">
                    <!-- flex布局 一行四个 各占25% -->
            <!-- 左 -->
          <div style="flex: 0 1 25%;">
              <dv-border-box-1 style="width: 100%;height: 100%;">
                <dv-capsule-chart v-if="!listLoading" :config="config2" style="width:90%;height:86%" />
              </dv-border-box-1>
              <!-- <dv-border-box-2 style="width: 100%;height: 40%;">
                <dv-conical-column-chart :config="config5" style="width:90%;height:90%;" />
              </dv-border-box-2> -->
            </div>
          <!-- 中 -->
          <div style="flex: 0 1 50%;">
            <dv-border-box-12 style="width: 100%;height: 100%">
              <dv-active-ring-chart v-if="!listLoading" :config="config4" style="width:95%;height:95%" />
            </dv-border-box-12>
          </div>
          <!-- 右 -->
          <div style="flex: 0 1 25%;">
            <dv-border-box-8 style="width: 100%;height: 100%">
              <dv-scroll-ranking-board v-if="!listLoading" :config="config2" style="width:90%;height:90%" />
            </dv-border-box-8>
          </div>
        </div>
                <!-- 第三行 -->
          <div class="module_box" style="height: 30vh;">
            <!-- flex布局 一行四个 各占25% -->
            <!-- 左 -->
            <div style="flex: 0 1 75%;">
              <dv-border-box-10 style="width: 100%;height: 200px;">
                <dv-conical-column-chart v-if="!listLoading" :config="config2" style="width:90%;height:100%" />
              </dv-border-box-10>
            </div>
            <!-- 中 -->
            <!-- <div style="flex: 0 1 25%;">
              <dv-border-box-13 style="width: 100%;height: 200px;">
                <dv-active-ring-chart :config="config8" style="width:100%;height:100%" />
              </dv-border-box-13>
            </div> -->
            <!-- 右 -->
             <div style="flex: 0 1 25%;">
              <dv-border-box-13 style="width: 100%;height: 200px;">
                <dv-percent-pond v-if="!listLoading" :config="config3" style="width:200px;height:100px;"/>
              </dv-border-box-13>
            </div>
          </div>
      </dv-full-screen-container>
    </div>
  </template>
  
  <script>
  import api from '@/api/datav';
  
  export default {
    name: 'HomeView',
    data() {
      return {
        listLoading: true,
        config2: {
          data: [
          ]
        },
        config3: {
          value: 80,
          borderWidth: 5,
          borderRadius: 10,
          borderGap: 5,
          backgroundColor: '#0f0', // 添加背景颜色
          borderColor: '#00f', // 添加边框颜色
          fontColor: '#fff', // 添加字体颜色
          fontSize: 30 // 添加字体大小
  },
        config4: {
          radius: '65%',
          activeRadius: '70%',
          data: [
          ],
          digitalFlopStyle: {
      fontSize: 30,
      lineWidth: 30,
      showOriginValue: true
    }
        }  // 确保 config4 被正确初始化,即使它现在可能是空的或未被使用
      };
    },
    created() {
      this.fetchData();
    },
    methods: {
      fetchData() {
        this.listLoading = true;
        api.findAllInfoOrder().then(response => {
          if (response && response.data && response.code === 200) {
            console.log(response.data); // 打印数据
            this.config2.data = this.formatData(response.data);
            this.config4.data = this.formatData(response.data);
            this.listLoading = false;
          } else {
            console.error('Failed to fetch data:', response.data ? response.message : 'No response data');
            this.listLoading = false;
          }
        }).catch(error => {
          console.error('Error during data fetch:', error);
          this.listLoading = false;
        });
      },
      formatData(rawData) {
        if (Array.isArray(rawData)) {
          // 如果原始数据已经是数组,则直接返回
          return rawData;
        } else {
          // 否则,格式化数据
          return Object.entries(rawData).map(([name, value]) => ({
            name,
            value
          }));
        }
      }
    }
  }
  </script>
  
  <style>
  .container {
    width: 100vw;
    height: 100vh;
    box-sizing: border-box;
  }
  
  #dv-full-screen-container {
    height: 100vh !important;
  }
  
  * {
    margin: 0;
    padding: 0;
  }
  
  /* 主体 */
  .content {
    color: #fff;
    background: #000;
    width: 100vw;
    height: 100vh;
  }
  
  .bg {
    background: url(../../assets/images/bg.jpg) center center;
    background-size: cover;
  }
  
  .module_box {
    display: flex;
    justify-content: space-between;
    margin: 5px;
  }
  
  .border-box-content {
    display: flex;
    justify-content: center;
    align-items: center;
  }
  </style>
  

在这里插入图片描述
这个是一个全屏的可视化界面,我设置的都是width: 100vw、height: 100vh;但是vue-admin-template他自己带了原有的侧边栏和头部,写好后会导致有部分被遮挡,所以我们如果需要在大屏幕上展示的话,有两种方案:1、需要重新打开一个界面来进行展示;2、对界面进行调整,使其适应界面主主体主体的大小。我们依次介绍:
第一种方法:打开一个界面来进行展示:
由于vue-admin-template的侧边栏是通过路由直接控制注入的,因此可以通过在路由中添加一个属性来决定是否在新窗口中打开页面。可以在路由配置中添加 target 属性,并在 SidebarItem 组件中根据这个属性来决定是否在新窗口中打开链接。
在路由中vue-admin-template-master\src\router\index.js添加target属性

  {
    path: '/visualization',
    name: 'Visualization',
    component: () => import('@/views/visualization/index'),
    meta: { title: '可视化-全屏', icon: 'dashboard', target: '_blank' }
  },

修改 SidebarItem 组件:
在 SidebarItem 组件中,根据 target 属性决定链接的打开方式:

<template>
  <div v-if="!item.hidden">
    <template v-if="hasOneShowingChild(item.children, item) && (!onlyOneChild.children || onlyOneChild.noShowingChildren) && !item.alwaysShow">
      <Link v-if="onlyOneChild.meta" :to="resolvePath(onlyOneChild.path)" :target="onlyOneChild.meta.target">
        <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown': !isNest}">
          <Item :icon="onlyOneChild.meta.icon || (item.meta && item.meta.icon)" :title="onlyOneChild.meta.title" />
        </el-menu-item>
      </Link>
    </template>
    <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
      <template slot="title">
        <Item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
      </template>
      <sidebar-item
        v-for="child in item.children"
        :key="child.path"
        :is-nest="true"
        :item="child"
        :base-path="resolvePath(child.path)"
        class="nest-menu"
      />
    </el-submenu>
  </div>
</template>

<script>
import path from 'path'
import { isExternal } from '@/utils/validate'
import Item from './Item'
import Link from './Link'
import FixiOSBug from './FixiOSBug'

export default {
  name: 'SidebarItem',
  components: { Item, Link },
  mixins: [FixiOSBug],
  props: {
    item: {
      type: Object,
      required: true
    },
    isNest: {
      type: Boolean,
      default: false
    },
    basePath: {
      type: String,
      default: ''
    }
  },
  data() {
    this.onlyOneChild = null
    return {}
  },
  methods: {
    hasOneShowingChild(children = [], parent) {
      const showingChildren = children.filter(item => {
        if (item.hidden) {
          return false
        } else {
          this.onlyOneChild = item
          return true
        }
      })

      if (showingChildren.length === 1) {
        return true
      }

      if (showingChildren.length === 0) {
        this.onlyOneChild = { ...parent, path: '', noShowingChildren: true }
        return true
      }

      return false
    },
    resolvePath(routePath) {
      if (isExternal(routePath)) {
        return routePath
      }
      if (isExternal(this.basePath)) {
        return this.basePath
      }
      return path.resolve(this.basePath, routePath)
    }
  }
}
</script>


修改 Link.vue 组件
在 Link.vue 组件中,根据 to 属性的值决定是否在新窗口中打开链接。

<template>
  <component :is="type" v-bind="linkProps(to)">
    <slot />
  </component>
</template>

<script>
import { isExternal } from '@/utils/validate'

export default {
  props: {
    to: {
      type: String,
      required: true
    },
    target: {
      type: String,
      default: '_self'
    }
  },
  computed: {
    isExternal() {
      return isExternal(this.to)
    },
    type() {
      if (this.isExternal) {
        return 'a'
      }
      return 'router-link'
    }
  },
  methods: {
    linkProps(to) {
      if (this.isExternal) {
        return {
          href: to,
          target: this.target,
          rel: 'noopener'
        }
      }
      return {
        to: to,
        target: this.target
      }
    }
  }
}
</script>


第二种方法:对界面进行调整,使其适应vue-admin-template框架界面主体的大小。
这个直接上代码就行,修改点样式即可

<template>
    <div class="app-container">
      <div class="content bg">
        <!-- 第一行 -->
        <div class="module_box" style="height: 10%;">
          <div style="flex: 0 1 30%;">
            <dv-decoration-10 style="width:100%;height:50px;" />
          </div>
          <div style="flex: 0 1 40%;">
            <div style="display: flex;width: 100%;">
              <dv-decoration-8 style="width:300px;height:50px;flex:1;transform: rotateY(180deg);" />
              <dv-decoration-11 style="width:200px;height:60px;flex:1">肉鸡表型数据中心</dv-decoration-11>
              <dv-decoration-8 style="width:300px;height:50px;flex:1" />
            </div>
          </div>
          <div style="flex: 0 1 30%;">
            <dv-decoration-10 style="width: 100%;height:50px;transform: rotateY(180deg);" />
          </div>
        </div>
        <!-- 第二行 -->
        <div class="module_box" style="height:60%;">
                    <!-- flex布局 一行四个 各占25% -->
            <!-- 左 -->
          <div style="flex: 0 1 25%;">
              <dv-border-box-1 style="width: 100%;height: 100%;">
                <dv-capsule-chart v-if="!listLoading" :config="config2" style="width:90%;height:86%" />
              </dv-border-box-1>
              <!-- <dv-border-box-2 style="width: 100%;height: 40%;">
                <dv-conical-column-chart :config="config5" style="width:90%;height:90%;" />
              </dv-border-box-2> -->
            </div>
          <!-- 中 -->
          <div style="flex: 0 1 50%;">
            <dv-border-box-12 style="width: 100%;height: 100%">
              <dv-active-ring-chart v-if="!listLoading" :config="config4" style="width:95%;height:95%" />
            </dv-border-box-12>
          </div>
          <!-- 右 -->
          <div style="flex: 0 1 25%;">
            <dv-border-box-8 style="width: 100%;height: 100%">
              <dv-scroll-ranking-board v-if="!listLoading" :config="config2" style="width:90%;height:90%" />
            </dv-border-box-8>
          </div>
        </div>
                <!-- 第三行 -->
          <div class="module_box" style="height: 30%;">
            <!-- flex布局 一行四个 各占25% -->
            <!-- 左 -->
            <div style="flex: 0 1 75%;">
              <dv-border-box-10 style="width: 100%;height: 200px;">
                <dv-conical-column-chart v-if="!listLoading" :config="config2" style="width:90%;height:100%" />
              </dv-border-box-10>
            </div>
            <!-- 中 -->
            <!-- <div style="flex: 0 1 25%;">
              <dv-border-box-13 style="width: 100%;height: 200px;">
                <dv-active-ring-chart :config="config8" style="width:100%;height:100%" />
              </dv-border-box-13>
            </div> -->
            <!-- 右 -->
             <div style="flex: 0 1 25%;">
              <dv-border-box-13 style="width: 100%;height: 200px;">
                <dv-percent-pond v-if="!listLoading" :config="config3" style="width:200px;height:100px;"/>
              </dv-border-box-13>
            </div>
          </div>
      </div>
    </div>
  </template>
  
  <script>
  import api from '@/api/datav';
  
  export default {
    name: 'HomeView',
    data() {
      return {
        listLoading: true,
        config2: {
          data: [
          ]
        },
        config3: {
          value: 80,
          borderWidth: 5,
          borderRadius: 10,
          borderGap: 5,
          backgroundColor: '#0f0', // 添加背景颜色
          borderColor: '#00f', // 添加边框颜色
          fontColor: '#fff', // 添加字体颜色
          fontSize: 30 // 添加字体大小
  },
        config4: {
          radius: '65%',
          activeRadius: '70%',
          data: [
          ],
          digitalFlopStyle: {
      fontSize: 30,
      lineWidth: 30,
      showOriginValue: true
    }
        }  // 确保 config4 被正确初始化,即使它现在可能是空的或未被使用
      };
    },
    created() {
      this.fetchData();
    },
    methods: {
      fetchData() {
        this.listLoading = true;
        api.findAllInfoOrder().then(response => {
          if (response && response.data && response.code === 200) {
            console.log(response.data); // 打印数据
            this.config2.data = this.formatData(response.data);
            this.config4.data = this.formatData(response.data);
            this.listLoading = false;
          } else {
            console.error('Failed to fetch data:', response.data ? response.message : 'No response data');
            this.listLoading = false;
          }
        }).catch(error => {
          console.error('Error during data fetch:', error);
          this.listLoading = false;
        });
      },
      formatData(rawData) {
        if (Array.isArray(rawData)) {
          // 如果原始数据已经是数组,则直接返回
          return rawData;
        } else {
          // 否则,格式化数据
          return Object.entries(rawData).map(([name, value]) => ({
            name,
            value
          }));
        }
      }
    }
  }
  </script>
  
  <style>
  .container {
    width: 100%;
    height: calc(100vh - 84px);
    box-sizing: border-box;
  }
  
  #dv-full-screen-container {
    height: 100vh !important;
  }
  
  * {
    margin: 0;
    padding: 0;
  }
  
  /* 主体 */
  .content {
    color: #fff;
    background: #000;
    width: 100%;
    height: calc(100vh - 84px);
  }
  
  .bg {
    background: url(../../assets/images/bg.jpg) center center;
    background-size: cover;
  }
  
  .module_box {
    display: flex;
    justify-content: space-between;
    margin: 5px;
  }
  
  .border-box-content {
    display: flex;
    justify-content: center;
    align-items: center;
  }
  </style>
  

效果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值