longyvfengyun
2023-11-17 3bb931d4eb57fec4a857c9dd0b11f9643c3506e5
内容提交
12个文件已修改
5个文件已添加
502 ■■■■ 已修改文件
src/assets/main.css 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/dangerActBox.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/echarts/hdwChart.vue 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/echarts/options/getNormalBar.js 112 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/echarts/options/horizontalTechnologyBar.js 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/echarts/options/normalLine.js 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/echarts/options/radiusBar.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/echarts/options/tools/getBarNum.js 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/echarts/options/tools/getMax.js 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/echarts/options/tools/getMin.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/battShow.vue 189 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/home.vue 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mainLayout/index.vue 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/moudle/bmsInf/apis.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/moudle/bmsInf/bmsInf.js 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/user/drivingAnalysis.vue 34 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/user/js/dangerActModule.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/main.css
@@ -5,4 +5,5 @@
}
.full-height {
  height: 100%;
  box-sizing: border-box;
}
src/components/dangerActBox.vue
@@ -17,10 +17,16 @@
        default: ""
    }
})
const emit = defineEmits(['click']);
const handleClick = ()=>{
    emit('click');
}
</script>
<template>
    <div class="danger-act-wrapper" :class="type">
    <div class="danger-act-wrapper" :class="type" @click="handleClick">
        <div class="danger-act-icon">
            <i class="iconfont" :class="icon"></i>
        </div>
