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