|
|
@@ -30,36 +30,71 @@
|
|
|
<div class="hidden lg:flex items-center gap-3 h-full">
|
|
|
<!-- 消息中心 -->
|
|
|
<el-dropdown trigger="click" placement="bottom-end">
|
|
|
- <div class="flex items-center gap-2 cursor-pointer pr-2">
|
|
|
+ <div class="flex items-center gap-2 cursor-pointer pr-6 pt-2">
|
|
|
+ <el-badge
|
|
|
+ :value="unreadMessageCount"
|
|
|
+ class="item"
|
|
|
+ v-if="hasUnreadMessages"
|
|
|
+ >
|
|
|
+ <Icon
|
|
|
+ icon="mdi:bell"
|
|
|
+ class="w-5 h-5 text-gray-600 hover:text-[#409EFF]"
|
|
|
+ />
|
|
|
+ </el-badge>
|
|
|
<Icon
|
|
|
+ v-else
|
|
|
icon="mdi:bell"
|
|
|
class="w-5 h-5 text-gray-600 hover:text-[#409EFF]"
|
|
|
/>
|
|
|
- <span class="text-sm text-gray-600">消息代办</span>
|
|
|
</div>
|
|
|
<template #dropdown>
|
|
|
<el-dropdown-menu class="notification-dropdown">
|
|
|
<div class="notification-tabs pl-2">
|
|
|
<el-tabs v-model="activeTab" class="demo-tabs">
|
|
|
- <el-tab-pane label="消息中心" name="messages">
|
|
|
+ <el-tab-pane label="CRM" name="messages">
|
|
|
+ <template #label>
|
|
|
+ <span class="custom-tabs-label">
|
|
|
+ <span>CRM</span>
|
|
|
+ <el-badge
|
|
|
+ :value="unreadMessageCount"
|
|
|
+ class="item ml-1"
|
|
|
+ v-if="hasUnreadMessages"
|
|
|
+ ></el-badge>
|
|
|
+ </span>
|
|
|
+ </template>
|
|
|
<div class="tab-content">
|
|
|
<!-- 消息中心内容 -->
|
|
|
+ <div>
|
|
|
+ <span
|
|
|
+ v-if="hasUnreadMessages"
|
|
|
+ class="cursor-pointer text-blue-500"
|
|
|
+ @click="markAllAsRead"
|
|
|
+ >全部标为已读</span
|
|
|
+ >
|
|
|
+
|
|
|
+ <span v-else class="cursor-pointer text-[#b2aaaa]"
|
|
|
+ >全部已读</span
|
|
|
+ >
|
|
|
+ </div>
|
|
|
<div
|
|
|
class="message-item"
|
|
|
v-for="(item, index) in messages"
|
|
|
:key="index"
|
|
|
>
|
|
|
- <div class="message-icon">
|
|
|
- <Icon
|
|
|
- :icon="item.icon"
|
|
|
- class="w-5 h-5"
|
|
|
- :class="item.typeClass"
|
|
|
- />
|
|
|
- </div>
|
|
|
+ <div class="message-icon"></div>
|
|
|
<div class="message-text">
|
|
|
- <p class="message-title">{{ item.title }}</p>
|
|
|
- <p class="message-desc">{{ item.desc }}</p>
|
|
|
- <p class="message-time">{{ item.time }}</p>
|
|
|
+ <!-- 未读就显示小红点 -->
|
|
|
+
|
|
|
+ <p class="message-title flex items-center gap-5">
|
|
|
+ <span
|
|
|
+ v-if="item.status === '0'"
|
|
|
+ class="w-2 h-2 bg-[#f56c6c] rounded-full"
|
|
|
+ ></span
|
|
|
+ >{{ item.contentMajor }}
|
|
|
+ </p>
|
|
|
+ <p class="message-desc">
|
|
|
+ {{ timestampToDateTime(item.createTime) }}
|
|
|
+ </p>
|
|
|
</div>
|
|
|
</div>
|
|
|
<div v-if="!messages.length" class="no-messages">
|
|
|
@@ -67,25 +102,38 @@
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-tab-pane>
|
|
|
- <el-tab-pane label="待办任务" name="tasks">
|
|
|
+ <el-tab-pane label="OA" name="tasks">
|
|
|
<div class="tab-content">
|
|
|
- <!-- 待办任务内容 -->
|
|
|
+ <!-- <div>
|
|
|
+ <span
|
|
|
+ class="cursor-pointer text-blue-500"
|
|
|
+ @click="markAllAsRead"
|
|
|
+ >全部标为已读</span
|
|
|
+ >
|
|
|
+ </div> -->
|
|
|
+ <!-- OA消息 -->
|
|
|
<div
|
|
|
class="task-item"
|
|
|
- v-for="(task, index) in tasks"
|
|
|
+ v-for="(task, index) in oaMessagesList"
|
|
|
:key="index"
|
|
|
>
|
|
|
<div class="task-info">
|
|
|
- <p class="task-title">{{ task.title }}</p>
|
|
|
- <p class="task-desc">{{ task.desc }}</p>
|
|
|
- <p class="task-time">截止时间: {{ task.dueTime }}</p>
|
|
|
+ <p class="task-title">
|
|
|
+ <span
|
|
|
+ class="w-3 h-3 bg-[#f56c6c] rounded-full"
|
|
|
+ ></span
|
|
|
+ >{{ task.contentMajor }}
|
|
|
+ </p>
|
|
|
+ <p class="message-desc">
|
|
|
+ {{ timestampToDateTime(task.createTime) }}
|
|
|
+ </p>
|
|
|
</div>
|
|
|
<el-tag :type="task.priorityTag" size="small">{{
|
|
|
task.priorityText
|
|
|
}}</el-tag>
|
|
|
</div>
|
|
|
- <div v-if="!tasks.length" class="no-tasks">
|
|
|
- 暂无待办任务
|
|
|
+ <div v-if="!oaMessagesList.length" class="no-tasks">
|
|
|
+ 暂无新消息
|
|
|
</div>
|
|
|
</div>
|
|
|
</el-tab-pane>
|
|
|
@@ -289,12 +337,17 @@
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
import { Icon } from "@iconify/vue";
|
|
|
-import { ref, computed } from "vue";
|
|
|
+import { ref, computed, onMounted } from "vue";
|
|
|
import { useRouter } from "vue-router";
|
|
|
import logo from "@/assets/images/logo.png";
|
|
|
import person from "@/assets/images/person.png";
|
|
|
import { useUserStoreWithOut } from "@/stores/useUserStore";
|
|
|
const userStore = useUserStoreWithOut();
|
|
|
+import {
|
|
|
+ getNotifyMessages,
|
|
|
+ getNotifyMessageList,
|
|
|
+ markMessageAsRead,
|
|
|
+} from "@api/user";
|
|
|
|
|
|
import {
|
|
|
getAccessToken,
|
|
|
@@ -307,29 +360,7 @@ import { deleteUserCache } from "@hooks/useCache";
|
|
|
|
|
|
// 新增消息中心状态
|
|
|
const activeTab = ref("messages");
|
|
|
-const messages = ref([
|
|
|
- {
|
|
|
- title: "系统通知",
|
|
|
- desc: "您的账户已成功激活",
|
|
|
- time: "10分钟前",
|
|
|
- icon: "mdi:message-text-outline",
|
|
|
- typeClass: "text-blue-500",
|
|
|
- },
|
|
|
- {
|
|
|
- title: "安全提醒",
|
|
|
- desc: "检测到异地登录行为",
|
|
|
- time: "30分钟前",
|
|
|
- icon: "mdi:security",
|
|
|
- typeClass: "text-red-500",
|
|
|
- },
|
|
|
- {
|
|
|
- title: "更新提示",
|
|
|
- desc: "系统将于今晚进行维护升级",
|
|
|
- time: "1小时前",
|
|
|
- icon: "mdi:update",
|
|
|
- typeClass: "text-green-500",
|
|
|
- },
|
|
|
-]);
|
|
|
+const messages = ref([]);
|
|
|
|
|
|
const tasks = ref([
|
|
|
{
|
|
|
@@ -361,9 +392,61 @@ const isLoggedIn = computed(
|
|
|
const userAvatar = computed(() => userStore.user?.avatar || "");
|
|
|
const userName = computed(() => userStore.user?.nickname || "");
|
|
|
|
|
|
+// 是否有未读消息
|
|
|
+const hasUnreadMessages = computed(() => {
|
|
|
+ return messages.value.some((msg) => msg.status === "0");
|
|
|
+});
|
|
|
+
|
|
|
+// 未读消息数量
|
|
|
+const unreadMessageCount = computed(() => {
|
|
|
+ return messages.value.filter((msg) => msg.status === "0").length;
|
|
|
+});
|
|
|
+
|
|
|
+// oa未读
|
|
|
+const oaMessagesList = ref([]);
|
|
|
+onMounted(async () => {
|
|
|
+ if (isLoggedIn) {
|
|
|
+ await getNotifyMessages(userStore.getUser.username);
|
|
|
+
|
|
|
+ const messageList = await getNotifyMessageList(userStore.getUser.username);
|
|
|
+ messages.value = messageList;
|
|
|
+
|
|
|
+ console.log("消息中心数据:", messages.value);
|
|
|
+ }
|
|
|
+});
|
|
|
+
|
|
|
+function timestampToDateTime(timestamp) {
|
|
|
+ // 兼容 10位(秒) / 13位(毫秒)
|
|
|
+ const len = String(timestamp).length;
|
|
|
+ const date = new Date(Number(timestamp) * (len === 10 ? 1000 : 1));
|
|
|
+
|
|
|
+ // 年
|
|
|
+ const year = date.getFullYear();
|
|
|
+ // 月(0~11 → +1)
|
|
|
+ const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
|
+ // 日
|
|
|
+ const day = String(date.getDate()).padStart(2, "0");
|
|
|
+ // 时
|
|
|
+ const hours = String(date.getHours()).padStart(2, "0");
|
|
|
+ // 分
|
|
|
+ const minutes = String(date.getMinutes()).padStart(2, "0");
|
|
|
+ // 秒
|
|
|
+ const seconds = String(date.getSeconds()).padStart(2, "0");
|
|
|
+
|
|
|
+ return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
|
|
+}
|
|
|
+
|
|
|
const router = useRouter();
|
|
|
const drawer = ref(false);
|
|
|
|
|
|
+// 全部标为已读
|
|
|
+const markAllAsRead = async () => {
|
|
|
+ await markMessageAsRead(userStore.getUser.username);
|
|
|
+ // 刷新消息列表
|
|
|
+ const messageList = await getNotifyMessageList(userStore.getUser.username);
|
|
|
+ messages.value = messageList;
|
|
|
+};
|
|
|
+
|
|
|
const goHome = () => {
|
|
|
router.push({ path: "/" });
|
|
|
};
|