You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

189 lines
4.7 KiB

<template>
<div class="ship-shore-power">
<div class="left" style="width: 800px;">
<div class="card digital-twin-card--deep-blue " style="flex: 1;">
<div class="card-title">
<div class="vertical-line"></div>
<img src="@/assets/svgs/data.svg" class="title-icon" />
<span class="title-text">概览</span>
</div>
<div class="card-content">
<div class="overview-grid">
<div class="overview-item">
<div class="overview-value">{{ berthingShips }}</div>
<div class="overview-label">在泊船舶数量</div>
</div>
<div class="overview-item">
<div class="overview-value">{{ shorePowerShips }}</div>
<div class="overview-label">使用岸电船舶数量</div>
</div>
<div class="overview-item">
<div class="overview-value">{{ noShorePowerShips }}</div>
<div class="overview-label">未使用岸电船舶数量</div>
</div>
</div>
</div>
</div>
<div class="card digital-twin-card--deep-blue " style="flex: 3;">
<div class="card-title">
<div class="vertical-line"></div>
<img src="@/assets/svgs/data.svg" class="title-icon" />
<span class="title-text">数据</span>
</div>
<div class="card-content">
<div class="ship-data-table-container" ref="scrollContainerRef">
<div class="ship-data-table">
<div v-for="(ship, index) in shipData" :key="index" class="ship-data-row">
<div class="ship-data-cell ship-name">{{ ship.name }}</div>
<div class="ship-data-cell wharf-name">{{ ship.wharf }}</div>
<div class="ship-data-cell berth-number">{{ ship.berth }}</div>
<div class="ship-data-cell shore-power-status" :class="ship.statusClass">{{ ship.status }}</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, watch } from 'vue'
// 定义组件属性
interface ShipDataItem {
name: string;
wharf: string;
berth: string;
status: string;
statusClass: string;
}
interface Props {
berthingShips: number;
shorePowerShips: number;
noShorePowerShips: number;
shipData: ShipDataItem[];
}
const props = defineProps<Props>()
// 滚动容器引用
const scrollContainerRef = ref<HTMLElement | null>(null)
// 滚动相关变量
let scrollInterval: NodeJS.Timeout | null = null
const scrollSpeed = ref<number>(20) // 滚动速度,越小越快
// 开始滚动
const startScroll = () => {
if (!scrollContainerRef.value) return
const container = scrollContainerRef.value
const content = container.querySelector('.ship-data-table')
if (!content) return
// 计算滚动距离
const scrollDistance = content.offsetHeight - container.clientHeight
if (scrollDistance <= 0) return // 内容高度小于容器高度,不需要滚动
let currentScroll = 0
let direction = 1 // 1 向下滚动,-1 向上滚动
// 清除可能存在的旧定时器
if (scrollInterval) {
clearInterval(scrollInterval)
}
// 创建新的滚动定时器
scrollInterval = setInterval(() => {
if (!scrollContainerRef.value) return
currentScroll += direction * scrollSpeed.value
// 检查是否到达边界
if (currentScroll >= scrollDistance) {
currentScroll = scrollDistance
direction = -1
} else if (currentScroll <= 0) {
currentScroll = 0
direction = 1
}
// 应用滚动
scrollContainerRef.value.scrollTop = currentScroll
}, 100)
}
// 停止滚动
const stopScroll = () => {
if (scrollInterval) {
clearInterval(scrollInterval)
scrollInterval = null
}
}
// 监听activeHeadGroup变化
watch(
() => props.shipData,
() => {
// 数据变化时重新开始滚动
stopScroll()
startScroll()
},
{ deep: true }
)
// 组件挂载时开始滚动
onMounted(() => {
// 延迟启动滚动,确保DOM已经渲染完成
setTimeout(() => {
startScroll()
}, 500)
})
// 组件销毁前停止滚动
onBeforeUnmount(() => {
stopScroll()
})
</script>
<style scoped>
.ship-shore-power {
display: flex;
height: 100%;
gap: 10px;
}
.ship-data-table-container {
height: 100%;
overflow-y: auto;
}
.ship-data-table {
width: 100%;
}
.ship-data-row {
display: flex;
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}
.ship-data-cell {
flex: 1;
padding: 10px;
color: #fff;
}
.shore-power-status {
font-weight: bold;
}
.shore-power-status.status-on {
color: #4CAF50;
}
.shore-power-status.status-off {
color: #F44336;
}
</style>