<template> <div class="boat-info" :class="{'tab-bgxx': currentTab==='bgxx', 'tab-gzxx': currentTab==='gzxx'}"> <div class="bi-header"> <span class="bih-title">{{ props.boatInfo.shipNameCn || '未查到信息' }}</span> <div class="bih-btns"> <span :class="{'highlight': cameraType==='down'}" @click="toggleCamera('down')">船身</span> <span :class="{'highlight': cameraType==='in'}" @click="toggleCamera('in')">船舱</span> <span :class="{'highlight': cameraType==='follow'}" @click="toggleCamera('follow')">船尾</span> </div> </div> <div class="dialog-tab bi-tab bottom-divider"> <div :class="{'highlight': currentTab==='cbxx'}" @click="changeTab('cbxx')"><span>船舶信息</span></div> <div :class="{'highlight': currentTab==='gzxx'}" @click="changeTab('gzxx')"><span>感知信息</span></div> <div :class="{'highlight': currentTab==='bgxx'}" @click="changeTab('bgxx')"><span>报告信息</span></div> </div> <ul class="boat-fields cf-cbxx bottom-divider" v-if="currentTab==='cbxx'"> <li><span>MMSI:</span><span>{{ props.boatInfo.mmsi }}</span></li> <li><span>船舶类型:</span><span>{{ props.boatInfo.shipTypeName || '-' }}</span></li> <li><span>船舶宽度:</span><span>{{ props.boatInfo.shipBreadth || '- ' }}米</span></li> <li><span>船舶长度:</span><span>{{ props.boatInfo.shipLength || '- ' }}米</span></li> <li><span>船舶总吨:</span><span>{{ props.boatInfo.shipGrossTon || '-' }}</span></li> <li><span>满载吃水:</span><span>{{ props.boatInfo.loadedDraft || '-' }}</span></li> <li style="margin-bottom: 0;"><span>空载吃水:</span><span>{{ props.boatInfo.noLoadedDraft || '-' }}</span></li> </ul> <ul class="boat-fields cf-bgxx bottom-divider" v-if="currentTab==='bgxx'"> <li><span>停靠泊位:</span><span>--</span></li> <li><span>报告时间:</span><span>--</span></li> <li><span>预抵时间:</span><span>--</span></li> <li><span>当前港口:</span><span>--</span></li> <li><span>上一港口:</span><span>--</span></li> <li><span>下一港口:</span><span>--</span></li> <li><span>申报人员:</span><span>--</span></li> <li><span>申报电话:</span><span>--</span></li> </ul> <div class="content-gzxx bottom-divider" v-if="currentTab==='gzxx'"> <div class="sjrh-wrapper bottom-divider"> <span>数据融合:</span> <span class="sjrh-btn" :class="{'disabled': !sjrhData.video}">视频</span> <span class="sjrh-btn" :class="{'disabled': !sjrhData.laser}">激光</span> <span class="sjrh-btn" :class="{'disabled': !sjrhData.AIS}">AIS</span> <span class="sjrh-btn" :class="{'disabled': !sjrhData.RFID}">RFID</span> </div> <ul class="gzxx-fields boat-fields"> <li><span>航向:</span><span>{{ props.boatInfo.inOrOut || '-' }}</span></li> <li><span>航速:</span><span>{{ props.boatInfo.speed || '- ' }}(公里/时)</span></li> <li><span>载重:</span><span>{{ props.boatInfo.load || '-' }}</span></li> <li><span>船长:</span><span>{{ props.boatInfo.length || '-' }}</span></li> <li><span>船宽:</span><span>{{ props.boatInfo.width || '-' }}</span></li> <li><span>船高:</span><span>{{ props.boatInfo.height || '-' }}</span></li> </ul> <ul class="gzxx-warning"> <li v-for="item in warningData.value" :class="{'isOn': item.isWarning}"><i></i><span>{{ item.name }}</span></li> </ul> </div> <div class="boat-playback"> <div class="cb-row1"> <span :class="{'highlight': bottomType==='playback'}" @click="toggleBottom('playback')">轨迹回放</span> <span :class="{'highlight': bottomType==='pic'}" @click="toggleBottom('pic')">过船图片</span> </div> <div class="cb-time"> <div> <i class="cbt-icon"></i> <el-date-picker v-model="timeRange.time1" type="datetime" placeholder="请选择" size="small" popper-class="date-popper" class="date-picker-custom1" value-format="YYYY-MM-DD HH:mm:ss" /> </div> <div> <i class="cbt-icon"></i> <el-date-picker v-model="timeRange.time2" type="datetime" placeholder="请选择" size="small" popper-class="date-popper" class="date-picker-custom1" value-format="YYYY-MM-DD HH:mm:ss" /> </div> </div> <div class="cb-play"> <span class="speed" :class="{'selected': playSpeed===1.5}" @click="ChangePlaySpeed(1.5)">x1.5</span> <span class="speed" :class="{'selected': playSpeed===2}" @click="ChangePlaySpeed(2)">x2.0</span> <span class="speed" :class="{'selected': playSpeed===3}" @click="ChangePlaySpeed(3)">x3.0</span> <span class="play-btn" :class="{'btn-disabled': playState===-1}" v-show="playState<1" @click="track_play">播放</span> <span class="play-btn" v-show="playState===1||playState===2" @click="track_stop">停止</span> <span class="play-btn" v-show="playState===1" @click="track_pause">暂停</span> <span class="play-btn" v-show="playState===2" @click="track_resume">继续</span> </div> </div> <div class="pic-carousel-wrapper" v-show="picsShow"> <i class="pc-switch-left" @click="pcSwitch('left')"></i> <i class="pc-switch-right" @click="pcSwitch('right')"></i> <i class="pc-close" @click="picsShow=false;bottomType='playback'"></i> <el-carousel type="card" class="pic-carousel" arrow="never" :autoplay="false" ref="pic_carousel" > <el-carousel-item v-for="pic, index in props.boatInfo.photoList" :key="pic"> <img :src="pic" :alt="'过船图片-'+(index+1)" class="pics"> </el-carousel-item> </el-carousel> </div> </div> </template> <script> export default { name: 'BoatKkjk', } </script> <script setup> import { reactive, ref, watch, onBeforeUnmount, nextTick } from 'vue' import { ElDatePicker,ElMessage } from 'element-plus' import 'element-plus/es/components/message/style/css' import 'element-plus/es/components/date-picker/style/css' import { ElCarousel, ElCarouselItem } from 'element-plus' import 'element-plus/es/components/carousel/style/css' import 'element-plus/es/components/carousel-item/style/css' import bus from '@/utils/bus' import { ueCallBoatGuiji, ueCallSetBoatDriveSpeed, ueCallBoatDrive, ueCallBoatCloseDrive, ueCallBoatStop, ueCallBoatContinue, ueCallChangeTrackType } from '@/utils/UIInteractions' import { useDateFormat } from '@vueuse/core' const props = defineProps(['boat-info']) const cameraType = ref('follow') function toggleCamera(type) { cameraType.value = type ueCallChangeTrackType(type) } const sjrhData = reactive({ video: false, laser: false, AIS: false, RFID: false, }) watch(()=>props.boatInfo, (val) => { nextTick(() => { warningData.value.forEach(i => { if(val.warningList.length===0) { i.isWarning = false } else { val.warningList.forEach(j => { if(i.fullName===j.warningType) { i.isWarning = true return } else { i.isWarning = false } }) } }) if(!val.isFinish) { return } val.isFinish.split('').forEach((i,index) => { switch (index) { case 0: sjrhData.AIS = +i break case 1: sjrhData.video = +i break case 3: sjrhData.RFID = +i } }) timeRange.time1 = useDateFormat((new Date).getTime() - 30 * 60 * 1000, 'YYYY-MM-DD HH:mm:00').value timeRange.time2 = useDateFormat((new Date).getTime(), 'YYYY-MM-DD HH:mm:00').value }) },{immediate:true}) const currentTab = ref('cbxx') const warningData = reactive({value:[ { name: 'AIS', fullName: 'AIS未开启', isWarning: false }, { name: '报港', fullName: '申报预警', isWarning: false }, { name: '超载', fullName: '超载预警', isWarning: false }, { name: '重点', fullName: '重点监控船舶', isWarning: false }, // { name: '超限', fullName: '超限预警', isWarning: false }, { name: '证书', fullName: '船舶证书预警', isWarning: false }, // { name: '救生衣', fullName: '未穿救生衣', isWarning: false }, { name: '自定义', fullName: '自定义预警', isWarning: false }, ]}) const timeRange = reactive({ time1: '', time2: '' }) bus.on('ueRec_boatGuiji', (data) => { if(data.isOk=='true') { playState.value=0 } else { ElMessage({type: 'warning',message:'此船舶该时段未查到轨迹点'}) } }) onBeforeUnmount(() => { bus.off('ueRec_boatGuiji') bus.off('ueRec_boatFockClear') ueCallBoatCloseDrive() }) const bottomType = ref('playback') const picsShow = ref(false) const pic_carousel = ref(null) function pcSwitch(type) { if(type==='left') { pic_carousel.value.prev() } else if(type==='right') { pic_carousel.value.next() } } function toggleBottom(type) { if(type==='pic') { picsShow.value = true // let len = document.getElementsByClassName('pics').length // for(let i=0; i<len; i++) { // document.getElementsByClassName('pics')[i].addEventListener('wheel', (e) => { // console.log(e) // }) // } } bottomType.value = type } const playSpeed = ref(1) const playState = ref(0) /* 0--未开始/已结束; 1--播放中; 2--已暂停; -1--禁用状态 */ function ChangePlaySpeed(s) { playSpeed.value = s===playSpeed.value? 1: s ueCallSetBoatDriveSpeed(playSpeed.value) } function track_play() { if(timeRange.time1&&timeRange.time2) { playState.value=-1 ueCallBoatGuiji(timeRange.time1, timeRange.time2) let timer = setInterval(() => { if(playState.value===-1) { return } ueCallBoatDrive() playState.value = 1 clearInterval(timer) }, 300); } } function track_stop() { playState.value = 0 ueCallBoatCloseDrive() } function track_pause() { playState.value = 2 ueCallBoatStop() } function track_resume() { playState.value = 1 ueCallBoatContinue() } const emit = defineEmits(['closeBoatInfo']) function changeTab(name) { currentTab.value = name } </script> <style lang="scss" scoped> .boat-info { box-sizing: border-box; width: 429px; height: 374px; background: url('@/assets/imgs/page_kkjk/bi-bg-1.png') no-repeat; background-size: contain; .dialog-close { top: 8px; } &.tab-bgxx { height: 408px; background: url('@/assets/imgs/page_kkjk/bi-bg-2.png') no-repeat; background-size: contain; } &.tab-gzxx { height: 494px; background: url('@/assets/imgs/page_kkjk/bi-bg-3.png') no-repeat; background-size: contain; } .bi-tab { padding-right: 20px; margin: 10px 0 20px; &>div.highlight::after { display: none; } } .cf-cbxx { margin: 15px 0 16px; li { margin-bottom: 10px; } } .cf-bgxx { margin-bottom: 22px; } .content-gzxx { margin-bottom: 28px; .sjrh-wrapper { display: flex; justify-content: space-between; align-items: center; box-sizing: border-box; padding: 0 40px 0 30px; margin-bottom: 25px; &>span:first-child { font-size: 14px; color: #D9E6FF; text-shadow: 0px 3px 5px rgba(0,38,76,0.4); } .sjrh-btn { display: block; width: 71px; height: 30px; background: url('@/assets/imgs/page_kkjk/bi-sjrh-btn1.png'); background-size: 89px 37px; background-position: center; cursor: pointer; line-height: 30px; font-size: 14px; color: #eee; &.disabled { filter: brightness(0.5); } } } .gzxx-fields { &>li>span:first-child { width: 50px; } } .gzxx-warning { box-sizing: border-box; padding: 0 20px 0 10px; display: flex; justify-content: center; align-items: center; margin-top: 6px; &>li { display: flex; flex-direction: column; align-items: center; &.isOn { &>i { background: url('@/assets/imgs/page_kkjk/bi-warning-on.png'); background-size: contain; } &>span { color: rgba($color: #fff, $alpha: 0.9); } } &>i { display: block; width: 20px; height: 20px; background: url('@/assets/imgs/page_kkjk/bi-warning-off.png'); background-size: contain; margin-top: 8px; } &>span { font-size: 12px; line-height: 12px; color: rgba($color: #fff, $alpha: 0.3); } width: 51px; height: 51px; background: url('@/assets/imgs/page_kkjk/bi-warning-bg.png'); background-size: contain; } } } .pic-carousel-wrapper { position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; background-color: rgba($color: #000000, $alpha: 0.7); z-index: 999; :deep(.pic-carousel) { position: absolute; top: 20%; left: 50%; transform: translateX(-50%); width: 85%; height: 55vh; .el-carousel__indicators { display: none; } .el-carousel__container { height: 100%; } .el-carousel__item { box-sizing: border-box; border: 1px solid #4DA6FF; &:not(.is-active) { filter: brightness(60%); } &>img { width: 100%; height: 100%; } } } .pc-switch-right,.pc-switch-left { display: block; position: absolute; top: 46%; width: 35px; height: 59px; cursor: pointer; } .pc-switch-left { left: 4%; background: url('@/assets/imgs/navi/sxdx-arrow-left.png'); background-size: contain; } .pc-switch-right { right: 4%; background: url('@/assets/imgs/navi/sxdx-arrow-right.png'); background-size: contain; } .pc-close { display: block; position: absolute; bottom: 17%; left: calc(50% - 12px); width: 24px; height: 24px; cursor: pointer; background: url('@/assets/imgs/page_kkjk/bi-pics-close.png'); background-size: contain; &:hover { transform: scale(1.1); } } } } </style>