| | |
| | | # 页面标题 |
| | | VUE_APP_TITLE = 射洪智慧项目管理系统 |
| | | VUE_APP_TITLE = 农投项目管理系统 |
| | | |
| | | # 开发环境配置 |
| | | ENV = 'development' |
| | | |
| | | # 射洪智慧项目管理系统/开发环境 |
| | | # 农投项目管理系统/开发环境 |
| | | VUE_APP_BASE_API = '/dev-api' |
| | | |
| | | # 路由懒加载 |
| | |
| | | # 页面标题 |
| | | VUE_APP_TITLE = 射洪智慧项目管理系统 |
| | | VUE_APP_TITLE = 农投项目管理系统 |
| | | |
| | | # 生产环境配置 |
| | | ENV = 'production' |
| | | |
| | | # 射洪智慧项目管理系统/生产环境 |
| | | # 农投项目管理系统/生产环境 |
| | | VUE_APP_BASE_API = '/prod-api' |
| | | |
| | | # 开打新的tab的url前缀 |
| | |
| | | # 页面标题 |
| | | VUE_APP_TITLE = 射洪智慧项目管理系统 |
| | | VUE_APP_TITLE = 农投项目管理系统 |
| | | |
| | | BABEL_ENV = production |
| | | |
| | |
| | | # 测试环境配置 |
| | | ENV = 'staging' |
| | | |
| | | # 射洪智慧项目管理系统/测试环境 |
| | | # 农投项目管理系统/测试环境 |
| | | VUE_APP_BASE_API = '/stage-api' |
| | |
| | | { |
| | | "name": "ruoyi", |
| | | "version": "3.8.8", |
| | | "description": "射洪智慧项目管理系统", |
| | | "description": "农投项目管理系统", |
| | | "author": "射洪项目", |
| | | "license": "MIT", |
| | | "scripts": { |
| | |
| | | } |
| | | |
| | | .el-card__header { |
| | | padding: 14px 15px 7px !important; |
| | | padding: 7px 15px 7px !important; |
| | | min-height: 40px; |
| | | } |
| | | |
| | |
| | | // 文件类型, 例如['png', 'jpg', 'jpeg'] |
| | | fileType: { |
| | | type: Array, |
| | | default: () => ["doc", "xls", "ppt", "txt", "pdf"], |
| | | default: () => ["doc", "docx", "xls", "xlsx", "ppt", "txt", "pdf", "jpg", "png"], |
| | | }, |
| | | // 是否显示提示 |
| | | isShowTip: { |
| | |
| | | <div class="navbar"> |
| | | <div class="ruoyi-logo"> |
| | | <img src="@/assets/logo/logo.png" alt="" /> |
| | | <span>射洪智慧项目管理系统</span> |
| | | <span>农投项目管理系统</span> |
| | | </div> |
| | | <div class="right-menu flex align-center"> |
| | | <div style="color: rgb(49,48,48);margin-right: 30px;font-size: 16px"> |
| | |
| | | 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> |
| | |
| | | <div class="login"> |
| | | <div class="nav"> |
| | | <img alt="" src="../assets/images/bj.png" /> |
| | | <div class="ml-[10px]">射洪智慧项目管理系统</div> |
| | | <div class="ml-[10px]">农投项目管理系统</div> |
| | | </div> |
| | | <div class="conter"> |
| | | <div class="left"> |
| | | <div class="title">射洪智慧项目管理系统</div> |
| | | <div class="title">农投项目管理系统</div> |
| | | <div> |
| | | 运用系统的观点、方法和理论,对项目涉及的全部工作进行有效地管理 |
| | | </div> |
| | |
| | | class="login-corporation" |
| | | @click="currentClick('corporation')" |
| | | > |
| | | 法人登录 |
| | | </div> |
| | | <div |
| | | :class="{ active: currentTab === 'supervise' }" |
| | | class="login-supervise" |
| | | @click="superviseClick('supervise')" |
| | | > |
| | | 监管部门登录 |
| | | 账号登录 |
| | | </div> |
| | | </div> |
| | | <el-form |
| | |
| | | .right { |
| | | border-radius: 6px; |
| | | background: #ffffff; |
| | | width: 500px; |
| | | width: 450px; |
| | | padding: 0px 25px 5px 25px; |
| | | |
| | | .tab { |
New file |
| | |
| | | <template> |
| | | <div class="basic-info"> |
| | | <el-form ref="demoFormRef" :disabled="disabled" :model="projectFromForm" class="dialog_form"> |
| | | <el-form-item label="依据说明" label-width="120px" prop="projectFromWhere" style="width: 100%"> |
| | | <el-input type="textarea" v-model="projectFromForm.projectFromWhere" style="width: 100%" |
| | | placeholder="请输入"/> |
| | | </el-form-item> |
| | | <el-form-item label="依据附件" label-width="120px" prop="projectFromFile" style="width: 100%"> |
| | | <file-upload :limit="5" :file-size="100" @input="getUploadResult" /> |
| | | </el-form-item> |
| | | </el-form> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | |
| | | import FileUpload from "@/components/FileUpload" |
| | | |
| | | export default { |
| | | name: 'ProjectForm', |
| | | components: {FileUpload}, |
| | | props: { |
| | | disabled: { |
| | | type: Boolean, |
| | | default: false, |
| | | required: true |
| | | }, |
| | | }, |
| | | data() { |
| | | return { |
| | | projectFromForm: { |
| | | projectFromWhere: '', |
| | | projectFromFile: '', |
| | | }, |
| | | } |
| | | }, |
| | | mounted() { |
| | | |
| | | |
| | | }, |
| | | beforeDestroy() { |
| | | |
| | | }, |
| | | methods: { |
| | | getUploadResult(fileList) { |
| | | console.log("上传结果", fileList) |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | |
| | | </style> |
| | |
| | | import InvestInfo from "@/views/projectEngineering/projectLibrary/component/InvestInfo"; |
| | | import InvestmentFunds from "@/views/projectEngineering/projectLibrary/component/investmentFunds"; |
| | | import LegalPerson from "@/views/projectEngineering/projectLibrary/component/legalPerson"; |
| | | import ProjectFrom from "@/views/projectEngineering/projectLibrary/component/ProjectFrom"; |
| | | import PolicyInfo from "@/views/projectEngineering/projectLibrary/component/PolicyInfo"; |
| | | import DocumentsInfo from "@/views/projectEngineering/projectLibrary/component/DocumentsInfo"; |
| | | import { editProject } from "@/api/projectEngineering/projectInfo"; |
| | |
| | | value: "项目(法人)单位登记信息", |
| | | componentName: LegalPerson, |
| | | }, |
| | | { |
| | | label: "项目发起依据", |
| | | value: "项目发起依据", |
| | | componentName: ProjectFrom, |
| | | }, |
| | | // { |
| | | // label: "投资项目产业政策符合情况", |
| | | // value: "投资项目产业政策符合情况", |
New file |
| | |
| | | <template> |
| | | <div class="dashboard-container"> |
| | | <!-- 顶部导航栏 --> |
| | | <div class="top-navbar"> |
| | | <div class="welcome-message"> |
| | | <h2>早安,{{ this.$store.state.user.name }}!</h2> |
| | | <p>今天是{{ currentDate }},祝您工作愉快!</p> |
| | | </div> |
| | | <div class="quick-stats"> |
| | | <div class="stat-item"> |
| | | <span class="stat-number">{{ todayTasks }}</span> |
| | | <span class="stat-label">今日待办</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-number">{{ todaySchedules }}</span> |
| | | <span class="stat-label">今日日程</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-number">{{ unreadMessages }}</span> |
| | | <span class="stat-label">未读消息</span> |
| | | </div> |
| | | </div> |
| | | <div class="user-profile"> |
| | | <!-- <el-dropdown>--> |
| | | <!-- <div class="user-avatar">--> |
| | | <!-- <img :src="userInfo.avatar" alt="用户头像">--> |
| | | <!-- <span>{{ userInfo.name }}</span>--> |
| | | <!-- </div>--> |
| | | <!-- <el-dropdown-menu slot="dropdown">--> |
| | | <!-- <el-dropdown-item>个人中心</el-dropdown-item>--> |
| | | <!-- <el-dropdown-item>设置</el-dropdown-item>--> |
| | | <!-- <el-dropdown-item divided>退出登录</el-dropdown-item>--> |
| | | <!-- </el-dropdown-menu>--> |
| | | <!-- </el-dropdown>--> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 主内容区 --> |
| | | <div class="main-content"> |
| | | <!-- 左侧项目列表 --> |
| | | <div class="left-sidebar"> |
| | | <div class="project-list"> |
| | | <h3>项目列表</h3> |
| | | <el-menu |
| | | :default-active="activeProject" |
| | | class="project-menu" |
| | | @select="handleProjectSelect"> |
| | | <el-menu-item index="all"> |
| | | <i class="el-icon-menu"></i> |
| | | <span slot="title">全部项目</span> |
| | | </el-menu-item> |
| | | <el-menu-item |
| | | v-for="project in projects" |
| | | :key="project.id" |
| | | :index="project.id"> |
| | | <i class="el-icon-folder"></i> |
| | | <span slot="title" class="project-name" :title="project.name"> |
| | | {{ project.name }} |
| | | </span> |
| | | </el-menu-item> |
| | | </el-menu> |
| | | <div class="project-actions"> |
| | | <el-button type="primary" icon="el-icon-plus" size="small">新建项目</el-button> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 中间内容区 --> |
| | | <div class="center-content"> |
| | | <!-- 待办任务 --> |
| | | <div class="task-section"> |
| | | <div class="section-header"> |
| | | <h3>待办任务</h3> |
| | | <el-button type="text" icon="el-icon-refresh">刷新</el-button> |
| | | </div> |
| | | <el-table |
| | | :data="tasks" |
| | | border |
| | | style="width: 100%" |
| | | > |
| | | <el-table-column |
| | | prop="name" |
| | | label="任务名称" |
| | | width="240"> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="project" |
| | | label="所属项目" |
| | | show-overflow-tooltip |
| | | width="300"> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="startTime" |
| | | label="开始时间" |
| | | align="center" |
| | | width="160"> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="deadline" |
| | | label="截止时间" |
| | | align="center" |
| | | width="160"> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="status" |
| | | label="状态" |
| | | align="center" |
| | | width="100"> |
| | | <template slot-scope="scope"> |
| | | <el-tag :type="scope.row.status === '待完成' ? 'success' : 'warning'" size="small"> |
| | | {{ scope.row.status }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="操作" |
| | | fixed="right" |
| | | width="120"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="mini" @click="handleTaskEdit(scope.row)">办理</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <!-- 项目办理日志 --> |
| | | <div class="log-section"> |
| | | <div class="section-header"> |
| | | <h3>项目办理日志</h3> |
| | | <el-button type="text" icon="el-icon-refresh">刷新</el-button> |
| | | </div> |
| | | <div class="log-list"> |
| | | <div v-for="log in logs" :key="log.id" class="log-item"> |
| | | <div class="log-time">{{ log.time }}</div> |
| | | <div class="log-content"> |
| | | <span class="log-project">{{ log.project }}</span> |
| | | <span class="log-action">{{ log.action }}</span> |
| | | <span class="log-detail">{{ log.detail }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 右侧边栏 --> |
| | | <div class="right-sidebar"> |
| | | <!-- 个人成就 --> |
| | | <div class="achievement-section"> |
| | | <h3>个人成就</h3> |
| | | <div class="achievement-stats"> |
| | | <div class="stat-item"> |
| | | <div class="stat-number">{{ achievements.completedTasks }}</div> |
| | | <div class="stat-label">完成任务</div> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <div class="stat-number">{{ achievements.avgDuration }}天</div> |
| | | <div class="stat-label">平均用时</div> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <div class="stat-number">{{ achievements.totalSchedules }}</div> |
| | | <div class="stat-label">安排日程</div> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <div class="stat-number">{{ achievements.completedSchedules }}</div> |
| | | <div class="stat-label">完成日程</div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 日历 --> |
| | | <div class="calendar-section"> |
| | | <el-calendar v-model="calendarDate"> |
| | | <template |
| | | slot="dateCell" |
| | | slot-scope="{date, data}"> |
| | | <div class="calendar-day"> |
| | | {{ data.day.split('-').slice(2).join('-') }} |
| | | <div v-if="getScheduleCount(date) > 0" class="schedule-count"> |
| | | {{ getScheduleCount(date) }}个日程 |
| | | </div> |
| | | </div> |
| | | </template> |
| | | </el-calendar> |
| | | </div> |
| | | |
| | | <!-- 日程列表 --> |
| | | <div class="schedule-list-section"> |
| | | <div class="section-header"> |
| | | <h3>日程列表</h3> |
| | | <div> |
| | | <el-button type="text" icon="el-icon-plus" @click="handleAddSchedule">新增</el-button> |
| | | <el-button type="text" icon="el-icon-refresh">刷新</el-button> |
| | | </div> |
| | | </div> |
| | | <div class="schedule-list"> |
| | | <el-table |
| | | :data="filteredSchedules" |
| | | style="width: 100%" |
| | | height="250"> |
| | | <el-table-column |
| | | prop="time" |
| | | label="时间" |
| | | width="100"> |
| | | </el-table-column> |
| | | <el-table-column |
| | | prop="title" |
| | | label="事项" |
| | | width="120"> |
| | | </el-table-column> |
| | | <el-table-column |
| | | label="操作" |
| | | width="120"> |
| | | <template slot-scope="scope"> |
| | | <el-button size="mini" @click="handleEditSchedule(scope.row)">编辑</el-button> |
| | | <el-button size="mini" type="danger" @click="handleDeleteSchedule(scope.row)">删除</el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script> |
| | | export default { |
| | | data() { |
| | | return { |
| | | userInfo: { |
| | | name: '张工程师', |
| | | avatar: 'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png', |
| | | department: '项目部' |
| | | }, |
| | | currentDate: this.formatDate(new Date()), |
| | | todayTasks: 5, |
| | | todaySchedules: 3, |
| | | unreadMessages: 2, |
| | | activeProject: 'all', |
| | | projects: [ |
| | | { id: '1', name: '射洪市沱牌镇综合水利设施建设项目' }, |
| | | { id: '2', name: '射洪市国家储备林建设项目(一期)' }, |
| | | { id: '3', name: '射洪市白羽肉鸡产业建设项目' }, |
| | | { id: '4', name: '遂宁市射洪2024—2027年度东北片区高标准农田建设项目' }, |
| | | { id: '5', name: '射洪市现代种业示范基地建设项目' }, |
| | | ], |
| | | tasks: [ |
| | | { id: 1, name: '审核施工图纸', project: '射洪市国家储备林建设项目(一期)', startTime: '2025-05-05', deadline: '2025-06-15', status: '待完成' }, |
| | | { id: 2, name: '采购材料清单', project: '射洪市白羽肉鸡产业建设项目', startTime: '2025-05-14', deadline: '2025-06-18', status: '待完成' }, |
| | | { id: 3, name: '现场安全检查', project: '遂宁市射洪2024—2027年度东北片区高标准农田建设项目', startTime: '2025-05-10', deadline: '2025-06-12', status: '容缺中' }, |
| | | { id: 4, name: '项目进度报告', project: '射洪市现代种业示范基地建设项目', startTime: '2025-05-23', deadline: '2025-06-20', status: '待完成' }, |
| | | { id: 5, name: '供应商会议', project: '射洪市沱牌镇综合水利设施建设项目', startTime: '2025-05-14', deadline: '2025-06-14', status: '容缺中' } |
| | | ], |
| | | logs: [ |
| | | { id: 1, time: '09:30', project: '射洪市国家储备林建设项目(一期)', action: '提交', detail: '提交了施工图纸审核申请' }, |
| | | { id: 2, time: '10:15', project: '射洪市白羽肉鸡产业建设项目', action: '更新', detail: '更新了材料采购清单' }, |
| | | { id: 3, time: '11:00', project: '遂宁市射洪2024—2027年度东北片区高标准农田建设项目', action: '完成', detail: '完成了电力设备测试' }, |
| | | { id: 4, time: '14:30', project: '射洪市现代种业示范基地建设项目', action: '创建', detail: '创建了新的安装计划' }, |
| | | { id: 5, time: '16:45', project: '射洪市沱牌镇综合水利设施建设项目', action: '审批', detail: '审批通过了安全方案' } |
| | | ], |
| | | achievements: { |
| | | completedTasks: 128, |
| | | avgDuration: 3.5, |
| | | totalSchedules: 89, |
| | | completedSchedules: 76 |
| | | }, |
| | | calendarDate: new Date(), |
| | | schedules: [ |
| | | { id: 1, date: '2025-05-10', time: '09:00', title: '项目启动会议', project: '射洪市国家储备林建设项目(一期)' }, |
| | | { id: 2, date: '2025-05-10', time: '14:00', title: '供应商洽谈', project: '射洪市白羽肉鸡产业建设项目' }, |
| | | { id: 3, date: '2025-05-11', time: '10:30', title: '现场勘察', project: '遂宁市射洪2024—2027年度东北片区高标准农田建设项目' }, |
| | | { id: 4, date: '2025-05-12', time: '09:00', title: '安全培训', project: '射洪市现代种业示范基地建设项目' }, |
| | | { id: 5, date: '2025-05-12', time: '15:00', title: '进度汇报', project: '射洪市沱牌镇综合水利设施建设项目' }, |
| | | { id: 6, date: '2025-05-15', time: '13:00', title: '设备验收', project: '射洪市白羽肉鸡产业建设项目' } |
| | | ] |
| | | } |
| | | }, |
| | | computed: { |
| | | filteredSchedules() { |
| | | const selectedDate = this.formatCalendarDate(this.calendarDate); |
| | | return this.schedules.filter(schedule => schedule.date === selectedDate); |
| | | } |
| | | }, |
| | | methods: { |
| | | // 截断过长的项目名称 |
| | | truncateProjectName(name) { |
| | | const maxLength = 10; // 最大显示长度 |
| | | return name.length > maxLength ? `${name.substring(0, maxLength)}...` : name; |
| | | }, |
| | | // 判断项目名是否过长 |
| | | isProjectNameTooLong(name) { |
| | | return name.length > 10; |
| | | }, |
| | | formatDate(date) { |
| | | const year = date.getFullYear(); |
| | | const month = date.getMonth() + 1; |
| | | const day = date.getDate(); |
| | | return `${year}年${month}月${day}日`; |
| | | }, |
| | | formatCalendarDate(date) { |
| | | const year = date.getFullYear(); |
| | | const month = (date.getMonth() + 1).toString().padStart(2, '0'); |
| | | const day = date.getDate().toString().padStart(2, '0'); |
| | | return `${year}-${month}-${day}`; |
| | | }, |
| | | handleProjectSelect(index) { |
| | | this.activeProject = index; |
| | | // 这里可以添加项目筛选逻辑 |
| | | }, |
| | | getPriorityType(priority) { |
| | | switch (priority) { |
| | | case '高': return 'danger'; |
| | | case '中': return 'warning'; |
| | | case '低': return 'success'; |
| | | default: return 'info'; |
| | | } |
| | | }, |
| | | handleTaskEdit(task) { |
| | | console.log('编辑任务:', task); |
| | | this.$message.info(`开始处理任务: ${task.name}`); |
| | | }, |
| | | getScheduleCount(date) { |
| | | const dateStr = this.formatCalendarDate(date); |
| | | return this.schedules.filter(s => s.date === dateStr).length; |
| | | }, |
| | | handleAddSchedule() { |
| | | this.$message.info('新增日程'); |
| | | }, |
| | | handleEditSchedule(schedule) { |
| | | this.$message.info(`编辑日程: ${schedule.title}`); |
| | | }, |
| | | handleDeleteSchedule(schedule) { |
| | | this.$confirm('确定删除该日程吗?', '提示', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | this.$message.success('删除成功'); |
| | | }).catch(() => { |
| | | this.$message.info('已取消删除'); |
| | | }); |
| | | } |
| | | } |
| | | } |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .dashboard-container { |
| | | font-family: 'Helvetica Neue', Helvetica, 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', Arial, sans-serif; |
| | | height: 100vh; |
| | | display: flex; |
| | | flex-direction: column; |
| | | background-color: #f5f7fa; |
| | | } |
| | | |
| | | /* 顶部导航栏样式 */ |
| | | .top-navbar { |
| | | background-color: #1e88e5; |
| | | color: white; |
| | | padding: 15px 20px; |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .welcome-message h2 { |
| | | margin: 0; |
| | | font-size: 20px; |
| | | } |
| | | |
| | | .welcome-message p { |
| | | margin: 5px 0 0; |
| | | font-size: 14px; |
| | | opacity: 0.9; |
| | | } |
| | | |
| | | .quick-stats { |
| | | display: flex; |
| | | gap: 30px; |
| | | } |
| | | |
| | | .stat-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | |
| | | .stat-number { |
| | | font-size: 24px; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 14px; |
| | | opacity: 0.9; |
| | | } |
| | | |
| | | .user-profile { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | .user-avatar { |
| | | display: flex; |
| | | align-items: center; |
| | | cursor: pointer; |
| | | } |
| | | |
| | | .user-avatar img { |
| | | width: 40px; |
| | | height: 40px; |
| | | border-radius: 50%; |
| | | margin-right: 10px; |
| | | } |
| | | |
| | | /* 主内容区样式 */ |
| | | .main-content { |
| | | display: flex; |
| | | flex: 1; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | .left-sidebar { |
| | | width: 220px; |
| | | background-color: white; |
| | | border-right: 1px solid #e6e6e6; |
| | | padding: 15px; |
| | | margin-top: 10px; |
| | | overflow-y: auto; |
| | | } |
| | | .project-name { |
| | | display: inline-block; |
| | | max-width: 150px; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | .project-list h3 { |
| | | margin-top: 0; |
| | | color: #333; |
| | | padding-bottom: 10px; |
| | | border-bottom: 1px solid #eee; |
| | | } |
| | | |
| | | .project-menu { |
| | | border-right: none; |
| | | } |
| | | |
| | | .project-actions { |
| | | margin-top: 15px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .center-content { |
| | | flex: 1; |
| | | padding: 15px; |
| | | overflow-y: auto; |
| | | background-color: white; |
| | | margin: 10px 10px 0px; |
| | | border-radius: 4px; |
| | | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 15px; |
| | | } |
| | | |
| | | .section-header h3 { |
| | | margin: 0; |
| | | color: #333; |
| | | } |
| | | |
| | | .task-section { |
| | | margin-bottom: 20px; |
| | | height: 350px; |
| | | } |
| | | |
| | | .log-list { |
| | | border: 1px solid #ebeef5; |
| | | border-radius: 4px; |
| | | padding: 10px; |
| | | } |
| | | |
| | | .log-item { |
| | | display: flex; |
| | | padding: 8px 0; |
| | | border-bottom: 1px dashed #eee; |
| | | } |
| | | |
| | | .log-item:last-child { |
| | | border-bottom: none; |
| | | } |
| | | |
| | | .log-time { |
| | | width: 60px; |
| | | color: #666; |
| | | font-size: 14px; |
| | | } |
| | | |
| | | .log-content { |
| | | flex: 1; |
| | | } |
| | | |
| | | .log-project { |
| | | color: #1e88e5; |
| | | margin-right: 10px; |
| | | font-weight: bold; |
| | | } |
| | | |
| | | .log-action { |
| | | color: #ff9800; |
| | | margin-right: 10px; |
| | | } |
| | | |
| | | .right-sidebar { |
| | | width: 320px; |
| | | background-color: white; |
| | | border-left: 1px solid #e6e6e6; |
| | | padding: 15px; |
| | | margin-top: 10px; |
| | | overflow-y: auto; |
| | | } |
| | | |
| | | .achievement-section h3 { |
| | | margin-top: 0; |
| | | color: #333; |
| | | padding-bottom: 10px; |
| | | border-bottom: 1px solid #eee; |
| | | } |
| | | |
| | | .achievement-stats { |
| | | display: grid; |
| | | grid-template-columns: 1fr 1fr; |
| | | gap: 15px; |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .achievement-stats .stat-item { |
| | | background-color: #f5f7fa; |
| | | padding: 15px; |
| | | border-radius: 4px; |
| | | text-align: center; |
| | | } |
| | | |
| | | .achievement-stats .stat-number { |
| | | font-size: 24px; |
| | | color: #1e88e5; |
| | | font-weight: bold; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .achievement-stats .stat-label { |
| | | font-size: 14px; |
| | | color: #666; |
| | | } |
| | | |
| | | .calendar-section { |
| | | margin-bottom: 20px; |
| | | } |
| | | |
| | | .calendar-day { |
| | | height: 45px; |
| | | padding: 5px; |
| | | box-sizing: border-box; |
| | | } |
| | | |
| | | .schedule-count { |
| | | font-size: 12px; |
| | | color: #1e88e5; |
| | | margin-top: 2px; |
| | | } |
| | | |
| | | .schedule-list-section h3 { |
| | | margin-top: 0; |
| | | color: #333; |
| | | padding-bottom: 10px; |
| | | border-bottom: 1px solid #eee; |
| | | } |
| | | |
| | | .calendar-section >>> .el-calendar-table .el-calendar-day { |
| | | height: 40px !important; /* 设置每日单元格高度 */ |
| | | padding: 0 !important; |
| | | } |
| | | .calendar-section >>> .el-calendar__header { |
| | | padding: 0 !important; |
| | | border: none !important; |
| | | } |
| | | .calendar-section >>> .el-calendar__body { |
| | | padding: 0 !important; |
| | | border: none !important; |
| | | } |
| | | </style> |
| | |
| | | |
| | | const CompressionPlugin = require('compression-webpack-plugin') |
| | | |
| | | const name = process.env.VUE_APP_TITLE || '射洪智慧项目管理系统' // 网页标题 |
| | | const name = process.env.VUE_APP_TITLE || '农投项目管理系统' // 网页标题 |
| | | |
| | | const port = process.env.port || process.env.npm_config_port || 80 // 端口 |
| | | |