From 179abe01b02b13a79bd0e66737c7514ec98d40a1 Mon Sep 17 00:00:00 2001 From: zzc <1761997216@qq.com> Date: Mon, 15 Jun 2026 00:15:23 +0800 Subject: [PATCH] feat: rating --- App.vue | 5 + api/notification.js | 60 ++ components/LoginPopup/LoginPopup.vue | 3 + pages/message/index.vue | 879 +++++++++++++++++++++++++++ stores/user.js | 4 + utils/tabBar.js | 65 ++ 6 files changed, 1016 insertions(+) create mode 100644 api/notification.js create mode 100644 utils/tabBar.js diff --git a/App.vue b/App.vue index ceaacbf..ede85fb 100644 --- a/App.vue +++ b/App.vue @@ -1,6 +1,7 @@ diff --git a/api/notification.js b/api/notification.js new file mode 100644 index 0000000..c132fa0 --- /dev/null +++ b/api/notification.js @@ -0,0 +1,60 @@ +import { request } from "@/utils/request.js"; + +export const RatingNotificationTypeEnum = { + TOPIC_SUBMIT: 'topic_submit', + TOPIC_APPROVED: 'topic_approved', + TOPIC_REJECTED: 'topic_rejected', + ITEM_SUBMIT: 'item_submit', + ITEM_APPROVED: 'item_approved', + ITEM_REJECTED: 'item_rejected', + COMMENT: 'comment', + COMMENT_LIKE: 'comment_like', + SYSTEM: 'system', +} +/** + * @description: 获取当前用户的消息列表 + * @param {page: number, type?: RatingNotificationTypeEnum} data + * @return + */ +export const fetchNotificationList = async (data) => { + return request({ + url: "/api/rating/personal/notification/list", + method: "GET", + data, + }); +}; + +/** + * @description: 获取当前用户未读消息数量 + * @return + */ + +export const fetchUnreadCount = async () => { + return request({ + url: "/api/rating/personal/notification/unread_count", + method: "GET", + }); +}; + +/** + * @description: 标记指定消息为已读 + * @param {id: number} data + * @return + */ +export const markAsRead = async (id) => { + return request({ + url: "/api/rating/personal/notification/read/" + id, + method: "Patch", + }); +}; + +/** + * @description: 标记所有消息为已读 + * @return + */ +export const markAllAsRead = async () => { + return request({ + url: "/api/rating/personal/notification/read_all", + method: "Patch", + }); +}; diff --git a/components/LoginPopup/LoginPopup.vue b/components/LoginPopup/LoginPopup.vue index f5809ef..cf040b9 100644 --- a/components/LoginPopup/LoginPopup.vue +++ b/components/LoginPopup/LoginPopup.vue @@ -94,6 +94,7 @@ import { getPlatformProvider, isSinglePageMode } from "@/utils/system"; import { uploadImage } from "@/utils/common"; import { apiLogin } from "@/api/auth.js"; import { wxLogin, alipayLogin } from "@/utils/login.js"; +import { refreshMessageTabBarBadge } from "@/utils/tabBar"; import PrivacyPopup from "@/components/PrivacyPopup/PrivacyPopup.vue"; const popupRef = ref(null); @@ -219,6 +220,7 @@ const handleAlipayLogin = async () => { uni.hideLoading(); uni.showToast({ title: "登录成功", icon: "success" }); + refreshMessageTabBarBadge(); emit("logind"); popupRef.value.close(); @@ -292,6 +294,7 @@ const confirmLogin = async () => { userStore.setToken(loginRes.token); uni.hideLoading(); uni.showToast({ title: "登录成功", icon: "success" }); + refreshMessageTabBarBadge(); emit("logind"); popupRef.value.close(); diff --git a/pages/message/index.vue b/pages/message/index.vue index e69de29..3fbfd79 100644 --- a/pages/message/index.vue +++ b/pages/message/index.vue @@ -0,0 +1,879 @@ + + + + + diff --git a/stores/user.js b/stores/user.js index c532398..c73c84a 100644 --- a/stores/user.js +++ b/stores/user.js @@ -34,6 +34,8 @@ export const useUserStore = defineStore("user", { this.userInfo = {}; uni.removeStorageSync("token"); uni.removeStorageSync("userInfo"); + uni.removeTabBarBadge({ index: 3 }); + uni.hideTabBarRedDot({ index: 3 }); }, loadUserInfo() { const userStr = uni.getStorageSync("userInfo"); @@ -83,6 +85,8 @@ export const useUserStore = defineStore("user", { this.token = ""; uni.removeStorageSync("userInfo"); uni.removeStorageSync("token"); + uni.removeTabBarBadge({ index: 3 }); + uni.hideTabBarRedDot({ index: 3 }); }, }, }); diff --git a/utils/tabBar.js b/utils/tabBar.js new file mode 100644 index 0000000..85f0ac2 --- /dev/null +++ b/utils/tabBar.js @@ -0,0 +1,65 @@ +import { fetchUnreadCount } from "@/api/notification"; + +const MESSAGE_TAB_INDEX = 3; + +function parseStoredUserInfo() { + const raw = uni.getStorageSync("userInfo"); + if (!raw) return {}; + + try { + return typeof raw === "string" ? JSON.parse(raw) : raw; + } catch (error) { + return {}; + } +} + +function hasLoginState() { + const token = uni.getStorageSync("token"); + const userInfo = parseStoredUserInfo(); + return !!token || !!userInfo?.nickName; +} + +export function syncMessageTabBarBadge(unreadCount = 0) { + const count = Number(unreadCount) || 0; + + if (count > 0) { + const text = count > 99 ? "99+" : String(count); + uni.setTabBarBadge({ + index: MESSAGE_TAB_INDEX, + text, + }); + return; + } + + uni.removeTabBarBadge({ + index: MESSAGE_TAB_INDEX, + }); + uni.hideTabBarRedDot({ + index: MESSAGE_TAB_INDEX, + }); +} + +export async function refreshMessageTabBarBadge() { + if (!hasLoginState()) { + syncMessageTabBarBadge(0); + return 0; + } + + try { + const res = await fetchUnreadCount(); + const count = + Number( + res?.data?.count ?? + res?.data?.unreadCount ?? + res?.count ?? + res?.unreadCount ?? + res?.data ?? + 0 + ) || 0; + + syncMessageTabBarBadge(count); + return count; + } catch (error) { + return 0; + } +}