diff --git a/src/components/biz/ai-translate-modal.tsx b/src/components/biz/ai-translate-modal.tsx index bf2b389..8dd2f06 100644 --- a/src/components/biz/ai-translate-modal.tsx +++ b/src/components/biz/ai-translate-modal.tsx @@ -15,10 +15,11 @@ type Props = { onOpenChange: (next: boolean) => void; languages: string[]; path: string; + prompt: string | undefined; onConfirm: (result: Record) => Promise | void; }; -function AiTranslateModalImpl({ open, onOpenChange, languages, path, onConfirm }: Props) { +function AiTranslateModalImpl({ open, onOpenChange, languages, path, prompt, onConfirm }: Props) { const [text, setText] = useState(""); const [loading, setLoading] = useState(false); const [error, setError] = useState(null); @@ -37,7 +38,7 @@ function AiTranslateModalImpl({ open, onOpenChange, languages, path, onConfirm } setLoading(true); setError(null); try { - const result = await requestTranslations({ text: payload, languages }); + const result = await requestTranslations({ text: payload, languages, prompt }); // 二次校验 keys 完整性 for (const l of languages) { if (!Object.prototype.hasOwnProperty.call(result, l)) { diff --git a/src/components/biz/project-settings-modal.tsx b/src/components/biz/project-settings-modal.tsx new file mode 100644 index 0000000..01e684e --- /dev/null +++ b/src/components/biz/project-settings-modal.tsx @@ -0,0 +1,95 @@ +import { memo, useEffect, useState } from "react"; +import { Button } from "@/components/ui/button"; +import { Input } from "@/components/ui/input"; +import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "@/components/ui/dialog"; +import type { Project } from "@/lib/db"; + +type Props = { + open: boolean; + onOpenChange: (v: boolean) => void; + project: Project | null; + onSave: (update: { name: string; preferences: { aiPrompt?: string } }) => Promise | void; + onDelete: () => Promise | void; +}; + +function ProjectSettingsModalImpl({ open, onOpenChange, project, onSave, onDelete }: Props) { + const [name, setName] = useState(""); + const [aiPrompt, setAiPrompt] = useState(""); + const [saving, setSaving] = useState(false); + const [err, setErr] = useState(null); + + useEffect(() => { + if (open) { + setName(project?.name ?? ""); + setAiPrompt(project?.preferences?.aiPrompt ?? ""); + setSaving(false); + setErr(null); + } + }, [open, project]); + + async function handleSubmit(e: React.FormEvent) { + e.preventDefault(); + const trimmed = name.trim(); + if (!trimmed) return setErr("项目名称不能为空"); + setSaving(true); + try { + await onSave({ + name: trimmed, + preferences: { aiPrompt }, + }); + onOpenChange(false); + } catch (e) { + setErr((e as Error)?.message ?? "保存失败"); + } finally { + setSaving(false); + } + } + + async function handleDelete() { + if (!confirm("确认删除整个项目?该操作不可恢复!")) return; + setSaving(true); + try { + await onDelete(); + onOpenChange(false); + } catch (e) { + setErr((e as Error)?.message ?? "删除失败"); + } finally { + setSaving(false); + } + } + + return ( + { if (!saving) onOpenChange(v); }}> + + + 项目设置 + +
+
+ + setName(e.target.value)} placeholder="输入项目名称" /> +
+
+ +