优化客服消息通知提醒
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user