集团数据中心页面修改

This commit is contained in:
chenlin
2025-12-29 18:02:12 +08:00
parent b5b987ae85
commit 7534a20556

View File

@@ -64,15 +64,29 @@
<div class="donut-chart-wrapper"> <div class="donut-chart-wrapper">
<Echart :options="riskChartOption" width="100%" height="200px" /> <Echart :options="riskChartOption" width="100%" height="200px" />
</div> </div>
<div class="risk-distribution"> <div class="risk-distribution-table">
<div class="distribution-title">风险等级分布</div> <div class="distribution-title">区域风险分布</div>
<div class="distribution-list"> <div class="table-wrapper">
<div class="distribution-item" v-for="item in riskDistribution" :key="item.level"> <table class="risk-table">
<span class="dot" :style="{ backgroundColor: item.color }"></span> <thead>
<span class="region-name">{{ item.level }}</span> <tr>
<span class="region-count">{{ item.count }}</span> <th>区域</th>
<span class="region-percent">({{ item.percent }})</span> <th></th>
</div> <th>一般</th>
<th>较大</th>
<th>重大</th>
</tr>
</thead>
<tbody>
<tr v-for="item in areaRiskDistribution" :key="item.area">
<td>{{ item.area }}</td>
<td>{{ item.low || '0' }}</td>
<td>{{ item.general || '0' }}</td>
<td>{{ item.moderate || '0' }}</td>
<td>{{ item.major || '0' }}</td>
</tr>
</tbody>
</table>
</div> </div>
</div> </div>
</div> </div>
@@ -91,13 +105,36 @@
<div class="line-chart-wrapper"> <div class="line-chart-wrapper">
<Echart :options="hiddenDangerChartOption" width="100%" height="180px" /> <Echart :options="hiddenDangerChartOption" width="100%" height="180px" />
</div> </div>
<div class="rectification-status"> <div class="rectification-status-grid">
<div class="distribution-title">整改状态</div> <div class="distribution-title">区域整改状态</div>
<div class="status-list"> <div class="grid-wrapper">
<div class="status-item" v-for="item in rectificationStatus" :key="item.status"> <!-- 第一列区域名称 -->
<span class="dot" :style="{ backgroundColor: item.color }"></span> <div class="grid-column">
<span class="status-name">{{ item.status }}</span> <div class="grid-header empty-header"></div>
<span class="status-count">{{ item.count }}</span> <div class="grid-park-name" v-for="item in areaRectificationStatus" :key="'area-' + item.area">
{{ item.area }}
</div>
</div>
<!-- 已逾期列 -->
<div class="grid-column">
<div class="grid-header status-overdue">已逾期</div>
<div class="grid-number status-overdue" v-for="item in areaRectificationStatus" :key="'overdue-' + item.area">
{{ item.overdue }}
</div>
</div>
<!-- 处理中列 -->
<div class="grid-column">
<div class="grid-header status-processing">处理中</div>
<div class="grid-number status-processing" v-for="item in areaRectificationStatus" :key="'processing-' + item.area">
{{ item.processing }}
</div>
</div>
<!-- 已处理列 -->
<div class="grid-column">
<div class="grid-header status-processed">已处理</div>
<div class="grid-number status-processed" v-for="item in areaRectificationStatus" :key="'processed-' + item.area">
{{ item.processed }}
</div>
</div> </div>
</div> </div>
</div> </div>
@@ -257,6 +294,14 @@ interface DistributionItem {
color: string color: string
} }
interface AreaRiskItem {
area: string
low: number | string
general: number
moderate: number
major: number
}
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
@@ -375,26 +420,17 @@ const initOutsourcingData = async () => {
// 风险管理数据 // 风险管理数据
const riskTotal = ref<number>(0) // 风险总数 const riskTotal = ref<number>(0) // 风险总数
const riskDistribution = ref<DistributionItem[]>([]) const riskDistribution = ref<DistributionItem[]>([])
const areaRiskDistribution = ref<AreaRiskItem[]>([])
// 风险等级映射和颜色配置
const riskLevelMap: Record<string, { name: string; color: string }> = {
'低': { name: '低风险', color: '#10b981' },
'低风险': { name: '低风险', color: '#10b981' },
'一般': { name: '一般风险', color: '#f59e0b' },
'一般风险': { name: '一般风险', color: '#f59e0b' },
'较大': { name: '较大风险', color: '#ef4444' },
'较大风险': { name: '较大风险', color: '#ef4444' },
'重大': { name: '重大风险', color: '#dc2626' },
'重大风险': { name: '重大风险', color: '#dc2626' }
}
// 隐患管理数据 // 隐患管理数据
const hiddenDangerTrend = ref<Array<{ date: string; general: number; major: number }>>([]) const hiddenDangerTrend = ref<Array<{ date: string; general: number; major: number }>>([])
const rectificationStatus = ref<DistributionItem[]>([ interface AreaRectificationItem {
{ status: '已逾期', count: 0, color: '#ef4444' }, area: string
{ status: '处理中', count: 0, color: '#f59e0b' }, overdue: number
{ status: '已处理', count: 0, color: '#10b981' } processing: number
]) processed: number
}
const areaRectificationStatus = ref<AreaRectificationItem[]>([])
// 高危作业数据 // 高危作业数据
const highRiskTotal = ref<number>(0) // 高危作业总数 const highRiskTotal = ref<number>(0) // 高危作业总数
@@ -958,49 +994,83 @@ const initRiskData = async () => {
const records = response?.records || [] const records = response?.records || []
if (records && records.length > 0) { if (records && records.length > 0) {
// 计算风险总数 // 按风险等级分组统计,用于环形图
const total = records.reduce((sum: number, item: any) => { const levelMap = new Map<string, number>()
return sum + Number(item.total || 0)
}, 0)
riskTotal.value = total // 按区域和风险等级分组统计,用于表格
const areaLevelMap = new Map<string, { low: number; general: number; moderate: number; major: number }>()
// 处理风险等级分布数据 records.forEach((item: any) => {
riskDistribution.value = records.map((item: any) => { const level = item.name || ''
const area = item.area || ''
const count = Number(item.total || 0) const count = Number(item.total || 0)
const percent = total > 0 ? ((count / total) * 100).toFixed(1) + '%' : '0%'
// 映射风险等级名称和颜色 // 统计风险等级分布(用于环形图)
const levelKey = item.name || '' if (level) {
const levelConfig = riskLevelMap[levelKey] || { name: levelKey || '未知', color: '#9ca3af' } levelMap.set(level, (levelMap.get(level) || 0) + count)
}
return { // 统计区域风险分布(用于表格)
level: levelConfig.name, if (area) {
count, if (!areaLevelMap.has(area)) {
percent, areaLevelMap.set(area, { low: 0, general: 0, moderate: 0, major: 0 })
color: levelConfig.color }
const areaData = areaLevelMap.get(area)!
if (level === '低' || level === '低风险') {
areaData.low += count
} else if (level === '一般' || level === '一般风险') {
areaData.general += count
} else if (level === '较大' || level === '较大风险') {
areaData.moderate += count
} else if (level === '重大' || level === '重大风险') {
areaData.major += count
}
} }
}) })
// 如果没有数据确保包含所有四个风险等级显示为0 // 计算总数
const total = Array.from(levelMap.values()).reduce((sum, count) => sum + count, 0)
riskTotal.value = total
// 处理风险等级分布数据(用于环形图)
const allLevels = [ const allLevels = [
{ level: '低风险', count: 0, percent: '0%', color: '#10b981' }, { key: '低', level: '低风险', count: 0, percent: '0%', color: '#10b981' },
{ level: '一般风险', count: 0, percent: '0%', color: '#f59e0b' }, { key: '一般', level: '一般风险', count: 0, percent: '0%', color: '#f59e0b' },
{ level: '较大风险', count: 0, percent: '0%', color: '#ef4444' }, { key: '较大', level: '较大风险', count: 0, percent: '0%', color: '#ef4444' },
{ level: '重大风险', count: 0, percent: '0%', color: '#dc2626' } { key: '重大', level: '重大风险', count: 0, percent: '0%', color: '#dc2626' }
] ]
// 合并数据如果某个等级有数据就使用数据没有就保留0 riskDistribution.value = allLevels.map(defaultItem => {
const mergedDistribution = allLevels.map(defaultItem => { const count = levelMap.get(defaultItem.key) || levelMap.get(defaultItem.level) || 0
const existingItem = riskDistribution.value.find(item => item.level === defaultItem.level) const percent = total > 0 ? ((count / total) * 100).toFixed(1) + '%' : '0%'
return existingItem || defaultItem return {
level: defaultItem.level,
count,
percent,
color: defaultItem.color
}
}) })
riskDistribution.value = mergedDistribution // 处理区域风险分布表
areaRiskDistribution.value = Array.from(areaLevelMap.entries())
.map(([area, data]) => ({
area,
low: data.low > 0 ? data.low : '',
general: data.general,
moderate: data.moderate,
major: data.major
}))
.sort((a, b) => {
// 按总数降序排序
const totalA = (typeof a.low === 'number' ? a.low : 0) + a.general + a.moderate + a.major
const totalB = (typeof b.low === 'number' ? b.low : 0) + b.general + b.moderate + b.major
return totalB - totalA
})
console.log('处理后的风险管理数据:', { console.log('处理后的风险管理数据:', {
total: riskTotal.value, total: riskTotal.value,
distribution: riskDistribution.value levelDistribution: riskDistribution.value,
areaDistribution: areaRiskDistribution.value
}) })
} else { } else {
// 如果没有数据,设置为默认值 // 如果没有数据,设置为默认值
@@ -1011,6 +1081,7 @@ const initRiskData = async () => {
{ level: '较大风险', count: 0, percent: '0%', color: '#ef4444' }, { level: '较大风险', count: 0, percent: '0%', color: '#ef4444' },
{ level: '重大风险', count: 0, percent: '0%', color: '#dc2626' } { level: '重大风险', count: 0, percent: '0%', color: '#dc2626' }
] ]
areaRiskDistribution.value = []
console.log('风险管理无数据') console.log('风险管理无数据')
} }
} catch (error) { } catch (error) {
@@ -1023,6 +1094,7 @@ const initRiskData = async () => {
{ level: '较大风险', count: 0, percent: '0%', color: '#ef4444' }, { level: '较大风险', count: 0, percent: '0%', color: '#ef4444' },
{ level: '重大风险', count: 0, percent: '0%', color: '#dc2626' } { level: '重大风险', count: 0, percent: '0%', color: '#dc2626' }
] ]
areaRiskDistribution.value = []
} }
} }
@@ -1066,13 +1138,14 @@ const initDangerData = async () => {
// 按日期和等级分组统计,用于折线图 // 按日期和等级分组统计,用于折线图
const trendMap = new Map<string, { general: number; major: number }>() const trendMap = new Map<string, { general: number; major: number }>()
// 按状态统计,用于整改状态 // 按区域和状态分组统计,用于整改状态表
const statusMap = new Map<string, number>() const areaStatusMap = new Map<string, { overdue: number; processing: number; processed: number }>()
records.forEach((item: any) => { records.forEach((item: any) => {
const dayname = item.dayname || '' const dayname = item.dayName || item.dayname || ''
const level = item.name || '' const level = item.name || ''
const status = item.status || '' const status = item.status || ''
const area = item.area || ''
const count = Number(item.total || 0) const count = Number(item.total || 0)
// 统计趋势数据(按日期和等级) // 统计趋势数据(按日期和等级)
@@ -1088,9 +1161,19 @@ const initDangerData = async () => {
} }
} }
// 统计状态数据 // 统计区域整改状态数据
if (status) { if (area) {
statusMap.set(status, (statusMap.get(status) || 0) + count) if (!areaStatusMap.has(area)) {
areaStatusMap.set(area, { overdue: 0, processing: 0, processed: 0 })
}
const areaStatus = areaStatusMap.get(area)!
if (status === '已逾期') {
areaStatus.overdue += count
} else if (status === '处理中') {
areaStatus.processing += count
} else if (status === '已处理') {
areaStatus.processed += count
}
} }
}) })
@@ -1098,54 +1181,45 @@ const initDangerData = async () => {
hiddenDangerTrend.value = Array.from(trendMap.entries()) hiddenDangerTrend.value = Array.from(trendMap.entries())
.map(([date, counts]) => ({ date, ...counts })) .map(([date, counts]) => ({ date, ...counts }))
.sort((a, b) => { .sort((a, b) => {
// 提取日期中的数字部分进行排序 // 处理日期排序:如果是"10月"这种格式,提取月份数字
const numA = parseInt(a.date.replace('日', '')) || 0 const numA = parseInt(a.date.replace(/[^0-9]/g, '')) || 0
const numB = parseInt(b.date.replace('日', '')) || 0 const numB = parseInt(b.date.replace(/[^0-9]/g, '')) || 0
return numA - numB // 如果是"日"格式(如"10日"),也处理
const dayA = parseInt(a.date.replace('日', '')) || 0
const dayB = parseInt(b.date.replace('日', '')) || 0
return (numA || dayA) - (numB || dayB)
}) })
// 更新整改状态数 // 转换为区域整改状态数
rectificationStatus.value = [ areaRectificationStatus.value = Array.from(areaStatusMap.entries())
{ .map(([area, status]) => ({
status: '已逾期', area,
count: statusMap.get('已逾期') || 0, overdue: status.overdue,
color: '#ef4444' processing: status.processing,
}, processed: status.processed
{ }))
status: '处理中', .sort((a, b) => {
count: statusMap.get('处理中') || 0, // 按总数降序排序
color: '#f59e0b' const totalA = a.overdue + a.processing + a.processed
}, const totalB = b.overdue + b.processing + b.processed
{ return totalB - totalA
status: '已处理', })
count: statusMap.get('已处理') || 0,
color: '#10b981'
}
]
console.log('处理后的隐患管理数据:', { console.log('处理后的隐患管理数据:', {
trend: hiddenDangerTrend.value, trend: hiddenDangerTrend.value,
status: rectificationStatus.value areaStatus: areaRectificationStatus.value
}) })
} else { } else {
// 如果没有数据,重置为空 // 如果没有数据,重置为空
hiddenDangerTrend.value = [] hiddenDangerTrend.value = []
rectificationStatus.value = [ areaRectificationStatus.value = []
{ status: '已逾期', count: 0, color: '#ef4444' },
{ status: '处理中', count: 0, color: '#f59e0b' },
{ status: '已处理', count: 0, color: '#10b981' }
]
console.log('隐患管理无数据') console.log('隐患管理无数据')
} }
} catch (error) { } catch (error) {
console.error('获取隐患管理数据失败:', error) console.error('获取隐患管理数据失败:', error)
// 如果接口失败,重置为空 // 如果接口失败,重置为空
hiddenDangerTrend.value = [] hiddenDangerTrend.value = []
rectificationStatus.value = [ areaRectificationStatus.value = []
{ status: '已逾期', count: 0, color: '#ef4444' },
{ status: '处理中', count: 0, color: '#f59e0b' },
{ status: '已处理', count: 0, color: '#10b981' }
]
} }
} }
@@ -1739,8 +1813,8 @@ onMounted(async () => {
} }
.region-distribution, .region-distribution,
.risk-distribution, .risk-distribution-table,
.rectification-status, .rectification-status-grid,
.operation-distribution, .operation-distribution,
.park-operation-distribution, .park-operation-distribution,
.regional-progress { .regional-progress {
@@ -1753,15 +1827,13 @@ onMounted(async () => {
margin-bottom: 12px; margin-bottom: 12px;
} }
.distribution-list, .distribution-list {
.status-list {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 8px; gap: 8px;
} }
.distribution-item, .distribution-item {
.status-item {
display: flex; display: flex;
align-items: center; align-items: center;
gap: 8px; gap: 8px;
@@ -1776,14 +1848,12 @@ onMounted(async () => {
flex-shrink: 0; flex-shrink: 0;
} }
.region-name, .region-name {
.status-name {
flex: 1; flex: 1;
color: #374151; color: #374151;
} }
.region-count, .region-count {
.status-count {
color: #1f2937; color: #1f2937;
font-weight: 500; font-weight: 500;
margin-left: auto; margin-left: auto;
@@ -1796,6 +1866,125 @@ onMounted(async () => {
} }
} }
// 网格样式
.rectification-status-grid {
.grid-wrapper {
display: flex;
gap: 0;
justify-content: flex-start;
}
.grid-column {
display: flex;
flex-direction: column;
align-items: center;
min-width: 0;
&:first-child {
align-items: flex-start;
margin-right: 20px;
flex: 0 0 auto;
min-width: 80px;
}
&:not(:first-child) {
flex: 1;
min-width: 60px;
}
}
.grid-header {
font-size: 14px;
font-weight: bold;
margin-bottom: 12px;
height: 20px;
line-height: 20px;
&.empty-header {
visibility: hidden;
}
&.status-overdue {
color: #ef4444;
}
&.status-processing {
color: #f59e0b;
}
&.status-processed {
color: #10b981;
}
}
.grid-park-name {
font-size: 13px;
color: #333;
margin-bottom: 8px;
text-align: left;
height: 24px;
line-height: 24px;
&:last-child {
margin-bottom: 0;
}
}
.grid-number {
font-size: 16px;
font-weight: 500;
margin-bottom: 8px;
text-align: center;
height: 24px;
line-height: 24px;
&:last-child {
margin-bottom: 0;
}
&.status-overdue {
color: #ef4444;
}
&.status-processing {
color: #f59e0b;
}
&.status-processed {
color: #10b981;
}
}
}
.table-wrapper {
overflow-x: auto;
}
.risk-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
thead {
background-color: #f9fafb;
}
th, td {
padding: 8px;
text-align: left;
border-bottom: 1px solid #e5e7eb;
}
th {
font-weight: bold;
color: #333;
}
td {
color: #666;
}
}
.drill-info { .drill-info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;