519fb92c34
Turn on react-hooks/set-state-in-effect and react-hooks/incompatible-library, then remove effect-driven local state sync patterns across affected pages. Keep behavior stable by deriving values from source state, remounting tab state by role key, and replacing useForm watch with useWatch.
209 lines
5.7 KiB
TypeScript
209 lines
5.7 KiB
TypeScript
"use client"
|
|
|
|
import {
|
|
AlertTriangle,
|
|
CheckCircle2,
|
|
Clock,
|
|
MessageSquare,
|
|
RefreshCw,
|
|
Star,
|
|
XCircle,
|
|
} from "lucide-react"
|
|
import Link from "next/link"
|
|
import { useEffect } from "react"
|
|
import { Button } from "@/components/ui/button"
|
|
import { notifySuccess } from "@/lib/toast"
|
|
import type { OrderStatus } from "@/lib/types"
|
|
import { useChatStore } from "@/store/chat"
|
|
import { useOrderStore } from "@/store/orders"
|
|
import { useShopStore } from "@/store/shops"
|
|
|
|
interface OrderActionsProps {
|
|
orderId: string
|
|
initialStatus: OrderStatus
|
|
chatSessionId?: string
|
|
serviceId: string
|
|
}
|
|
|
|
function showFeedback(message: string) {
|
|
notifySuccess(message)
|
|
}
|
|
|
|
export default function OrderActions({
|
|
orderId,
|
|
initialStatus,
|
|
chatSessionId,
|
|
serviceId,
|
|
}: OrderActionsProps) {
|
|
const order = useOrderStore((state) => state.orders.find((item) => item.id === orderId))
|
|
const updateOrderStatus = useOrderStore((state) => state.updateOrderStatus)
|
|
const sessions = useChatStore((state) => state.sessions)
|
|
const ensureOrderSession = useChatStore((state) => state.ensureOrderSession)
|
|
const dispatchMode = useShopStore((state) => {
|
|
if (!order?.shopId) return "manual"
|
|
const shop = state.shops.find((item) => item.id === order.shopId)
|
|
return shop?.dispatchMode ?? "manual"
|
|
})
|
|
const resolvedChatSessionId =
|
|
chatSessionId ??
|
|
sessions.find((session) => session.type === "order" && session.orderId === orderId)?.id
|
|
|
|
const status = order?.status ?? initialStatus
|
|
|
|
useEffect(() => {
|
|
if (chatSessionId || !order || resolvedChatSessionId) return
|
|
ensureOrderSession(order)
|
|
}, [chatSessionId, order, ensureOrderSession, resolvedChatSessionId])
|
|
|
|
useEffect(() => {
|
|
if (!order) return
|
|
if (order.status !== "pending_accept") return
|
|
if (!order.shopId) return
|
|
if (dispatchMode !== "auto") return
|
|
|
|
const timer = setTimeout(() => {
|
|
updateOrderStatus(orderId, "in_progress")
|
|
showFeedback("系统已自动派单")
|
|
}, 3000)
|
|
|
|
return () => clearTimeout(timer)
|
|
}, [dispatchMode, order, orderId, updateOrderStatus])
|
|
|
|
return (
|
|
<div className="flex gap-2 flex-wrap">
|
|
{status === "pending_payment" && (
|
|
<>
|
|
<Button
|
|
variant="outline"
|
|
onClick={() => {
|
|
updateOrderStatus(orderId, "cancelled")
|
|
showFeedback("订单已取消")
|
|
}}
|
|
>
|
|
<XCircle className="mr-1 h-4 w-4" />
|
|
取消订单
|
|
</Button>
|
|
<Button
|
|
onClick={() => {
|
|
updateOrderStatus(orderId, "pending_accept")
|
|
}}
|
|
>
|
|
<CheckCircle2 className="mr-1 h-4 w-4" />
|
|
确认支付
|
|
</Button>
|
|
</>
|
|
)}
|
|
|
|
{status === "pending_accept" && (
|
|
<>
|
|
<Button
|
|
variant="outline"
|
|
onClick={() => {
|
|
updateOrderStatus(orderId, "cancelled")
|
|
showFeedback("订单已取消")
|
|
}}
|
|
>
|
|
<XCircle className="mr-1 h-4 w-4" />
|
|
取消订单
|
|
</Button>
|
|
{order?.shopId && dispatchMode === "auto" ? (
|
|
<Button disabled>
|
|
<Clock className="mr-1 h-4 w-4" />
|
|
系统派单中
|
|
</Button>
|
|
) : (
|
|
<Button
|
|
onClick={() => {
|
|
updateOrderStatus(orderId, "in_progress")
|
|
showFeedback("已接单")
|
|
}}
|
|
>
|
|
<CheckCircle2 className="mr-1 h-4 w-4" />
|
|
接单
|
|
</Button>
|
|
)}
|
|
</>
|
|
)}
|
|
|
|
{(status === "in_progress" || status === "pending_close") && resolvedChatSessionId && (
|
|
<Button asChild>
|
|
<Link href={`/chat/${resolvedChatSessionId}`}>
|
|
<MessageSquare className="mr-1 h-4 w-4" />
|
|
聊天
|
|
</Link>
|
|
</Button>
|
|
)}
|
|
|
|
{status === "in_progress" && (
|
|
<>
|
|
<Button
|
|
onClick={() => {
|
|
updateOrderStatus(orderId, "pending_close")
|
|
showFeedback("已发起结单")
|
|
}}
|
|
>
|
|
发起结单
|
|
</Button>
|
|
<Button variant="destructive" asChild>
|
|
<Link href={`/dispute/${orderId}`}>
|
|
<AlertTriangle className="mr-1 h-4 w-4" />
|
|
发起争议
|
|
</Link>
|
|
</Button>
|
|
</>
|
|
)}
|
|
|
|
{status === "pending_close" && (
|
|
<>
|
|
<Button
|
|
onClick={() => {
|
|
updateOrderStatus(orderId, "pending_review")
|
|
}}
|
|
>
|
|
确认结单
|
|
</Button>
|
|
<Button variant="destructive" asChild>
|
|
<Link href={`/dispute/${orderId}`}>
|
|
<AlertTriangle className="mr-1 h-4 w-4" />
|
|
发起争议
|
|
</Link>
|
|
</Button>
|
|
</>
|
|
)}
|
|
|
|
{status === "pending_review" && (
|
|
<Button asChild>
|
|
<Link href={`/review/${orderId}`}>
|
|
<Star className="mr-1 h-4 w-4" />
|
|
评价
|
|
</Link>
|
|
</Button>
|
|
)}
|
|
|
|
{status === "completed" && (
|
|
<Button variant="outline" asChild>
|
|
<Link href={`/order/new?serviceId=${serviceId}`}>
|
|
<RefreshCw className="mr-1 h-4 w-4" />
|
|
再来一单
|
|
</Link>
|
|
</Button>
|
|
)}
|
|
|
|
{status === "cancelled" && (
|
|
<Button variant="outline" asChild>
|
|
<Link href={`/order/new?serviceId=${serviceId}`}>
|
|
<RefreshCw className="mr-1 h-4 w-4" />
|
|
再来一单
|
|
</Link>
|
|
</Button>
|
|
)}
|
|
|
|
{status === "disputed" && (
|
|
<Button variant="outline" asChild>
|
|
<Link href={`/dispute/${orderId}`}>查看详情</Link>
|
|
</Button>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|