Explorar o código

调整消息页面

ys hai 2 semanas
pai
achega
d51dd71ba5
Modificáronse 1 ficheiros con 275 adicións e 7 borrados
  1. 275 7
      yushu-uivue3/src/layout/components/Navbar.vue

+ 275 - 7
yushu-uivue3/src/layout/components/Navbar.vue

@@ -11,13 +11,95 @@
         <screenfull id="screenfull" class="right-menu-item hover-effect" />
 
         <!-- 消息中心 -->
-        <a-tooltip title="消息中心" placement="bottom">
-          <div class="right-menu-item hover-effect message-center" @click="goMessage">
+        <a-popover 
+          v-model:open="messagePopoverVisible" 
+          trigger="click" 
+          placement="bottomRight"
+          overlay-class-name="message-popover"
+          :arrow="false"
+        >
+          <template #content>
+            <div class="message-panel">
+              <a-tabs v-model:activeKey="messageTab" centered>
+                <a-tab-pane key="notification" tab="通知">
+                  <div class="message-list">
+                    <template v-if="notificationList.length > 0">
+                      <div 
+                        v-for="item in notificationList" 
+                        :key="item.id" 
+                        class="message-item"
+                        @click="handleNotificationClick(item)"
+                      >
+                        <div class="message-icon" :class="item.type">
+                          <BellOutlined v-if="item.type === 'system'" />
+                          <MessageOutlined v-else-if="item.type === 'message'" />
+                          <CheckCircleOutlined v-else-if="item.type === 'success'" />
+                          <InfoCircleOutlined v-else />
+                        </div>
+                        <div class="message-content">
+                          <div class="message-title">{{ item.title }}</div>
+                          <div class="message-time">{{ item.time }}</div>
+                        </div>
+                      </div>
+                    </template>
+                    <a-empty v-else description="暂无通知" :image="Empty.PRESENTED_IMAGE_SIMPLE" />
+                  </div>
+                </a-tab-pane>
+                <a-tab-pane key="message" tab="消息">
+                  <div class="message-list">
+                    <template v-if="messageList.length > 0">
+                      <div 
+                        v-for="item in messageList" 
+                        :key="item.id" 
+                        class="message-item"
+                        @click="handleMessageClick(item)"
+                      >
+                        <a-avatar :src="item.avatar" :size="36">{{ item.sender?.charAt(0) }}</a-avatar>
+                        <div class="message-content">
+                          <div class="message-title">{{ item.sender }}</div>
+                          <div class="message-desc">{{ item.content }}</div>
+                          <div class="message-time">{{ item.time }}</div>
+                        </div>
+                      </div>
+                    </template>
+                    <a-empty v-else description="暂无消息" :image="Empty.PRESENTED_IMAGE_SIMPLE" />
+                  </div>
+                </a-tab-pane>
+                <a-tab-pane key="todo" tab="待办">
+                  <div class="message-list">
+                    <template v-if="todoList.length > 0">
+                      <div 
+                        v-for="item in todoList" 
+                        :key="item.id" 
+                        class="message-item"
+                        @click="handleTodoClick(item)"
+                      >
+                        <div class="message-icon todo">
+                          <ClockCircleOutlined />
+                        </div>
+                        <div class="message-content">
+                          <div class="message-title">{{ item.title }}</div>
+                          <div class="message-desc">{{ item.description }}</div>
+                          <div class="message-time">{{ item.time }}</div>
+                        </div>
+                      </div>
+                    </template>
+                    <a-empty v-else description="暂无待办" :image="Empty.PRESENTED_IMAGE_SIMPLE" />
+                  </div>
+                </a-tab-pane>
+              </a-tabs>
+              <div class="message-footer">
+                <a-button type="link" @click="clearAll">清空</a-button>
+                <a-button type="link" @click="goMessageCenter">查看更多</a-button>
+              </div>
+            </div>
+          </template>
+          <div class="right-menu-item hover-effect message-center">
             <a-badge :count="unreadCount" :number-style="{ display: unreadCount === 0 ? 'none' : 'block' }" :overflow-count="99">
-              <MessageOutlined :style="{ fontSize: '18px' }" />
+              <BellOutlined :style="{ fontSize: '18px' }" />
             </a-badge>
           </div>
-        </a-tooltip>
+        </a-popover>
       </template>
 
       <a-dropdown class="avatar-container right-menu-item hover-effect" trigger="hover">
@@ -47,8 +129,8 @@
 <script setup>
 import { ref, onMounted, onUnmounted } from 'vue'
 import { useRouter } from 'vue-router'
-import { Modal } from 'ant-design-vue'
-import { MessageOutlined } from '@ant-design/icons-vue'
+import { Modal, Empty } from 'ant-design-vue'
+import { BellOutlined, MessageOutlined, CheckCircleOutlined, InfoCircleOutlined, ClockCircleOutlined } from '@ant-design/icons-vue'
 import Breadcrumb from '@/components/Breadcrumb'
 import TopNav from '@/components/TopNav'
 import Hamburger from '@/components/Hamburger'
