更新安全配置项目

This commit is contained in:
2026-04-13 22:10:43 +08:00
parent 8e245076fe
commit 70d3020035
8 changed files with 43 additions and 284 deletions
-152
View File
@@ -1,152 +0,0 @@
"use client";
import {useState, useEffect} from "react";
import {useToast} from "@/components/ui/toast";
import {Loader2} from "lucide-react";
import {Button} from "@/components/ui/button";
interface DBConfig {
host: string;
port: number;
user: string;
password: string;
database: string;
}
const defaultDBConfig: DBConfig = {
host: "127.0.0.1",
port: 3306,
user: "root",
password: "",
database: "recipe_tools",
};
export default function DatabasePage() {
const [config, setConfig] = useState<DBConfig>(defaultDBConfig);
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
const {addToast} = useToast();
useEffect(() => {
fetch("/api/config")
.then((res) => res.json())
.then((result) => {
if (result.success && result.data) {
setConfig({
host: result.data.db?.host || defaultDBConfig.host,
port: result.data.db?.port || defaultDBConfig.port,
user: result.data.db?.user || defaultDBConfig.user,
password: result.data.db?.password || defaultDBConfig.password,
database: result.data.db?.database || defaultDBConfig.database,
});
}
})
.catch(console.error)
.finally(() => setLoading(false));
}, []);
const handleSave = async () => {
setSaving(true);
try {
const response = await fetch("/api/config", {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({db: config}),
});
const result = await response.json();
if (result.success) {
addToast({type: "success", title: "数据库配置已保存"});
} else {
addToast({type: "error", title: "保存失败", description: result.error});
}
} catch {
addToast({type: "error", title: "保存失败"});
} finally {
setSaving(false);
}
};
if (loading) {
return (
<div className="space-y-6">
<div>
<h2 className="text-lg font-semibold"></h2>
<p className="text-sm text-muted-foreground"> MySQL </p>
</div>
<div className="h-40 animate-pulse rounded-lg bg-muted"/>
</div>
);
}
return (
<div className="space-y-6">
<div className={"flex items-center justify-between"}>
<div>
<h2 className="text-lg font-semibold"></h2>
<p className="text-sm text-muted-foreground"> MySQL </p>
</div>
<div className="flex gap-3">
<Button onClick={handleSave} disabled={saving}>
{saving && <Loader2 className="mr-2 h-4 w-4 animate-spin"/>}
{saving ? "保存中..." : "保存配置"}
</Button>
</div>
</div>
<div className="grid gap-4 md:grid-cols-2">
<div className="space-y-2">
<label className="text-sm font-medium"></label>
<input
type="text"
value={config.host}
onChange={(e) => setConfig({...config, host: e.target.value})}
className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
placeholder="127.0.0.1"
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium"></label>
<input
type="text"
value={config.port}
onChange={(e) => setConfig({...config, port: parseInt(e.target.value) || 3306})}
className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
placeholder="3306"
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium"></label>
<input
type="text"
value={config.user}
onChange={(e) => setConfig({...config, user: e.target.value})}
className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
placeholder="root"
/>
</div>
<div className="space-y-2">
<label className="text-sm font-medium"></label>
<input
type="password"
value={config.password}
onChange={(e) => setConfig({...config, password: e.target.value})}
className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
placeholder="******"
/>
</div>
<div className="space-y-2 md:col-span-2">
<label className="text-sm font-medium"></label>
<input
type="text"
value={config.database}
onChange={(e) => setConfig({...config, database: e.target.value})}
className="w-full rounded-md border border-input bg-background px-3 py-2 text-sm"
placeholder="recipe_tools"
/>
</div>
</div>
</div>
);
}
+3 -15
View File
@@ -1,23 +1,11 @@
"use client";
import Link from "next/link";
import { usePathname } from "next/navigation";
import {
Database,
Globe,
FileText,
ChevronRight,
UtensilsCrossed,
Bandage
} from "lucide-react";
import { Button } from "@/components/ui/button";
import {usePathname} from "next/navigation";
import {Bandage, ChevronRight, FileText, Globe, UtensilsCrossed} from "lucide-react";
import {Button} from "@/components/ui/button";
const settingsMenu = [
{
title: "数据库配置",
icon: Database,
href: "/settings/database",
},
{
title: "翻译词库",
icon: Globe,
+2 -2
View File
@@ -4,12 +4,12 @@ import {useEffect} from "react";
import {useRouter} from "next/navigation";
import {Loader2} from "lucide-react";
// 主设置页面 - 重定向到数据库设置
// 主设置页面 - 重定向到库设置
export default function SettingsPage() {
const router = useRouter();
useEffect(() => {
router.replace("/settings/database");
router.replace("/settings/translation");
}, [router]);
return (