From 1fa6ac40e2ce16e1174cec9ca538d45eeb660fdc Mon Sep 17 00:00:00 2001 From: xiangpei <xiangpei@timesnew.cn> Date: 星期四, 05 六月 2025 18:17:56 +0800 Subject: [PATCH] 工作台 --- src/views/workbench.vue | 596 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 596 insertions(+), 0 deletions(-) diff --git a/src/views/workbench.vue b/src/views/workbench.vue new file mode 100644 index 0000000..ce8c638 --- /dev/null +++ b/src/views/workbench.vue @@ -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: '灏勬椽甯傜幇浠g涓氱ず鑼冨熀鍦板缓璁鹃」鐩�' }, + ], + 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: '灏勬椽甯傜幇浠g涓氱ず鑼冨熀鍦板缓璁鹃」鐩�', 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: '灏勬椽甯傜幇浠g涓氱ず鑼冨熀鍦板缓璁鹃」鐩�', 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: '灏勬椽甯傜幇浠g涓氱ず鑼冨熀鍦板缓璁鹃」鐩�' }, + { 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> -- Gitblit v1.8.0