|
|
@@ -0,0 +1,531 @@
|
|
|
+<template>
|
|
|
+ <div class="water-station-content">
|
|
|
+ <!-- 测站信息面板 - 右侧 -->
|
|
|
+ <div class="right-panel">
|
|
|
+ <div class="station-card">
|
|
|
+ <div class="card-header">
|
|
|
+ <div class="header-icon">📍</div>
|
|
|
+ <div class="header-title">水文测站</div>
|
|
|
+ </div>
|
|
|
+ <div class="station-list">
|
|
|
+ <div
|
|
|
+ v-for="(station, index) in stations"
|
|
|
+ :key="index"
|
|
|
+ class="station-item"
|
|
|
+ :class="{ active: selectedIndex === index }"
|
|
|
+ @click="selectStation(index)"
|
|
|
+ >
|
|
|
+ <div class="station-name">{{ station.name }}</div>
|
|
|
+ <div class="station-type">{{ station.type }}</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="station-detail">
|
|
|
+ <div class="detail-header">
|
|
|
+ <div class="detail-name">{{ currentStation.name }}</div>
|
|
|
+ <div class="detail-type">{{ currentStation.type }}</div>
|
|
|
+ </div>
|
|
|
+ <div class="detail-info">
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="label">站点编号</span>
|
|
|
+ <span class="value">{{ currentStation.code }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="label">所在河流</span>
|
|
|
+ <span class="value">{{ currentStation.river }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="label">建站时间</span>
|
|
|
+ <span class="value">{{ currentStation.establishDate }}</span>
|
|
|
+ </div>
|
|
|
+ <div class="info-item">
|
|
|
+ <span class="label">监测要素</span>
|
|
|
+ <span class="value">{{ currentStation.elements }}</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="detail-data">
|
|
|
+ <div class="data-title">实时数据</div>
|
|
|
+ <div class="data-grid">
|
|
|
+ <div class="data-item">
|
|
|
+ <div class="data-value">{{ currentStation.waterLevel }}</div>
|
|
|
+ <div class="data-unit">m</div>
|
|
|
+ <div class="data-label">水位</div>
|
|
|
+ </div>
|
|
|
+ <div class="data-item">
|
|
|
+ <div class="data-value">{{ currentStation.flow }}</div>
|
|
|
+ <div class="data-unit">m³/s</div>
|
|
|
+ <div class="data-label">流量</div>
|
|
|
+ </div>
|
|
|
+ <div class="data-item">
|
|
|
+ <div class="data-value">{{ currentStation.rainfall }}</div>
|
|
|
+ <div class="data-unit">mm</div>
|
|
|
+ <div class="data-label">降雨量</div>
|
|
|
+ </div>
|
|
|
+ <div class="data-item">
|
|
|
+ <div class="data-value">{{ currentStation.quality }}</div>
|
|
|
+ <div class="data-unit">类</div>
|
|
|
+ <div class="data-label">水质等级</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 底部测站统计 -->
|
|
|
+ <div class="bottom-panel">
|
|
|
+ <div class="bottom-container">
|
|
|
+ <div class="stat-item">
|
|
|
+ <div class="stat-value">57</div>
|
|
|
+ <div class="stat-label">测站总数</div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-item">
|
|
|
+ <div class="stat-value">42</div>
|
|
|
+ <div class="stat-label">河道站</div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-item">
|
|
|
+ <div class="stat-value">8</div>
|
|
|
+ <div class="stat-label">雨量站</div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-item">
|
|
|
+ <div class="stat-value">7</div>
|
|
|
+ <div class="stat-label">水质站</div>
|
|
|
+ </div>
|
|
|
+ <div class="stat-item">
|
|
|
+ <div class="stat-value">100%</div>
|
|
|
+ <div class="stat-label">在线率</div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref, computed, onMounted, onBeforeUnmount } from "vue"
|
|
|
+import emitter from "@/utils/emitter"
|
|
|
+
|
|
|
+const stations = ref([
|
|
|
+ {
|
|
|
+ name: "昆山水文站",
|
|
|
+ type: "国家基本站",
|
|
|
+ code: "30101200",
|
|
|
+ river: "吴淞江",
|
|
|
+ establishDate: "1954-01",
|
|
|
+ elements: "水位、流量、水质",
|
|
|
+ waterLevel: "2.85",
|
|
|
+ flow: "128.5",
|
|
|
+ rainfall: "12.5",
|
|
|
+ quality: "II"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "玉山站",
|
|
|
+ type: "省级重点站",
|
|
|
+ code: "30101201",
|
|
|
+ river: "娄江",
|
|
|
+ establishDate: "1978-06",
|
|
|
+ elements: "水位、流量",
|
|
|
+ waterLevel: "2.72",
|
|
|
+ flow: "92.3",
|
|
|
+ rainfall: "12.5",
|
|
|
+ quality: "II"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "花桥站",
|
|
|
+ type: "省级重点站",
|
|
|
+ code: "30101202",
|
|
|
+ river: "吴淞江",
|
|
|
+ establishDate: "1985-03",
|
|
|
+ elements: "水位、流量、水质",
|
|
|
+ waterLevel: "2.68",
|
|
|
+ flow: "105.6",
|
|
|
+ rainfall: "12.5",
|
|
|
+ quality: "II"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "周市站",
|
|
|
+ type: "省级重点站",
|
|
|
+ code: "30101203",
|
|
|
+ river: "杨林塘",
|
|
|
+ establishDate: "1982-07",
|
|
|
+ elements: "水位、流量",
|
|
|
+ waterLevel: "2.75",
|
|
|
+ flow: "88.4",
|
|
|
+ rainfall: "12.5",
|
|
|
+ quality: "III"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "陆家站",
|
|
|
+ type: "一般站",
|
|
|
+ code: "30101204",
|
|
|
+ river: "吴淞江",
|
|
|
+ establishDate: "1990-05",
|
|
|
+ elements: "水位、水质",
|
|
|
+ waterLevel: "2.66",
|
|
|
+ flow: "--",
|
|
|
+ rainfall: "12.5",
|
|
|
+ quality: "II"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "张浦站",
|
|
|
+ type: "一般站",
|
|
|
+ code: "30101205",
|
|
|
+ river: "淀山湖",
|
|
|
+ establishDate: "1988-09",
|
|
|
+ elements: "水位、水质",
|
|
|
+ waterLevel: "2.78",
|
|
|
+ flow: "--",
|
|
|
+ rainfall: "12.5",
|
|
|
+ quality: "II"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "周庄站",
|
|
|
+ type: "旅游监测站",
|
|
|
+ code: "30101206",
|
|
|
+ river: "急水港",
|
|
|
+ establishDate: "1995-04",
|
|
|
+ elements: "水位、流量、水质",
|
|
|
+ waterLevel: "2.82",
|
|
|
+ flow: "45.2",
|
|
|
+ rainfall: "12.5",
|
|
|
+ quality: "I"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "巴城站",
|
|
|
+ type: "一般站",
|
|
|
+ code: "30101207",
|
|
|
+ river: "阳澄湖",
|
|
|
+ establishDate: "1986-08",
|
|
|
+ elements: "水位、水质",
|
|
|
+ waterLevel: "2.74",
|
|
|
+ flow: "--",
|
|
|
+ rainfall: "12.5",
|
|
|
+ quality: "II"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "淀山湖站",
|
|
|
+ type: "湖泊站",
|
|
|
+ code: "30101208",
|
|
|
+ river: "淀山湖",
|
|
|
+ establishDate: "1965-04",
|
|
|
+ elements: "水位、水质",
|
|
|
+ waterLevel: "2.76",
|
|
|
+ flow: "--",
|
|
|
+ rainfall: "12.5",
|
|
|
+ quality: "III"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "千灯站",
|
|
|
+ type: "一般站",
|
|
|
+ code: "30101209",
|
|
|
+ river: "千灯浦",
|
|
|
+ establishDate: "1992-06",
|
|
|
+ elements: "水位、流量",
|
|
|
+ waterLevel: "2.71",
|
|
|
+ flow: "68.5",
|
|
|
+ rainfall: "12.5",
|
|
|
+ quality: "II"
|
|
|
+ },
|
|
|
+ {
|
|
|
+ name: "锦溪站",
|
|
|
+ type: "旅游监测站",
|
|
|
+ code: "30101210",
|
|
|
+ river: "五保湖",
|
|
|
+ establishDate: "1998-03",
|
|
|
+ elements: "水位、水质",
|
|
|
+ waterLevel: "2.79",
|
|
|
+ flow: "--",
|
|
|
+ rainfall: "12.5",
|
|
|
+ quality: "I"
|
|
|
+ }
|
|
|
+])
|
|
|
+
|
|
|
+const selectedIndex = ref(0)
|
|
|
+
|
|
|
+const currentStation = computed(() => stations.value[selectedIndex.value])
|
|
|
+
|
|
|
+function selectStation(index) {
|
|
|
+ selectedIndex.value = index
|
|
|
+}
|
|
|
+
|
|
|
+// 监听地图上图标点击事件
|
|
|
+onMounted(() => {
|
|
|
+ emitter.$on("waterStationClick", handleWaterStationClick)
|
|
|
+})
|
|
|
+
|
|
|
+onBeforeUnmount(() => {
|
|
|
+ emitter.$off("waterStationClick", handleWaterStationClick)
|
|
|
+})
|
|
|
+
|
|
|
+function handleWaterStationClick(data) {
|
|
|
+ console.log("收到水文站点击事件:", data)
|
|
|
+ // 根据点击的水文站代码找到对应的索引
|
|
|
+ const index = stations.value.findIndex(station => station.code === data.code)
|
|
|
+ if (index !== -1) {
|
|
|
+ selectedIndex.value = index
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss">
|
|
|
+.water-station-content {
|
|
|
+ position: absolute;
|
|
|
+ top: 0;
|
|
|
+ left: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ z-index: 2;
|
|
|
+ pointer-events: none;
|
|
|
+
|
|
|
+ .map {
|
|
|
+ z-index: 1;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.right-panel {
|
|
|
+ position: absolute;
|
|
|
+ z-index: 4;
|
|
|
+ width: 380px;
|
|
|
+ right: 32px;
|
|
|
+ top: 120px;
|
|
|
+ bottom: 120px;
|
|
|
+ perspective: 800px;
|
|
|
+ perspective-origin: 50% 50%;
|
|
|
+}
|
|
|
+
|
|
|
+.station-card {
|
|
|
+ position: absolute;
|
|
|
+ left: 0;
|
|
|
+ top: 0;
|
|
|
+ right: 0;
|
|
|
+ bottom: 0;
|
|
|
+ background: rgba(0, 20, 40, 0.85);
|
|
|
+ border: 1px solid rgba(48, 220, 255, 0.3);
|
|
|
+ border-radius: 10px;
|
|
|
+ box-shadow: 0 0 20px rgba(48, 220, 255, 0.1);
|
|
|
+ transform: translate3d(0px, 0px, 0px) scaleX(1) scaleY(1) rotateX(0deg) rotateY(-6deg) rotateZ(0deg) skewX(0deg) skewY(0deg);
|
|
|
+ padding: 15px;
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 15px;
|
|
|
+ pointer-events: auto;
|
|
|
+ transform: translateX(150%);
|
|
|
+ opacity: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.card-header {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ gap: 10px;
|
|
|
+ padding-bottom: 10px;
|
|
|
+ border-bottom: 1px solid rgba(48, 220, 255, 0.2);
|
|
|
+ .header-icon {
|
|
|
+ font-size: 24px;
|
|
|
+ }
|
|
|
+ .header-title {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #30dcff;
|
|
|
+ letter-spacing: 2px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.station-list {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: column;
|
|
|
+ gap: 8px;
|
|
|
+ max-height: 200px;
|
|
|
+ overflow-y: auto;
|
|
|
+
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 4px;
|
|
|
+ }
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ background: rgba(48, 220, 255, 0.3);
|
|
|
+ border-radius: 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .station-item {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ padding: 10px 12px;
|
|
|
+ background: rgba(48, 220, 255, 0.1);
|
|
|
+ border: 1px solid rgba(48, 220, 255, 0.2);
|
|
|
+ border-radius: 6px;
|
|
|
+ cursor: pointer;
|
|
|
+ transition: all 0.3s ease;
|
|
|
+ pointer-events: auto;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ background: rgba(48, 220, 255, 0.2);
|
|
|
+ border-color: rgba(48, 220, 255, 0.4);
|
|
|
+ }
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ background: rgba(48, 220, 255, 0.3);
|
|
|
+ border-color: rgba(48, 220, 255, 0.6);
|
|
|
+ box-shadow: 0 0 10px rgba(48, 220, 255, 0.3);
|
|
|
+ }
|
|
|
+
|
|
|
+ .station-name {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #c4f3fe;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .station-type {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #00bfff;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.station-detail {
|
|
|
+ flex: 1;
|
|
|
+ background: rgba(0, 180, 255, 0.05);
|
|
|
+ border-radius: 8px;
|
|
|
+ padding: 15px;
|
|
|
+ border: 1px solid rgba(48, 220, 255, 0.1);
|
|
|
+ overflow-y: auto;
|
|
|
+
|
|
|
+ &::-webkit-scrollbar {
|
|
|
+ width: 4px;
|
|
|
+ }
|
|
|
+ &::-webkit-scrollbar-thumb {
|
|
|
+ background: rgba(48, 220, 255, 0.3);
|
|
|
+ border-radius: 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-header {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 15px;
|
|
|
+ padding-bottom: 10px;
|
|
|
+ border-bottom: 1px solid rgba(48, 220, 255, 0.2);
|
|
|
+
|
|
|
+ .detail-name {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #30dcff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-type {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #43e97b;
|
|
|
+ padding: 4px 8px;
|
|
|
+ background: rgba(67, 233, 123, 0.1);
|
|
|
+ border-radius: 4px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-info {
|
|
|
+ margin-bottom: 15px;
|
|
|
+
|
|
|
+ .info-item {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 8px 0;
|
|
|
+ border-bottom: 1px solid rgba(48, 220, 255, 0.1);
|
|
|
+
|
|
|
+ &:last-child {
|
|
|
+ border-bottom: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ .label {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #a3dcde;
|
|
|
+ }
|
|
|
+
|
|
|
+ .value {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #c4f3fe;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .detail-data {
|
|
|
+ padding-top: 15px;
|
|
|
+ border-top: 1px solid rgba(48, 220, 255, 0.2);
|
|
|
+
|
|
|
+ .data-title {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #30dcff;
|
|
|
+ margin-bottom: 12px;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .data-grid {
|
|
|
+ display: grid;
|
|
|
+ grid-template-columns: 1fr 1fr;
|
|
|
+ gap: 10px;
|
|
|
+
|
|
|
+ .data-item {
|
|
|
+ background: rgba(48, 220, 255, 0.1);
|
|
|
+ border-radius: 6px;
|
|
|
+ padding: 12px;
|
|
|
+ text-align: center;
|
|
|
+ border: 1px solid rgba(48, 220, 255, 0.2);
|
|
|
+
|
|
|
+ .data-value {
|
|
|
+ font-size: 24px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #30dcff;
|
|
|
+ line-height: 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ .data-unit {
|
|
|
+ font-size: 11px;
|
|
|
+ color: #a3dcde;
|
|
|
+ margin-top: 2px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .data-label {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #c4f3fe;
|
|
|
+ margin-top: 6px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.bottom-panel {
|
|
|
+ position: absolute;
|
|
|
+ left: 100px;
|
|
|
+ right: 430px;
|
|
|
+ bottom: 20px;
|
|
|
+ height: 70px;
|
|
|
+ z-index: 4;
|
|
|
+}
|
|
|
+
|
|
|
+.bottom-container {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-around;
|
|
|
+ align-items: center;
|
|
|
+ height: 100%;
|
|
|
+ background: rgba(0, 20, 40, 0.85);
|
|
|
+ border: 1px solid rgba(48, 220, 255, 0.3);
|
|
|
+ border-radius: 10px;
|
|
|
+ padding: 0 30px;
|
|
|
+ pointer-events: auto;
|
|
|
+ transform: translateY(100%);
|
|
|
+ opacity: 0;
|
|
|
+
|
|
|
+ .stat-item {
|
|
|
+ text-align: center;
|
|
|
+
|
|
|
+ .stat-value {
|
|
|
+ font-size: 28px;
|
|
|
+ font-weight: bold;
|
|
|
+ color: #30dcff;
|
|
|
+ text-shadow: 0 0 10px rgba(48, 220, 255, 0.5);
|
|
|
+ }
|
|
|
+
|
|
|
+ .stat-label {
|
|
|
+ font-size: 13px;
|
|
|
+ color: #a3dcde;
|
|
|
+ margin-top: 5px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|