| | |
| | | } |
| | | |
| | | .el-card__header { |
| | | padding: 14px 15px 7px !important; |
| | | padding: 7px 15px 7px !important; |
| | | min-height: 40px; |
| | | } |
| | | |
| | |
| | | children: [ |
| | | { |
| | | path: 'index', |
| | | component: () => import('@/views/index'), |
| | | component: () => import('@/views/index-nongtou'), |
| | | name: 'Index', |
| | | meta: { title: '首页', icon: 'dashboard', affix: true } |
| | | } |
New file |
| | |
| | | <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: '建设工程竣工验收申请', |
| | | 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: '射洪市现代种业示范基地建设项目' }, |
| | | { 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: ['在库', '储备', '前期', '实施', '竣工'], |
| | | 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> |