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.
1334 lines
40 KiB
1334 lines
40 KiB
<template>
|
|
<div class="show-data">
|
|
<div v-if="showShipList || shorePowerCardShow" class="left">
|
|
<!-- <div style="display: flex; align-items: center; justify-content: space-between;"> -->
|
|
<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>
|
|
<img src="@/assets/svgs/data.svg" class="title-icon" />
|
|
<span class="title-text">船舶状态</span>
|
|
</div>
|
|
<div style="display: flex; align-items: center;gap: 4px;height: 32px;">
|
|
<input class="search-container" type="text" placeholder="搜索船舶" v-model="searchKeyword"
|
|
@input="handleSearch" />
|
|
<el-button class="close-btn" size="small" type="text" @click="handleCloseShipList">×</el-button>
|
|
</div>
|
|
|
|
</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="ship in filteredShipStatusData" :key="ship.id" class="ship-table-row"
|
|
@click="handleSelectItem(ship)">
|
|
<div class="ship-table-column ship-name">
|
|
<div class="ship-icon">🚢</div>
|
|
<span class="ship-name-text">{{ ship.shipBasicInfo.name }}</span>
|
|
</div>
|
|
<div class="ship-table-column ship-status">
|
|
<div class="status-tag" :class="getStatusClass(ship.shipStatus)">
|
|
{{ ship.shipStatus }}
|
|
</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="showShipHistory(ship)">查看</el-button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<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>
|
|
<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-detail">
|
|
<div class="detail-item">
|
|
<span class="label">名称:</span>
|
|
<span class="value">{{ shipSelectedItem.shipBasicInfo.name + '-' +
|
|
shipSelectedItem.shipBasicInfo.nameEn
|
|
}}</span>
|
|
</div>
|
|
<!-- <div class="detail-item">
|
|
<span class="label">英文船名:</span>
|
|
<span class="value">{{ selectedItem.shipBasicInfo.nameEn }}</span>
|
|
</div> -->
|
|
<!-- <div class="detail-item">
|
|
<span class="label">船舶呼号:</span>
|
|
<span class="value">{{ selectedItem.shipBasicInfo.callSign }}</span>
|
|
</div> -->
|
|
<div class="detail-item">
|
|
<span class="label">长度:</span>
|
|
<span class="value">{{ shipSelectedItem.shipBasicInfo.length }} 米</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="label">宽度:</span>
|
|
<span class="value">{{ shipSelectedItem.shipBasicInfo.width }} 米</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="label">吨位:</span>
|
|
<span class="value">{{ shipSelectedItem.shipBasicInfo.tonnage }} 吨</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="label">满载吃水深度:</span>
|
|
<span class="value">{{ shipSelectedItem.shipBasicInfo.fullLoadDraft }} 米</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="label">电压:</span>
|
|
<span class="value">{{ getValueById(realtimeDeviceData,
|
|
shipSelectedItem.shorePower.voltageDeviceId,
|
|
'measureValue') }}</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="label">电流:</span>
|
|
<span class="value">{{ getValueById(realtimeDeviceData,
|
|
shipSelectedItem.shorePower.currentDeviceId,
|
|
'measureValue') }}</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="label">频率:</span>
|
|
<span class="value">{{ getValueById(realtimeDeviceData,
|
|
shipSelectedItem.shorePower.frequencyDeviceId,
|
|
'measureValue') }}</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="label">靠泊状态:</span>
|
|
<span class="value">{{ getOperationTypeLabel(shipSelectedItem.shorePowerAndShip.status,
|
|
SHORE_POWER_STATUS,
|
|
) }}</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="label">靠泊类型:</span>
|
|
<span class="value">{{ getOperationTypeLabel(shipSelectedItem.shorePowerAndShip.type,
|
|
BERTH_TYPE)
|
|
}}</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="label">靠泊时间:</span>
|
|
<span class="value">{{
|
|
formatTimestamp(shipSelectedItem?.usageRecordInfo?.actualBerthTime) }}</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="label">当前状态:</span>
|
|
<span class="value">{{ shipSelectedItem.shipStatus }}<span v-if="shipSelectedItem.StatusReason">({{
|
|
shipSelectedItem.StatusReason
|
|
}})</span></span>
|
|
</div>
|
|
<div v-if="shipSelectedItem.applyInfo.reason === 0" class="detail-item">
|
|
<span class="label">岸电使用时长</span>
|
|
<span class="value">{{ showStatus(shipSelectedItem, realtimeDeviceData)?.useTime }}</span>
|
|
</div>
|
|
<div v-if="shipSelectedItem.applyInfo.reason === 0" class="detail-item">
|
|
<span class="label">岸电使用用量:</span>
|
|
<span class="value">{{ showStatus(shipSelectedItem, realtimeDeviceData)?.useValue }}</span>
|
|
</div>
|
|
<div v-if="shipSelectedItem.applyInfo.reason != 0" class="detail-item">
|
|
<span class="label">未使用岸电原因:</span>
|
|
<span class="value">{{ getOperationTypeLabel(shipSelectedItem?.applyInfo?.reason,
|
|
UNUSED_SHORE_POWER_REASON) }}</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="label">岸电联系人:</span>
|
|
<span class="value">{{ shipSelectedItem?.shipBasicInfo?.shorePowerContact
|
|
}}</span>
|
|
</div>
|
|
<div class="detail-item">
|
|
<span class="label">联系方式:</span>
|
|
<span class="value">{{ shipSelectedItem?.shipBasicInfo?.shorePowerContactPhone
|
|
}}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-if="shorePowerCardShow && !showShipList" style="width: 840px">
|
|
<ShorePowerUsageRate :realtimeDeviceDataTime="realtimeDeviceDataTime" :handleClose="handleCloseRate" />
|
|
|
|
</div>
|
|
<!-- <div v-if="shorePowerCardShow" class="card digital-twin-card--deep-blue"
|
|
style=" display: inline-block; width: 840px;">
|
|
<div class="card-title">
|
|
<el-button class="close-btn" size="small" type="text" @click="handleCloseShipDetail">×</el-button>
|
|
<div class="vertical-line"></div>
|
|
<img src="@/assets/svgs/data.svg" class="title-icon" />
|
|
<span class="title-text">岸电使用率</span>
|
|
</div>
|
|
<div class="card-content">
|
|
12
|
|
</div>
|
|
</div> -->
|
|
<!-- </div> -->
|
|
</div>
|
|
<div class="right" style="width: 900px">
|
|
<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> -->
|
|
</div>
|
|
<div class="card-content">
|
|
<!-- 港口岸电使用情况 -->
|
|
<div class="module-section">
|
|
|
|
<div class="module-header">
|
|
<div style="display: flex; align-items: center; gap: 20px;">
|
|
<h3 class="module-title" @click="handleGoToModule(1, portActivePeriod)">港区岸电用电量统计</h3>
|
|
<div class="module-time">
|
|
<div>{{ portStartTime }} 至 {{ realtimeDeviceDataTime }}</div>
|
|
</div>
|
|
</div>
|
|
<div class="period-filter">
|
|
<div v-for="period in periodOptions" :key="period.value"
|
|
:class="['period-option', { active: portActivePeriod === period.value }]"
|
|
@click="switchPortPeriod(period.value)">
|
|
{{ period.label }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="port-overview">
|
|
<div class="first-row">
|
|
<div class="benefit-card" @click="handleCardClick('totalPower')">
|
|
<div class="benefit-value">{{ chartData[portActivePeriod].totalPower }}</div>
|
|
<div class="benefit-unit">累计用电 (千瓦时)</div>
|
|
</div>
|
|
<div class="benefit-card" @click="handleCardClick('co2')">
|
|
<div class="benefit-value">{{ chartData[portActivePeriod].co2 }}</div>
|
|
<div class="benefit-unit">减少二氧化碳排放 (千克)</div>
|
|
</div>
|
|
</div>
|
|
<div class="second-row">
|
|
<div class="benefit-card" @click="handleCardClick('fuel')">
|
|
<div class="benefit-value">{{ chartData[portActivePeriod].fuel }}</div>
|
|
<div class="benefit-unit">减少燃油<br /> (吨)</div>
|
|
</div>
|
|
<div class="benefit-card" @click="handleCardClick('pm25')">
|
|
<div class="benefit-value">{{ chartData[portActivePeriod].pm25 }}</div>
|
|
<div class="benefit-unit">减少PM2.5排放<br /> (千克)</div>
|
|
</div>
|
|
<div class="benefit-card" @click="handleCardClick('nox')">
|
|
<div class="benefit-value">{{ chartData[portActivePeriod].nox }}</div>
|
|
<div class="benefit-unit">减少氮氧化物<br /> (千克)</div>
|
|
</div>
|
|
<div class="benefit-card" @click="handleCardClick('so2')">
|
|
<div class="benefit-value">{{ chartData[portActivePeriod].so2 }}</div>
|
|
<div class="benefit-unit">减少二氧化硫<br /> (千克)</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 港口企业岸电使用 -->
|
|
<div class="module-section">
|
|
<div class="module-header">
|
|
<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 v-for="period in periodOptions" :key="period.value"
|
|
:class="['period-option', { active: enterpriseActivePeriod === period.value }]"
|
|
@click="switchEnterprisePeriod(period.value)">
|
|
{{ period.label }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="enterprise-usage">
|
|
<div class="usage-bars">
|
|
<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">
|
|
<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" style="flex: 1;">
|
|
<div class="module-header">
|
|
<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> -->
|
|
<div class="period-filter">
|
|
<div v-for="period in periodOptions" :key="period.value"
|
|
:class="['period-option', { active: shipActivePeriod === period.value }]"
|
|
@click="switchShipPeriod(period.value)">
|
|
{{ period.label }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="ship-status">
|
|
<div class="usage-rate shadow" @click="handleOpenRate">
|
|
<div class="rate-value">{{ calculateShorePowerUsageRate() }}%</div>
|
|
<div class="rate-label">岸电使用率</div>
|
|
</div>
|
|
<div class="status-grid">
|
|
<div class="status-card">
|
|
<div class="status-value">{{ shipTotalData.allPortAreaCount }}</div>
|
|
<div class="status-label">在港船舶</div>
|
|
</div>
|
|
<div class="status-card" @click="handleShowShipList('all')">
|
|
<div class="status-value">{{ shipTotalData.berthingShips }}</div>
|
|
<div class="status-label">在泊船舶</div>
|
|
</div>
|
|
<div class="status-card" @click="handleShowShipList('using')">
|
|
<div class="status-value">{{ shipTotalData.shorePowerShips }}</div>
|
|
<div class="status-label">使用岸电船舶</div>
|
|
</div>
|
|
<div class="status-card" @click="handleShowShipList('notUsing')">
|
|
<div class="status-value">{{ shipTotalData.noShorePowerShips }}</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>
|
|
<ShipHistoryDialog v-model="shipHistoryVisible.visible" :ship-param="shipHistoryVisible.searchParams"
|
|
:realtime-device-data="realtimeDeviceData" />
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { 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 {
|
|
handleGoToModule: (moduleType: number, timeRange?: string) => void
|
|
realtimeDeviceDataTime: string
|
|
realtimeDeviceData: RealtimeDeviceData[]
|
|
chartData: {
|
|
[key in 'day' | 'month' | 'year' | 'realtime']: {
|
|
'totalPower': number,
|
|
'fuel': number,
|
|
'co2': number,
|
|
'pm25': number,
|
|
'nox': number,
|
|
'so2': number,
|
|
}
|
|
};
|
|
shipTotalData: {
|
|
'allPortAreaCount': number,
|
|
'berthingShips': number,
|
|
'shorePowerShips': number,
|
|
'noShorePowerShips': number,
|
|
}
|
|
shipDataList: ShipRespVo[]
|
|
companyShorePowerData: CompanyShorePowerData[]
|
|
yearData: any[];
|
|
monthData: any[];
|
|
dayData: any[];
|
|
}
|
|
|
|
const props = defineProps<Props>()
|
|
const currentShip = ref<ShipRespVo | null>(null)
|
|
const showShipList = ref(false)
|
|
const searchKeyword = ref('')
|
|
// 获取当前日期
|
|
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 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({
|
|
visible: false,
|
|
searchParams: {
|
|
shipId: 0 as number | null,
|
|
ids: [] as number[] | null,
|
|
type: 1 as number
|
|
}
|
|
})
|
|
|
|
const shipSelectedItem = ref<ShipRespVo | null>(null)
|
|
const shorePowerCardShow = ref(false)
|
|
|
|
const periodOptions = [
|
|
{ label: '当日', value: 'day' },
|
|
{ label: '当月', value: 'month' },
|
|
{ label: '当年', value: 'year' },
|
|
{ label: '汇总', value: 'realtime' },
|
|
]
|
|
|
|
// 模拟不同时间段的数据
|
|
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 handleCloseRate = () => {
|
|
shorePowerCardShow.value = false
|
|
}
|
|
|
|
const handleOpenRate = () => {
|
|
handleCloseShipList()
|
|
shorePowerCardShow.value = true
|
|
|
|
}
|
|
|
|
|
|
|
|
// 根据选择的时间段动态生成起始时间 - 为每个模块创建独立的计算属性
|
|
const portStartTime = computed(() => {
|
|
const now = new Date()
|
|
let startDate: Date
|
|
|
|
switch (portActivePeriod.value) {
|
|
case 'day':
|
|
// 今日的零点
|
|
startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())
|
|
break
|
|
case 'month':
|
|
// 当月的第一天零点
|
|
startDate = new Date(now.getFullYear(), now.getMonth(), 1)
|
|
break
|
|
case 'year':
|
|
// 当年的第一天零点
|
|
startDate = new Date(now.getFullYear(), 0, 1)
|
|
break
|
|
case 'realtime':
|
|
startDate = new Date(2020, 0, 1) // 2020年1月1日
|
|
break
|
|
default:
|
|
startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())
|
|
}
|
|
|
|
// 格式化日期时间
|
|
const year = startDate.getFullYear()
|
|
const month = String(startDate.getMonth() + 1).padStart(2, '0')
|
|
const day = String(startDate.getDate()).padStart(2, '0')
|
|
const hours = String(startDate.getHours()).padStart(2, '0')
|
|
const minutes = String(startDate.getMinutes()).padStart(2, '0')
|
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}`
|
|
})
|
|
|
|
const enterpriseStartTime = computed(() => {
|
|
const now = new Date()
|
|
let startDate: Date
|
|
|
|
switch (enterpriseActivePeriod.value) {
|
|
case 'day':
|
|
// 今日的零点
|
|
startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())
|
|
break
|
|
case 'month':
|
|
// 当月的第一天零点
|
|
startDate = new Date(now.getFullYear(), now.getMonth(), 1)
|
|
break
|
|
case 'year':
|
|
// 当年的第一天零点
|
|
startDate = new Date(now.getFullYear(), 0, 1)
|
|
break
|
|
case 'realtime':
|
|
startDate = new Date(2020, 0, 1) // 2020年1月1日
|
|
break
|
|
default:
|
|
startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())
|
|
}
|
|
|
|
// 格式化日期时间
|
|
const year = startDate.getFullYear()
|
|
const month = String(startDate.getMonth() + 1).padStart(2, '0')
|
|
const day = String(startDate.getDate()).padStart(2, '0')
|
|
const hours = String(startDate.getHours()).padStart(2, '0')
|
|
const minutes = String(startDate.getMinutes()).padStart(2, '0')
|
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}`
|
|
})
|
|
|
|
const shipStartTime = computed(() => {
|
|
const now = new Date()
|
|
let startDate: Date
|
|
|
|
switch (shipActivePeriod.value) {
|
|
case 'day':
|
|
// 今日的零点
|
|
startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())
|
|
break
|
|
case 'month':
|
|
// 当月的第一天零点
|
|
startDate = new Date(now.getFullYear(), now.getMonth(), 1)
|
|
break
|
|
case 'year':
|
|
// 当年的第一天零点
|
|
startDate = new Date(now.getFullYear(), 0, 1)
|
|
break
|
|
case 'realtime':
|
|
startDate = new Date(2020, 0, 1) // 2020年1月1日
|
|
break
|
|
default:
|
|
startDate = new Date(now.getFullYear(), now.getMonth(), now.getDate())
|
|
}
|
|
|
|
// 格式化日期时间
|
|
const year = startDate.getFullYear()
|
|
const month = String(startDate.getMonth() + 1).padStart(2, '0')
|
|
const day = String(startDate.getDate()).padStart(2, '0')
|
|
const hours = String(startDate.getHours()).padStart(2, '0')
|
|
const minutes = String(startDate.getMinutes()).padStart(2, '0')
|
|
|
|
return `${year}-${month}-${day} ${hours}:${minutes}`
|
|
})
|
|
|
|
|
|
// 计算岸电使用率
|
|
const calculateShorePowerUsageRate = (): number => {
|
|
if (!props.shipTotalData || props.shipTotalData.berthingShips === 0) return 0
|
|
|
|
// 计算使用岸电船舶数量占总在港船舶数量的比例
|
|
const usageRate = (props.shipTotalData.shorePowerShips / props.shipTotalData.allPortAreaCount) * 100
|
|
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 maxPower = Math.max(...companyData.map(item => {
|
|
return parseFloat(handGetDeviceData(item.shorePowerIds, getCompanyTimeRange(item.id)))
|
|
}))
|
|
|
|
// 如果最大值为0,返回0以避免除以0
|
|
if (maxPower === 0) return 0
|
|
|
|
// 计算百分比,最小值设为5%以确保即使是最小的值也能在视觉上显示
|
|
const percentage = (parseFloat(companyPower) / maxPower) * 100
|
|
return Math.max(percentage, 5)
|
|
}
|
|
|
|
// 切换时间段 - 为每个模块创建独立的切换方法
|
|
const switchPortPeriod = (period: 'realtime' | 'day' | 'month' | 'year') => {
|
|
portActivePeriod.value = period
|
|
}
|
|
|
|
const switchEnterprisePeriod = (period: 'realtime' | 'day' | 'month' | 'year') => {
|
|
enterpriseActivePeriod.value = period
|
|
}
|
|
|
|
const switchShipPeriod = (period: 'realtime' | 'day' | 'month' | 'year') => {
|
|
shipActivePeriod.value = period
|
|
}
|
|
|
|
// 处理卡片点击事件,跳转到详细页面并设置对应的卡片
|
|
const handleCardClick = (cardType: string) => {
|
|
// 先跳转到港口岸电使用情况模块(activeHeadGroup = 1)
|
|
props.handleGoToModule(5, portActivePeriod.value)
|
|
// 使用nextTick确保组件已经渲染后再设置selectedCard
|
|
setTimeout(() => {
|
|
// 发送消息到父组件或通过事件总线通知ShorePowerUsage组件切换卡片
|
|
window.dispatchEvent(new CustomEvent('cardSelected', { detail: cardType }))
|
|
}, 100)
|
|
}
|
|
|
|
// 处理搜索输入
|
|
const handleSearch = () => {
|
|
// 输入处理逻辑(如果需要额外处理可以在这里添加)
|
|
}
|
|
|
|
// 定义事件
|
|
const emit = defineEmits<{
|
|
(e: 'switch-ship', ship: ShipRespVo): void;
|
|
(e: 'item-click', item: any): void;
|
|
// handleSelectItem(ship)
|
|
|
|
}>()
|
|
|
|
const handleSelectItem = async (item: ShipRespVo) => {
|
|
const deviceId = item.shorePower?.totalPowerDeviceId;
|
|
const res = await MapApi.getRealtimeDataByIdList({ ids: deviceId })
|
|
console.log(res)
|
|
shipSelectedItem.value = {
|
|
...item,
|
|
shorePowerEquipment: {
|
|
...item.shorePowerEquipment,
|
|
'measureValue': res[0].measureValue || 'N/A',
|
|
}
|
|
}
|
|
emit('item-click', {
|
|
type: 'ship',
|
|
item: item
|
|
})
|
|
}
|
|
|
|
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-default'
|
|
}
|
|
}
|
|
|
|
// 过滤后的船舶数据
|
|
const filteredShipStatusData = computed(() => {
|
|
let filterData: ShipRespVo[] = []
|
|
if (filterType.value === 'using') {
|
|
filterData = props.shipDataList.filter(ship => ['在用'].includes(ship.shipStatus || ''))
|
|
} else if (filterType.value === 'notUsing') {
|
|
filterData = props.shipDataList.filter(ship => !['在用'].includes(ship.shipStatus || ''))
|
|
} else {
|
|
filterData = props.shipDataList
|
|
}
|
|
|
|
if (!searchKeyword.value) {
|
|
return filterData
|
|
}
|
|
return filterData.filter(ship =>
|
|
ship.shipBasicInfo.name.toLowerCase().includes(searchKeyword.value.toLowerCase())
|
|
)
|
|
})
|
|
|
|
// 显示船舶历史记录
|
|
const showShipHistory = (ship: ShipRespVo) => {
|
|
console.log('ship', ship)
|
|
currentShip.value = ship
|
|
shipHistoryVisible.value = {
|
|
visible: true,
|
|
searchParams: {
|
|
shipId: ship.shipBasicInfo.id,
|
|
ids: null,
|
|
type: 1,
|
|
}
|
|
}
|
|
}
|
|
|
|
const handleShowShipList = (type: string) => {
|
|
handleCloseRate()
|
|
filterType.value = type
|
|
showShipList.value = true
|
|
}
|
|
|
|
// 关闭船舶列表面板
|
|
const handleCloseShipList = () => {
|
|
handleCloseShipDetail()
|
|
showShipList.value = false
|
|
}
|
|
|
|
// 关闭船舶详情面板
|
|
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">
|
|
.show-data {
|
|
display: flex;
|
|
gap: 10px;
|
|
height: 100%;
|
|
}
|
|
|
|
.left {
|
|
// height: 100%;
|
|
// flex: 1;
|
|
display: flex;
|
|
flex-direction: row;
|
|
width: auto;
|
|
// flex-direction: column;
|
|
gap: 10px;
|
|
|
|
.card {
|
|
// width: 200px;
|
|
|
|
padding: 12px;
|
|
padding-top: 24px;
|
|
padding-bottom: 24px;
|
|
}
|
|
}
|
|
|
|
.right {
|
|
top: 0;
|
|
height: 100vh;
|
|
}
|
|
|
|
.card {
|
|
padding-top: 0px;
|
|
padding-right: 0px;
|
|
padding-left: 12px;
|
|
}
|
|
|
|
.card-content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
padding: 8px;
|
|
}
|
|
|
|
.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;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 8px;
|
|
}
|
|
|
|
.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: 8px;
|
|
}
|
|
|
|
.module-header {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding-bottom: 12px;
|
|
/* border-bottom: 2px solid rgba(64, 158, 255, 0.3); */
|
|
}
|
|
|
|
.module-title {
|
|
font-size: 22px;
|
|
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;
|
|
}
|
|
|
|
.module-time {
|
|
font-size: 18px;
|
|
color: #67c23a;
|
|
}
|
|
|
|
.module-time div {
|
|
line-height: 1.5;
|
|
}
|
|
|
|
|
|
|
|
/* 港口岸电使用情况 */
|
|
.port-overview {
|
|
margin-bottom: 6px 12px;
|
|
}
|
|
|
|
.first-row {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 12px;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.second-row {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
gap: 12px;
|
|
}
|
|
|
|
.total-electricity {
|
|
text-align: center;
|
|
margin-bottom: 20px;
|
|
padding: 20px;
|
|
background: rgba(30, 120, 255, 0.1);
|
|
border-radius: 10px;
|
|
}
|
|
|
|
.total-value {
|
|
font-size: 36px;
|
|
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: 12px;
|
|
}
|
|
|
|
.benefit-card {
|
|
background: rgba(30, 120, 255, 0.15);
|
|
border: 1px solid rgba(64, 158, 255, 0.4);
|
|
border-radius: 8px;
|
|
padding: 16px 8px;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.benefit-card:hover {
|
|
background: rgba(30, 120, 255, 0.25);
|
|
border: 1px solid rgba(64, 158, 255, 0.6);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.benefit-value {
|
|
font-size: 32px;
|
|
font-weight: bold;
|
|
color: #FFF;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.benefit-unit {
|
|
font-size: 18px;
|
|
color: #a0cfff;
|
|
}
|
|
|
|
/* 港口企业岸电使用 */
|
|
.enterprise-usage {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.usage-bars {
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.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: #cce6ff;
|
|
}
|
|
|
|
.bar-value {
|
|
font-size: 14px;
|
|
color: #FFF;
|
|
font-weight: bold;
|
|
}
|
|
|
|
:deep(.el-progress-bar__outer) {
|
|
background: rgba(30, 120, 255, 0.3);
|
|
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;
|
|
height: 100%;
|
|
}
|
|
|
|
.usage-rate {
|
|
text-align: center;
|
|
height: 50%;
|
|
padding: 16px 8px;
|
|
background: rgba(30, 120, 255, 0.15);
|
|
border-radius: 10px;
|
|
margin-bottom: 6px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
|
|
&:hover {
|
|
transform: translateY(-2px);
|
|
color: #66b1ff;
|
|
}
|
|
}
|
|
|
|
.usage-rate.shadow {
|
|
box-shadow: 0 0px 10px rgb(255, 255, 255);
|
|
border: 2px solid rgba(255, 255, 255, 0.2);
|
|
}
|
|
|
|
.rate-value {
|
|
font-size: 36px;
|
|
font-weight: bold;
|
|
color: #FFF;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.rate-label {
|
|
font-size: 24px;
|
|
color: #a0cfff;
|
|
}
|
|
|
|
.status-grid {
|
|
height: 38%;
|
|
display: grid;
|
|
grid-template-columns: repeat(4, 1fr);
|
|
gap: 12px;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.status-card {
|
|
background: rgba(30, 120, 255, 0.15);
|
|
border: 1px solid rgba(64, 158, 255, 0.4);
|
|
border-radius: 8px;
|
|
padding: 16px;
|
|
text-align: center;
|
|
cursor: pointer;
|
|
transition: all 0.3s ease;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.status-card:hover {
|
|
background: rgba(30, 120, 255, 0.25);
|
|
border: 1px solid rgba(64, 158, 255, 0.6);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.status-value {
|
|
font-size: 42px;
|
|
font-weight: bold;
|
|
color: #FFF;
|
|
margin-bottom: 5px;
|
|
}
|
|
|
|
.status-label {
|
|
font-size: 24px;
|
|
font-weight: 500;
|
|
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: 180px;
|
|
}
|
|
|
|
.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: #ffffff;
|
|
}
|
|
|
|
.branch-value {
|
|
font-size: 26px;
|
|
font-weight: bold;
|
|
color: #409eff;
|
|
min-width: 140px;
|
|
text-align: right;
|
|
margin-right: 12px;
|
|
}
|
|
|
|
.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: 24px;
|
|
height: 24px;
|
|
// border-radius: 50%;
|
|
// background-color: #ff4d4f;
|
|
color: white;
|
|
border: none;
|
|
font-weight: bold;
|
|
font-size: 16px;
|
|
cursor: pointer;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-left: 10px;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.close-btn:hover {
|
|
color: #f5222d;
|
|
}
|
|
</style>
|