Browse Source

update

feature
jiangAB 3 weeks ago
parent
commit
9e7040ec83
  1. 323
      public/map/components/CompanyShorePower.vue
  2. 4
      public/map/components/ShipShorePower.vue
  3. 22
      public/map/components/ShorePowerUsage.vue
  4. 64
      public/map/components/ShowData.vue
  5. 18
      public/map/components/cesiumMap.vue
  6. 8
      public/map/components/dictionaryTable.ts
  7. 46
      public/map/index.vue

323
public/map/components/CompanyShorePower.vue

@ -8,9 +8,6 @@
<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">起始时间: 2025-01-01 00:00:00</div>
<div class="data-update-time">更新时间: {{ realtimeDeviceDataTime }}</div>
</div> </div>
<!-- 返回上个页面 --> <!-- 返回上个页面 -->
<el-button type="primary" @click.stop="handleGoBack()">返回</el-button> <el-button type="primary" @click.stop="handleGoBack()">返回</el-button>
@ -24,12 +21,22 @@
<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="data-update-time">起始时间: {{ getStartTimeByRange(getCompanyTimeRange(company.id)) }} 更新时间: {{
realtimeDeviceDataTime }}</div>
<div class="company-header"> <div class="company-header">
<div class="company-info"> <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 class="company-berth-count">泊位数: {{ company.children?.length || 0 }}</div>
</div> </div>
<div class="company-total">总量: {{ calculateTotal(company.children).toFixed(2) }}</div> <div class="time-range-container">
<button v-for="option in timeRangeOptions" :key="option.value"
:class="['time-range-btn', { active: getCompanyTimeRange(company.id) === option.value }]"
@click.stop="() => handleTimeRangeChange(company.id, option.value)">
{{ option.label }}
</button>
<div class="company-total">总量: {{ calculateTotal(company.children).toFixed(2) }}</div>
</div>
</div> </div>
<div class="overview-grid"> <div class="overview-grid">
<div v-for="(berth, index) in (company.children || [])" :key="index" class="overview-item" <div v-for="(berth, index) in (company.children || [])" :key="index" class="overview-item"
@ -45,65 +52,112 @@
</div> </div>
</div> </div>
</div> </div>
<div class="right" v-if="selectedShorePowerItem"> <div class="right" style="width: 800px;" :style="{ width: selectedShorePowerItem ? '800px' : '420px' }">
<div class="card digital-twin-card--deep-blue"> <div style="display: flex; gap: 12px; height: 100%;">
<div style="display: flex; align-items: center; justify-content: space-between;"> <div v-if="selectedShorePowerItem" class="card digital-twin-card--deep-blue">
<div class="card-title"> <div style="display: flex; align-items: center; justify-content: space-between;">
<div class="vertical-line"></div> <div class="card-title">
<img src="@/assets/svgs/data.svg" class="title-icon" /> <div class="vertical-line"></div>
<span class="title-text">岸电箱详情</span> <img src="@/assets/svgs/data.svg" class="title-icon" />
</div> <span class="title-text">岸电箱详情</span>
<div style="ma"> </div>
<el-button type="primary" @click="handleOpenHistory">查看历史记录</el-button> <el-button class="close-btn" type="text" @click="closeShorePowerDetail">×</el-button>
<!-- <div style="ma">
<el-button type="primary" @click="handleOpenHistory">查看历史记录</el-button>
</div> -->
</div> </div>
</div>
<div class="card-content"> <div class="card-content">
<div class="ship-detail"> <div class="ship-detail">
<div class="detail-item"> <div class="detail-item">
<span class="label">名称:</span> <span class="label">名称:</span>
<span class="value">{{ selectedShorePowerItem?.name }}</span> <span class="value">{{ selectedShorePowerItem?.name }}</span>
</div> </div>
<div class="detail-item"> <div class="detail-item">
<span class="label">位置:</span> <span class="label">位置:</span>
<span class="value">{{ selectedShorePowerItem?.position }}</span> <span class="value">{{ selectedShorePowerItem?.position }}</span>
</div> </div>
<div class="detail-item"> <div class="detail-item">
<span class="label">电压:</span> <span class="label">电压:</span>
<span class="value">{{ selectedShorePowerItem?.shorePowerEquipmentInfo?.voltage }}</span> <span class="value">{{ selectedShorePowerItem?.shorePowerEquipmentInfo?.voltage }}</span>
</div> </div>
<div class="detail-item"> <div class="detail-item">
<span class="label">频率:</span> <span class="label">频率:</span>
<span class="value">{{ selectedShorePowerItem?.shorePowerEquipmentInfo?.frequency }} </span> <span class="value">{{ selectedShorePowerItem?.shorePowerEquipmentInfo?.frequency }} </span>
</div> </div>
<div class="detail-item"> <div class="detail-item">
<span class="label">容量:</span> <span class="label">容量:</span>
<span class="value">{{ selectedShorePowerItem?.shorePowerEquipmentInfo?.capacity }}</span> <span class="value">{{ selectedShorePowerItem?.shorePowerEquipmentInfo?.capacity }}</span>
</div> </div>
<div class="detail-item"> <div class="detail-item">
<span class="label">当前电压:</span> <span class="label">当前电压:</span>
<span class="value">{{ getValueById(realtimeDeviceData, selectedShorePowerItem.voltageDeviceId, <span class="value">{{ getValueById(realtimeDeviceData, selectedShorePowerItem.voltageDeviceId,
'measureValue') }}</span> 'measureValue') }}</span>
</div> </div>
<div class="detail-item"> <div class="detail-item">
<span class="label">当前电流:</span> <span class="label">当前电流:</span>
<span class="value">{{ getValueById(realtimeDeviceData, selectedShorePowerItem.currentDeviceId, <span class="value">{{ getValueById(realtimeDeviceData, selectedShorePowerItem.currentDeviceId,
'measureValue') }}</span> 'measureValue') }}</span>
</div> </div>
<div class="detail-item"> <div class="detail-item">
<span class="label">当前频率:</span> <span class="label">当前频率:</span>
<span class="value">{{ getValueById(realtimeDeviceData, selectedShorePowerItem.frequencyDeviceId, <span class="value">{{ getValueById(realtimeDeviceData, selectedShorePowerItem.frequencyDeviceId,
'measureValue') }}</span> 'measureValue') }}</span>
</div>
<div class="detail-item">
<span class="label">当前总用量:</span>
<span class="value">{{ getValueById(realtimeDeviceData, selectedShorePowerItem.totalPowerDeviceId,
'measureValue') }}</span>
</div>
<div class="detail-item">
<span class="label">当前状态:</span>
<span class="value">{{ selectedShorePowerItem.storePowerStatus }}</span>
</div>
</div> </div>
<div class="detail-item"> </div>
<span class="label">当前总用量:</span> </div>
<span class="value">{{ getValueById(realtimeDeviceData, selectedShorePowerItem.totalPowerDeviceId, <div class="card digital-twin-card--deep-blue ">
'measureValue') }}</span> <div style="display: flex; align-items: center; justify-content: space-between;">
<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>
<div class="detail-item"> <input class="search-container" type="text" placeholder="搜索岸电设备" v-model="storeSearchKeyword"
<span class="label">当前状态:</span> @input="handlStoreSearch" />
<span class="value">{{ selectedShorePowerItem.storePowerStatus }}</span> </div>
<div class=" card-content">
<div class="ship-table">
<div class="ship-table-header">
<div class="ship-table-column ship-name-header">岸电箱名称</div>
<div class="ship-table-column ship-status-header">状态</div>
<div class="ship-table-column ship-status-header">历史</div>
</div>
<div class="ship-table-body">
<div v-for="shorepower in filteredShorePowerList" :key="shorepower.id" class="ship-table-row"
@click="handleSelectShorePower(shorepower)">
<div class="ship-table-column ship-name">
<div class="ship-icon"></div>
<span class="ship-name-text">{{ shorepower.name }}</span>
</div>
<div class="ship-table-column ship-status">
<div class="status-tag" :class="getStatusClass(shorepower.storePowerStatus)">
{{ shorepower.storePowerStatus }}
</div>
<!-- <div class="status-tag" :class="getStatusClass('空闲')">
空闲
</div>
<div class="status-tag" :class="getStatusClass('故障')">
故障
</div> -->
</div>
<div class="ship-table-column ship-status-header">
<el-button type="primary" link @click.stop="showShorePowerHistory(shorepower)">查看</el-button>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -118,7 +172,7 @@
import { ref } from 'vue' import { ref } from 'vue'
import { MapApi } from "@/api/shorepower/map"; import { MapApi } from "@/api/shorepower/map";
import ShipHistoryDialog from './ShipHistoryDialog.vue'; import ShipHistoryDialog from './ShipHistoryDialog.vue';
import { RealtimeDeviceData, ShorePowerBerth } from '@/types/shorepower'; import { RealtimeDeviceData, ShipRespVo, ShorePowerBerth } from '@/types/shorepower';
import { getValueById } from './utils'; import { getValueById } from './utils';
// //
interface ChartDataItem { interface ChartDataItem {
@ -147,6 +201,134 @@ interface Props {
const props = defineProps<Props>() const props = defineProps<Props>()
const selectedShorePowerItem = ref<ShorePowerBerth>() const selectedShorePowerItem = ref<ShorePowerBerth>()
const shorepowerSelectedItem = ref<ShorePowerBerth & { position: string; } | null>(null)
const storeSearchKeyword = ref('')
//
interface TimeRangeOption {
value: 'day' | 'month' | 'year' | 'realtime';
label: string;
}
const timeRangeOptions: TimeRangeOption[] = [
{ value: 'day', label: '本日' },
{ value: 'month', label: '本月' },
{ value: 'year', label: '本年' },
{ value: 'realtime', label: '总' },
]
const closeShorePowerDetail = () => {
selectedShorePowerItem.value = undefined
}
//
const handlStoreSearch = () => {
//
}
const getStatusClass = (status: string | undefined) => {
switch (status) {
case '正常':
return 'status-normal'
case '在用':
return 'status-normal'
case '在线':
return 'status-normal'
case '空闲':
return 'status-idle'
case '故障':
return 'status-fault'
case '超容':
return 'status-maintenance'
case '异常':
return 'status-abnormal'
case '维修中':
return 'status-maintenance'
case '岸电使用中':
return 'status-shorepower'
// case '':
// return 'status-fault'
default:
return 'status-normal'
}
}
//
const filteredShorePowerList = computed(() => {
if (!storeSearchKeyword.value) {
return props.shorePowerList
}
return props.shorePowerList.filter(shorepower =>
shorepower.name.toLowerCase().includes(storeSearchKeyword.value.toLowerCase())
)
})
//
const emit = defineEmits<{
(e: 'switch-ship', ship: ShipRespVo): void;
(e: 'item-click', item: any): void;
// handleSelectItem(ship)
}>()
const handleSelectShorePower = async (shorepower: ShorePowerBerth & { position: string }) => {
// selectedItem.value = shorepower
shorepowerSelectedItem.value = shorepower
selectedShorePowerItem.value = shorepower
emit('item-click', {
type: 'shorepower_box',
item: shorepower
})
// const data = await MapApi.getRealtimeDataByIdList({ ids: shorepower.totalPowerDeviceId })
// console.log('voltageDeviceId', data)
}
//
const companyTimeRanges = ref<Record<number, 'realtime' | 'day' | 'month' | 'year'>>({})
// 'day'
const getCompanyTimeRange = (companyId: number) => {
return companyTimeRanges.value[companyId] || 'day'
}
//
const getStartTimeByRange = (range: 'realtime' | 'day' | 'month' | 'year') => {
const now = new Date();
switch (range) {
case 'day':
// 00:00:00
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
return formatDate(today);
case 'month':
// 00:00:00
const firstDayOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
return formatDate(firstDayOfMonth);
case 'year':
// 00:00:00
const firstDayOfYear = new Date(now.getFullYear(), 0, 1);
return formatDate(firstDayOfYear);
case 'realtime':
//
return '2020-01-01 00:00:00';
default:
return formatDate(new Date(now.getFullYear(), now.getMonth(), now.getDate()));
}
}
// YYYY-MM-DD HH:mm:ss
const formatDate = (date: Date) => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day} 00:00:00`;
}
//
const handleTimeRangeChange = (companyId: number, range: 'realtime' | 'day' | 'month' | 'year') => {
companyTimeRanges.value[companyId] = range
//
}
// //
const calculateTotal = (children?: ChartDataItem[]) => { const calculateTotal = (children?: ChartDataItem[]) => {
@ -363,4 +545,27 @@ onMounted(() => {
.card-content::-webkit-scrollbar-thumb:hover { .card-content::-webkit-scrollbar-thumb:hover {
background: rgba(17, 138, 237, 1); background: rgba(17, 138, 237, 1);
} }
.time-range-container {
display: flex;
align-items: center;
gap: 4px;
}
.search-container {
height: 100%;
width: 200px;
border-radius: 4px;
border: 1px solid rgb(10, 130, 170);
color: #FFF;
padding: 0 10px;
margin-bottom: 8px;
background-color: rgba(255, 255, 255, 0.1);
}
.close-btn {
width: 36px;
height: 36px;
margin-bottom: 8px;
}
</style> </style>

4
public/map/components/ShipShorePower.vue

@ -76,11 +76,11 @@
<span>{{ formatDateTime(scope.row?.usageRecordInfo?.endTime) }}</span> <span>{{ formatDateTime(scope.row?.usageRecordInfo?.endTime) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="shipStatus" label="船舶状态"> <!-- <el-table-column prop="shipStatus" label="船舶状态">
<template #default="scope"> <template #default="scope">
<span :class="[getStatusClass(scope.row.shipStatus)]">{{ scope.row.shipStatus }}</span> <span :class="[getStatusClass(scope.row.shipStatus)]">{{ scope.row.shipStatus }}</span>
</template> </template>
</el-table-column> </el-table-column> -->
<el-table-column prop="status" label="岸电状态" width="400"> <el-table-column prop="status" label="岸电状态" width="400">
<template #default="scope"> <template #default="scope">
<span v-if="scope.row.applyInfo?.reason === 0" <span v-if="scope.row.applyInfo?.reason === 0"

22
public/map/components/ShorePowerUsage.vue

@ -1077,28 +1077,6 @@ onBeforeUnmount(() => {
font-weight: bold; font-weight: bold;
} }
.time-range-btn {
padding: 4px 12px;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 4px;
background: transparent;
color: rgba(255, 255, 255, 0.7);
font-size: 12px;
cursor: pointer;
transition: all 0.3s ease;
}
.time-range-btn:hover {
background: rgba(255, 255, 255, 0.1);
border-color: rgba(255, 255, 255, 0.5);
}
.time-range-btn.active {
background: rgba(76, 175, 80, 0.8);
border-color: #4CAF50;
color: #fff;
}
.time-range-item { .time-range-item {
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;

64
public/map/components/ShowData.vue

@ -61,12 +61,14 @@
<div class="card-content"> <div class="card-content">
<!-- 港口岸电使用情况 --> <!-- 港口岸电使用情况 -->
<div class="module-section"> <div class="module-section">
<div class="module-time">
<div>起始时间{{ portStartTime }}</div>
<div>更新时间{{ realtimeDeviceDataTime }}</div>
</div>
<div class="module-header"> <div class="module-header">
<h3 class="module-title" @click="handleGoToModule(1)">港口岸电使用情况</h3> <div style="display: flex; align-items: center; gap: 20px;">
<h3 class="module-title" @click="handleGoToModule(1)">港区岸电使用情况</h3>
<div class="module-time">
<div>{{ portStartTime }} {{ realtimeDeviceDataTime }}</div>
</div>
</div>
<div class="period-filter"> <div class="period-filter">
<div v-for="period in periodOptions" :key="period.value" <div v-for="period in periodOptions" :key="period.value"
:class="['period-option', { active: portActivePeriod === period.value }]" :class="['period-option', { active: portActivePeriod === period.value }]"
@ -109,12 +111,13 @@
<!-- 港口企业岸电使用 --> <!-- 港口企业岸电使用 -->
<div class="module-section"> <div class="module-section">
<div class="module-time">
<div>起始时间{{ enterpriseStartTime }}</div>
<div>更新时间{{ realtimeDeviceDataTime }}</div>
</div>
<div class="module-header"> <div class="module-header">
<h3 class="module-title" @click="handleGoToModule(2)">港口企业岸电使用</h3> <div style="display: flex; align-items: center; gap: 20px;">
<h3 class="module-title" @click="handleGoToModule(2)">港口港区企业岸电使用</h3>
<div class="module-time">
<div>{{ enterpriseStartTime }} {{ realtimeDeviceDataTime }}</div>
</div>
</div>
<div class="period-filter"> <div class="period-filter">
<div v-for="period in periodOptions" :key="period.value" <div v-for="period in periodOptions" :key="period.value"
:class="['period-option', { active: enterpriseActivePeriod === period.value }]" :class="['period-option', { active: enterpriseActivePeriod === period.value }]"
@ -164,12 +167,13 @@
<!-- 船舶岸电使用情况 --> <!-- 船舶岸电使用情况 -->
<div class="module-section"> <div class="module-section">
<div class="module-time">
<div>起始时间{{ shipStartTime }}</div>
<div>更新时间{{ realtimeDeviceDataTime }}</div>
</div>
<div class="module-header"> <div class="module-header">
<h3 class="module-title" @click="handleGoToModule(3)">船舶岸电使用情况</h3> <div style="display: flex; align-items: center; gap: 20px;">
<h3 class="module-title" @click="handleGoToModule(3)">港区船舶岸电使用情况</h3>
<div class="module-time">
<div>{{ shipStartTime }} {{ realtimeDeviceDataTime }}</div>
</div>
</div>
<!-- <span>实时</span> --> <!-- <span>实时</span> -->
<div class="period-filter"> <div class="period-filter">
<div v-for="period in periodOptions" :key="period.value" <div v-for="period in periodOptions" :key="period.value"
@ -536,6 +540,8 @@ const getStatusClass = (status: string | undefined) => {
switch (status) { switch (status) {
case '正常': case '正常':
return 'status-normal' return 'status-normal'
case '在用':
return 'status-normal'
case '在线': case '在线':
return 'status-normal' return 'status-normal'
case '空闲': case '空闲':
@ -561,9 +567,9 @@ const getStatusClass = (status: string | undefined) => {
const filteredShipStatusData = computed(() => { const filteredShipStatusData = computed(() => {
let filterData: ShipRespVo[] = [] let filterData: ShipRespVo[] = []
if (filterType.value === 'using') { if (filterType.value === 'using') {
filterData = props.shipDataList.filter(ship => ['正常', '超容'].includes(ship.shipStatus || '')) filterData = props.shipDataList.filter(ship => ['在用'].includes(ship.shipStatus || ''))
} else if (filterType.value === 'notUsing') { } else if (filterType.value === 'notUsing') {
filterData = props.shipDataList.filter(ship => !['正常', '超容'].includes(ship.shipStatus || '')) filterData = props.shipDataList.filter(ship => !['在用'].includes(ship.shipStatus || ''))
} else { } else {
filterData = props.shipDataList filterData = props.shipDataList
} }
@ -634,8 +640,8 @@ const handleCloseShipList = () => {
.card-content { .card-content {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: 8px;
padding: 16px; padding: 8px;
} }
.card-title { .card-title {
@ -675,7 +681,7 @@ const handleCloseShipList = () => {
} }
.module-section { .module-section {
margin-bottom: 20px; // margin-bottom: 8px;
} }
.module-header { .module-header {
@ -711,8 +717,6 @@ const handleCloseShipList = () => {
.module-time { .module-time {
font-size: 14px; font-size: 14px;
color: #67c23a; color: #67c23a;
margin-bottom: 12px;
padding-left: 4px;
} }
.module-time div { .module-time div {
@ -729,14 +733,14 @@ const handleCloseShipList = () => {
.first-row { .first-row {
display: grid; display: grid;
grid-template-columns: repeat(2, 1fr); grid-template-columns: repeat(2, 1fr);
gap: 12px; gap: 4px;
margin-bottom: 12px; margin-bottom: 4px;
} }
.second-row { .second-row {
display: grid; display: grid;
grid-template-columns: repeat(4, 1fr); grid-template-columns: repeat(4, 1fr);
gap: 12px; gap: 4px;
} }
.total-electricity { .total-electricity {
@ -769,7 +773,7 @@ const handleCloseShipList = () => {
background: rgba(30, 120, 255, 0.15); background: rgba(30, 120, 255, 0.15);
border: 1px solid rgba(64, 158, 255, 0.4); border: 1px solid rgba(64, 158, 255, 0.4);
border-radius: 8px; border-radius: 8px;
padding: 20px 8px; padding: 16px 8px;
text-align: center; text-align: center;
cursor: pointer; cursor: pointer;
transition: all 0.3s ease; transition: all 0.3s ease;
@ -857,10 +861,10 @@ const handleCloseShipList = () => {
.usage-rate { .usage-rate {
text-align: center; text-align: center;
padding: 20px; padding: 16px 8px;
background: rgba(30, 120, 255, 0.15); background: rgba(30, 120, 255, 0.15);
border-radius: 10px; border-radius: 10px;
margin-bottom: 12px; margin-bottom: 6px;
} }
.rate-value { .rate-value {
@ -878,8 +882,8 @@ const handleCloseShipList = () => {
.status-grid { .status-grid {
display: grid; display: grid;
grid-template-columns: repeat(3, 1fr); grid-template-columns: repeat(3, 1fr);
gap: 12px; gap: 6px;
margin-bottom: 12px; margin-bottom: 6px;
} }
.status-card { .status-card {

18
public/map/components/cesiumMap.vue

@ -168,12 +168,12 @@ const dataWithModels = ref([]); // 存储带有模型实例的数据列表
// //
const presetViews = { const presetViews = {
overview: { overview: {
"longitude": 118.59194426567525, "longitude": 118.62637973547224,
"latitude": 38.74592604188135, "latitude": 38.75189077356901,
"height": 18601.357067923822, "height": 18603.526551007664,
"heading": 354.44934020869243, "heading": 354.4493407804326,
"pitch": -33.90715396773357, "pitch": -33.907145214928995,
"roll": 359.986620026677 "roll": 359.9866190017743
} }
}; };
@ -852,7 +852,7 @@ onMounted(async () => {
}) })
let labelColor = null let labelColor = null
let statusImage = null; let statusImage = null;
if (item.shipStatus === '正常') { if (['在用', '正常'].includes(item.shipStatus)) {
// statusImage = null; // statusImage = null;
} else if (item.shipStatus === '超容') { } else if (item.shipStatus === '超容') {
statusImage = '/img/故障.png'; statusImage = '/img/故障.png';
@ -861,6 +861,10 @@ onMounted(async () => {
statusImage = '/img/未连接.png'; statusImage = '/img/未连接.png';
labelColor = Cesium.Color.RED; // 线 labelColor = Cesium.Color.RED; // 线
} }
if (item.applyInfo.reason !== 0) {
statusImage = '/img/故障.png';
labelColor = Cesium.Color.YELLOW;
}
// //
if (statusImage) { if (statusImage) {
const overlayBillboard = viewer.entities.add({ const overlayBillboard = viewer.entities.add({

8
public/map/components/dictionaryTable.ts

@ -127,3 +127,11 @@ export const APPLY_STATUS = [
{ label: '申请完成', value: 10 }, { label: '申请完成', value: 10 },
{ label: '已取消', value: 11 }, { label: '已取消', value: 11 },
] ]
export const SHIP_STATUS = [
{ label: '在用', value: 1 },
{ label: '故障', value: 2 },
{ label: '故障', value: 3 },
{ label: '异常', value: 4 },
]

46
public/map/index.vue

@ -133,7 +133,9 @@
</div> </div>
<div class="detail-item"> <div class="detail-item">
<span class="label">当前状态:</span> <span class="label">当前状态:</span>
<span class="value">{{ selectedElectricalBox.data.shipStatus }}</span> <span class="value">{{ selectedElectricalBox.data.shipStatus }}<span
v-if="selectedElectricalBox.data.StatusReason">({{ selectedElectricalBox.data.StatusReason
}})</span></span>
</div> </div>
<div v-if="selectedElectricalBox.data.applyInfo.reason === 0" class="detail-item"> <div v-if="selectedElectricalBox.data.applyInfo.reason === 0" class="detail-item">
<span class="label">岸电使用时长</span> <span class="label">岸电使用时长</span>
@ -586,10 +588,10 @@ const handleGetRealtimeAllData = async () => {
const StatusMap = { const StatusMap = {
1: '故障', 1: '故障',
2: '故障', 2: '故障',
3: '在线', 3: '在',
4: '在线', 4: '在',
5: '离线', 5: '故障',
6: '在线', 6: '在',
8: '故障', 8: '故障',
9: '离线', 9: '离线',
} }
@ -617,7 +619,7 @@ const handleGetStorePower = async () => {
const getShipStatus = (ship: ShipRespVo) => { const getShipStatus = (ship: ShipRespVo) => {
if (ship.shorePowerAndShip.status === 9) { if (ship.shorePowerAndShip.status === 9) {
return '未使用' return '正常'
} else { } else {
const shorePower = realtimeDeviceData.value.find(item => item.deviceId === ship.shorePowerAndShip.shorePowerId) const shorePower = realtimeDeviceData.value.find(item => item.deviceId === ship.shorePowerAndShip.shorePowerId)
if (!shorePower) { if (!shorePower) {
@ -628,7 +630,7 @@ const getShipStatus = (ship: ShipRespVo) => {
if ([2, 5, 8].includes(shorePower.deviceStatus)) { if ([2, 5, 8].includes(shorePower.deviceStatus)) {
return '故障' return '故障'
} else if (shorePower?.deviceStatus === 6) { } else if (shorePower?.deviceStatus === 6) {
return '超容' return '在用'
} else { } else {
const Vobj = realtimeDeviceData.value.find(item => item.deviceId === ship.shorePower.voltageDeviceId) const Vobj = realtimeDeviceData.value.find(item => item.deviceId === ship.shorePower.voltageDeviceId)
const Cobj = realtimeDeviceData.value.find(item => item.deviceId === ship.shorePower.currentDeviceId) const Cobj = realtimeDeviceData.value.find(item => item.deviceId === ship.shorePower.currentDeviceId)
@ -641,9 +643,9 @@ const getShipStatus = (ship: ShipRespVo) => {
} }
const power = (Vobj?.measureValue ?? 0) * (Cobj?.measureValue ?? 0); const power = (Vobj?.measureValue ?? 0) * (Cobj?.measureValue ?? 0);
if (power / 1000 > capacity) { if (power / 1000 > capacity) {
return '超容' return '在用'
} }
return '正常' return '在用'
} }
} }
} }
@ -1019,8 +1021,8 @@ const handleBuildCompanyShorePower = (realtimeDeviceData: RealtimeDeviceData[])
const handleBuildCompanyShorePowerYear = (shipData: any) => { const handleBuildCompanyShorePowerYear = (shipData: any) => {
shipTotalData.value = { shipTotalData.value = {
'berthingShips': shipData.length, 'berthingShips': shipData.length,
'shorePowerShips': shipData.filter(ship => ['正常', '超容'].includes(ship.shipStatus || '')).length, 'shorePowerShips': shipData.filter(ship => ['在用'].includes(ship.shipStatus || '')).length,
'noShorePowerShips': shipData.filter(ship => !['正常', '超容'].includes(ship.shipStatus || '')).length, 'noShorePowerShips': shipData.filter(ship => !['在用'].includes(ship.shipStatus || '')).length,
} }
} }
@ -1623,4 +1625,26 @@ const handleBuildCompanyShorePowerYear = (shipData: any) => {
font-size: 16px; font-size: 16px;
font-weight: 600; font-weight: 600;
} }
.time-range-btn {
padding: 4px 12px;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 4px;
background: transparent;
color: rgba(255, 255, 255, 0.7);
font-size: 12px;
cursor: pointer;
transition: all 0.3s ease;
}
.time-range-btn:hover {
background: rgba(255, 255, 255, 0.1);
border-color: rgba(255, 255, 255, 0.5);
}
.time-range-btn.active {
background: rgba(76, 175, 80, 0.8);
border-color: #4CAF50;
color: #fff;
}
</style> </style>

Loading…
Cancel
Save