diff --git a/src/views/Home/Index10.vue b/src/views/Home/Index10.vue index dd6457f..0c7811d 100644 --- a/src/views/Home/Index10.vue +++ b/src/views/Home/Index10.vue @@ -38,13 +38,30 @@
-
区域分布
-
-
- - {{ item.region }} - {{ item.count }}人 - ({{ item.percent }}) +
区域人数分布
+
+ +
+
+
+ {{ item.region }} +
+
+ +
+
人数
+
+ {{ item.count }}人 +
+
+ +
+
占比
+
+ {{ item.percent }} +
@@ -66,27 +83,46 @@
区域风险分布
-
- - - - - - - - - - - - - - - - - - - -
区域一般较大重大
{{ item.area }}{{ item.low || '0' }}{{ item.general || '0' }}{{ item.moderate || '0' }}{{ item.major || '0' }}
+
+ +
+
+
+ {{ item.area }} +
+
+ +
+
+
+ {{ item.low || '0' }} +
+
+ +
+
一般
+
+ {{ item.general || '0' }} +
+
+ +
+
较大
+
+ {{ item.moderate || '0' }} +
+
+ +
+
重大
+
+ {{ item.major || '0' }} +
+
@@ -107,7 +143,10 @@
区域整改状态
-
+
+ 暂无数据 +
+
@@ -118,22 +157,25 @@
已逾期
-
- {{ item.overdue }} +
+ {{ item.overdue ?? 0 }}
处理中
-
- {{ item.processing }} +
+ {{ item.processing ?? 0 }}
已处理
-
- {{ item.processed }} +
+ {{ item.processed ?? 0 }}
@@ -266,12 +308,12 @@ import RegionSelector from '@/views/screen/components/RegionSelector.vue' import { getTableList } from '@/api/design/report' import type { EChartsOption } from 'echarts' import dayjs from 'dayjs' -import { - getHiddenDangerManagementData, - getHiddenDangerManagementDataWeek, +import { + getHiddenDangerManagementData, + getHiddenDangerManagementDataWeek, getHiddenDangerManagementDataMonth, - getOutsourcingManagementData, - getRiskManagementData, + getOutsourcingManagementData, + getRiskManagementData, getHighRiskManagementData, getEmergencyPlanManagementData, getTrainingManagementData @@ -336,22 +378,23 @@ const dateRange = ref(getInitialDateRange()) // 应急预案:/yayl/table/view/1966394259751907330 // 安全培训:/pxks/table/view/1968225010550091777 const openOutsourcingManagement = () => { - window.open('/person/table/view/1959187451673116674', '_blank') + // 不打开新标签页 + router.push('/person/table/view/1959187451673116674') } const openRiskManagement = () => { - window.open('/fx/table/view/1978723750599790594', '_blank') + router.push('/fx/table/view/1978723750599790594') } const openHiddenDangerManagement = () => { - window.open('/fx/table/view/1963446160885366786', '_blank') + router.push('/fx/table/view/1963446160885366786') } const openHighRiskManagement = () => { - window.open('/low/table/view/1964253329070571521', '_blank') + router.push('/low/table/view/1964253329070571521') } const openEmergencyPlanManagement = () => { - window.open('/yayl/table/view/1966394259751907330', '_blank') + router.push('/yayl/table/view/1966394259751907330') } const openTrainingManagement = () => { - window.open('/pxks/table/view/1968225010550091777', '_blank') + router.push('/pxks/table/view/1968225010550091777') } // 外协管理数据 @@ -370,27 +413,27 @@ const initOutsourcingData = async () => { pageNo: 1, pageSize: 10000 }) - + console.log('外协管理接口返回:', response) - + // axios封装后,response就是 { code: 0, data: {...}, msg: "" } // 所以records在 response.data.records const records = response?.records || [] - + if (records && records.length > 0) { // 计算总人数(从records中累加total) const total = records.reduce((sum: number, item: any) => { return sum + Number(item.total || 0) }, 0) - + outsourcingTotal.value = total - + // 处理区域分布数据 outsourcingDistribution.value = records.map((item: any, index: number) => { const count = Number(item.total || 0) const percent = total > 0 ? ((count / total) * 100).toFixed(1) + '%' : '0%' const color = regionColors[index % regionColors.length] - + return { region: item.name, count, @@ -398,7 +441,7 @@ const initOutsourcingData = async () => { color } }) - + console.log('处理后的外协管理数据:', { total: outsourcingTotal.value, distribution: outsourcingDistribution.value @@ -472,7 +515,7 @@ const outsourcingChartOption = computed(() => { name: item.region, itemStyle: { color: item.color } })) - + // 如果没有数据,显示空状态 if (chartData.length === 0 || outsourcingTotal.value === 0) { return { @@ -509,7 +552,7 @@ const outsourcingChartOption = computed(() => { ] } } - + return { tooltip: { trigger: 'item', @@ -559,7 +602,7 @@ const riskChartOption = computed(() => { name: item.level, itemStyle: { color: item.color } })) - + // 如果没有数据,显示空状态 if (chartData.length === 0 || riskTotal.value === 0) { return { @@ -583,7 +626,7 @@ const riskChartOption = computed(() => { }] } } - + return { tooltip: { trigger: 'item', formatter: '{a}
{b}: {c} ({d}%)' }, series: [{ @@ -611,17 +654,20 @@ const riskChartOption = computed(() => { const hiddenDangerChartOption = computed(() => { // 提取日期和对应的数据 const dates = hiddenDangerTrend.value.map(item => item.date) - const generalData = hiddenDangerTrend.value.map(item => item.general) - const majorData = hiddenDangerTrend.value.map(item => item.major) - + const generalData = hiddenDangerTrend.value.map(item => item.general ?? 0) + const majorData = hiddenDangerTrend.value.map(item => item.major ?? 0) + + // 判断是否为空数据 + const isEmpty = dates.length === 0 || (generalData.every(v => v === 0) && majorData.every(v => v === 0)) + // 计算Y轴最大值(向上取整到最近的10的倍数) - const maxValue = Math.max( + const maxValue = isEmpty ? 10 : Math.max( ...generalData, ...majorData, 10 // 最小值为10,避免图表显示过小 ) const yAxisMax = Math.ceil(maxValue / 10) * 10 || 10 - + return { tooltip: { trigger: 'axis', @@ -646,18 +692,42 @@ const hiddenDangerChartOption = computed(() => { xAxis: { type: 'category', boundaryGap: false, - data: dates.length > 0 ? dates : [] + data: dates.length > 0 ? dates : [], + show: !isEmpty }, yAxis: { type: 'value', - max: yAxisMax + max: yAxisMax, + show: !isEmpty }, - series: [ + graphic: isEmpty ? [ + { + type: 'group', + left: 'center', + top: 'center', + children: [ + { + type: 'text', + z: 100, + left: 'center', + top: 'center', + style: { + text: '暂无数据', + fontSize: 16, + fontWeight: 'normal', + fill: '#9ca3af', + textAlign: 'center' + } + } + ] + } + ] : [], + series: isEmpty ? [] : [ { name: '一般隐患', type: 'line', smooth: true, - data: generalData.length > 0 ? generalData : [], + data: generalData, itemStyle: { color: '#f59e0b' }, lineStyle: { color: '#f59e0b', width: 2 }, areaStyle: { @@ -678,7 +748,7 @@ const hiddenDangerChartOption = computed(() => { name: '重大隐患', type: 'line', smooth: true, - data: majorData.length > 0 ? majorData : [], + data: majorData, itemStyle: { color: '#ef4444' }, lineStyle: { color: '#ef4444', width: 2 }, areaStyle: { @@ -708,7 +778,7 @@ const highRiskChartOption = computed(() => { name: item.type, itemStyle: { color: item.color } })) - + // 如果没有数据,显示空状态 if (chartData.length === 0 || highRiskTotal.value === 0) { return { @@ -732,7 +802,7 @@ const highRiskChartOption = computed(() => { }] } } - + return { tooltip: { trigger: 'item', formatter: '{a}
{b}: {c} ({d}%)' }, series: [{ @@ -758,10 +828,10 @@ const highRiskChartOption = computed(() => { // 应急预案环形进度图配置 const emergencyPlanChartOption = computed(() => { - const percent = emergencyPlanTotal.value > 0 + const percent = emergencyPlanTotal.value > 0 ? ((emergencyPlanCompleted.value / emergencyPlanTotal.value) * 100).toFixed(0) : 0 - + return { tooltip: { trigger: 'item' }, series: [{ @@ -793,12 +863,12 @@ const safetyTrainingChartOption = computed(() => { const regions = trainingBarData.value.regions || [] const trainingCount = trainingBarData.value.trainingCount || [] const participants = trainingBarData.value.participants || [] - + // 计算堆叠后的最大值(培训次数 + 参与人次) const stackedValues = trainingCount.map((count, index) => count + (participants[index] || 0)) const maxValue = Math.max(...stackedValues, 10) // 最小值为10,避免图表显示过小 const yAxisMax = Math.ceil(maxValue / 10) * 10 || 10 - + return { tooltip: { trigger: 'axis', @@ -936,8 +1006,8 @@ const onRegionChange = (item: RegionItem): void => { selectedRegion.value = item.name router.push({ path: '/region', - query: { - region: item.name, + query: { + region: item.name, regionCode: item.code, sDate: dateRange.value[0], eDate: dateRange.value[1] @@ -988,28 +1058,28 @@ const initRiskData = async () => { pageNo: 1, pageSize: 10000 }) - + console.log('风险管理接口返回:', response) - + const records = response?.records || [] - + if (records && records.length > 0) { // 按风险等级分组统计,用于环形图 const levelMap = new Map() - + // 按区域和风险等级分组统计,用于表格 const areaLevelMap = new Map() - + records.forEach((item: any) => { const level = item.name || '' const area = item.area || '' const count = Number(item.total || 0) - + // 统计风险等级分布(用于环形图) if (level) { levelMap.set(level, (levelMap.get(level) || 0) + count) } - + // 统计区域风险分布(用于表格) if (area) { if (!areaLevelMap.has(area)) { @@ -1027,11 +1097,11 @@ const initRiskData = async () => { } } }) - + // 计算总数 const total = Array.from(levelMap.values()).reduce((sum, count) => sum + count, 0) riskTotal.value = total - + // 处理风险等级分布数据(用于环形图) const allLevels = [ { key: '低', level: '低风险', count: 0, percent: '0%', color: '#10b981' }, @@ -1039,7 +1109,7 @@ const initRiskData = async () => { { key: '较大', level: '较大风险', count: 0, percent: '0%', color: '#ef4444' }, { key: '重大', level: '重大风险', count: 0, percent: '0%', color: '#dc2626' } ] - + 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%' @@ -1050,7 +1120,7 @@ const initRiskData = async () => { color: defaultItem.color } }) - + // 处理区域风险分布表 areaRiskDistribution.value = Array.from(areaLevelMap.entries()) .map(([area, data]) => ({ @@ -1066,7 +1136,7 @@ const initRiskData = async () => { const totalB = (typeof b.low === 'number' ? b.low : 0) + b.general + b.moderate + b.major return totalB - totalA }) - + console.log('处理后的风险管理数据:', { total: riskTotal.value, levelDistribution: riskDistribution.value, @@ -1103,7 +1173,7 @@ const getHiddenDangerApi = (startDate: string, endDate: string) => { const start = dayjs(startDate) const end = dayjs(endDate) const daysDiff = end.diff(start, 'day') + 1 // 包含起始和结束日期 - + // 如果日期范围 <= 7天,使用"天"接口 if (daysDiff <= 7) { return getHiddenDangerManagementData @@ -1122,32 +1192,32 @@ const initDangerData = async () => { try { // 根据日期范围选择接口 const apiFunc = getHiddenDangerApi(dateRange.value[0], dateRange.value[1]) - + const response = await apiFunc({ sDate: dateRange.value[0], eDate: dateRange.value[1], pageNo: 1, pageSize: 10000 }) - + console.log('隐患管理接口返回:', response) - + const records = response?.records || [] - + if (records && records.length > 0) { // 按日期和等级分组统计,用于折线图 const trendMap = new Map() - + // 按区域和状态分组统计,用于整改状态表格 const areaStatusMap = new Map() - + records.forEach((item: any) => { const dayname = item.dayName || item.dayname || '' const level = item.name || '' const status = item.status || '' const area = item.area || '' const count = Number(item.total || 0) - + // 统计趋势数据(按日期和等级) if (dayname) { if (!trendMap.has(dayname)) { @@ -1160,7 +1230,7 @@ const initDangerData = async () => { trend.major += count } } - + // 统计区域整改状态数据 if (area) { if (!areaStatusMap.has(area)) { @@ -1176,7 +1246,7 @@ const initDangerData = async () => { } } }) - + // 转换为数组并按日期排序 hiddenDangerTrend.value = Array.from(trendMap.entries()) .map(([date, counts]) => ({ date, ...counts })) @@ -1189,7 +1259,7 @@ const initDangerData = async () => { const dayB = parseInt(b.date.replace('日', '')) || 0 return (numA || dayA) - (numB || dayB) }) - + // 转换为区域整改状态数组 areaRectificationStatus.value = Array.from(areaStatusMap.entries()) .map(([area, status]) => ({ @@ -1204,7 +1274,7 @@ const initDangerData = async () => { const totalB = b.overdue + b.processing + b.processed return totalB - totalA }) - + console.log('处理后的隐患管理数据:', { trend: hiddenDangerTrend.value, areaStatus: areaRectificationStatus.value @@ -1231,38 +1301,38 @@ const initHighRiskData = async () => { pageNo: 1, pageSize: 10000 }) - + console.log('高危作业接口返回:', response) - + const records = response?.records || [] - + if (records && records.length > 0) { // 按作业类型分组统计,用于环形图 const typeMap = new Map() - + // 按区域分组统计,用于区域分布列表 const areaMap = new Map() - + records.forEach((item: any) => { const itemType = item.item || '' const area = item.area || '' const count = Number(item.total || 0) - + // 统计作业类型 if (itemType) { typeMap.set(itemType, (typeMap.get(itemType) || 0) + count) } - + // 统计区域分布 if (area) { areaMap.set(area, (areaMap.get(area) || 0) + count) } }) - + // 计算总数 const total = Array.from(typeMap.values()).reduce((sum, count) => sum + count, 0) highRiskTotal.value = total - + // 处理作业类型分布数据 operationTypeDistribution.value = Array.from(typeMap.entries()) .map(([type, count]) => ({ @@ -1272,7 +1342,7 @@ const initHighRiskData = async () => { color: operationTypeColors[type] || '#9ca3af' // 如果没有配置颜色,使用灰色 })) .sort((a, b) => b.count - a.count) // 按数量降序排序 - + // 处理区域分布数据 operationDistribution.value = Array.from(areaMap.entries()) .map(([region, count]) => ({ @@ -1280,7 +1350,7 @@ const initHighRiskData = async () => { count })) .sort((a, b) => b.count - a.count) // 按数量降序排序 - + console.log('处理后的高危作业数据:', { total: highRiskTotal.value, typeDistribution: operationTypeDistribution.value, @@ -1310,19 +1380,19 @@ const initEmergencyPlanData = async () => { pageNo: 1, pageSize: 10000 }) - + console.log('应急预案接口返回:', response) - + const records = response?.records || [] - + if (records && records.length > 0) { // 统计应完成演练总数(所有记录的total总和) const total = records.reduce((sum: number, item: any) => { return sum + Number(item.total || 0) }, 0) - + emergencyPlanTotal.value = total - + // 统计已完成演练数(根据状态判断) // 可能的完成状态:已完成、已完成演练、已执行等 const completedCount = records.reduce((sum: number, item: any) => { @@ -1334,18 +1404,18 @@ const initEmergencyPlanData = async () => { } return sum }, 0) - + emergencyPlanCompleted.value = completedCount - + // 按区域统计演练完成率 const areaMap = new Map() - + records.forEach((item: any) => { const area = item.area || '' const count = Number(item.total || 0) const status = item.status || '' const isCompleted = status.includes('完成') || status.includes('已执行') - + if (area) { if (!areaMap.has(area)) { areaMap.set(area, { total: 0, completed: 0 }) @@ -1357,11 +1427,11 @@ const initEmergencyPlanData = async () => { } } }) - + // 转换为数组并计算完成率 regionalDrillProgress.value = Array.from(areaMap.entries()) .map(([region, data]) => { - const percent = data.total > 0 + const percent = data.total > 0 ? ((data.completed / data.total) * 100).toFixed(0) + '%' : '0%' return { region, percent } @@ -1372,7 +1442,7 @@ const initEmergencyPlanData = async () => { const percentB = parseFloat(b.percent) return percentB - percentA }) - + console.log('处理后的应急预案数据:', { total: emergencyPlanTotal.value, completed: emergencyPlanCompleted.value, @@ -1402,25 +1472,25 @@ const initTrainingData = async () => { pageNo: 1, pageSize: 10000 }) - + console.log('安全培训接口返回:', response) - + const records = response?.records || [] - + if (records && records.length > 0) { // 按区域分组统计 const areaMap = new Map() - + records.forEach((item: any) => { // 只统计有区域字段的记录 if (!item.area) { return } - + const area = item.area const trainingCount = Number(item.plannum || 0) // 计划数量作为培训次数 const participants = Number(item.exenum || 0) // 执行数量作为参与人次 - + if (!areaMap.has(area)) { areaMap.set(area, { trainingCount: 0, participants: 0 }) } @@ -1428,7 +1498,7 @@ const initTrainingData = async () => { areaData.trainingCount += trainingCount areaData.participants += participants }) - + // 转换为数组并排序 const areaDataArray = Array.from(areaMap.entries()) .map(([region, data]) => ({ @@ -1443,20 +1513,20 @@ const initTrainingData = async () => { // 按培训次数降序排序 return b.trainingCount - a.trainingCount }) - + // 更新柱状图数据 trainingBarData.value = { regions: areaDataArray.map(item => item.region), trainingCount: areaDataArray.map(item => item.trainingCount), participants: areaDataArray.map(item => item.participants) } - + // 更新区域培训完成率数据 regionalTrainingProgress.value = areaDataArray.map(item => ({ region: item.region, percent: item.percent })) - + console.log('处理后的安全培训数据:', { barData: trainingBarData.value, regionalProgress: regionalTrainingProgress.value @@ -1486,7 +1556,7 @@ const initTrainingData = async () => { const initData = async () => { await initRegionData() initOutsourcingData() - + initRiskData() initDangerData() initHighRiskData() @@ -1540,15 +1610,15 @@ onMounted(async () => { color: white; user-select: none; font-weight: 600; - span { - margin-left: 8px; - font-size: 18px; - color: #6b7280; - } + gap: 5px; &:hover { - background: #e5e7eb; - border-color: #d1d5db; + background: #2563eb; + } + + span { + font-size: 18px; + line-height: 1; } &:active { @@ -1616,16 +1686,17 @@ onMounted(async () => { } @media (max-width: 1200px) { + .high-risk-top, .emergency-plan-top { gap: 10px; } - + .donut-chart-wrapper-small, .progress-chart-wrapper { min-width: 160px; } - + .operation-type-list, .drill-info { min-width: 140px; @@ -1634,12 +1705,13 @@ onMounted(async () => { } @media (max-width: 768px) { + .high-risk-top, .emergency-plan-top { flex-direction: column; align-items: stretch; } - + .donut-chart-wrapper-small, .progress-chart-wrapper { min-width: 100%; @@ -1647,7 +1719,7 @@ onMounted(async () => { height: 220px; min-height: 220px; } - + .operation-type-list, .drill-info { min-width: 100%; @@ -1825,6 +1897,14 @@ onMounted(async () => { font-weight: 600; color: #374151; margin-bottom: 12px; + display: flex; + align-items: center; + justify-content: space-between; + span { + font-size: 14px; + font-weight: 600; + color: #374151; + } } .distribution-list { @@ -1868,55 +1948,62 @@ onMounted(async () => { // 网格样式 .rectification-status-grid { + .empty-data-tip { + text-align: center; + padding: 40px 0; + color: #9ca3af; + font-size: 14px; + } + .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; @@ -1924,12 +2011,12 @@ onMounted(async () => { text-align: left; height: 24px; line-height: 24px; - + &:last-child { margin-bottom: 0; } } - + .grid-number { font-size: 16px; font-weight: 500; @@ -1937,51 +2024,188 @@ onMounted(async () => { 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-distribution-table { + .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-low { + color: #117cee; + } + + &.status-general { + color: #fbde28; + } + + &.status-moderate { + color: #ed740c; + } + + &.status-major { + color: #df2a3f; + } + } + + .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-low { + color: #117cee; + } + + &.status-general { + color: #fbde28; + } + + &.status-moderate { + color: #ed740c; + } + + &.status-major { + color: #df2a3f; + } + } } -.risk-table { - width: 100%; - border-collapse: collapse; - font-size: 13px; - - thead { - background-color: #f9fafb; +// 外协管理网格样式(与隐患管理一致) +.region-distribution { + .grid-wrapper { + display: flex; + gap: 0; + justify-content: flex-start; } - - th, td { - padding: 8px; - text-align: left; - border-bottom: 1px solid #e5e7eb; + + .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; + } } - - th { + + .grid-header { + font-size: 14px; font-weight: bold; - color: #333; + margin-bottom: 12px; + height: 20px; + line-height: 20px; + color: #374151; + + &.empty-header { + visibility: hidden; + } } - - td { - color: #666; + + .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; + color: #1f2937; + + &:last-child { + margin-bottom: 0; + } } } @@ -2052,7 +2276,7 @@ onMounted(async () => { box-shadow: 0 2px 4px rgba(139, 92, 246, 0.3); position: relative; overflow: hidden; - + &::after { content: ''; position: absolute; @@ -2060,12 +2284,10 @@ onMounted(async () => { left: 0; bottom: 0; right: 0; - background: linear-gradient( - 90deg, - transparent 0%, - rgba(255, 255, 255, 0.3) 50%, - transparent 100% - ); + background: linear-gradient(90deg, + transparent 0%, + rgba(255, 255, 255, 0.3) 50%, + transparent 100%); animation: shimmer 2s infinite; } } @@ -2084,6 +2306,7 @@ onMounted(async () => { 0% { transform: translateX(-100%); } + 100% { transform: translateX(100%); } diff --git a/src/views/Home/Index12.vue b/src/views/Home/Index12.vue index f531164..a166036 100644 --- a/src/views/Home/Index12.vue +++ b/src/views/Home/Index12.vue @@ -41,16 +41,33 @@
-
园区分布
-
-
- - {{ item.region }} - {{ item.count }}人 - ({{ item.percent }}) -
+
园区人数分布
+
+ +
+
+
+ {{ item.region }}
+
+ +
+
人数
+
+ {{ item.count }}人
+
+ +
+
占比
+
+ {{ item.percent }} +
+
+
+
@@ -69,28 +86,47 @@
园区风险分布
-
- - - - - - - - - - - - - - - - - - - -
园区一般较大重大
{{ item.park }}{{ item.low || '' }}{{ item.general }}{{ item.moderate }}{{ item.major }}
-
+
+ +
+
+
+ {{ item.park }} +
+
+ +
+
+
+ {{ item.low || '0' }} +
+
+ +
+
一般
+
+ {{ item.general || '0' }} +
+
+ +
+
较大
+
+ {{ item.moderate || '0' }} +
+
+ +
+
重大
+
+ {{ item.major || '0' }} +
+
+
@@ -110,7 +146,10 @@
园区整改状态
-
+
+ 暂无数据 +
+
@@ -122,21 +161,21 @@
已逾期
- {{ item.overdue }} + {{ item.overdue ?? 0 }}
处理中
- {{ item.processing }} + {{ item.processing ?? 0 }}
已处理
- {{ item.processed }} + {{ item.processed ?? 0 }}
@@ -329,22 +368,22 @@ const parkOption = ref([]) // 应急预案:/yayl/table/view/1966394259751907330 // 安全培训:/pxks/table/view/1968225010550091777 const openOutsourcingManagement = () => { - window.open('/person/table/view/1959187451673116674', '_blank') + router.push('/person/table/view/1959187451673116674') } const openRiskManagement = () => { - window.open('/fx/table/view/1978723750599790594', '_blank') + router.push('/fx/table/view/1978723750599790594') } const openHiddenDangerManagement = () => { - window.open('/fx/table/view/1963446160885366786', '_blank') + router.push('/fx/table/view/1963446160885366786') } const openHighRiskManagement = () => { - window.open('/low/table/view/1964253329070571521', '_blank') + router.push('/low/table/view/1964253329070571521') } const openEmergencyPlanManagement = () => { - window.open('/yayl/table/view/1966394259751907330', '_blank') + router.push('/yayl/table/view/1966394259751907330') } const openTrainingManagement = () => { - window.open('/pxks/table/view/1968225010550091777', '_blank') + router.push('/pxks/table/view/1968225010550091777') } // 时间选择相关 - 默认当前月起止,如果路由中有日期范围参数则使用 const getCurrentMonthRange = () => { @@ -1130,8 +1169,11 @@ const riskChartOption = computed(() => { // 隐患管理折线图配置 const hiddenDangerChartOption = computed(() => { const dates = hiddenDangerTrend.value.map(item => item.date) - const generalData = hiddenDangerTrend.value.map(item => item.general) - const majorData = hiddenDangerTrend.value.map(item => item.major) + const generalData = hiddenDangerTrend.value.map(item => item.general ?? 0) + const majorData = hiddenDangerTrend.value.map(item => item.major ?? 0) + + // 判断是否为空数据 + const isEmpty = dates.length === 0 || (generalData.every(v => v === 0) && majorData.every(v => v === 0)) return { tooltip: { trigger: 'axis' }, @@ -1139,14 +1181,40 @@ const hiddenDangerChartOption = computed(() => { data: ['一般隐患', '重大隐患'], top: 10 }, - grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, + grid: { left: '3%', right: '4%', bottom: '3%', top: '12%', containLabel: true }, xAxis: { type: 'category', boundaryGap: false, - data: dates + data: dates, + show: !isEmpty }, - yAxis: { type: 'value' }, - series: [ + yAxis: { + type: 'value', + show: !isEmpty + }, + graphic: isEmpty ? [ + { + type: 'group', + left: 'center', + top: 'center', + children: [ + { + type: 'text', + z: 100, + left: 'center', + top: 'center', + style: { + text: '暂无数据', + fontSize: 16, + fontWeight: 'normal', + fill: '#9ca3af', + textAlign: 'center' + } + } + ] + } + ] : [], + series: isEmpty ? [] : [ { name: '一般隐患', type: 'line', @@ -1559,6 +1627,14 @@ onMounted(() => { font-weight: bold; color: #333; margin-bottom: 10px; + display: flex; + align-items: center; + justify-content: space-between; + span { + font-size: 14px; + font-weight: 600; + color: #374151; + } } .distribution-list { @@ -1595,11 +1671,104 @@ onMounted(() => { color: #999; } -.table-wrapper { - overflow-x: auto; +// 风险管理网格样式(与隐患管理一致) +.risk-distribution-table { + .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-low { + color: #117cee; + } + + &.status-general { + color: #fbde28; + } + + &.status-moderate { + color: #ed740c; + } + + &.status-major { + color: #df2a3f; + } + } + + .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-low { + color: #117cee; + } + + &.status-general { + color: #fbde28; + } + + &.status-moderate { + color: #ed740c; + } + + &.status-major { + color: #df2a3f; + } + } } -.risk-table, .status-table { width: 100%; border-collapse: collapse; @@ -1616,7 +1785,7 @@ onMounted(() => { } th { - font-weight: bold; + font-weight: bold; color: #333; } @@ -1627,6 +1796,13 @@ onMounted(() => { // 九宫格样式 .rectification-status-grid { + .empty-data-tip { + text-align: center; + padding: 40px 0; + color: #9ca3af; + font-size: 14px; + } + .grid-wrapper { display: flex; gap: 0; @@ -1715,6 +1891,74 @@ onMounted(() => { } } +// 外协管理网格样式(与隐患管理一致) +.region-distribution { + .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; + color: #374151; + + &.empty-header { + visibility: hidden; + } + } + + .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; + color: #1f2937; + + &:last-child { + margin-bottom: 0; + } + } +} + .high-risk-top { display: flex; align-items: center; diff --git a/src/views/Home/Index13.vue b/src/views/Home/Index13.vue index 323c1b1..1948ec4 100644 --- a/src/views/Home/Index13.vue +++ b/src/views/Home/Index13.vue @@ -38,16 +38,33 @@
-
供应商分布
-
-
- - {{ item.supplier }} - {{ item.count }}人 - ({{ item.percent }}) -
-
+
供应商人数分布
+
+ +
+
+
+ {{ item.supplier }}
+
+ +
+
人数
+
+ {{ item.count }}人 +
+
+ +
+
占比
+
+ {{ item.percent }} +
+
+
+
@@ -66,28 +83,47 @@
地点风险分布
-
- - - - - - - - - - - - - - - - - - - -
所在地点一般较大重大
{{ item.location }}{{ item.low || '' }}{{ item.general }}{{ item.moderate }}{{ item.major }}
-
+
+ +
+
+
+ {{ item.location }} +
+
+ +
+
+
+ {{ item.low || '0' }} +
+
+ +
+
一般
+
+ {{ item.general || '0' }} +
+
+ +
+
较大
+
+ {{ item.moderate || '0' }} +
+
+ +
+
重大
+
+ {{ item.major || '0' }} +
+
+
@@ -107,7 +143,10 @@
所属公司整改状态
-
+
+ 暂无数据 +
+
@@ -119,21 +158,21 @@
已逾期
- {{ item.overdue }} + {{ item.overdue ?? 0 }}
处理中
- {{ item.processing }} + {{ item.processing ?? 0 }}
已处理
- {{ item.processed }} + {{ item.processed ?? 0 }}
@@ -319,22 +358,22 @@ const route = useRoute() // 应急预案:/yayl/table/view/1966394259751907330 // 安全培训:/pxks/table/view/1968225010550091777 const openOutsourcingManagement = () => { - window.open('/person/table/view/1959187451673116674', '_blank') + router.push('/person/table/view/1959187451673116674') } const openRiskManagement = () => { - window.open('/fx/table/view/1978723750599790594', '_blank') + router.push('/fx/table/view/1978723750599790594') } const openHiddenDangerManagement = () => { - window.open('/fx/table/view/1963446160885366786', '_blank') + router.push('/fx/table/view/1963446160885366786') } const openHighRiskManagement = () => { - window.open('/low/table/view/1964253329070571521', '_blank') + router.push('/low/table/view/1964253329070571521') } const openEmergencyPlanManagement = () => { - window.open('/yayl/table/view/1966394259751907330', '_blank') + router.push('/yayl/table/view/1966394259751907330') } const openTrainingManagement = () => { - window.open('/pxks/table/view/1968225010550091777', '_blank') + router.push('/pxks/table/view/1968225010550091777') } // 园区名称 - 从路由参数获取 const selectedPark = ref('') @@ -1051,8 +1090,11 @@ const riskChartOption = computed(() => { // 隐患管理折线图配置 const hiddenDangerChartOption = computed(() => { const dates = hiddenDangerTrend.value.map(item => item.date) - const generalData = hiddenDangerTrend.value.map(item => item.general) - const majorData = hiddenDangerTrend.value.map(item => item.major) + const generalData = hiddenDangerTrend.value.map(item => item.general ?? 0) + const majorData = hiddenDangerTrend.value.map(item => item.major ?? 0) + + // 判断是否为空数据 + const isEmpty = dates.length === 0 || (generalData.every(v => v === 0) && majorData.every(v => v === 0)) return { tooltip: { trigger: 'axis' }, @@ -1060,14 +1102,41 @@ const hiddenDangerChartOption = computed(() => { data: ['一般隐患', '重大隐患'], top: 10 }, - grid: { left: '3%', right: '4%', bottom: '3%', containLabel: true }, + grid: { left: '3%', right: '4%', bottom: '3%', top: '12%', containLabel: true }, xAxis: { type: 'category', boundaryGap: false, - data: dates + data: dates, + show: !isEmpty }, - yAxis: { type: 'value', max: 45 }, - series: [ + yAxis: { + type: 'value', + max: 45, + show: !isEmpty + }, + graphic: isEmpty ? [ + { + type: 'group', + left: 'center', + top: 'center', + children: [ + { + type: 'text', + z: 100, + left: 'center', + top: 'center', + style: { + text: '暂无数据', + fontSize: 16, + fontWeight: 'normal', + fill: '#9ca3af', + textAlign: 'center' + } + } + ] + } + ] : [], + series: isEmpty ? [] : [ { name: '一般隐患', type: 'line', @@ -1466,6 +1535,14 @@ onMounted(() => { font-weight: bold; color: #333; margin-bottom: 10px; + display: flex; + align-items: center; + justify-content: space-between; + span { + font-size: 14px; + font-weight: 600; + color: #374151; + } } .distribution-list { @@ -1502,11 +1579,104 @@ onMounted(() => { color: #999; } -.table-wrapper { - overflow-x: auto; +// 风险管理网格样式(与隐患管理一致) +.risk-distribution-table { + .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-low { + color: #117cee; + } + + &.status-general { + color: #fbde28; + } + + &.status-moderate { + color: #ed740c; + } + + &.status-major { + color: #df2a3f; + } + } + + .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-low { + color: #117cee; + } + + &.status-general { + color: #fbde28; + } + + &.status-moderate { + color: #ed740c; + } + + &.status-major { + color: #df2a3f; + } + } } -.risk-table, .status-table { width: 100%; border-collapse: collapse; @@ -1535,6 +1705,13 @@ onMounted(() => { // 九宫格样式 // 九宫格样式 .rectification-status-grid { + .empty-data-tip { + text-align: center; + padding: 40px 0; + color: #9ca3af; + font-size: 14px; + } + .grid-wrapper { display: flex; gap: 0; @@ -1623,6 +1800,74 @@ onMounted(() => { } } +// 外协管理网格样式(与隐患管理一致) +.region-distribution { + .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; + color: #374151; + + &.empty-header { + visibility: hidden; + } + } + + .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; + color: #1f2937; + + &:last-child { + margin-bottom: 0; + } + } +} + .high-risk-top { display: flex; align-items: center;