项目看板开发经验分享(一)——光伏绿色能源看板

news2024/12/28 19:56:10

今天新开一个系列,专门介绍近期工作中开发的几个比较酷炫的看板的开发思路与经验分享。第一节我们就来介绍下这个光伏绿色能源看板,整体浏览如下:

在这里插入图片描述


那就直接进入正题吧——

0、可复用组件panel

在讲解各个模块之前,我们先来完成一个安放每个模块title标题的可复用组件:panel
在这里插入图片描述
在同一个甚至不同看板内要多次重复使用的样式,将其做成组件会省事很多,这也是面试题中常出现的组件的可重用性。

在蓝湖上ued提供的两张图
在这里插入图片描述

引入panel文件:

import panel from './components/panel';

export default {
  name: "kanban_photovoltaic_energy",
  components: {
    panel
  },

 ...

组件完整代码:

<template>
  <div class="photovoltaic_panel">
    <div class="title">
      <div class="arrow"></div>
      <div class="title_text">{{title}}</div>
    </div>
    <div class="underline" :style="`width:${underlineWidth}`"></div>
    <slot></slot>
    <!-- `slot`插槽为未来的组件扩展占个地,但按理来说基本用不到 -->
  </div>
</template>
  <script> 
export default {
  props: {
    title: {
      type: String,
      default: () => {
        return '表头';
      }
    },
    underlineWidth: {
      type: String,
      default: () => {
        return '456px';
      }
    }
  }
};
  </script>
  <style lang="less">
.photovoltaic_panel {
  overflow: hidden;
  .title {
    font-size: 18px;
    color: rgba(255, 255, 255, 0.85);
    display: flex;
    line-height: 34px;
    margin-bottom: 4px;
    .arrow {
      width: 18px;
      height: 34px;
      background-image: url(./../../../assets/photovoltaicEnergy/panel_arrow.png);
      background-repeat: no-repeat;
      background-size: 100% 100%;
      margin-right: 8px;
    }
  }
  .underline {
    width: 456px;
    height: 7px;
    background-image: url(./../../../assets/photovoltaicEnergy/panel_underline.png);
    background-repeat: no-repeat;
    background-size: 100% 100%;
  }
}
</style>

看板中调用:

   <panel :title="'园区概况'"></panel>

在这里插入图片描述


1、动态背景background

该看板在开启时会调用天气接口获取当天天气,并根据不同的天气给看板表层加不同滤镜,例如:

晴天
在这里插入图片描述

雨天
在这里插入图片描述

近三天的天气会反映在右上角的环境监测里
在这里插入图片描述

来看看这部分怎么实现,首先我们看一下后端给我们的天气接口:
在这里插入图片描述

不难发现对我们有用的只有:

private String textDay; //预报白天天气状况文字描述,包括阴晴雨雪等天气状态的描述
private String tempMax; //预报当天最高温度
private String tempMin; //预报当天最低温度

然而textDay的天气类型有几十种,而我们看板上需要显示的只有阴、雨、晴三种

在这里插入图片描述

此时该怎么办呢?不要犹豫,直接去找产品询问取值规则:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

ok,明白取值规则后,封装一个简单的判断天气的函数:

    // 判断天气
    setWeather(name) {
      let type = '';
      if (name.indexOf('晴') != -1) {
        type = 'sunny';
      } else if (name.indexOf('雨') != -1) {
        type = 'rain';
      } else {
        type = 'cloudy';
      }
      return type
    },

然后在生命周期mounted内执行的search()函数中获取天气:

    search() {
      // 获取城市天气情况
      axios.getWeather().then((res) => {
        if (res && res.data.body.length) {
          this.todayWeather = this.setWeather(res.data.body[0].textDay); // todayWeather用来判断背景图
          for (let i = 0; i < 3; i++) {
            // 数组weatherData用来渲染右上环境监测的数据
            this.weatherData[i].type = this.setWeather(res.data.body[i].textDay);
            this.weatherData[i].wheatherName = res.data.body[i].textDay;
            this.weatherData[i].temp_min = res.data.body[i].tempMin;
            this.weatherData[i].temp_max = res.data.body[i].tempMax;
          }
        }
      })
      
      // ......
    }

动态背景的实现:在该vue文件最外层的div标签(或占据整个看板全屏的标签)上加一个动态style控制backgroundImage属性:

    <div
      class="kanban_photovoltaic_energy"
      v-loading="loading"
      element-loading-text="loading..."
      element-loading-background="rgba(0, 0, 0, 0.5)"
      :style="{backgroundImage:`url(${todayWeather=='cloudy'?backgroundImg.cloudy:todayWeather=='sunny'?backgroundImg.sunny:backgroundImg.rain})`}"
    >
    <!-- v-loading是elementui提供的加载动画 -->

根据todayWeather的不同而决定backgroundImg引用哪张图片。在data中:

backgroundImg: {
        cloudy: require('./../../assets/photovoltaicEnergy/bg_overcast.png'),
        sunny: require('./../../assets/photovoltaicEnergy/bg_sunny.png'),
        rain: require('./../../assets/photovoltaicEnergy/bg_rain.png'),
      },

当然不要忘了css中给该标签添加background-repeatbackground-size属性使得背景图片得以平铺:

.kanban_photovoltaic_energy {
  height: 1080px;
  width: 1920px;
  background-repeat: no-repeat;
  background-size: 100% 100%;
  
  ......

而右上角的环境监测模块则是直接根据包装处理好的weatherData数组搭配上v-forcss来完成:

标签

          <div class="right_top">
            <panel :title="'环境检测'" :underlineWidth="'503px'"></panel>
            <div class="weather">
              <div class="weather_box" v-for="(item, index) in weatherData" :key="index">
                <div class="label">{{item.label}}</div>
                <div class="line"></div>
                <div class="icon sunny" v-if="item.type == 'sunny'"></div>
                <div class="icon cloudy" v-if="item.type == 'cloudy'"></div>
                <div class="icon rain" v-if="item.type == 'rain'"></div>
                <div class="type">{{item.wheatherName}}</div>
                <div class="temp">{{item.temp_min}}-{{item.temp_max}}℃</div>
              </div>
            </div>
          </div>

css

      .right_top {
        .weather {
          height: 167px;
          display: flex; // 经典flex布局
          justify-content: space-around;
          .weather_box {
            text-align: center;
            .label {
              margin: 24px auto 8px;
            }
            .line {
              width: 36px;
              height: 2px;
              background-image: url(./../../assets/photovoltaicEnergy/weather_line.png);
              background-repeat: no-repeat;
              background-size: 100% 100%;
              margin: 0 auto 15px;
            }
            .icon {
              width: 24px;
              height: 24px;
              background-repeat: no-repeat;
              background-size: 100% 100%;
              margin: 0 auto 0;
            }
            .sunny {
              background-image: url(./../../assets/photovoltaicEnergy/icon_sunny.png);
            }
            .cloudy {
              background-image: url(./../../assets/photovoltaicEnergy/icon_cloudy.png);
            }
            .rain {
              background-image: url(./../../assets/photovoltaicEnergy/icon_rain.png);
            }
            .type {
              margin: 10px auto 12px;
            }
            .temp {
              margin: 0 auto 0;
            }
          }
        }
      }

第一个模块就完成了。


2、 左边一列

在这里插入图片描述
基本上也都是用v-for搭配css的flex布局完成,没什么好讲的直接上代码吧,看了代码就懂了。

html:

        <div class="body_left">
          <div class="left_top">
            <panel :title="'园区概况'"></panel>
            <div class="content">
              <div class="box" v-for="(item, index) in overviewData" :key="index">
                <img :src="item.img_url" />
                <div class="text">
                  <div class="title">{{item.title}}</div>
                  <div class="value">{{item.val}}</div>
                </div>
              </div>
            </div>
          </div>
          <div class="left_middle">
            <panel :title="'园区光伏信息'"></panel>
            <div class="info_top">
              <div class="base_days">
                <div class="base_text">设备已运行</div>
                <div class="days_val">
                  {{runningDays}}
                  <div class="unit"></div>
                </div>
              </div>
              <div class="pieChart" ref="pieChart"></div>
            </div>
            <div class="info_bottom">
              <div class="info_box" v-for="(item, index) in infoData" :key="index">
                <div class="label">{{item.label}}</div>
                <div class="value">{{item.val}}{{item.unit}}</div>
              </div>
            </div>
          </div>
          <div class="left_bottom">
            <panel :title="'社会贡献'"></panel>
            <div class="social_box">
              <div class="social_circle blue">
                节约标准煤
                <div class="social_val">{{socialData.savingCoal}}万吨</div>
                <img :src="socialArrow.blue" />
                1度电≈0.4kg
              </div>
              <div class="social_circle yellow">
                CO2减排
                <div class="social_val">{{socialData.savingCO2}}万吨</div>
                <img :src="socialArrow.yellow" />
                1度电≈0.997kg
              </div>
              <div class="social_circle green">
                等效植树
                <div class="social_val">{{socialData.planting}}亿棵</div>
                <img :src="socialArrow.green" />
                1度电≈106棵
              </div>
            </div>
          </div>
        </div>

date数据:

  data() {
    return {
      overviewData: [
        {
          prop: 'photovoltaicNum',
          title: '园区光伏板(块)',
          val: '--',
          img_url: require('./../../assets/photovoltaicEnergy/icon_photovoltaicNum.png'),
        },
        {
          prop: 'electricTotal',
          title: '累计发电量',
          val: '--万亿度',
          img_url: require('./../../assets/photovoltaicEnergy/icon_electricTotal.png'),
        },
        {
          prop: 'areaVoltaic',
          title: '园区总面积(m²)',
          val: '--',
          img_url: require('./../../assets/photovoltaicEnergy/icon_areaVoltaic.png'),
        },
        {
          prop: 'ongridTotal',
          title: '累计并网量',
          val: '--万亿度',
          img_url: require('./../../assets/photovoltaicEnergy/icon_ongridTotal.png'),
        },
      ],
      infoData: [
        {
          prop: 'yearElectric',
          label: '本年发电量',
          val: '--',
          unit: '万度',
        },
        {
          prop: 'yearElectric',
          label: '本年并网量',
          val: '--',
          unit: '万度',
        },
        {
          prop: 'yearElectric',
          label: '本月发电量',
          val: '--',
          unit: '万度',
        },
        {
          prop: 'yearElectric',
          label: '今日发电量',
          val: '--',
          unit: '万度',
        },
        {
          prop: 'yearElectric',
          label: '今日最大功率',
          val: '--',
          unit: '千瓦',
        },
        {
          prop: 'yearElectric',
          label: '本月最大功率',
          val: '--',
          unit: '千瓦',
        },
      ],
      socialData: {
        savingCoal: '--',
        savingCO2: '--',
        planting: '--',
      },
      socialArrow: {
        blue: require('./../../assets/photovoltaicEnergy/social_arrow_blue.png'),
        yellow: require('./../../assets/photovoltaicEnergy/social_arrow_yellow.png'),
        green: require('./../../assets/photovoltaicEnergy/social_arrow_green.png'),
      },
    };
  },

css:

    .body_left {
      float: left;
      width: 505px;
      height: 100%;
      padding: 104px 16px 0 23px;
      // background: rgba(0, 255, 255, 0.3);
      background: linear-gradient(270deg, rgba(5, 19, 53, 0) 0%, #000000 100%);
      .left_top {
        .content {
          height: 200px;
          width: 100%;
          display: flex;
          flex-wrap: wrap;
          padding: 19px 0 23px 16px;
          .box {
            width: 216px;
            height: 74px;
            margin-bottom: 10px;
            display: flex;
            img {
              width: 74px;
              height: 74px;
              margin-right: 8px;
            }
            .text {
              .title {
                height: 34px;
                line-height: 34px;
                color: rgba(151, 222, 255, 0.85);
                font-size: 14px;
              }
              .value {
                height: 32px;
                line-height: 32px;
                font-size: 22px;
              }
            }
          }
        }
      }
      .left_middle {
        .info_top {
          height: 162px;
          width: 100%;
          display: flex;
          justify-content: space-between;
          .base_days {
            width: 182px;
            height: 104px;
            margin-top: 50px;
            background-image: url(./../../assets/photovoltaicEnergy/base_img.png);
            background-repeat: no-repeat;
            background-size: 100% 100%;
            position: relative;
            .base_text {
              position: absolute;
              font-size: 14px;
              color: rgba(151, 222, 255, 0.85);
              left: 50%;
              transform: translateX(-50%);
              top: 18px;
            }
            .days_val {
              position: absolute;
              font-size: 30px;
              left: 50%;
              transform: translateX(-50%);
              top: -30px;
              display: flex;
              .unit {
                height: 35px;
                line-height: 35px;
                font-size: 14px;
                margin-left: 8px;
              }
            }
          }
          .pieChart {
            width: 260px;
            height: 162px;
          }
        }
        .info_bottom {
          height: 256px;
          padding: 20px 0 28px;
          display: flex;
          flex-wrap: wrap;
          justify-content: space-between;
          .info_box {
            width: 225px;
            height: 56px;
            line-height: 58px;
            font-size: 20px;
            background-image: url(./../../assets/photovoltaicEnergy/info_border.png);
            background-repeat: no-repeat;
            background-size: 100% 100%;
            display: flex;
            justify-content: space-around;
            .label {
              font-size: 15px;
              color: rgba(151, 222, 255, 0.85);
            }
          }
        }
      }
      .left_bottom {
        .social_box {
          height: 138px;
          margin-top: 23px;
          display: flex;
          justify-content: space-between;
          .blue {
            background-image: url(./../../assets/photovoltaicEnergy/circle_blue.png);
            color: rgba(0, 158, 250, 1);
          }
          .yellow {
            background-image: url(./../../assets/photovoltaicEnergy/circle_yellow.png);
            color: rgba(231, 197, 66, 1);
          }
          .green {
            background-image: url(./../../assets/photovoltaicEnergy/circle_green.png);
            color: rgba(16, 178, 143, 1);
          }
          .social_circle {
            height: 138px;
            width: 138px;
            background-repeat: no-repeat;
            background-size: 100% 100%;
            text-align: center;
            font-size: 15px;
            padding-top: 40px;
            .social_val {
              font-size: 22px;
              margin-top: 12px;
              color: rgba(255, 255, 255, 0.85);
            }
            img {
              display: block;
              width: 12px;
              height: 15px;
              margin: 45px auto 6px;
            }
          }
        }
      }
    }

这一块的3D饼图我建议是百度找个案例直接照搬一下,我自己也是复制粘贴后修改数据弄出来的,这玩意代码太长了,不复杂就是很费时间,建议直接ctrl c + ctrl v一下
在这里插入图片描述


3、右边一列

待更新

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/164610.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mybatis 框架下 SQL 注入攻击的 3 种方式

SQL注入漏洞作为WEB安全的最常见的漏洞之一&#xff0c;在java中随着预编译与各种ORM框架的使用&#xff0c;注入问题也越来越少。 新手代码审计者往往对Java Web应用的多个框架组合而心生畏惧&#xff0c;不知如何下手&#xff0c;希望通过Mybatis框架使用不当导致的SQL注入问…

Node.js学习笔记

Node.js学习笔记 浏览器的内核包括两部分核心&#xff1a;DOM渲染引擎、JavaScript解析引擎。脱离浏览器环境也可以运行JavaScript&#xff0c;只要有JavaScript引擎就可以。 Node.js是一个基于Chrome V8引擎的JavaScript运行环境。Node.js内置了Chrome的V8 引擎&#xff0c;…

SpringBoot项目部署

系列文章目录 Spring Boot[概述、功能、快速入门]_心态还需努力呀的博客-CSDN博客 Spring Boot读取配置文件内容的三种方式_心态还需努力呀的博客-CSDN博客 Spring Boot整合Junit_心态还需努力呀的博客-CSDN博客 Spring Boot自动配置--如何切换内置Web服务器_心态还需努力呀…

Open3D SOR滤波(Python版本)

文章目录一、简介二、实现代码三、实现效果参考资料一、简介 SOR滤波过程相对简单&#xff0c;其原理是通过查询点与邻域点集之间的距离统计判断来进行过滤离群点。假设一个点的邻近点集符合正太分布&#xff0c;因此我们可以通过计算出该点到它所有临近点的平均距离meanD和标准…

国内怎么体验openAI chatGPT

怎么体验openAI chatGPT 一&#xff0c;前提 1&#xff0c;先准备好一个gmai的邮箱&#xff0c;注册时要用 2&#xff0c;&#xff08;懂得都懂&#xff09; 3&#xff0c;ChatGPT&#xff1a;网址 二&#xff0c;开始注册 1,sign up&#xff0c;用Gmail注册&#xff0c;我…

洛谷P8942 Digital Fortress

题目大意 给定一个区间&#xff0c;构造一个单调不减的序列&#xff0c;使得其前缀异或和与后缀异或和均单调递减&#xff0c;判断这种序列是否存在并输出任意一种解。 思路 暴力 dfs 当然会 TLE,所以我们要仔细分析&#xff1a; ① 在什么情况下异或和能够单调不减&#x…

2023/1/15 JS-原型与原型链

1 什么是原型 原型是Javascript中的继承的基础&#xff0c;JavaScript的继承就是基于原型的继承。每一个JS对象都可以获得自己的原型&#xff0c;通过原型可以共享函数对象和实例对象之间的属性和方法。 原型的出现&#xff0c;就是为了解决 构造函数 的缺点&#xff1a; 每一…

HTB-Shoppy

HTB-Shoppy信息收集开机提权信息收集 22和80。 能扫描出来的东西很杂&#xff0c;但是admin和login可以重点关注。 访问其中之一&#xff0c;能发现是一个登陆界面。 对其进行简单的sql注入测试。输入admin’or11#会出现504超时&#xff0c;判断可能是因为有sql防御措施所致。…

SpringCloud Netflix复习之Zuul

文章目录写作背景Zuul是什么Zuul的核心功能上手实战SpringCloud中Zuul如何使用自定义过滤器配置全局Fallback降级Zuul请求头Ribbon等其他参数配置过滤敏感请求头参数配置开启Ribbon懒加载和Ribbon超时配置开启Hystrix超时配置(一般不配置没啥用)源码部分请求入口ZuulServlet注入…

C++入门--list

目录 list的介绍&#xff1a; list的构造&#xff1a; 遍历&#xff1a; reverse、sort、unique list的模拟实现&#xff1a; 反向迭代器&#xff1a; list与vector的比较&#xff1a; list的介绍&#xff1a; list是序列容器&#xff0c;允许在序列内的任何位置执行O(…

RocketMQ源码(19)—Broker处理DefaultMQPushConsumer发起的拉取消息请求源码【一万字】

基于RocketMQ release-4.9.3&#xff0c;深入的介绍了Broker处理DefaultMQPushConsumer发起的拉取消息请求源码。 此前我们学习了RocketMQ源码(18)—DefaultMQPushConsumer消费者发起拉取消息请求源码。我们知道consumer在发送了拉取消息请求的时候&#xff0c;请求的Code为PUL…

【 JavaScript编程详解 -1 】什么是JavaScript ?

文章目录简介Java与JavaScript的不同Javascrpt可以做什么JavaScript的构成为什么可以在浏览器中运行如何将 JavaScript 代码添加到网站&#xff1f;方法1- \<script\>标签内嵌JavaScript方法1- \<script\>标签引入外部JavaScript文件方法3- 内联 JavaScript编辑器推…

蛇形矩阵(简单明了的方法)

T112524 【数组2】蛇形矩阵 题目来源 AC代码 #include<stdio.h>int main() {int arr[111][111];int n 0;scanf("%d",&n);int temp 0;int sum 1;while(temp<(2*n-2)){for(int i0;i<n;i){for(int j0;j<n;j){if((ij) temp){if(temp%2 0){arr[…

基于FPGA的时间数字转换(TDC)设计(三)

1.多相位TDC计时测试 以下为多相位TDC计时的测试。图1为多相位TDC计时的测试框图,利用信号发生器,产生两路同相位、具有固定延时的脉冲信号,一路作为Start信号,另外一路作为Stop信号。由于分辨率为312.5ps,因此以312.5ps为步进,对Stop信号进行延时,扫描一个周期,通过UA…

红米 12C earth Fastboot 线刷包 root TWRP 刷入magisk recovery卡刷

红米 12C earth Fastboot 线刷包 root TWRP 刷入magisk recovery卡刷 红米 12C (earth) 国行版 Fastboot 线刷包 & Recovery 卡刷包 ROM 红米 12C earth Fastboot 线刷包 root TWRP 刷入magisk recovery卡刷下载 红米 12C 稳定版 Fastboot 线刷包 要安装国行版 红米 12C F…

对笔试使用《剑指offer》吧(第十天)

跟着博主一起刷题 这里使用的是题库&#xff1a; https://leetcode.cn/problem-list/xb9nqhhg/?page1 目录剑指 Offer 62. 圆圈中最后剩下的数字剑指 Offer 64. 求12…n剑指 Offer 65. 不用加减乘除做加法剑指 Offer 62. 圆圈中最后剩下的数字 剑指 Offer 62. 圆圈中最后剩下的…

【BP靶场portswigger-客户端12】跨站点请求伪造CSRF-12个实验(全)

前言&#xff1a; 介绍&#xff1a; 博主&#xff1a;网络安全领域狂热爱好者&#xff08;承诺在CSDN永久无偿分享文章&#xff09;。 殊荣&#xff1a;CSDN网络安全领域优质创作者&#xff0c;2022年双十一业务安全保卫战-某厂第一名&#xff0c;某厂特邀数字业务安全研究员&…

YOLO家族系列模型的演变:从v1到v8(上)

YOLO V8已经在本月发布了&#xff0c;我们这篇文章的目的是对整个YOLO家族进行比较分析。了解架构的演变可以更好地知道哪些改进提高了性能&#xff0c;并且明确哪些版本是基于那些版本的改进&#xff0c;因为YOLO的版本和变体的命名是目前来说最乱的&#xff0c;希望看完这篇文…

Android 深入系统完全讲解(18)

3 su Root 的相关代码原理 在 Android4.4 的时候&#xff0c;我们经常能够看到 Root Apk&#xff0c;作为发烧友操作这个才算是真的会 Android。那么学习 su 的代码&#xff0c;就是非常有意义的事情。这一节来说下 su 是如何管理权限 的&#xff0c;如何调用授权 Apk&#xf…

撒贝宁搭档某网红,直播带货人气破十万,央视主持人能接私活吗

随着互联网的发展&#xff0c;直播已经司空见惯&#xff0c;直播带货更是成为家常便饭&#xff0c;尤其是那些有了名气的人。就在不久前&#xff0c;央视著名主持人撒贝宁&#xff0c;也开启了自己的直播带货首秀&#xff0c;不得不说央视主持人还是多才多艺。 在很短时间内&am…