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> |