Browse Source

update

feature
jiangAB 2 months ago
parent
commit
7e8c0a1607
  1. 33
      public/map/components/CompanyShorePower.vue
  2. 6
      public/map/components/ShipShorePower.vue
  3. 6
      public/map/components/ShorePowerUsage.vue
  4. 648
      public/map/components/ShowData.vue
  5. 84
      public/map/components/cesiumMap.vue
  6. 48
      public/map/index.vue

33
public/map/components/CompanyShorePower.vue

@ -8,7 +8,12 @@
<div class="vertical-line"></div> <div class="vertical-line"></div>
<img src="@/assets/svgs/data.svg" class="title-icon" /> <img src="@/assets/svgs/data.svg" class="title-icon" />
<span class="title-text">码头与泊位信息</span> <span class="title-text">码头与泊位信息</span>
<div class="data-update-time">更新时间: {{ realtimeDeviceDataTime }}</div>
</div> </div>
<!-- 返回上个页面 -->
<el-button type="primary" @click.stop="handleGoBack()">返回</el-button>
<!-- <div> <!-- <div>
<el-date-picker type="daterange" range-separator="" start-placeholder="开始日期" end-placeholder="结束日期" <el-date-picker type="daterange" range-separator="" start-placeholder="开始日期" end-placeholder="结束日期"
format="YYYY-MM-DD" value-format="YYYY-MM-DD" class="date-range-picker" /> format="YYYY-MM-DD" value-format="YYYY-MM-DD" class="date-range-picker" />
@ -19,7 +24,10 @@
<div class="card-content"> <div class="card-content">
<div v-for="company in companyComparisonData" :key="company.name" class="company-section"> <div v-for="company in companyComparisonData" :key="company.name" class="company-section">
<div class="company-header"> <div class="company-header">
<div class="company-info">
<div class="company-name">{{ company.name }}</div> <div class="company-name">{{ company.name }}</div>
<div class="company-berth-count">泊位数: {{ company.children?.length || 0 }}</div>
</div>
<div class="company-total">总量: {{ calculateTotal(company.children).toFixed(2) }}</div> <div class="company-total">总量: {{ calculateTotal(company.children).toFixed(2) }}</div>
</div> </div>
<div class="overview-grid"> <div class="overview-grid">
@ -100,8 +108,8 @@
</div> </div>
</div> </div>
</div> </div>
<ship-history-dialog v-if="historyVisible.visible" v-model="historyVisible.visible" <ship-history-dialog v-model="historyVisible.visible" :ship-param="historyVisible.searchParams"
:ship-param="historyVisible.searchParams" :realtime-device-data="realtimeDeviceData" /> :realtime-device-data="realtimeDeviceData" />
</div> </div>
</template> </template>
@ -131,7 +139,9 @@ const historyVisible = ref({
interface Props { interface Props {
realtimeDeviceData: RealtimeDeviceData[]; realtimeDeviceData: RealtimeDeviceData[];
realtimeDeviceDataTime: string;
shorePowerList: ShorePowerBerth[]; shorePowerList: ShorePowerBerth[];
handleGoBack: () => void;
} }
const props = defineProps<Props>() const props = defineProps<Props>()
@ -300,12 +310,24 @@ onMounted(() => {
padding: 0 4px; padding: 0 4px;
} }
.company-info {
display: flex;
align-items: baseline;
gap: 2px
}
.company-name { .company-name {
font-size: 24px; font-size: 24px;
font-weight: bold; font-weight: bold;
color: #fff; color: #fff;
} }
.company-berth-count {
font-size: 16px;
color: #aaa;
margin-top: 4px;
}
.company-total { .company-total {
font-size: 24px; font-size: 24px;
font-weight: bold; font-weight: bold;
@ -315,6 +337,13 @@ onMounted(() => {
border-radius: 4px; border-radius: 4px;
} }
.data-update-time {
margin-left: 6px;
font-size: 16px;
color: #aaa;
white-space: nowrap;
}
/* 自定义滚动条样式 */ /* 自定义滚动条样式 */
.card-content::-webkit-scrollbar { .card-content::-webkit-scrollbar {
width: 6px; width: 6px;

6
public/map/components/ShipShorePower.vue

@ -2,11 +2,16 @@
<div class="ship-shore-power"> <div class="ship-shore-power">
<div class="left" style="width: 70%;"> <div class="left" style="width: 70%;">
<div class="card digital-twin-card--deep-blue" style="flex: 1;"> <div class="card digital-twin-card--deep-blue" style="flex: 1;">
<div style="display: flex; justify-content: space-between; align-items: center;">
<div class="card-title"> <div class="card-title">
<div class="vertical-line"></div> <div class="vertical-line"></div>
<img src="@/assets/svgs/data.svg" class="title-icon" /> <img src="@/assets/svgs/data.svg" class="title-icon" />
<span class="title-text">概览</span> <span class="title-text">概览</span>
</div> </div>
<el-button type="primary" @click.stop="handleGoBack()">返回</el-button>
</div>
<div class="card-content"> <div class="card-content">
<div class="overview-grid"> <div class="overview-grid">
<div class="overview-item"> <div class="overview-item">
@ -599,6 +604,7 @@ import { formatTimestamp, getValueById, showStatus } from './utils';
interface Props { interface Props {
shipData: ShipRespVo[]; shipData: ShipRespVo[];
realtimeDeviceData: RealtimeDeviceData[]; realtimeDeviceData: RealtimeDeviceData[];
handleGoBack: () => void;
} }

6
public/map/components/ShorePowerUsage.vue

@ -154,6 +154,9 @@
@click.stop="handleTimeRangeChange(option.value)"> @click.stop="handleTimeRangeChange(option.value)">
{{ option.label }} {{ option.label }}
</button> </button>
<!-- 返回上个页面 -->
<el-button type="primary" @click.stop="handleGoBack()">返回</el-button>
</div> </div>
<div v-if="card.type === 'chart'" class="show-value"> <div v-if="card.type === 'chart'" class="show-value">
<span class="show-value-label">{{timeRangeOptions.find(option => option.value === timeRange)?.label || <span class="show-value-label">{{timeRangeOptions.find(option => option.value === timeRange)?.label ||
@ -507,6 +510,7 @@ import { formatTimestamp, parseRangeToTimestamp } from './utils';
interface Props { interface Props {
realtimeDeviceData: RealtimeDeviceData[]; realtimeDeviceData: RealtimeDeviceData[];
activeHeadGroup?: number; activeHeadGroup?: number;
handleGoBack?: () => void;
} }
const props = defineProps<Props>() const props = defineProps<Props>()
@ -1166,7 +1170,7 @@ onBeforeUnmount(() => {
} }
.magnify { .magnify {
width: 40%; width: 100%;
padding: 12px; padding: 12px;
height: calc(100vh - 72px); height: calc(100vh - 72px);
position: absolute; position: absolute;

648
public/map/components/ShowData.vue

@ -0,0 +1,648 @@
<template>
<div class="show-data">
<div class="right" style="width: 800px">
<div class="card digital-twin-card--deep-blue">
<div class="card-title">
<div class="vertical-line"></div>
<img src="@/assets/svgs/data.svg" class="title-icon" />
<!-- <span class="title-text">岸电管理大屏系统</span> -->
<span class="title-date">{{ currentDate }}</span>
<span class="update-time">更新时间: {{ realtimeDeviceDataTime }}</span>
</div>
<div class="card-content">
<!-- 港口岸电使用情况 -->
<div class="module-section">
<div class="module-header">
<h3 class="module-title" @click="handleGoToModule(1)">港口岸电使用情况</h3>
<div class="period-filter">
<div v-for="period in periodOptions" :key="period"
:class="['period-option', { active: activePeriod === period }]" @click="switchPeriod(period)">
{{ period }}
</div>
</div>
</div>
<div class="port-overview">
<div class="first-row">
<div class="benefit-card">
<div class="benefit-value">835380.87</div>
<div class="benefit-unit">累计用电 (千瓦时)</div>
</div>
<div class="benefit-card">
<div class="benefit-value">559705.19</div>
<div class="benefit-unit">减少二氧化碳排放 (千克)</div>
</div>
</div>
<div class="second-row">
<div class="benefit-card">
<div class="benefit-value">105.25</div>
<div class="benefit-unit">减少燃油 ()</div>
</div>
<div class="benefit-card">
<div class="benefit-value">1219.66</div>
<div class="benefit-unit">减少PM2.5排放 (千克)</div>
</div>
<div class="benefit-card">
<div class="benefit-value">15120.39</div>
<div class="benefit-unit">减少氮氧化物 (千克)</div>
</div>
<div class="benefit-card">
<div class="benefit-value">8771.51</div>
<div class="benefit-unit">减少二氧化硫 (千克)</div>
</div>
</div>
</div>
</div>
<!-- 港口企业岸电使用 -->
<div class="module-section">
<div class="module-header">
<h3 class="module-title" @click="handleGoToModule(2)">港口企业岸电使用</h3>
<div class="period-filter">
<div v-for="period in periodOptions" :key="period"
:class="['period-option', { active: activePeriod === period }]" @click="switchPeriod(period)">
{{ period }}
</div>
</div>
</div>
<div class="enterprise-usage">
<div class="usage-bars">
<div class="bar-item">
<div class="bar-header">
<span class="bar-name">华能码头</span>
<span class="bar-value">232235.88 kWH</span>
</div>
<el-progress :percentage="65" :show-text="false" />
</div>
<div class="bar-item">
<div class="bar-header">
<span class="bar-name">国投码头</span>
<span class="bar-value">413513.53 kWH</span>
</div>
<el-progress :percentage="95" :show-text="false" />
</div>
<div class="bar-item">
<div class="bar-header">
<span class="bar-name">华电码头 (储运)</span>
<span class="bar-value">189631.46 kWH</span>
</div>
<el-progress :percentage="55" :show-text="false" />
</div>
</div>
<!-- <div class="current-usage">
<div class="usage-detail">
<span>华能码头</span>
<span>3泊位</span>
<span>华元503</span>
<span>正在用电</span>
<span>2192kWH</span>
</div>
</div> -->
</div>
</div>
<!-- 船舶岸电使用情况 -->
<div class="module-section">
<div class="module-header">
<h3 class="module-title" @click="handleGoToModule(3)">船舶岸电使用情况</h3>
<div class="period-filter">
<div v-for="period in periodOptions" :key="period"
:class="['period-option', { active: activePeriod === period }]" @click="switchPeriod(period)">
{{ period }}
</div>
</div>
</div>
<div class="ship-status">
<div class="usage-rate">
<div class="rate-value">23.08%</div>
<div class="rate-label">岸电使用率</div>
</div>
<div class="status-grid">
<div class="status-card">
<div class="status-value">13</div>
<div class="status-label">在港船舶数量</div>
</div>
<div class="status-card">
<div class="status-value">3</div>
<div class="status-label">使用岸电船舶数量</div>
</div>
<div class="status-card">
<div class="status-value">10</div>
<div class="status-label">未使用岸电船舶数量</div>
</div>
</div>
<!-- <div class="ship-list">
<div class="ship-item">
<span class="ship-name">华元503</span>
<span class="ship-dock">华能码头</span>
<span class="ship-berth">3泊位</span>
<span class="ship-status-text">使用岸电21小时45分钟, 2479kWH</span>
</div>
<div class="ship-item">
<span class="ship-name">信洋新征程</span>
<span class="ship-dock">国投码头</span>
<span class="ship-berth">202#泊位</span>
<span class="ship-status-text">无受电设备</span>
</div>
<div class="ship-item">
<span class="ship-name">华海航2</span>
<span class="ship-dock">华电码头 (储运)</span>
<span class="ship-berth">806泊位</span>
<span class="ship-status-text">船电设施损坏, 预计2025-11-30恢复</span>
</div>
<div class="ship-item">
<span class="ship-name">东亿603</span>
<span class="ship-dock">国投码头</span>
<span class="ship-berth">205#泊位</span>
<span class="ship-status-text">电缆长度不匹配</span>
</div>
<div class="ship-item">
<span class="ship-name">东成山</span>
<span class="ship-dock">华能码头</span>
<span class="ship-berth">2泊位</span>
<span class="ship-status-text">岸电用电接口不匹配</span>
</div>
<div class="ship-item">
<span class="ship-name">中茂98</span>
<span class="ship-dock">华电码头 (储运)</span>
<span class="ship-berth">807泊位</span>
<span class="ship-status-text">岸电设施维护中</span>
</div>
</div> -->
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, computed } from 'vue'
interface Props {
handleGoToModule: (moduleType: number) => void
realtimeDeviceDataTime: string
}
defineProps<Props>()
//
const currentDate = computed(() => {
const now = new Date()
const year = now.getFullYear()
const month = String(now.getMonth() + 1).padStart(2, '0')
const day = String(now.getDate()).padStart(2, '0')
return `${year}-${month}-${day}`
})
//
const updateTime = computed(() => {
const now = new Date()
const hours = String(now.getHours()).padStart(2, '0')
const minutes = String(now.getMinutes()).padStart(2, '0')
const seconds = String(now.getSeconds()).padStart(2, '0')
return `${hours}:${minutes}:${seconds}`
})
//
const activePeriod = ref('今日')
const periodOptions = ['今日', '本月', '本年', '全部']
//
const rankingData = {
今日: [
{ rank: 1, name: '华能曹妃甸港口有限公司', value: '350,000', change: '+15%', isUp: true },
{ rank: 2, name: '河北华电曹妃甸储运有限公司', value: '280,000', change: '+8%', isUp: true },
{ rank: 3, name: '国投曹妃甸港口有限公司', value: '220,000', change: '-3%', isUp: false }
],
本月: [
{ rank: 1, name: '华能曹妃甸港口有限公司', value: '8,350,000', change: '+12%', isUp: true },
{ rank: 2, name: '国投曹妃甸港口有限公司', value: '7,280,000', change: '+5%', isUp: true },
{ rank: 3, name: '河北华电曹妃甸储运有限公司', value: '6,220,000', change: '-2%', isUp: false }
],
本年: [
{ rank: 1, name: '华能曹妃甸港口有限公司', value: '120,350,000', change: '+18%', isUp: true },
{ rank: 2, name: '国投曹妃甸港口有限公司', value: '95,280,000', change: '+9%', isUp: true },
{ rank: 3, name: '河北华电曹妃甸储运有限公司', value: '82,220,000', change: '+3%', isUp: true }
],
全部: [
{ rank: 1, name: '华能曹妃甸港口有限公司', value: '2,120,350,000', change: '+15%', isUp: true },
{ rank: 2, name: '国投曹妃甸港口有限公司', value: '1,095,280,000', change: '+11%', isUp: true },
{ rank: 3, name: '河北华电曹妃甸储运有限公司', value: '882,220,000', change: '+7%', isUp: true }
]
}
//
const currentRankingData = computed(() => {
return rankingData[activePeriod.value as keyof typeof rankingData] || []
})
//
const switchPeriod = (period: string) => {
activePeriod.value = period
}
</script>
<style scoped>
.show-data {
display: flex;
gap: 10px;
height: 100%;
}
.card {
padding-right: 0px;
padding-left: 12px;
}
.card-content {
display: flex;
flex-direction: column;
gap: 12px;
padding: 12px;
}
.card-title {
display: flex;
align-items: center;
}
.title-text {
font-size: 28px;
font-weight: bold;
}
.title-date {
font-size: 16px;
color: #a0cfff;
margin-left: auto;
padding-right: 20px;
}
.update-time {
font-size: 14px;
color: #67c23a;
margin-left: 10px;
padding-right: 20px;
}
.section-title {
font-size: 24px;
font-weight: bold;
color: #409eff;
margin: 0;
padding-bottom: 6px;
border-bottom: 1px solid rgba(64, 158, 255, 0.3);
}
.module-section {
margin-bottom: 0px;
}
.module-header {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 8px;
/* border-bottom: 2px solid rgba(64, 158, 255, 0.3); */
}
.module-title {
font-size: 24px;
font-weight: bold;
color: #409eff;
text-decoration: underline;
margin: 0;
cursor: pointer;
transition: all 0.3s ease;
user-select: none;
}
.module-title:hover {
transform: translateY(-2px);
color: #66b1ff;
}
.module-title:active {
transform: translateY(-4px);
color: #337ecc;
text-decoration: none;
}
/* 港口岸电使用情况 */
.port-overview {
margin-bottom: 6px;
}
.first-row {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 8px;
margin-bottom: 8px;
}
.second-row {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 8px;
}
.total-electricity {
text-align: center;
margin-bottom: 20px;
padding: 20px;
background: rgba(30, 120, 255, 0.1);
border-radius: 10px;
}
.total-value {
font-size: 48px;
font-weight: bold;
color: #FFF;
margin-bottom: 5px;
}
.total-unit {
font-size: 16px;
color: #a0cfff;
}
.benefits-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 15px;
}
.benefit-card {
background: rgba(30, 120, 255, 0.1);
border: 1px solid rgba(64, 158, 255, 0.3);
border-radius: 8px;
padding: 15px;
text-align: center;
}
.benefit-value {
font-size: 28px;
font-weight: bold;
color: #FFF;
margin-bottom: 5px;
}
.benefit-unit {
font-size: 14px;
color: #a0cfff;
}
/* 港口企业岸电使用 */
.enterprise-usage {
margin-bottom: 20px;
}
.usage-bars {
margin-bottom: 15px;
}
.bar-item {
margin-bottom: 15px;
}
.bar-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 5px;
}
.bar-name {
font-size: 16px;
color: #a0cfff;
}
.bar-value {
font-size: 14px;
color: #FFF;
font-weight: bold;
}
:deep(.el-progress-bar__outer) {
background: rgba(30, 120, 255, 0.2);
border-radius: 10px;
overflow: hidden;
}
:deep(.el-progress-bar__inner) {
background: linear-gradient(90deg, #67c23a, #409eff);
border-radius: 10px;
}
.current-usage {
background: rgba(30, 120, 255, 0.1);
border: 1px solid rgba(64, 158, 255, 0.3);
border-radius: 8px;
padding: 15px;
}
.usage-detail {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 16px;
color: #a0cfff;
}
/* 船舶岸电使用情况 */
.ship-status {
margin-bottom: 8px;
}
.usage-rate {
text-align: center;
padding: 20px;
background: rgba(30, 120, 255, 0.1);
border-radius: 10px;
margin-bottom: 8px;
}
.rate-value {
font-size: 48px;
font-weight: bold;
color: #FFF;
margin-bottom: 5px;
}
.rate-label {
font-size: 16px;
color: #a0cfff;
}
.status-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 8px;
margin-bottom: 8px;
}
.status-card {
background: rgba(30, 120, 255, 0.1);
border: 1px solid rgba(64, 158, 255, 0.3);
border-radius: 8px;
padding: 20px;
text-align: center;
}
.status-value {
font-size: 36px;
font-weight: bold;
color: #FFF;
margin-bottom: 5px;
}
.status-label {
font-size: 16px;
color: #a0cfff;
}
.ship-list {
background: rgba(30, 120, 255, 0.1);
border: 1px solid rgba(64, 158, 255, 0.3);
border-radius: 8px;
padding: 15px;
}
.ship-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
border-bottom: 1px solid rgba(64, 158, 255, 0.2);
}
.ship-item:last-child {
border-bottom: none;
}
.ship-name {
font-size: 16px;
color: #67c23a;
font-weight: bold;
width: 120px;
}
.ship-dock {
font-size: 16px;
color: #a0cfff;
width: 120px;
}
.ship-berth {
font-size: 16px;
color: #a0cfff;
width: 100px;
}
.ship-status-text {
font-size: 14px;
color: #a0cfff;
text-align: right;
flex: 1;
}
/* 分公司排名样式 */
.period-filter {
display: flex;
gap: 10px;
margin-bottom: 0;
}
.period-option {
padding: 4px 8px;
background: rgba(30, 120, 255, 0.1);
border: 1px solid rgba(64, 158, 255, 0.3);
border-radius: 8px;
color: #a0cfff;
cursor: pointer;
transition: all 0.3s ease;
}
.period-option:hover {
background: rgba(30, 120, 255, 0.2);
}
.period-option.active {
background: #409eff;
color: white;
border-color: #409eff;
}
.ranking-list {
display: flex;
flex-direction: column;
gap: 6px;
}
.ranking-item {
display: flex;
align-items: center;
padding: 10px 12px;
background: rgba(30, 120, 255, 0.05);
border-radius: 8px;
border: 1px solid rgba(30, 120, 255, 0.1);
}
.change {
font-size: 16px;
font-weight: bold;
}
.up {
color: #67c23a;
}
.down {
color: #f56c6c;
}
.rank-number {
width: 24px;
height: 24px;
border-radius: 50%;
background: #409eff;
color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: bold;
margin-right: 12px;
}
.first .rank-number {
background: #ffd700;
color: #333;
}
.second .rank-number {
background: #c0c0c0;
color: #333;
}
.third .rank-number {
background: #cd7f32;
color: #333;
}
.branch-name {
flex: 1;
font-size: 20px;
color: #e6f2ff;
}
.branch-value {
font-size: 26px;
font-weight: bold;
color: #409eff;
min-width: 140px;
text-align: right;
margin-right: 12px;
}
</style>

84
public/map/components/cesiumMap.vue

@ -196,6 +196,27 @@ const createView = (obj) => {
} }
} }
//
const createPulsingLabel = (text, color) => {
return {
text: text,
font: '28px sans-serif',
fillColor: new Cesium.CallbackProperty(function (time, result) {
// t
const t = Cesium.JulianDate.toDate(time).getTime() / 1000;
//
const alpha = 0.7 + Math.sin(t * 4) * 0.3; // 0.4-1.0
return color.withAlpha(alpha);
}, false),
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
disableDepthTest: true,
scaleByDistance: new Cesium.NearFarScalar(1000, 1.0, 50000, 0.1)
// scale
};
};
onMounted(async () => { onMounted(async () => {
if (!Cesium) { if (!Cesium) {
console.error("Cesium 对象未找到,请检查 index.html 文件!"); console.error("Cesium 对象未找到,请检查 index.html 文件!");
@ -826,43 +847,16 @@ onMounted(async () => {
type: 'ship', type: 'ship',
data: item data: item
}) })
let labelColor = null
const MODEL_HEIGHT_METERS = 80;
const cartographic = Cesium.Cartographic.fromCartesian(xposition);
const labelAltitude = cartographic.height + MODEL_HEIGHT_METERS;
const labelPosition = Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
labelAltitude
);
const xelectricalBoxLabel = viewer.entities.add({
// 使 3D
position: labelPosition,
name: '船',
properties: {
modelType: 'ship',
data: item
},
label: {
text: item.shipBasicInfo.name,
font: '28px sans-serif',
fillColor: Cesium.Color.LIME,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
disableDepthTest: true,
scaleByDistance: new Cesium.NearFarScalar(1000, 1.0, 50000, 0.1)
}
});
labelInstance.push(xelectricalBoxLabel)
let statusImage = null; let statusImage = null;
if (item.shipStatus === '正常') { if (item.shipStatus === '正常') {
// statusImage = null; // statusImage = null;
} else if (item.shipStatus === '超容') { } else if (item.shipStatus === '超容') {
statusImage = '/img/故障.png'; statusImage = '/img/故障.png';
labelColor = Cesium.Color.YELLOW; //
} else { } else {
statusImage = '/img/未连接.png'; statusImage = '/img/未连接.png';
labelColor = Cesium.Color.RED; // 线
} }
// //
if (statusImage) { if (statusImage) {
@ -887,6 +881,36 @@ onMounted(async () => {
}); });
} }
const MODEL_HEIGHT_METERS = 80;
const cartographic = Cesium.Cartographic.fromCartesian(xposition);
const labelAltitude = cartographic.height + MODEL_HEIGHT_METERS;
const labelPosition = Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
labelAltitude
);
const xelectricalBoxLabel = viewer.entities.add({
// 使 3D
position: labelPosition,
name: '船',
properties: {
modelType: 'ship',
data: item
},
label: !labelColor ? {
text: item.shipBasicInfo.name,
font: '28px sans-serif',
fillColor: Cesium.Color.LIME,
outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
style: Cesium.LabelStyle.FILL_AND_OUTLINE,
disableDepthTest: true,
scaleByDistance: new Cesium.NearFarScalar(1000, 1.0, 50000, 0.1)
} : createPulsingLabel(item.shipBasicInfo.name, labelColor)
});
labelInstance.push(xelectricalBoxLabel)
/* if (!itemShipInfo) { /* if (!itemShipInfo) {
return; return;
} */ } */

48
public/map/index.vue

@ -10,17 +10,14 @@
<div class="head"> <div class="head">
<div class="head-title"> <div class="head-title">
<span>曹妃甸港区船舶岸电监管平台</span> <span>曹妃甸港区船舶岸电监管平台</span>
</div>
<el-button class="view-btn" size="small" type="success" @click="handleOverviewClick"
style="margin-right: 10px;">概览视角</el-button>
<div class="head-group"> <div class="head-group">
<div v-for="item in headGroupList" :key="item.value" class="head-group-item" <div class="head-group-item" size="small" type="success" @click="handleOverviewClick"
:class="{ 'active': activeHeadGroup === item.value }" @click="selectHeadGroup(item.value)"> style="margin-right: 10px;">
{{ item.label }} 概览视角</div>
</div> </div>
</div> </div>
<div class="head-time">{{ currentTime }}</div>
<div class="head-time"></div>
</div> </div>
<!-- 港区概览 --> <!-- 港区概览 -->
@ -29,23 +26,27 @@
:shore-power-status-data="shorePowerStatusData" @item-click="handleSwitch" :shore-power-status-data="shorePowerStatusData" @item-click="handleSwitch"
:realtime-device-data="realtimeDeviceData" :shore-power-list="ShorePowerList" :ship-data-list="shipDataList" /> --> :realtime-device-data="realtimeDeviceData" :shore-power-list="ShorePowerList" :ship-data-list="shipDataList" /> -->
<!-- </template> --> <!-- </template> -->
<ShowData v-show="activeHeadGroup === 0" :handleGoToModule="handleGoToModule"
:realtime-device-data-time="realtimeDeviceDataTime" />
<!-- 港口岸电使用情况 --> <!-- 港口岸电使用情况 -->
<!-- <template v-if="activeHeadGroup === 1"> --> <!-- <template v-if="activeHeadGroup === 1"> -->
<ShorePowerUsage v-show="activeHeadGroup === 1" :realtime-device-data="realtimeDeviceData" <ShorePowerUsage v-show="activeHeadGroup === 1" :realtime-device-data="realtimeDeviceData"
:active-head-group="activeHeadGroup" v-if="dataLoad" /> :active-head-group="activeHeadGroup" v-if="dataLoad" :handleGoBack="handleGoBack" />
<!-- </template> --> <!-- </template> -->
<!-- 港口企业岸电使用 --> <!-- 港口企业岸电使用 -->
<!-- <template v-if="activeHeadGroup === 2"> --> <!-- <template v-if="activeHeadGroup === 2"> -->
<CompanyShorePower v-show="activeHeadGroup === 2" :realtime-device-data="realtimeDeviceData" <CompanyShorePower v-show="activeHeadGroup === 2" :realtime-device-data="realtimeDeviceData"
:shore-power-list="ShorePowerList" /> :shore-power-list="ShorePowerList" :handleGoBack="handleGoBack"
:realtime-device-data-time="realtimeDeviceDataTime" />
<!-- </template> --> <!-- </template> -->
<!-- 船舶岸电使用情况 --> <!-- 船舶岸电使用情况 -->
<!-- <template > --> <!-- <template > -->
<ShipShorePower v-show="activeHeadGroup === 3" :ship-data="shipDataList" :selected-ship="selectedShip" <ShipShorePower v-show="activeHeadGroup === 3" :ship-data="shipDataList" :selected-ship="selectedShip"
@item-click="handleSwitch" :realtime-device-data="realtimeDeviceData" v-if="dataLoad" /> @item-click="handleSwitch" :realtime-device-data="realtimeDeviceData" v-if="dataLoad"
:handleGoBack="handleGoBack" />
<!-- </template> --> <!-- </template> -->
<template v-if="activeHeadGroup === 4"> <template v-if="activeHeadGroup === 4">
@ -235,8 +236,9 @@
<script setup lang="ts"> <script setup lang="ts">
import PublicMapComponents from './components/cesiumMap.vue' import PublicMapComponents from './components/cesiumMap.vue'
import PortOverview from './components/PortOverview.vue' // import PortOverview from './components/PortOverview.vue'
import ShorePowerUsage from './components/ShorePowerUsage.vue' import ShorePowerUsage from './components/ShorePowerUsage.vue'
import ShowData from './components/ShowData.vue'
import CompanyShorePower from './components/CompanyShorePower.vue' import CompanyShorePower from './components/CompanyShorePower.vue'
import ShipShorePower from './components/ShipShorePower.vue' import ShipShorePower from './components/ShipShorePower.vue'
import dayjs from 'dayjs' import dayjs from 'dayjs'
@ -248,13 +250,13 @@ import { formatDuration, formatTimestamp, getValueById, showStatus } from './com
defineOptions({ name: 'PublicMap' }) defineOptions({ name: 'PublicMap' })
let getRealtimeIntervalId: NodeJS.Timeout | null = null let getRealtimeIntervalId: NodeJS.Timeout | null = null
const headGroupList = ref<{ value: number, label: string }[]>([ const headGroupList = ref<{ value: number, label: string }[]>([
// { value: 0, label: '' }, { value: 0, label: '总体概览' },
{ value: 1, label: '港口岸电使用情况' }, { value: 1, label: '港口岸电使用情况' },
{ value: 2, label: '港口企业岸电使用' }, { value: 2, label: '港口企业岸电使用' },
{ value: 3, label: '船舶岸电使用情况' }, { value: 3, label: '船舶岸电使用情况' },
]) ])
const activeHeadGroup = ref<number>(-1) const activeHeadGroup = ref<number>(0)
// //
interface PublicMapComponentsType { interface PublicMapComponentsType {
@ -285,6 +287,9 @@ const currentTime = ref<string>(dayjs().format('YYYY-MM-DD HH:mm:ss'))
// //
const realtimeDeviceData = ref<RealtimeDeviceData[]>([]) const realtimeDeviceData = ref<RealtimeDeviceData[]>([])
//
const realtimeDeviceDataTime = ref<string>('')
const ShorePowerList = ref<(ShorePowerBerth & { position: string; })[]>([]) const ShorePowerList = ref<(ShorePowerBerth & { position: string; })[]>([])
const shipDataList = ref<ShipRespVo[]>([]) const shipDataList = ref<ShipRespVo[]>([])
const dataLoad = ref<boolean>(false) const dataLoad = ref<boolean>(false)
@ -497,6 +502,8 @@ const handleGetRealtimeAllData = async () => {
const data = await MapApi.getRealtimeAllData({}) const data = await MapApi.getRealtimeAllData({})
const arrayOfObjects = Object.values(data) as RealtimeDeviceData[] const arrayOfObjects = Object.values(data) as RealtimeDeviceData[]
realtimeDeviceData.value = arrayOfObjects realtimeDeviceData.value = arrayOfObjects
//
realtimeDeviceDataTime.value = dayjs().format('YYYY-MM-DD HH:mm:ss')
// console.log('getRealtimeAllData', arrayOfObjects) // console.log('getRealtimeAllData', arrayOfObjects)
} }
@ -664,6 +671,13 @@ const shorePowerStatusData = computed(() => {
}) })
}) })
const handleGoToModule = (moduleType: number) => {
activeHeadGroup.value = moduleType
}
const handleGoBack = () => {
activeHeadGroup.value = 0
}
// //
const shipStatusData = computed(() => { const shipStatusData = computed(() => {
if (!mapComponentRef.value || !mapComponentRef.value.dataWithModels) { if (!mapComponentRef.value || !mapComponentRef.value.dataWithModels) {
@ -932,12 +946,15 @@ const shipStatusData = computed(() => {
padding: 12px 24px; padding: 12px 24px;
.head-title { .head-title {
width: 420px; // width: 420px;
font-size: 28px; font-size: 28px;
color: rgba(20, 200, 255, 1); color: rgba(20, 200, 255, 1);
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
text-align: left; text-align: left;
display: flex;
align-items: center;
gap: 8px;
} }
.head-group { .head-group {
@ -946,6 +963,7 @@ const shipStatusData = computed(() => {
gap: 10px; gap: 10px;
.head-group-item { .head-group-item {
font-size: 16px;
padding: 8px 16px; padding: 8px 16px;
background-color: rgba(50, 50, 50, 0.5); background-color: rgba(50, 50, 50, 0.5);
color: #ccc; color: #ccc;

Loading…
Cancel
Save