增加前端格式检查配置
This commit is contained in:
@@ -68,9 +68,12 @@ export async function ensureSupportChat() {
|
||||
}
|
||||
|
||||
export async function fetchChatMessages(id: number, page = 1, pageSize = 100) {
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<ChatMessage>>>(`/chats/${id}/messages`, {
|
||||
params: { page, page_size: pageSize },
|
||||
})
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<ChatMessage>>>(
|
||||
`/chats/${id}/messages`,
|
||||
{
|
||||
params: { page, page_size: pageSize },
|
||||
}
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
@@ -88,9 +91,12 @@ export async function markChatRead(id: number) {
|
||||
}
|
||||
|
||||
export async function fetchAdminChats(page = 1, pageSize = 50, filter = 'all') {
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<ChatConversation>>>('/admin/chats', {
|
||||
params: { page, page_size: pageSize, filter },
|
||||
})
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<ChatConversation>>>(
|
||||
'/admin/chats',
|
||||
{
|
||||
params: { page, page_size: pageSize, filter },
|
||||
}
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
@@ -100,13 +106,20 @@ export async function fetchAdminChat(id: number) {
|
||||
}
|
||||
|
||||
export async function fetchAdminChatMessages(id: number, page = 1, pageSize = 100) {
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<ChatMessage>>>(`/admin/chats/${id}/messages`, {
|
||||
params: { page, page_size: pageSize },
|
||||
})
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<ChatMessage>>>(
|
||||
`/admin/chats/${id}/messages`,
|
||||
{
|
||||
params: { page, page_size: pageSize },
|
||||
}
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function sendAdminChatMessage(id: number, content: string, attachmentUrls: string[] = []) {
|
||||
export async function sendAdminChatMessage(
|
||||
id: number,
|
||||
content: string,
|
||||
attachmentUrls: string[] = []
|
||||
) {
|
||||
const { data } = await apiClient.post<ApiResponse<ChatMessage>>(`/admin/chats/${id}/messages`, {
|
||||
content,
|
||||
attachment_urls: attachmentUrls,
|
||||
@@ -132,14 +145,20 @@ export async function fetchSupportAdmins() {
|
||||
}
|
||||
|
||||
export async function transferChat(id: number, toAdminId: number) {
|
||||
const { data } = await apiClient.post<ApiResponse<{ transferred: boolean }>>(`/admin/chats/${id}/transfer`, {
|
||||
to_admin_id: toAdminId,
|
||||
})
|
||||
const { data } = await apiClient.post<ApiResponse<{ transferred: boolean }>>(
|
||||
`/admin/chats/${id}/transfer`,
|
||||
{
|
||||
to_admin_id: toAdminId,
|
||||
}
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function updateChatRemark(id: number, remark: string) {
|
||||
const { data } = await apiClient.put<ApiResponse<{ updated: boolean }>>(`/admin/chats/${id}/remark`, { remark })
|
||||
const { data } = await apiClient.put<ApiResponse<{ updated: boolean }>>(
|
||||
`/admin/chats/${id}/remark`,
|
||||
{ remark }
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
@@ -157,7 +176,12 @@ export async function fetchQuickReplies() {
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function createQuickReply(title: string, content: string, sortOrder = 0, isGlobal = false) {
|
||||
export async function createQuickReply(
|
||||
title: string,
|
||||
content: string,
|
||||
sortOrder = 0,
|
||||
isGlobal = false
|
||||
) {
|
||||
const { data } = await apiClient.post<ApiResponse<QuickReply>>('/admin/chats/quick-replies', {
|
||||
title,
|
||||
content,
|
||||
@@ -167,22 +191,35 @@ export async function createQuickReply(title: string, content: string, sortOrder
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function updateQuickReply(id: number, updates: { title?: string; content?: string; sort_order?: number }) {
|
||||
const { data } = await apiClient.put<ApiResponse<{ updated: boolean }>>(`/admin/chats/quick-replies/${id}`, updates)
|
||||
export async function updateQuickReply(
|
||||
id: number,
|
||||
updates: { title?: string; content?: string; sort_order?: number }
|
||||
) {
|
||||
const { data } = await apiClient.put<ApiResponse<{ updated: boolean }>>(
|
||||
`/admin/chats/quick-replies/${id}`,
|
||||
updates
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function deleteQuickReply(id: number) {
|
||||
const { data } = await apiClient.delete<ApiResponse<{ deleted: boolean }>>(`/admin/chats/quick-replies/${id}`)
|
||||
const { data } = await apiClient.delete<ApiResponse<{ deleted: boolean }>>(
|
||||
`/admin/chats/quick-replies/${id}`
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function fetchAutoWelcomeMessage() {
|
||||
const { data } = await apiClient.get<ApiResponse<{ message: string }>>('/admin/chats/auto-welcome')
|
||||
const { data } = await apiClient.get<ApiResponse<{ message: string }>>(
|
||||
'/admin/chats/auto-welcome'
|
||||
)
|
||||
return data.data.message
|
||||
}
|
||||
|
||||
export async function updateAutoWelcomeMessage(message: string) {
|
||||
const { data } = await apiClient.put<ApiResponse<{ updated: boolean }>>('/admin/chats/auto-welcome', { message })
|
||||
const { data } = await apiClient.put<ApiResponse<{ updated: boolean }>>(
|
||||
'/admin/chats/auto-welcome',
|
||||
{ message }
|
||||
)
|
||||
return data.data
|
||||
}
|
||||
|
||||
@@ -34,9 +34,8 @@ async function loadImage() {
|
||||
}
|
||||
try {
|
||||
const key = extractObjectKey(props.source)
|
||||
const blob = props.admin && key
|
||||
? await fetchAdminFileBlob(key)
|
||||
: await fetchFileBlobByURL(props.source)
|
||||
const blob =
|
||||
props.admin && key ? await fetchAdminFileBlob(key) : await fetchFileBlobByURL(props.source)
|
||||
objectURL.value = URL.createObjectURL(blob)
|
||||
} catch {
|
||||
failed.value = true
|
||||
@@ -55,7 +54,7 @@ onBeforeUnmount(revokeCurrentURL)
|
||||
|
||||
<template>
|
||||
<button v-if="objectURL" class="chat-image-button" type="button" @click="openImage">
|
||||
<img :src="objectURL" alt="聊天图片" loading="lazy" decoding="async">
|
||||
<img :src="objectURL" alt="聊天图片" loading="lazy" decoding="async" />
|
||||
</button>
|
||||
<span v-else class="chat-image-fallback">{{ failed ? '图片加载失败' : '图片加载中' }}</span>
|
||||
</template>
|
||||
|
||||
@@ -49,18 +49,22 @@ export function useChatSSE(scope: AuthScope, endpoint: string) {
|
||||
connected.value = true
|
||||
})
|
||||
|
||||
source.addEventListener('new_message', (e) => {
|
||||
source.addEventListener('new_message', e => {
|
||||
try {
|
||||
const data = JSON.parse((e as MessageEvent).data) as ChatEvent
|
||||
handlers.forEach(h => h(data))
|
||||
} catch { /* ignore */ }
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
})
|
||||
|
||||
source.addEventListener('conversation_updated', (e) => {
|
||||
source.addEventListener('conversation_updated', e => {
|
||||
try {
|
||||
const data = JSON.parse((e as MessageEvent).data) as ChatEvent
|
||||
handlers.forEach(h => h(data))
|
||||
} catch { /* ignore */ }
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
})
|
||||
|
||||
source.onerror = async () => {
|
||||
|
||||
@@ -68,10 +68,15 @@ function roleLabel(role: string) {
|
||||
}
|
||||
|
||||
function previewText(item: ChatConversation) {
|
||||
return item.last_message_preview || (item.type === 'general_support' ? '客服会话已创建' : '订单群聊已创建')
|
||||
return (
|
||||
item.last_message_preview ||
|
||||
(item.type === 'general_support' ? '客服会话已创建' : '订单群聊已创建')
|
||||
)
|
||||
}
|
||||
|
||||
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)
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -113,7 +118,9 @@ const unreadTotal = computed(() => conversations.value.reduce((sum, item) => sum
|
||||
<div class="conversation-main">
|
||||
<div class="conversation-title-row">
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user