@@ -37,6 +43,10 @@
.danger-act-wrapper {
    padding: 8px;
    display: flex;
    cursor: pointer;
    &:hover {
        background-color: #fafa5c50;
    }
    .danger-act-icon {
        display: flex;
        padding: 4px 16px;
src/components/echarts/hdwChart.vue
@@ -78,7 +78,8 @@
defineExpose({
    setOption,
    resize
    resize,
    getChart
});
</script>
src/components/echarts/options/getNormalBar.js
@@ -1,6 +1,114 @@
const getNormalBar = ()=>{
  return {
import getMax from "./tools/getMax";
import getMin from "./tools/getMin";
const getNormalBar = (data)=>{
  const defaultOption = {
    minRatio: 0,
    maxRatio: 1.2,
    grid: {
      top: '15%',
      right: '3%',
      left: '10%',
      bottom: '12%'
    },
    min: 0,
    max: 0,
    maxColor: "#FF0000",
    minColor: "#35f10a",
    normalColor: "rgb(24, 166, 253)"
  };
  let option = {...defaultOption, ...data};
  return {
    option,
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'shadow'
      }
    },
    grid: option.grid,
    xAxis: {
      type: 'category',
      axisLine: {
        lineStyle: {
          color: 'rgba(255,255,255,0.12)'
        }
      },
      axisLabel: {
        color: '#e2e9ff',
        fontSize: 14
      },
    },
    yAxis: {
      type: 'value',
      min(data) {
        const min =data.min;
        if(isNaN(min)) {
          return 0;
        }else {
          return min * option.minRatio;
        }
      },
      max(data) {
        const max = data.max;
        if(isNaN(max)) {
          return 1;
        }else {
          return (max * option.maxRatio).toHold(0);
        }
      },
      axisLabel: {
        formatter: '{value}',
        color: '#e2e9ff',
      },
      axisLine: {
        show: true,
        lineStyle: {
          color: 'rgba(255,255,255,0.12)'
        }
      },
      splitLine: {
        lineStyle: {
          color: 'rgba(255,255,255,0.12)'
        }
      }
    },
    title: {
      show: true,
      text: "最大值=0;最小值=0;平均值=0",
      x: "center",
      textStyle: {
        color: "#FFFFFF",
        fontSize: "14",
      },
    },
    series: [
      {
        name: "",
        data: [],
        type: 'bar',
        showBackground: true,
        backgroundStyle: {
          color: 'rgba(180, 180, 180, 0.2)'
        },
        itemStyle: {
          color(cData) {
            if(option.max === Number(cData.data[1])) {
              return option.maxColor;
            }else if(option.min === Number(cData.data[1])) {
              return option.minColor;
            }else {
              return option.normalColor;
            }
          }
        },
        label: {
          show: true,
          position: "top",
          color: "#FFFFFF"
        }
      }
    ],
  }
}
src/components/echarts/options/horizontalTechnologyBar.js
@@ -1,27 +1,36 @@
const getHorizontalTechnologyOption = ()=> {
const getHorizontalTechnologyOption = (list)=> {
  let category= [
    {
      name: "告警1",
      value: 2500
      value: 0
    },
    {
      name: "告警2",
      value: 8000
      value: 0
    },
    {
      name: "告警3",
      value: 3000
      value: 0
    },
    {
      name: "告警4",
      value: 3000
      value: 0
    },
    {
      name: "告警5",
      value: 3000
      value: 0
    }
  ]; // 类别
  let total = 10000; // 数据总数
  let total = 10; // 数据总数
  if(list && list.length !== 0) {
    category = list;
    total = 0;
    for(let i=0; i<list.length; i++) {
      total += Number(list[i].value);
    }
  }
  let datas = [];
  category.forEach(value => {
    datas.push(value.value);
src/components/echarts/options/normalLine.js
@@ -1,7 +1,7 @@
const getNormalLine = (data)=>{
  const defaultOption = {
    minRatio: 0,
    maxRatio: 1.2
    maxRatio: 1.1
  };
  const option = {...defaultOption, ...data};
  return {
@@ -35,14 +35,14 @@
        },
      },
    },
    yAxis: {
    yAxis: [{
      type: 'value',
      min(data) {
        const min =data.min;
        if(isNaN(min)) {
          return 0;
        }else {
          return min * option.minRatio;
          return (min * option.minRatio).toHold(0);
        }
      },
      max(data) {
@@ -50,11 +50,10 @@
        if(isNaN(max)) {
          return 1;
        }else {
          return max * option.maxRatio;
          return (max * option.maxRatio).toHold(0);
        }
      },
      axisLabel: {
        formatter: '{value}',
        color: '#e2e9ff',
      },
      axisLine: {
@@ -68,7 +67,7 @@
          color: 'rgba(255,255,255,0.12)'
        }
      }
    },
    }],
    series: []
  }
}
src/components/echarts/options/radiusBar.js
@@ -50,7 +50,7 @@
        if(isNaN(max)) {
          return 1;
        }else {
          return max * option.maxRatio;
          return (max * option.maxRatio).toHold(0);
        }
      },
      axisLabel: {
src/components/echarts/options/tools/getBarNum.js
New file
@@ -0,0 +1,28 @@
/**
 * 获取柱状图的重要的数据
 *
 * @param   {[type]}  data  柱状图数据
 *
 * @return  {[type]}        [return description]
 */
function getBarNum(data) {
    let result = {};
    let arr = [];
    let sum = 0;
    data.forEach(item=> {
        let val = Number(item[1]);
        arr.push(val);
        sum += val;
    });
    // 获取平均值
    let avg = data.length>0?sum/data.length:0;
    return {
        min: arr.length>0?Math.min.apply(null, arr):0,
        max: arr.length>0?Math.max.apply(null, arr):0,
        sum: sum,
        avg: avg.toHold(2),
    }
}
export default getBarNum;
src/components/echarts/options/tools/getMax.js
New file
@@ -0,0 +1,8 @@
function getMax(list) {
  let arr = list.map((item) => {
    return item[1];
  });
  return Math.max.apply(null, arr);
}
export default getMax;
src/components/echarts/options/tools/getMin.js
New file
@@ -0,0 +1,7 @@
function getMin(list) {
  let arr = list.map((item) => {
    return item[1];
  });
  return Math.min.apply(null, arr);
}
export default getMin;
src/views/battShow.vue
@@ -3,8 +3,16 @@
import ChartBox from "@/components/chartBox.vue";
import HdwChart from "@/components/echarts/hdwChart.vue";
import getNormalLine from "@/components/echarts/options/normalLine"
import {nextTick, onMounted, ref} from "vue";
import {onMounted, ref} from "vue";
import getRadiusBarOption from "@/components/echarts/options/radiusBar";
import carInfoModule from "@/views/moudle/battShow/carInfo";
import battHistoryModule from "@/views/moudle/battShow/battHistory";
import getDataIndex from "@/util/getDataIndex";
import getNormalBar from "@/components/echarts/options/getNormalBar";
import getMin from "@/components/echarts/options/tools/getMin";
import getMax from "@/components/echarts/options/tools/getMax";
import getBarNum from "@/components/echarts/options/tools/getBarNum";
import * as echarts from 'echarts';
const carName = ref("");
const timeRange = ref("");
@@ -21,11 +29,7 @@
  totalVolLine.value.resize();
}
import carInfoModule from "@/views/moudle/battShow/carInfo";
const {carList, getCarNames} = carInfoModule();
import battHistoryModule from "@/views/moudle/battShow/battHistory";
import getDataIndex from "@/util/getDataIndex";
const {
    getBattHistory
@@ -43,7 +47,13 @@
        totalData = data;
        slideVal.value = 100;
        let currentDataIndex = getDataIndex(totalData.length, slideVal.value);
        console.log(totalData[currentDataIndex]);
        if(currentDataIndex !== -1 && totalData.length !== 0) {
            setBarData(totalData[currentDataIndex]);
        }else {
            setBarData(-1)
        }
        setLineData(data);
    }catch (e) {
        console.log(e);
    }
@@ -53,51 +63,165 @@
const handleSlideInput = ()=>{
    let currentDataIndex = getDataIndex(totalData.length, slideVal.value);
    if(currentDataIndex !== -1) {
        console.log(totalData[currentDataIndex]);
    if(currentDataIndex !== -1 && totalData.length !== 0) {
        setBarData(totalData[currentDataIndex]);
    }else {
        setBarData(-1);
    }
}
const formatTooltip = (val)=>{
    let currentDataIndex = getDataIndex(totalData.length, slideVal.value);
    let rs = val+"";
    if(currentDataIndex !== -1) {
    if(currentDataIndex !== -1 && totalData.length !== 0) {
        let data = totalData[currentDataIndex];
        return new Date(data.gatherTime).format("yyyy-MM-dd hh:mm:ss");
    }
    return rs;
}
onMounted(()=>{
const tempBarOption = getNormalBar({
    grid: {
        top: '15%',
        right: '3%',
        left: '5%',
        bottom: '6%'
    }
});
const volBarOption = getNormalBar({
    grid: {
        top: '15%',
        right: '3%',
        left: '5%',
        bottom: '6%'
    }
});
const setBarData = (data)=>{
    tempBarOption.series[0].name = "单体温度";
    volBarOption.series[0].name = "单体电压";
    volBarOption.series[0].label.show = false;
    if(data !== -1) {
        let tempData = data.monomerTemp.split(",").map((item, key) => {
            return ["#" + (key + 1), item]
        });
        const tempNum = getBarNum(tempData);
        tempBarOption.option.min = tempNum.min;
        tempBarOption.option.max = tempNum.max;
        tempBarOption.title.text = "最大值="+tempNum.max+"℃;最小值="+tempNum.min+"℃;平均值="+tempNum.avg+"℃"
        tempBarOption.series[0].data = tempData;
        let volData = data.monomerVol.split(",").map((item, key) => {
            return ["#" + (key + 1), item]
        });
        const volNum = getBarNum(volData);
        volBarOption.option.min = volNum.min;
        volBarOption.option.max = volNum.max;
        volBarOption.title.text = "最大值="+volNum.max+"V;最小值="+volNum.min+"V;平均值="+volNum.avg+"V"
        volBarOption.series[0].data = volData;
    }else {
        tempBarOption.series[0].data = [];
        volBarOption.series[0].data = [];
    }
    tempBar.value.setOption(tempBarOption);
    volBar.value.setOption(volBarOption);
}
const alarmLineOption = getNormalLine({
    minRatio: 0.9
});
const totalVolLineOption = getNormalLine({
    minRatio: 0.9
});
let lineData = {
    times: [],
    vol: [],
    temp: []
};
const setLineData = (data)=>{
    // 初始化lineData
    lineData = {
        times: [],
        vol: [],
        temp: []
    };
    // 遍历数据
    for(let i=0; i<data.length; i++) {
        let itemData = data[i];
        lineData.times.push(new Date(itemData.gatherTime).format("yyyy-MM-dd hh:mm:ss"));
        // 单体温度
        itemData.monomerTemp.split(",").map((item, key)=>{
            if(lineData.temp[key] === undefined) {
                lineData.temp[key] = [];
            }
            lineData.temp[key].push(item);
        });
        // 单体电压
        itemData.monomerVol.split(",").map((item, key)=>{
            if(lineData.vol[key] === undefined) {
                lineData.vol[key] = [];
            }
            lineData.vol[key].push(item);
        });
    }
    alarmLineOption.xAxis.data = lineData.times;
    alarmLineOption.series = lineData.temp.map((item, key)=>{
        return {
            name: '#'+(key+1),
            type: 'line',
            smooth: false,
            symbolSize: 0,
            data: item,
        }
    });
    alarmLine.value.setOption(alarmLineOption);
    totalVolLineOption.xAxis.data = lineData.times;
    totalVolLineOption.tooltip.formatter = (params)=>{
        let res = params[0].name + '<br/>';
        res +='<table>'
        params.forEach((item,key) => {
            res += "<td style='padding: 2px'>";
            res += item.marker;
            res += item.seriesName;
            res += ' : ' + item.data + 'V';
            res += "</td>";
            if((key+1)%5 === 0) {
                res += '<tr></tr>';
            }
        });
        res +='<table>'
        return res;
    };
    totalVolLineOption.series = lineData.vol.map((item, key)=>{
        return {
            name: '#'+(key+1),
            type: 'line',
            smooth: false,
            symbolSize: 0,
            data: item,
        }
    });
    totalVolLine.value.setOption(totalVolLineOption);
}
onMounted(()=>{
    getCarNames();
  const tempBarOption = getRadiusBarOption({
      grid: {
          top: '15%',
          right: '3%',
          left: '5%',
          bottom: '5%'
      }
  });
  tempBar.value.setOption(tempBarOption);
  const volBarOption = getRadiusBarOption({
      grid: {
          top: '15%',
          right: '3%',
          left: '5%',
          bottom: '5%'
      }
  });
  volBar.value.setOption(volBarOption);
  const alarmLineOption = getNormalLine();
  alarmLine.value.setOption(alarmLineOption);
  const totalVolLineOption = getNormalLine();
  alarmLine.value.setOption(alarmLineOption);
  totalVolLine.value.setOption(totalVolLineOption);
    echarts.connect([
        alarmLine.value.getChart(),
        totalVolLine.value.getChart()
    ]);
    resize();
});
</script>
@@ -166,7 +290,7 @@
                      <div class="batt-chart-item left">
                          <flex-box>
                              <div class="flex-box-content">
                                  <chart-box title="告警事件">
                                  <chart-box title="总单体温度">
                                      <hdw-chart ref="alarmLine"></hdw-chart>
                                  </chart-box>
                              </div>
@@ -191,7 +315,6 @@
                      @input="handleSlideInput"></el-slider>
              </div>
          </div>
      </div>
    </div>
  </div>
@@ -242,7 +365,7 @@
        }
    }
    .batt-chart-list-footer {
        padding: 4px 16px;
        padding: 4px 8px;
    }
}
.flex-box-content {
src/views/home.vue
@@ -214,6 +214,28 @@
    getTotalVideoNum
} = totalVideoNumModule();
import {
    bmsStaticAlarmModule
} from "@/views/moudle/bmsInf/bmsInf";
const {
    getBmsStaticAlarm
} = bmsStaticAlarmModule();
let alarmBarOption = getHorizontalTechnologyOption();
const searchBmsStaticAlarm = async ()=>{
    let res = await getBmsStaticAlarm();
    alarmBarOption = getHorizontalTechnologyOption(res.map(item=>{
        return {
            name: item.bmsAlarmName,
            value: item.num
        }
    }));
    alarmBar.value.setOption(alarmBarOption);
}
/**
 * 查询车辆,电池,摄像头,告警的图表数据
 */
@@ -226,6 +248,8 @@
    searchRecentDaysBattNum();
    getTotalBattNum();
    searchBmsStaticAlarm();
}
onMounted(()=>{
@@ -237,10 +261,8 @@
    battGauge.value.setOption(battGaugeOption);
    battBar.value.setOption(battBarOption);
    searchEchartsData();
    const alarmBarOption = getHorizontalTechnologyOption();
    alarmBar.value.setOption(alarmBarOption);
});
</script>
src/views/mainLayout/index.vue
@@ -90,7 +90,7 @@
            </div>
        </div>
        <div class="main-layout-content">
            <div class="full-height">
            <div class="full-height" style="overflow-x: hidden">
                <div class="main-layout-content-wrapper">
                    <div class="main-layout-content-header">
                        <page-header :is-collapse="isCollapse"></page-header>
@@ -146,6 +146,7 @@
    }
    .main-layout-content {
        flex: 1;
        overflow-y: auto;
    }
}
.main-layout-content-wrapper {
@@ -155,16 +156,13 @@
    .main-layout-content-body {
        position: relative;
        flex: 1;
        overflow-y: auto;
        background-color: #FFFFFF;
        box-shadow: 0 0 3px 0 rgba(0,0,0,.1);
        .body-absolute {
            position: absolute;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            overflow-x: hidden;
        }
    }
}
src/views/moudle/bmsInf/apis.js
New file
@@ -0,0 +1,12 @@
import axios from "@/assets/js/axios";
/**
 * 统计BMS告警信息
 * @return {Promise<axios.AxiosResponse<any>> | *}
 */
