Browse Source

update

feature
jiangAB 2 weeks ago
parent
commit
4ca9409216
  1. 94
      public/map/components/CompanyShorePower.vue
  2. 2
      public/map/components/ShorePowerUsageRate.vue
  3. 4
      public/map/components/ShorePowerUsageSingleData.vue
  4. 134
      public/map/components/ShowData.vue
  5. 50
      public/map/index.vue
  6. 33
      src/types/shorepower.d.ts

94
public/map/components/CompanyShorePower.vue

@ -182,21 +182,10 @@
import { ref, computed } from 'vue'
import { MapApi } from "@/api/shorepower/map";
import ShipHistoryDialog from './ShipHistoryDialog.vue';
import { RealtimeDeviceData, ShipRespVo, ShorePowerBerth } from '@/types/shorepower';
import { CompanyShorePowerData, RealtimeDeviceData, ShipRespVo, ShorePowerBerth } from '@/types/shorepower';
import { getValueById } from './utils';
//
interface companyData {
id: number;
harborDistrictId: number;
name?: string;
shorePowerCount: number; //
shorePowerIds: number[]; // ID
distributionList: {
id: number;
name: string;
shorePowerList: any[];
}[];
}
const historyVisible = ref({
visible: false,
@ -215,6 +204,7 @@ interface Props {
yearData: any[];
monthData: any[];
dayData: any[];
companyComparisonData: CompanyShorePowerData[];
}
const props = defineProps<Props>()
@ -348,13 +338,13 @@ const handleTimeRangeChange = (companyId: number, range: 'realtime' | 'day' | 'm
}
/* 点击泊位box */
const handleClickShorePowerName = (data: companyData) => {
const handleClickShorePowerName = (data: CompanyShorePowerData) => {
const shorePower = props.shorePowerList.find(item => item.id === data.id)
selectedShorePowerItem.value = shorePower
console.log(shorePower)
}
const handleClickhorePowerValue = (data: companyData) => {
const handleClickhorePowerValue = (data: CompanyShorePowerData) => {
const shorePower = props.shorePowerList.find(item => item.id === data.id)
if (!shorePower) {
return
@ -374,7 +364,7 @@ const showShorePowerHistory = (berth: ShorePowerBerth) => {
}
}
}
const companyComparisonData = ref<companyData[]>([])
// const companyComparisonData = ref<companyData[]>([])
//
const deviceDataMap = computed(() => {
@ -430,43 +420,43 @@ const handGetDeviceData = (deviceId: number | number[], range: 'realtime' | 'day
return totalValue.toFixed(2);
}
const handleGetBuildData = async () => {
const dockList = await MapApi.getDockIdAndNameList()
// const berthList = await MapApi.getBerthIdAndNameList()
const distributionList = groupByShorePowerEquipmentId(props.shorePowerList)
const buildData = dockList.map(dock => {
const filterData = distributionList.filter(item => item.dockId === dock.id)
const shorePowerCount = filterData.reduce((total, item) => {
return total + item.shorePowerList.length
}, 0)
return {
...dock,
shorePowerCount: shorePowerCount, //
shorePowerIds: filterData.map(item => item.shorePowerList.map(shorePower => shorePower.id)).flat(),
distributionList: filterData
}
})
companyComparisonData.value = buildData
/* 转换函数 */
function groupByShorePowerEquipmentId(data) {
const map = new Map();
for (const item of data) {
const { shorePowerEquipmentInfo, ...rest } = item;
const id = shorePowerEquipmentInfo.id;
if (!map.has(id)) {
map.set(id, {
...shorePowerEquipmentInfo,
shorePowerList: []
});
}
map.get(id).shorePowerList.push(rest);
}
return Array.from(map.values());
}
}
// const handleGetBuildData = async () => {
// const dockList = await MapApi.getDockIdAndNameList()
// // const berthList = await MapApi.getBerthIdAndNameList()
// const distributionList = groupByShorePowerEquipmentId(props.shorePowerList)
// const buildData = dockList.map(dock => {
// const filterData = distributionList.filter(item => item.dockId === dock.id)
// const shorePowerCount = filterData.reduce((total, item) => {
// return total + item.shorePowerList.length
// }, 0)
// return {
// ...dock,
// shorePowerCount: shorePowerCount, //
// shorePowerIds: filterData.map(item => item.shorePowerList.map(shorePower => shorePower.id)).flat(),
// distributionList: filterData
// }
// })
// companyComparisonData.value = buildData
// /* */
// function groupByShorePowerEquipmentId(data) {
// const map = new Map();
// for (const item of data) {
// const { shorePowerEquipmentInfo, ...rest } = item;
// const id = shorePowerEquipmentInfo.id;
// if (!map.has(id)) {
// map.set(id, {
// ...shorePowerEquipmentInfo,
// shorePowerList: []
// });
// }
// map.get(id).shorePowerList.push(rest);
// }
// return Array.from(map.values());
// }
// }
onMounted(() => {
handleGetBuildData()
// handleGetBuildData()
})
</script>

2
public/map/components/ShorePowerUsageRate.vue

@ -67,7 +67,7 @@ interface Props {
// activeHeadGroup?: number;
handleClose: () => void;
realtimeDeviceDataTime: string;
comparativeData: ComparativeData;
// comparativeData: ComparativeData;
initialTimeRange?: 'realtime' | 'day' | 'month' | 'year';
}

4
public/map/components/ShorePowerUsageSingleData.vue

@ -1133,7 +1133,7 @@ onBeforeUnmount(() => {
.big {
height: 100%;
width: calc(55%);
width: calc(60%);
.card {
height: 100%;
@ -1154,7 +1154,7 @@ onBeforeUnmount(() => {
}
.right-row {
width: calc(45% - 8px);
width: calc(40% - 8px);
height: 100%;
display: flex;
flex-direction: column;

134
public/map/components/ShowData.vue

@ -1,8 +1,9 @@
<template>
<div class="show-data">
<div class="left">
<div v-if="showShipList || shorePowerCardShow" class="left">
<!-- <div style="display: flex; align-items: center; justify-content: space-between;"> -->
<div v-if="showShipList" class="card digital-twin-card--deep-blue " style=" display: inline-block; width: 420px;">
<div v-if="showShipList && !shorePowerCardShow" class="card digital-twin-card--deep-blue "
style=" display: inline-block; width: 420px;">
<div style="display: flex; align-items: center; justify-content: space-between;">
<div class="card-title">
<div class="vertical-line"></div>
@ -50,7 +51,7 @@
</div>
</div>
</div>
<div v-if="shipSelectedItem && showShipList" class="card digital-twin-card--deep-blue"
<div v-if="shipSelectedItem && showShipList && !shorePowerCardShow" class="card digital-twin-card--deep-blue"
style=" display: inline-block; width: 420px;">
<div class="card-title">
<el-button class="close-btn" size="small" type="text" @click="handleCloseShipDetail">×</el-button>
@ -64,7 +65,7 @@
<span class="label">名称:</span>
<span class="value">{{ shipSelectedItem.shipBasicInfo.name + '-' +
shipSelectedItem.shipBasicInfo.nameEn
}}</span>
}}</span>
</div>
<!-- <div class="detail-item">
<span class="label">英文船名:</span>
@ -118,7 +119,7 @@
<span class="label">靠泊类型:</span>
<span class="value">{{ getOperationTypeLabel(shipSelectedItem.shorePowerAndShip.type,
BERTH_TYPE)
}}</span>
}}</span>
</div>
<div class="detail-item">
<span class="label">靠泊时间:</span>
@ -129,7 +130,7 @@
<span class="label">当前状态:</span>
<span class="value">{{ shipSelectedItem.shipStatus }}<span v-if="shipSelectedItem.StatusReason">({{
shipSelectedItem.StatusReason
}})</span></span>
}})</span></span>
</div>
<div v-if="shipSelectedItem.applyInfo.reason === 0" class="detail-item">
<span class="label">岸电使用时长</span>
@ -147,17 +148,17 @@
<div class="detail-item">
<span class="label">岸电联系人:</span>
<span class="value">{{ shipSelectedItem?.shipBasicInfo?.shorePowerContact
}}</span>
}}</span>
</div>
<div class="detail-item">
<span class="label">联系方式:</span>
<span class="value">{{ shipSelectedItem?.shipBasicInfo?.shorePowerContactPhone
}}</span>
}}</span>
</div>
</div>
</div>
</div>
<div v-if="shorePowerCardShow" style="width: 840px">
<div v-if="shorePowerCardShow && !showShipList" style="width: 840px">
<ShorePowerUsageRate :realtimeDeviceDataTime="realtimeDeviceDataTime" :handleClose="handleCloseRate" />
</div>
@ -253,14 +254,23 @@
</div>
<div class="enterprise-usage">
<div class="usage-bars">
<div class="bar-item" v-for="item in companyShorePowerBuildData[enterpriseActivePeriod]"
<!-- <div class="bar-item" v-for="item in companyShorePowerBuildData[enterpriseActivePeriod]"
:key="item.harborDistrictId">
<div class="bar-header">
<span class="bar-name">{{ item.name }}</span>
<span class="bar-value">{{ item.totalPower.toFixed(2) }} kWH</span>
</div>
<el-progress
:percentage="calculatePercentage(item.totalPower, companyShorePowerBuildData[enterpriseActivePeriod])"
:percentage="calculatePercentageForCompany(item, companyShorePowerData)"
:show-text="false" :stroke-width="10" />
</div> -->
<div class="bar-item" v-for="item in companyShorePowerData" :key="item.id">
<div class="bar-header">
<span class="bar-name">{{ item.name }}</span>
<span class="bar-value">{{ handGetDeviceData(item.shorePowerIds,
getCompanyTimeRange(item.id)) }} kWH</span>
</div>
<el-progress :percentage="calculatePercentageForCompany(item, companyShorePowerData)"
:show-text="false" :stroke-width="10" />
</div>
<!-- <div class="bar-item">
@ -380,10 +390,11 @@
</template>
<script setup lang="ts">
import { CompanyShorePowerBuildDataItem, RealtimeDeviceData, ShipRespVo, TimeRange } from '@/types/shorepower';
import { CompanyShorePowerBuildDataItem, CompanyShorePowerData, RealtimeDeviceData, ShipRespVo, TimeRange } from '@/types/shorepower';
import { ref, computed } from 'vue'
import { MapApi } from "@/api/shorepower/map";
import ShipHistoryDialog from './ShipHistoryDialog.vue'
import ShorePowerUsageRate from './ShorePowerUsageRate.vue'
import { formatTimestamp, getValueById, showStatus } from './utils';
import { BERTH_TYPE, getOperationTypeLabel, SHORE_POWER_STATUS, UNUSED_SHORE_POWER_REASON } from './dictionaryTable';
interface Props {
@ -409,6 +420,10 @@ interface Props {
'noShorePowerShips': number,
}
shipDataList: ShipRespVo[]
companyShorePowerData: CompanyShorePowerData[]
yearData: any[];
monthData: any[];
dayData: any[];
}
const props = defineProps<Props>()
@ -434,9 +449,9 @@ const updateTime = computed(() => {
})
// -
const portActivePeriod = ref('day') // 使
const enterpriseActivePeriod = ref('day') // 使
const shipActivePeriod = ref('day') // 使
const portActivePeriod = ref<'realtime' | 'day' | 'month' | 'year'>('day') // 使
const enterpriseActivePeriod = ref<'realtime' | 'day' | 'month' | 'year'>('day') // 使
const shipActivePeriod = ref<'realtime' | 'day' | 'month' | 'year'>('day') // 使
const filterType = ref('all') // 使
const shipHistoryVisible = ref({
@ -449,7 +464,7 @@ const shipHistoryVisible = ref({
})
const shipSelectedItem = ref<ShipRespVo | null>(null)
const shorePowerCardShow = ref(true)
const shorePowerCardShow = ref(false)
const periodOptions = [
{ label: '当日', value: 'day' },
@ -490,6 +505,7 @@ const handleCloseRate = () => {
const handleOpenRate = () => {
handleCloseShipList()
shorePowerCardShow.value = true
}
@ -597,10 +613,6 @@ const shipStartTime = computed(() => {
return `${year}-${month}-${day} ${hours}:${minutes}`
})
//
const currentRankingData = computed(() => {
return rankingData[activePeriod.value as keyof typeof rankingData] || []
})
// 使
const calculateShorePowerUsageRate = (): number => {
@ -611,33 +623,36 @@ const calculateShorePowerUsageRate = (): number => {
return Number(usageRate.toFixed(2))
}
//
const calculatePercentageForCompany = (company: CompanyShorePowerData, companyData: CompanyShorePowerData[]): number => {
if (!companyData || companyData.length === 0) return 0
//
const companyPower = handGetDeviceData(company.shorePowerIds, getCompanyTimeRange(company.id))
//
const calculatePercentage = (value: number, dataArray: typeof props.companyShorePowerBuildData[TimeRange]): number => {
if (!dataArray || dataArray.length === 0) return 0
//
const maxValue = Math.max(...dataArray.map(item => item.totalPower))
//
const maxPower = Math.max(...companyData.map(item => {
return parseFloat(handGetDeviceData(item.shorePowerIds, getCompanyTimeRange(item.id)))
}))
// 000
if (maxValue === 0) return 0
if (maxPower === 0) return 0
// 5%使
const percentage = (value / maxValue) * 100
const percentage = (parseFloat(companyPower) / maxPower) * 100
return Math.max(percentage, 5)
}
// -
const switchPortPeriod = (period: string) => {
const switchPortPeriod = (period: 'realtime' | 'day' | 'month' | 'year') => {
portActivePeriod.value = period
}
const switchEnterprisePeriod = (period: string) => {
const switchEnterprisePeriod = (period: 'realtime' | 'day' | 'month' | 'year') => {
enterpriseActivePeriod.value = period
}
const switchShipPeriod = (period: string) => {
const switchShipPeriod = (period: 'realtime' | 'day' | 'month' | 'year') => {
shipActivePeriod.value = period
}
@ -758,6 +773,63 @@ const handleCloseShipList = () => {
const handleCloseShipDetail = () => {
shipSelectedItem.value = null
}
const handGetDeviceData = (deviceId: number | number[], range: 'realtime' | 'day' | 'month' | 'year') => {
let totalValue = 0;
let rangData: RealtimeDeviceData[] = []
if (range === 'realtime') {
rangData = props.realtimeDeviceData
} else if (range === 'day') {
rangData = props.dayData
} else if (range === 'month') {
rangData = props.monthData
} else if (range === 'year') {
rangData = props.yearData
}
if (Array.isArray(deviceId)) {
// If deviceId is an array, sum all the measure values and subtract start values
deviceId.forEach(id => {
const deviceData = deviceDataMap.value.get(id);
const startData = rangData.find(item => item.deviceId === id)
if (deviceData?.measureValue) {
totalValue += deviceData.measureValue;
}
// For non-realtime ranges, subtract the start value
if (range !== 'realtime' && startData?.measureValue) {
totalValue -= startData.measureValue;
}
});
} else {
// If deviceId is a single number, get its measure value
const deviceData = deviceDataMap.value.get(deviceId);
const startData = rangData.find(item => item.deviceId === deviceId)
if (deviceData?.measureValue) {
totalValue = deviceData.measureValue;
}
if (range !== 'realtime' && startData?.measureValue) {
totalValue -= startData.measureValue
}
}
return totalValue.toFixed(2);
}
const getCompanyTimeRange = (companyId: number): 'realtime' | 'day' | 'month' | 'year' => {
return enterpriseActivePeriod.value
}
const deviceDataMap = computed(() => {
const map = new Map<number, RealtimeDeviceData>();
props.realtimeDeviceData.forEach(item => {
map.set(item.deviceId, item);
});
return map;
});
</script>
<style scoped lang="scss">

50
public/map/index.vue

@ -35,7 +35,8 @@
:realtime-device-data-time="realtimeDeviceDataTime" :chart-data="chartData"
:company-shore-power-build-data="companyShorePowerBuildData" :ship-total-data="shipTotalData"
:ship-data-list="shipDataList" @item-click="handleSwitch" :realtime-device-data="realtimeDeviceData"
v-if="dataLoad" />
v-if="dataLoad" :company-shore-power-data="companyComparisonData" :year-data="yearDataRes"
:month-data="monthDataRes" :day-data="dayDataRes" />
<!-- 港口岸电使用情况多数据 -->
<ShorePowerUsage v-show="activeHeadGroup === 1" :realtime-device-data-time="realtimeDeviceDataTime"
@ -53,7 +54,7 @@
<CompanyShorePower v-show="activeHeadGroup === 2" :realtime-device-data="realtimeDeviceData"
:shore-power-list="ShorePowerList" :handleGoBack="handleGoBack" :year-data="yearDataRes"
:month-data="monthDataRes" :day-data="dayDataRes" :realtime-device-data-time="realtimeDeviceDataTime"
v-if="dataLoad" />
:company-comparison-data="companyComparisonData" v-if="dataLoad" />
<!-- </template> -->
<!-- 船舶岸电使用情况 -->
@ -262,7 +263,7 @@ import dayjs from 'dayjs'
import { onMounted, onUnmounted, ref, computed, watch } from 'vue'
import { Loading } from '@element-plus/icons-vue'
import { MapApi } from "@/api/shorepower/map";
import { CompanyShorePowerBuildDataItem, ComparativeData, RealtimeDeviceData, ShipBasicInfoRespVO, ShipRespVo, ShorePowerBerth } from '@/types/shorepower'
import { CompanyShorePowerBuildDataItem, CompanyShorePowerData, ComparativeData, RealtimeDeviceData, ShipBasicInfoRespVO, ShipRespVo, ShorePowerBerth } from '@/types/shorepower'
import { BERTH_TYPE, DOCK_DISTRICT, getOperationTypeLabel, HARBOR_DISTRICT, SHORE_POWER_STATUS, UNUSED_SHORE_POWER_REASON } from './components/dictionaryTable'
import { formatDuration, formatTimestamp, getValueById, showStatus } from './components/utils'
defineOptions({ name: 'PublicMap' })
@ -327,6 +328,8 @@ const yearDataRes = ref<any>({})
const monthDataRes = ref<any>({})
const dayDataRes = ref<any>({})
const companyComparisonData = ref<CompanyShorePowerData[]>([])
// const allPortAreaCount = ref<number>(0)
@ -730,6 +733,8 @@ onMounted(async () => {
await handleGetStorePower()
const tempBuildShipData = await handleGetShipData()
handleBuildCompanyShorePowerYear(tempBuildShipData)
await handleGetBuildData()
dataLoad.value = true
getRealtimeIntervalId = setInterval(async () => {
const data = await handleGetRealtimeAllData()
@ -1081,6 +1086,43 @@ const handleBuildCompanyShorePowerYear = async (shipData: any) => {
}
}
/* 构建企业岸电数据 */
const handleGetBuildData = async () => {
const dockList = await MapApi.getDockIdAndNameList()
// const berthList = await MapApi.getBerthIdAndNameList()
const distributionList = groupByShorePowerEquipmentId(ShorePowerList.value)
const buildData = dockList.map(dock => {
const filterData = distributionList.filter(item => item.dockId === dock.id)
const shorePowerCount = filterData.reduce((total, item) => {
return total + item.shorePowerList.length
}, 0)
return {
...dock,
shorePowerCount: shorePowerCount, //
shorePowerIds: filterData.map(item => item.shorePowerList.map(shorePower => shorePower.id)).flat(),
distributionList: filterData
}
})
companyComparisonData.value = buildData
/* 转换函数 */
function groupByShorePowerEquipmentId(data) {
const map = new Map();
for (const item of data) {
const { shorePowerEquipmentInfo, ...rest } = item;
const id = shorePowerEquipmentInfo.id;
if (!map.has(id)) {
map.set(id, {
...shorePowerEquipmentInfo,
shorePowerList: []
});
}
map.get(id).shorePowerList.push(rest);
}
return Array.from(map.values());
}
}
/**
* 构建日年三个维度的环比对比数据和同比数据
* - 日环比今日 00:00 至当前 vs 昨日 00:00 至昨日此时
@ -1110,7 +1152,7 @@ const handleBuildTimeComparison = async (): Promise<ComparativeData> => {
* - previous 0 current 也为 0 返回 0
* - previous 0 current > 0 返回 null表示新增
*/
const calculateGrowthRate = (current: number, previous: number): number | null => {
const calculateGrowthRate = (current: number | null, previous: number | null): number => {
if (previous === 0) {
return current === 0 ? 0 : null; // null 0
}

33
src/types/shorepower.d.ts

@ -498,56 +498,69 @@ interface ComparativeData {
day: {
growthRate: number
current: {
period: string
period: string | null
value: number
}
previous: {
period: string
period: string | null
value: number
}
}
dayYearOnYear: {
growthRate: number
current: {
period: string
period: string | null
value: number
}
previous: {
period: string
period: string | null
value: number
}
}
month: {
growthRate: number
current: {
period: string
period: string | null
value: number
}
previous: {
period: string
period: string | null
value: number
}
}
monthYearOnYear: {
growthRate: number
current: {
period: string
period: string | null
value: number
}
previous: {
period: string
period: string | null
value: number
}
}
year: {
growthRate: number
current: {
period: string
period: string | null
value: number
}
previous: {
period: string
period: string | null
value: number
}
}
}
export interface CompanyShorePowerData {
id: number
harborDistrictId: number
name?: string
shorePowerCount: number // 岸电箱总数
shorePowerIds: number[] // 岸电箱ID列表
distributionList: {
id: number
name: string
shorePowerList: any[]
}[]
}

Loading…
Cancel
Save