feat: 首次推送到Gitea - 完整项目代码 + 安全加固 + 知识库

This commit is contained in:
ZhuiGuangAI Dev
2026-10-02 18:52:49 +08:00
parent b44601bb66
commit 8205ae709c
1185 changed files with 49841 additions and 12802 deletions
+60 -2
View File
@@ -10,6 +10,8 @@ import {
DialogFooter,
} from "@/components/ui/dialog";
import { LazyImage } from "@/components/ui/LazyImage";
interface Tool {
id: number;
name: string;
@@ -137,6 +139,19 @@ export default function ToolsAdminPage() {
const [isNew, setIsNew] = useState(false);
const [form, setForm] = useState(emptyForm);
const [saving, setSaving] = useState(false);
const [verifiedToolIds, setVerifiedToolIds] = useState<Set<number>>(new Set());
const fetchVerifiedTools = useCallback(async () => {
try {
const res = await fetch("/api/admin/tools/verify");
const data = await res.json();
if (data.verifiedTools) {
const ids = new Set<number>();
(data.verifiedTools as { toolId: number }[]).forEach((v) => ids.add(v.toolId));
setVerifiedToolIds(ids);
}
} catch { /* ignore */ }
}, []);
const fetchTools = useCallback(async () => {
setError("");
@@ -173,7 +188,8 @@ export default function ToolsAdminPage() {
useEffect(() => {
fetchTools();
fetchCategories();
}, [fetchTools, fetchCategories]);
fetchVerifiedTools();
}, [fetchTools, fetchCategories, fetchVerifiedTools]);
const openEdit = (tool: Tool) => {
setIsNew(false);
@@ -247,6 +263,30 @@ export default function ToolsAdminPage() {
}
};
const handleVerifyToggle = async (toolId: number) => {
try {
const res = await fetch("/api/admin/tools/verify", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ toolId }),
});
const data = await res.json();
if (data.success) {
setVerifiedToolIds((prev) => {
const next = new Set(prev);
if (data.verified) {
next.add(toolId);
} else {
next.delete(toolId);
}
return next;
});
}
} catch {
console.error("Verify toggle failed");
}
};
const publishedCount = tools.filter((t) => t.status === "published").length;
const draftCount = tools.filter((t) => t.status === "draft").length;
const totalViews = tools.reduce((sum, t) => sum + t.viewCount, 0);
@@ -403,10 +443,12 @@ export default function ToolsAdminPage() {
<td className="px-5 py-3.5">
<div className="flex items-center gap-3">
{tool.logoUrl ? (
<img
<LazyImage
src={tool.logoUrl}
referrerPolicy="no-referrer"
alt=""
width={48}
height={48}
className="h-9 w-9 rounded-lg border border-border/50 bg-white object-contain p-0.5"
/>
) : (
@@ -441,6 +483,22 @@ export default function ToolsAdminPage() {
</td>
<td className="px-5 py-3.5">
<div className="flex justify-end gap-2">
<Button
size="sm"
variant="outline"
onClick={() => handleVerifyToggle(tool.id)}
className={`gap-1.5 rounded-lg text-xs ${
verifiedToolIds.has(tool.id)
? "border-blue-300/60 bg-blue-50 text-blue-600 hover:bg-blue-100"
: "border-border/50"
}`}
title={verifiedToolIds.has(tool.id) ? "取消验证" : "标记为已验证"}
>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M5 13l4 4L19 7" />
</svg>
{verifiedToolIds.has(tool.id) ? "已验证" : "验证"}
</Button>
<Button
size="sm"
variant="outline"