diff --git a/app/(order)/review/[id]/page.tsx b/app/(order)/review/[id]/page.tsx index 1e4db0c..f2f53f0 100644 --- a/app/(order)/review/[id]/page.tsx +++ b/app/(order)/review/[id]/page.tsx @@ -7,6 +7,7 @@ import { Button } from "@/components/ui/button" import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card" import { Label } from "@/components/ui/label" import { Textarea } from "@/components/ui/textarea" +import { notifyInfo, notifySuccess } from "@/lib/toast" import { useAuthStore } from "@/store/auth" import { useOrderStore } from "@/store/orders" import { useReviewStore } from "@/store/reviews" @@ -37,6 +38,18 @@ export default function ReviewPage({ params }: { params: Promise<{ id: string }> const hasSubmitted = Boolean(userId && reviews.some((review) => review.fromUserId === userId)) const isRevealed = reviews.length >= 2 && reviews.every((review) => !review.sealed) + if (order.status !== "pending_review") { + return ( +
+

当前阶段不可评价

+

仅待评价状态的订单可以提交评价。

+ + 返回订单详情 + +
+ ) + } + if (hasSubmitted && !isRevealed) { return (
@@ -126,12 +139,19 @@ export default function ReviewPage({ params }: { params: Promise<{ id: string }> disabled={rating === 0 || !userId} onClick={() => { if (!userId) return - submitReview({ + const decision = submitReview({ orderId: id, fromUserId: userId, rating, content, }) + + if (decision.ok) { + notifySuccess("评价已提交") + return + } + + notifyInfo(decision.message ?? "评价提交失败") }} > 提交评价 diff --git a/store/reviews.ts b/store/reviews.ts index c189df1..64aedd0 100644 --- a/store/reviews.ts +++ b/store/reviews.ts @@ -1,5 +1,7 @@ import { create } from "zustand" import { generateId } from "@/lib/id" +import { allow, deny } from "@/lib/policy/assert" +import type { PolicyDecision } from "@/lib/policy/decision" import { mockReviews, mockUsers } from "@/lib/mock" import type { Review } from "@/lib/types" import { useOrderStore } from "@/store/orders" @@ -13,13 +15,11 @@ interface SubmitReviewInput { interface ReviewState { reviews: Review[] - submitReview: (input: SubmitReviewInput) => void + submitReview: (input: SubmitReviewInput) => PolicyDecision getReviewsByOrder: (orderId: string) => Review[] hasUserReviewed: (orderId: string, userId: string) => boolean } -const autoReplyTimers = new Map>() - function resolveUser(userId: string) { return mockUsers.find((user) => user.id === userId) } @@ -53,11 +53,32 @@ export const useReviewStore = create((set, get) => ({ hasUserReviewed: (orderId, userId) => get().reviews.some((review) => review.orderId === orderId && review.fromUserId === userId), submitReview: (input) => { + if (!input.fromUserId) { + return deny("AUTH_REQUIRED", "请先登录") + } + + if (!Number.isFinite(input.rating) || input.rating < 1 || input.rating > 5) { + return deny("VALIDATION_FAILED", "评分范围应为 1-5") + } + + const order = useOrderStore.getState().orders.find((item) => item.id === input.orderId) + if (!order) { + return deny("NOT_FOUND", "订单不存在") + } + + if (order.status !== "pending_review") { + return deny("INVALID_STATUS", "仅待评价订单可提交评价") + } + const relation = resolveOrderUser(input.orderId, input.fromUserId) - if (!relation) return + if (!relation) { + return deny("NOT_PARTICIPANT", "仅订单参与方可评价") + } const exists = get().hasUserReviewed(input.orderId, input.fromUserId) - if (exists) return + if (exists) { + return deny("ALREADY_DONE", "该订单已提交过评价") + } const fromUser = resolveUser(input.fromUserId) const createdAt = new Date().toISOString() @@ -79,37 +100,13 @@ export const useReviewStore = create((set, get) => ({ const orderReviews = get().getReviewsByOrder(input.orderId) if (orderReviews.length >= 2) { - const timer = autoReplyTimers.get(input.orderId) - if (timer) { - clearTimeout(timer) - autoReplyTimers.delete(input.orderId) - } - set((state) => ({ reviews: state.reviews.map((item) => item.orderId === input.orderId ? { ...item, sealed: false } : item, ), })) - useOrderStore.getState().updateOrderStatus(input.orderId, "completed") - return } - if (autoReplyTimers.has(input.orderId)) return - - const timer = setTimeout(() => { - autoReplyTimers.delete(input.orderId) - if (get().hasUserReviewed(input.orderId, relation.toUserId)) { - return - } - - get().submitReview({ - orderId: input.orderId, - fromUserId: relation.toUserId, - rating: 5, - content: `收到 ${relation.toUserName} 的评价,感谢本次对局。`, - }) - }, 3000) - - autoReplyTimers.set(input.orderId, timer) + return allow() }, }))