Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
J
JINRUN-DP
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
xinzhedeai
JINRUN-DP
Commits
8a90e89b
Commit
8a90e89b
authored
Nov 18, 2025
by
xinzhedeai
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add:cesium show
parent
18bfc848
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
1532 additions
and
226 deletions
+1532
-226
index-dp.vue
src/views/index-dp.vue
+159
-40
index.vue
src/views/index.vue
+1373
-186
No files found.
src/views/index-dp.vue
View file @
8a90e89b
...
...
@@ -4,7 +4,7 @@
<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>
<div
class=
"header-info"
>
<div
class=
"current-time"
>
{{
currentTime
}}
</div>
...
...
@@ -16,7 +16,7 @@
</header>
<!-- 菜单栏 -->
<nav
class=
"menu-bar"
>
<nav
class=
"menu-bar"
style=
"display: none"
>
<ul
class=
"menu-list"
>
<li
class=
"menu-item active"
>
<span
class=
"menu-icon home-icon"
></span>
...
...
@@ -42,7 +42,7 @@
</nav>
<!-- 主内容区 -->
<main
class=
"main-content"
>
<main
class=
"main-content"
style=
"display: none"
>
<!-- 左侧数据模块 -->
<div
class=
"left-modules"
>
<!-- 模块1:数据总览 -->
...
...
@@ -239,7 +239,32 @@ export default {
return
{
currentTime
:
""
,
currentTimeShort
:
""
,
// 版本号
version
:
"
3.8.9
"
,
// Cesium查看器实例
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
()
{
...
...
@@ -285,60 +310,154 @@ export default {
});
},
// 初始化Cesium地图
initCesium
()
{
/**
* 初始化Cesium地图
*/
async
initCesium
()
{
Cesium
.
Ion
.
defaultAccessToken
=
"
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI0ZDAxZGFhYy02MjJlLTRiNzktODNhZi00N2VjZGY0NTk4YmIiLCJpZCI6Mjc0NDAxLCJpYXQiOjE3NjMzNDYwNTR9.ZQW2DZ4KaMGbHuwrtIbyI6EdSSvgMJUHmmD74eZW7PQ
"
;
try
{
// 设置Cesium基础路径
window
.
CESIUM_BASE_URL
=
"
/cesium/
"
;
// 创建Cesium视图
// 创建Cesium Viewer实例
this
.
viewer
=
new
Cesium
.
Viewer
(
"
cesiumContainer
"
,
{
// 设置地图提供者,这里使用默认的Bing Maps
imageryProvider
:
new
Cesium
.
BingMapsImageryProvider
({
url
:
"
https://dev.virtualearth.net
"
,
key
:
"
AgcbDCAOb9zMfquaT4Z-MdHfx--9wUNrLRiiS7rIElFx8f-4lLulxZ0QnhqX5Lm6
"
,
mapStyle
:
Cesium
.
BingMapsStyle
.
AERIAL
,
key
:
"
your-bing-maps-key
"
,
// 请替换为实际的Bing Maps密钥
}),
baseLayerPicker
:
false
,
timeline
:
false
,
animation
:
false
,
fullscreenButton
:
false
,
geocoder
:
false
,
homeButton
:
false
,
infoBox
:
false
,
sceneModePicker
:
false
,
navigationHelpButton
:
false
,
// 配置是否显示各种控件
animation
:
false
,
// 动画控件
baseLayerPicker
:
true
,
// 底图选择器
fullscreenButton
:
true
,
// 全屏按钮
geocoder
:
true
,
// 地址搜索
homeButton
:
true
,
// 主页按钮
infoBox
:
true
,
// 信息框
sceneModePicker
:
true
,
// 场景模式选择器
selectionIndicator
:
true
,
// 选择指示器
timeline
:
false
,
// 时间线
navigationHelpButton
:
false
,
// 导航帮助按钮
navigationInstructionsInitiallyVisible
:
false
,
// 设置初始视图位置(中国区域)
center
:
Cesium
.
Cartesian3
.
fromDegrees
(
104.06
,
30.67
,
10000000
),
});
// 设置相机位置
this
.
viewer
.
camera
.
setView
({
destination
:
Cesium
.
Cartesian3
.
fromDegrees
(
116.397428
,
39.90923
,
10000.0
),
// 设置相机视图
// this.viewer.camera.setView({
// destination: Cesium.Cartesian3.fromDegrees(104.06, 30.67, 10000000), // 经度、纬度、高度
// orientation: {
// heading: Cesium.Math.toRadians(0.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
:
{
heading
:
Cesium
.
Math
.
toRadians
(
0.0
)
,
pitch
:
Cesium
.
Math
.
toRadians
(
-
90.0
)
,
roll
:
0.0
,
heading
:
6.037000745578596
,
pitch
:
-
1.2499586064720978
,
roll
:
0.0
00005306352659495417
,
},
});
// 禁用默认的点击事件
this
.
viewer
.
cesiumWidget
.
screenSpaceEventHandler
.
removeInputAction
(
Cesium
.
ScreenSpaceEventType
.
LEFT_CLICK
);
// 隐藏Cesium logo
this
.
viewer
.
_cesiumWidget
.
_creditContainer
.
style
.
display
=
"
none
"
;
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
)
{
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
"
;
console
.
error
(
"
Cesium地图初始化失败:
"
,
error
);
}
},
/**
* 获取倾斜摄影模型的经纬度并将摄像机视角转向模型上方
*/
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
()
{
const
container
=
document
.
getElementById
(
"
trendChart
"
);
...
...
src/views/index.vue
View file @
8a90e89b
<
template
>
<div
class=
"app-container home"
>
<!-- Cesium地图容器 -->
<div
id=
"cesiumContainer"
class=
"cesium-container"
></div>
<div
class=
"screen-container"
>
<!-- Cesium地图背景 -->
<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>
</
template
>
<
script
>
import
{
getTokenApi
}
from
"
@/api/token
"
;
import
{
localStg
}
from
"
@/utils/storage
"
;
export
default
{
name
:
"
Index
"
,
data
()
{
return
{
currentTime
:
""
,
currentTimeShort
:
""
,
// 版本号
version
:
"
3.8.9
"
,
// Cesium查看器实例
...
...
@@ -38,116 +265,95 @@ export default {
],
personModelInterval
:
null
,
bgEntities
:
{},
// 所有的key都对应一个实体对象。而人员的实体对应的key不是数字。
// 轨迹追踪相关数据
selectedPerson
:
""
,
// 选中的人员
timePoints
:
[],
// 时间点数组
currentTimeIndex
:
0
,
// 当前时间索引
personTrajectories
:
{},
// 人员轨迹数据 { 人员名称: [{time, lng, lat, height}] }
trailEntities
:
{},
// 轨迹实体
isTracking
:
false
,
// 是否正在实时追踪
currentTimeDisplay
:
""
,
// 当前显示时间
};
},
mounted
()
{
// 组件挂载后初始化地图
// 初始化时间
this
.
updateTime
();
setInterval
(()
=>
this
.
updateTime
(),
1000
);
// 初始化Cesium地图
this
.
initCesium
();
},
beforeMount
()
{
localStg
.
set
(
"
token
"
,
222233
);
// 初始化时间点数据
this
.
initTimePoints
();
if
(
localStg
.
get
(
"
token
"
))
{
return
;
}
// 组件挂载前获取token
getTokenApi
().
then
((
res
)
=>
{
console
.
log
(
"
token
"
,
res
);
localStg
.
set
(
"
token
"
,
res
.
data
.
data
);
// 初始化图表
this
.
$nextTick
(()
=>
{
this
.
drawTrendChart
();
});
// 监听窗口大小变化
window
.
addEventListener
(
"
resize
"
,
this
.
handleResize
);
},
beforeDestroy
()
{
window
.
removeEventListener
(
"
resize
"
,
this
.
handleResize
);
if
(
this
.
viewer
)
{
this
.
viewer
.
destroy
();
}
// 组件销毁前清理地图资源
if
(
this
.
viewer
)
{
this
.
viewer
.
destroy
();
this
.
viewer
=
null
;
}
if
(
this
.
personModelInterval
)
{
clearInterval
(
this
.
personModelInterval
);
}
if
(
this
.
trackingInterval
)
{
clearInterval
(
this
.
trackingInterval
);
}
},
methods
:
{
createPersonModel
()
{
// 批次号管理(每次定时器触发时生成一个新的批次号)
// var currentBatch = 0;
// const batchMap = {};
// 更新时间
updateTime
()
{
const
now
=
new
Date
();
// 完整时间格式
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
)
{
this
.
personModelInterval
=
setInterval
(()
=>
{
console
.
log
(
"
开始获取实时数据
"
);
// currentBatch++; // 每次定时器触发,生成新的批次号
if
(
this
.
bgEntities
)
{
for
(
let
key
in
this
.
bgEntities
)
{
if
(
isNaN
(
parseFloat
(
key
)))
{
// 非数字键名的是人员实体
this
.
viewer
.
entities
.
remove
(
this
.
bgEntities
[
key
]);
delete
this
.
bgEntities
[
key
];
}
}
}
// 初始化时间点数据(生成过去1小时的时间点,每5分钟一个)
initTimePoints
()
{
const
now
=
new
Date
();
const
points
=
[];
// 从API获取最新的人员定位数据
this
.
personCardList
((
list
)
=>
{
// let perList = 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
,
// 禁用地形深度测试
// 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秒刷新一次
// 生成过去1小时的时间点,每5分钟一个
for
(
let
i
=
60
;
i
>=
0
;
i
-=
5
)
{
const
time
=
new
Date
(
now
.
getTime
()
-
i
*
60
*
1000
);
points
.
push
(
time
);
}
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
({
x
:
-
2686273.730145489
,
y
:
4293961.185794622
,
...
...
@@ -157,52 +363,234 @@ export default {
const
baseLatitude
=
Cesium
.
Math
.
toDegrees
(
cartographic
.
latitude
);
const
baseHeight
=
cartographic
.
height
+
1
;
console
.
log
(
"
人员经纬度基准点:
"
,
{
longitude
:
baseLongitude
,
latitude
:
baseLatitude
,
height
:
baseHeight
,
// 为每个人生成轨迹数据
this
.
personnelList
.
forEach
((
person
)
=>
{
const
trajectories
=
[];
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米(赤道附近)
// 为了确保不超过100米,我们使用±0.00005度的随机偏移
const
maxOffset
=
0.00005
;
// 人员选择变化处理
onPersonSelect
()
{
this
.
clearTrails
();
if
(
this
.
selectedPerson
)
{
this
.
updatePersonPositionByTimeIndex
(
this
.
currentTimeIndex
);
this
.
showFullPath
();
}
},
for
(
let
index
=
0
;
index
<
10
;
index
++
)
{
// 生成随机偏移量,确保每个点都不同但距离不远
const
lngOffset
=
(
Math
.
random
()
-
0.5
)
*
2
*
maxOffset
;
const
latOffset
=
(
Math
.
random
()
-
0.5
)
*
2
*
maxOffset
;
// 时间轴变化处理
onTimelineChange
()
{
this
.
currentTimeDisplay
=
this
.
formatTime
(
this
.
timePoints
[
this
.
currentTimeIndex
]
);
this
.
updatePersonPositionByTimeIndex
(
this
.
currentTimeIndex
);
},
this
.
personnelList
.
push
({
lng
:
baseLongitude
+
lngOffset
,
lat
:
baseLatitude
+
latOffset
,
height
:
baseHeight
,
// 高度略有不同,便于区分
perName
:
"
张三
"
+
index
,
status
:
"
online
"
,
// 在线
avatar
:
"
/static/images/avatars/zhangsan.png
"
,
// 头像
// 根据时间索引更新人员位置
updatePersonPositionByTimeIndex
(
index
)
{
if
(
!
this
.
selectedPerson
||
!
this
.
personTrajectories
[
this
.
selectedPerson
]
)
{
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
({
description
:
description
,
// 停止实时追踪
stopTracking
()
{
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 {
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
>
<
style
scoped
lang=
"scss"
>
.home
{
width
:
100%
;
<
style
lang=
"scss"
scope
>
// 基础样式 - 1rem = 100px
html
{
font-size
:
100px
;
}
// 屏幕容器
.screen-container
{
position
:
relative
;
width
:
100vw
;
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
;
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
;
display
:
flex
;
flex-direction
:
column
;
backdrop-filter
:
blur
(
0
.05rem
);
box-shadow
:
0
0
0
.15rem
rgba
(
0
,
100
,
200
,
0
.3
);
blockquote
{
padding
:
10px
20px
;
margin
:
0
0
20px
;
font-size
:
17
.5px
;
border-left
:
5px
solid
#eee
;
&
:nth-child
(
1
)
{
height
:
2
.2rem
;
}
hr
{
margin-top
:
20px
;
margin-bottom
:
20px
;
border
:
0
;
border-top
:
1px
solid
#eee
;
&
:nth-child
(
2
)
{
height
:
2
.5rem
;
}
.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
;
font-size
:
0
.16rem
;
font-weight
:
500
;
color
:
#00ffcc
;
}
font-family
:
"open sans"
,
"Helvetica Neue"
,
Helvetica
,
Arial
,
sans-serif
;
font-size
:
13px
;
color
:
#676a6c
;
overflow-x
:
hidden
;
.refresh-icon
,
.view-more
{
font-size
:
0
.12rem
;
color
:
#99ccff
;
cursor
:
pointer
;
}
ul
{
list-style-type
:
none
;
.alarm-count
{
background-color
:
#ff3333
;
color
:
#fff
;
padding
:
0
.02rem
0
.08rem
;
border-radius
:
0
.1rem
;
font-size
:
0
.12rem
;
font-weight
:
bold
;
}
h4
{
margin-top
:
0px
;
.time-range
,
.chart-type
,
.system-time
{
font-size
:
0
.12rem
;
color
:
#66ccff
;
}
}
h2
{
margin-top
:
10px
;
font-size
:
26px
;
font-weight
:
100
;
// 模块内容区
.module-body
{
flex
:
1
;
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
{
margin-top
:
10px
;
.progress-bars
{
margin-top
:
0
.1rem
;
}
b
{
font-weight
:
700
;
}
.progress-item
{
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
{
ol
{
display
:
block
;
list-style-type
:
decimal
;
margin-block-start
:
1em
;
margin-block-end
:
1em
;
margin-inline-start
:
0
;
margin-inline-end
:
0
;
padding-inline-start
:
40px
;
}
&
:
:-
webkit-scrollbar-track
{
background
:
rgba
(
0
,
40
,
80
,
0
.5
);
}
&
:
:-
webkit-scrollbar-thumb
{
background
:
#0070b0
;
border-radius
:
0
.02rem
;
}
}
.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容器样式
.cesium-container
{
// width: 100vw;
// height: 100vh;
width
:
87vw
;
height
:
87vh
;
position
:
absolute
;
top
:
0
;
left
:
0
;
z-index
:
1
;
&
.level-2
{
border-color
:
#ff9900
;
background
:
rgba
(
255
,
153
,
0
,
0
.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
>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment