From b158a9a85078d57a0e660aba680f6ad88da7ab6a Mon Sep 17 00:00:00 2001 From: liukangdong <898885815@qq.com> Date: 星期四, 07 十一月 2024 11:39:01 +0800 Subject: [PATCH] ll --- screen/src/views/SecurityControl.vue | 488 +++++++++++++++++++++++++++++++++++++++++------------- 1 files changed, 369 insertions(+), 119 deletions(-) diff --git a/screen/src/views/SecurityControl.vue b/screen/src/views/SecurityControl.vue index 33bdaad..8afd905 100644 --- a/screen/src/views/SecurityControl.vue +++ b/screen/src/views/SecurityControl.vue @@ -28,25 +28,26 @@ </div> <div class="num_wrap"> <div class="la">鎬昏溅浣嶏細</div> - <div class="val">100</div> + <div class="val">{{ data.parkingLotTotal }}</div> </div> </div> <div class="stall_static"> <div class="residue"> <div class="la">鍓╀綑杞︿綅</div> - <div class="val">50</div> + <div class="val">{{ data.freeParkingLot }}</div> </div> <div class="total"> <div class="la">杞︿綅鎬绘暟</div> - <div class="val">50</div> + <div class="val">{{ data.parkingLotTotal }}</div> </div> <div class="rate"> <div class="la"> <span>杞︿綅浣跨敤鐜�</span> - <span class="num">50%</span> + <span v-if="data.inParkCarTotal && data.parkingLotTotal" class="num">{{ ((data.inParkCarTotal / + data.parkingLotTotal) * 100).toFixed(0) }}%</span> </div> <div class="val"> - <Percent :rate="50" /> + <Percent :rate="((data.inParkCarTotal / data.parkingLotTotal) * 100).toFixed(0)" /> </div> </div> </div> @@ -58,20 +59,23 @@ </div> <div class="private_car"> <div class="item"> - <img src="" class="icon" alt=""> - <div class="num">20</div> <div class="name">鍛樺伐杞﹁締</div> + <div class="num">{{ data.internalCarTotal }}</div> </div> <div class="item"> - <img src="" class="icon" alt=""> - <div class="num">20</div> <div class="name">鐩稿叧鏂硅溅杈�</div> + <div class="num num2">{{ data.relatedCarTotal }}</div> </div> <div class="item"> - <img src="" class="icon" alt=""> - <div class="num">20</div> + <div class="name">鏉ヨ杞﹁締</div> + <div class="num num3">{{ data.visitCarTotal }}</div> </div> + </div> + <div class="section"> + <div class="item" :style="{ flex: data.internalCarTotal }"></div> + <div class="item" :style="{ flex: data.relatedCarTotal }"></div> + <div class="item" :style="{ flex: data.visitCarTotal }"></div> </div> <div class="second_title"> <div class="title"> @@ -82,32 +86,19 @@ <div class="car_static"> <div class="echart_wrap"> <div class="pie_text"> - <div class="fs30"><strong>300</strong></div> + <div class="fs30"><strong v-if="data.visitJobCarTotal">{{ data.internalJobCarTotal + + data.relatedJobCarTotal + data.visitJobCarTotal }}</strong></div> <div>璐ц溅</div> </div> <div class="echart" id="echart1"></div> </div> <div class="list"> - <div class="item"> + <div class="item" v-for="item, i in dataList1"> <div class="line"> - <div :style="{ background: colors[0] }" class="icon"></div> - <div class="text">鍐呰繍杞﹁締</div> + <div :style="{ background: colors[i] }" class="icon"></div> + <div class="text">{{ item.name }}</div> </div> - <div :style="{ color: colors[0] }" class="num">100</div> - </div> - <div class="item"> - <div class="line"> - <div :style="{ background: colors[1] }" class="icon"></div> - <div class="text">澶栧崗杩愯緭杞﹁締</div> - </div> - <div :style="{ color: colors[1] }" class="num">100</div> - </div> - <div class="item"> - <div class="line"> - <div :style="{ background: colors[2] }" class="icon"></div> - <div class="text">甯傚叕鍙稿嵏璐ц溅杈�</div> - </div> - <div :style="{ color: colors[2] }" class="num">100</div> + <div :style="{ color: colors[i] }" class="num">{{ item.value }}</div> </div> </div> </div> @@ -122,7 +113,7 @@ <img src="@/assets/images/SecurityControl/title_short@2x.png" class="bg" alt=""> </div> <div class="num_wrap"> - <div class="num">200</div> + <div class="num">{{ data.inParkTotal }}</div> <img src="@/assets/images/SecurityControl/anfang_ic_data@2x.png" class="bg" alt=""> </div> </div> @@ -132,7 +123,7 @@ <img src="@/assets/images/SecurityControl/title_short@2x.png" class="bg" alt=""> </div> <div class="num_wrap"> - <div class="num">200</div> + <div class="num">{{ data.inParkCarTotal }}</div> <img src="@/assets/images/SecurityControl/anfang_ic_data@2x.png" class="bg" alt=""> </div> </div> @@ -142,7 +133,7 @@ <img src="@/assets/images/SecurityControl/title_short@2x.png" class="bg" alt=""> </div> <div class="num_wrap"> - <div class="num">200</div> + <div class="num">{{ data.deviceTotal }}</div> <img src="@/assets/images/SecurityControl/anfang_ic_data@2x.png" class="bg" alt=""> </div> </div> @@ -152,7 +143,7 @@ <img src="@/assets/images/SecurityControl/title_short@2x.png" class="bg" alt=""> </div> <div class="num_wrap"> - <div class="num">200</div> + <div class="num">{{ data.errTotal }}</div> <img src="@/assets/images/SecurityControl/anfang_ic_data@2x.png" class="bg" alt=""> </div> </div> @@ -179,21 +170,24 @@ <img src="@/assets/images/SecurityControl/staff_ic_neibu@2x.png" alt=""> <div class="content"> <div class="name">鍐呴儴鍛樺伐</div> - <div class="num"><span>1000</span> | 66.6%</div> + <div class="num" v-if="data.internalTotal && data.inParkTotal"><span>{{ data.internalTotal }}</span> | + {{ ((data.internalTotal / data.inParkTotal) * 100).toFixed(1) }}%</div> </div> </div> <div class="item"> <img src="@/assets/images/SecurityControl/staff_ic_xiangguanfang@2x.png" alt=""> <div class="content"> <div class="name">闀挎湡鐩稿叧鏂�</div> - <div class="num today"><span>1000</span> | 66.6%</div> + <div class="num today" v-if="data.relatedTotal && data.inParkTotal"><span>{{ data.relatedTotal + }}</span> | {{ ((data.relatedTotal / data.inParkTotal) * 100).toFixed(1) }}%</div> </div> </div> <div class="item"> <img src="@/assets/images/SecurityControl/staff_ic_fangke@2x.png" alt=""> <div class="content"> <div class="name">鍦ㄥ洯璁垮</div> - <div class="num finish"><span>1000</span> | 66.6%</div> + <div class="num finish" v-if="data.visitTotal && data.inParkTotal"><span>{{ data.visitTotal }}</span> + | {{ ((data.visitTotal / data.inParkTotal) * 100).toFixed(1) }}%</div> </div> </div> </div> @@ -207,15 +201,15 @@ <div class="item"> <div class="name">寰呰闂�</div> <div class="num_wrap"> - <span class="num">22</span> + <span class="num">{{ data4.waitVisitNum }}</span> <span>浜�</span> </div> </div> <div class="spacing"></div> <div class="item"> - <div class="name">宸茬櫥鏈�</div> + <div class="name">宸茬櫥璁�</div> <div class="num_wrap"> - <span class="num">22</span> + <span class="num">{{ data4.registerVisitNum }}</span> <span>浜�</span> </div> </div> @@ -223,7 +217,7 @@ <div class="item"> <div class="name">宸茬寮�</div> <div class="num_wrap"> - <span class="num">22</span> + <span class="num">{{ data4.levelNum }}</span> <span>浜�</span> </div> </div> @@ -231,11 +225,12 @@ <div class="item"> <div class="name">婊炵暀</div> <div class="num_wrap"> - <span class="num">22</span> + <span class="num">{{ data4.retentionNum }}</span> <span>浜�</span> </div> </div> </div> + <div class="echart3" id="echart3"></div> </div> <div class="right_box_two"> @@ -338,30 +333,30 @@ </div> <img src="@/assets/images/title@2x.png" class="bg" alt="" /> </div> + <div class="monitoring"> + <img src="@/assets/images/SecurityControl/jiankong.png" class="icon" alt=""> + <div>鐩戞帶鍒楄〃</div> + <img src="@/assets/images/SecurityControl/jiankong_ic_open@2x.png" class="top" alt=""> + </div> <div class="content"> <div class="sa_static"> <div class="echart_wrap"> <div class="pie_text"> - <div class="fs30"><strong>300</strong></div> + <div class="fs30"><strong v-if="dataListT2 && dataListT2.length == 2">{{ dataListT2[0].value + + dataListT2[1].value }}</strong></div> <div>鎬昏</div> </div> <div class="echart" id="echart2"></div> </div> <div class="list"> - <div class="item"> + <div class="item" v-for="item, i in dataListT2"> <div class="line"> - <div :style="{ background: colors[1] }" class="icon"></div> - <div class="text">鍦ㄧ嚎</div> + <div :style="{ background: colors[i] }" class="icon"></div> + <div class="text">{{ item.name }}</div> </div> - <div :style="{ color: colors[1] }" class="num">100</div> + <div :style="{ color: colors[i] }" class="num">{{ item.value }} | {{ item.rate }}%</div> </div> - <div class="item"> - <div class="line"> - <div :style="{ background: colors[2] }" class="icon"></div> - <div class="text">绂荤嚎</div> - </div> - <div :style="{ color: colors[2] }" class="num">100</div> - </div> + </div> </div> <div class="table"> @@ -372,22 +367,18 @@ <div>绂荤嚎鏁�</div> <div>鍦ㄧ嚎鐜�</div> </div> - <div class="line"> - <div class="driver">闂ㄧ璁惧</div> - <div>10</div> - <div>10</div> - <div>10</div> - <div>10</div> - </div> - <div class="separate"></div> - <div class="line"> - <div class="driver">闂ㄧ璁惧</div> - <div>10</div> - <div>10</div> - <div>10</div> - <div>10</div> - </div> - <div class="separate"></div> + <template v-for="item, i in dataList2"> + <div class="line"> + <div class="driver">{{ item.deviceType }}</div> + <div>{{ item.totalNum }}</div> + <div>{{ item.onlineNum }}</div> + <div>{{ item.offlineDeviceNum }}</div> + <div v-if="item.onlineNum && item.totalNum">{{ ((item.onlineNum / item.totalNum) * 100).toFixed(0) }}% + </div> + </div> + <div class="separate"></div> + </template> + </div> </div> </div> @@ -405,18 +396,14 @@ <div class="dept">鎷滆閮ㄩ棬</div> <div class="dept">瓒呮椂鏃堕暱</div> </div> - <div class="line"> - <div>name</div> - <div class="dept">缁煎悎绠$悊绉�</div> - <div class="dept">10:21</div> - </div> - <div class="separate"></div> - <div class="line"> - <div>name</div> - <div class="dept">缁煎悎绠$悊绉�</div> - <div class="dept">10:21</div> - </div> - <div class="separate"></div> + <template v-for="item in dataList3"> + <div class="line"> + <div>{{ item.name }}</div> + <div class="dept">{{ item.companyName }}</div> + <div class="dept">{{ item.timeOutMinuteT }}</div> + </div> + <div class="separate"></div> + </template> </div> </div> </div> @@ -429,9 +416,12 @@ import VScaleScreen from 'v-scale-screen' import Percent from '@/components/percent.vue' import dayjs from 'dayjs' - +import duration from 'dayjs/plugin/duration' +dayjs.extend(duration) import * as echarts from 'echarts' -const colors = ['#FEAF01', '#01ABFE', '#51F9E4'] +import { getEnergyCenterData, getSecurityDeviceData, getVisitRetentionData, afgetVisitData } from '@/api' + + const weekMap = ['鏄熸湡鏃�', '鏄熸湡涓�', '鏄熸湡浜�', '鏄熸湡涓�', '鏄熸湡鍥�', '鏄熸湡浜�', '鏄熸湡鍏�',] const date = ref(dayjs().format('YYYY.MM.DD')) const week = ref(weekMap[new Date().getDay()]) @@ -504,8 +494,18 @@ myChart.resize() }) } + +const dataList1 = ref([]) const initEchart1 = () => { const myChart = echarts.init(document.getElementById('echart1')) + const temp = [] + temp.push({ name: '鍐呰繍杞﹁締', value: data.value.internalJobCarTotal }) + temp.push({ name: '澶栧崗杩愯緭杞﹁締', value: data.value.relatedJobCarTotal }) + temp.push({ name: '甯傚叕鍙稿嵏璐ц溅杈�', value: data.value.visitJobCarTotal }) + temp.sort((a, b) => { + return a.value - b.value + }) + dataList1.value = temp const option = { series: [ { @@ -523,11 +523,7 @@ labelLine: { show: false }, - data: [ - { value: 1048, name: 'Search Engine' }, - { value: 735, name: 'Direct' }, - { value: 580, name: 'Email' } - ] + data: temp } ] } @@ -536,6 +532,8 @@ myChart.resize() }) } + +const colors = ['#FEAF01', '#01ABFE', '#51F9E4'] const initEchart2 = () => { const myChart = echarts.init(document.getElementById('echart2')) const option = { @@ -555,11 +553,7 @@ labelLine: { show: false }, - data: [ - { value: 1048, name: 'Search Engine' }, - { value: 735, name: 'Direct' }, - { value: 580, name: 'Email' } - ] + data: dataListT2.value } ] } @@ -568,11 +562,206 @@ myChart.resize() }) } +const initEchart3 = () => { + const myChart = echarts.init(document.getElementById('echart3')) + var colors = [ + new echarts.graphic.LinearGradient(0, 1, 0, 0, [{ + offset: 0, + color: '#7fe3fc' + }, + { + offset: 1, + color: '#9ce9fc' + }]), + new echarts.graphic.LinearGradient(0, 1, 0, 0, [{ + offset: 0, + color: '#64d7fa' + }, { + offset: 1, + color: '#7de3fc' + }]), + new echarts.graphic.LinearGradient(0, 1, 0, 0, [{ + offset: 0, + color: '#4679f6' + }, { + offset: 1, + color: '#4674f6' + }]), + new echarts.graphic.LinearGradient(0, 1, 0, 0, [{ + offset: 0, + color: '#4370f2' + }, { + offset: 1, + color: '#61d3f9' + }])] + const data = [] + data.push({ name: '寰呰闂�', value: data4.value.waitVisitNum,rate: data4.value.waitVisitRata }) + data.push({ name: '宸茬櫥璁�', value: data4.value.registerVisitNum,rate: data4.value.registerVisitRata }) + data.push({ name: '宸茬寮�', value: data4.value.levelNum,rate: data4.value.levelRata }) + data.push({ name: '婊炵暀', value: data4.value.retentionNum,rate: data4.value.retentionRata }) + const option = { + color: colors, + tooltip: { + trigger: "axis", + axisPointer: { + type: "cross", + label: { + backgroundColor: "red" + }, + lineStyle: { + color: "#9eb2cb" + } + } + }, + + legend: { + show: false, + top: "top", + left: "2%", + textStyle: { + color: "#000" + }, + itemHeight: 2, + data: data.map(i => i.name) + }, + series: [ + { + type: 'funnel', + left: '15%', + right: '45%', + top: '10%', + bottom: '10%', + minSize: '20%', + maxSize: '80%', + gap: 4, + label: { + show: false, + }, + tooltip: { + trigger: 'none', // 褰撻紶鏍囨偓娴湪鏌愪釜鏁版嵁椤逛笂鏃惰Е鍙� + }, + itemStyle: { //鍘绘帀榛樿鐧借壊杈规绾� + borderWidth: 0, + borderColor: '#fff' + }, + data + }, + { + type: 'funnel', + left: '15%', + right: '45%', + top: '10%', + bottom: '10%', + minSize: '80%', + maxSize: '80%', + gap: 4, + z: 1, + label: { + show: true, + position: 'outside', + formatter: '{a|{b}} {a|{c}%}', + rich: { + a: { + color: '#869CC9', + fontSize: 13 + }, + } + }, + labelLine: { + show: true, + normal: { + length: 80, + position: 'right', + lineStyle: { + width: 1, + type: 'dashed', + color: 'rgba(102, 160, 239,.5)' + } + }, + }, + itemStyle: { //鍘绘帀榛樿鐧借壊杈规绾� + borderWidth: 0, + borderColor: '#fff' + }, + itemStyle: { + normal: { + color: 'transparent', + borderWidth: 0, + opacity: 1 + } + }, + data + }, + ] + } + myChart.setOption(option) + window.addEventListener('resize', function () { // 鎵ц + myChart.resize() + }) +} + +const data = ref({}) +const getData1 = () => { + getEnergyCenterData().then(res => { + const result = res.data + data.value = result + initEchart1() + }) +} + +const dataList2 = ref([]) +const dataListT2 = ref([]) +const getData2 = () => { + getSecurityDeviceData().then(res => { + const result = res.data + let temp = [] + let online = 0 + let outline = 0 + dataList2.value = result.map(item => { + online += item.onlineNum + outline += item.offlineDeviceNum + return item + }) + if (online >= outline) { + temp.push({ name: '鍦ㄧ嚎', value: online, rate: ((online / (online + outline)) * 100).toFixed(1) }) + temp.push({ name: '绂荤嚎', value: outline, rate: ((outline / (online + outline)) * 100).toFixed(1) }) + } else { + temp.push({ name: '绂荤嚎', value: outline, rate: ((outline / (online + outline)) * 100).toFixed(1) }) + temp.push({ name: '鍦ㄧ嚎', value: online, rate: ((online / (online + outline)) * 100).toFixed(1) }) + } + + dataListT2.value = temp + initEchart2() + }) +} + +const dataList3 = ref([]) +const getData3 = () => { + getVisitRetentionData().then(res => { + const result = res.data || [] + dataList3.value = result.map(i => { + i.timeOutMinuteT = dayjs.duration(i.timeOutMinute * 60 * 1000).format('HH:mm') + return i + }) + }) +} +const data4 = ref({}) +const getData4 = () => { + afgetVisitData().then(res => { + const result = res.data || {} + dataList4.value = result + initEchart3() + }) +} + onMounted(() => { - // initEnergy() - initEchart1() - initEchart2() + getData1() + getData2() + getData3() + getData4() + + // initEchart1() }) @@ -604,7 +793,7 @@ .stall_static { display: flex; - margin-bottom: 40px; + margin-bottom: 60px; padding: 0 20px; .residue { @@ -645,31 +834,60 @@ } .private_car { - padding: 4px 32px; + padding: 4px 20px; display: flex; justify-content: space-between; - margin-bottom: 36px; + margin-bottom: 10px; .item { display: flex; flex-direction: column; - align-items: center; - .icon { - width: 52px; - height: 52px; - margin-bottom: 10px; - } - + /* align-items: center; */ .num { line-height: 28px; height: 28px; - margin-bottom: 2px; + margin-top: 4px; font-weight: bold; font-size: 18px; color: #01D9FE; } + .num2 { + color: #FEAF01; + } + + .num3 { + color: #09FACD; + } + + } + } + + .section { + margin: 0 auto; + display: flex; + align-items: center; + width: 320px; + height: 20px; + background: rgba(255, 255, 255, 0.1); + padding: 0 4px; + margin-bottom: 60px; + + .item { + height: 10px; + margin-right: 1px; + background-color: #63d6fa; + flex: 1; + + &:nth-of-type(2) { + background-color: #f2b23e; + } + + &:nth-last-child(1) { + margin-right: 0; + background-color: #73f6cf; + } } } @@ -847,7 +1065,7 @@ .visitor_list { display: flex; justify-content: space-between; - padding: 20px; + padding: 20px 20px 16px; .item { font-size: 12px; @@ -872,6 +1090,11 @@ background-color: #405173; margin: 0 24px; } + } + + .echart3 { + width: 100%; + height: 140px; } } @@ -915,15 +1138,14 @@ align-items: center; .time { - width: 180px; + width: 130px; display: flex; justify-content: flex-end; - padding-bottom: 10px; - font-size: 36px; + font-size: 30px; } .week { - margin-left: 36px; + margin-left: 20px; } } @@ -1002,7 +1224,7 @@ margin-right: 20px; .list { - height: 147px; + height: 124px; overflow: auto; margin-top: 15px; scrollbar-width: none; @@ -1100,6 +1322,7 @@ .garden_warning { flex: 1; margin-right: 20px; + position: relative; .content { display: flex; @@ -1118,7 +1341,7 @@ .pie_text { width: 82px; height: 82px; - border: 1px dashed rgba(1, 217, 254, 0.7); + box-shadow: inset 0px 0px 8px 0px #01D9FE; border-radius: 50%; position: absolute; @@ -1200,14 +1423,41 @@ } } + .monitoring { + position: absolute; + top: -60px; + right: 0; + display: flex; + align-items: center; + justify-content: center; + font-weight: 500; + font-size: 15px; + width: 134px; + height: 40px; + background: linear-gradient(180deg, #021F4A 0%, #054281 100%), linear-gradient(180deg, #011738 0%, rgba(5, 66, 129, 0.26) 100%), #00141F; + border-radius: 2px; + border: 1px solid rgba(12, 153, 236, 0.68); + + .icon { + width: 30px; + } + + .top { + width: 12px; + height: 12px; + margin-left: 8px; + } + } + } .visitor_warning { width: 360px; - .table{ - .line{ - div{ - .dept{ + + .table { + .line { + div { + .dept { flex: 5; } } -- Gitblit v1.9.3