feat: Features架构迁移 - P0和P1部分完成
## 完成的工作 ### P0: 基础设施准备 - 创建 features/ 和 shared/ 目录结构 - 迁移共享资源:API基础设施、工具函数、类型定义 - 迁移通用composables:useMoney, useSmsCountdown, usePricingCalculator - 迁移全局样式文件 - 建立模块化导出系统 ### P1.1: 钱包模块 (wallet) - 迁移 API: wallet.ts - 迁移 Views: WalletView.vue - 新增 Composable: useWallet.ts (封装钱包状态管理) - 更新导入路径到 shared/ ### P1.2: 聊天模块 (chats) - 迁移 API: chats.ts - 迁移 Views: ChatView, MessagesView (桌面+移动) - 迁移 Composables: useChatSSE.ts - 迁移 Components: ChatAttachmentImage.vue - 更新导入路径到 shared/ ## 技术改进 - 修复 shared/composables 导出问题 (default → 命名导出) - 修复 shared/api/client.ts 类型导入路径 - 建立清晰的模块边界和导出规范 ## 文档 - 添加完整的迁移计划文档 - 添加进度跟踪文档 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
10acca637e
commit
b5903a169f
@@ -0,0 +1,187 @@
|
||||
import { apiClient } from '@/shared/api/client'
|
||||
import type { ApiResponse, PaginatedResult } from '@/shared/types/types'
|
||||
|
||||
export interface ChatParticipant {
|
||||
id: number
|
||||
conversation_id: number
|
||||
participant_type: 'user' | 'admin'
|
||||
participant_id: number
|
||||
role: 'renter' | 'owner' | 'support' | 'customer'
|
||||
remark: string
|
||||
display_name: string
|
||||
avatar_url: string
|
||||
last_read_at?: string
|
||||
joined_at: string
|
||||
}
|
||||
|
||||
export interface ChatConversation {
|
||||
id: number
|
||||
order_id: number | null
|
||||
type: string
|
||||
title: string
|
||||
status: string
|
||||
role: 'renter' | 'owner' | 'support' | 'customer'
|
||||
participants?: ChatParticipant[]
|
||||
last_message_id?: number
|
||||
last_message_preview: string
|
||||
last_message_at?: string
|
||||
unread_count: number
|
||||
created_at: string
|
||||
updated_at: string
|
||||
}
|
||||
|
||||
export interface ChatMessage {
|
||||
id: number
|
||||
conversation_id: number
|
||||
sender_type: 'user' | 'admin' | 'system'
|
||||
sender_id: number
|
||||
sender_role: 'renter' | 'owner' | 'support' | 'customer' | 'system'
|
||||
sender_name: string
|
||||
sender_avatar: string
|
||||
is_self: boolean
|
||||
content_type: 'text' | 'system'
|
||||
content: string
|
||||
attachment_urls: string[]
|
||||
created_at: string
|
||||
}
|
||||
|
||||
export async function fetchChats(page = 1, pageSize = 20) {
|
||||
const { data } = await apiClient.get<ApiResponse<PaginatedResult<ChatConversation>>>('/chats', {
|
||||
params: { page, page_size: pageSize },
|
||||
})
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function fetchChat(id: number) {
|
||||
const { data } = await apiClient.get<ApiResponse<ChatConversation>>(`/chats/${id}`)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function fetchOrderChat(orderId: number) {
|
||||
const { data } = await apiClient.get<ApiResponse<ChatConversation>>(`/orders/${orderId}/chat`)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function ensureSupportChat() {
|
||||
const { data } = await apiClient.post<ApiResponse<ChatConversation>>('/chats/support')
|
||||
return data.data
|
||||
}
|
||||
|
||||
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 },
|
||||
})
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function sendChatMessage(id: number, content: string, attachmentUrls: string[] = []) {
|
||||
const { data } = await apiClient.post<ApiResponse<ChatMessage>>(`/chats/${id}/messages`, {
|
||||
content,
|
||||
attachment_urls: attachmentUrls,
|
||||
})
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function markChatRead(id: number) {
|
||||
const { data } = await apiClient.post<ApiResponse<{ read: boolean }>>(`/chats/${id}/read`)
|
||||
return data.data
|
||||
}
|
||||
|
||||
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 },
|
||||
})
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function fetchAdminChat(id: number) {
|
||||
const { data } = await apiClient.get<ApiResponse<ChatConversation>>(`/admin/chats/${id}`)
|
||||
return data.data
|
||||
}
|
||||
|
||||
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 },
|
||||
})
|
||||
return data.data
|
||||
}
|
||||
|
||||
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,
|
||||
})
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function markAdminChatRead(id: number) {
|
||||
const { data } = await apiClient.post<ApiResponse<{ read: boolean }>>(`/admin/chats/${id}/read`)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export interface SupportAdmin {
|
||||
id: number
|
||||
nickname: string
|
||||
chat_count: number
|
||||
}
|
||||
|
||||
export async function fetchSupportAdmins() {
|
||||
const { data } = await apiClient.get<ApiResponse<SupportAdmin[]>>('/admin/chats/support-admins')
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function transferChat(id: number, toAdminId: number) {
|
||||
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 })
|
||||
return data.data
|
||||
}
|
||||
|
||||
export interface QuickReply {
|
||||
id: number
|
||||
admin_user_id: number
|
||||
title: string
|
||||
content: string
|
||||
sort_order: number
|
||||
is_global: boolean
|
||||
}
|
||||
|
||||
export async function fetchQuickReplies() {
|
||||
const { data } = await apiClient.get<ApiResponse<QuickReply[]>>('/admin/chats/quick-replies')
|
||||
return data.data
|
||||
}
|
||||
|
||||
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,
|
||||
sort_order: sortOrder,
|
||||
is_global: isGlobal,
|
||||
})
|
||||
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)
|
||||
return data.data
|
||||
}
|
||||
|
||||
export async function deleteQuickReply(id: number) {
|
||||
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')
|
||||
return data.data.message
|
||||
}
|
||||
|
||||
export async function updateAutoWelcomeMessage(message: string) {
|
||||
const { data } = await apiClient.put<ApiResponse<{ updated: boolean }>>('/admin/chats/auto-welcome', { message })
|
||||
return data.data
|
||||
}
|
||||
Reference in New Issue
Block a user