| | |
| | | } |
| | | .full-height { |
| | | height: 100%; |
| | | box-sizing: border-box; |
| | | } |
| | |
| | | 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> |
| | |
| | | .danger-act-wrapper { |
| | | padding: 8px; |
| | | display: flex; |
| | | cursor: pointer; |
| | | &:hover { |
| | | background-color: #fafa5c50; |
| | | } |
| | | .danger-act-icon { |
| | | display: flex; |
| | | padding: 4px 16px; |
| | |
| | | |
| | | defineExpose({ |
| | | setOption, |
| | | resize |
| | | resize, |
| | | getChart |
| | | }); |
| | | </script> |
| | | |
| | |
| | | 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" |
| | | } |
| | | } |
| | | ], |
| | | } |
| | | } |
| | | |
| | |
| | | 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); |
| | |
| | | const getNormalLine = (data)=>{ |
| | | const defaultOption = { |
| | | minRatio: 0, |
| | | maxRatio: 1.2 |
| | | maxRatio: 1.1 |
| | | }; |
| | | const option = {...defaultOption, ...data}; |
| | | return { |
| | |
| | | }, |
| | | }, |
| | | }, |
| | | 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) { |
| | |
| | | if(isNaN(max)) { |
| | | return 1; |
| | | }else { |
| | | return max * option.maxRatio; |
| | | return (max * option.maxRatio).toHold(0); |
| | | } |
| | | }, |
| | | axisLabel: { |
| | | formatter: '{value}', |
| | | color: '#e2e9ff', |
| | | }, |
| | | axisLine: { |
| | |
| | | color: 'rgba(255,255,255,0.12)' |
| | | } |
| | | } |
| | | }, |
| | | }], |
| | | series: [] |
| | | } |
| | | } |
| | |
| | | if(isNaN(max)) { |
| | | return 1; |
| | | }else { |
| | | return max * option.maxRatio; |
| | | return (max * option.maxRatio).toHold(0); |
| | | } |
| | | }, |
| | | axisLabel: { |
New file |
| | |
| | | /** |
| | | * 获取柱状图的重要的数据 |
| | | * |
| | | * @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; |
New file |
| | |
| | | function getMax(list) { |
| | | let arr = list.map((item) => { |
| | | return item[1]; |
| | | }); |
| | | return Math.max.apply(null, arr); |
| | | } |
| | | |
| | | export default getMax; |
New file |
| | |
| | | function getMin(list) { |
| | | let arr = list.map((item) => { |
| | | return item[1]; |
| | | }); |
| | | return Math.min.apply(null, arr); |
| | | } |
| | | export default getMin; |
| | |
| | | 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(""); |
| | |
| | | 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 |
| | |
| | | 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); |
| | | } |
| | |
| | | |
| | | 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(()=>{ |
| | | |
| | | getCarNames(); |
| | | |
| | | const tempBarOption = getRadiusBarOption({ |
| | | const tempBarOption = getNormalBar({ |
| | | grid: { |
| | | top: '15%', |
| | | right: '3%', |
| | | left: '5%', |
| | | bottom: '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 volBarOption = getRadiusBarOption({ |
| | | grid: { |
| | | top: '15%', |
| | | right: '3%', |
| | | left: '5%', |
| | | bottom: '5%' |
| | | 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, |
| | | } |
| | | }); |
| | | volBar.value.setOption(volBarOption); |
| | | |
| | | const alarmLineOption = getNormalLine(); |
| | | alarmLine.value.setOption(alarmLineOption); |
| | | |
| | | const totalVolLineOption = getNormalLine(); |
| | | 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(); |
| | | |
| | | tempBar.value.setOption(tempBarOption); |
| | | volBar.value.setOption(volBarOption); |
| | | |
| | | |
| | | alarmLine.value.setOption(alarmLineOption); |
| | | totalVolLine.value.setOption(totalVolLineOption); |
| | | |
| | | echarts.connect([ |
| | | alarmLine.value.getChart(), |
| | | totalVolLine.value.getChart() |
| | | ]); |
| | | resize(); |
| | | }); |
| | | </script> |
| | |
| | | <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> |
| | |
| | | @input="handleSlideInput"></el-slider> |
| | | </div> |
| | | </div> |
| | | |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | } |
| | | } |
| | | .batt-chart-list-footer { |
| | | padding: 4px 16px; |
| | | padding: 4px 8px; |
| | | } |
| | | } |
| | | .flex-box-content { |
| | |
| | | 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); |
| | | } |
| | | |
| | | /** |
| | | * 查询车辆,电池,摄像头,告警的图表数据 |
| | | */ |
| | |
| | | |
| | | searchRecentDaysBattNum(); |
| | | getTotalBattNum(); |
| | | |
| | | searchBmsStaticAlarm(); |
| | | } |
| | | |
| | | onMounted(()=>{ |
| | |
| | | |
| | | battGauge.value.setOption(battGaugeOption); |
| | | battBar.value.setOption(battBarOption); |
| | | |
| | | searchEchartsData(); |
| | | |
| | | const alarmBarOption = getHorizontalTechnologyOption(); |
| | | alarmBar.value.setOption(alarmBarOption); |
| | | }); |
| | | </script> |
| | |
| | | </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> |
| | |
| | | } |
| | | .main-layout-content { |
| | | flex: 1; |
| | | overflow-y: auto; |
| | | } |
| | | } |
| | | .main-layout-content-wrapper { |
| | |
| | | .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; |
| | | } |
| | | } |
| | | } |
New file |
| | |
| | | import axios from "@/assets/js/axios"; |
| | | |
| | | /** |
| | | * 统计BMS告警信息 |
| | | * @return {Promise<axios.AxiosResponse<any>> | *} |
| | | */ |
| | | export const searchBmsAlarm = ()=>{ |
| | | return axios({ |
| | | method: "GET", |
| | | url: "/monitor/bmsAlamMonitor/slectStaticBms", |
| | | }); |
| | | } |
New file |
| | |
| | | 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 |
| | | } |
| | | } |
| | |
| | | alarmLine.value.setOption(alarmLineOption); |
| | | } |
| | | |
| | | const photo = ref(videoContent); |
| | | const dangerBoxClick = (data)=>{ |
| | | photo.value = data.photo; |
| | | } |
| | | |
| | | onMounted(()=>{ |
| | | setAlarmLine(); |
| | | setLastAlarm(); |
| | |
| | | <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> |
| | |
| | | <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"> |
| | |
| | | overflow-y: auto; |
| | | } |
| | | } |
| | | .video-img { |
| | | width: auto; |
| | | height: 100%; |
| | | } |
| | | |
| | | .risk-act-wrapper { |
| | | display: flex; |
| | |
| | | } |
| | | } |
| | | } |
| | | |
| | | .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> |
| | |
| | | |
| | | const setLastAlarm = async ()=> { |
| | | dangerList.value = await searchLastAlarmList(); |
| | | console.log(dangerList.value) |
| | | } |
| | | |
| | | return { |