From 833d0b717734b08c8b32ae057679282be6c2b66d Mon Sep 17 00:00:00 2001 From: xiangpei <xiangpei@timesnew.cn> Date: 星期四, 05 六月 2025 16:25:41 +0800 Subject: [PATCH] 首页 --- src/assets/styles/ruoyi.scss | 2 src/views/index-nongtou.vue | 882 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/router/index.js | 2 3 files changed, 884 insertions(+), 2 deletions(-) diff --git a/src/assets/styles/ruoyi.scss b/src/assets/styles/ruoyi.scss index 2a328ff..14d1b7e 100644 --- a/src/assets/styles/ruoyi.scss +++ b/src/assets/styles/ruoyi.scss @@ -197,7 +197,7 @@ } .el-card__header { - padding: 14px 15px 7px !important; + padding: 7px 15px 7px !important; min-height: 40px; } diff --git a/src/router/index.js b/src/router/index.js index 64c8440..99fc5a2 100644 --- a/src/router/index.js +++ b/src/router/index.js @@ -68,7 +68,7 @@ children: [ { path: 'index', - component: () => import('@/views/index'), + component: () => import('@/views/index-nongtou'), name: 'Index', meta: { title: '棣栭〉', icon: 'dashboard', affix: true } } diff --git a/src/views/index-nongtou.vue b/src/views/index-nongtou.vue new file mode 100644 index 0000000..2ad76fc --- /dev/null +++ b/src/views/index-nongtou.vue @@ -0,0 +1,882 @@ +<template> + <div class="project-management-container"> + <!-- 椤甸潰鏍囬 --> +<!-- <div class="page-header">--> +<!-- <h1>椤圭洰绠$悊绯荤粺</h1>--> +<!-- <div class="user-info">--> +<!-- <span>娆㈣繋锛寋{ userName }}</span>--> +<!-- <el-avatar :size="36" :src="userAvatar"></el-avatar>--> +<!-- </div>--> +<!-- </div>--> + + <!-- 鏁版嵁姒傝鍗$墖 --> + <div class="overview-cards"> + <el-card class="overview-card" shadow="hover"> + <div class="card-content"> + <div class="card-icon" style="background-color: #409EFF20;"> + <i class="el-icon-s-data" style="color: #409EFF;"></i> + </div> + <div class="card-info"> + <div class="card-title">椤圭洰鎬绘暟</div> + <div class="card-value">{{ overviewData.totalProjects }}</div> + </div> + </div> + </el-card> + + <el-card class="overview-card" shadow="hover"> + <div class="card-content"> + <div class="card-icon" style="background-color: #67C23A20;"> + <i class="el-icon-success" style="color: #67C23A;"></i> + </div> + <div class="card-info"> + <div class="card-title">杩涜涓�</div> + <div class="card-value">{{ overviewData.inProgress }}</div> + </div> + </div> + </el-card> + + <el-card class="overview-card" shadow="hover"> + <div class="card-content"> + <div class="card-icon" style="background-color: #E6A23C20;"> + <i class="el-icon-warning" style="color: #E6A23C;"></i> + </div> + <div class="card-info"> + <div class="card-title">鏈夐闄�</div> + <div class="card-value">{{ overviewData.atRisk }}</div> + </div> + </div> + </el-card> + + <el-card class="overview-card" shadow="hover"> + <div class="card-content"> + <div class="card-icon" style="background-color: #F56C6C20;"> + <i class="el-icon-error" style="color: #F56C6C;"></i> + </div> + <div class="card-info"> + <div class="card-title">宸插欢鏈�</div> + <div class="card-value">{{ overviewData.delayed }}</div> + </div> + </div> + </el-card> + </div> + + <!-- 涓昏鍐呭鍖哄煙 --> + <div class="main-content"> + <!-- 宸︿晶鍐呭 --> + <div class="left-content"> + <!-- 椤圭洰杩涘害鍥捐〃 --> + <el-card class="chart-card" style="min-height: 400px" shadow="hover"> + <div slot="header" class="clearfix row"> + <div style="flex: 1">椤圭洰杩涘害缁熻</div> + <div style="flex: 3;display: flex;justify-content: flex-end"> + <el-select + v-model="selectedMonth" + placeholder="閫夋嫨鏈堜唤" + style="width: 120px; margin-right: 10px;" + @change="updateProgressChart" + > + <el-option + v-for="month in months" + :key="month.value" + :label="month.label" + :value="month.value" + ></el-option> + </el-select> + <el-select + v-model="selectedProjects" + multiple + collapse-tags + placeholder="閫夋嫨椤圭洰" + style="width: 350px; margin-right: 10px;" + @change="updateProgressChart" + > + <el-option + v-for="project in allProjects" + :key="project.id" + :label="project.name" + :value="project.id" + ></el-option> + </el-select> + <el-button type="text" @click="showDetail">璇︽儏</el-button> + </div> + </div> + <div class="chart-container" ref="progressChart" style="height: 400px;"></div> + </el-card> + + <!-- 鍗$偣浠诲姟鍒楄〃 --> + <el-card class="blocking-tasks-card" shadow="hover"> + <div slot="header" class="clearfix row"> + <div style="flex: 1">鎺ㄨ繘鍗$偣</div> + <div style="flex: 3; display: flex; justify-content: flex-end"> + <el-button type="text">鍏ㄩ儴</el-button> + </div> + </div> + <el-table :data="blockingTasks" style="width: 100%" height="250"> + <el-table-column prop="taskName" label="浠诲姟鍚嶇О" width="180"></el-table-column> + <el-table-column prop="project" label="鎵�灞為」鐩�"></el-table-column> + <el-table-column prop="owner" label="璐熻矗浜�" width="100"></el-table-column> + <el-table-column prop="startTime" label="寮�濮嬫椂闂�" width="120"></el-table-column> + <el-table-column prop="deadline" label="鎴鏃ユ湡" width="120"></el-table-column> + <el-table-column prop="overTime" label="宸茶秴鏃�" width="120"></el-table-column> + <el-table-column prop="totalOverTimes" label="绱瓒呮椂娆℃暟" width="120" align="center"></el-table-column> + <el-table-column label="鎿嶄綔" width="80"> + <template slot-scope="scope"> + <el-button size="mini" @click="handleTaskDetail(scope.row)">鏌ョ湅</el-button> + </template> + </el-table-column> + </el-table> + </el-card> + </div> + + <!-- 鍙充晶鍐呭 --> + <div class="right-content"> + <!-- 璧勯噾浣跨敤鎯呭喌 --> + <el-card class="chart-card" style="min-height: 400px" shadow="hover"> + <div slot="header" class="clearfix"> + <span>璧勯噾浣跨敤鎯呭喌</span> + <div style="float: right;"> + <el-select + v-model="fundSelectedProjects" + multiple + collapse-tags + placeholder="閫夋嫨椤圭洰" + style="width: 350px; margin-right: 10px;" + @change="updateFundChart" + > + <el-option + v-for="project in allProjects" + :key="project.id" + :label="project.name" + :value="project.id" + ></el-option> + </el-select> + <el-button type="text" @click="showFundDetail">璇︽儏</el-button> + </div> + </div> + <div class="chart-container" ref="fundChart" style="height: 400px;"></div> + </el-card> + + <!-- 椤圭洰闃舵缁熻 --> + <el-card class="chart-card" shadow="hover"> + <div slot="header" class="clearfix row"> + <div style="flex:1">椤圭洰闃舵缁熻</div> + <div style="flex:3;display: flex;justify-content: flex-end"> + <el-button type="text">璇︽儏</el-button> + </div> + </div> + <div class="chart-container" ref="stageChart" style="height: 250px;"></div> + </el-card> + </div> + </div> + </div> +</template> + +<script> +import * as echarts from 'echarts'; + +export default { + name: 'ProjectManagement', + data() { + return { + userName: '寮犵粡鐞�', + userAvatar: 'https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png', + overviewData: { + totalProjects: 42, + inProgress: 28, + atRisk: 7, + delayed: 5 + }, + blockingTasks: [ + { + taskName: '鍙栧緱鍦熷湴鏉冨睘', + project: '灏勬椽甯傞厭绮熀鍦板缓璁鹃」鐩�', + owner: '鏉庡洓', + startTime: '2025-05-15', + overTime: '10澶�06灏忔椂', + deadline: '2025-06-05', + totalOverTimes: 4, + status: '绱ф��' + }, + { + taskName: '鍙鎬х爺绌舵姤鍛婄敵璇�', + project: '灏勬椽甯傞厭绮熀鍦板缓璁鹃」鐩�', + owner: '鐜嬩簲', + startTime: '2025-05-21', + overTime: '8澶�', + deadline: '2025-05-30', + totalOverTimes: '5', + status: '楂橀闄�' + }, + { + taskName: '寤鸿宸ョ▼绔e伐楠屾敹鐢宠', + project: '灏勬椽甯傚疁灞呭疁涓氬拰缇庝埂鏉戝缓璁鹃」鐩�', + owner: '璧靛叚', + startTime: '2025-05-24', + overTime: '4澶�14灏忔椂', + deadline: '2025-06-04', + totalOverTimes: '4', + status: '寤舵湡' + }, + { + taskName: '鐢熶骇寤鸿椤圭洰姘村湡淇濇寔鏂规缂栧埗', + project: '灏勬椽甯傚疁灞呭疁涓氬拰缇庝埂鏉戝缓璁鹃」鐩�', + owner: '閽变竷', + startTime: '2025-06-01', + overTime: '4澶�', + deadline: '2025-06-07', + totalOverTimes: '6', + status: '杩涜涓�' + }, + ], + progressChart: null, + fundChart: null, + stageChart: null, + // 绛涢�夋暟鎹� + selectedMonth: '2025-06', + months: [ + { value: '2025-05', label: '2025骞�5鏈�' }, + { value: '2025-06', label: '2025骞�6鏈�' }, + { value: '2025-07', label: '2025骞�7鏈�' }, + { value: '2025-08', label: '2025骞�8鏈�' } + ], + selectedProjects: [], + fundSelectedProjects: [], + allProjects: [ + { id: 'p1', name: '灏勬椽甯傚浗瀹跺偍澶囨灄寤鸿椤圭洰锛堜竴鏈燂級' }, + { id: 'p2', name: '灏勬椽甯傜櫧缇借倝楦′骇涓氬缓璁鹃」鐩�' }, + { id: 'p3', name: '閬傚畞甯傚皠娲�2024鈥�2027骞村害涓滃寳鐗囧尯楂樻爣鍑嗗啘鐢板缓璁鹃」鐩�' }, + { id: 'p4', name: '灏勬椽甯傜幇浠g涓氱ず鑼冨熀鍦板缓璁鹃」鐩�' }, + { id: 'p5', name: '灏勬椽甯傚疁灞呭疁涓氬拰缇庝埂鏉戝缓璁鹃」鐩�' }, + { id: 'p6', name: '灏勬椽甯傛脖鐗岄晣缁煎悎姘村埄璁炬柦寤鸿椤圭洰' } + ], + // 椤圭洰杩涘害妯℃嫙鏁版嵁 + progressData: { + '2025-05': { + 'p1': { completed: 30, inProgress: 50, notStarted: 20 }, + 'p2': { completed: 40, inProgress: 40, notStarted: 20 }, + 'p3': { completed: 10, inProgress: 60, notStarted: 30 }, + 'p4': { completed: 60, inProgress: 30, notStarted: 10 }, + 'p5': { completed: 25, inProgress: 45, notStarted: 30 }, + 'p6': { completed: 35, inProgress: 35, notStarted: 30 } + }, + '2025-06': { + 'p1': { completed: 50, inProgress: 40, notStarted: 10 }, + 'p2': { completed: 60, inProgress: 30, notStarted: 10 }, + 'p3': { completed: 30, inProgress: 50, notStarted: 20 }, + 'p4': { completed: 80, inProgress: 15, notStarted: 5 }, + 'p5': { completed: 45, inProgress: 35, notStarted: 20 }, + 'p6': { completed: 55, inProgress: 25, notStarted: 20 } + }, + '2025-07': { + 'p1': { completed: 70, inProgress: 25, notStarted: 5 }, + 'p2': { completed: 80, inProgress: 15, notStarted: 5 }, + 'p3': { completed: 50, inProgress: 40, notStarted: 10 }, + 'p4': { completed: 90, inProgress: 10, notStarted: 0 }, + 'p5': { completed: 65, inProgress: 25, notStarted: 10 }, + 'p6': { completed: 75, inProgress: 15, notStarted: 10 } + }, + '2025-08': { + 'p1': { completed: 90, inProgress: 10, notStarted: 0 }, + 'p2': { completed: 95, inProgress: 5, notStarted: 0 }, + 'p3': { completed: 70, inProgress: 25, notStarted: 5 }, + 'p4': { completed: 100, inProgress: 0, notStarted: 0 }, + 'p5': { completed: 85, inProgress: 10, notStarted: 5 }, + 'p6': { completed: 90, inProgress: 5, notStarted: 5 } + } + }, + // 璧勯噾浣跨敤妯℃嫙鏁版嵁 + fundData: { + 'p1': { + total: 5000, + allocated: 3500, + remaining: 1500, + completed: 2800, + sources: { + projectCapital: 2000, + countyInvestment: 1500, + otherInvestment: 1000, + governmentInvestment: 500 + } + }, + 'p2': { + total: 3200, + allocated: 2500, + remaining: 700, + completed: 1800, + sources: { + projectCapital: 1200, + countyInvestment: 1000, + governmentInvestment: 1000 + } + }, + 'p3': { + total: 4200, + allocated: 3000, + remaining: 1200, + completed: 2200, + sources: { + projectCapital: 1500, + otherInvestment: 1200, + governmentInvestment: 1500 + } + }, + 'p4': { + total: 2800, + allocated: 2000, + remaining: 800, + completed: 1500, + sources: { + projectCapital: 1000, + countyInvestment: 800, + otherInvestment: 500, + governmentInvestment: 500 + } + }, + 'p5': { + total: 3800, + allocated: 3000, + remaining: 800, + completed: 2500, + sources: { + projectCapital: 1500, + countyInvestment: 1000, + governmentInvestment: 1300 + } + }, + 'p6': { + total: 4500, + allocated: 3500, + remaining: 1000, + completed: 3000, + sources: { + projectCapital: 2000, + countyInvestment: 1500, + otherInvestment: 500, + governmentInvestment: 500 + } + } + } + }; + }, + mounted() { + this.selectedProjects = this.allProjects.map(p => p.id); // 榛樿鍏ㄩ�� + this.fundSelectedProjects = this.allProjects.map(p => p.id); // 榛樿鍏ㄩ�� + this.initCharts(); + window.addEventListener('resize', this.handleResize); + }, + beforeDestroy() { + window.removeEventListener('resize', this.handleResize); + if (this.progressChart) { + this.progressChart.dispose(); + } + if (this.fundChart) { + this.fundChart.dispose(); + } + if (this.stageChart) { + this.stageChart.dispose(); + } + }, + methods: { + initCharts() { + // 鍒濆鍖栭」鐩繘搴﹀浘琛� + this.progressChart = echarts.init(this.$refs.progressChart); + this.updateProgressChart(); + + // 鍒濆鍖栬祫閲戜娇鐢ㄦ儏鍐靛浘琛� + this.fundChart = echarts.init(this.$refs.fundChart); + this.updateFundChart(); + + // 鍒濆鍖栭」鐩樁娈电粺璁″浘琛� + this.stageChart = echarts.init(this.$refs.stageChart); + this.stageChart.setOption({ + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + } + }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + containLabel: true + }, + xAxis: { + type: 'category', + data: ['鍦ㄥ簱', '鍌ㄥ', '鍓嶆湡', '瀹炴柦', '绔e伐'], + axisLine: { + lineStyle: { + color: '#409EFF' + } + } + }, + yAxis: { + type: 'value', + axisLine: { + lineStyle: { + color: '#409EFF' + } + } + }, + series: [ + { + data: [15, 12, 10, 8, 6, 4, 2], + type: 'line', + smooth: true, + lineStyle: { + width: 3, + color: '#409EFF' + }, + itemStyle: { + color: '#409EFF' + }, + areaStyle: { + color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [ + { + offset: 0, + color: 'rgba(64, 158, 255, 0.5)' + }, + { + offset: 1, + color: 'rgba(64, 158, 255, 0.1)' + } + ]) + } + } + ] + }); + }, + + // 鏇存柊椤圭洰杩涘害鍥捐〃鏁版嵁 + updateProgressChart() { + if (!this.progressChart) return; + + const monthData = this.progressData[this.selectedMonth]; + const filteredProjects = this.allProjects.filter(p => + this.selectedProjects.includes(p.id) + ); + + const categories = filteredProjects.map(p => p.name); + const completedData = filteredProjects.map(p => monthData[p.id].completed); + const inProgressData = filteredProjects.map(p => monthData[p.id].inProgress); + const notStartedData = filteredProjects.map(p => monthData[p.id].notStarted); + + this.progressChart.setOption({ + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + }, + formatter: function(params) { + let result = params[0].name + '<br/>'; + params.forEach(param => { + result += `${param.seriesName}: ${param.value}%<br/>`; + }); + result += `鎬昏: ${params.reduce((sum, param) => sum + param.value, 0)}%`; + return result; + } + }, + legend: { + data: ['宸插畬鎴愪簨椤�', '杩涜涓簨椤�', '鏈紑濮嬩簨椤�'] + }, + grid: { + left: '3%', + right: '4%', + bottom: '3%', + containLabel: true + }, + xAxis: { + type: 'value', + max: 100, + axisLabel: { + formatter: '{value}%' + } + }, + yAxis: { + type: 'category', + data: categories + }, + series: [ + { + name: '宸插畬鎴愪簨椤�', + type: 'bar', + stack: 'total', + emphasis: { + focus: 'series' + }, + data: completedData, + itemStyle: { + color: '#67C23A' + }, + label: { + show: true, + position: 'inside', + formatter: '{c}%' + } + }, + { + name: '杩涜涓簨椤�', + type: 'bar', + stack: 'total', + emphasis: { + focus: 'series' + }, + data: inProgressData, + itemStyle: { + color: '#409EFF' + }, + label: { + show: true, + position: 'inside', + formatter: '{c}%' + } + }, + { + name: '鏈紑濮嬩簨椤�', + type: 'bar', + stack: 'total', + emphasis: { + focus: 'series' + }, + data: notStartedData, + itemStyle: { + color: '#E6A23C' + }, + label: { + show: true, + position: 'inside', + formatter: '{c}%' + } + } + ] + }); + }, + + // 鏇存柊璧勯噾浣跨敤鍥捐〃鏁版嵁 + updateFundChart() { + if (!this.fundChart) return; + + const filteredProjects = this.allProjects.filter(p => + this.fundSelectedProjects.includes(p.id) + ); + + const categories = filteredProjects.map(p => p.name); + const allocatedData = filteredProjects.map(p => this.fundData[p.id].allocated); + const remainingData = filteredProjects.map(p => this.fundData[p.id].remaining); + + // 璧勯噾鏉ユ簮鏁版嵁 + const projectCapitalData = filteredProjects.map(p => + this.fundData[p.id].sources.projectCapital || 0 + ); + const countyInvestmentData = filteredProjects.map(p => + this.fundData[p.id].sources.countyInvestment || 0 + ); + const otherInvestmentData = filteredProjects.map(p => + this.fundData[p.id].sources.otherInvestment || 0 + ); + const governmentInvestmentData = filteredProjects.map(p => + this.fundData[p.id].sources.governmentInvestment || 0 + ); + + this.fundChart.setOption({ + tooltip: { + trigger: 'axis', + axisPointer: { + type: 'shadow' + }, + formatter: function(params) { + let result = params[0].name + '<br/>'; + // 璧勯噾鎷ㄤ粯鍜屽墿浣� + result += `璧勯噾鎷ㄤ粯: ${params[0].value}涓囧厓<br/>`; + result += `鍓╀綑閲戦: ${params[1].value}涓囧厓<br/>`; + result += `鎬婚噾棰�: ${params[0].value + params[1].value}涓囧厓<br/>`; + result += `瀹屾垚鎶曡祫: ${params[0].axisValueLabel}涓囧厓<br/><br/>`; + + // 璧勯噾鏉ユ簮 + result += '<strong>璧勯噾鏉ユ簮鏋勬垚:</strong><br/>'; + result += `椤圭洰鏈噾: ${params[2].value}涓囧厓<br/>`; + result += `鍘�(甯傘�佸尯)鎶曡祫: ${params[3].value}涓囧厓<br/>`; + result += `鍏朵粬鎶曡祫: ${params[4].value}涓囧厓<br/>`; + result += `鏀垮簻鎶曡祫: ${params[5].value}涓囧厓<br/>`; + + return result; + } + }, + legend: { + data: ['鍓╀綑閲戦', '璧勯噾鎷ㄤ粯', '椤圭洰鏈噾', '鍘�(甯傘�佸尯)鎶曡祫', '鏀垮簻鎶曡祫', '鍏朵粬鎶曡祫'] + }, + grid: { + top: '30%', + left: '3%', + right: '4%', + bottom: '5%', + containLabel: true + }, + xAxis: { + type: 'category', + data: categories, + axisLabel: { + interval: 0, + rotate: 30 + } + }, + yAxis: { + type: 'value', + name: '閲戦(涓囧厓)' + }, + series: [ + { + name: '璧勯噾鎷ㄤ粯', + type: 'bar', + stack: 'total', + emphasis: { + focus: 'series' + }, + data: allocatedData, + itemStyle: { + color: '#409EFF' + }, + label: { + show: true, + position: 'inside', + formatter: '{c}' + } + }, + { + name: '鍓╀綑閲戦', + type: 'bar', + stack: 'total', + emphasis: { + focus: 'series' + }, + data: remainingData, + itemStyle: { + color: '#E6A23C' + }, + label: { + show: true, + position: 'inside', + formatter: '{c}' + } + }, + { + name: '椤圭洰鏈噾', + type: 'bar', + stack: 'sources', + emphasis: { + focus: 'series' + }, + data: projectCapitalData, + itemStyle: { + color: '#67C23A' + } + }, + { + name: '鍘�(甯傘�佸尯)鎶曡祫', + type: 'bar', + stack: 'sources', + emphasis: { + focus: 'series' + }, + data: countyInvestmentData, + itemStyle: { + color: '#F56C6C' + } + }, + { + name: '鍏朵粬鎶曡祫', + type: 'bar', + stack: 'sources', + emphasis: { + focus: 'series' + }, + data: otherInvestmentData, + itemStyle: { + color: '#909399' + } + }, + { + name: '鏀垮簻鎶曡祫', + type: 'bar', + stack: 'sources', + emphasis: { + focus: 'series' + }, + data: governmentInvestmentData, + itemStyle: { + color: '#8E44AD' + } + } + ] + }); + }, + + // 鏇存柊鎵�鏈夊浘琛� + updateCharts() { + this.updateProgressChart(); + this.updateFundChart(); + }, + + handleResize() { + if (this.progressChart) { + this.progressChart.resize(); + } + if (this.fundChart) { + this.fundChart.resize(); + } + if (this.stageChart) { + this.stageChart.resize(); + } + }, + getStatusTagType(status) { + const map = { + '绱ф��': 'danger', + '楂橀闄�': 'warning', + '寤舵湡': 'info', + '杩涜涓�': 'primary' + }; + return map[status] || ''; + }, + handleTaskDetail(task) { + this.$message.info(`鏌ョ湅浠诲姟璇︽儏: ${task.taskName}`); + }, + showDetail() { + this.$message.info(`鏌ョ湅${this.selectedMonth}鏈堜唤鐨勯」鐩繘搴﹁鎯卄); + }, + showFundDetail() { + this.$message.info('鏌ョ湅璧勯噾浣跨敤璇︽儏'); + } + } +}; +</script> + +<style scoped> +.project-management-container { + padding: 20px; + background-color: #f5f7fa; + min-height: 100vh; +} + +.page-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + padding-bottom: 15px; + border-bottom: 1px solid #ebeef5; +} + +.page-header h1 { + color: #409EFF; + margin: 0; +} + +.user-info { + display: flex; + align-items: center; +} + +.user-info span { + margin-right: 10px; + color: #606266; +} + +.overview-cards { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 20px; + margin-bottom: 20px; +} + +.overview-card { + border-radius: 8px; + border-top: 3px solid #409EFF; +} + +.overview-card:nth-child(1) { + border-top-color: #409EFF; +} +.overview-card:nth-child(2) { + border-top-color: #67C23A; +} +.overview-card:nth-child(3) { + border-top-color: #E6A23C; +} +.overview-card:nth-child(4) { + border-top-color: #F56C6C; +} + +.card-content { + display: flex; + align-items: center; + padding: 10px 0; +} + +.card-icon { + width: 50px; + height: 50px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + margin-right: 15px; +} + +.card-icon i { + font-size: 24px; +} + +.card-info { + flex: 1; +} + +.card-title { + font-size: 14px; + color: #909399; + margin-bottom: 5px; +} + +.card-value { + font-size: 24px; + font-weight: bold; + color: #303133; +} + +.main-content { + display: grid; + grid-template-columns: 2fr 1fr; + gap: 20px; +} + +.chart-card, .blocking-tasks-card { + border-radius: 8px; + margin-bottom: 20px; + border: 1px solid #ebeef5; +} + +.chart-card >>> .el-card__header { + background-color: #f5f7fa; + border-bottom: 1px solid #ebeef5; + padding: 12px 20px; + font-weight: bold; + color: #409EFF; +} + +.blocking-tasks-card >>> .el-card__header { + background-color: #f5f7fa; + border-bottom: 1px solid #ebeef5; + padding: 12px 20px; + font-weight: bold; + color: #409EFF; +} + +.chart-container { + width: 100%; +} + +.row { + display: flex; + align-items: center; + height: 36px; +} +</style> -- Gitblit v1.8.0