export const searchBmsAlarm = ()=>{
  return axios({
    method: "GET",
    url: "/monitor/bmsAlamMonitor/slectStaticBms",
  });
}
src/views/moudle/bmsInf/bmsInf.js
New file
@@ -0,0 +1,27 @@
import {
  searchBmsAlarm
} from "./apis"
export const bmsStaticAlarmModule = ()=>{
  /**
   * 统计BMS告警信息
   * @return {Promise<*[]>}
   */
  const getBmsStaticAlarm = async ()=>{
    try{
      const res = await searchBmsAlarm();
      const rs = res.data;
      let data = [];
      if(rs.code === 1) {
        data = rs.data;
      }
      return data;
    }catch (e) {
      console.log(e);
      return [];
    }
  }
  return {
    getBmsStaticAlarm
  }
}
src/views/user/drivingAnalysis.vue
@@ -28,6 +28,11 @@
    alarmLine.value.setOption(alarmLineOption);
}
const photo = ref(videoContent);
const dangerBoxClick = (data)=>{
    photo.value = data.photo;
}
onMounted(()=>{
    setAlarmLine();
    setLastAlarm();
@@ -47,6 +52,7 @@
                                <div class="danger-act-container-absolute">
                                    <danger-act-box
                                        v-for="(item, key) in dangerList" :key="'key'+key"
                                        @click="dangerBoxClick(item)"
                                        :name="item.name" :time="item.time"
                                        :icon="item.icon" :type="item.type"></danger-act-box>
                                </div>
@@ -59,7 +65,11 @@
        <div class="content-wrapper middle">
            <div class="video-wrapper">
                <flex-box>
                    <img class="video-img" :src="videoContent" alt="">
                    <div class="position-relative">
                        <div class="position-absolute">
                            <img class="video-img" :src="photo" alt="">
                        </div>
                    </div>
                </flex-box>
            </div>
            <div class="alarm-line-wrapper">
@@ -199,10 +209,6 @@
        overflow-y: auto;
    }
}
.video-img {
    width: auto;
    height: 100%;
}
.risk-act-wrapper {
    display: flex;
@@ -246,4 +252,22 @@
        }
    }
}
.position-relative {
    position: relative;
    height: 100%;
    .position-absolute {
        position: absolute;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        right: 0;
        bottom: 0;
        .video-img {
            width: 100%;
            height: 100%;
        }
    }
}
</style>
src/views/user/js/dangerActModule.js
@@ -42,6 +42,7 @@
  const setLastAlarm = async ()=> {
    dangerList.value = await searchLastAlarmList();
    console.log(dangerList.value)
  }
  return {