Commit 8a90e89b authored by xinzhedeai's avatar xinzhedeai

add:cesium show

parent 18bfc848
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
<div id="cesiumContainer" class="cesium-background"></div> <div id="cesiumContainer" class="cesium-background"></div>
<!-- 顶部标题栏 --> <!-- 顶部标题栏 -->
<header class="top-title-bar"> <header class="top-title-bar" style="display: none">
<h1 class="system-title">数据监测分析系统</h1> <h1 class="system-title">数据监测分析系统</h1>
<div class="header-info"> <div class="header-info">
<div class="current-time">{{ currentTime }}</div> <div class="current-time">{{ currentTime }}</div>
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
</header> </header>
<!-- 菜单栏 --> <!-- 菜单栏 -->
<nav class="menu-bar"> <nav class="menu-bar" style="display: none">
<ul class="menu-list"> <ul class="menu-list">
<li class="menu-item active"> <li class="menu-item active">
<span class="menu-icon home-icon"></span> <span class="menu-icon home-icon"></span>
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
</nav> </nav>
<!-- 主内容区 --> <!-- 主内容区 -->
<main class="main-content"> <main class="main-content" style="display: none">
<!-- 左侧数据模块 --> <!-- 左侧数据模块 -->
<div class="left-modules"> <div class="left-modules">
<!-- 模块1:数据总览 --> <!-- 模块1:数据总览 -->
...@@ -239,7 +239,32 @@ export default { ...@@ -239,7 +239,32 @@ export default {
return { return {
currentTime: "", currentTime: "",
currentTimeShort: "", currentTimeShort: "",
// 版本号
version: "3.8.9",
// Cesium查看器实例
viewer: null, viewer: null,
tileset: null,
personnelList: [
{
longitude: 121.70710830038986,
latitude: 36.853636402927986,
height: 100,
name: "张三",
status: "online", // 在线
avatar: "/static/images/avatars/zhangsan.png", // 头像
},
{
longitude: 121.70810830038986,
latitude: 36.854636402927986,
height: 100,
name: "李四",
status: "offline", // 离线
avatar: "/static/images/avatars/lisi.png", // 头像
},
// 其他人员数据...
],
personModelInterval: null,
bgEntities: {}, // 所有的key都对应一个实体对象。而人员的实体对应的key不是数字。
}; };
}, },
mounted() { mounted() {
...@@ -285,60 +310,154 @@ export default { ...@@ -285,60 +310,154 @@ export default {
}); });
}, },
// 初始化Cesium地图 /**
initCesium() { * 初始化Cesium地图
*/
async initCesium() {
Cesium.Ion.defaultAccessToken =
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0ZDAxZGFhYy02MjJlLTRiNzktODNhZi00N2VjZGY0NTk4YmIiLCJpZCI6Mjc0NDAxLCJpYXQiOjE3NjMzNDYwNTR9.ZQW2DZ4KaMGbHuwrtIbyI6EdSSvgMJUHmmD74eZW7PQ";
try { try {
// 设置Cesium基础路径 // 创建Cesium Viewer实例
window.CESIUM_BASE_URL = "/cesium/";
// 创建Cesium视图
this.viewer = new Cesium.Viewer("cesiumContainer", { this.viewer = new Cesium.Viewer("cesiumContainer", {
// 设置地图提供者,这里使用默认的Bing Maps
imageryProvider: new Cesium.BingMapsImageryProvider({ imageryProvider: new Cesium.BingMapsImageryProvider({
url: "https://dev.virtualearth.net", url: "https://dev.virtualearth.net",
key: "AgcbDCAOb9zMfquaT4Z-MdHfx--9wUNrLRiiS7rIElFx8f-4lLulxZ0QnhqX5Lm6",
mapStyle: Cesium.BingMapsStyle.AERIAL, mapStyle: Cesium.BingMapsStyle.AERIAL,
key: "your-bing-maps-key", // 请替换为实际的Bing Maps密钥
}), }),
baseLayerPicker: false, // 配置是否显示各种控件
timeline: false, animation: false, // 动画控件
animation: false, baseLayerPicker: true, // 底图选择器
fullscreenButton: false, fullscreenButton: true, // 全屏按钮
geocoder: false, geocoder: true, // 地址搜索
homeButton: false, homeButton: true, // 主页按钮
infoBox: false, infoBox: true, // 信息框
sceneModePicker: false, sceneModePicker: true, // 场景模式选择器
navigationHelpButton: false, selectionIndicator: true, // 选择指示器
timeline: false, // 时间线
navigationHelpButton: false, // 导航帮助按钮
navigationInstructionsInitiallyVisible: false, navigationInstructionsInitiallyVisible: false,
// 设置初始视图位置(中国区域)
center: Cesium.Cartesian3.fromDegrees(104.06, 30.67, 10000000),
}); });
// 设置相机位置 // 设置相机视图
this.viewer.camera.setView({ // this.viewer.camera.setView({
destination: Cesium.Cartesian3.fromDegrees( // destination: Cesium.Cartesian3.fromDegrees(104.06, 30.67, 10000000), // 经度、纬度、高度
116.397428, // orientation: {
39.90923, // heading: Cesium.Math.toRadians(0.0), // 方向
10000.0 // pitch: Cesium.Math.toRadians(-90.0), // 倾斜角度
), // roll: 0.0, // 翻滚角度
// },
// });
this.viewer.scene.camera.setView({
// 视角-环翠
duration: 1,
destination: {
x: -2739843.563038797,
y: 4357442.794747324,
z: 3880768.3292693933,
},
orientation: { orientation: {
heading: Cesium.Math.toRadians(0.0), heading: 6.037000745578596,
pitch: Cesium.Math.toRadians(-90.0), pitch: -1.2499586064720978,
roll: 0.0, roll: 0.000005306352659495417,
}, },
}); });
// 禁用默认的点击事件 // 隐藏Cesium logo
this.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction( this.viewer._cesiumWidget._creditContainer.style.display = "none";
Cesium.ScreenSpaceEventType.LEFT_CLICK
); const VUE_APP_GIS =
"http://192.168.2.11:8080/Apps/assets/media/gaoquyingji";
try {
const tileset = await Cesium.Cesium3DTileset.fromUrl(
VUE_APP_GIS + "/tiles/01_guanwei/tileset.json"
);
this.viewer.scene.primitives.add(tileset);
console.log("倾斜摄影模型加载成功tileset", tileset);
if (tileset) {
this.tileset = tileset;
this.locateToTileset();
}
} catch (error) {
console.error(`加载倾斜摄影模型失败: ${error}`);
}
console.log("Cesium地图初始化成功");
} catch (error) { } catch (error) {
console.error("Cesium初始化失败:", error); console.error("Cesium地图初始化失败:", error);
// 设置备用背景
const container = document.getElementById("cesiumContainer");
container.style.backgroundColor = "#001a33";
container.style.backgroundImage =
"linear-gradient(45deg, #001a33 25%, #00264d 25%, #00264d 50%, #001a33 50%, #001a33 75%, #00264d 75%, #00264d 100%)";
container.style.backgroundSize = "10px 10px";
} }
}, },
/**
* 获取倾斜摄影模型的经纬度并将摄像机视角转向模型上方
*/
locateToTileset() {
if (!this.tileset || !this.viewer) {
console.error("模型或视图未准备就绪");
return;
}
try {
// 获取模型的边界球
const boundingSphere = this.tileset.boundingSphere;
if (!boundingSphere) {
console.error("无法获取模型边界");
return;
}
// 获取模型中心点的笛卡尔坐标
const center = boundingSphere.center;
// 将笛卡尔坐标转换为经纬度坐标
const cartographic = Cesium.Cartographic.fromCartesian(center);
const longitude = Cesium.Math.toDegrees(cartographic.longitude);
const latitude = Cesium.Math.toDegrees(cartographic.latitude);
const height = cartographic.height;
console.log("倾斜摄影模型中心点经纬度:", {
longitude: longitude,
latitude: latitude,
height: height,
});
// 计算合适的观察距离 - 基于模型半径的倍数
const distance = boundingSphere.radius * 2.5; // 可以根据需要调整倍数
// 设置相机位置在模型上方
const cameraPosition = Cesium.Cartesian3.fromRadians(
cartographic.longitude,
cartographic.latitude,
height + distance // 相机高度为模型最高点加上观察距离
);
// 计算相机看向模型中心的方向
const heading = Cesium.Math.toRadians(0); // 方向角
const pitch = Cesium.Math.toRadians(-90); // 俯仰角 - 负数表示向下看
const roll = Cesium.Math.toRadians(0); // 翻滚角
// 使用flyTo方法平滑过渡到目标位置
this.viewer.camera.flyTo({
destination: cameraPosition,
orientation: {
heading: heading,
pitch: pitch,
roll: roll,
},
duration: 2, // 过渡时间2秒
complete: () => {
console.log("相机已成功定位到模型上方");
this.createPersonModel(); // 定位后创建人员模型
},
});
} catch (error) {
console.error("定位到模型上方失败:", error);
}
},
// 绘制趋势图 // 绘制趋势图
drawTrendChart() { drawTrendChart() {
const container = document.getElementById("trendChart"); const container = document.getElementById("trendChart");
......
<template> <template>
<div class="app-container home"> <div class="screen-container">
<!-- Cesium地图容器 --> <!-- Cesium地图背景 -->
<div id="cesiumContainer" class="cesium-container"></div> <div id="cesiumContainer" class="cesium-background"></div>
<!-- 顶部标题栏 -->
<header class="top-title-bar" style="display: none1">
<h1 class="system-title">数据监测分析系统</h1>
<div class="header-info">
<div class="current-time">{{ currentTime }}</div>
<div class="system-status">
<span class="status-dot online"></span>
<span>系统正常运行中</span>
</div>
</div>
</header>
<!-- 菜单栏 -->
<!-- <nav class="menu-bar" style="display: none1">
<ul class="menu-list">
<li class="menu-item active">
<span class="menu-icon home-icon"></span>
<span>首页概览</span>
</li>
<li class="menu-item">
<span class="menu-icon monitor-icon"></span>
<span>实时监测</span>
</li>
<li class="menu-item">
<span class="menu-icon alarm-icon"></span>
<span>报警管理</span>
</li>
<li class="menu-item">
<span class="menu-icon analysis-icon"></span>
<span>数据分析</span>
</li>
<li class="menu-item">
<span class="menu-icon system-icon"></span>
<span>系统设置</span>
</li>
</ul>
</nav> -->
<!-- 主内容区 -->
<!-- <main class="main-content" style="display: none1"> -->
<!-- 左侧数据模块 -->
<div class="left-modules">
<!-- 模块1:数据总览 -->
<div class="data-module">
<div class="module-header">
<h3>数据总览</h3>
<span class="refresh-icon"></span>
</div>
<div class="module-body">
<div class="data-stats">
<div class="stat-item">
<span class="stat-label">监测点位</span>
<span class="stat-value">256</span>
</div>
<div class="stat-item">
<span class="stat-label">在线设备</span>
<span class="stat-value online">245</span>
</div>
<div class="stat-item">
<span class="stat-label">数据采集量</span>
<span class="stat-value">1.2万</span>
</div>
</div>
<div class="progress-bars">
<div class="progress-item">
<span class="progress-label">设备在线率</span>
<div class="progress-container">
<div class="progress-bar" style="width: 95%"></div>
</div>
<span class="progress-value">95.7%</span>
</div>
</div>
</div>
</div>
<!-- 模块2:实时报警 -->
<div class="data-module">
<div class="module-header">
<h3>实时报警</h3>
<span class="alarm-count">5</span>
</div>
<div class="module-body">
<div class="alarm-list">
<div class="alarm-item level-1">
<span class="alarm-level">紧急</span>
<span class="alarm-content">温度异常</span>
<span class="alarm-point">A-12区</span>
<span class="alarm-time">10:23</span>
</div>
<div class="alarm-item level-2">
<span class="alarm-level">重要</span>
<span class="alarm-content">设备离线</span>
<span class="alarm-point">B-05区</span>
<span class="alarm-time">09:45</span>
</div>
<div class="alarm-item level-3">
<span class="alarm-level">一般</span>
<span class="alarm-content">数据异常</span>
<span class="alarm-point">C-08区</span>
<span class="alarm-time">08:30</span>
</div>
<div class="alarm-item level-3">
<span class="alarm-level">一般</span>
<span class="alarm-content">压力偏低</span>
<span class="alarm-point">D-01区</span>
<span class="alarm-time">07:55</span>
</div>
</div>
</div>
</div>
<!-- 模块3:环境监测 -->
<div class="data-module">
<div class="module-header">
<h3>环境监测</h3>
<span class="time-range">今日</span>
</div>
<div class="module-body">
<div class="env-data-grid">
<div class="env-item">
<span class="env-icon temp"></span>
<span class="env-label">平均温度</span>
<span class="env-value">26.3°C</span>
</div>
<div class="env-item">
<span class="env-icon humidity"></span>
<span class="env-label">平均湿度</span>
<span class="env-value">65.8%</span>
</div>
<div class="env-item">
<span class="env-icon pressure"></span>
<span class="env-label">平均气压</span>
<span class="env-value">101.5kPa</span>
</div>
<div class="env-item">
<span class="env-icon wind"></span>
<span class="env-label">平均风速</span>
<span class="env-value">3.2m/s</span>
</div>
</div>
</div>
</div>
</div>
<!-- 右侧数据模块 -->
<div class="right-modules">
<!-- 模块4:趋势分析 -->
<div class="data-module">
<div class="module-header">
<h3>数据趋势分析</h3>
<span class="chart-type">24小时</span>
</div>
<div class="module-body">
<div class="chart-container" id="trendChart"></div>
</div>
</div>
<!-- 模块5:设备状态 -->
<div class="data-module">
<div class="module-header">
<h3>设备运行状态</h3>
<span class="view-more">查看全部</span>
</div>
<div class="module-body">
<div class="device-status-list">
<div class="device-item">
<span class="device-name">传感器A-1</span>
<span class="device-status normal">正常</span>
<span class="device-value">125.6</span>
<span class="device-time">3分钟前</span>
</div>
<div class="device-item">
<span class="device-name">传感器B-3</span>
<span class="device-status normal">正常</span>
<span class="device-value">89.2</span>
<span class="device-time">5分钟前</span>
</div>
<div class="device-item">
<span class="device-name">传感器C-2</span>
<span class="device-status warning">警告</span>
<span class="device-value">185.3</span>
<span class="device-time">1分钟前</span>
</div>
<div class="device-item">
<span class="device-name">传感器D-5</span>
<span class="device-status offline">离线</span>
<span class="device-value">--</span>
<span class="device-time">2小时前</span>
</div>
</div>
</div>
</div>
<!-- 模块6:系统负载 -->
<div class="data-module">
<div class="module-header">
<h3>系统资源监控</h3>
<span class="system-time">{{ currentTimeShort }}</span>
</div>
<div class="module-body">
<div class="system-resources">
<div class="resource-item">
<span class="resource-label">CPU使用率</span>
<div class="resource-bar-container">
<div class="resource-bar cpu-bar" style="width: 42%"></div>
</div>
<span class="resource-value">42%</span>
</div>
<div class="resource-item">
<span class="resource-label">内存使用率</span>
<div class="resource-bar-container">
<div class="resource-bar mem-bar" style="width: 68%"></div>
</div>
<span class="resource-value">68%</span>
</div>
<div class="resource-item">
<span class="resource-label">磁盘使用率</span>
<div class="resource-bar-container">
<div class="resource-bar disk-bar" style="width: 35%"></div>
</div>
<span class="resource-value">35%</span>
</div>
</div>
</div>
</div>
</div>
<!-- </main> -->
</div> </div>
</template> </template>
<script> <script>
import { getTokenApi } from "@/api/token";
import { localStg } from "@/utils/storage";
export default { export default {
name: "Index",
data() { data() {
return { return {
currentTime: "",
currentTimeShort: "",
// 版本号 // 版本号
version: "3.8.9", version: "3.8.9",
// Cesium查看器实例 // Cesium查看器实例
...@@ -38,116 +265,95 @@ export default { ...@@ -38,116 +265,95 @@ export default {
], ],
personModelInterval: null, personModelInterval: null,
bgEntities: {}, // 所有的key都对应一个实体对象。而人员的实体对应的key不是数字。 bgEntities: {}, // 所有的key都对应一个实体对象。而人员的实体对应的key不是数字。
// 轨迹追踪相关数据
selectedPerson: "", // 选中的人员
timePoints: [], // 时间点数组
currentTimeIndex: 0, // 当前时间索引
personTrajectories: {}, // 人员轨迹数据 { 人员名称: [{time, lng, lat, height}] }
trailEntities: {}, // 轨迹实体
isTracking: false, // 是否正在实时追踪
currentTimeDisplay: "", // 当前显示时间
}; };
}, },
mounted() { mounted() {
// 组件挂载后初始化地图 // 初始化时间
this.updateTime();
setInterval(() => this.updateTime(), 1000);
// 初始化Cesium地图
this.initCesium(); this.initCesium();
}, // 初始化时间点数据
beforeMount() { this.initTimePoints();
localStg.set("token", 222233);
if (localStg.get("token")) { // 初始化图表
return; this.$nextTick(() => {
} this.drawTrendChart();
// 组件挂载前获取token
getTokenApi().then((res) => {
console.log("token", res);
localStg.set("token", res.data.data);
}); });
// 监听窗口大小变化
window.addEventListener("resize", this.handleResize);
}, },
beforeDestroy() { beforeDestroy() {
window.removeEventListener("resize", this.handleResize);
if (this.viewer) {
this.viewer.destroy();
}
// 组件销毁前清理地图资源 // 组件销毁前清理地图资源
if (this.viewer) { if (this.viewer) {
this.viewer.destroy(); this.viewer.destroy();
this.viewer = null; this.viewer = null;
} }
if (this.personModelInterval) {
clearInterval(this.personModelInterval);
}
if (this.trackingInterval) {
clearInterval(this.trackingInterval);
}
}, },
methods: { methods: {
createPersonModel() { // 更新时间
// 批次号管理(每次定时器触发时生成一个新的批次号) updateTime() {
// var currentBatch = 0; const now = new Date();
// const batchMap = {}; // 完整时间格式
this.currentTime = now.toLocaleString("zh-CN", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
});
// 短时间格式
this.currentTimeShort = now.toLocaleTimeString("zh-CN", {
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
});
},
if (!this.personModelInterval) { // 初始化时间点数据(生成过去1小时的时间点,每5分钟一个)
this.personModelInterval = setInterval(() => { initTimePoints() {
console.log("开始获取实时数据"); const now = new Date();
// currentBatch++; // 每次定时器触发,生成新的批次号 const points = [];
if (this.bgEntities) {
for (let key in this.bgEntities) {
if (isNaN(parseFloat(key))) {
// 非数字键名的是人员实体
this.viewer.entities.remove(this.bgEntities[key]);
delete this.bgEntities[key];
}
}
}
// 从API获取最新的人员定位数据 // 生成过去1小时的时间点,每5分钟一个
this.personCardList((list) => { for (let i = 60; i >= 0; i -= 5) {
// let perList = list; // 使用全部人员数据 const time = new Date(now.getTime() - i * 60 * 1000);
console.log("人员数据", this.personnelList); points.push(time);
// 创建新实体
for (let item of this.personnelList) {
let lng = Number(item.lng);
let lat = Number(item.lat);
let height = Number(item.height);
let position = Cesium.Cartesian3.fromDegrees(lng, lat, height);
console.log(item.perName, position);
// 创建人员标记
let entity = this.viewer.entities.add({
position: position,
label: {
text: item.perName,
font: "16px",
backgroundColor: Cesium.Color.fromCssColorString("#173349"),
showBackground: true,
fillColor: Cesium.Color.YELLOW,
depthTestAgainstTerrain: false, // 禁用地形深度测试
// text: "高区管委",
// font: "16px",
// // scale: 0.5,
// backgroundColor: Cesium.Color.fromCssColorString("#173349"),
// color: Cesium.Color.WHITE,
// showBackground: true,
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0,
// 8000.0
// ),
pixelOffset: new Cesium.Cartesian2(0, -35),
// fillColor: Cesium.Color.WHITE,
// backgroundColor: new Cesium.Color(0.0, 0.486, 0.65, 0.8),
// disableDepthTestDistance: 5,
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
},
billboard: {
image: "/poi-marker-default.png",
scale: 0.5,
// heightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
// disableDepthTestDistance: 5,
// distanceDisplayCondition: new Cesium.DistanceDisplayCondition(
// 1.0,
// 8000.0
// ),
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
},
description: `<div><h4>${item.perName}${item.status}</h4></div>`,
fixedFrame: Cesium.Transforms.eastNorthUpToFixedFrame(position),
});
entity.info = item; // 添加 info 属性
// entity.batch = currentBatch; // 标记当前批次
this.bgEntities[item.perName] = entity; // 存储新实体
}
});
}, 10000); // 每10秒刷新一次
} }
this.timePoints = points;
this.currentTimeIndex = points.length - 1; // 默认显示最新时间
this.currentTimeDisplay = this.formatTime(points[points.length - 1]);
// 初始化人员轨迹数据
this.initPersonTrajectories();
}, },
personCardList(fn) {
console.log("人员定位数据", this.personnelList); // 初始化人员轨迹数据
// 将笛卡尔坐标转换为经纬度坐标 initPersonTrajectories() {
// 将笛卡尔坐标转换为经纬度坐标作为基准点
const cartographic = Cesium.Cartographic.fromCartesian({ const cartographic = Cesium.Cartographic.fromCartesian({
x: -2686273.730145489, x: -2686273.730145489,
y: 4293961.185794622, y: 4293961.185794622,
...@@ -157,52 +363,234 @@ export default { ...@@ -157,52 +363,234 @@ export default {
const baseLatitude = Cesium.Math.toDegrees(cartographic.latitude); const baseLatitude = Cesium.Math.toDegrees(cartographic.latitude);
const baseHeight = cartographic.height + 1; const baseHeight = cartographic.height + 1;
console.log("人员经纬度基准点:", { // 为每个人生成轨迹数据
longitude: baseLongitude, this.personnelList.forEach((person) => {
latitude: baseLatitude, const trajectories = [];
height: baseHeight, let currentLng = baseLongitude + (Math.random() - 0.5) * 0.0001;
let currentLat = baseLatitude + (Math.random() - 0.5) * 0.0001;
this.timePoints.forEach((time) => {
// 生成平滑的移动路径
currentLng += (Math.random() - 0.5) * 0.00002;
currentLat += (Math.random() - 0.5) * 0.00002;
trajectories.push({
time,
lng: currentLng,
lat: currentLat,
height: baseHeight,
});
});
this.personTrajectories[person.perName] = trajectories;
}); });
},
// 清除现有的人员列表 // 格式化时间显示
this.personnelList = []; formatTime(date = new Date()) {
const hours = date.getHours().toString().padStart(2, "0");
const minutes = date.getMinutes().toString().padStart(2, "0");
return `${hours}:${minutes}`;
},
// 生成10个不同的经纬度坐标,确保它们之间的距离不超过100米 // 人员选择变化处理
// 在经纬度上,约0.00001度的变化大约对应1米(赤道附近) onPersonSelect() {
// 为了确保不超过100米,我们使用±0.00005度的随机偏移 this.clearTrails();
const maxOffset = 0.00005; if (this.selectedPerson) {
this.updatePersonPositionByTimeIndex(this.currentTimeIndex);
this.showFullPath();
}
},
for (let index = 0; index < 10; index++) { // 时间轴变化处理
// 生成随机偏移量,确保每个点都不同但距离不远 onTimelineChange() {
const lngOffset = (Math.random() - 0.5) * 2 * maxOffset; this.currentTimeDisplay = this.formatTime(
const latOffset = (Math.random() - 0.5) * 2 * maxOffset; this.timePoints[this.currentTimeIndex]
);
this.updatePersonPositionByTimeIndex(this.currentTimeIndex);
},
this.personnelList.push({ // 根据时间索引更新人员位置
lng: baseLongitude + lngOffset, updatePersonPositionByTimeIndex(index) {
lat: baseLatitude + latOffset, if (
height: baseHeight, // 高度略有不同,便于区分 !this.selectedPerson ||
perName: "张三" + index, !this.personTrajectories[this.selectedPerson]
status: "online", // 在线 ) {
avatar: "/static/images/avatars/zhangsan.png", // 头像 return;
}
const trajectory = this.personTrajectories[this.selectedPerson][index];
if (!trajectory) return;
// 更新人员实体位置
const personEntity = this.bgEntities[this.selectedPerson];
if (personEntity) {
const position = Cesium.Cartesian3.fromDegrees(
trajectory.lng,
trajectory.lat,
trajectory.height
);
personEntity.position.setValue(position);
// 更新描述信息,包含时间
personEntity.description = `<div><h4>${
this.selectedPerson
}</h4><p>时间: ${this.formatTime(trajectory.time)}</p></div>`;
}
// 移动相机到人员位置
if (this.isTracking) {
this.viewer.camera.flyTo({
destination: Cesium.Cartesian3.fromDegrees(
trajectory.lng,
trajectory.lat,
trajectory.height + 100
),
duration: 0.5,
}); });
} }
},
fn(this.personnelList); // 开始实时追踪
startTracking() {
if (!this.selectedPerson) {
alert("请先选择要追踪的人员");
return;
}
this.isTracking = true;
this.currentTimeIndex = this.timePoints.length - 1;
// 设置定时器模拟时间流逝
this.trackingInterval = setInterval(() => {
// 模拟新时间点的到来
const now = new Date();
this.timePoints.push(now);
// 为每个人员生成新的位置数据
this.personnelList.forEach((person) => {
if (!this.personTrajectories[person.perName]) {
this.personTrajectories[person.perName] = [];
}
const lastPos =
this.personTrajectories[person.perName][
this.personTrajectories[person.perName].length - 1
];
let newLng = lastPos.lng + (Math.random() - 0.5) * 0.00002;
let newLat = lastPos.lat + (Math.random() - 0.5) * 0.00002;
this.personTrajectories[person.perName].push({
time: now,
lng: newLng,
lat: newLat,
height: lastPos.height,
});
});
// 更新到最新时间
this.currentTimeIndex = this.timePoints.length - 1;
this.currentTimeDisplay = this.formatTime(now);
this.updatePersonPositionByTimeIndex(this.currentTimeIndex);
// 如果选择了当前人员,显示最新轨迹
if (this.selectedPerson) {
this.updateTrailDisplay();
}
}, 5000); // 每5秒更新一次
}, },
showPersonInfo(description) {
// 使用 Cesium 的 InfoBox 显示信息 // 停止实时追踪
this.viewer.selectedEntity = this.viewer.entities.add({ stopTracking() {
description: description, this.isTracking = false;
if (this.trackingInterval) {
clearInterval(this.trackingInterval);
this.trackingInterval = null;
}
},
// 显示完整轨迹
showFullPath() {
if (
!this.selectedPerson ||
!this.personTrajectories[this.selectedPerson]
) {
return;
}
this.clearTrails();
this.updateTrailDisplay();
},
// 更新轨迹显示
updateTrailDisplay() {
const trajectories = this.personTrajectories[this.selectedPerson];
if (!trajectories || trajectories.length < 2) return;
// 创建轨迹点数组
const positions = [];
trajectories.forEach((point) => {
positions.push(
Cesium.Cartesian3.fromDegrees(point.lng, point.lat, point.height)
);
});
// 创建轨迹线
const trailEntity = this.viewer.entities.add({
polyline: {
positions: positions,
width: 3,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.5,
color: Cesium.Color.YELLOW,
}),
clampToGround: false,
},
});
this.trailEntities[this.selectedPerson] = trailEntity;
// 添加轨迹点标记
trajectories.forEach((point, index) => {
// 只显示部分点,避免过多标记影响性能
if (
index % Math.ceil(trajectories.length / 10) === 0 ||
index === trajectories.length - 1
) {
const pointEntity = this.viewer.entities.add({
position: Cesium.Cartesian3.fromDegrees(
point.lng,
point.lat,
point.height + 5
),
point: {
pixelSize: 5,
color:
index === trajectories.length - 1
? Cesium.Color.RED
: Cesium.Color.GREEN,
outlineColor: Cesium.Color.WHITE,
outlineWidth: 2,
},
description: `<div><p>时间: ${this.formatTime(
point.time
)}</p></div>`,
});
if (!this.trailEntities[`${this.selectedPerson}_point_${index}`]) {
this.trailEntities[`${this.selectedPerson}_point_${index}`] =
pointEntity;
}
}
}); });
this.viewer.infoBox.frame.sandbox =
"allow-same-origin allow-top-navigation allow-pointer-lock allow-popups allow-forms allow-scripts";
this.viewer.infoBox.frame.src = "about:blank";
this.viewer.infoBox.frame.contentDocument.write(description);
this.viewer.infoBox.frame.contentDocument.close();
this.viewer.infoBox.viewModel.showInfo = true;
this.viewer.scene.globe.depthTestAgainstTerrain = true;
}, },
goTarget(href) {
window.open(href, "_blank"); // 清除轨迹
clearTrails() {
for (let key in this.trailEntities) {
this.viewer.entities.remove(this.trailEntities[key]);
}
this.trailEntities = {};
}, },
/** /**
...@@ -353,87 +741,886 @@ export default { ...@@ -353,87 +741,886 @@ export default {
console.error("定位到模型上方失败:", error); console.error("定位到模型上方失败:", error);
} }
}, },
createPersonModel() {
if (!this.personModelInterval) {
this.personModelInterval = setInterval(() => {
console.log("开始获取实时数据");
if (this.bgEntities) {
for (let key in this.bgEntities) {
if (isNaN(parseFloat(key))) {
// 非数字键名的是人员实体
this.viewer.entities.remove(this.bgEntities[key]);
delete this.bgEntities[key];
}
}
}
// 从API获取最新的人员定位数据
this.personCardList((list) => {
console.log("人员数据", this.personnelList);
// 创建新实体
for (let item of this.personnelList) {
let lng = Number(item.lng);
let lat = Number(item.lat);
let height = Number(item.height);
let position = Cesium.Cartesian3.fromDegrees(lng, lat, height);
console.log(item.perName, position);
// 创建人员标记
let entity = this.viewer.entities.add({
position: position,
label: {
text: item.perName,
font: "16px",
backgroundColor: Cesium.Color.fromCssColorString("#173349"),
showBackground: true,
fillColor: Cesium.Color.YELLOW,
depthTestAgainstTerrain: false, // 禁用地形深度测试
pixelOffset: new Cesium.Cartesian2(0, -35),
},
billboard: {
image: "/poi-marker-default.png",
scale: 0.5,
},
description: `<div><h4>${item.perName}${item.status}</h4></div>`,
fixedFrame: Cesium.Transforms.eastNorthUpToFixedFrame(position),
});
entity.info = item; // 添加 info 属性
this.bgEntities[item.perName] = entity; // 存储新实体
}
// 如果已经选择了人员,更新其位置和轨迹
if (this.selectedPerson) {
this.updatePersonPositionByTimeIndex(this.currentTimeIndex);
}
});
}, 10000); // 每10秒刷新一次
}
},
personCardList(fn) {
// 将笛卡尔坐标转换为经纬度坐标
const cartographic = Cesium.Cartographic.fromCartesian({
x: -2686273.730145489,
y: 4293961.185794622,
z: 3863430.5618300107,
});
const baseLongitude = Cesium.Math.toDegrees(cartographic.longitude);
const baseLatitude = Cesium.Math.toDegrees(cartographic.latitude);
const baseHeight = cartographic.height + 1;
console.log("人员经纬度基准点:", {
longitude: baseLongitude,
latitude: baseLatitude,
height: baseHeight,
});
// 清除现有的人员列表
this.personnelList = [];
// 生成10个不同的经纬度坐标
const maxOffset = 0.00005;
for (let index = 0; index < 10; index++) {
// 生成随机偏移量
const lngOffset = (Math.random() - 0.5) * 2 * maxOffset;
const latOffset = (Math.random() - 0.5) * 2 * maxOffset;
this.personnelList.push({
lng: baseLongitude + lngOffset,
lat: baseLatitude + latOffset,
height: baseHeight,
perName: "张三" + index,
status: "online", // 在线
avatar: "/static/images/avatars/zhangsan.png", // 头像
});
}
// 初始化轨迹数据(如果尚未初始化)
if (Object.keys(this.personTrajectories).length === 0) {
this.initPersonTrajectories();
}
fn(this.personnelList);
},
showPersonInfo(description) {
// 使用 Cesium 的 InfoBox 显示信息
this.viewer.selectedEntity = this.viewer.entities.add({
description: description,
});
this.viewer.infoBox.frame.sandbox =
"allow-same-origin allow-top-navigation allow-pointer-lock allow-popups allow-forms allow-scripts";
this.viewer.infoBox.frame.src = "about:blank";
this.viewer.infoBox.frame.contentDocument.write(description);
this.viewer.infoBox.frame.contentDocument.close();
this.viewer.infoBox.viewModel.showInfo = true;
this.viewer.scene.globe.depthTestAgainstTerrain = true;
},
// 绘制趋势图
drawTrendChart() {
const container = document.getElementById("trendChart");
if (!container) return;
const canvas = document.createElement("canvas");
canvas.width = container.clientWidth;
canvas.height = container.clientHeight;
container.appendChild(canvas);
const ctx = canvas.getContext("2d");
// 模拟数据
const data = [
12, 19, 15, 25, 32, 28, 22, 35, 29, 21, 18, 24, 27, 31, 26, 29, 33, 38,
35, 30, 28, 25, 22, 27,
];
const labels = Array.from({ length: 24 }, (_, i) => `${i}h`);
// 设置画布大小和边距
const padding = { top: 20, right: 20, bottom: 30, left: 40 };
const width = canvas.width - padding.left - padding.right;
const height = canvas.height - padding.top - padding.bottom;
// 计算数据范围
const maxValue = Math.max(...data);
const minValue = Math.min(...data);
const valueRange = maxValue - minValue || 1;
// 绘制背景
ctx.fillStyle = "rgba(0, 20, 40, 0.5)";
ctx.fillRect(padding.left, padding.top, width, height);
// 绘制网格线
ctx.strokeStyle = "rgba(100, 150, 200, 0.3)";
ctx.lineWidth = 1;
// 垂直网格线
for (let i = 0; i <= 24; i++) {
const x = padding.left + (width / 24) * i;
ctx.beginPath();
ctx.moveTo(x, padding.top);
ctx.lineTo(x, padding.top + height);
ctx.stroke();
}
// 水平网格线
for (let i = 0; i <= 5; i++) {
const y = padding.top + (height / 5) * i;
ctx.beginPath();
ctx.moveTo(padding.left, y);
ctx.lineTo(padding.left + width, y);
ctx.stroke();
}
// 绘制趋势线
ctx.strokeStyle = "#00ffcc";
ctx.lineWidth = 2;
ctx.beginPath();
data.forEach((value, index) => {
const x = padding.left + (width / 23) * index;
const y =
padding.top + height - ((value - minValue) / valueRange) * height;
if (index === 0) {
ctx.moveTo(x, y);
} else {
ctx.lineTo(x, y);
}
});
ctx.stroke();
// 绘制数据点
ctx.fillStyle = "#00ffcc";
data.forEach((value, index) => {
const x = padding.left + (width / 23) * index;
const y =
padding.top + height - ((value - minValue) / valueRange) * height;
ctx.beginPath();
ctx.arc(x, y, 3, 0, Math.PI * 2);
ctx.fill();
});
// 绘制时间标签
ctx.fillStyle = "#ffffff";
ctx.font = "10px Arial";
ctx.textAlign = "center";
for (let i = 0; i < labels.length; i += 3) {
const x = padding.left + (width / 23) * i;
const y = padding.top + height + 15;
ctx.fillText(labels[i], x, y);
}
},
// 处理窗口大小变化
handleResize() {
// 重新调整Cesium视图大小
if (this.viewer) {
this.viewer.resize();
}
// 重新绘制图表
const chartContainer = document.getElementById("trendChart");
if (chartContainer && chartContainer.firstChild) {
chartContainer.removeChild(chartContainer.firstChild);
this.drawTrendChart();
}
},
}, },
}; };
</script> </script>
<style scoped lang="scss"> <style lang="scss" scope>
.home { // 基础样式 - 1rem = 100px
width: 100%; html {
font-size: 100px;
}
// 屏幕容器
.screen-container {
position: relative;
width: 100vw;
height: 100vh; height: 100vh;
background-color: #000;
color: #fff;
font-family: "Microsoft YaHei", Arial, sans-serif;
overflow: hidden;
}
// Cesium地图背景
.cesium-background {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1;
}
// 顶部标题栏
.top-title-bar {
position: relative; position: relative;
height: 0.6rem;
background: linear-gradient(to right, #003366, #0066cc);
border-bottom: 2px solid #00aaff;
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 0.4rem;
z-index: 100;
box-shadow: 0 2px 10px rgba(0, 170, 255, 0.3);
.system-title {
font-size: 0.22rem;
font-weight: bold;
color: #ffffff;
text-shadow: 0 0 10px rgba(0, 170, 255, 0.5);
margin: 0;
}
.header-info {
display: flex;
align-items: center;
gap: 0.3rem;
}
.current-time {
font-size: 0.14rem;
color: #00ffcc;
font-weight: 500;
}
.system-status {
display: flex;
align-items: center;
gap: 0.08rem;
font-size: 0.14rem;
}
.status-dot {
width: 0.08rem;
height: 0.08rem;
border-radius: 50%;
&.online {
background-color: #00ff00;
box-shadow: 0 0 0.05rem #00ff00;
}
&.offline {
background-color: #ff3333;
box-shadow: 0 0 0.05rem #ff3333;
}
}
}
// 菜单栏
.menu-bar {
position: relative;
height: 0.4rem;
background: rgba(0, 30, 60, 0.9);
border-bottom: 1px solid #005080;
z-index: 99;
.menu-list {
display: flex;
align-items: center;
height: 100%;
margin: 0;
padding: 0 0.2rem;
list-style: none;
}
.menu-item {
display: flex;
align-items: center;
gap: 0.08rem;
padding: 0 0.2rem;
height: 0.3rem;
margin-right: 0.2rem;
border-radius: 0.04rem;
cursor: pointer;
transition: all 0.3s ease;
font-size: 0.14rem;
&:hover {
background: rgba(0, 170, 255, 0.2);
}
&.active {
background: linear-gradient(to right, #005080, #0078b0);
box-shadow: 0 0 0.1rem rgba(0, 170, 255, 0.5);
}
}
.menu-icon {
width: 0.16rem;
height: 0.16rem;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.home-icon {
background-image: url("/static/images/home-icon.png");
}
.monitor-icon {
background-image: url("/static/images/monitor-icon.png");
}
.alarm-icon {
background-image: url("/static/images/alarm-icon.png");
}
.analysis-icon {
background-image: url("/static/images/analysis-icon.png");
}
.system-icon {
background-image: url("/static/images/system-icon.png");
}
}
// 主内容区
.main-content {
position: relative;
display: flex;
justify-content: space-between;
padding: 0.2rem;
height: calc(100vh - 1rem);
z-index: 2;
}
// 左右模块容器
.left-modules,
.right-modules {
width: 3.6rem;
display: flex;
flex-direction: column;
gap: 0.2rem;
position: absolute;
z-index: 5;
top: 1rem;
}
.left-modules {
left: 0;
}
.right-modules {
right: 0;
}
// 数据模块通用样式
.data-module {
background: rgba(0, 20, 40, 0.85);
border: 1px solid #005080;
border-radius: 0.04rem;
overflow: hidden; overflow: hidden;
display: flex;
flex-direction: column;
backdrop-filter: blur(0.05rem);
box-shadow: 0 0 0.15rem rgba(0, 100, 200, 0.3);
blockquote { &:nth-child(1) {
padding: 10px 20px; height: 2.2rem;
margin: 0 0 20px;
font-size: 17.5px;
border-left: 5px solid #eee;
} }
hr {
margin-top: 20px; &:nth-child(2) {
margin-bottom: 20px; height: 2.5rem;
border: 0;
border-top: 1px solid #eee;
} }
.col-item {
margin-bottom: 20px; &:nth-child(3) {
height: 2rem;
} }
}
ul { // 模块头部
padding: 0; .module-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0.12rem 0.16rem;
background: linear-gradient(to right, #003060, #005090);
border-bottom: 1px solid #0070b0;
h3 {
margin: 0; margin: 0;
font-size: 0.16rem;
font-weight: 500;
color: #00ffcc;
} }
font-family: "open sans", "Helvetica Neue", Helvetica, Arial, sans-serif; .refresh-icon,
font-size: 13px; .view-more {
color: #676a6c; font-size: 0.12rem;
overflow-x: hidden; color: #99ccff;
cursor: pointer;
}
ul { .alarm-count {
list-style-type: none; background-color: #ff3333;
color: #fff;
padding: 0.02rem 0.08rem;
border-radius: 0.1rem;
font-size: 0.12rem;
font-weight: bold;
} }
h4 { .time-range,
margin-top: 0px; .chart-type,
.system-time {
font-size: 0.12rem;
color: #66ccff;
} }
}
h2 { // 模块内容区
margin-top: 10px; .module-body {
font-size: 26px; flex: 1;
font-weight: 100; padding: 0.16rem;
overflow: hidden;
}
// 数据总览样式
.data-stats {
display: flex;
justify-content: space-between;
margin-bottom: 0.16rem;
}
.stat-item {
display: flex;
flex-direction: column;
align-items: center;
min-width: 0.8rem;
}
.stat-label {
font-size: 0.12rem;
color: #99ccff;
margin-bottom: 0.05rem;
}
.stat-value {
font-size: 0.2rem;
font-weight: bold;
color: #ffffff;
&.online {
color: #00ff00;
} }
}
p { .progress-bars {
margin-top: 10px; margin-top: 0.1rem;
}
b { .progress-item {
font-weight: 700; display: flex;
} align-items: center;
gap: 0.1rem;
margin-bottom: 0.08rem;
}
.progress-label {
font-size: 0.12rem;
color: #ffffff;
width: 0.8rem;
}
.progress-container {
flex: 1;
height: 0.06rem;
background: rgba(0, 40, 80, 0.6);
border: 1px solid #005080;
border-radius: 0.03rem;
overflow: hidden;
}
.progress-bar {
height: 100%;
background: linear-gradient(to right, #00aaff, #00ffcc);
box-shadow: 0 0 0.05rem rgba(0, 255, 204, 0.7);
}
.progress-value {
font-size: 0.12rem;
color: #00ffcc;
font-weight: bold;
width: 0.4rem;
text-align: right;
}
// 报警列表样式
.alarm-list {
height: 100%;
overflow-y: auto;
&::-webkit-scrollbar {
width: 0.04rem;
} }
.update-log { &::-webkit-scrollbar-track {
ol { background: rgba(0, 40, 80, 0.5);
display: block; }
list-style-type: decimal;
margin-block-start: 1em; &::-webkit-scrollbar-thumb {
margin-block-end: 1em; background: #0070b0;
margin-inline-start: 0; border-radius: 0.02rem;
margin-inline-end: 0; }
padding-inline-start: 40px; }
}
.alarm-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.1rem;
margin-bottom: 0.08rem;
border-radius: 0.04rem;
border-left: 3px solid;
background: rgba(0, 30, 60, 0.7);
font-size: 0.12rem;
&.level-1 {
border-color: #ff3333;
background: rgba(255, 51, 51, 0.1);
} }
// Cesium容器样式 &.level-2 {
.cesium-container { border-color: #ff9900;
// width: 100vw; background: rgba(255, 153, 0, 0.1);
// height: 100vh;
width: 87vw;
height: 87vh;
position: absolute;
top: 0;
left: 0;
z-index: 1;
} }
&.level-3 {
border-color: #ffff00;
background: rgba(255, 255, 0, 0.1);
}
}
.alarm-level {
font-weight: bold;
width: 0.35rem;
.alarm-item.level-1 & {
color: #ff3333;
}
.alarm-item.level-2 & {
color: #ff9900;
}
.alarm-item.level-3 & {
color: #ffff00;
}
}
.alarm-content {
flex: 1;
color: #ffffff;
}
.alarm-point {
color: #99ccff;
width: 0.5rem;
}
.alarm-time {
color: #66ccff;
font-size: 0.11rem;
}
// 环境数据样式
.env-data-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 0.15rem;
height: 100%;
}
.env-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background: rgba(0, 30, 60, 0.7);
border-radius: 0.04rem;
border: 1px solid #005080;
padding: 0.1rem;
}
.env-icon {
width: 0.3rem;
height: 0.3rem;
margin-bottom: 0.08rem;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.env-icon.temp {
background-image: url("/static/images/temp-icon.png");
}
.env-icon.humidity {
background-image: url("/static/images/humidity-icon.png");
}
.env-icon.pressure {
background-image: url("/static/images/pressure-icon.png");
}
.env-icon.wind {
background-image: url("/static/images/wind-icon.png");
}
.env-label {
font-size: 0.12rem;
color: #99ccff;
margin-bottom: 0.05rem;
}
.env-value {
font-size: 0.16rem;
font-weight: bold;
color: #00ffcc;
}
// 图表容器
.chart-container {
width: 100%;
height: 100%;
min-height: 1.5rem;
}
// 设备状态列表
.device-status-list {
height: 100%;
overflow-y: auto;
&::-webkit-scrollbar {
width: 0.04rem;
}
&::-webkit-scrollbar-track {
background: rgba(0, 40, 80, 0.5);
}
&::-webkit-scrollbar-thumb {
background: #0070b0;
border-radius: 0.02rem;
}
}
.device-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0.1rem 0;
border-bottom: 1px solid rgba(0, 100, 200, 0.2);
font-size: 0.12rem;
&:last-child {
border-bottom: none;
}
}
.device-name {
color: #ffffff;
width: 0.8rem;
}
.device-status {
padding: 0.02rem 0.08rem;
border-radius: 0.03rem;
font-size: 0.11rem;
font-weight: bold;
&.normal {
background: rgba(0, 255, 0, 0.2);
color: #00ff00;
}
&.warning {
background: rgba(255, 153, 0, 0.2);
color: #ff9900;
}
&.offline {
background: rgba(255, 51, 51, 0.2);
color: #ff3333;
}
}
.device-value {
color: #00ffcc;
font-weight: bold;
width: 0.6rem;
text-align: right;
}
.device-time {
color: #66ccff;
font-size: 0.11rem;
}
// 系统资源监控
.system-resources {
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-around;
}
.resource-item {
display: flex;
align-items: center;
gap: 0.1rem;
}
.resource-label {
font-size: 0.12rem;
color: #ffffff;
width: 0.9rem;
}
.resource-bar-container {
flex: 1;
height: 0.08rem;
background: rgba(0, 40, 80, 0.6);
border: 1px solid #005080;
border-radius: 0.04rem;
overflow: hidden;
}
.resource-bar {
height: 100%;
box-shadow: 0 0 0.05rem;
&.cpu-bar {
background: linear-gradient(to right, #00aaff, #00ffcc);
box-shadow: 0 0 0.05rem rgba(0, 255, 204, 0.7);
}
&.mem-bar {
background: linear-gradient(to right, #ff9900, #ffcc00);
box-shadow: 0 0 0.05rem rgba(255, 204, 0, 0.7);
}
&.disk-bar {
background: linear-gradient(to right, #00cc66, #00ff99);
box-shadow: 0 0 0.05rem rgba(0, 255, 153, 0.7);
}
}
.resource-value {
font-size: 0.12rem;
font-weight: bold;
width: 0.4rem;
text-align: right;
&.low {
color: #00ff00;
}
&.medium {
color: #ffcc00;
}
&.high {
color: #ff3333;
}
}
// 响应式设计 - 基于1920*1080分辨率的适配
@media (max-width: 1600px) {
html {
font-size: 83.3px; // 1600/1920 * 100
}
}
@media (max-width: 1440px) {
html {
font-size: 75px; // 1440/1920 * 100
}
.left-modules,
.right-modules {
width: 3rem;
}
}
@media (max-width: 1280px) {
html {
font-size: 66.7px; // 1280/1920 * 100
}
.left-modules,
.right-modules {
width: 2.6rem;
}
}
// 修复滚动条样式
*::-webkit-scrollbar {
width: 0.04rem;
height: 0.04rem;
}
*::-webkit-scrollbar-track {
background: rgba(0, 40, 80, 0.3);
border-radius: 0.02rem;
}
*::-webkit-scrollbar-thumb {
background: #0070b0;
border-radius: 0.02rem;
}
*::-webkit-scrollbar-thumb:hover {
background: #0090d0;
} }
</style> </style>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment