ys 2 săptămâni în urmă
părinte
comite
9dcf5dcf02
1 a modificat fișierele cu 69 adăugiri și 462 ștergeri
  1. 69 462
      yushu-uivue3/src/views/index.vue

+ 69 - 462
yushu-uivue3/src/views/index.vue

@@ -32,120 +32,81 @@
     </a-row>
 
     <!-- 主要内容区域 -->
-    <a-row :gutter="20" class="main-content">
-      <!-- 左侧:今日待办 + 最近消息 -->
+    <a-row :gutter="[16, 16]" style="margin-top: 16px">
+      <!-- 今日待办 -->
       <a-col :xs="24" :lg="12">
-        <!-- 今日待办 -->
-        <a-card hoverable class="todo-card">
-          <template #title>
-            <div class="card-header">
-              <span><CheckSquareOutlined /> 今日待办</span>
-              <a-button type="link" size="small" @click="goRoute('/system/todo')">查看全部</a-button>
-            </div>
-          </template>
-          <div class="todo-list">
-            <a-empty v-if="todoList.length === 0" description="暂无待办事项" :image="Empty.PRESENTED_IMAGE_SIMPLE" />
-            <div v-else v-for="item in todoList" :key="item.id" class="todo-item" @click="goRoute('/system/todo')">
-              <div class="todo-checkbox">
-                <CheckCircleOutlined v-if="item.status === '1'" class="checked" />
-                <ClockCircleOutlined v-else class="pending" />
-              </div>
-              <div class="todo-content">
-                <div class="todo-title">{{ item.title }}</div>
-                <div class="todo-time">
-                  <CalendarOutlined />
-                  <span>{{ item.dueDate }}</span>
-                </div>
-              </div>
-              <a-tag :color="getPriorityColor(item.priority)" size="small">
-                {{ getPriorityText(item.priority) }}
-              </a-tag>
-            </div>
-          </div>
-        </a-card>
-
-        <!-- 最近消息 -->
-        <a-card hoverable class="message-card mt-20">
-          <template #title>
-            <div class="card-header">
-              <span><MessageOutlined /> 最近消息</span>
-              <a-button type="link" size="small" @click="goRoute('/message')">查看全部</a-button>
-            </div>
-          </template>
-          <div class="message-list">
-            <a-empty v-if="recentMessages.length === 0" description="暂无消息" :image="Empty.PRESENTED_IMAGE_SIMPLE" />
-            <div v-else v-for="item in recentMessages" :key="item.id" class="message-item" @click="goRoute('/message')">
-              <a-avatar :src="item.avatar" :size="40">{{ item.sender?.charAt(0) }}</a-avatar>
-              <div class="message-content">
-                <div class="message-header">
-                  <span class="message-sender">{{ item.sender }}</span>
-                  <span class="message-time">{{ item.time }}</span>
-                </div>
-                <div class="message-text">{{ item.content }}</div>
-              </div>
-              <a-badge v-if="!item.isRead" dot />
-            </div>
-          </div>
+        <a-card title="今日待办" :extra="h(AButton, { type: 'link', onClick: () => goRoute('/system/todo') }, () => '查看全部')">
+          <a-list :data-source="todoList" :locale="{ emptyText: '暂无待办事项' }">
+            <template #renderItem="{ item }">
+              <a-list-item @click="goRoute('/system/todo')" style="cursor: pointer">
+                <a-list-item-meta>
+                  <template #avatar>
+                    <CheckCircleOutlined v-if="item.status === '1'" style="color: #52c41a; font-size: 20px" />
+                    <ClockCircleOutlined v-else style="color: #faad14; font-size: 20px" />
+                  </template>
+                  <template #title>{{ item.title }}</template>
+                  <template #description>
+                    <CalendarOutlined /> {{ item.dueDate }}
+                  </template>
+                </a-list-item-meta>
+                <template #actions>
+                  <a-tag :color="getPriorityColor(item.priority)">{{ getPriorityText(item.priority) }}</a-tag>
+                </template>
+              </a-list-item>
+            </template>
+          </a-list>
         </a-card>
       </a-col>
 
-      <!-- 右侧:日程安排 + 快捷入口 -->
+      <!-- 最近消息 -->
       <a-col :xs="24" :lg="12">
-        <!-- 本周日程 -->
-        <a-card hoverable class="schedule-card">
-          <template #title>
-            <div class="card-header">
-              <span><CalendarOutlined /> 本周日程</span>
-              <span class="week-range">{{ weekRange }}</span>
-            </div>
-          </template>
-          <a-timeline class="schedule-timeline">
-            <a-timeline-item v-for="item in scheduleList" :key="item.id" :color="item.color">
-              <div class="schedule-item">
-                <div class="schedule-time">
-                  <ClockCircleOutlined />
-                  <span>{{ item.time }}</span>
-                </div>
-                <div class="schedule-title">{{ item.title }}</div>
-                <div class="schedule-desc">{{ item.description }}</div>
-              </div>
-            </a-timeline-item>
-          </a-timeline>
-        </a-card>
-
-        <!-- 快捷入口 -->
-        <a-card hoverable class="quick-entry-card mt-20">
-          <template #title>
-            <div class="card-header">
-              <span><AppstoreOutlined /> 快捷入口</span>
-            </div>
-          </template>
-          <div class="quick-nav-grid">
-            <div 
-              v-for="item in quickLinks" 
-              :key="item.path" 
-              class="quick-nav-item"
-              @click="goRoute(item.path)"
-            >
-              <div class="nav-icon" :style="{ background: item.bg }">
-                <component :is="item.icon" :style="{ fontSize: '24px', color: item.color }" />
-              </div>
-              <span class="nav-label">{{ item.name }}</span>
-            </div>
-          </div>
+        <a-card title="最近消息" :extra="h(AButton, { type: 'link', onClick: () => goRoute('/message') }, () => '查看全部')">
+          <a-list :data-source="recentMessages" :locale="{ emptyText: '暂无消息' }">
+            <template #renderItem="{ item }">
+              <a-list-item @click="goRoute('/message')" style="cursor: pointer">
+                <a-list-item-meta :description="item.content">
+                  <template #avatar>
+                    <a-badge :dot="!item.isRead">
+                      <a-avatar :src="item.avatar">{{ item.sender?.charAt(0) }}</a-avatar>
+                    </a-badge>
+                  </template>
+                  <template #title>
+                    <a-space>
+                      <span>{{ item.sender }}</span>
+                      <a-typography-text type="secondary" style="font-size: 12px">{{ item.time }}</a-typography-text>
+                    </a-space>
+                  </template>
+                </a-list-item-meta>
+              </a-list-item>
+            </template>
+          </a-list>
         </a-card>
       </a-col>
     </a-row>
+
+    <!-- 快捷入口 -->
+    <a-card title="快捷入口" style="margin-top: 16px">
+      <a-row :gutter="[16, 16]">
+        <a-col :xs="12" :sm="6" v-for="item in quickLinks" :key="item.path">
+          <div class="quick-item" @click="goRoute(item.path)">
+            <a-avatar :size="56" :style="{ backgroundColor: item.bg }">
+              <component :is="item.icon" :style="{ fontSize: '24px', color: item.color }" />
+            </a-avatar>
+            <div style="margin-top: 8px; text-align: center">{{ item.name }}</div>
+          </div>
+        </a-col>
+      </a-row>
+    </a-card>
   </div>
 </template>
 
 <script setup name="Workbench">
-import { ref, onMounted, onUnmounted, computed } from 'vue'
+import { ref, onMounted, onUnmounted, computed, h } from 'vue'
 import { useRouter } from 'vue-router'
-import { Empty } from 'ant-design-vue'
+import { Button as AButton } from 'ant-design-vue'
 import { 
   ClockCircleOutlined, CalendarOutlined, CheckSquareOutlined, MessageOutlined,
-  CheckCircleOutlined, BellOutlined, FileTextOutlined, AppstoreOutlined,
+  CheckCircleOutlined, BellOutlined, FileTextOutlined,
   UserOutlined, SettingOutlined, FolderOutlined, TeamOutlined
 } from '@ant-design/icons-vue'
 import { getMyTodo } from '@/api/system/todo'
@@ -202,16 +163,6 @@ const todoList = ref([])
 // 最近消息
 const recentMessages = ref([])
 
-// 本周日程
-const weekRange = ref('')
-const scheduleList = ref([
-  { id: 1, time: '周一 09:00', title: '团队周会', description: '讨论本周工作计划', color: 'blue' },
-  { id: 2, time: '周二 14:00', title: '项目评审', description: '新功能需求评审', color: 'green' },
-  { id: 3, time: '周三 10:30', title: '技术分享', description: 'Vue3 最佳实践', color: 'orange' },
-  { id: 4, time: '周四 15:00', title: '客户沟通', description: '产品演示和反馈收集', color: 'purple' },
-  { id: 5, time: '周五 16:00', title: '周总结', description: '本周工作总结和复盘', color: 'red' }
-])
-
 // 快捷入口
 const quickLinks = ref([])
 
@@ -274,24 +225,6 @@ function updateTime() {
   }
 }
 
-// 获取本周日期范围
-function getWeekRange() {
-  const now = new Date()
-  const day = now.getDay()
-  const diff = now.getDate() - day + (day === 0 ? -6 : 1)
-  const monday = new Date(now.setDate(diff))
-  const sunday = new Date(monday)
-  sunday.setDate(monday.getDate() + 6)
-  
-  const format = (date) => {
-    const m = (date.getMonth() + 1).toString().padStart(2, '0')
-    const d = date.getDate().toString().padStart(2, '0')
-    return `${m}.${d}`
-  }
-  
-  weekRange.value = `${format(monday)} - ${format(sunday)}`
-}
-
 // 加载快捷入口(从菜单获取)
 async function loadQuickLinks() {
   try {
@@ -393,7 +326,6 @@ let timer = null
 
 onMounted(() => {
   updateTime()
-  getWeekRange()
   loadQuickLinks()
   loadTodoList()
   loadRecentMessages()
@@ -413,344 +345,19 @@ onUnmounted(() => {
   padding: 24px;
   background-color: #f0f2f5;
   min-height: 100vh;
-  
-  .mt-20 {
-    margin-top: 20px;
-  }
-}
-
-// 问候区域
-.greeting-section {
-  background: #fff;
-  border-radius: 8px;
-  padding: 32px;
-  margin-bottom: 20px;
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
-  
-  .greeting-content {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    
-    .greeting-text {
-      h1 {
-        font-size: 28px;
-        font-weight: 500;
-        color: #303133;
-        margin: 0 0 8px 0;
-      }
-      
-      .greeting-subtitle {
-        font-size: 14px;
-        color: #909399;
-        margin: 0;
-      }
-    }
-    
-    .greeting-time {
-      .time-display {
-        display: flex;
-        align-items: center;
-        gap: 12px;
-        background: #409eff;
-        padding: 12px 20px;
-        border-radius: 8px;
-        
-        .time-icon {
-          font-size: 20px;
-          color: #fff;
-        }
-        
-        .current-time {
-          font-size: 24px;
-          font-weight: 500;
-          color: #fff;
-          font-family: 'Courier New', monospace;
-        }
-      }
-    }
-  }
-}
-
-// 概览卡片
-.overview-cards {
-  margin-bottom: 20px;
-  
-  .stat-card-item {
-    border: none;
-    border-radius: 8px;
-    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
-    transition: all 0.3s;
-    cursor: pointer;
-    
-    &:hover {
-      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
-    }
-    
-    :deep(.ant-card-body) {
-      padding: 20px;
-    }
-    
-    .stat-card-content {
-      display: flex;
-      align-items: center;
-      gap: 16px;
-      
-      .stat-icon-wrapper {
-        width: 52px;
-        height: 52px;
-        border-radius: 8px;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-      }
-      
-      .stat-info {
-        flex: 1;
-        
-        .stat-value {
-          font-size: 26px;
-          font-weight: 600;
-          color: #303133;
-          margin-bottom: 4px;
-        }
-        
-        .stat-label {
-          font-size: 14px;
-          color: #909399;
-        }
-      }
-    }
-  }
-}
-
-// 主要内容区域
-.main-content {
-  .card-header {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-    font-weight: 500;
-    
-    span {
-      display: flex;
-      align-items: center;
-      gap: 8px;
-    }
-  }
-}
-
-// 待办卡片
-.todo-card {
-  border-radius: 8px;
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
-  
-  .todo-list {
-    .todo-item {
-      display: flex;
-      align-items: center;
-      gap: 12px;
-      padding: 14px;
-      border-radius: 6px;
-      margin-bottom: 10px;
-      background: #f5f7fa;
-      cursor: pointer;
-      transition: all 0.3s;
-      
-      &:hover {
-        background: #ecf5ff;
-      }
-      
-      &:last-child {
-        margin-bottom: 0;
-      }
-      
-      .todo-checkbox {
-        font-size: 18px;
-        
-        .checked {
-          color: #67c23a;
-        }
-        
-        .pending {
-          color: #e6a23c;
-        }
-      }
-      
-      .todo-content {
-        flex: 1;
-        
-        .todo-title {
-          font-size: 14px;
-          color: #303133;
-          margin-bottom: 4px;
-        }
-        
-        .todo-time {
-          font-size: 12px;
-          color: #909399;
-          display: flex;
-          align-items: center;
-          gap: 4px;
-        }
-      }
-    }
-  }
-}
-
-// 消息卡片
-.message-card {
-  border-radius: 8px;
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
-  
-  .message-list {
-    .message-item {
-      display: flex;
-      align-items: flex-start;
-      gap: 12px;
-      padding: 14px;
-      border-radius: 6px;
-      margin-bottom: 10px;
-      background: #f5f7fa;
-      cursor: pointer;
-      transition: all 0.3s;
-      
-      &:hover {
-        background: #ecf5ff;
-      }
-      
-      &:last-child {
-        margin-bottom: 0;
-      }
-      
-      .message-content {
-        flex: 1;
-        min-width: 0;
-        
-        .message-header {
-          display: flex;
-          justify-content: space-between;
-          align-items: center;
-          margin-bottom: 4px;
-          
-          .message-sender {
-            font-size: 14px;
-            font-weight: 500;
-            color: #303133;
-          }
-          
-          .message-time {
-            font-size: 12px;
-            color: #909399;
-          }
-        }
-        
-        .message-text {
-          font-size: 13px;
-          color: #606266;
-          overflow: hidden;
-          text-overflow: ellipsis;
-          white-space: nowrap;
-        }
-      }
-    }
-  }
-}
-
-// 日程卡片
-.schedule-card {
-  border-radius: 8px;
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
-  
-  .card-header {
-    .week-range {
-      font-size: 13px;
-      color: #909399;
-      font-weight: normal;
-    }
-  }
-  
-  .schedule-timeline {
-    margin-top: 16px;
-    
-    .schedule-item {
-      .schedule-time {
-        display: flex;
-        align-items: center;
-        gap: 6px;
-        font-size: 13px;
-        color: #606266;
-        margin-bottom: 6px;
-      }
-      
-      .schedule-title {
-        font-size: 14px;
-        font-weight: 500;
-        color: #303133;
-        margin-bottom: 4px;
-      }
-      
-      .schedule-desc {
-        font-size: 13px;
-        color: #909399;
-      }
-    }
-  }
 }
 
-// 快捷入口
-.quick-entry-card {
+.quick-item {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  cursor: pointer;
+  padding: 16px;
   border-radius: 8px;
-  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
-  
-  .quick-nav-grid {
-    display: grid;
-    grid-template-columns: repeat(4, 1fr);
-    gap: 20px;
-    padding: 16px;
-    
-    .quick-nav-item {
-      display: flex;
-      flex-direction: column;
-      align-items: center;
-      justify-content: center;
-      cursor: pointer;
-      padding: 20px 10px;
-      border-radius: 6px;
-      transition: all 0.3s;
-      
-      &:hover {
-        background: #f5f7fa;
-      }
-      
-      .nav-icon {
-        width: 56px;
-        height: 56px;
-        border-radius: 8px;
-        display: flex;
-        align-items: center;
-        justify-content: center;
-        margin-bottom:10px;
-      }
-      
-      .nav-label {
-        font-size: 14px;
-        color: #606266;
-        text-align: center;
-      }
-    }
-  }
-}
-
-@media (max-width: 768px) {
-  .greeting-content {
-    flex-direction: column;
-    gap: 20px;
-    text-align: center;
-  }
+  transition: all 0.3s;
   
-  .quick-nav-grid {
-    grid-template-columns: repeat(2, 1fr) !important;
+  &:hover {
+    background: #f5f7fa;
   }
 }
 </style>