refactor(api-docs): 重构 API 文档组件并优化构建 ID 生成逻辑
- 移除了公告功能,替换为固定公告内容 - 更新了站点信息,包括友情链接和邮箱地址 - 优化了图片总数和接口文档的展示方式 - 重新实现了构建 ID 生成逻辑,使用项目文件哈希值代替时间戳
This commit is contained in:
parent
c6818e848c
commit
36ef5db441
@ -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 ? (
|
<div
|
||||||
<Skeleton className="h-20 w-full" />
|
className="mb-4 last:mb-0 bg-gray-50 p-4 rounded-lg"
|
||||||
) : announcements.length > 0 ? (
|
>
|
||||||
announcements.map((announcement, index) => (
|
<Badge
|
||||||
<div
|
variant="outline"
|
||||||
key={index}
|
className="bg-teal-100 text-teal-800 mb-2"
|
||||||
className="mb-4 last:mb-0 bg-gray-50 p-4 rounded-lg"
|
|
||||||
>
|
>
|
||||||
<Badge
|
2024-10-03
|
||||||
variant="outline"
|
</Badge>
|
||||||
className="bg-teal-100 text-teal-800 mb-2"
|
<p className="text-gray-700">目前API已由无数据库的屎山代码重构为使用 Mysql 的高性能代码</p>
|
||||||
>
|
</div>
|
||||||
{announcement.date}
|
|
||||||
</Badge>
|
|
||||||
<p className="text-gray-700">{announcement.content}</p>
|
|
||||||
</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>
|
||||||
))}
|
))}
|
||||||
|
@ -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();
|
Loading…
Reference in New Issue
Block a user