refactor(api-docs): 重构 API 文档组件并优化构建 ID 生成逻辑

- 移除了公告功能,替换为固定公告内容
- 更新了站点信息,包括友情链接和邮箱地址
- 优化了图片总数和接口文档的展示方式
- 重新实现了构建 ID 生成逻辑,使用项目文件哈希值代替时间戳
This commit is contained in:
mei 2025-02-07 11:10:18 +08:00
parent c6818e848c
commit 36ef5db441
2 changed files with 47 additions and 46 deletions

View File

@ -20,27 +20,20 @@ import { ExternalLink, GitCommit } from "lucide-react";
export default function ApiDocsComponent() { export default function ApiDocsComponent() {
const [activePage, setActivePage] = useState("home"); const [activePage, setActivePage] = useState("home");
const [imageCount, setImageCount] = useState<number | null>(null); const [imageCount, setImageCount] = useState<number | null>(null);
const [announcements, setAnnouncements] = useState<
Array<{ date: string; content: string }>
>([]);
const [loading, setLoading] = useState(true); const [loading, setLoading] = useState(true);
useEffect(() => { useEffect(() => {
const fetchData = async () => { const fetchData = async () => {
setLoading(true); setLoading(true);
try { try {
const [imageCountResponse, announcementsResponse] = await Promise.all([ const [imageCountResponse] = await Promise.all([
fetch("/?api=total-pic"), fetch("/?api=total-pic")
fetch("/?api=announcements"),
]); ]);
const imageCountData = await imageCountResponse.json(); const imageCountData = await imageCountResponse.json();
const announcementsData = await announcementsResponse.json();
setImageCount(imageCountData.count); setImageCount(imageCountData.count);
setAnnouncements(announcementsData.announcements);
} catch (error) { } catch (error) {
console.error("Failed to fetch data:", error); console.error("Failed to fetch data:", error);
setImageCount(null); setImageCount(null);
setAnnouncements([]);
} finally { } finally {
setLoading(false); setLoading(false);
} }
@ -119,7 +112,7 @@ export default function ApiDocsComponent() {
]; ];
const friendlyLinks = [ const friendlyLinks = [
{ name: "mei的网络日志", url: "https://mmeiblog.cn" } { name: "mei的网络日志", url: "https://mei.lv" }
]; ];
const HomePage = () => ( const HomePage = () => (
@ -144,16 +137,6 @@ export default function ApiDocsComponent() {
<p className="mt-4 text-gray-600"> <p className="mt-4 text-gray-600">
</p> </p>
<p className="mt-4 text-gray-600">
API有什么不完善的地方或者说你有什么更好的想{" "}
<a
href="mailto:i@mmeiblog.cn"
className="text-blue-600 hover:underline"
>
i@mmeiblog.cn
</a>
</p>
</CardContent> </CardContent>
</Card> </Card>
@ -162,26 +145,17 @@ export default function ApiDocsComponent() {
<CardTitle className="text-2xl font-bold"></CardTitle> <CardTitle className="text-2xl font-bold"></CardTitle>
</CardHeader> </CardHeader>
<CardContent className="p-6"> <CardContent className="p-6">
{loading ? (
<Skeleton className="h-20 w-full" />
) : announcements.length > 0 ? (
announcements.map((announcement, index) => (
<div <div
key={index}
className="mb-4 last:mb-0 bg-gray-50 p-4 rounded-lg" className="mb-4 last:mb-0 bg-gray-50 p-4 rounded-lg"
> >
<Badge <Badge
variant="outline" variant="outline"
className="bg-teal-100 text-teal-800 mb-2" className="bg-teal-100 text-teal-800 mb-2"
> >
{announcement.date} 2024-10-03
</Badge> </Badge>
<p className="text-gray-700">{announcement.content}</p> <p className="text-gray-700">API已由无数据库的屎山代码重构为使用 Mysql </p>
</div> </div>
))
) : (
<p className="text-gray-500 italic"></p>
)}
</CardContent> </CardContent>
</Card> </Card>
@ -224,7 +198,7 @@ export default function ApiDocsComponent() {
</CardHeader> </CardHeader>
<CardContent className="p-6"> <CardContent className="p-6">
<p className="text-gray-700"> <p className="text-gray-700">
API API !
</p> </p>
<p className="mt-4 text-gray-600"> <p className="mt-4 text-gray-600">
:{" "} :{" "}
@ -283,7 +257,7 @@ export default function ApiDocsComponent() {
<TableCell>{endpoint.id}</TableCell> <TableCell>{endpoint.id}</TableCell>
<TableCell>{endpoint.device}</TableCell> <TableCell>{endpoint.device}</TableCell>
<TableCell>{endpoint.method}</TableCell> <TableCell>{endpoint.method}</TableCell>
<TableCell>{endpoint.url}</TableCell> <TableCell><a href = {endpoint.url}>{endpoint.url}</a></TableCell>
<TableCell>{endpoint.description}</TableCell> <TableCell>{endpoint.description}</TableCell>
</TableRow> </TableRow>
))} ))}

View File

@ -1,12 +1,39 @@
const fs = require('fs'); import fs from 'fs';
const path = require('path'); import path from 'path';
import crypto from 'crypto';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const generateProjectHash = () => {
const hash = crypto.createHash('sha256');
const walk = (dir) => {
const files = fs.readdirSync(dir);
files.forEach(file => {
const filePath = path.join(dir, file);
const stat = fs.statSync(filePath);
if (stat.isDirectory()) {
walk(filePath);
} else {
hash.update(fs.readFileSync(filePath));
}
});
};
walk(path.join(__dirname, '..'));
return hash.digest('hex').substring(0, 7); // 使用前10个字符作为短哈希
};
const generateBuildId = () => { const generateBuildId = () => {
const buildId = Date.now().toString(36) + Math.random().toString(36).substr(2, 5); const projectHash = generateProjectHash();
const envFilePath = path.join(__dirname, '..', '.env.local'); const envFilePath = path.join(__dirname, '..', '.env.local');
fs.appendFileSync(envFilePath, `\nNEXT_PUBLIC_BUILD_ID=${buildId}`); if (fs.existsSync(envFilePath)) {
console.log(`Build ID generated: ${buildId}`); fs.unlinkSync(envFilePath);
}
fs.writeFileSync(envFilePath, `NEXT_PUBLIC_BUILD_ID=${projectHash}`);
console.log(`Build ID generated: ${projectHash}`);
}; };
generateBuildId(); generateBuildId();