"use client" import { useEffect, useMemo, useState } from "react" import { MessageSquarePlusIcon } from "lucide-react" import { toast } from "sonner" import { OptionCombobox } from "@/components/option-combobox" import { Button } from "@/components/ui/button" import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle, } from "@/components/ui/dialog" import { Textarea } from "@/components/ui/textarea" import { fetchAgentProfilesAll, type AdminAgentProfile } from "@/lib/api/admin" import { addTicketInternalNote, replyTicket } from "@/lib/api/ticket" type TicketReplyDialogProps = { open: boolean ticketId: number | null onOpenChange: (open: boolean) => void onSuccess?: () => Promise | void } export function TicketReplyDialog({ open, ticketId, onOpenChange, onSuccess, }: TicketReplyDialogProps) { const [replyMode, setReplyMode] = useState<"public" | "internal">("public") const [replyContent, setReplyContent] = useState("") const [mentionUserId, setMentionUserId] = useState("") const [mentionedUsers, setMentionedUsers] = useState([]) const [agents, setAgents] = useState([]) const [loadingAgents, setLoadingAgents] = useState(false) const [submitting, setSubmitting] = useState(false) useEffect(() => { if (!open) { return } setReplyMode("public") setReplyContent("") setMentionUserId("") setMentionedUsers([]) }, [open]) useEffect(() => { if (!open) { return } setLoadingAgents(true) fetchAgentProfilesAll() .then((data) => { setAgents(Array.isArray(data) ? data : []) }) .catch((error) => { toast.error(error instanceof Error ? error.message : "加载客服列表失败") }) .finally(() => { setLoadingAgents(false) }) }, [open]) const mentionOptions = useMemo( () => agents.map((agent) => ({ value: String(agent.userId), label: agent.displayName || agent.nickname || agent.username || `客服 #${agent.userId}`, })), [agents], ) function handleAddMentionUser() { const userId = Number(mentionUserId) if (!userId) { return } const user = agents.find((item) => item.userId === userId) if (!user) { return } setMentionedUsers((current) => { if (current.some((item) => item.userId === user.userId)) { return current } return [...current, user] }) setMentionUserId("") } async function handleSubmit() { if (!ticketId) { toast.error("工单不存在") return } if (!replyContent.trim()) { toast.error(replyMode === "public" ? "回复内容不能为空" : "备注内容不能为空") return } setSubmitting(true) try { if (replyMode === "public") { await replyTicket({ ticketId, contentType: "text", content: replyContent.trim(), }) toast.success("已回复客户") } else { const payload = mentionedUsers.length > 0 ? JSON.stringify({ mentionUserIds: mentionedUsers.map((item) => item.userId), }) : undefined await addTicketInternalNote({ ticketId, contentType: "text", content: replyContent.trim(), payload, }) toast.success("已添加内部备注") } onOpenChange(false) await onSuccess?.() } catch (error) { toast.error(error instanceof Error ? error.message : "提交失败") } finally { setSubmitting(false) } } return ( 回复与备注