2 changed files with 955 additions and 0 deletions
@ -0,0 +1,946 @@ |
|||
<template> |
|||
<div class="enforcement-record app_content"> |
|||
<!-- 步骤条导航 - 固定在顶部 --> |
|||
<div class="step-nav" :class="{ 'step-nav-fixed': isNavFixed }"> |
|||
<div class="step-nav-inner"> |
|||
<div v-for="(step, index) in steps" :key="step.id" class="step-item" |
|||
:class="{ active: activeStep === index }" @click="scrollToSection(step.id, index)"> |
|||
<div class="step-dot"></div> |
|||
<span class="step-label">{{ step.label }}</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 内容区域 --> |
|||
<div class="content-area" ref="contentRef"> |
|||
<!-- 通知栏 --> |
|||
<!-- 执法概览统计卡片 --> |
|||
<div class="overview-cards" id="section-overview"> |
|||
<!-- 标题 --> |
|||
<div class="overview-title">执法概览</div> |
|||
|
|||
<!-- 第一行:三列统计 --> |
|||
<div class="stats-row three-col"> |
|||
<div class="stat-item"> |
|||
<div class="stat-value">89.5万</div> |
|||
<div class="stat-label">企业总数</div> |
|||
</div> |
|||
<div class="stat-item"> |
|||
<div class="stat-value">3.75万次</div> |
|||
<div class="stat-label">单独执法</div> |
|||
</div> |
|||
<div class="stat-item"> |
|||
<div class="stat-value">6,563次</div> |
|||
<div class="stat-label">联合执法</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 第二行:两列统计 --> |
|||
<div class="stats-row two-col"> |
|||
<div class="stat-item"> |
|||
<div class="stat-value">89.5万</div> |
|||
<div class="stat-label">被执法企业</div> |
|||
</div> |
|||
<div class="stat-item"> |
|||
<div class="stat-value">89.5%</div> |
|||
<div class="stat-label">入企压减率</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- Tab切换栏:执法维度 --> |
|||
<van-tabs v-model:active="overviewTab" color="#2563eb" title-active-color="#2563eb" |
|||
title-inactive-color="#666" swipeable animated line-width="20px" line-height="2px"> |
|||
<van-tab title="执法力量"></van-tab> |
|||
<van-tab title="执法力度"></van-tab> |
|||
<van-tab title="执法频次"></van-tab> |
|||
<van-tab title="执法效率"></van-tab> |
|||
<van-tab title="执法结果"></van-tab> |
|||
</van-tabs> |
|||
|
|||
<!-- 执法力量 --> |
|||
<div v-if="overviewTab === 0" class="tab-content-cards"> |
|||
<div class="large-card"> |
|||
<div class="large-card-value">100家</div> |
|||
<div class="large-card-label">执法单位数</div> |
|||
</div> |
|||
<div class="large-card"> |
|||
<div class="large-card-value">5000名</div> |
|||
<div class="large-card-label">执法人员数</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 执法力度图表 --> |
|||
<div v-if="overviewTab === 1" class="force-chart-wrapper"> |
|||
<div class="force-chart" ref="forceChartRef"></div> |
|||
<div class="force-legend"> |
|||
<div v-for="(item, index) in forceChartData" :key="index" class="fl-item"> |
|||
<span class="fl-dot" :style="{ background: item.color }"></span> |
|||
<span class="fl-name">{{ item.name }}</span> |
|||
<span class="fl-value">{{ item.value }}次</span> |
|||
<span class="fl-percent">{{ item.percent }}%</span> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 执法频次 --> |
|||
<div v-if="overviewTab === 2" class="tab-content-cards"> |
|||
<div class="large-card"> |
|||
<div class="large-card-value">3<span class="large-card-unit">次/天</span></div> |
|||
<div class="large-card-label">涉企检查频次</div> |
|||
</div> |
|||
<div class="large-card"> |
|||
<div class="large-card-value">68<span class="large-card-unit">%</span></div> |
|||
<div class="large-card-label">重复检查率</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 执法效率 --> |
|||
<div v-if="overviewTab === 3" class="tab-content-cards"> |
|||
<div class="large-card"> |
|||
<div class="large-card-value">10<span class="large-card-unit">小时</span></div> |
|||
<div class="large-card-label">涉企行政处罚案件平均办理时长</div> |
|||
</div> |
|||
<div class="large-card"> |
|||
<div class="large-card-value">68<span class="large-card-unit">%</span></div> |
|||
<div class="large-card-label">执法案件按时办结率</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 执法结果 --> |
|||
<div v-if="overviewTab === 4" class="tab-content-cards"> |
|||
<div class="large-card"> |
|||
<div class="large-card-value">10<span class="large-card-unit">小时</span></div> |
|||
<div class="large-card-label">行政处罚撤销率</div> |
|||
</div> |
|||
<div class="large-card"> |
|||
<div class="large-card-value">68<span class="large-card-unit">%</span></div> |
|||
<div class="large-card-label">行政处罚变更率</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 执法监管 --> |
|||
<div class="supervision-section" id="section-supervision"> |
|||
<div class="section-title">执法监管</div> |
|||
<div class="supervision-grid"> |
|||
<div class="supervision-item"> |
|||
<div class="sv-value">200<span class="sv-unit">条</span></div> |
|||
<div class="sv-label">计划总数</div> |
|||
</div> |
|||
<div class="supervision-item"> |
|||
<div class="sv-value">200<span class="sv-unit">条</span></div> |
|||
<div class="sv-label">预告总数</div> |
|||
</div> |
|||
<div class="supervision-item"> |
|||
<div class="sv-value">498<span class="sv-unit">条</span></div> |
|||
<div class="sv-label">涉企执法总数</div> |
|||
</div> |
|||
<div class="supervision-item"> |
|||
<div class="sv-value">89<span class="sv-unit">条</span></div> |
|||
<div class="sv-label">检查评价总数</div> |
|||
</div> |
|||
<div class="supervision-item"> |
|||
<div class="sv-value">4<span class="sv-unit">条</span></div> |
|||
<div class="sv-label">检查投诉总数</div> |
|||
</div> |
|||
<div class="supervision-item"> |
|||
<div class="sv-value">89<span class="sv-unit">次</span></div> |
|||
<div class="sv-label">职权使用数</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 预警态势 --> |
|||
<div class="warning-section" id="section-warning"> |
|||
<div class="section-title">预警态势</div> |
|||
|
|||
<!-- 第一行:两列统计 --> |
|||
<div class="warning-grid"> |
|||
<div class="warning-item"> |
|||
<div class="sv-value">89<span class="sv-unit">条</span></div> |
|||
<div class="sv-label">风险信用预警</div> |
|||
</div> |
|||
<div class="warning-item"> |
|||
<div class="sv-value">95<span class="sv-unit">条</span></div> |
|||
<div class="sv-label">高额检查预警</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- 第二行:两列 + 中间竖线分隔 --> |
|||
<div class="warning-grid warning-grid-divider"> |
|||
<div class="warning-item"> |
|||
<div class="sv-value">87<span class="sv-unit">人</span></div> |
|||
<div class="sv-label">异常人员</div> |
|||
</div> |
|||
<div class="warning-divider"></div> |
|||
<div class="warning-item"> |
|||
<div class="sv-value">68<span class="sv-unit">次</span></div> |
|||
<div class="sv-label">异常行为数</div> |
|||
</div> |
|||
</div> |
|||
|
|||
<!-- Tab切换:各区域/各领域 --> |
|||
<van-tabs v-model:active="warningTab" color="#2563eb" title-active-color="#2563eb" |
|||
title-inactive-color="#666" swipeable animated line-width="20px"> |
|||
<van-tab title="各区风险态势感知"></van-tab> |
|||
<van-tab title="各领域风险态势感知"></van-tab> |
|||
</van-tabs> |
|||
|
|||
<!-- 各区表格 --> |
|||
<div class="warning-table-wrapper"> |
|||
<table class="warning-table"> |
|||
<tbody> |
|||
<tr v-for="(row, index) in currentTableData" :key="index"> |
|||
<td class="wt-name">{{ row.name }}</td> |
|||
<td v-for="(status, idx) in row.statuses" :key="idx" :class="'wt-cell wt-' + status">{{ |
|||
status }}</td> |
|||
</tr> |
|||
<!-- 时间轴作为最后一行 --> |
|||
<tr class="wt-timeline-row"> |
|||
<td class="wt-name"></td> |
|||
<td v-for="(item, idx) in warningTimeline" :key="idx" class="wt-time-cell">{{ item }} |
|||
</td> |
|||
</tr> |
|||
</tbody> |
|||
</table> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</template> |
|||
|
|||
<script setup name="enforcementRecord"> |
|||
import { ref, reactive, computed, watch, nextTick, onMounted, onUnmounted } from 'vue'; |
|||
import * as echarts from 'echarts'; |
|||
|
|||
const activeTab = ref(0); |
|||
const overviewTab = ref(0); |
|||
const warningTab = ref(0); |
|||
const activeStep = ref(0); |
|||
const isNavFixed = ref(false); |
|||
const contentRef = ref(null); |
|||
const forceChartRef = ref(null); |
|||
let forceChartInstance = null; |
|||
|
|||
// 执法力度图表数据 |
|||
const forceChartData = [ |
|||
{ name: '行政检查', value: 30, percent: 50, color: '#5b8ff9' }, |
|||
{ name: '行政处罚', value: 9, percent: 15, color: '#5ad8a6' }, |
|||
{ name: '行政强制', value: 9, percent: 15, color: '#5d7092' }, |
|||
{ name: '其他', value: 6, percent: 10, color: '#f6bd16' }, |
|||
]; |
|||
|
|||
// 执法频次数据 |
|||
const frequencyData = ref([ |
|||
{ value: 1200, unit: '次', label: '年度执法总次数' }, |
|||
{ value: 98.5, unit: '%', label: '计划完成率' }, |
|||
{ value: 320, unit: '次', label: '月均执法次数' }, |
|||
{ value: 45, unit: '家', label: '重点企业检查数' }, |
|||
]); |
|||
|
|||
// 执法效率数据 |
|||
const efficiencyData = ref([ |
|||
{ value: 2.3, unit: '小时', label: '平均响应时间' }, |
|||
{ value: 96.2, unit: '%', label: '按时办结率' }, |
|||
{ value: 4.5, unit: '天', label: '平均结案周期' }, |
|||
{ value: 99.1, unit: '%', label: '合规率' }, |
|||
]); |
|||
|
|||
// 执法结果数据 |
|||
const resultData = ref([ |
|||
{ value: 156, unit: '件', label: '立案总数' }, |
|||
{ value: 142, unit: '件', label: '已结案数' }, |
|||
{ value: 91.0, unit: '%', label: '结案率' }, |
|||
{ value: 28, unit: '万元', label: '罚没金额' }, |
|||
]); |
|||
|
|||
// 渲染执法力度饼图 |
|||
const renderForceChart = () => { |
|||
if (!forceChartRef.value) return; |
|||
if (forceChartInstance) { |
|||
forceChartInstance.dispose(); |
|||
forceChartInstance = null; |
|||
} |
|||
forceChartInstance = echarts.init(forceChartRef.value); |
|||
const option = { |
|||
series: [{ |
|||
type: 'pie', |
|||
radius: ['45%', '70%'], |
|||
center: ['50%', '50%'], |
|||
avoidLabelOverlap: false, |
|||
label: { |
|||
show: true, |
|||
position: 'center', |
|||
formatter: '{value|250次}\n{label|合计}', |
|||
rich: { |
|||
value: { fontSize: 20, fontWeight: 'bold', color: '#333', lineHeight: 28 }, |
|||
label: { fontSize: 12, color: '#999', lineHeight: 18 }, |
|||
}, |
|||
}, |
|||
data: forceChartData.map(item => ({ value: item.value, itemStyle: { color: item.color } })), |
|||
}], |
|||
}; |
|||
forceChartInstance.setOption(option); |
|||
}; |
|||
|
|||
// 监听 Tab 切换 |
|||
watch(overviewTab, (val) => { |
|||
if (val === 1) { |
|||
nextTick(() => renderForceChart()); |
|||
} else if (forceChartInstance) { |
|||
forceChartInstance.dispose(); |
|||
forceChartInstance = null; |
|||
} |
|||
}); |
|||
|
|||
// 步骤条配置 |
|||
const steps = [ |
|||
{ id: 'section-overview', label: '执法概览' }, |
|||
{ id: 'section-supervision', label: '执法监管' }, |
|||
{ id: 'section-warning', label: '预警态势' }, |
|||
]; |
|||
|
|||
let observer = null; |
|||
|
|||
// 点击步骤跳转到对应区域 |
|||
const scrollToSection = (id, index) => { |
|||
// 立即设置高亮,不等滚动完成 |
|||
activeStep.value = index; |
|||
|
|||
const el = document.getElementById(id); |
|||
const container = contentRef.value; |
|||
if (el && container) { |
|||
const navHeight = 10; |
|||
const offsetTop = el.offsetTop - navHeight; |
|||
container.scrollTo({ top: offsetTop, behavior: 'smooth' }); |
|||
} |
|||
}; |
|||
|
|||
// 滚动监听:检测当前可见区域,点亮对应步骤 |
|||
const handleScroll = () => { |
|||
const container = contentRef.value; |
|||
if (!container) return; |
|||
|
|||
const scrollTop = container.scrollTop; |
|||
isNavFixed.value = scrollTop > 0; |
|||
|
|||
// 检测各区域位置 |
|||
const navHeight = 50; |
|||
for (let i = 0; i < steps.length; i++) { |
|||
const section = document.getElementById(steps[i].id); |
|||
if (!section) continue; |
|||
const rect = section.getBoundingClientRect(); |
|||
if (rect.top <= navHeight + 30) { |
|||
activeStep.value = i; |
|||
} |
|||
} |
|||
|
|||
// 如果滚回顶部,重置为第一个 |
|||
if (scrollTop <= 10) { |
|||
activeStep.value = 0; |
|||
} |
|||
}; |
|||
|
|||
onMounted(() => { |
|||
const container = contentRef.value; |
|||
if (container) { |
|||
container.addEventListener('scroll', handleScroll, { passive: true }); |
|||
} |
|||
}); |
|||
|
|||
onUnmounted(() => { |
|||
const container = contentRef.value; |
|||
if (container) { |
|||
container.removeEventListener('scroll', handleScroll); |
|||
} |
|||
if (observer) observer.disconnect(); |
|||
}); |
|||
|
|||
// 预警态势表格数据 |
|||
// 预警态势时间轴 |
|||
const warningTimeline = ref(['2025Q2', '2025Q3', '2025Q4', '2026Q1']); |
|||
|
|||
// 各区数据 |
|||
const warningTableData = ref([ |
|||
{ name: '福田区', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '罗湖区', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '盐田区', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '南山区', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '宝安区', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '龙岗区', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '龙华区', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '坪山区', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '光明区', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '大鹏新区', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '深汕特别合作区', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
]); |
|||
|
|||
// 各领域数据 |
|||
const fieldTableData = ref([ |
|||
{ name: '应急管理局', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '消防救援', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '住建和建设局', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '生态环境局', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '卫生健康委员会', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '交通运输委员会', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '市场监督管理局', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '城市管理和综合执法局', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
{ name: '消防救援支队', statuses: ['一般', '良好', '优良', '优良'] }, |
|||
]); |
|||
|
|||
// 根据 Tab 切换数据源 |
|||
const currentTableData = computed(() => { |
|||
return warningTab.value === 0 ? warningTableData.value : fieldTableData.value; |
|||
}); |
|||
</script> |
|||
|
|||
<style lang="less" scoped> |
|||
.enforcement-record { |
|||
display: flex; |
|||
flex-direction: column; |
|||
height: 100%; |
|||
overflow: hidden; |
|||
background: #f0f6ff; |
|||
font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', sans-serif; |
|||
} |
|||
|
|||
/* ===== 顶部蓝色背景区域 ===== */ |
|||
.header-bg { |
|||
background: linear-gradient(135deg, #1a4f8e 0%, #2563eb 50%, #3b82f6 100%); |
|||
padding: 30px 20px 20px; |
|||
position: relative; |
|||
overflow: hidden; |
|||
|
|||
&::after { |
|||
content: ''; |
|||
position: absolute; |
|||
right: -60px; |
|||
top: -60px; |
|||
width: 200px; |
|||
height: 200px; |
|||
border-radius: 50%; |
|||
background: rgba(255, 255, 255, 0.06); |
|||
} |
|||
|
|||
&::before { |
|||
content: ''; |
|||
position: absolute; |
|||
left: -40px; |
|||
bottom: -40px; |
|||
width: 150px; |
|||
height: 150px; |
|||
border-radius: 50%; |
|||
background: rgba(255, 255, 255, 0.04); |
|||
} |
|||
} |
|||
|
|||
.header-content { |
|||
position: relative; |
|||
z-index: 1; |
|||
} |
|||
|
|||
.header-title { |
|||
font-size: 28px; |
|||
font-weight: 700; |
|||
color: #fff; |
|||
letter-spacing: 2px; |
|||
} |
|||
|
|||
.header-subtitle { |
|||
font-size: 13px; |
|||
color: rgba(255, 255, 255, 0.75); |
|||
margin-top: 6px; |
|||
letter-spacing: 4px; |
|||
} |
|||
|
|||
/* ===== 步骤条导航 ===== */ |
|||
.step-nav { |
|||
position: sticky; |
|||
top: 0; |
|||
z-index: 100; |
|||
background: #fff; |
|||
transition: box-shadow 0.2s; |
|||
|
|||
&.step-nav-fixed { |
|||
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08); |
|||
} |
|||
} |
|||
|
|||
.step-nav-inner { |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
padding: 10px 16px; |
|||
position: relative; |
|||
|
|||
/* 虚线连接线 */ |
|||
&::before { |
|||
content: ''; |
|||
position: absolute; |
|||
left: 20%; |
|||
right: 20%; |
|||
top: 50%; |
|||
height: 1px; |
|||
background-image: linear-gradient(to right, #d1d5db 50%, transparent 50%); |
|||
background-size: 8px 1px; |
|||
background-repeat: repeat-x; |
|||
z-index: 0; |
|||
} |
|||
} |
|||
|
|||
.step-item { |
|||
display: flex; |
|||
flex-direction: column; |
|||
align-items: center; |
|||
gap: 4px; |
|||
cursor: pointer; |
|||
padding: 0 20px; |
|||
position: relative; |
|||
z-index: 1; |
|||
flex: 1; |
|||
max-width: 120px; |
|||
transition: all 0.3s ease; |
|||
|
|||
.step-dot { |
|||
width: 14px; |
|||
height: 14px; |
|||
border-radius: 50%; |
|||
border: 2px solid #d1d5db; |
|||
background: #fff; |
|||
transition: all 0.3s ease; |
|||
position: relative; |
|||
|
|||
&::after { |
|||
content: ''; |
|||
position: absolute; |
|||
top: 50%; |
|||
left: 50%; |
|||
transform: translate(-50%, -50%) scale(0); |
|||
width: 6px; |
|||
height: 6px; |
|||
border-radius: 50%; |
|||
background: #2563eb; |
|||
transition: transform 0.3s ease; |
|||
} |
|||
} |
|||
|
|||
.step-label { |
|||
font-size: 13px; |
|||
color: #999; |
|||
font-weight: 400; |
|||
white-space: nowrap; |
|||
transition: color 0.3s ease; |
|||
} |
|||
|
|||
&.active { |
|||
.step-dot { |
|||
border-color: #2563eb; |
|||
background: #fff; |
|||
|
|||
&::after { |
|||
transform: translate(-50%, -50%) scale(1); |
|||
} |
|||
} |
|||
|
|||
.step-label { |
|||
color: #2563eb; |
|||
font-weight: 600; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* ===== 内容区域 ===== */ |
|||
.content-area { |
|||
position: relative; |
|||
z-index: 2; |
|||
flex: 1; |
|||
overflow-y: auto; |
|||
} |
|||
|
|||
/* 概览卡片 */ |
|||
.overview-cards { |
|||
display: flex; |
|||
flex-direction: column; |
|||
gap: 10px; |
|||
margin-bottom: 14px; |
|||
background-color: #fff; |
|||
padding: 16px 16px; |
|||
} |
|||
|
|||
/* 执法概览标题 */ |
|||
.overview-title { |
|||
font-size: 16px; |
|||
font-weight: 700; |
|||
color: #1a1a1a; |
|||
padding-left: 12px; |
|||
border-left: 3px solid #2563eb; |
|||
line-height: 1; |
|||
margin-bottom: 12px; |
|||
} |
|||
|
|||
/* 统计行 */ |
|||
.stats-row { |
|||
display: flex; |
|||
gap: 10px; |
|||
|
|||
&.three-col { |
|||
.stat-item { |
|||
flex: 1; |
|||
} |
|||
} |
|||
|
|||
&.two-col { |
|||
.stat-item { |
|||
flex: 1; |
|||
} |
|||
} |
|||
|
|||
.stat-item { |
|||
background: #f0f6ff; |
|||
border-radius: 8px; |
|||
padding: 14px 10px; |
|||
text-align: center; |
|||
|
|||
.stat-value { |
|||
font-size: 20px; |
|||
font-weight: 700; |
|||
color: #2563eb; |
|||
line-height: 1.3; |
|||
} |
|||
|
|||
.stat-label { |
|||
font-size: 12px; |
|||
color: #666; |
|||
margin-top: 4px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* 概览区Tab样式覆盖 */ |
|||
.overview-cards { |
|||
:deep(.van-tabs__nav) { |
|||
background: transparent !important; |
|||
} |
|||
|
|||
:deep(.van-tab) { |
|||
font-size: 12px; |
|||
padding: 0 8px; |
|||
} |
|||
|
|||
:deep(.van-tabs__line) { |
|||
width: 20px !important; |
|||
height: 2px !important; |
|||
background-color: #2563eb; |
|||
border-radius: 0; |
|||
} |
|||
} |
|||
|
|||
/* 执法力度图表 */ |
|||
.force-chart-wrapper { |
|||
display: flex; |
|||
align-items: center; |
|||
padding: 16px 12px; |
|||
background: #fff; |
|||
|
|||
.force-chart { |
|||
width: 150px; |
|||
height: 150px; |
|||
flex-shrink: 0; |
|||
} |
|||
|
|||
.force-legend { |
|||
flex: 1; |
|||
display: flex; |
|||
flex-direction: column; |
|||
gap: 10px; |
|||
padding-left: 8px; |
|||
} |
|||
|
|||
.fl-item { |
|||
display: flex; |
|||
align-items: center; |
|||
font-size: 13px; |
|||
} |
|||
|
|||
.fl-dot { |
|||
width: 10px; |
|||
height: 10px; |
|||
border-radius: 50%; |
|||
margin-right: 6px; |
|||
flex-shrink: 0; |
|||
} |
|||
|
|||
.fl-name { |
|||
color: #333; |
|||
width: 60px; |
|||
flex-shrink: 0; |
|||
} |
|||
|
|||
.fl-value { |
|||
color: #333; |
|||
width: 40px; |
|||
text-align: right; |
|||
flex-shrink: 0; |
|||
} |
|||
|
|||
.fl-percent { |
|||
color: #999; |
|||
width: 36px; |
|||
text-align: right; |
|||
flex-shrink: 0; |
|||
} |
|||
} |
|||
|
|||
/* Tab内容区 */ |
|||
.tab-content-cards { |
|||
display: flex; |
|||
flex-direction: column; |
|||
gap: 10px; |
|||
padding: 8px 0; |
|||
|
|||
.large-card { |
|||
width: 100%; |
|||
margin: 0; |
|||
box-sizing: border-box; |
|||
} |
|||
} |
|||
|
|||
.tab-content-grid { |
|||
display: grid; |
|||
grid-template-columns: repeat(2, 1fr); |
|||
gap: 10px; |
|||
padding: 8px 0; |
|||
|
|||
.stat-card-sm { |
|||
background: #f5f9ff; |
|||
border-radius: 8px; |
|||
padding: 14px 16px; |
|||
text-align: center; |
|||
|
|||
.sc-value { |
|||
font-size: 20px; |
|||
font-weight: 700; |
|||
color: #2563eb; |
|||
|
|||
.sc-unit { |
|||
font-size: 13px; |
|||
font-weight: 400; |
|||
color: #666; |
|||
} |
|||
} |
|||
|
|||
.sc-label { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin-top: 4px; |
|||
} |
|||
} |
|||
} |
|||
|
|||
/* 大卡片 */ |
|||
.large-card { |
|||
background: #f5f9ff; |
|||
border-radius: 8px; |
|||
padding: 18px 16px; |
|||
text-align: center; |
|||
|
|||
.large-card-value { |
|||
font-size: 22px; |
|||
font-weight: 700; |
|||
color: #2563eb; |
|||
line-height: 1.3; |
|||
} |
|||
|
|||
.large-card-label { |
|||
font-size: 13px; |
|||
color: #666; |
|||
margin-top: 4px; |
|||
} |
|||
} |
|||
|
|||
/* ===== 通用区块标题 ===== */ |
|||
.section-title { |
|||
font-size: 16px; |
|||
font-weight: 700; |
|||
color: #1a1a1a; |
|||
padding-left: 12px; |
|||
border-left: 3px solid #2563eb; |
|||
line-height: 1; |
|||
margin-bottom: 12px; |
|||
} |
|||
|
|||
/* ===== 执法监管 ===== */ |
|||
.supervision-section { |
|||
margin-bottom: 14px; |
|||
background-color: #fff; |
|||
padding: 16px 16px; |
|||
} |
|||
|
|||
.supervision-grid { |
|||
display: grid; |
|||
grid-template-columns: repeat(2, 1fr); |
|||
gap: 10px; |
|||
} |
|||
|
|||
.supervision-item, |
|||
.warning-item { |
|||
background: #f0f6ff; |
|||
border-radius: 8px; |
|||
padding: 16px 10px; |
|||
text-align: center; |
|||
|
|||
.sv-value { |
|||
font-size: 22px; |
|||
font-weight: 700; |
|||
color: #2563eb; |
|||
line-height: 1.3; |
|||
|
|||
.sv-unit { |
|||
font-size: 13px; |
|||
font-weight: 400; |
|||
color: #2563eb; |
|||
margin-left: 2px; |
|||
} |
|||
} |
|||
|
|||
.sv-label { |
|||
font-size: 12px; |
|||
color: #666; |
|||
margin-top: 4px; |
|||
} |
|||
} |
|||
|
|||
/* ===== 预警态势 ===== */ |
|||
.warning-section { |
|||
margin-bottom: 14px; |
|||
background-color: #fff; |
|||
padding: 16px 16px; |
|||
} |
|||
|
|||
.warning-grid { |
|||
display: grid; |
|||
grid-template-columns: repeat(2, 1fr); |
|||
gap: 10px; |
|||
|
|||
&.warning-grid-divider { |
|||
position: relative; |
|||
grid-template-columns: 1fr auto 1fr; |
|||
background: #f0f6ff; |
|||
border-radius: 8px; |
|||
margin-top: 10px; |
|||
.warning-item { |
|||
text-align: center; |
|||
|
|||
.sv-value { |
|||
justify-content: center; |
|||
font-size: 22px; |
|||
} |
|||
|
|||
.sv-label { |
|||
margin-top: 4px; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
.warning-divider { |
|||
width: 1px; |
|||
align-self: stretch; |
|||
background: #c0d5ef; |
|||
height: 30px; |
|||
margin-top: 22px; |
|||
} |
|||
|
|||
/* 预警态势内Tab */ |
|||
.warning-section { |
|||
:deep(.van-tabs__nav) { |
|||
background: transparent !important; |
|||
} |
|||
|
|||
:deep(.van-tab) { |
|||
font-size: 13px; |
|||
padding: 0 12px; |
|||
} |
|||
} |
|||
|
|||
/* 预警态势表格 */ |
|||
.warning-table-wrapper { |
|||
margin-top: 8px; |
|||
border-radius: 8px; |
|||
overflow: hidden; |
|||
background: #fff; |
|||
} |
|||
|
|||
.warning-table { |
|||
width: 100%; |
|||
border-collapse: collapse; |
|||
font-size: 13px; |
|||
|
|||
th, |
|||
td { |
|||
padding: 10px 6px; |
|||
text-align: center; |
|||
border-bottom: 1px solid #f0f0f0; |
|||
} |
|||
|
|||
th { |
|||
background: #e8f4ff; |
|||
color: #666; |
|||
font-weight: 500; |
|||
font-size: 12px; |
|||
} |
|||
|
|||
.wt-name { |
|||
color: #333; |
|||
font-weight: 500; |
|||
text-align: right; |
|||
padding-left: 8px; |
|||
width: 60px; |
|||
} |
|||
|
|||
tbody tr:last-child td { |
|||
border-bottom: none; |
|||
} |
|||
|
|||
.wt-cell { |
|||
text-align: center; |
|||
font-size: 13px; |
|||
font-weight: 500; |
|||
|
|||
&.wt-一般 { |
|||
color: #b45309; |
|||
background: #fef3c7; |
|||
} |
|||
|
|||
&.wt-良好 { |
|||
color: #047857; |
|||
background: #d1fae5; |
|||
} |
|||
|
|||
&.wt-优良 { |
|||
color: #1d4ed8; |
|||
background: #dbeafe; |
|||
} |
|||
} |
|||
|
|||
// 时间轴行 |
|||
.wt-timeline-row { |
|||
border-top: 1px solid #e8e8e8; |
|||
|
|||
td { |
|||
padding: 10px 4px; |
|||
} |
|||
} |
|||
|
|||
.wt-time-cell { |
|||
text-align: center; |
|||
font-size: 12px; |
|||
color: #999; |
|||
|
|||
&.wt-time-active { |
|||
color: #2563eb; |
|||
font-weight: 600; |
|||
} |
|||
} |
|||
} |
|||
</style> |
|||
Loading…
Reference in new issue