refactor(api): add adapter layer for order/chat/review/dispute writes

This commit is contained in:
zetaloop
2026-02-23 11:04:16 +08:00
parent 1dfcd3927d
commit 8e62b15403
10 changed files with 258 additions and 98 deletions
+42
View File
@@ -1,4 +1,6 @@
import { allow, deny } from "@/lib/policy/assert"
import { useChatStore } from "@/store/chat"
import { useAuthStore } from "@/store/auth"
export function listChatSessions() {
return useChatStore.getState().sessions
@@ -11,3 +13,43 @@ export function getChatSessionById(sessionId: string) {
export function listChatMessages(sessionId: string) {
return useChatStore.getState().messages.filter((message) => message.sessionId === sessionId)
}
export function sendTextMessage(sessionId: string, content: string) {
const userId = useAuthStore.getState().user?.id
if (!userId) return deny("AUTH_REQUIRED", "请先登录")
const chatState = useChatStore.getState()
const session = chatState.sessions.find((item) => item.id === sessionId)
if (!session) return deny("NOT_FOUND", "会话不存在")
if (session.readonly) return deny("INVALID_STATUS", "当前会话只读")
if (!session.participants.some((participant) => participant.id === userId)) {
return deny("NOT_PARTICIPANT", "仅会话参与方可发送消息")
}
if (!content.trim()) {
return deny("VALIDATION_FAILED", "消息不能为空")
}
chatState.sendTextMessage(sessionId, userId, content)
return allow()
}
export function sendImageMessage(sessionId: string, imageUrl: string) {
const userId = useAuthStore.getState().user?.id
if (!userId) return deny("AUTH_REQUIRED", "请先登录")
const chatState = useChatStore.getState()
const session = chatState.sessions.find((item) => item.id === sessionId)
if (!session) return deny("NOT_FOUND", "会话不存在")
if (session.readonly) return deny("INVALID_STATUS", "当前会话只读")
if (!session.participants.some((participant) => participant.id === userId)) {
return deny("NOT_PARTICIPANT", "仅会话参与方可发送消息")
}
if (!imageUrl.trim()) {
return deny("VALIDATION_FAILED", "图片地址无效")
}
chatState.sendImageMessage(sessionId, userId, imageUrl)
return allow()
}
+41
View File
@@ -1,3 +1,5 @@
import { deny } from "@/lib/policy/assert"
import { useAuthStore } from "@/store/auth"
import { useDisputeStore } from "@/store/disputes"
export function listDisputes() {
@@ -7,3 +9,42 @@ export function listDisputes() {
export function getDisputeByOrderId(orderId: string) {
return useDisputeStore.getState().disputes.find((dispute) => dispute.orderId === orderId)
}
export function submitDispute(input: { orderId: string; reason: string; evidence: string[] }) {
const user = useAuthStore.getState().user
if (!user?.id || !user.nickname) {
return { decision: deny("AUTH_REQUIRED", "请先登录") }
}
return useDisputeStore.getState().submitDispute({
orderId: input.orderId,
initiatorId: user.id,
initiatorName: user.nickname,
reason: input.reason,
evidence: input.evidence,
})
}
export function submitDisputeResponse(input: {
disputeId: string
reason: string
evidence: string[]
}) {
const userId = useAuthStore.getState().user?.id
if (!userId) {
return deny("AUTH_REQUIRED", "请先登录")
}
return useDisputeStore
.getState()
.submitResponse(input.disputeId, userId, input.reason, input.evidence)
}
export function submitDisputeAppeal(input: { disputeId: string; reason: string }) {
const userId = useAuthStore.getState().user?.id
if (!userId) {
return deny("AUTH_REQUIRED", "请先登录")
}
return useDisputeStore.getState().submitAppeal(input.disputeId, userId, input.reason)
}
+86
View File
@@ -1,4 +1,11 @@
import { resolveOwnerShop } from "@/lib/domain/resolve-current-shop"
import { allow, deny } from "@/lib/policy/assert"
import type { Actor } from "@/lib/policy/actor"
import type { PolicyDecision } from "@/lib/policy/decision"
import type { PlayerService } from "@/lib/types"
import { useAuthStore } from "@/store/auth"
import { useOrderStore } from "@/store/orders"
import { useShopStore } from "@/store/shops"
export function listOrders() {
return useOrderStore.getState().orders
@@ -11,3 +18,82 @@ export function getOrderById(orderId: string) {
export function listOrdersByConsumer(consumerId: string) {
return useOrderStore.getState().orders.filter((order) => order.consumerId === consumerId)
}
interface CreatePaidOrderInput {
consumerId: string
consumerName: string
playerId: string
playerName: string
shopId?: string
shopName?: string
service: PlayerService
totalPrice: number
note?: string
}
function resolveActorContext(): { actor?: Actor; decision: PolicyDecision } {
const auth = useAuthStore.getState()
if (!auth.user?.id) {
return { decision: deny("AUTH_REQUIRED", "请先登录") }
}
const shopId =
auth.currentRole === "owner"
? resolveOwnerShop(auth.user.id, useShopStore.getState().shops)?.id
: undefined
return {
actor: {
userId: auth.user.id,
role: auth.currentRole,
shopId,
},
decision: allow(),
}
}
export function createPaidOrder(input: CreatePaidOrderInput) {
const { actor, decision } = resolveActorContext()
if (!actor) return { decision }
return useOrderStore.getState().createPaidOrder(input, actor)
}
export function payOrder(orderId: string) {
const { actor, decision } = resolveActorContext()
if (!actor) return { decision }
return useOrderStore.getState().payOrder(orderId, actor)
}
export function acceptOrder(orderId: string) {
const { actor, decision } = resolveActorContext()
if (!actor) return { decision }
return useOrderStore.getState().acceptOrder(orderId, actor)
}
export function acceptOrderAsActor(orderId: string, actor: Actor) {
return useOrderStore.getState().acceptOrder(orderId, actor)
}
export function requestClose(orderId: string) {
const { actor, decision } = resolveActorContext()
if (!actor) return { decision }
return useOrderStore.getState().requestClose(orderId, actor)
}
export function confirmClose(orderId: string) {
const { actor, decision } = resolveActorContext()
if (!actor) return { decision }
return useOrderStore.getState().confirmClose(orderId, actor)
}
export function cancelPreAccept(orderId: string) {
const { actor, decision } = resolveActorContext()
if (!actor) return { decision }
return useOrderStore.getState().cancelPreAccept(orderId, actor)
}
export function markDisputed(orderId: string) {
const { actor, decision } = resolveActorContext()
if (!actor) return { decision }
return useOrderStore.getState().markDisputed(orderId, actor)
}
+16
View File
@@ -1,3 +1,5 @@
import { deny } from "@/lib/policy/assert"
import { useAuthStore } from "@/store/auth"
import { useReviewStore } from "@/store/reviews"
export function listReviews() {
@@ -11,3 +13,17 @@ export function listReviewsByOrder(orderId: string) {
export function listReviewsByTargetUser(userId: string) {
return useReviewStore.getState().reviews.filter((review) => review.toUserId === userId)
}
export function submitReview(input: { orderId: string; rating: number; content?: string }) {
const userId = useAuthStore.getState().user?.id
if (!userId) {
return deny("AUTH_REQUIRED", "请先登录")
}
return useReviewStore.getState().submitReview({
orderId: input.orderId,
fromUserId: userId,
rating: input.rating,
content: input.content,
})
}