|
|
@@ -36,6 +36,7 @@
|
|
|
<component :is="cat.icon" />
|
|
|
</el-icon>
|
|
|
<span class="side-text">{{ cat.title }}</span>
|
|
|
+ <el-badge v-if="cat.unread > 0" :value="handleReadCount(cat.unread)" class="side-badge" />
|
|
|
</div>
|
|
|
</template>
|
|
|
</div>
|
|
|
@@ -134,6 +135,7 @@
|
|
|
v-for="(item, index) in currentMessageList"
|
|
|
:key="item.id + '_' + index"
|
|
|
class="message-card message-card-clickable"
|
|
|
+ :class="{ unread: item.unread }"
|
|
|
@click="handleMessageItemClick(item)"
|
|
|
>
|
|
|
<div class="message-avatar">
|
|
|
@@ -146,8 +148,16 @@
|
|
|
<span class="message-sender">{{ item.senderName }}</span>
|
|
|
<span class="message-date">{{ item.date }}</span>
|
|
|
</div>
|
|
|
- <div class="message-content">
|
|
|
- {{ processContent(item) }}
|
|
|
+ <div class="message-content-row">
|
|
|
+ <span class="message-content">{{ processContent(item) }}</span>
|
|
|
+ <div class="message-status">
|
|
|
+ <!-- 非免打扰:显示数字徽标 -->
|
|
|
+ <span v-if="item.isNotDisturb !== '1' && (item.notReadCount ?? 0) > 0" class="message-count">
|
|
|
+ {{ handleReadCount(item.notReadCount!) }}
|
|
|
+ </span>
|
|
|
+ <!-- 免打扰:显示小红点 -->
|
|
|
+ <span v-else-if="item.isNotDisturb === '1' && (item.notReadCount ?? 0) > 0" class="message-dot" />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
@@ -175,8 +185,8 @@ import {
|
|
|
getNoticeListForHeader,
|
|
|
readNoticeById,
|
|
|
getCountUnreadByType,
|
|
|
- getNoFriendMessage,
|
|
|
- getMessageList
|
|
|
+ getMessageList,
|
|
|
+ getStrangerMessageNum
|
|
|
} from "@/api/modules/headerNotice";
|
|
|
import type { NoFriendMessageItem } from "@/api/modules/headerNotice";
|
|
|
|
|
|
@@ -202,7 +212,13 @@ interface MessageItem {
|
|
|
content: string;
|
|
|
date: string;
|
|
|
unread: boolean;
|
|
|
+ /** 未读数量,用于展示红点/数字 */
|
|
|
+ notReadCount?: number;
|
|
|
+ /** 免打扰:'0' 非免打扰显示数字,'1' 免打扰显示小红点(与商家端一致) */
|
|
|
+ isNotDisturb?: string;
|
|
|
avatar?: string;
|
|
|
+ /** 发送方 phoneId,用于跳转聊天页 */
|
|
|
+ phoneId?: string;
|
|
|
/** 发送方 id,用于跳转聊天页 */
|
|
|
senderId?: string;
|
|
|
/** 消息类型,用于 processContent 展示 */
|
|
|
@@ -300,17 +316,21 @@ function switchMessageCategory(key: string) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 未关注人消息:/message/getNoFriendMessage,参数 receiverId
|
|
|
+// 未关注人消息:/message/getNoFriendMessage,参数 receiverId。映射与商家端 message-notices 一致
|
|
|
function mapNoFriendToMessageItem(item: NoFriendMessageItem): MessageItem {
|
|
|
const createdTime = item.createdTime ?? "";
|
|
|
const dateStr = createdTime.includes(" ") ? createdTime.split(" ")[0].replace(/-/g, "/") : createdTime.replace(/-/g, "/");
|
|
|
+ const notReadCount = item.notReadCount ?? (item.isRead === 0 ? 1 : 0);
|
|
|
return {
|
|
|
id: String(item.id ?? ""),
|
|
|
senderName: item.senderName ?? item.userName ?? "",
|
|
|
content: item.content ?? "",
|
|
|
date: dateStr,
|
|
|
unread: item.isRead === 0,
|
|
|
+ notReadCount,
|
|
|
+ isNotDisturb: (item as any).isNotDisturb ?? "0",
|
|
|
avatar: item.userImage ?? item.senderImg ?? item.storeImg ?? undefined,
|
|
|
+ phoneId: (item as any).phoneId != null ? String((item as any).phoneId) : undefined,
|
|
|
senderId: item.senderId != null ? String(item.senderId) : undefined,
|
|
|
type: item.type,
|
|
|
voiceDuration: (item as any).voiceDuration ?? (item as any).duration,
|
|
|
@@ -318,31 +338,53 @@ function mapNoFriendToMessageItem(item: NoFriendMessageItem): MessageItem {
|
|
|
};
|
|
|
}
|
|
|
|
|
|
-async function fetchNoFriendMessage() {
|
|
|
+// 未关注人消息未读数:使用 message/getStrangerMessageNum 接口,取 data.notReadCount
|
|
|
+async function fetchUnfollowedUnreadCount() {
|
|
|
const receiverId = getReceiverId();
|
|
|
if (!receiverId) {
|
|
|
- messageListByCategory.value.unfollowed = [];
|
|
|
const cat = messageCategories.value.find(c => c.key === "unfollowed");
|
|
|
if (cat) cat.unread = 0;
|
|
|
return;
|
|
|
}
|
|
|
+ try {
|
|
|
+ const res: any = await getStrangerMessageNum({ receiverId: "store_" + receiverId });
|
|
|
+ if (res?.mas == "暂无承载数据" || res?.msg == "暂无承载数据") {
|
|
|
+ const cat = messageCategories.value.find(c => c.key === "unfollowed");
|
|
|
+ if (cat) cat.unread = 0;
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const data = res?.data ?? res;
|
|
|
+ const notReadCount = data?.notReadCount ?? 0;
|
|
|
+ const cat = messageCategories.value.find(c => c.key === "unfollowed");
|
|
|
+ if (cat) cat.unread = Number(notReadCount) || 0;
|
|
|
+ } catch (e) {
|
|
|
+ const cat = messageCategories.value.find(c => c.key === "unfollowed");
|
|
|
+ if (cat) cat.unread = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// 陌生人/未关注人消息列表:使用 message/getMessageList,friendType=2(与商家端 message-notFriend 一致)
|
|
|
+async function fetchNoFriendMessage() {
|
|
|
+ const receiverId = getReceiverId();
|
|
|
+ if (!receiverId) {
|
|
|
+ messageListByCategory.value.unfollowed = [];
|
|
|
+ await fetchUnfollowedUnreadCount();
|
|
|
+ return;
|
|
|
+ }
|
|
|
messageLoading.value = true;
|
|
|
try {
|
|
|
- const res: any = await getNoFriendMessage({ receiverId: "store_" + receiverId });
|
|
|
+ const res: any = await getMessageList({ receiverId: "store_" + receiverId, friendType: 2 });
|
|
|
const data = res?.data ?? res;
|
|
|
- if (data.msg == "暂无承载数据") {
|
|
|
+ if (data?.msg == "暂无承载数据") {
|
|
|
messageListByCategory.value.unfollowed = [];
|
|
|
+ const cat = messageCategories.value.find(c => c.key === "unfollowed");
|
|
|
+ if (cat) cat.unread = 0;
|
|
|
return;
|
|
|
}
|
|
|
const rawList = Array.isArray(data) ? data : data ? [data] : [];
|
|
|
const list: MessageItem[] = rawList.map((item: NoFriendMessageItem) => mapNoFriendToMessageItem(item));
|
|
|
messageListByCategory.value.unfollowed = list;
|
|
|
- const unreadTotal = rawList.reduce(
|
|
|
- (sum: number, item: NoFriendMessageItem) => sum + (item.notReadCount ?? (item.isRead === 0 ? 1 : 0)),
|
|
|
- 0
|
|
|
- );
|
|
|
- const cat = messageCategories.value.find(c => c.key === "unfollowed");
|
|
|
- if (cat) cat.unread = unreadTotal;
|
|
|
+ await fetchUnfollowedUnreadCount();
|
|
|
} catch (e) {
|
|
|
messageListByCategory.value.unfollowed = [];
|
|
|
const cat = messageCategories.value.find(c => c.key === "unfollowed");
|
|
|
@@ -352,7 +394,7 @@ async function fetchNoFriendMessage() {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-// 消息列表:/message/getMessageList,参数 friendType 默认 0、receiverId,返回结构与 getNoFriendMessage 一致
|
|
|
+// 消息列表:/message/getMessageList,friendType=1 仅返回已关注/好友消息(不包含未关注人,与商家端一致)
|
|
|
async function fetchMessageList() {
|
|
|
const receiverId = getReceiverId();
|
|
|
if (!receiverId) {
|
|
|
@@ -363,7 +405,7 @@ async function fetchMessageList() {
|
|
|
}
|
|
|
messageLoading.value = true;
|
|
|
try {
|
|
|
- const res: any = await getMessageList({ receiverId: "store_" + receiverId, friendType: 0 });
|
|
|
+ const res: any = await getMessageList({ receiverId: "store_" + receiverId, friendType: 1 });
|
|
|
const data = res?.data ?? res;
|
|
|
const rawList = Array.isArray(data) ? data : data ? [data] : [];
|
|
|
const list: MessageItem[] = rawList.map((item: NoFriendMessageItem) => mapNoFriendToMessageItem(item));
|
|
|
@@ -388,10 +430,16 @@ function getReceiverId(): string {
|
|
|
return localGet("iphone") || localGet("geeker-user")?.userInfo?.phone || "";
|
|
|
}
|
|
|
|
|
|
-// 点击消息列表项:关闭抽屉并跳转聊天页(与 storeDecoration 装修聊天一致)
|
|
|
+// 未读数量展示:超过 99 显示 99(与商家端 handleReadCount 一致)
|
|
|
+function handleReadCount(val: number): string {
|
|
|
+ if (Number(val) > 99) return "99";
|
|
|
+ return String(val);
|
|
|
+}
|
|
|
+
|
|
|
+// 点击消息列表项:关闭抽屉并跳转聊天页(与 storeDecoration 装修聊天一致,receiverId 用 phoneId)
|
|
|
function handleMessageItemClick(item: MessageItem) {
|
|
|
- console.log("item", item);
|
|
|
- const receiverId = item.senderName;
|
|
|
+ const receiverId = item.phoneId ?? item.senderId;
|
|
|
+
|
|
|
if (!receiverId) return;
|
|
|
emit("close");
|
|
|
const params = new URLSearchParams({
|
|
|
@@ -577,6 +625,20 @@ function handleDelete(item: NoticeItem, index: number) {
|
|
|
const cat = noticeCategories.value.find(c => c.key === key);
|
|
|
if (cat && item.unread) cat.unread = Math.max(0, cat.unread - 1);
|
|
|
}
|
|
|
+/** 刷新全部(供 WebSocket 消息到达时实时更新,与商家端一致) */
|
|
|
+function refresh() {
|
|
|
+ if (activeTab.value === "notice") {
|
|
|
+ fetchNoticeUnreadCounts();
|
|
|
+ fetchNoticeList(activeCategory.value);
|
|
|
+ } else {
|
|
|
+ fetchUnfollowedUnreadCount();
|
|
|
+ fetchNoFriendMessage();
|
|
|
+ fetchMessageList();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+defineExpose({ refresh });
|
|
|
+
|
|
|
onMounted(() => {
|
|
|
refreshAllNoticeCategories();
|
|
|
});
|
|
|
@@ -740,14 +802,51 @@ watch(activeTab, val => {
|
|
|
}
|
|
|
}
|
|
|
.message-date {
|
|
|
+ flex-shrink: 0;
|
|
|
font-size: 12px;
|
|
|
color: var(--el-text-color-secondary);
|
|
|
}
|
|
|
- .message-content {
|
|
|
+ .message-content-row {
|
|
|
+ display: flex;
|
|
|
+ gap: 10px;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
margin-bottom: 8px;
|
|
|
+ }
|
|
|
+ .message-content {
|
|
|
+ flex: 1;
|
|
|
+ min-width: 0;
|
|
|
+ overflow: hidden;
|
|
|
font-size: 14px;
|
|
|
line-height: 1.5;
|
|
|
color: var(--el-text-color-regular);
|
|
|
+ text-overflow: ellipsis;
|
|
|
+ white-space: nowrap;
|
|
|
+ }
|
|
|
+ .message-status {
|
|
|
+ position: relative;
|
|
|
+ display: flex;
|
|
|
+ flex-shrink: 0;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+ .message-count {
|
|
|
+ display: inline-flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ min-width: 20px;
|
|
|
+ height: 20px;
|
|
|
+ padding: 0 6px;
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #ffffff;
|
|
|
+ background: #ff2442;
|
|
|
+ border-radius: 10px;
|
|
|
+ }
|
|
|
+ .message-dot {
|
|
|
+ width: 8px;
|
|
|
+ height: 8px;
|
|
|
+ background: var(--el-color-danger);
|
|
|
+ border-radius: 50%;
|
|
|
}
|
|
|
.message-actions {
|
|
|
display: flex;
|