xiangpei
2025-06-05 1fa6ac40e2ce16e1174cec9ca538d45eeb660fdc
工作台
1个文件已添加
596 ■■■■■ 已修改文件
src/views/workbench.vue 596 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/workbench.vue
New file
@@ -0,0 +1,596 @@
<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>