50 lines
3.5 KiB
TypeScript
50 lines
3.5 KiB
TypeScript
"use client";
|
||
|
||
import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog";
|
||
import type { PromptToolMode } from "@/lib/video-canvas/prompt-tools";
|
||
|
||
export function VideoPromptToolDialog({ mode, busy, error, output, source, currentPrompt, model, models, onModelChange, onOutputChange, onRun, onApply, onClose }: {
|
||
mode: PromptToolMode;
|
||
busy: boolean;
|
||
error: string;
|
||
output: string;
|
||
source: string;
|
||
currentPrompt: string;
|
||
model: string;
|
||
models: { id: string; label: string }[];
|
||
onModelChange: (value: string) => void;
|
||
onOutputChange: (value: string) => void;
|
||
onRun: () => void;
|
||
onApply: () => void;
|
||
onClose: () => void;
|
||
}) {
|
||
const title = mode === "optimize" ? "提示词优化" : "提示词翻译";
|
||
return (
|
||
<Dialog open onOpenChange={open => { if (!open) onClose(); }}>
|
||
<DialogContent hideCloseButton aria-describedby={undefined} onPointerDown={event => event.stopPropagation()} className="flex max-h-[90dvh] w-[620px] max-w-full flex-col gap-4 overflow-y-auto rounded-2xl border border-white/10 bg-[#262626] p-5 text-white shadow-2xl">
|
||
<div className="flex items-center justify-between">
|
||
<DialogTitle className="text-base font-medium">{title}</DialogTitle>
|
||
<button aria-label="关闭提示词工具" className="rounded px-2 py-1 text-white/60 hover:bg-white/10" onClick={onClose} type="button">✕</button>
|
||
</div>
|
||
<label className="flex items-center gap-3 text-sm text-white/65">
|
||
处理模型
|
||
<select aria-label="提示词处理模型" className="min-w-0 flex-1 rounded-lg border border-white/15 bg-[#202020] px-3 py-2" disabled={busy} onChange={event => onModelChange(event.target.value)} value={model}>
|
||
<option value="auto">使用管理员默认模型</option>
|
||
{model !== "auto" && !models.some(item => item.id === model) ? <option value={model}>当前配置模型(暂不可选)</option> : null}
|
||
{models.map(item => <option key={item.id} value={item.id}>{item.label}</option>)}
|
||
</select>
|
||
</label>
|
||
<details className="text-sm text-white/55"><summary className="cursor-pointer">查看原提示词</summary><p className="mt-2 whitespace-pre-wrap">{source}</p></details>
|
||
{error ? <p role="alert" className="rounded-lg bg-red-400/10 p-3 text-sm text-red-200">{error}</p> : null}
|
||
<textarea aria-label={`${title}结果`} className="min-h-[220px] w-full resize-y rounded-xl border border-white/10 bg-black/20 p-3 text-sm leading-6 outline-none focus:border-white/30" disabled={busy} onChange={event => onOutputChange(event.target.value)} placeholder={busy ? "正在处理,请稍候…" : "处理结果会显示在这里,确认后填入视频节点。"} value={output} />
|
||
{source !== currentPrompt ? <p className="text-xs text-amber-200">原文已修改,应用结果将替换当前提示词。</p> : null}
|
||
<div className="flex items-center justify-end gap-2">
|
||
<button className="rounded-lg px-3 py-2 text-sm text-white/65 hover:bg-white/10" onClick={onClose} type="button">{busy ? "取消处理" : "取消"}</button>
|
||
<button className="rounded-lg border border-white/15 px-3 py-2 text-sm disabled:opacity-40" disabled={busy} onClick={onRun} type="button">{busy ? "处理中…" : output ? "重新生成" : "重试"}</button>
|
||
<button className="rounded-lg bg-white px-4 py-2 text-sm text-black disabled:opacity-40" disabled={busy || !output.trim() || Boolean(error)} onClick={onApply} type="button">应用到提示词</button>
|
||
</div>
|
||
</DialogContent>
|
||
</Dialog>
|
||
);
|
||
}
|