| | |
| | | <script setup> |
| | | import { ref, reactive } from "vue"; |
| | | <script setup name="realtime"> |
| | | import { ref, reactive, watch, onMounted, onActivated } from "vue"; |
| | | import tabPower from "./tabs/power.vue"; |
| | | import tabSystem from "./tabs/system.vue"; |
| | | import tabVol from './tabs/vol.vue'; |
| | | import tabRes from './tabs/res.vue'; |
| | | import tabTemp from './tabs/temp.vue'; |
| | | // import tabThreeD from './tabs/threeD.vue'; |
| | | // import tabSelf from './tabs/self.vue'; |
| | | import tabManage from './tabs/manage.vue'; |
| | | import siteList from "@/components/siteList/index.vue"; |
| | | import getQueryString from "@/utils/getQueryString"; |
| | | import formatSeconds from '@/utils/formatSeconds'; |
| | | import battAlarmParams from '@/views/alarm/battAlarmParams.vue'; |
| | | |
| | | |
| | | import { useRoute, useRouter } from "vue-router"; |
| | | import useWebSocket from "@/hooks/useWebSocket"; |
| | | |
| | | const route = useRoute(); |
| | | const router = useRouter(); |
| | | |
| | | const { message, sendData } = useWebSocket('real'); |
| | | |
| | | const curStationId = ref( |
| | | getQueryString("stationId") || '' |
| | | ); |
| | | |
| | | const curPowerId = ref( |
| | | getQueryString("powerId") || '' |
| | | ); |
| | | |
| | | const curBattgroupId = ref( |
| | | getQueryString("battgroupId") || '' |
| | | ); |
| | | |
| | | const curDevId = ref( |
| | | getQueryString("devId") || '' |
| | | ); |
| | | |
| | | const rtData = reactive({ |
| | | system: {}, |
| | | power: {}, |
| | | vol: {}, |
| | | res: {}, |
| | | tmp: {}, |
| | | threeD: {}, |
| | | self: {}, |
| | | manage: {}, |
| | | }); |
| | | |
| | | const statusList = reactive([ |
| | | { label: '系统状态', value: '充电' }, |
| | | { label: '设备状态', value: '正常' }, |
| | | { label: '电源状态', value: '正常' }, |
| | | { label: '电池状态', value: '正常' }, |
| | | { label: '母线电压', value: 60 }, |
| | | { label: '在线电压', value: 60 }, |
| | | { label: '组端电压', value: 60 }, |
| | | { label: '电池电流', value: 60 }, |
| | | { label: '测试时长', value: 60 }, |
| | | { label: '测试容量', value: 60 }, |
| | | { label: '预估剩余容量', value: 60 }, |
| | | { label: '预估剩余续航', value: 60 }, |
| | | { label: '告警', value: '无' }, |
| | | { label: '更新日期', value: '2022-01-01' }, |
| | | { label: '系统状态', prop: 'systemStateName', unit: '' }, |
| | | { label: '设备状态', prop: 'devStateName', unit: '' }, |
| | | { label: '电源状态', prop: 'pwrStateName', unit: '' }, |
| | | { label: '电池状态', prop: 'battStateName', unit: '' }, |
| | | { label: '母线电压', prop: 'vbusVol', unit: 'V' }, |
| | | { label: '在线电压', prop: 'onlineVol', unit: 'V' }, |
| | | { label: '组端电压', prop: 'captestGroupvol', unit: 'V' }, |
| | | { label: '电池电流', prop: 'captestCurr', unit: 'A' }, |
| | | { label: '测试时长', prop: 'captestTimelong', unit: '' }, |
| | | { label: '测试容量', prop: 'captestCap', unit: 'Ah' }, |
| | | { label: '预估剩余容量', prop: 'restCap', unit: 'Ah' }, |
| | | { label: '预估剩余续航', prop: 'restTime', unit: '' }, |
| | | { label: '告警', prop: 'allALmNum', unit: '' }, |
| | | { label: '更新日期', prop: 'recordtime', unit: '' }, |
| | | ]); |
| | | |
| | | const tabs = ref([ |
| | |
| | | { label: '电源', name: 'power' }, |
| | | { label: '电压', name: 'vol' }, |
| | | { label: '内阻', name: 'res' }, |
| | | { label: '温度', name: 'temp' }, |
| | | { label: '3D', name: '3d' }, |
| | | { label: '温度', name: 'tmp' }, |
| | | { label: '3D', name: '3D' }, |
| | | { label: '自愈能力', name: 'self' }, |
| | | { label: '管理信息', name: 'manage' }, |
| | | ]); |
| | | |
| | | const btns = ref([ |
| | | { label: '电源告警参数设置', name: 'powerAlarmSet' }, |
| | | { label: '电池告警参数设置', name: 'battAlarmSet' }, |
| | | { label: '图片', name: 'img' }, |
| | |
| | | |
| | | const acTab = ref(tabs.value[0].name); |
| | | |
| | | const fullName = ref('湖北省-武汉市-武昌区-武昌机房-电池组1'); |
| | | const fullName = ref(''); |
| | | const topData = ref({}); |
| | | |
| | | |
| | | function sendMessage() { |
| | | let params = { |
| | | stationId: curStationId.value || 0, |
| | | powerId: curPowerId.value || 0, |
| | | devId: curDevId.value || 0, |
| | | battgroupId: curBattgroupId.value || 0, |
| | | // system, power, vol, res, tmp, 3D, self, manage |
| | | pageType: acTab.value |
| | | }; |
| | | sendData(JSON.stringify(params)); |
| | | } |
| | | |
| | | function tabClick(item) { |
| | | acTab.value = item.name; |
| | | sendMessage(); |
| | | } |
| | | |
| | | const visibles = reactive({ |
| | | powerAlarmSet: false, |
| | | battAlarmSet: false |
| | | }); |
| | | |
| | | function btnClick(item) { |
| | | console.log('item', item, '============='); |
| | | // 改为跳转 |
| | | switch(item.name) { |
| | | case 'powerAlarmSet': |
| | | router.push({ |
| | | path: '/alarm/power-setting', |
| | | query: { |
| | | stationId: curStationId.value || 0, |
| | | powerId: curPowerId.value || 0, |
| | | devId: curDevId.value || 0, |
| | | battgroupId: curBattgroupId.value || 0, |
| | | pageFlag: Math.random(), |
| | | } |
| | | }); |
| | | break; |
| | | case 'battAlarmSet': |
| | | // visibles.battAlarmSet = true; |
| | | router.push({ |
| | | path: '/alarm/batt-setting', |
| | | query: { |
| | | stationId: curStationId.value || 0, |
| | | powerId: curPowerId.value || 0, |
| | | devId: curDevId.value || 0, |
| | | battgroupId: curBattgroupId.value || 0, |
| | | pageFlag: Math.random(), |
| | | } |
| | | }); |
| | | break; |
| | | case 'img': |
| | | break; |
| | | case 'history': |
| | | router.push({ |
| | | path: '/datas/history', |
| | | query: { |
| | | stationId: curStationId.value || 0, |
| | | powerId: curPowerId.value || 0, |
| | | devId: curDevId.value || 0, |
| | | battgroupId: curBattgroupId.value || 0, |
| | | pageTab: 'his-test', |
| | | pageFlag: Math.random(), |
| | | } |
| | | }); |
| | | break; |
| | | case 'hisRt': |
| | | router.push({ |
| | | path: '/datas/history', |
| | | query: { |
| | | stationId: curStationId.value || 0, |
| | | powerId: curPowerId.value || 0, |
| | | devId: curDevId.value || 0, |
| | | battgroupId: curBattgroupId.value || 0, |
| | | pageTab: 'his-real', |
| | | pageFlag: Math.random(), |
| | | } |
| | | }); |
| | | break; |
| | | } |
| | | |
| | | } |
| | | function leafClick(item) { |
| | | // console.log('item', item, '============='); |
| | | curStationId.value = item.stationId; |
| | | curPowerId.value = item.powerId; |
| | | curBattgroupId.value = item.battgroupId || 0; |
| | | curDevId.value = item.devId || 0; |
| | | |
| | | sendMessage(); |
| | | } |
| | | |
| | | |
| | | |
| | | watch( |
| | | () => message.value, |
| | | (n) => { |
| | | if (n) { |
| | | let {data2: { topRes, realRes}} = JSON.parse(n); |
| | | let data = {}; |
| | | if (topRes.code && topRes.data) { |
| | | data = topRes.data2; |
| | | fullName.value = `${data.fullName} ${data.powerName} ${data.devName} ${data.battGroupName}`; |
| | | } |
| | | topData.value = data; |
| | | if (realRes.code && realRes.data) { |
| | | rtData[realRes.data2.pageType] = realRes.data2; |
| | | } |
| | | } |
| | | } |
| | | ); |
| | | |
| | | onActivated(() => { |
| | | sendMessage(); |
| | | }); |
| | | |
| | | onMounted(() => { |
| | | sendMessage(); |
| | | }); |
| | | </script> |
| | | |
| | | <template> |
| | | <div class="page-contain"> |
| | | <div class="page-header"> |
| | | <div class="p-title">{{ fullName }}</div> |
| | | <div class="status-bar"> |
| | | <div |
| | | :class="['status-item',]" |
| | | v-for="(item, index) in statusList" |
| | | :key="'status_' + index" |
| | | > |
| | | <div class="item-value">{{ item.value }}</div> |
| | | <div class="item-name">{{ item.label }}</div> |
| | | <site-list @leaf-click="leafClick"></site-list> |
| | | <div class="page-inner"> |
| | | <div class="page-header"> |
| | | <div class="p-title">{{ fullName }}</div> |
| | | <div class="status-bar"> |
| | | <div |
| | | :class="['status-item',]" |
| | | v-for="(item, index) in statusList" |
| | | :key="'status_' + index" |
| | | > |
| | | <div class="item-value" v-if="item.prop == 'captestTimelong' || item.prop == 'restTime'">{{ topData[item.prop] ? formatSeconds(topData[item.prop]) : '--' }}</div> |
| | | <div class="item-value time" v-else-if="item.prop == 'recordtime'">{{ topData[item.prop] || '--' }}</div> |
| | | <div class="item-value" v-else>{{ topData[item.prop] || '--' }}{{ item.unit }}</div> |
| | | <div class="item-name">{{ item.label }}</div> |
| | | </div> |
| | | </div> |
| | | <div class="p-tabs"> |
| | | <div |
| | | :class="['tab-item', {'active': item.name == acTab}]" |
| | | v-for="(item, index) in tabs" |
| | | :key="'tab_' + index" |
| | | @click="tabClick(item)" |
| | | > |
| | | {{ item.label }} |
| | | </div> |
| | | <div |
| | | class="btn-item tab-item" |
| | | v-for="(item, index) in btns" |
| | | :key="'btn_' + index" |
| | | @click="btnClick(item)" |
| | | > |
| | | {{ item.label }} |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="p-tabs"> |
| | | <div |
| | | :class="['tab-item', {'active': item.name == acTab}]" |
| | | v-for="(item, index) in tabs" |
| | | :key="'tab_' + index" |
| | | @click="tabClick(item)" |
| | | > |
| | | {{ item.label }} |
| | | <div class="page-main"> |
| | | <div class="tab-contain" v-if="acTab == 'system'"> |
| | | <tab-system :data="rtData['system']" :powerId="curPowerId" :devId="curDevId" :battgroupId="curBattgroupId"></tab-system> |
| | | </div> |
| | | <div class="tab-contain" v-if="acTab == 'power'"> |
| | | <tab-power :data="rtData['power']"></tab-power> |
| | | </div> |
| | | <div class="tab-contain" v-if="acTab == 'vol'"> |
| | | <tab-vol :data="rtData['vol']"></tab-vol> |
| | | </div> |
| | | <div class="tab-contain" v-if="acTab == 'res'"> |
| | | <tab-res :data="rtData['res']"></tab-res> |
| | | </div> |
| | | <div class="tab-contain" v-if="acTab == 'tmp'"> |
| | | <tab-temp :data="rtData['tmp']"></tab-temp> |
| | | </div> |
| | | <div class="tab-contain" v-if="acTab == '3D'">5</div> |
| | | <div class="tab-contain" v-if="acTab == 'self'">6</div> |
| | | <div class="tab-contain" v-if="acTab == 'manage'"> |
| | | <tab-manage :data="rtData['manage']"></tab-manage> |
| | | </div> |
| | | <!-- <div class="tab-contain" v-if="acTab == 'powerAlarmSet'">8</div> |
| | | <div class="tab-contain" v-if="acTab == 'battAlarmSet'">9</div> |
| | | <div class="tab-contain" v-if="acTab == 'img'">10</div> |
| | | <div class="tab-contain" v-if="acTab == 'history'">11</div> |
| | | <div class="tab-contain" v-if="acTab == 'hisRt'">12</div> --> |
| | | </div> |
| | | </div> |
| | | <div class="page-main"> |
| | | <div class="tab-contain" v-if="acTab == 'system'"> |
| | | <tab-system></tab-system> |
| | | </div> |
| | | <div class="tab-contain" v-if="acTab == 'power'"> |
| | | <tab-power></tab-power> |
| | | </div> |
| | | <div class="tab-contain" v-if="acTab == 'vol'">2</div> |
| | | <div class="tab-contain" v-if="acTab == 'res'">3</div> |
| | | <div class="tab-contain" v-if="acTab == 'temp'">4</div> |
| | | <div class="tab-contain" v-if="acTab == '3d'">5</div> |
| | | <div class="tab-contain" v-if="acTab == 'self'">6</div> |
| | | <div class="tab-contain" v-if="acTab == 'manage'">7</div> |
| | | <div class="tab-contain" v-if="acTab == 'powerAlarmSet'">8</div> |
| | | <div class="tab-contain" v-if="acTab == 'battAlarmSet'">9</div> |
| | | <div class="tab-contain" v-if="acTab == 'img'">10</div> |
| | | <div class="tab-contain" v-if="acTab == 'history'">11</div> |
| | | <div class="tab-contain" v-if="acTab == 'hisRt'">12</div> |
| | | </div> |
| | | <!-- 电池告警参数 --> |
| | | <!-- <el-dialog v-model="visibles.battAlarmSet" title="电池告警参数" width="900"> |
| | | <batt-alarm-params @close="visibles.battAlarmSet = false" v-if="visibles.battAlarmSet" :id="curBattgroupId"></batt-alarm-params> |
| | | </el-dialog> --> |
| | | </div> |
| | | </template> |
| | | |
| | | <style scoped lang="less"> |
| | | .page-contain { |
| | | display: flex; |
| | | flex-direction: column; |
| | | padding: 8px 8px 8px 0; |
| | | margin-left: 8px; |
| | | overflow: hidden; |
| | | .page-inner { |
| | | display: flex; |
| | | flex-direction: column; |
| | | flex: 1; |
| | | margin-left: 8px; |
| | | } |
| | | |
| | | .page-header { |
| | | // border: 1px solid #0ff; |
| | |
| | | color: #50c7f1; |
| | | // border: 1px solid #0F6B79; |
| | | border-radius: 6px; |
| | | margin: 4px 6px; |
| | | margin: 4px 2px; |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | |
| | | margin-bottom: 6px; |
| | | color: #ff0; |
| | | font-size: 20px; |
| | | &.time { |
| | | white-space: nowrap; |
| | | font-size: 12px; |
| | | } |
| | | } |
| | | |
| | | .item-name { |
| | |
| | | background: #47CAFE; |
| | | color: #03216e; |
| | | } |
| | | &.btn-item { |
| | | background: #076fe8; |
| | | // border-radius: 6px; |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | .page-main { |
| | | flex: 1; |
| | | |
| | | padding-left: 0; |
| | | padding-right: 0; |
| | | .tab-contain { |
| | | height: 100%; |
| | | } |