12284290cc
- orders: remove name fields from creation, keep dispatchMode logic - chat: remove readonly/senderName/senderAvatar references - reviews: remove fromUserAvatar/toUserId, simplify participant check - disputes: remove initiatorId/initiatorName from creation - posts: remove authorRole/quotedPostId, keep linkedOrderId as number - comments: remove postId from creation - wallet: use string amounts
105 lines
2.7 KiB
TypeScript
105 lines
2.7 KiB
TypeScript
import { generateId } from "@/lib/id"
|
|
import type { ChatMessage, ChatSession, Order } from "@/lib/types"
|
|
import { create } from "zustand"
|
|
|
|
interface ChatState {
|
|
sessions: ChatSession[]
|
|
messages: ChatMessage[]
|
|
ensureOrderSession: (order: Order) => ChatSession
|
|
sendTextMessage: (sessionId: string, actorId: string, content: string) => void
|
|
sendImageMessage: (sessionId: string, actorId: string, imageUrl: string) => void
|
|
}
|
|
|
|
function resolveAvatar(_userId: string) {
|
|
return ""
|
|
}
|
|
|
|
export const useChatStore = create<ChatState>((set, get) => ({
|
|
sessions: [],
|
|
messages: [],
|
|
ensureOrderSession: (order) => {
|
|
const existing = get().sessions.find(
|
|
(session) => session.type === "order" && session.orderId === order.id,
|
|
)
|
|
|
|
if (existing) {
|
|
return existing
|
|
}
|
|
|
|
const session: ChatSession = {
|
|
id: `chat-${order.id}`,
|
|
type: "order",
|
|
orderId: order.id,
|
|
participants: [
|
|
{
|
|
id: order.consumerId,
|
|
nickname: "",
|
|
avatar: resolveAvatar(order.consumerId),
|
|
},
|
|
{
|
|
id: order.playerId,
|
|
nickname: "",
|
|
avatar: resolveAvatar(order.playerId),
|
|
},
|
|
],
|
|
unreadCount: 0,
|
|
}
|
|
|
|
set((state) => ({
|
|
sessions: [session, ...state.sessions],
|
|
}))
|
|
|
|
return session
|
|
},
|
|
sendTextMessage: (sessionId, actorId, content) => {
|
|
const text = content.trim()
|
|
if (!text) return
|
|
const session = get().sessions.find((item) => item.id === sessionId)
|
|
if (!session) return
|
|
|
|
const sender = session.participants.find((participant) => participant.id === actorId)
|
|
if (!sender) return
|
|
|
|
const now = new Date().toISOString()
|
|
const message: ChatMessage = {
|
|
id: generateId("msg"),
|
|
sessionId,
|
|
senderId: actorId,
|
|
type: "text",
|
|
content: text,
|
|
createdAt: now,
|
|
}
|
|
|
|
set((state) => ({
|
|
messages: [...state.messages, message],
|
|
sessions: state.sessions.map((s) => (s.id === sessionId ? { ...s, lastMessage: text } : s)),
|
|
}))
|
|
},
|
|
sendImageMessage: (sessionId, actorId, imageUrl) => {
|
|
const content = imageUrl.trim()
|
|
if (!content) return
|
|
const session = get().sessions.find((item) => item.id === sessionId)
|
|
if (!session) return
|
|
|
|
const sender = session.participants.find((participant) => participant.id === actorId)
|
|
if (!sender) return
|
|
|
|
const now = new Date().toISOString()
|
|
const message: ChatMessage = {
|
|
id: generateId("msg"),
|
|
sessionId,
|
|
senderId: actorId,
|
|
type: "image",
|
|
content,
|
|
createdAt: now,
|
|
}
|
|
|
|
set((state) => ({
|
|
messages: [...state.messages, message],
|
|
sessions: state.sessions.map((item) =>
|
|
item.id === sessionId ? { ...item, lastMessage: "[图片]" } : item,
|
|
),
|
|
}))
|
|
},
|
|
}))
|