Files
lc_frontend/src/views/screen/components/ScreenFrame.vue
2025-12-12 11:01:19 +08:00

1901 lines
48 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="dashboard-container">
<!-- 顶部标题栏 -->
<div class="header-container">
<div class="header-left">
<img class="back-img" @click="returnToHeadquarters" src="@/assets/images/screen/back_image.png" />
<div class="back-button"> {{ selectedPark }} </div>
</div>
<h1 class="header-title">总部安全管理大屏</h1>
<div class="header-right">
{{ currentTime }}
</div>
</div>
<!-- <span class="weather-warning">
天气预警:
<span style="color: red">
2025年08月19日13:25分中央气象台发布雄安地区于17时至夜间将有200毫米强降雨并伴有10级大风......
</span>
</span> -->
<!-- 主内容区 -->
<div class="content-container">
<div class="left-wrapper">
<div class="left-top">
<div class="panel-title">总体概览</div>
<img style="margin: 8px 0" src="@/assets/images/title_border_line_1.png" />
<div class="top-card">
<div class="top-card-left">
<div>
<img width="33px" src="@/assets/images/1_224520_821.png" />
</div>
<span>总计</span>
<div class="number-wrapper">
<span class="total-number" v-for="item in 6" :key="item">{{ item }}</span>
</div>
<span></span>
</div>
<div class="top-card-right">
<div class="top-card-right-item">
<img width="18px" src="@/assets/images/v2_rel0n8.png" />
<span>正式员工</span>
<div class="type-number-wrapper" style="margin-left: 2vw">
<span class="type-number" v-for="item in 3" :key="item">{{ item }}</span>
</div>
<span></span>
</div>
<div class="top-card-right-item">
<img width="18px" src="@/assets/images/v2_rel0n23.png" />
<span>外协人员</span>
<div class="type-number-wrapper" style="margin-left: 1vw">
<span class="type-number" v-for="item in 2" :key="item">{{ item }}</span>
</div>
<span></span>
</div>
<div class="top-card-right-item">
<img width="18px" src="@/assets/images/24508_654.png" />
<span>访客</span>
<div class="type-number-wrapper">
<span class="type-number" v-for="item in 4" :key="item">{{ item }}</span>
</div>
<span></span>
</div>
</div>
</div>
<div class="bottom-card">
<div class="bottom-card-title">
<span>各园区统计</span>
<img width="50%" style="margin: 8px 0" src="@/assets/images/line_1.png" />
</div>
<div ref="barChart" class="bar-chart"></div>
</div>
</div>
<div class="left-bottom">
<div class="panel-title">
<div class="tabs">
<span class="tab" :class="{ active: activeTab === '高危作业' }" @click="activeTab = '高危作业'">高危作业</span>
<span class="divider">|</span>
<span class="tab" :class="{ active: activeTab === '安全培训考试' }" @click="activeTab = '安全培训考试'">安全培训考试</span>
<span class="divider">|</span>
<span
class="tab" :class="{ active: activeTab === '安全培训考试' }"
@click="activeTab = '安全培训考试'">安全培训考试</span>
</div>
</div>
<img style="margin: 8px 0" src="@/assets/images/title_border_line.png" />
<div class="bottom-card">
<div class="bottom-card-title">
<span>各园区统计</span>
<img width="50%" style="margin: 8px 0" src="@/assets/images/line_1.png" />
</div>
</div>
<div ref="donutChart" class="donut-chart-with-labels"></div>
</div>
</div>
<div class="right-wrapper">
<div class="right-top" style="text-align: right">
<div class="panel-title">高风险告警</div>
<div>
<img style="margin: 8px 0" src="@/assets/images/title_border_line_1.png" />
</div>
<div class="tip-container">
<div class="tip-image">
<img src="@/assets/images/screen/circle_image.png" width="80" height="80" />
<span class="number">1234</span>
</div>
<img src="@/assets/images/screen/tip_bg_image.png" width="100%" height="70" />
<div class="tip-content">
<div class="col-item">
<img src="@/assets/images/screen/warning_img.png" width="23" />
<span>告警总数</span>
<span style="font-size: 1.2rem; marker-start: 2vw; color: yellow;">456</span>
</div>
<div class="col-item">
<span>已处理</span>
<span style="font-size: 1.2rem; marker-start: 2vw; color: greenyellow;">456</span>
</div>
<div class="col-item" style=" display: flex;margin-left: 2vw; align-items: center;">
<span>待处理</span>
<span style="font-size: 1.2rem; marker-start: 2vw; color: yellow;">456</span>
</div>
<div class="col-item" style=" display: flex;margin-left: 2vw; align-items: center;">
<span>处理中</span>
<span style="font-size: 1.2rem; marker-start: 2vw; color: yellow;">456</span>
</div>
</div>
</div>
<div class="list-content">
<div class="list-title">
<span>告警详情</span>
<img width="50%" src="@/assets/images/line_1.png" />
</div>
<div class="list">
<div class="list-wrapper">
<div class="list-item" v-for="(item, index) in sourceAcitve" :key="index + item.text">
<span class="alert-text" :class="[{ error: item.error }, { warn: item.warn }]">{{ (index + 1) *
sourceIndex }} {{ item.text }}</span>
</div>
</div>
</div>
</div>
</div>
<div class="right-bottom" style="text-align: right">
<div class="panel-title">超时工单</div>
<img style="margin: 8px 0" src="@/assets/images/title_border_line_1.png" />
<div class="tip-container">
<div class="tip-image">
<img src="@/assets/images/screen/circle_image.png" width="80" height="80" />
<span class="number">1234</span>
</div>
<img src="@/assets/images/screen/tip_bg_image.png" width="100%" height="70" />
<div class="tip-content">
<div class="col-item">
<img src="@/assets/images/screen/warning_img.png" width="23" />
<span>超时工单数</span>
<span style="font-size: 1.2rem; marker-start: 2vw; color: red;">10</span>
</div>
</div>
</div>
<div class="list-content">
<div class="list-title">
<span>工单详情</span>
<img width="50%" src="@/assets/images/line_1.png" />
</div>
<div class="list">
<div class="list-wrapper">
<div class="list-item" v-for="(item, index) in sourceAcitve" :key="index + item.text">
<span class="alert-text" :class="[{ error: item.error }, { warn: item.warn }]">{{ (index + 1) *
sourceIndex }} {{ item.text }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="center-container">
<div class="center-content">
<span class="title">隐患排查治理</span>
<img class="bottom-border-line" src="@/assets/images/title_border_line_1.png" />
<span class="sub-title">分类风险</span>
<img width="50%" src="@/assets/images/line_1.png" />
<div class="type-wrapper">
<div class="type-item">
<span class="type-btn">重大</span>
<span class="type-num">1234</span>
</div>
<div class="type-item">
<span class="type-btn active">一般</span>
<span class="type-num">1234</span>
</div>
</div>
<div class="clasic-wrapper">
<div class="clasic-item">
<span>处理进度</span>
<img width="100%" src="@/assets/images/line_1.png" />
</div>
<div class="clasic-item">
<span>Top3隐患类</span>
<img width="100%" src="@/assets/images/line_1.png" />
</div>
</div>
<div class="echart-wrapper">
<div class="lf-rt">
<div ref="progressChart" class="progress-chart"></div>
<div class="progress-legend">
<div class="legend-item"><span class="dot red"></span>已逾期</div>
<div class="legend-item"><span class="dot green"></span>已处理</div>
</div>
<div class="progress-legend">
<div class="legend-item"><span class="dot yellow"></span>待排查</div>
<div class="legend-item"><span class="dot blue"></span>处理中</div>
</div>
</div>
<div class="lf-rt">
<div ref="classicChart" class="progress-chart"></div>
<div class="progress-legend">
<div class="legend-item"><span class="dot red"></span>门禁</div>
<div class="legend-item"><span class="dot green"></span>消费</div>
<div class="legend-item"><span class="dot yellow"></span>巡检</div>
</div>
</div>
</div>
<div class="safe-wrapper">
<span class="safe-title">
<img width="22" style="margin: 3px 5px 0 0" src="@/assets/images/ybp_icon.png" />
安全指数:
</span>
<span class="pending-count">86</span>
</div>
</div>
</div>
</div>
</div>
<!-- 区域选择弹窗 -->
<RegionSelector v-model="regionSelectorVisible" v-model:modelSelected="selectedRegion" @change="onRegionChange" />
</template>
<script>
import { rgbToHex } from '@/utils/color'
import * as echarts from 'echarts'
import RegionSelector from './RegionSelector.vue'
export default {
name: 'MainScreen',
components: {
RegionSelector,
},
data () {
return {
currentTime: '',
regionSelectorVisible: false,
parkSelectorVisible: false,
selectedRegion: '',
selectedPark: '',
activeTab: '高危作业',
barChart: null,
donutChart: null,
bottomBarChart: null,
bottomPieChart: null,
source: [
// {
// text: '2024-07-10 上午8:00 雄安园区隐患内容管理 状态 处理',
// error: true
// },
// {
// text: '2025-07-09  上海XXX区域A1门禁告警  处理中  紧急',
// error: true
// },
// {
// text: '2025-07-09 上海XXX区域A1门禁告警 处理中 紧急',
// error: true
// },
// {
// text: '2020-06-18 编辑内容编辑内容编辑内容编辑内容编辑内容 状态 结果',
// warn: true
// },
// {
// text: '2020-06-18  编辑内容编辑内容编辑内容编辑内容编辑内容  状态  结果',
// warn: true
// },
// {
// text: '2020-06-18  编辑内容编辑内容编辑内容编辑内容编辑内容  状态  结果'
// }
],
sourceIndex: 1,
source1: [
// {
// text: '2025-08-10 上午8:00 武汉园区隐患内容管理 状态 处理'
// },
// {
// text: '2025-08-09  背景XXX区域A1门禁告警  处理中  紧急',
// error: true
// },
// {
// text: '2025-08-09 武汉金融港区域A1门禁告警 处理中 紧急',
// error: true
// },
// {
// text: '2020-08-18 这是编辑的内容容编辑内容 状态 结果'
// },
// {
// text: '2020-07-18  武汉光谷软件园容编辑内容  状态  结果'
// },
// {
// text: '2020-08-18  成都天府软件园A区编辑内容编辑内容  状态  结果',
// warn: true
// }
],
sourceAcitve: [],
progressChart: null,
classicChart: null,
}
},
watch: {
sourceIndex () {
console.log('sourceIndex', this.sourceIndex)
if (this.sourceIndex === 2) {
this.sourceAcitve = this.source1
} else {
this.sourceAcitve = this.source
}
}
},
created () {
this.selectedPark = this.$route.query.park
this.sourceAcitve = this.source
},
mounted () {
this.updateTime()
this.initCharts()
this.initBottomCharts() // 初始化底部图表
setInterval(this.updateTime, 1000)
this.sourceAcitve = this.source
this.timeOut1()
nextTick(() => {
this.initProgressChart()
this.initClassicChart()
})
},
methods: {
// 区域选择变更
onRegionChange (name) {
this.selectedRegion = name
this.$router.push({
path: '/screen/region',
query: { region: name }
})
},
// 返回上一级:总部
returnToHeadquarters () {
this.$router.back()
},
// 处理进度
initProgressChart () {
this.progressChart = echarts.init(this.$refs.progressChart)
const width = this.progressChart.getWidth()
const progressOption = {
series: [
{
type: 'pie',
radius: '60%',
center: ['50%', '50%'],
left: 0,
top: 0,
bottom: 0,
data: [
{ value: 20, name: 'Search Engine' },
{ value: 15, name: 'Direct' },
{ value: 30, name: 'Email' },
{ value: 25, name: 'Union Ads' },
],
// itemStyle: {
// borderColor: '#fff',
// borderWidth: 1
// },
label: {
alignTo: 'edge',
// formatter: '{time|{c} %}\n{name|{b}}',
formatter: '{time|{c} %}\n',
minMargin: 5,
edgeDistance: 10,
lineHeight: 15,
rich: {
time: {
fontSize: 10,
color: '#fff'
}
}
},
labelLine: {
length: 5,
length2: 0,
maxSurfaceAngle: 10
},
labelLayout: function (params) {
const isLeft = params.labelRect.x < width / 2;
const points = params.labelLinePoints;
points[2][0] = isLeft
? params.labelRect.x
: params.labelRect.x + params.labelRect.width;
return {
labelLinePoints: points
};
},
}
]
}
this.progressChart.setOption(progressOption)
},
// Top3隐患类
initClassicChart () {
this.classicChart = echarts.init(this.$refs.classicChart)
const width = this.classicChart.getWidth()
const progressOption = {
series: [
{
type: 'pie',
roseType: 'radius',
radius: [30, 50],
center: ['50%', '50%'],
left: 0,
top: 0,
bottom: 0,
data: [
{ value: 123, name: '门禁' },
{ value: 45, name: '消防' },
{ value: 68, name: '巡检' },
],
label: {
alignTo: 'edge',
// formatter: '{time|{c} %}\n{name|{b}}',
formatter: '{time|{c}}\n',
minMargin: 5,
edgeDistance: 10,
lineHeight: 15,
rich: {
time: {
fontSize: 10,
color: '#fff'
}
}
},
labelLine: {
length: 5,
length2: 0,
maxSurfaceAngle: 10
},
labelLayout: function (params) {
const isLeft = params.labelRect.x < width / 2;
const points = params.labelLinePoints;
points[2][0] = isLeft
? params.labelRect.x
: params.labelRect.x + params.labelRect.width;
return {
labelLinePoints: points
};
},
}
]
}
this.classicChart.setOption(progressOption)
},
timeOut1 () {
setInterval(() => {
if (this.sourceIndex === 2) {
this.sourceIndex--
} else {
this.sourceIndex++
}
}, 3000)
},
updateTime () {
const now = new Date()
const year = now.getFullYear()
const month = String(now.getMonth() + 1).padStart(2, '0')
const day = String(now.getDate()).padStart(2, '0')
const weekdays = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
const weekday = weekdays[now.getDay()]
const hours = String(now.getHours()).padStart(2, '0')
const minutes = String(now.getMinutes()).padStart(2, '0')
const seconds = String(now.getSeconds()).padStart(2, '0')
// this.currentDate = `${year}年${month}月${day}日`
// this.currentWeek = weekday
// this.currentTime = `${hours}:${minutes}:${seconds}`
this.currentTime = `${year}${month}${day}${weekday} ${hours}:${minutes}:${seconds}`
},
initCharts () {
this.initBarChart()
this.initDonutChart()
this.initProgressCharts()
},
initBarChart () {
if (this.$refs.barChart) {
this.barChart = echarts.init(this.$refs.barChart)
const option = {
legend: {
top: '10%',
right: '15%',
orient: 'vertical',
textStyle: {
color: '#ffffff',
fontSize: '11px'
}
},
grid: {
left: '5%',
right: '30%',
top: '10%',
bottom: '15%'
},
xAxis: {
type: 'category',
data: ['雄安', '北京丰台', '北京恒毅', '上海', '重庆', '成都'],
axisLabel: {
color: '#ffffff',
fontSize: 10
},
axisLine: {
lineStyle: { color: '#334155' }
}
},
yAxis: {
type: 'value',
axisLabel: {
color: '#ffffff',
fontSize: 10
},
axisLine: {
lineStyle: { color: '#334155' }
},
splitLine: {
lineStyle: { color: '#334155' }
}
},
series: [
{
name: '正式员工',
type: 'bar',
data: [320, 302, 301, 334, 390, 330],
itemStyle: { color: rgbToHex(99, 196, 251) },
barWidth: '15%'
},
{
name: '外协人员',
type: 'bar',
data: [120, 132, 101, 134, 90, 230],
itemStyle: { color: rgbToHex(251, 246, 85) },
barWidth: '15%'
},
{
name: '访客',
type: 'bar',
data: [220, 182, 191, 234, 290, 330],
itemStyle: { color: rgbToHex(200, 69, 237) },
barWidth: '15%'
}
]
}
this.barChart.setOption(option)
}
},
initDonutChart () {
if (this.$refs.donutChart) {
this.donutChart = echarts.init(this.$refs.donutChart)
const option = {
legend: {
bottom: '10%',
right: '0%',
orient: 'vertical',
textStyle: {
color: '#ffffff',
fontSize: '11px'
}
},
series: [
{
type: 'pie',
radius: ['25%', '55%'],
center: ['50%', '50%'],
title: '阿斯顿发生',
data: [
{ value: 12, name: '已逾期', itemStyle: { color: '#ef4444' } },
{ value: 234, name: '已处理', itemStyle: { color: '#10b981' } },
{ value: 34, name: '待排查', itemStyle: { color: '#eab308' } },
{ value: 134, name: '处理中', itemStyle: { color: '#3b82f6' } },
{ value: 124, name: '分类五', itemStyle: { color: '#f59e0b' } }
],
label: {
show: true,
position: 'outside',
formatter: function (params) {
return params.value + ' ' + params.percent + '%'
},
fontSize: 12,
color: '#ffffff',
fontWeight: 'bold'
},
labelLine: {
show: true,
length: 15,
length2: 10,
lineStyle: {
color: '#64748b',
width: 1
}
}
}
]
}
this.donutChart.setOption(option)
}
},
initProgressCharts () {
const progressOptions = [
{ value: 25, color: '#ef4444' },
{ value: 20, color: '#10b981' },
{ value: 15, color: '#eab308' }
]
const refs = []
const charts = []
refs.forEach((ref, index) => {
if (this.$refs[ref]) {
this[charts[index]] = echarts.init(this.$refs[ref])
const option = {
series: [
{
type: 'pie',
radius: ['60%', '80%'],
center: ['50%', '50%'],
startAngle: 90,
data: [
{
value: progressOptions[index].value,
itemStyle: { color: progressOptions[index].color }
},
{
value: 100 - progressOptions[index].value,
itemStyle: { color: 'rgba(51, 65, 85, 0.3)' }
}
],
label: { show: false },
labelLine: { show: false },
silent: true
}
]
}
this[charts[index]].setOption(option)
}
})
},
initBottomCharts () {
this.initBottomBarChart()
this.initBottomPieChart()
},
initBottomBarChart () {
if (this.$refs.bottomBarChart) {
this.bottomBarChart = echarts.init(this.$refs.bottomBarChart)
const option = {
grid: {
left: '5%',
right: '5%',
top: '15%',
bottom: '15%'
},
xAxis: {
type: 'category',
data: ['雄安', '北京丰台', '北京恒毅', '上海', '重庆', '成都'],
axisLabel: {
color: '#94a3b8',
fontSize: 10
},
axisLine: {
lineStyle: { color: '#334155' }
}
},
yAxis: {
type: 'value',
axisLabel: {
color: '#94a3b8',
fontSize: 10
},
axisLine: {
lineStyle: { color: '#334155' }
},
splitLine: {
lineStyle: { color: '#334155' }
}
},
series: [
{
name: '数据1',
type: 'bar',
data: [230, 200, 210, 220, 190, 240],
itemStyle: { color: '#3b82f6' },
barWidth: '20%'
},
{
name: '数据2',
type: 'bar',
data: [200, 180, 190, 210, 170, 220],
itemStyle: { color: '#eab308' },
barWidth: '20%'
},
{
name: '数据3',
type: 'bar',
data: [220, 210, 200, 230, 180, 250],
itemStyle: { color: '#8b5cf6' },
barWidth: '20%'
}
]
}
this.bottomBarChart.setOption(option)
}
},
initBottomPieChart () {
if (this.$refs.bottomPieChart) {
this.bottomPieChart = echarts.init(this.$refs.bottomPieChart)
const option = {
series: [
{
type: 'pie',
radius: ['40%', '70%'],
center: ['50%', '50%'],
data: [
{ value: 1234, name: '分类一', itemStyle: { color: '#3b82f6' } },
{ value: 1234, name: '分类二', itemStyle: { color: '#eab308' } },
{ value: 1234, name: '分类三', itemStyle: { color: '#8b5cf6' } },
{ value: 1234, name: '分类四', itemStyle: { color: '#10b981' } },
{ value: 1234, name: '分类五', itemStyle: { color: '#f59e0b' } }
],
label: {
show: true,
position: 'outside',
formatter: function (params) {
return params.name + ' ' + params.percent + '%'
},
fontSize: 10,
color: '#ffffff',
fontWeight: 'bold'
},
labelLine: {
show: true,
length: 10,
length2: 5,
lineStyle: {
color: '#64748b',
width: 1
}
}
}
]
}
this.bottomPieChart.setOption(option)
}
},
}
}
</script>
<style scoped lang="scss">
/* 响应式设计 - 自动适应不同屏幕尺寸 */
@media (width <=1200px) {
.dashboard-container {
.content-container {
column-gap: 4vw;
.center-container {
width: 60vh;
height: 60vh;
}
}
}
}
@media (width <=1024px) {
.dashboard-container {
.header-container {
.header-title {
font-size: 1.1rem;
}
.header-left .back-button {
min-width: 8vw;
font-size: 0.8rem;
}
.header-right {
font-size: 0.8rem;
}
}
.content-container {
column-gap: 3vw;
padding: 0 8px 15px;
.left-wrapper {
.left-top .top-card {
.top-card-left {
min-width: 18vw;
}
.top-card-right {
min-width: 25vw;
}
}
.left-bottom .donut-chart-with-labels {
width: 35vw;
height: 35vh;
}
}
.center-container {
width: 55vh;
height: 55vh;
.center-content {
.title {
font-size: 0.8rem;
}
.sub-title {
font-size: 0.7rem;
}
.type-wrapper {
width: 85%;
.type-item .type-btn {
padding: 2px 25px;
font-size: 0.65rem;
}
}
}
}
}
}
}
@media (width <=768px) {
.dashboard-container {
font-size: 0.7rem;
.header-container {
height: 70px;
.header-left {
line-height: 70px;
.back-button {
min-width: 12vw;
padding: 3px 12px;
font-size: 0.7rem;
}
}
.header-title {
font-size: 1rem;
line-height: 35px;
}
.header-right {
margin-right: 15px;
font-size: 0.7rem;
line-height: 70px;
}
}
.weather-warning {
margin-left: 5%;
font-size: 0.7rem;
line-height: 35px;
}
.content-container {
column-gap: 2vw;
padding: 0 5px 10px;
.panel-title {
margin: 3px 15px 0;
font-size: 0.7rem;
}
.left-wrapper {
.left-top .top-card {
padding: 0 15px;
column-gap: 10px;
.top-card-left {
height: 10vh;
min-width: 20vw;
.total-number {
width: 22px;
height: 40px;
font-size: 0.7rem;
line-height: 40px;
}
}
.top-card-right {
height: 10vh;
min-width: 30vw;
.top-card-right-item {
font-size: 0.65rem;
.type-number-wrapper .type-number {
width: 12px;
height: 20px;
font-size: 0.8rem;
line-height: 20px;
}
}
}
}
.left-bottom {
.tabs .tab {
padding: 1px 8px;
font-size: 0.7rem;
}
.donut-chart-with-labels {
width: 40vw;
height: 40vh;
margin-left: 1vw;
}
}
}
.right-wrapper {
.right-top,
.right-bottom {
.tip-container {
width: 80%;
height: 70px;
.tip-image img {
width: 60px;
height: 60px;
}
.tip-content .col-item {
font-size: 0.65rem;
}
}
.list-content {
width: 75%;
.list .list-item {
padding: 0.4vh 0.3vw;
font-size: 0.65rem;
}
}
}
}
.center-container {
top: 60%;
width: 50vh;
height: 50vh;
.center-content {
.title {
margin-top: 1.5vh;
font-size: 0.7rem;
}
.sub-title {
font-size: 0.65rem;
}
.type-wrapper {
width: 90%;
margin-top: 0.3vh;
.type-item {
.type-btn {
padding: 2px 20px;
font-size: 0.6rem;
}
.type-num {
font-size: 0.9rem;
}
}
}
.clasic-wrapper {
width: 90%;
margin-top: 1vh;
.clasic-item {
font-size: 0.7rem;
}
}
.echart-wrapper {
width: 90%;
.lf-rt .progress-legend .legend-item {
font-size: 0.6rem;
}
}
.safe-wrapper {
width: 50%;
.safe-title {
font-size: 0.7rem;
}
.pending-count {
font-size: 1.4rem;
}
}
}
}
}
}
}
@media (width <=480px) {
.dashboard-container {
.header-container {
height: 60px;
.header-left {
line-height: 60px;
.back-button {
min-width: 15vw;
padding: 2px 10px;
font-size: 0.65rem;
}
}
.header-title {
font-size: 0.9rem;
line-height: 30px;
}
.header-right {
margin-right: 10px;
font-size: 0.65rem;
line-height: 60px;
}
}
.weather-warning {
margin-left: 3%;
font-size: 0.65rem;
line-height: 30px;
}
.content-container {
column-gap: 1vw;
padding: 0 3px 8px;
.left-wrapper {
.left-top .top-card {
padding: 0 10px;
column-gap: 8px;
.top-card-left {
height: 8vh;
min-width: 25vw;
.total-number {
width: 18px;
height: 35px;
font-size: 0.65rem;
line-height: 35px;
}
}
.top-card-right {
height: 8vh;
min-width: 35vw;
.top-card-right-item {
font-size: 0.6rem;
.type-number-wrapper .type-number {
width: 10px;
height: 18px;
font-size: 0.7rem;
line-height: 18px;
}
}
}
}
.left-bottom .donut-chart-with-labels {
width: 45vw;
height: 45vh;
margin-left: 0.5vw;
}
}
.center-container {
top: 65%;
width: 45vh;
height: 45vh;
.center-content {
.title {
margin-top: 1vh;
font-size: 0.65rem;
}
.sub-title {
font-size: 0.6rem;
}
.type-wrapper {
width: 95%;
.type-item .type-btn {
padding: 1px 15px;
font-size: 0.55rem;
}
}
.echart-wrapper {
width: 95%;
}
.safe-wrapper {
width: 60%;
.safe-title {
font-size: 0.65rem;
}
.pending-count {
font-size: 1.2rem;
}
}
}
}
}
}
}
.dashboard-container {
position: relative;
display: flex;
width: 100vw;
height: 100vh;
font-size: 0.8rem;
color: #fff;
background: url('@/assets/images/v2_rel0n6.png');
background-color: #030e22;
background-size: cover;
flex-direction: column;
}
.dot {
width: 6px;
height: 6px;
border-radius: 50%;
}
.dot.red {
background-color: #ef4444;
}
.dot.green {
background-color: #10b981;
}
.dot.yellow {
background-color: #eab308;
}
.dot.blue {
background-color: #3b82f6;
}
.dot.cyan {
background-color: #06b6d4;
}
.dot.purple {
background-color: #8b5cf6;
}
.dot.orange {
background-color: #f59e0b;
}
.header-container {
display: flex;
height: 80px;
background: url('@/assets/images/top_bg.png') no-repeat;
background-size: 100%;
.header-left {
display: flex;
padding-left: 1vw;
line-height: 80px;
flex: 1;
align-items: center;
.back-img {
height: 3vh;
cursor: pointer;
transition: all 0.3s ease;
}
.back-button {
display: inline-flex;
height: 2vh;
min-width: 6vw;
padding: 4px 16px;
margin-left: 0.5vw;
font-size: 0.9rem;
cursor: pointer;
background: rgb(13 24 84 / 80%);
border: 1px solid rgb(59 130 246 / 40%);
transition: all 0.3s ease;
align-items: center;
justify-content: space-between;
}
.back-button:hover {
background: rgb(59 130 246 / 30%);
border-color: rgb(59 130 246 / 60%);
}
}
.header-right {
margin-right: 20px;
font-size: 0.9rem;
line-height: 80px;
text-align: right;
flex: 1;
}
.header-title {
font-size: 1.3rem;
font-weight: bold;
line-height: 40px;
color: #fff;
text-align: center;
flex: 1;
}
}
.weather-warning {
margin-left: 10%;
line-height: 45px;
}
.content-container {
position: relative;
display: flex;
width: calc(100vw - 20px);
height: calc(100vh - 105px);
padding: 0 10px 20px;
column-gap: 7vw;
.panel-title {
margin: 4px 20px 0;
font-size: 0.8rem;
font-weight: bold;
color: #fff;
}
.bottom-card {
display: flex;
flex-direction: column;
.bottom-card-title {
display: flex;
margin-top: 5px;
margin-left: -15%;
flex-direction: column;
align-items: center;
}
.bar-chart {
flex: 1;
width: 80%;
min-height: 17.5vh;
}
}
.left-wrapper {
flex: 1;
display: flex;
flex-direction: column;
row-gap: 1rem;
height: 100%;
.left-top {
padding: 0 5px;
background-image:
url('@/assets/images/screen/left_top_img.png'),
url('@/assets/images/screen/left_center_img.png'),
url('@/assets/images/screen/left_bottom_img.png');
background-position:
top center,
left center,
bottom center;
/* 设置大小,注意中间的背景图应该覆盖整个容器 */
background-repeat: no-repeat, no-repeat, no-repeat;
/* 设置位置 */
background-size:
100% 90px,
cover,
100% 68px;
flex: 1;
/* 设置重复方式 */
.top-card {
display: flex;
padding: 0 20px;
column-gap: 15px;
font-size: 0.8rem;
.top-card-left {
display: flex;
height: 12vh;
min-width: 15vw;
padding: 0 10px;
background-image: url('@/assets/imgs/total_count_card_bg.png');
background-size: cover;
column-gap: 6px;
align-items: center;
.number-wrapper {
display: flex;
align-items: center;
gap: 2px;
font-size: 0.8rem;
color: #fff;
}
.total-number {
display: inline-block;
width: 26px;
height: 50px;
font-size: 0.8rem;
line-height: 50px;
color: #fff;
text-align: center;
background-color: rgb(177 74 201 / 100%);
border-radius: 4px;
}
}
.top-card-right {
display: flex;
height: 12vh;
min-width: 20vw;
background-image: url('@/assets/imgs/staff_types_bg.png');
background-position: top center;
background-size: cover;
flex-direction: column;
justify-content: center;
row-gap: 4px;
.top-card-right-item {
display: flex;
align-items: center;
column-gap: 5px;
padding: 0 10px;
font-size: 0.7rem;
color: #fff;
.type-number-wrapper {
display: flex;
align-items: center;
gap: 2px;
font-size: 0.8rem;
color: #fff;
.type-number {
display: inline-block;
width: 14px;
height: 25px;
font-size: 0.9rem;
line-height: 25px;
color: #fff;
text-align: center;
background-color: #1afb8f;
border-radius: 2px;
}
}
}
}
}
}
.left-bottom {
background-image:
url('@/assets/images/screen/left_top_2_img.png'),
url('@/assets/images/screen/left_center_img.png'),
url('@/assets/images/screen/left_bottom_img.png');
background-position:
top center,
left center,
bottom center;
/* 设置大小,注意中间的背景图应该覆盖整个容器 */
background-repeat: no-repeat, no-repeat, no-repeat;
/* 设置位置 */
background-size:
100% 90px,
cover,
100% 68px;
flex: 1;
/* 设置重复方式 */
.tabs {
display: inline-flex;
align-items: center;
column-gap: 8px;
}
.tab {
padding: 2px 10px;
color: #fff;
cursor: pointer;
border-radius: 4px;
transition: all 0.2s ease-in-out;
user-select: none;
}
.tab:hover {
color: #1afb8f;
}
.tab.active {
color: #1afb8f;
background: rgb(26 251 143 / 12%);
border: 1px solid rgb(26 251 143 / 35%);
}
.divider {
margin: 0 2px;
color: #94a3b8;
}
.donut-chart-with-labels {
width: 30vw;
height: 30vh;
margin-left: 2vw;
}
}
}
.right-wrapper {
display: flex;
height: 100%;
flex: 1;
flex-direction: column;
row-gap: 1rem;
.right-top {
/* 设置重复方式 */
display: flex;
background-image:
url('@/assets/images/screen/right_top_img.png'),
url('@/assets/images/screen/right_center_img.png'),
url('@/assets/images/screen/right_bottom_img.png');
background-position:
top center,
right center,
bottom center;
/* 设置大小,注意中间的背景图应该覆盖整个容器 */
background-repeat: no-repeat, no-repeat, no-repeat;
/* 设置位置 */
background-size:
100% 90px,
cover,
100% 68px;
flex: 1;
flex-direction: column;
align-items: flex-end;
.tip-container {
position: relative;
display: flex;
width: 70%;
height: 80px;
padding-right: 20px;
align-items: center;
justify-content: end;
.tip-image {
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%) translateX(-50%);
.number {
position: absolute;
top: 50%;
left: 50%;
font-size: 1rem;
color: #fff;
transform: translate(-80%, -50%);
}
}
.tip-content {
position: absolute;
inset: 0% 0 0 6%;
display: flex;
padding-left: 20px;
align-items: center;
.col-item {
display: flex;
margin-left: 1vw;
align-items: center;
span {
margin-right: 10px;
}
}
}
}
.list-content {
display: flex;
width: 68%;
height: calc(100% - 100px);
margin-top: 20px;
flex-direction: column;
align-items: flex-end;
.list-title {
display: flex;
flex-direction: column;
align-items: center;
}
.list {
display: flex;
width: 100%;
max-height: 22vh;
flex: 1;
flex-direction: column;
align-items: center;
.list-wrapper {
display: flex;
width: 100%;
height: 100%;
margin-top: 10px;
overflow: hidden scroll;
flex-direction: column;
row-gap: 4px;
}
.list-item {
display: inline-flex;
padding: 0.5vh 0.4vw;
font-size: 0.75rem;
background: rgb(51 65 85 / 30%);
border: 1px solid #1e40af;
border-radius: 0.37vh;
align-items: center;
justify-content: center;
.alert-text.error {
color: #f00;
}
.alert-text.warn {
color: #ff0;
}
}
}
}
}
.right-bottom {
/* 设置重复方式 */
display: flex;
background-image:
url('@/assets/images/screen/right_top_img.png'),
url('@/assets/images/screen/right_center_img.png'),
url('@/assets/images/screen/right_bottom_img.png');
background-position:
top center,
right center,
bottom center;
/* 设置大小,注意中间的背景图应该覆盖整个容器 */
background-repeat: no-repeat, no-repeat, no-repeat;
/* 设置位置 */
background-size:
100% 90px,
cover,
100% 68px;
flex: 1;
flex-direction: column;
align-items: flex-end;
.tip-container {
position: relative;
display: flex;
width: 50%;
height: 80px;
padding-right: 20px;
align-items: center;
justify-content: end;
.tip-image {
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%) translateX(-50%);
.number {
position: absolute;
top: 50%;
left: 50%;
font-size: 1rem;
color: #fff;
transform: translate(-80%, -50%);
}
}
.tip-content {
position: absolute;
inset: 0% 0 0 6%;
display: flex;
padding-left: 20px;
align-items: center;
.col-item {
display: flex;
margin-left: 1vw;
align-items: center;
span {
margin-right: 10px;
}
}
}
}
.list-content {
display: flex;
width: 68%;
height: calc(100% - 100px);
margin-top: 20px;
flex-direction: column;
align-items: flex-end;
.list-title {
display: flex;
flex-direction: column;
align-items: center;
}
.list {
display: flex;
width: 100%;
max-height: 22vh;
flex: 1;
flex-direction: column;
align-items: center;
.list-wrapper {
display: flex;
width: 100%;
height: 100%;
margin-top: 10px;
overflow: hidden scroll;
flex-direction: column;
row-gap: 4px;
}
.list-item {
display: inline-flex;
padding: 0.5vh 0.4vw;
font-size: 0.75rem;
background: rgb(51 65 85 / 30%);
border: 1px solid #1e40af;
border-radius: 0.37vh;
align-items: center;
justify-content: center;
.alert-text.error {
color: #f00;
}
.alert-text.warn {
color: #ff0;
}
}
}
}
}
}
.center-container {
position: fixed;
top: 55%;
left: 50%;
z-index: 1;
display: flex;
width: 65vh;
height: 65vh;
color: #fff;
background-image: url('@/assets/images/circle_bg.png');
background-size: cover;
transform: translate(-50%, -50%);
align-items: center;
justify-content: center;
.center-content {
display: flex;
// background: rgba(255, 22, 1, 0.3);
width: 77%;
height: 77%;
overflow: hidden;
border-radius: 50%;
align-items: center;
flex-direction: column;
.title {
margin-top: 2vh;
font-size: 0.9rem;
font-weight: bold;
}
.bottom-border-line {
width: 20%;
margin: 1vh 0 1.2vh;
}
.sub-title {
font-size: 0.8rem;
}
.type-wrapper {
display: flex;
justify-content: space-around;
width: 80%;
font-size: 0.8rem;
color: #fff;
.type-item {
display: flex;
flex-direction: column;
align-items: center;
margin-top: 0.5vh;
.type-btn {
padding: 2px 30px;
margin-bottom: 5px;
font-size: 0.7rem;
background-color: #d97706;
border-radius: 15px;
&.active {
background-color: #059669;
}
}
.type-num {
font-size: 1rem;
}
}
}
.clasic-wrapper {
display: flex;
width: 80%;
margin-top: 1.2vh;
font-size: 0.8rem;
color: #fff;
justify-content: space-around;
.clasic-item {
display: flex;
width: 45%;
margin-top: 0.6vh;
margin-bottom: -1vh;
flex-direction: column;
align-items: center;
img {
width: 100%;
height: 2px;
}
}
}
.echart-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
width: 85%;
height: 75%;
.lf-rt {
display: flex;
width: 50%;
height: 100%;
flex-direction: column;
.progress-chart {
display: flex;
width: 100%;
height: 80%;
align-items: center;
justify-content: center;
}
.progress-legend {
display: flex;
justify-content: center;
gap: 8px;
.legend-item {
display: flex;
align-items: center;
gap: 4px;
font-size: 0.7rem;
}
}
}
}
.safe-wrapper {
display: flex;
width: 40%;
height: 20%;
margin-bottom: 5%;
align-items: center;
column-gap: 1vw;
.safe-title {
display: flex;
align-items: center;
margin-left: 1vw;
}
.pending-count {
margin-bottom: 0.7vh;
font-size: 1.6rem;
font-weight: 500;
color: yellow;
}
}
}
}
}
/* 全局样式 */
</style>