"use client"; import { useEffect, useRef, useState } from "react"; import { Check, MessageSquarePlus, RotateCcw, X } from "lucide-react"; import { ThinkingIndicator } from "@/components/ThinkingIndicator"; import { Button } from "@/components/ui/Button"; import { SectionHeader } from "@/components/ui/SectionHeader"; import { StatusNote } from "@/components/ui/StatusNote"; import { TextArea } from "@/components/ui/TextArea"; import { useRefine } from "@/lib/workbench/useRefine"; interface RefinePanelProps { projectId: string; chapterNo: number; // 选中原文;打开即对其回炉一次。 original: string; // 接受回填:把选段替换为该产出(调用方按内容重锚落回草稿)。 onAccept: (refined: string) => void; onClose: () => void; } // 润色 / 再沟通结果卡(内联,非模态):打开即润色选段;作者可「再沟通」追加意见迭代出新版, // 择版接受回填正文,或放弃。原文只读、生成不写库(不变量 #3),accept 才动草稿。 export function RefinePanel({ projectId, chapterNo, original, onAccept, onClose, }: RefinePanelProps) { const { status, versions, latest, refine, recommunicate } = useRefine(); const [instruction, setInstruction] = useState(""); const ranRef = useRef(false); // 打开即对选段回炉一次(仅一次,避免重复请求)。 useEffect(() => { if (ranRef.current) return; ranRef.current = true; void refine(projectId, chapterNo, original); }, [projectId, chapterNo, original, refine]); const busy = status === "refining"; const onRecommunicate = (): void => { const trimmed = instruction.trim(); if (!trimmed || busy) return; setInstruction(""); void recommunicate(projectId, chapterNo, trimmed); }; return (
{original}
{latest.refined}
) : status === "error" ? (