158 lines
4.7 KiB
TypeScript
158 lines
4.7 KiB
TypeScript
"use client";
|
|
|
|
import { SparklesIcon } from "lucide-react";
|
|
import { useEffect, useState } from "react";
|
|
|
|
import { Button } from "@/components/ui/button";
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogDescription,
|
|
DialogFooter,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
} from "@/components/ui/dialog";
|
|
import {
|
|
Select,
|
|
SelectContent,
|
|
SelectItem,
|
|
SelectTrigger,
|
|
SelectValue,
|
|
} from "@/components/ui/select";
|
|
import { Textarea } from "@/components/ui/textarea";
|
|
import { ModelNameSelect } from "@/components/workspace/model-name-select";
|
|
import type { DocumentRewriteStyle } from "@/open-canvas/api/rewrite";
|
|
|
|
const STYLE_OPTIONS: { value: DocumentRewriteStyle; label: string; description: string }[] = [
|
|
{
|
|
value: "formal_analysis",
|
|
label: "正式分析",
|
|
description: "客观、严谨,适合报告与研究材料。",
|
|
},
|
|
{
|
|
value: "professional",
|
|
label: "专业正式",
|
|
description: "适合业务文档和说明材料。",
|
|
},
|
|
{
|
|
value: "concise",
|
|
label: "精炼简洁",
|
|
description: "减少重复,保留核心信息。",
|
|
},
|
|
{
|
|
value: "readable",
|
|
label: "清晰易读",
|
|
description: "优化段落衔接和阅读节奏。",
|
|
},
|
|
];
|
|
|
|
export function DocumentRewriteDialog({
|
|
open,
|
|
onOpenChange,
|
|
fileName,
|
|
charCount,
|
|
onStart,
|
|
}: {
|
|
open: boolean;
|
|
onOpenChange: (open: boolean) => void;
|
|
fileName: string;
|
|
charCount: number;
|
|
onStart: (input: {
|
|
instruction: string;
|
|
style: DocumentRewriteStyle;
|
|
modelName: string | null;
|
|
}) => void;
|
|
}) {
|
|
const [instruction, setInstruction] = useState(
|
|
"统一表达风格,减少重复内容,改善段落衔接;不新增原文没有依据的事实。",
|
|
);
|
|
const [style, setStyle] = useState<DocumentRewriteStyle>("formal_analysis");
|
|
const [modelName, setModelName] = useState<string | null>(null);
|
|
|
|
useEffect(() => {
|
|
if (!open) return;
|
|
setStyle("formal_analysis");
|
|
setModelName(null);
|
|
}, [open]);
|
|
|
|
const selectedStyle = STYLE_OPTIONS.find((item) => item.value === style);
|
|
const canStart = instruction.trim().length > 0;
|
|
|
|
return (
|
|
<Dialog open={open} onOpenChange={onOpenChange}>
|
|
<DialogContent className="sm:max-w-xl">
|
|
<DialogHeader>
|
|
<DialogTitle className="flex items-center gap-2">
|
|
<SparklesIcon className="size-5 text-primary" />
|
|
AI 全文改写
|
|
</DialogTitle>
|
|
<DialogDescription>
|
|
将以当前文件快照生成临时草稿。校验通过前不会覆盖原 Markdown。
|
|
</DialogDescription>
|
|
</DialogHeader>
|
|
|
|
<div className="rounded-lg border bg-muted/35 px-3 py-2.5 text-sm">
|
|
<div className="font-medium">{fileName}</div>
|
|
<div className="text-muted-foreground mt-1">原文约 {charCount.toLocaleString()} 字</div>
|
|
</div>
|
|
|
|
<label className="grid gap-2 text-sm font-medium">
|
|
改写要求
|
|
<Textarea
|
|
value={instruction}
|
|
onChange={(event) => setInstruction(event.target.value)}
|
|
placeholder="例如:统一为正式行业分析语气,减少重复,不新增外部事实。"
|
|
rows={4}
|
|
/>
|
|
</label>
|
|
|
|
<div className="grid gap-4 sm:grid-cols-2">
|
|
<label className="grid gap-2 text-sm font-medium">
|
|
改写风格
|
|
<Select value={style} onValueChange={(value) => setStyle(value as DocumentRewriteStyle)}>
|
|
<SelectTrigger>
|
|
<SelectValue />
|
|
</SelectTrigger>
|
|
<SelectContent>
|
|
{STYLE_OPTIONS.map((item) => (
|
|
<SelectItem key={item.value} value={item.value}>
|
|
{item.label}
|
|
</SelectItem>
|
|
))}
|
|
</SelectContent>
|
|
</Select>
|
|
<span className="text-muted-foreground text-xs">{selectedStyle?.description}</span>
|
|
</label>
|
|
|
|
<label className="grid gap-2 text-sm font-medium">
|
|
模型
|
|
<ModelNameSelect
|
|
value={modelName}
|
|
onChange={setModelName}
|
|
triggerClassName="h-10 text-sm"
|
|
defaultLabel="系统默认模型"
|
|
/>
|
|
<span className="text-muted-foreground text-xs">仅影响本次全文改写。</span>
|
|
</label>
|
|
</div>
|
|
|
|
<DialogFooter>
|
|
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
|
取消
|
|
</Button>
|
|
<Button
|
|
disabled={!canStart}
|
|
onClick={() => {
|
|
if (!canStart) return;
|
|
onStart({ instruction: instruction.trim(), style, modelName });
|
|
}}
|
|
>
|
|
<SparklesIcon />
|
|
开始改写
|
|
</Button>
|
|
</DialogFooter>
|
|
</DialogContent>
|
|
</Dialog>
|
|
);
|
|
}
|