|
|
@ -189,7 +189,13 @@ |
|
|
<div class="video-monitor-body" :class="{ 'tree-visible': treeVisible }"> |
|
|
<div class="video-monitor-body" :class="{ 'tree-visible': treeVisible }"> |
|
|
<div class="video-monitor-main"> |
|
|
<div class="video-monitor-main"> |
|
|
<div class="camera-stats"> |
|
|
<div class="camera-stats"> |
|
|
<div v-for="item in cameraStats" :key="item.label" class="camera-stat"> |
|
|
|
|
|
|
|
|
<div |
|
|
|
|
|
v-for="item in cameraStats" |
|
|
|
|
|
:key="item.key" |
|
|
|
|
|
class="camera-stat" |
|
|
|
|
|
:class="{ active: treeVisible && treeDeviceSource === item.deviceSource }" |
|
|
|
|
|
@click="selectCameraSource(item)" |
|
|
|
|
|
> |
|
|
<img class="camera-icon" :src="item.icon" alt=""> |
|
|
<img class="camera-icon" :src="item.icon" alt=""> |
|
|
<div class="camera-meta"> |
|
|
<div class="camera-meta"> |
|
|
<div class="camera-value">{{ item.value }}</div> |
|
|
<div class="camera-value">{{ item.value }}</div> |
|
|
@ -245,9 +251,10 @@ |
|
|
|
|
|
|
|
|
<aside v-if="treeMounted" v-show="treeVisible" class="portal-device-tree"> |
|
|
<aside v-if="treeMounted" v-show="treeVisible" class="portal-device-tree"> |
|
|
<portal-device-tree |
|
|
<portal-device-tree |
|
|
:key="portalTreeStationCode || 'all'" |
|
|
|
|
|
|
|
|
:key="`${portalTreeStationCode || 'all'}-${treeDeviceSource || 'all-source'}`" |
|
|
:selected-code="selectedPortalCameraCode" |
|
|
:selected-code="selectedPortalCameraCode" |
|
|
:station-code="portalTreeStationCode" |
|
|
:station-code="portalTreeStationCode" |
|
|
|
|
|
:device-source="treeDeviceSource" |
|
|
@channels-loaded="handlePortalTreeChannels" |
|
|
@channels-loaded="handlePortalTreeChannels" |
|
|
@open="openPortalChannel" |
|
|
@open="openPortalChannel" |
|
|
/> |
|
|
/> |
|
|
@ -337,7 +344,8 @@ function createEmptyOverview() { |
|
|
totalDefects: 0, |
|
|
totalDefects: 0, |
|
|
slightDefects: 0, |
|
|
slightDefects: 0, |
|
|
generalDefects: 0, |
|
|
generalDefects: 0, |
|
|
importantDefects: 0 |
|
|
|
|
|
|
|
|
seriousDefects: 0, |
|
|
|
|
|
urgentDefects: 0 |
|
|
})); |
|
|
})); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -356,7 +364,8 @@ function createEmptyTrend() { |
|
|
const DEFECT_SLIDES = [ |
|
|
const DEFECT_SLIDES = [ |
|
|
{ key: "slight", label: "轻微缺陷", fields: ["slightDefects", "minorDefects"] }, |
|
|
{ key: "slight", label: "轻微缺陷", fields: ["slightDefects", "minorDefects"] }, |
|
|
{ key: "general", label: "一般缺陷", fields: ["generalDefects", "normalDefects"] }, |
|
|
{ key: "general", label: "一般缺陷", fields: ["generalDefects", "normalDefects"] }, |
|
|
{ key: "important", label: "重要缺陷", fields: ["importantDefects", "majorDefects"] } |
|
|
|
|
|
|
|
|
{ key: "serious", label: "严重缺陷", fields: ["seriousDefects"] }, |
|
|
|
|
|
{ key: "urgent", label: "重大缺陷", fields: ["urgentDefects"] } |
|
|
]; |
|
|
]; |
|
|
|
|
|
|
|
|
// 场站卡片下方的缺陷趋势快捷筛选 |
|
|
// 场站卡片下方的缺陷趋势快捷筛选 |
|
|
@ -415,6 +424,8 @@ export default { |
|
|
videoList: [], |
|
|
videoList: [], |
|
|
videoStationId: "", |
|
|
videoStationId: "", |
|
|
activeVideoIndex: 0, |
|
|
activeVideoIndex: 0, |
|
|
|
|
|
// 空字符串表示摄像头总数,不按设备来源过滤树 |
|
|
|
|
|
treeDeviceSource: "", |
|
|
treeVisible: false, |
|
|
treeVisible: false, |
|
|
treeMounted: false, |
|
|
treeMounted: false, |
|
|
portalPlayers: {}, |
|
|
portalPlayers: {}, |
|
|
@ -447,10 +458,10 @@ export default { |
|
|
}, |
|
|
}, |
|
|
cameraStats() { |
|
|
cameraStats() { |
|
|
return [ |
|
|
return [ |
|
|
{ label: "摄像头总数", value: this.cameraCount.total, icon: iconTotal }, |
|
|
|
|
|
{ label: "动环摄像头", value: this.cameraCount.donghuan, icon: iconDonghuan }, |
|
|
|
|
|
{ label: "消防摄像头", value: this.cameraCount.fire, icon: iconFire }, |
|
|
|
|
|
{ label: "安防摄像头", value: this.cameraCount.security, icon: iconSecurity } |
|
|
|
|
|
|
|
|
{ key: "total", label: "摄像头总数", value: this.cameraCount.total, icon: iconTotal, deviceSource: "" }, |
|
|
|
|
|
{ key: "donghuan", label: "动环摄像头", value: this.cameraCount.donghuan, icon: iconDonghuan, deviceSource: "动环" }, |
|
|
|
|
|
{ key: "fire", label: "消防摄像头", value: this.cameraCount.fire, icon: iconFire, deviceSource: "消防" }, |
|
|
|
|
|
{ key: "security", label: "安防摄像头", value: this.cameraCount.security, icon: iconSecurity, deviceSource: "安防" } |
|
|
]; |
|
|
]; |
|
|
}, |
|
|
}, |
|
|
filteredVideos() { |
|
|
filteredVideos() { |
|
|
@ -500,6 +511,10 @@ export default { |
|
|
this.videoStationId = station.id; |
|
|
this.videoStationId = station.id; |
|
|
this.openDeviceTree(); |
|
|
this.openDeviceTree(); |
|
|
}, |
|
|
}, |
|
|
|
|
|
selectCameraSource(item) { |
|
|
|
|
|
this.treeDeviceSource = item && item.deviceSource ? item.deviceSource : ""; |
|
|
|
|
|
this.openDeviceTree(); |
|
|
|
|
|
}, |
|
|
openDeviceTree() { |
|
|
openDeviceTree() { |
|
|
this.treeMounted = true; |
|
|
this.treeMounted = true; |
|
|
this.treeVisible = true; |
|
|
this.treeVisible = true; |
|
|
@ -559,10 +574,9 @@ export default { |
|
|
counts.forEach(item => { |
|
|
counts.forEach(item => { |
|
|
const source = String(item.deviceSource || ""); |
|
|
const source = String(item.deviceSource || ""); |
|
|
const count = toCount(item.count); |
|
|
const count = toCount(item.count); |
|
|
if (source.includes("动环")) cameraCount.donghuan += count; |
|
|
|
|
|
else if (source.includes("消防")) cameraCount.fire += count; |
|
|
|
|
|
else if (source.includes("安防")) cameraCount.security += count; |
|
|
|
|
|
else cameraCount.security += count; |
|
|
|
|
|
|
|
|
if (source === "动环") cameraCount.donghuan += count; |
|
|
|
|
|
else if (source === "消防") cameraCount.fire += count; |
|
|
|
|
|
else if (source === "安防") cameraCount.security += count; |
|
|
}); |
|
|
}); |
|
|
this.cameraCount = cameraCount; |
|
|
this.cameraCount = cameraCount; |
|
|
}).catch((error) => { |
|
|
}).catch((error) => { |
|
|
@ -894,7 +908,8 @@ export default { |
|
|
totalDefects: toCount(item.defectCount), |
|
|
totalDefects: toCount(item.defectCount), |
|
|
slightDefects: toCount(item.minorCount), |
|
|
slightDefects: toCount(item.minorCount), |
|
|
generalDefects: toCount(item.generalCount), |
|
|
generalDefects: toCount(item.generalCount), |
|
|
importantDefects: toCount(item.seriousCount) + toCount(item.urgentCount) |
|
|
|
|
|
|
|
|
seriousDefects: toCount(item.seriousCount), |
|
|
|
|
|
urgentDefects: toCount(item.urgentCount) |
|
|
}; |
|
|
}; |
|
|
}); |
|
|
}); |
|
|
}).catch((error) => { |
|
|
}).catch((error) => { |
|
|
@ -1361,6 +1376,32 @@ $panel-border: rgba(84, 130, 255, 0.22); |
|
|
|
|
|
|
|
|
.overview-stat.is-defect-carousel { |
|
|
.overview-stat.is-defect-carousel { |
|
|
padding: 4px 4px 16px; |
|
|
padding: 4px 4px 16px; |
|
|
|
|
|
cursor: pointer; |
|
|
|
|
|
transition: box-shadow .25s ease; |
|
|
|
|
|
|
|
|
|
|
|
&::before { |
|
|
|
|
|
content: ""; |
|
|
|
|
|
position: absolute; |
|
|
|
|
|
inset: 0; |
|
|
|
|
|
z-index: 0; |
|
|
|
|
|
pointer-events: none; |
|
|
|
|
|
background: |
|
|
|
|
|
linear-gradient(135deg, rgba(150, 210, 255, 0.16) 0%, rgba(80, 160, 230, 0.05) 28%, transparent 52%), |
|
|
|
|
|
radial-gradient(120% 80% at 0% 0%, rgba(90, 180, 240, 0.14), transparent 58%); |
|
|
|
|
|
opacity: 0; |
|
|
|
|
|
transition: opacity .25s ease; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
&:hover { |
|
|
|
|
|
box-shadow: |
|
|
|
|
|
inset 0 1px 0 rgba(42, 198, 255, 0.28), |
|
|
|
|
|
inset 0 0 16px rgba(40, 130, 200, 0.2), |
|
|
|
|
|
0 0 8px rgba(30, 110, 190, 0.2); |
|
|
|
|
|
|
|
|
|
|
|
&::before { |
|
|
|
|
|
opacity: 1; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
.overview-defect-viewport { |
|
|
.overview-defect-viewport { |
|
|
position: relative; |
|
|
position: relative; |
|
|
@ -1374,6 +1415,8 @@ $panel-border: rgba(84, 130, 255, 0.22); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.overview-defect-content { |
|
|
.overview-defect-content { |
|
|
|
|
|
position: relative; |
|
|
|
|
|
z-index: 1; |
|
|
display: flex; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
align-items: center; |
|
|
justify-content: center; |
|
|
justify-content: center; |
|
|
@ -1382,18 +1425,23 @@ $panel-border: rgba(84, 130, 255, 0.22); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
&.severity-slight .overview-value { |
|
|
&.severity-slight .overview-value { |
|
|
color: #1ad6fb; |
|
|
|
|
|
text-shadow: 0 0 12px rgba(26, 214, 251, 0.52); |
|
|
|
|
|
|
|
|
color: #2f7bff; |
|
|
|
|
|
text-shadow: 0 0 12px rgba(47, 123, 255, 0.52); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
&.severity-general .overview-value { |
|
|
&.severity-general .overview-value { |
|
|
color: #ffb849; |
|
|
|
|
|
text-shadow: 0 0 12px rgba(255, 184, 73, 0.48); |
|
|
|
|
|
|
|
|
color: #3ad07a; |
|
|
|
|
|
text-shadow: 0 0 12px rgba(58, 208, 122, 0.48); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
&.severity-important .overview-value { |
|
|
|
|
|
color: #f1dc1d; |
|
|
|
|
|
text-shadow: 0 0 12px rgba(241, 220, 29, 0.45); |
|
|
|
|
|
|
|
|
&.severity-serious .overview-value { |
|
|
|
|
|
color: #f0c14a; |
|
|
|
|
|
text-shadow: 0 0 12px rgba(240, 193, 74, 0.45); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
&.severity-urgent .overview-value { |
|
|
|
|
|
color: #ef5b5b; |
|
|
|
|
|
text-shadow: 0 0 12px rgba(239, 91, 91, 0.45); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
@ -1504,25 +1552,53 @@ $panel-border: rgba(84, 130, 255, 0.22); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.station-card { |
|
|
.station-card { |
|
|
|
|
|
position: relative; |
|
|
display: flex; |
|
|
display: flex; |
|
|
flex-direction: column; |
|
|
flex-direction: column; |
|
|
justify-content: space-between; |
|
|
justify-content: space-between; |
|
|
gap: 7px; |
|
|
gap: 7px; |
|
|
min-width: 0; |
|
|
min-width: 0; |
|
|
padding: 9px 11px 8px; |
|
|
padding: 9px 11px 8px; |
|
|
|
|
|
overflow: hidden; |
|
|
border: 1px solid rgba(46, 121, 232, 0.18); |
|
|
border: 1px solid rgba(46, 121, 232, 0.18); |
|
|
border-radius: 0; |
|
|
border-radius: 0; |
|
|
cursor: pointer; |
|
|
cursor: pointer; |
|
|
background: linear-gradient(90deg, rgba(10, 49, 119, 0.96), rgba(8, 38, 101, 0.92)); |
|
|
background: linear-gradient(90deg, rgba(10, 49, 119, 0.96), rgba(8, 38, 101, 0.92)); |
|
|
transition: border-color .2s, box-shadow .2s; |
|
|
|
|
|
|
|
|
transition: border-color .25s ease, box-shadow .25s ease; |
|
|
|
|
|
|
|
|
|
|
|
&::after { |
|
|
|
|
|
content: ""; |
|
|
|
|
|
position: absolute; |
|
|
|
|
|
inset: 0; |
|
|
|
|
|
z-index: 1; |
|
|
|
|
|
pointer-events: none; |
|
|
|
|
|
background: |
|
|
|
|
|
linear-gradient(135deg, rgba(150, 210, 255, 0.16) 0%, rgba(80, 160, 230, 0.05) 28%, transparent 52%), |
|
|
|
|
|
radial-gradient(120% 80% at 0% 0%, rgba(90, 180, 240, 0.14), transparent 58%); |
|
|
|
|
|
opacity: 0; |
|
|
|
|
|
transition: opacity .25s ease; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
&.selected { |
|
|
&.selected { |
|
|
border-color: rgba(18, 215, 248, 0.72); |
|
|
border-color: rgba(18, 215, 248, 0.72); |
|
|
box-shadow: inset 0 0 16px rgba(18, 215, 248, 0.12), 0 0 10px rgba(18, 215, 248, 0.12); |
|
|
box-shadow: inset 0 0 16px rgba(18, 215, 248, 0.12), 0 0 10px rgba(18, 215, 248, 0.12); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
&:hover { |
|
|
|
|
|
border-color: rgba(72, 156, 214, 0.55); |
|
|
|
|
|
box-shadow: |
|
|
|
|
|
inset 0 0 18px rgba(40, 130, 200, 0.16), |
|
|
|
|
|
0 0 10px rgba(30, 110, 190, 0.22); |
|
|
|
|
|
|
|
|
|
|
|
&::after { |
|
|
|
|
|
opacity: 1; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.station-head { |
|
|
.station-head { |
|
|
|
|
|
position: relative; |
|
|
|
|
|
z-index: 2; |
|
|
display: flex; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
align-items: center; |
|
|
gap: 7px; |
|
|
gap: 7px; |
|
|
@ -1578,6 +1654,8 @@ $panel-border: rgba(84, 130, 255, 0.22); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.station-btns { |
|
|
.station-btns { |
|
|
|
|
|
position: relative; |
|
|
|
|
|
z-index: 2; |
|
|
display: grid; |
|
|
display: grid; |
|
|
grid-template-columns: repeat(3, 1fr); |
|
|
grid-template-columns: repeat(3, 1fr); |
|
|
gap: 6px; |
|
|
gap: 6px; |
|
|
@ -1828,20 +1906,57 @@ $panel-border: rgba(84, 130, 255, 0.22); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
.camera-stat { |
|
|
.camera-stat { |
|
|
|
|
|
position: relative; |
|
|
display: flex; |
|
|
display: flex; |
|
|
align-items: center; |
|
|
align-items: center; |
|
|
gap: 14px; |
|
|
gap: 14px; |
|
|
padding: 12px 16px; |
|
|
padding: 12px 16px; |
|
|
|
|
|
overflow: hidden; |
|
|
|
|
|
border: 1px solid transparent; |
|
|
border-radius: 0; |
|
|
border-radius: 0; |
|
|
|
|
|
cursor: pointer; |
|
|
background: #0B2E6F; |
|
|
background: #0B2E6F; |
|
|
|
|
|
transition: border-color .25s ease, box-shadow .25s ease; |
|
|
|
|
|
|
|
|
|
|
|
&::after { |
|
|
|
|
|
content: ""; |
|
|
|
|
|
position: absolute; |
|
|
|
|
|
inset: 0; |
|
|
|
|
|
z-index: 1; |
|
|
|
|
|
pointer-events: none; |
|
|
|
|
|
background: |
|
|
|
|
|
linear-gradient(135deg, rgba(150, 210, 255, 0.14) 0%, rgba(80, 160, 230, 0.04) 28%, transparent 52%), |
|
|
|
|
|
radial-gradient(120% 80% at 0% 0%, rgba(90, 180, 240, 0.12), transparent 58%); |
|
|
|
|
|
opacity: 0; |
|
|
|
|
|
transition: opacity .25s ease; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
&:hover, |
|
|
|
|
|
&.active { |
|
|
|
|
|
border-color: rgba(72, 156, 214, 0.5); |
|
|
|
|
|
box-shadow: |
|
|
|
|
|
inset 0 0 18px rgba(40, 130, 200, 0.16), |
|
|
|
|
|
0 0 10px rgba(30, 110, 190, 0.2); |
|
|
|
|
|
|
|
|
|
|
|
&::after { |
|
|
|
|
|
opacity: 1; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
.camera-icon { |
|
|
.camera-icon { |
|
|
|
|
|
position: relative; |
|
|
|
|
|
z-index: 2; |
|
|
flex: none; |
|
|
flex: none; |
|
|
width: 42px; |
|
|
width: 42px; |
|
|
height: 42px; |
|
|
height: 42px; |
|
|
object-fit: contain; |
|
|
object-fit: contain; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
.camera-meta { |
|
|
|
|
|
position: relative; |
|
|
|
|
|
z-index: 2; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
.camera-value { |
|
|
.camera-value { |
|
|
font-family: "DIN Alternate", "Arial", "Microsoft YaHei", sans-serif; |
|
|
font-family: "DIN Alternate", "Arial", "Microsoft YaHei", sans-serif; |
|
|
font-size: 24px; |
|
|
font-size: 24px; |
|
|
|