diff --git a/src/views/Home/Index10.vue b/src/views/Home/Index10.vue index 779351d..dd6457f 100644 --- a/src/views/Home/Index10.vue +++ b/src/views/Home/Index10.vue @@ -64,15 +64,29 @@
-
-
风险等级分布
-
-
- - {{ item.level }} - {{ item.count }}项 - ({{ item.percent }}) -
+
+
区域风险分布
+
+ + + + + + + + + + + + + + + + + + + +
区域一般较大重大
{{ item.area }}{{ item.low || '0' }}{{ item.general || '0' }}{{ item.moderate || '0' }}{{ item.major || '0' }}
@@ -91,13 +105,36 @@
-
-
整改状态
-
-
- - {{ item.status }} - {{ item.count }}项 +
+
区域整改状态
+
+ +
+
+
+ {{ item.area }} +
+
+ +
+
已逾期
+
+ {{ item.overdue }} +
+
+ +
+
处理中
+
+ {{ item.processing }} +
+
+ +
+
已处理
+
+ {{ item.processed }} +
@@ -257,6 +294,14 @@ interface DistributionItem { color: string } +interface AreaRiskItem { + area: string + low: number | string + general: number + moderate: number + major: number +} + const router = useRouter() const route = useRoute() @@ -375,26 +420,17 @@ const initOutsourcingData = async () => { // 风险管理数据 const riskTotal = ref(0) // 风险总数 const riskDistribution = ref([]) - -// 风险等级映射和颜色配置 -const riskLevelMap: Record = { - '低': { 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 areaRiskDistribution = ref([]) // 隐患管理数据 const hiddenDangerTrend = ref>([]) -const rectificationStatus = ref([ - { status: '已逾期', count: 0, color: '#ef4444' }, - { status: '处理中', count: 0, color: '#f59e0b' }, - { status: '已处理', count: 0, color: '#10b981' } -]) +interface AreaRectificationItem { + area: string + overdue: number + processing: number + processed: number +} +const areaRectificationStatus = ref([]) // 高危作业数据 const highRiskTotal = ref(0) // 高危作业总数 @@ -958,49 +994,83 @@ const initRiskData = async () => { const records = response?.records || [] if (records && records.length > 0) { - // 计算风险总数 - const total = records.reduce((sum: number, item: any) => { - return sum + Number(item.total || 0) - }, 0) + // 按风险等级分组统计,用于环形图 + const levelMap = new Map() - riskTotal.value = total + // 按区域和风险等级分组统计,用于表格 + const areaLevelMap = new Map() - // 处理风险等级分布数据 - riskDistribution.value = records.map((item: any) => { + records.forEach((item: any) => { + const level = item.name || '' + const area = item.area || '' const count = Number(item.total || 0) - const percent = total > 0 ? ((count / total) * 100).toFixed(1) + '%' : '0%' - // 映射风险等级名称和颜色 - const levelKey = item.name || '' - const levelConfig = riskLevelMap[levelKey] || { name: levelKey || '未知', color: '#9ca3af' } + // 统计风险等级分布(用于环形图) + if (level) { + levelMap.set(level, (levelMap.get(level) || 0) + count) + } - return { - level: levelConfig.name, - count, - percent, - color: levelConfig.color + // 统计区域风险分布(用于表格) + if (area) { + if (!areaLevelMap.has(area)) { + areaLevelMap.set(area, { low: 0, general: 0, moderate: 0, major: 0 }) + } + 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 = [ - { level: '低风险', count: 0, percent: '0%', color: '#10b981' }, - { level: '一般风险', count: 0, percent: '0%', color: '#f59e0b' }, - { level: '较大风险', count: 0, percent: '0%', color: '#ef4444' }, - { level: '重大风险', count: 0, percent: '0%', color: '#dc2626' } + { key: '低', level: '低风险', count: 0, percent: '0%', color: '#10b981' }, + { key: '一般', level: '一般风险', count: 0, percent: '0%', color: '#f59e0b' }, + { key: '较大', level: '较大风险', count: 0, percent: '0%', color: '#ef4444' }, + { key: '重大', level: '重大风险', count: 0, percent: '0%', color: '#dc2626' } ] - // 合并数据:如果某个等级有数据就使用数据,没有就保留0 - const mergedDistribution = allLevels.map(defaultItem => { - const existingItem = riskDistribution.value.find(item => item.level === defaultItem.level) - return existingItem || defaultItem + riskDistribution.value = allLevels.map(defaultItem => { + const count = levelMap.get(defaultItem.key) || levelMap.get(defaultItem.level) || 0 + const percent = total > 0 ? ((count / total) * 100).toFixed(1) + '%' : '0%' + 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('处理后的风险管理数据:', { total: riskTotal.value, - distribution: riskDistribution.value + levelDistribution: riskDistribution.value, + areaDistribution: areaRiskDistribution.value }) } else { // 如果没有数据,设置为默认值 @@ -1011,6 +1081,7 @@ const initRiskData = async () => { { level: '较大风险', count: 0, percent: '0%', color: '#ef4444' }, { level: '重大风险', count: 0, percent: '0%', color: '#dc2626' } ] + areaRiskDistribution.value = [] console.log('风险管理无数据') } } catch (error) { @@ -1023,6 +1094,7 @@ const initRiskData = async () => { { level: '较大风险', count: 0, percent: '0%', color: '#ef4444' }, { level: '重大风险', count: 0, percent: '0%', color: '#dc2626' } ] + areaRiskDistribution.value = [] } } @@ -1066,13 +1138,14 @@ const initDangerData = async () => { // 按日期和等级分组统计,用于折线图 const trendMap = new Map() - // 按状态统计,用于整改状态列表 - const statusMap = new Map() + // 按区域和状态分组统计,用于整改状态表格 + const areaStatusMap = new Map() records.forEach((item: any) => { - const dayname = item.dayname || '' + const dayname = item.dayName || item.dayname || '' const level = item.name || '' const status = item.status || '' + const area = item.area || '' const count = Number(item.total || 0) // 统计趋势数据(按日期和等级) @@ -1088,9 +1161,19 @@ const initDangerData = async () => { } } - // 统计状态数据 - if (status) { - statusMap.set(status, (statusMap.get(status) || 0) + count) + // 统计区域整改状态数据 + if (area) { + 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()) .map(([date, counts]) => ({ date, ...counts })) .sort((a, b) => { - // 提取日期中的数字部分进行排序 - const numA = parseInt(a.date.replace('日', '')) || 0 - const numB = parseInt(b.date.replace('日', '')) || 0 - return numA - numB + // 处理日期排序:如果是"10月"这种格式,提取月份数字 + const numA = parseInt(a.date.replace(/[^0-9]/g, '')) || 0 + const numB = parseInt(b.date.replace(/[^0-9]/g, '')) || 0 + // 如果是"日"格式(如"10日"),也处理 + const dayA = parseInt(a.date.replace('日', '')) || 0 + const dayB = parseInt(b.date.replace('日', '')) || 0 + return (numA || dayA) - (numB || dayB) }) - // 更新整改状态数据 - rectificationStatus.value = [ - { - status: '已逾期', - count: statusMap.get('已逾期') || 0, - color: '#ef4444' - }, - { - status: '处理中', - count: statusMap.get('处理中') || 0, - color: '#f59e0b' - }, - { - status: '已处理', - count: statusMap.get('已处理') || 0, - color: '#10b981' - } - ] + // 转换为区域整改状态数组 + areaRectificationStatus.value = Array.from(areaStatusMap.entries()) + .map(([area, status]) => ({ + area, + overdue: status.overdue, + processing: status.processing, + processed: status.processed + })) + .sort((a, b) => { + // 按总数降序排序 + const totalA = a.overdue + a.processing + a.processed + const totalB = b.overdue + b.processing + b.processed + return totalB - totalA + }) console.log('处理后的隐患管理数据:', { trend: hiddenDangerTrend.value, - status: rectificationStatus.value + areaStatus: areaRectificationStatus.value }) } else { // 如果没有数据,重置为空 hiddenDangerTrend.value = [] - rectificationStatus.value = [ - { status: '已逾期', count: 0, color: '#ef4444' }, - { status: '处理中', count: 0, color: '#f59e0b' }, - { status: '已处理', count: 0, color: '#10b981' } - ] + areaRectificationStatus.value = [] console.log('隐患管理无数据') } } catch (error) { console.error('获取隐患管理数据失败:', error) // 如果接口失败,重置为空 hiddenDangerTrend.value = [] - rectificationStatus.value = [ - { status: '已逾期', count: 0, color: '#ef4444' }, - { status: '处理中', count: 0, color: '#f59e0b' }, - { status: '已处理', count: 0, color: '#10b981' } - ] + areaRectificationStatus.value = [] } } @@ -1739,8 +1813,8 @@ onMounted(async () => { } .region-distribution, -.risk-distribution, -.rectification-status, +.risk-distribution-table, +.rectification-status-grid, .operation-distribution, .park-operation-distribution, .regional-progress { @@ -1753,15 +1827,13 @@ onMounted(async () => { margin-bottom: 12px; } - .distribution-list, - .status-list { + .distribution-list { display: flex; flex-direction: column; gap: 8px; } - .distribution-item, - .status-item { + .distribution-item { display: flex; align-items: center; gap: 8px; @@ -1776,14 +1848,12 @@ onMounted(async () => { flex-shrink: 0; } - .region-name, - .status-name { + .region-name { flex: 1; color: #374151; } - .region-count, - .status-count { + .region-count { color: #1f2937; font-weight: 500; 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 { display: flex; flex-direction: column;