diff --git a/dist/index.html b/dist/index.html
index fd7b68a..de16292 100644
--- a/dist/index.html
+++ b/dist/index.html
@@ -7,8 +7,8 @@
火情监控全链路业务监控视图
-
-
+
+
diff --git a/src/App.vue b/src/App.vue
index 1451579..78d003e 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -3,29 +3,17 @@
class="monitor-container"
:class="{ 'is-top2': currentStyle === 'top2', 'is-top3': currentStyle === 'top3' }"
>
-
+
-
-
-
+
+
@@ -37,8 +25,8 @@
>
-
-
-
+
+
+
告警看板
+
+
+
+
告警信息
+
告警1
+
告警2
+
告警3
+
+
+
+
+
+
+
故障看板
+
+
+
+
故障记录
+
故障1
+
故障2
+
故障3
+
+
+
指标
+
网络
+
视联网拉流
+
AI分析
+
+
+
+
+
+
+
+
+
@@ -151,18 +205,19 @@ import playIcon from './assets/play.svg'
import aiIcon from './assets/ai.svg'
import picIcon from './assets/pic.svg'
import mapKuang from './assets/map-kuang.svg'
+import headerBack from './assets/header-back.svg'
type StyleType = 'circle' | 'top2' | 'top3'
const svgWrapper = ref(null)
const svgContent = ref('')
-const currentStyle = ref('circle')
+const currentStyle = ref('top3')
const top2Stage = ref(null)
const top2Scale = ref(1)
const TOP_LAYOUTS = {
top2: { width: 1296, height: 692 },
- top3: { width: 1438, height: 832 },
+ top3: { width: 1438, height: 929 },
}
let top2ResizeObserver: ResizeObserver | null = null
@@ -225,13 +280,14 @@ const loadSvg = async (style: StyleType) => {
}
}
-const switchStyle = (style: StyleType) => {
- currentStyle.value = style
- loadSvg(style)
-}
-
onMounted(() => {
- loadSvg('circle')
+ nextTick(() => {
+ loadSvg(currentStyle.value)
+ if (currentStyle.value === 'top2' || currentStyle.value === 'top3') {
+ attachTop2Observer()
+ updateTop2Scale()
+ }
+ })
})
onBeforeUnmount(() => {
@@ -239,8 +295,9 @@ onBeforeUnmount(() => {
})
watch(currentStyle, async (style) => {
+ await nextTick()
+ loadSvg(style)
if (style === 'top2' || style === 'top3') {
- await nextTick()
attachTop2Observer()
updateTop2Scale()
} else {
@@ -252,6 +309,10 @@ const topLayoutClass = computed(() => (
currentStyle.value === 'top3' ? 'layout-top3' : 'layout-top2'
))
+const headerStyle = computed(() => (
+ currentStyle.value === 'top3' ? { '--header-back': `url(${headerBack})` } : {}
+))
+
const addFlowingAnimation = () => {
if (!svgWrapper.value) return
@@ -532,7 +593,8 @@ const addTop2Animation = () => {
.style-switcher {
display: flex;
- gap: 10px;
+ align-items: center;
+ gap: 12px;
margin-top: 10px;
}
@@ -545,41 +607,27 @@ const addTop2Animation = () => {
z-index: 5;
}
-.style-btn {
- padding: 10px 24px;
- font-size: 16px;
+.style-label {
+ font-size: 14px;
font-weight: 600;
- color: rgba(255, 255, 255, 0.7);
- background: rgba(255, 255, 255, 0.1);
- border: 2px solid rgba(255, 255, 255, 0.3);
- border-radius: 12px;
+ color: rgba(255, 255, 255, 0.75);
+}
+
+.style-select {
+ padding: 8px 14px;
+ font-size: 14px;
+ font-weight: 600;
+ color: #ffffff;
+ background: rgba(255, 255, 255, 0.12);
+ border: 1px solid rgba(255, 255, 255, 0.4);
+ border-radius: 10px;
cursor: pointer;
- transition: all 0.3s ease;
backdrop-filter: blur(10px);
+ outline: none;
}
-.style-btn:hover {
- color: rgba(255, 255, 255, 0.9);
- background: rgba(255, 255, 255, 0.15);
- border-color: rgba(255, 255, 255, 0.5);
- transform: translateY(-2px);
- box-shadow: 0 4px 12px rgba(255, 255, 255, 0.2);
-}
-
-.style-btn.active {
- color: white;
- background: linear-gradient(135deg, rgba(0, 245, 255, 0.25), rgba(77, 159, 255, 0.25));
- border-color: #00F5FF;
- box-shadow: 0 0 20px rgba(0, 245, 255, 0.4),
- 0 0 40px rgba(0, 245, 255, 0.2),
- inset 0 0 20px rgba(0, 245, 255, 0.1);
-}
-
-.style-btn.active:hover {
- background: linear-gradient(135deg, rgba(0, 245, 255, 0.35), rgba(77, 159, 255, 0.35));
- box-shadow: 0 0 25px rgba(0, 245, 255, 0.5),
- 0 0 50px rgba(0, 245, 255, 0.3),
- inset 0 0 25px rgba(0, 245, 255, 0.15);
+.style-select option {
+ color: #0e1a3f;
}
.title {
@@ -668,7 +716,7 @@ const addTop2Animation = () => {
.layout-top3 .top2-scale {
width: calc(1438px * var(--top2-scale));
- height: calc(832px * var(--top2-scale));
+ height: calc(929px * var(--top2-scale));
}
.layout-top2 .top2-layout {
@@ -678,7 +726,7 @@ const addTop2Animation = () => {
.layout-top3 .top2-layout {
width: 1438px;
- height: 832px;
+ height: 929px;
display: flex;
flex-direction: column;
gap: 16px;
@@ -702,12 +750,16 @@ const addTop2Animation = () => {
}
.layout-top3 .top2-header {
- height: 50px;
- border-radius: 16px;
- background: rgba(229, 229, 229, 0);
+ height: 72px;
+ border-radius: 0;
+ background: transparent;
display: flex;
align-items: center;
justify-content: center;
+ background-image: var(--header-back);
+ background-repeat: no-repeat;
+ background-position: center;
+ background-size: 1120px 72px;
}
.top2-title {
@@ -740,7 +792,8 @@ const addTop2Animation = () => {
}
.layout-top3 .top2-content {
- flex: 1;
+ width: 100%;
+ height: 809px;
display: flex;
gap: 16px;
}
@@ -755,7 +808,7 @@ const addTop2Animation = () => {
.layout-top3 .top2-left-col {
width: 315px;
- height: 734px;
+ height: 809px;
display: flex;
flex-direction: column;
gap: 16px;
@@ -772,10 +825,10 @@ const addTop2Animation = () => {
.layout-top3 .top2-center-col {
width: 744px;
- height: 734px;
+ height: 809px;
display: flex;
flex-direction: column;
- gap: 0;
+ gap: 8px;
padding: 0;
}
@@ -789,12 +842,170 @@ const addTop2Animation = () => {
.layout-top3 .top2-right-col {
width: 315px;
- height: 734px;
+ height: 809px;
display: flex;
flex-direction: column;
gap: 16px;
}
+.top3-board {
+ width: 315px;
+ height: 396.5px;
+ border-radius: 16px;
+ display: flex;
+ flex-direction: column;
+ gap: 10px;
+ align-items: stretch;
+}
+
+.top3-board-title {
+ font-family: 'Inter', 'Noto Sans JP', sans-serif;
+ font-size: 24px;
+ font-weight: 700;
+ color: #f02525;
+ text-align: center;
+ line-height: 40px;
+}
+
+.top3-board-table {
+ width: 100%;
+ height: 156px;
+ display: flex;
+}
+
+.top3-board-col {
+ display: flex;
+ flex-direction: column;
+ align-items: stretch;
+}
+
+.top3-rank-col {
+ width: 36px;
+}
+
+.top3-info-col {
+ width: 146px;
+}
+
+.top3-metric-col {
+ width: 133px;
+}
+
+.top3-table-head {
+ height: 40px;
+ background: #043272;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
+ font-size: 16px;
+ color: rgba(255, 255, 255, 0.75);
+}
+
+.top3-table-head-left {
+ justify-content: flex-start;
+ padding: 0 10px;
+}
+
+.top3-table-head-right {
+ justify-content: flex-start;
+ padding: 0 0 0 16px;
+ text-align: left;
+}
+
+.top3-table-cell {
+ display: flex;
+ align-items: center;
+ flex: 1;
+}
+
+.top3-rank-cell {
+ justify-content: center;
+}
+
+.top3-info-cell {
+ padding: 0 10px;
+ font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
+ font-size: 18px;
+ color: #ffffff;
+ line-height: 28px;
+}
+
+.top3-metric-cell {
+ justify-content: flex-start;
+ padding: 0 0 0 16px;
+ font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
+ font-size: 20px;
+ color: #4de4ff;
+}
+
+.rank-badge {
+ width: 24px;
+ height: 24px;
+ border-radius: 2px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ font-family: 'Mark Pro', 'Inter', sans-serif;
+ font-size: 16px;
+ font-weight: 700;
+ color: #ffffff;
+ letter-spacing: 0.75px;
+}
+
+.rank-1 {
+ background: #c85b3f;
+}
+
+.rank-2 {
+ background: #b99a3a;
+}
+
+.rank-3 {
+ background: #1fb2a4;
+}
+
+.top3-board-bottom {
+ width: 100%;
+ height: 180.5px;
+ background: #ffffff;
+ border-bottom-left-radius: 16px;
+ border-bottom-right-radius: 16px;
+ position: relative;
+ box-sizing: border-box;
+}
+
+.top3-bottom-title {
+ font-family: 'PingFang SC', 'Microsoft YaHei', sans-serif;
+ font-size: 16px;
+ font-weight: 600;
+ color: rgba(0, 0, 0, 0.6);
+ position: absolute;
+ left: 13.03px;
+ top: 15.427px;
+}
+
+.top3-bottom-line {
+ width: 246.568px;
+ height: 1.556px;
+ background: rgba(240, 226, 226, 0.9);
+ position: absolute;
+ left: 34.759px;
+}
+
+.top3-board-bottom .top3-bottom-line:nth-of-type(2) {
+ top: 72.508px;
+ left: 35.845px;
+}
+
+.top3-board-bottom .top3-bottom-line:nth-of-type(3) {
+ top: 109.548px;
+}
+
+.top3-board-bottom .top3-bottom-line:nth-of-type(4) {
+ top: 146.573px;
+}
+
.panel-outline {
border: 0.297px solid #f0e2e2;
border-radius: 10.684px;
@@ -810,6 +1021,10 @@ const addTop2Animation = () => {
position: relative;
}
+.top3-board.panel-outline {
+ border-radius: 16px;
+}
+
.layout-top2 .panel-left-top {
left: 0;
top: 0;
@@ -819,12 +1034,12 @@ const addTop2Animation = () => {
.layout-top3 .panel-left-top {
width: 315px;
- height: 234px;
+ height: 259px;
}
.layout-top3 .panel-left-middle {
width: 315px;
- height: 234px;
+ height: 259px;
}
.layout-top2 .panel-left-bottom {
@@ -836,7 +1051,7 @@ const addTop2Animation = () => {
.layout-top3 .panel-left-bottom {
width: 315px;
- height: 234px;
+ height: 259px;
}
.layout-top2 .panel-right-top {
@@ -880,13 +1095,13 @@ const addTop2Animation = () => {
.layout-top3 .panel-center-bottom-left {
width: auto;
flex: 1;
- height: 100%;
+ height: 242.813px;
}
.layout-top3 .panel-center-bottom-right {
width: auto;
flex: 1;
- height: 100%;
+ height: 242.813px;
}
.layout-top2 .top2-center {
@@ -914,8 +1129,7 @@ const addTop2Animation = () => {
.layout-top3 .top2-bottom-row {
width: 744px;
- height: auto;
- flex: 1;
+ height: 242.818px;
display: flex;
gap: 16px;
align-items: stretch;