diff --git a/package-lock.json b/package-lock.json
index 8d90bca..45dabcd 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,7 @@
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
+ "@types/pg": "^8.20.0",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
@@ -1629,6 +1630,18 @@
"undici-types": "~6.21.0"
}
},
+ "node_modules/@types/pg": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.20.0.tgz",
+ "integrity": "sha512-bEPFOaMAHTEP1EzpvHTbmwR8UsFyHSKsRisLIHVMXnpNefSbGA1bD6CVy+qKjGSqmZqNqBDV2azOBo8TgkcVow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "pg-protocol": "*",
+ "pg-types": "^2.2.0"
+ }
+ },
"node_modules/@types/react": {
"version": "19.2.14",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz",
diff --git a/package.json b/package.json
index 1e0740f..5480aa2 100644
--- a/package.json
+++ b/package.json
@@ -18,6 +18,7 @@
"devDependencies": {
"@tailwindcss/postcss": "^4",
"@types/node": "^20",
+ "@types/pg": "^8.20.0",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^9",
diff --git a/src/app/page.tsx b/src/app/page.tsx
index be8a5ca..5f971da 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -507,331 +507,12 @@ function HomeInner() {
);
}
- const [activeSection, setActiveSection] = useState("");
- const [sidebarOpen, setSidebarOpen] = useState(false);
- const [searchQuery, setSearchQuery] = useState("");
- const [copied, setCopied] = useState(false);
- const currentDoc = documentation.find((doc) => doc.slug === activeDoc);
- const sections = currentDoc?.sections || [];
-
- const handleCopy = () => {
- navigator.clipboard.writeText("npm install docs-site");
- setCopied(true);
- setTimeout(() => setCopied(false), 2000);
- };
-
- const handleNavClick = (id: string) => {
- setActiveSection(id);
- setSidebarOpen(false);
- const element = document.getElementById(id);
- element?.scrollIntoView({ behavior: "smooth", block: "start" });
- };
-
- const filteredDocs = documentation.filter(
- (doc) =>
- doc.title.includes(searchQuery) ||
- doc.description.includes(searchQuery)
- );
-
- return (
-
-
- {/* 移动端遮罩 */}
- {sidebarOpen && (
-
setSidebarOpen(false)}
- />
- )}
-
- {/* 左侧导航栏 */}
-
-
- {/* 主内容区 */}
-
- {/* 顶部导航栏 */}
-
-
-
-
-
{currentDoc?.title}
-
-
-
- {!authenticated && (
-
- 登录
-
- )}
- {/* 深色模式切换 */}
-
-
- {/* 复制链接 */}
-
-
-
-
-
- {/* 文档内容 */}
-
- {sections.map((section, index) => (
-
-
-
- {section.content && (
-
- {section.content}
-
- )}
-
- {section.features && (
-
- {(section.features as string[] | FeatureItem[]).map((feature, i) => {
- if (typeof feature === "string") {
- return (
-
- );
- }
- return (
-
- {feature.items && (
-
- {feature.items.map((item, j) => (
- -
- ✓
- {item}
-
- ))}
-
- )}
-
- );
- })}
-
- )}
-
- {section.code && (
-
- {section.code}
-
- )}
-
- {section.instructions && section.code && (
-
- {section.instructions}
-
- )}
-
- ))}
-
-
- {/* 便签 */}
-
-
-
-
- {/* 留言板 */}
-
-
-
-
- {/* 底部 */}
-
-
-
-
- );
+function Home() {
+ const [mounted, setMounted] = useState(false);
+ useEffect(() => setMounted(true), []);
+ if (!mounted) return
;
+ return
;
}
-export default HomeInner;
+export default Home;
diff --git a/src/app/page.tsx.backup b/src/app/page.tsx.backup
new file mode 100644
index 0000000..6821d6e
--- /dev/null
+++ b/src/app/page.tsx.backup
@@ -0,0 +1,517 @@
+"use client";
+
+import { useState, useEffect } from "react";
+import CodeBlock from "@/components/CodeBlock";
+import NotesList from "@/components/note/NotesList";
+import MessageBoard from "@/components/message/MessageBoard";
+import { useTheme } from "@/components/ThemeProvider";
+import { useAuth } from "@/components/AuthProvider";
+
+const documentation = [
+ {
+ title: "快速开始",
+ slug: "quick-start",
+ description: "了解如何开始使用我们的平台",
+ sections: [
+ {
+ title: "简介",
+ content: "欢迎使用我们的在线文档系统!这是一个现代、响应式、功能丰富的文档平台,专为技术文档设计。",
+ features: [
+ "响应式布局,支持移动端和桌面端",
+ "平滑滚动和锚点导航",
+ "代码高亮和复制功能",
+ "深色模式支持",
+ "内置搜索功能",
+ ],
+ },
+ {
+ title: "安装",
+ content: "开始之前,请确保你已经安装了以下工具:",
+ requirements: ["Node.js (v18 或更高版本)", "npm 或 yarn 包管理器"],
+ code: "npm install\ngit pull origin main",
+ instructions: "然后运行以下命令:\n\nnpm install\n\n然后:\n\nnpm run dev\n\n访问 http://localhost:3000 即可查看。",
+ },
+ {
+ title: "项目结构",
+ content: "项目采用以下目录结构:",
+ code: `docs-site/
+├── src/
+│ ├── app/
+│ │ ├── page.tsx # 主文档页面
+│ │ ├── layout.tsx # 根布局
+│ │ └── globals.css # 全局样式
+│ └── components/
+│ ├── Sidebar.tsx # 侧边栏组件
+│ ├── Navbar.tsx # 导航栏组件
+│ └── CodeBlock.tsx # 代码块组件
+├── public/
+└── package.json`,
+ },
+ ],
+ },
+ {
+ title: "核心功能",
+ slug: "features",
+ description: "探索平台的各项功能",
+ sections: [
+ {
+ title: "响应式布局",
+ content: "平台采用响应式设计,自动适配各种屏幕尺寸。",
+ features: [
+ {
+ title: "移动端",
+ items: ["侧边栏可折叠", "字体大小自动调整", "导航栏简化"],
+ },
+ {
+ title: "桌面端",
+ items: ["固定侧边栏", "更多内容展示", "优化排版"],
+ },
+ ],
+ },
+ {
+ title: "交互功能",
+ content: "平台提供丰富的交互功能:",
+ features: [
+ {
+ title: "代码复制",
+ description: "点击代码块右上角的复制按钮即可快速复制代码",
+ },
+ {
+ title: "平滑滚动",
+ description: "点击导航链接自动滚动到对应位置",
+ },
+ {
+ title: "深色模式",
+ description: "点击右上角切换按钮即可切换主题",
+ },
+ {
+ title: "锚点导航",
+ description: "每个章节都有独立的锚点链接",
+ },
+ ],
+ },
+ {
+ title: "搜索功能",
+ content: "内置搜索功能帮助你快速找到所需内容。",
+ code: "1. 点击右上角的搜索图标\n2. 输入关键词\n3. 查看搜索结果\n4. 点击结果跳转到对应章节",
+ instructions: "搜索支持标题、描述和代码片段。",
+ },
+ ],
+ },
+ {
+ title: "API 参考",
+ slug: "api-reference",
+ description: "API 接口文档",
+ sections: [
+ {
+ title: "获取文档列表",
+ content: "获取所有可用文档的列表。",
+ code: `// GET /api/docs
+
+Response:
+{
+ "docs": [
+ {
+ "title": "文档标题",
+ "slug": "文档_slug",
+ "description": "文档描述"
+ }
+ ]
+}`,
+ },
+ {
+ title: "获取文档内容",
+ content: "获取指定文档的详细内容。",
+ code: `// GET /api/docs/:slug
+
+Response:
+{
+ "title": "文档标题",
+ "sections": [
+ {
+ "title": "章节标题",
+ "content": "章节内容"
+ }
+ ]
+}`,
+ },
+ ],
+ },
+];
+
+interface FeatureItem {
+ title: string;
+ items?: string[];
+ description?: string;
+}
+
+function FeatureCard({ title, description, children }: {
+ title: string;
+ description?: string;
+ children?: React.ReactNode;
+}) {
+ return (
+
+
{title}
+ {description &&
{description}
}
+ {children}
+
+ );
+}
+
+function HomeInner() {
+ const { theme, toggleTheme } = useTheme();
+ const { authenticated, user, checkAuth } = useAuth();
+ const [activeDoc, setActiveDoc] = useState("quick-start");
+ const [activeSection, setActiveSection] = useState("");
+ const [sidebarOpen, setSidebarOpen] = useState(false);
+ const [searchQuery, setSearchQuery] = useState("");
+ const [copied, setCopied] = useState(false);
+
+ useEffect(() => {
+ checkAuth();
+ }, []);
+
+ const currentDoc = documentation.find((doc) => doc.slug === activeDoc);
+ const sections = currentDoc?.sections || [];
+
+ const handleCopy = () => {
+ navigator.clipboard.writeText("npm install docs-site");
+ setCopied(true);
+ setTimeout(() => setCopied(false), 2000);
+ };
+
+ const handleNavClick = (id: string) => {
+ setActiveSection(id);
+ setSidebarOpen(false);
+ const element = document.getElementById(id);
+ element?.scrollIntoView({ behavior: "smooth", block: "start" });
+ };
+
+ const filteredDocs = documentation.filter(
+ (doc) =>
+ doc.title.includes(searchQuery) ||
+ doc.description.includes(searchQuery)
+ );
+
+ return (
+
+
+ {/* 移动端遮罩 */}
+ {sidebarOpen && (
+
setSidebarOpen(false)}
+ />
+ )}
+
+ {/* 左侧导航栏 */}
+
+
+ {/* 主内容区 */}
+
+ {/* 顶部导航栏 */}
+
+
+
+
+
{currentDoc?.title}
+ {!authenticated && (
+
+ 登录
+
+ )}
+ {authenticated && user && (
+
+ {user.username}
+
+
+ )}
+
+
+
+ {/* 深色模式切换 */}
+
+
+ {/* 复制链接 */}
+
+
+
+
+
+ {/* 文档内容 */}
+
+ {sections.map((section, index) => (
+
+
+
+ {section.content && (
+
+ {section.content}
+
+ )}
+
+ {section.features && (
+
+ {(section.features as string[] | FeatureItem[]).map((feature, i) => {
+ if (typeof feature === "string") {
+ return (
+
+ );
+ }
+ return (
+
+ {feature.items && (
+
+ {feature.items.map((item, j) => (
+ -
+ ✓
+ {item}
+
+ ))}
+
+ )}
+
+ );
+ })}
+
+ )}
+
+ {section.code && (
+
+ {section.code}
+
+ )}
+
+ {section.instructions && section.code && (
+
+ {section.instructions}
+
+ )}
+
+ ))}
+
+ {/* 便签 */}
+
+
+
+
+ {/* 留言板 */}
+
+
+
+
+
+ {/* 底部 */}
+
+
+
+
+ );
+
+function Home() {
+ const [mounted, setMounted] = useState(false);
+ useEffect(() => setMounted(true), []);
+ if (!mounted) return
;
+ return
;
+}
+
+export default Home;
diff --git a/src/components/ThemeProvider.tsx b/src/components/ThemeProvider.tsx
index 8241769..f1ff39f 100644
--- a/src/components/ThemeProvider.tsx
+++ b/src/components/ThemeProvider.tsx
@@ -42,13 +42,9 @@ export function ThemeProvider({ children }: { children: React.ReactNode }) {
});
};
- if (!mounted) {
- return <>{children}>;
- }
-
return (
- {children}
+ {mounted ? children : {children}
}
);
}
diff --git a/src/lib/db.ts b/src/lib/db.ts
index 1f47ab7..06bc37b 100644
--- a/src/lib/db.ts
+++ b/src/lib/db.ts
@@ -42,10 +42,7 @@ export async function getClient(): Promise
{
const client = await getPool().connect();
const release = () => client.release();
- return {
- ...client,
- release,
- };
+ return client as PoolClient & { release: () => void };
}
// 初始化数据库表
@@ -213,7 +210,7 @@ export async function getDocs(): Promise {
ORDER BY d.created_at DESC
`
);
- return result.rows.map((row) => ({
+ return result.rows.map((row: any) => ({
title: row.title,
slug: row.slug,
description: row.description,