代码更新

This commit is contained in:
ZhengMingKing
2026-06-12 21:51:38 +08:00
parent c939e57010
commit b75380b973
3 changed files with 225 additions and 20 deletions

View File

@@ -118,6 +118,44 @@ body:not(.login-light-mode) {
color: var(--tech-text);
}
.el-button:not(.el-button--primary):not(.el-button--success):not(.el-button--warning):not(.el-button--danger):not(.el-button--info):not(.is-link):not(.is-text) {
--el-button-bg-color: rgba(2, 8, 23, 0.72);
--el-button-border-color: rgba(0, 212, 255, 0.42);
--el-button-text-color: #e9fbff;
--el-button-hover-bg-color: rgba(0, 212, 255, 0.18);
--el-button-hover-border-color: rgba(0, 212, 255, 0.72);
--el-button-hover-text-color: #ffffff;
--el-button-active-bg-color: rgba(0, 212, 255, 0.24);
--el-button-active-border-color: rgba(0, 212, 255, 0.82);
--el-button-active-text-color: #ffffff;
--el-button-disabled-bg-color: rgba(15, 23, 42, 0.48);
--el-button-disabled-border-color: rgba(0, 212, 255, 0.16);
--el-button-disabled-text-color: rgba(220, 243, 255, 0.5);
color: var(--el-button-text-color) !important;
font-weight: 700;
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.82);
background: var(--el-button-bg-color) !important;
border-color: var(--el-button-border-color) !important;
.el-icon {
color: currentColor;
}
&:hover,
&:focus {
color: var(--el-button-hover-text-color) !important;
background: var(--el-button-hover-bg-color) !important;
border-color: var(--el-button-hover-border-color) !important;
}
&:active {
color: var(--el-button-active-text-color) !important;
background: var(--el-button-active-bg-color) !important;
border-color: var(--el-button-active-border-color) !important;
}
}
.el-input__inner::placeholder,
.el-textarea__inner::placeholder {
color: rgba(220, 243, 255, 0.56);

View File

@@ -4,7 +4,7 @@
<div class="scan-light"></div>
<div class="container">
<div class="left">
<div class="module-card left-first-module">
<div class="module-card left-first-module device-link-card" role="button" tabindex="0" @click="goToEquipmentOverview" @keyup.enter="goToEquipmentOverview">
<div class="module-header">
<div class="module-title">
<span class="title-icon"></span>
@@ -16,7 +16,7 @@
<e-charts ref="deviceStatChartRef" :option="deviceStatOption" autoresize />
</div>
<div class="device-list">
<div class="device-item" v-for="(item, index) in deviceTypes" :key="index">
<div class="device-item" v-for="(item, index) in displayDeviceTypes" :key="index">
<span class="device-dot" :style="{ backgroundColor: item.color }"></span>
<span class="device-name">{{ item.name || item.deviceTypeName }}</span>
<span class="device-count" :style="{ color: item.color }">{{ item.count || item.value }}</span>
@@ -25,7 +25,7 @@
</div>
</div>
</div>
<div class="module-card left-second-module">
<div class="module-card left-second-module device-link-card" role="button" tabindex="0" @click="goToEquipmentOverview" @keyup.enter="goToEquipmentOverview">
<div class="module-header">
<div class="module-title">
<span class="title-icon"></span>
@@ -53,7 +53,7 @@
</el-table>
</div>
</div>
<div class="module-card left-third-module">
<div class="module-card left-third-module device-link-card" role="button" tabindex="0" @click="goToEquipmentOverview" @keyup.enter="goToEquipmentOverview">
<div class="module-header">
<div class="module-title">
<span class="title-icon"></span>
@@ -96,7 +96,7 @@
<div class="top2">
<div class="card map-card">
<div class="card-title" style="display: none">设备分布</div>
<div class="map-container-full" id="chinaMap" ref="chinaMap">
<div class="map-container-full" :class="`map-mode-${mapDisplayMode.toLowerCase()}`" id="chinaMap" ref="chinaMap">
<div class="map-corner top-left"></div>
<div class="map-corner top-right"></div>
<div class="map-corner bottom-left"></div>
@@ -107,6 +107,18 @@
<span class="map-title-main">全国设备态势</span>
<span class="map-title-sub">REAL-TIME DISTRIBUTION</span>
</div>
<div class="map-mode-switch">
<button
v-for="mode in mapModeOptions"
:key="mode.value"
class="map-mode-button"
:class="{ active: mapDisplayMode === mode.value }"
type="button"
@click="switchMapMode(mode.value)"
>
{{ mode.label }}
</button>
</div>
<div class="map-control">
<div class="control-top">
<div class="control-title">设备总数量</div>
@@ -163,7 +175,7 @@
</div>
</div>
<div class="right">
<div class="module-card alarm-pending-module">
<div class="module-card alarm-pending-module alarm-link-card" role="button" tabindex="0" @click="goToAllAlarmPage" @keyup.enter="goToAllAlarmPage">
<div class="module-header">
<div class="module-title">
<span class="title-icon"></span>
@@ -175,7 +187,7 @@
</div>
</div>
<div class="module-card alert-distribution-module">
<div class="module-card alert-distribution-module alarm-link-card" role="button" tabindex="0" @click="goToAllAlarmPage" @keyup.enter="goToAllAlarmPage">
<div class="module-header">
<div class="module-title">
<span class="title-icon"></span>
@@ -198,7 +210,7 @@
</div>
</div>
<div class="module-card alert-trend-module">
<div class="module-card alert-trend-module alarm-link-card" role="button" tabindex="0" @click="goToAllAlarmPage" @keyup.enter="goToAllAlarmPage">
<div class="module-header">
<div class="module-title">
<span class="title-icon"></span>
@@ -215,10 +227,12 @@
</template>
<script setup>
/* global AMap */
import * as serve from '@/api/largeScreen'
import { useRouterStore } from '@/pinia/modules/router'
import { onMounted, onBeforeUnmount, ref, nextTick, computed } from 'vue'
import * as echarts from 'echarts'
import { useRouter } from 'vue-router'
import ECharts from 'vue-echarts'
import {
getAlarmPendingOption,
@@ -229,15 +243,26 @@
} from './ttes.js'
import { techChartSeriesColors } from '@/utils/techChartTheme'
const router = useRouter()
const routerStore = useRouterStore()
const ALL_ALARM_ROUTE_PATH = 'securityControl/alarmList'
const EQUIPMENT_OVERVIEW_ROUTE_PATH = 'masterStation/equipment'
const bottomRef = ref(null)
const tableHeight = ref(180)
let resizeObserver = null
const mapInstance = ref(null)
const markers = ref([])
const mapDisplayMode = ref('3D')
const mapModeOptions = [
{ label: '3D', value: '3D' },
{ label: '2D', value: '2D' }
]
let buildingsLayer = null
const default3DCenter = [120.153576, 30.287459]
const default3DZoom = 17.6
const default2DZoom = 12
const tableData = ref([])
@@ -256,6 +281,7 @@
]
const deviceTypes = ref([])
const displayDeviceTypes = computed(() => deviceTypes.value.slice(0, 5))
const deviceChangeList = ref([])
@@ -295,6 +321,27 @@
return type === 'device_online' ? 'status-online' : 'status-offline'
}
const pushDynamicRoute = (routePath) => {
const targetRoute = Object.values(routerStore.routeMap).find((route) => {
return route.path === routePath || route.path?.endsWith(`/${routePath}`)
})
if (targetRoute?.name) {
router.push({ name: targetRoute.name })
return
}
router.push({ path: `/layout/${routePath}` })
}
const goToAllAlarmPage = () => {
pushDynamicRoute(ALL_ALARM_ROUTE_PATH)
}
const goToEquipmentOverview = () => {
pushDynamicRoute(EQUIPMENT_OVERVIEW_ROUTE_PATH)
}
const setRem = () => {
const designWidth = 1920
const designHeight = 1080
@@ -397,7 +444,7 @@
console.log('devices', devices.value)
nextTick(() => {
if (mapInstance.value) {
mapInstance.value.setZoomAndCenter(default3DZoom, getValidDeviceCenter())
mapInstance.value.setZoomAndCenter(getCurrentMapZoom(), getValidDeviceCenter())
}
addMarkers()
})
@@ -416,8 +463,12 @@
return [Number(firstValidDevice.gatewayLong), Number(firstValidDevice.gatewayLat)]
}
const getCurrentMapZoom = () => {
return mapDisplayMode.value === '3D' ? default3DZoom : default2DZoom
}
const add3DBuildingLayer = () => {
if (!mapInstance.value || typeof AMap === 'undefined' || !AMap.Buildings) return
if (!mapInstance.value || typeof AMap === 'undefined' || !AMap.Buildings || buildingsLayer) return
buildingsLayer = new AMap.Buildings({
zooms: [3, 20],
@@ -428,6 +479,42 @@
mapInstance.value.add(buildingsLayer)
}
const remove3DBuildingLayer = () => {
if (!mapInstance.value || !buildingsLayer) return
mapInstance.value.remove(buildingsLayer)
buildingsLayer = null
}
const applyMapMode = () => {
if (!mapInstance.value) return
const is3D = mapDisplayMode.value === '3D'
const center = getValidDeviceCenter()
mapInstance.value.setStatus({
pitchEnable: is3D,
rotateEnable: is3D
})
mapInstance.value.setFeatures(is3D ? ['bg', 'road', 'building', 'point'] : ['bg', 'road', 'point'])
mapInstance.value.setZoomAndCenter(is3D ? default3DZoom : default2DZoom, center)
mapInstance.value.setPitch(is3D ? 68 : 0)
mapInstance.value.setRotation(is3D ? -28 : 0)
if (is3D) {
add3DBuildingLayer()
} else {
remove3DBuildingLayer()
}
}
const switchMapMode = (mode) => {
if (mapDisplayMode.value === mode) return
mapDisplayMode.value = mode
applyMapMode()
}
const initMap = () => {
if (typeof AMap === 'undefined') {
console.error('高德地图API未加载')
@@ -437,16 +524,16 @@
console.log('开始初始化地图')
mapInstance.value = new AMap.Map('chinaMap', {
zoom: default3DZoom,
zoom: getCurrentMapZoom(),
zooms: [3, 20],
center: getValidDeviceCenter(),
mapStyle: 'amap://styles/blue',
viewMode: '3D',
pitch: 68,
rotation: -28,
pitch: mapDisplayMode.value === '3D' ? 68 : 0,
rotation: mapDisplayMode.value === '3D' ? -28 : 0,
terrain: true,
pitchEnable: true,
rotateEnable: true,
pitchEnable: mapDisplayMode.value === '3D',
rotateEnable: mapDisplayMode.value === '3D',
dragEnable: true,
zoomEnable: true,
buildingAnimation: true,
@@ -456,13 +543,13 @@
skyColor: '#020713'
})
add3DBuildingLayer()
applyMapMode()
mapInstance.value.on('complete', () => {
console.log('地图加载完成')
if (devices.value && devices.value.length > 0) {
const center = getValidDeviceCenter()
mapInstance.value.setZoomAndCenter(default3DZoom, center)
mapInstance.value.setZoomAndCenter(getCurrentMapZoom(), center)
addMarkers()
}
})
@@ -489,7 +576,7 @@
// 先只渲染前20个点测试
const testData = devices.value.slice(0, 20)
testData.forEach((device, index) => {
testData.forEach((device) => {
// console.log(`渲染第 ${index} 个点:`, device)
const longitude = Number(device.gatewayLong)
@@ -601,6 +688,11 @@
flex: 1;
}
.device-link-card {
cursor: pointer;
outline: none;
}
.module-header {
display: flex;
justify-content: space-between;
@@ -934,6 +1026,11 @@
flex-direction: column;
}
.alarm-link-card {
cursor: pointer;
outline: none;
}
.module-header {
display: flex;
justify-content: space-between;
@@ -1296,6 +1393,75 @@
letter-spacing: 0.04rem;
}
.map-mode-switch {
position: absolute;
top: 0.24rem;
right: 0.22rem;
z-index: 1001;
display: flex;
gap: 0.06rem;
padding: 0.06rem;
border: 1px solid rgba(0, 212, 255, 0.38);
border-radius: 0.12rem;
background:
linear-gradient(135deg, rgba(8, 47, 73, 0.9), rgba(15, 23, 42, 0.76)),
repeating-linear-gradient(90deg, transparent 0 0.16rem, rgba(0, 212, 255, 0.05) 0.17rem 0.18rem);
box-shadow:
inset 0 0 0.18rem rgba(0, 212, 255, 0.12),
0 0 0.24rem rgba(0, 212, 255, 0.18),
0 0.1rem 0.24rem rgba(0, 0, 0, 0.28);
backdrop-filter: blur(8px);
}
.map-mode-button {
min-width: 0.6rem;
height: 0.32rem;
padding: 0 0.14rem;
border: 1px solid rgba(0, 212, 255, 0.42);
border-radius: 0.08rem;
color: #e9fbff;
font-family: DIN Alternate, Bahnschrift, Arial, sans-serif;
font-size: 0.16rem;
font-weight: 800;
line-height: 0.32rem;
letter-spacing: 0.03rem;
cursor: pointer;
background: rgba(2, 8, 23, 0.72);
text-shadow:
0 0 0.06rem rgba(0, 212, 255, 0.9),
0 1px 2px rgba(0, 0, 0, 0.9);
transition: all 0.25s ease;
-webkit-font-smoothing: antialiased;
}
.map-mode-button:hover,
.map-mode-button.active {
color: #ffffff;
border-color: rgba(245, 158, 11, 0.86);
background: linear-gradient(135deg, rgba(245, 158, 11, 0.52), rgba(0, 212, 255, 0.28));
box-shadow:
inset 0 0 0.12rem rgba(255, 255, 255, 0.12),
0 0 0.18rem rgba(0, 212, 255, 0.46);
}
.map-container-full.map-mode-2d::before {
top: 0.82rem;
bottom: 0.24rem;
height: auto;
border-radius: 0.16rem;
opacity: 0.5;
transform: none;
}
.map-container-full.map-mode-2d .map-radar-glow {
transform: translate(-50%, -50%);
animation-name: radarRotate;
}
.map-container-full.map-mode-2d .map-3d-stage {
display: none;
}
.map-radar-glow {
position: absolute;
left: 50%;

View File

@@ -101,7 +101,7 @@
import { ElMessage, ElMessageBox } from 'element-plus'
import { MoreFilled } from '@element-plus/icons-vue'
const props = defineProps({
defineProps({
modelValue: {
type: Object,
default: () => ({})
@@ -241,6 +241,7 @@
background: transparent;
}
.device-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(330px, 1fr));