@@ -64,11 +146,65 @@ const appStore = useAppStore()
 const userStore = useUserStore()
 const settingsStore = useSettingsStore()
 
+// 消息弹窗
+const messagePopoverVisible = ref(false)
+const messageTab = ref('notification')
+
 // 未读消息数
 const unreadCount = ref(0)
 
+// 通知列表
+const notificationList = ref([
+  { id: 1, type: 'system', title: '系统升级通知', time: '10分钟前' },
+  { id: 2, type: 'success', title: '您的申请已通过审核', time: '1小时前' },
+  { id: 3, type: 'info', title: '新功能上线提醒', time: '2小时前' },
+])
+
+// 消息列表
+const messageList = ref([
+  { id: 1, sender: '张三', avatar: '', content: '请问项目进度如何?', time: '5分钟前' },
+  { id: 2, sender: '李四', avatar: '', content: '文档已经发送给您了', time: '30分钟前' },
+])
+
+// 待办列表
+const todoList = ref([
+  { id: 1, title: '审批流程', description: '有3个待审批事项', time: '待处理' },
+  { id: 2, title: '周报提交', description: '本周周报尚未提交', time: '截止今天' },
+])
+
+// 处理通知点击
+function handleNotificationClick(item) {
+  console.log('点击通知:', item)
+  messagePopoverVisible.value = false
+}
+
+// 处理消息点击
+function handleMessageClick(item) {
+  console.log('点击消息:', item)
+  messagePopoverVisible.value = false
+  router.push('/message')
+}
+
+// 处理待办点击
+function handleTodoClick(item) {
+  console.log('点击待办:', item)
+  messagePopoverVisible.value = false
+}
+
+// 清空消息
+function clearAll() {
+  if (messageTab.value === 'notification') {
+    notificationList.value = []
+  } else if (messageTab.value === 'message') {
+    messageList.value = []
+  } else {
+    todoList.value = []
+  }
+}
+
 // 跳转消息中心
-function goMessage() {
+function goMessageCenter() {
+  messagePopoverVisible.value = false
   router.push('/message')
 }
 
@@ -326,3 +462,135 @@ html.dark .navbar {
   }
 }
 </style>
+
+<style lang="scss">
+.message-popover {
+  .ant-popover-inner {
+    padding: 0;
+    border-radius: 8px;
+    box-shadow: 0 6px 16px 0 rgba(0, 0, 0, 0.08), 0 3px 6px -4px rgba(0, 0, 0, 0.12);
+  }
+}
+
+.message-panel {
+  width: 336px;
+  
+  .ant-tabs-nav {
+    margin-bottom: 0;
+    
+    &::before {
+      border-bottom: 1px solid #f0f0f0;
+    }
+  }
+  
+  .ant-tabs-tab {
+    padding: 12px 0;
+  }
+  
+  .message-list {
+    max-height: 320px;
+    overflow-y: auto;
+    
+    .message-item {
+      display: flex;
+      align-items: flex-start;
+      padding: 12px 16px;
+      cursor: pointer;
+      transition: background 0.2s;
+      
+      &:hover {
+        background: #f5f5f5;
+      }
+      
+      .message-icon {
+        width: 36px;
+        height: 36px;
+        border-radius: 50%;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        margin-right: 12px;
+        flex-shrink: 0;
+        font-size: 18px;
+        
+        &.system {
+          background: #e6f7ff;
+          color: #1890ff;
+        }
+        
+        &.success {
+          background: #f6ffed;
+          color: #52c41a;
+        }
+        
+        &.info {
+          background: #fff7e6;
+          color: #fa8c16;
+        }
+        
+        &.message {
+          background: #f9f0ff;
+          color: #722ed1;
+        }
+        
+        &.todo {
+          background: #fff1f0;
+          color: #f5222d;
+        }
+      }
+      
+      .ant-avatar {
+        margin-right: 12px;
+        flex-shrink: 0;
+      }
+      
+      .message-content {
+        flex: 1;
+        min-width: 0;
+        
+        .message-title {
+          font-size: 14px;
+          color: #333;
+          margin-bottom: 4px;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+        
+        .message-desc {
+          font-size: 12px;
+          color: #999;
+          margin-bottom: 4px;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+        
+        .message-time {
+          font-size: 12px;
+          color: #bbb;
+        }
+      }
+    }
+    
+    .ant-empty {
+      padding: 40px 0;
+    }
+  }
+  
+  .message-footer {
+    display: flex;
+    justify-content: space-between;
+    border-top: 1px solid #f0f0f0;
+    padding: 8px 0;
+    
+    .ant-btn-link {
+      color: #666;
+      
+      &:hover {
+        color: #1890ff;
+      }
+    }
+  }
+}
+</style>