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()
},
}))