优化客服消息通知提醒

This commit is contained in:
yml2213
2026-06-08 06:36:31 +08:00
parent 9d6b1d945c
commit 79ea3a476c
6 changed files with 385 additions and 168 deletions
@@ -5,10 +5,12 @@ import { ElMessage } from 'element-plus'
import { ChatDotRound, Refresh, Tickets } from '@element-plus/icons-vue'
import { fetchChats, type ChatConversation } from '@/features/chats/api/chats'
import { useChatSSE, type ChatEvent } from '@/features/chats/composables/useChatSSE'
import { useDesktopNotification } from '@/features/chats/composables/useDesktopNotification'
import NotificationSettings from '@/features/chats/components/NotificationSettings.vue'
import { formatDateMinute } from '@/utils/time'
const router = useRouter()
const currentUserId = Number(localStorage.getItem('user_id') || 0)
const loading = ref(false)
const conversations = ref<ChatConversation[]>([])
const page = ref(1)
@@ -16,12 +18,18 @@ const pageSize = 20
const total = ref(0)
const hasMore = computed(() => conversations.value.length < total.value)
const unreadTotal = computed(() => conversations.value.reduce((sum, item) => sum + item.unread_count, 0))
const unreadTotal = computed(() =>
conversations.value.reduce((sum, item) => sum + item.unread_count, 0)
)
const desktopNotification = useDesktopNotification('user')
const { onEvent } = useChatSSE('user', '/api/chats/events')
onEvent(handleSSEEvent)
onMounted(() => loadChats(true))
onMounted(() => {
desktopNotification.requestPermissionSilently()
loadChats(true)
})
async function loadChats(isRefresh = false, showLoading = true) {
if (isRefresh) page.value = 1
@@ -45,6 +53,12 @@ function handleSSEEvent(event: ChatEvent) {
if (event.type === 'new_message' || event.type === 'conversation_updated') {
loadChats(true, false)
}
if (event.type === 'new_message' && event.message) {
const isSelf = event.message.sender_type === 'user' && event.message.sender_id === currentUserId
if (!isSelf) {
desktopNotification.notify(event, null)
}
}
}
function openConversation(item: ChatConversation) {
@@ -52,12 +66,20 @@ function openConversation(item: ChatConversation) {
}
function roleLabel(role: string) {
const map: Record<string, string> = { renter: '租客', owner: '号主', support: '客服', customer: '咨询' }
const map: Record<string, string> = {
renter: '租客',
owner: '号主',
support: '客服',
customer: '咨询',
}
return map[role] || '成员'
}
function previewText(item: ChatConversation) {
return item.last_message_preview || (item.type === 'general_support' ? '客服会话已创建' : '订单群聊已创建')
return (
item.last_message_preview ||
(item.type === 'general_support' ? '客服会话已创建' : '订单群聊已创建')
)
}
</script>
@@ -72,7 +94,9 @@ function previewText(item: ChatConversation) {
<div class="header-actions">
<NotificationSettings scope="user" />
<el-button :icon="Refresh" :loading="loading" @click="loadChats(true)">刷新</el-button>
<el-button type="primary" :icon="Tickets" @click="router.push('/orders')">我的订单</el-button>
<el-button type="primary" :icon="Tickets" @click="router.push('/orders')"
>我的订单</el-button
>
</div>
</div>
@@ -80,7 +104,9 @@ function previewText(item: ChatConversation) {
<div v-else-if="!loading && conversations.length === 0" class="empty-panel">
<el-empty description="暂无会话">
<el-button type="primary" :icon="Tickets" @click="router.push('/orders')">查看订单</el-button>
<el-button type="primary" :icon="Tickets" @click="router.push('/orders')"
>查看订单</el-button
>
</el-empty>
</div>
@@ -99,11 +125,15 @@ function previewText(item: ChatConversation) {
<div class="conversation-body">
<div class="conversation-head">
<h2>{{ item.title }}</h2>
<span class="conversation-time">{{ formatDateMinute(item.last_message_at || item.created_at) }}</span>
<span class="conversation-time">{{
formatDateMinute(item.last_message_at || item.created_at)
}}</span>
</div>
<div class="conversation-meta">
<span class="role-chip">{{ roleLabel(item.role) }}</span>
<span class="order-id">{{ item.order_id ? `订单 #${item.order_id}` : '平台客服' }}</span>
<span class="order-id">{{
item.order_id ? `订单 #${item.order_id}` : '平台客服'
}}</span>
</div>
<p class="conversation-preview">{{ previewText(item) }}</p>
</div>
@@ -167,7 +197,9 @@ function previewText(item: ChatConversation) {
background: #fff;
text-align: left;
cursor: pointer;
transition: border-color 0.15s, box-shadow 0.15s;
transition:
border-color 0.15s,
box-shadow 0.15s;
box-shadow: 0 2px 8px rgba(15, 23, 42, 0.04);
}