12 KiB
title, type, date, audience, status
| title | type | date | audience | status |
|---|---|---|---|---|
| ARK Library Frontend — Backend API Requirements | api-requirements | 2026-05-25 | backend | draft |
ARK Library Frontend — Backend API Requirements
这份文档列出前端接下来需要后端提供的全部接口。重点是新的 Telegram-style 资料流;旧 resources 接口可作为过渡,但最终建议统一到 posts 模型。
0. 通用约定
- API base:前端通过
VITE_API_URL指向后端;本地可同源/api。 - 上传文件可通过
/uploads/...或完整 URL 返回;前端会用assetUrl()处理相对路径。 - 所有时间字段使用 ISO 8601 字符串,例如
2026-05-24T14:42:00.000Z。 - 语言字段:
zh-CN/en/ja/ko/vi/id/ms;默认语言为en。中文只有简体zh-CN,没有繁体中文。 - 错误格式:非 2xx + text/plain 或 JSON 均可;前端会显示错误文本。
- Admin 接口需要
Authorization: Bearer <token>。
1. 核心数据模型
1.1 Category
type Category = {
id: number;
slug: string; // 用于 /category/:slug 和 GET /api/posts?category=<slug>
name: string; // 已按 lang 返回本地化名称
description?: string;
iconKey: string; // folder/calendar/megaphone/video/image 等,前端已有 icon map
sortOrder: number;
};
1.2 Post(新资料流核心)
type AttachmentKind = "image" | "video" | "document";
type Attachment = {
id: string;
kind: AttachmentKind;
url: string; // 原始文件或可访问文件 URL
mime: string; // image/jpeg, application/pdf, video/mp4, ...
filename: string;
sizeBytes: number;
width?: number; // image/video 建议提供
height?: number;
durationSec?: number; // video 建议提供
posterUrl?: string; // video preview
thumbnailUrl?: string; // image/document preview
};
type Post = {
id: string;
categoryId: number;
categorySlug: string;
language: "zh-CN" | "en" | "ja" | "ko" | "vi" | "id" | "ms";
text?: string;
attachments: Attachment[];
isRecommended: boolean;
publishedAt: string;
updatedAt: string;
};
type PostListResponse = {
items: Post[];
nextCursor?: string;
};
1.3 Post 显示规则(后端必须按这个模型返回)
- 纯文字/链接:
attachments: [],text非空。 - 单张图片:
attachments.length === 1且kind: "image"。 - 图片 + 文字:
kind: "image"+text。 - 视频:
kind: "video",建议提供posterUrl/durationSec。 - 文件:
kind: "document",前端显示下载卡。 - 图片当文件上传:
kind: "document"且mime是 image;前端会显示缩略图 + 下载按钮。 - 多图:
- 2 / 3 / 4 张图:前端会独立纵向显示每张图,同一个 Post 只显示一次时间。
- 超过 4 张图:前端显示 2×2 合并格,第 4 格模糊并显示
+N。
2. Public API(前台用户)
2.1 分类列表
GET /api/categories?lang=en
Response:
Category[]
用途:Home 资料分类、CategoryPage 标题、Admin 表单分类选择。
2.2 全部资料 / 分类资料流
GET /api/posts?lang=en&limit=20&cursor=<cursor>&type=all&language=&category=<slug>
Query:
| 参数 | 必填 | 说明 |
|---|---|---|
lang |
是 | UI 语言 |
limit |
否 | 默认 20,最大建议 50 |
cursor |
否 | 后端返回的不透明 cursor |
category |
否 | 不传 = 全部资料;传 slug = 单分类 |
type |
否 | all/image/video/ppt/pdf/text/link/archive |
language |
否 | 资料语言:zh/en/ja/ko/vi/id/ms |
Response:
PostListResponse;
排序:publishedAt DESC。
用途:
/browse:不传category/category/:slug:传category=<slug>
2.3 Home 推荐资料
GET /api/posts/recommended?lang=en&limit=12
Response:
{ items: Post[] }
用途:Home「官方推荐」section。按 sortOrder ASC + publishedAt DESC 或后端自定义推荐顺序。
过渡期:当前前端 Home 仍可接受旧
/api/resources/recommended,但建议后端新做posts/recommended后前端再切换。
2.4 Home 最新资料
GET /api/posts/latest?lang=en&limit=8
Response:
{ items: Post[] }
用途:Home「最新更新」section。按 publishedAt DESC。
过渡期:当前前端 Home 仍可接受旧
/api/resources/latest。
2.5 单条 Post(旧链接落地)
GET /api/posts/:id
Response:
Post;
用途:旧 /resource/:id 前端重定向:拿 categorySlug 后跳到 /category/<slug>#post-<id>。
2.6 搜索
建议新接口:
GET /api/posts/search?q=<keyword>&lang=en&type=all&language=&cursor=&limit=20
Response:
PostListResponse;
搜索范围建议:text、filename、categoryName、tags。
过渡期当前前端仍使用:
GET /api/resources?q=<keyword>&lang=&type=&language=&limit=50
Response:
{ items: Resource[] }
2.7 搜索日志
POST /api/search-log
Content-Type: application/json
{ "query": "ARK" }
Response:204 或 { ok: true }。
用途:记录用户搜索词;失败不阻断用户体验。
2.8 下载统计(可选)
文件下载目前前端可直接打开 Attachment.url。如果后端需要统计下载,提供:
POST /api/posts/:postId/attachments/:attachmentId/download
Response:204 或 { ok: true }。
过渡期旧 Home 推荐卡还可能调用
POST /api/resources/:id/download。
3. Filter 语义
GET /api/posts 的 type 参数建议按以下规则命中:
| type | 命中条件 |
|---|---|
all |
全部 |
image |
任一 attachment kind === "image" |
video |
任一 attachment kind === "video" 或 mime.startsWith("video/") |
pdf |
任一 attachment 扩展名 pdf 或 mime === "application/pdf" |
ppt |
任一 attachment 扩展名 ppt/pptx/key 或 mime 含 presentation |
archive |
任一 attachment 扩展名 zip/rar/7z/tar/gz |
text |
text 非空 |
link |
text 中包含 https?:// |
4. Wallet Auth API
4.1 取得签名 nonce/message
POST /api/auth/wallet/nonce
Content-Type: application/json
{ "address": "0x..." }
Response:
{
message: string;
}
4.2 验证签名并签发 token
POST /api/auth/wallet/verify
Content-Type: application/json
{
"address": "0x...",
"message": "...",
"signature": "0x..."
}
Response:
{
token: string;
}
4.3 验证当前 wallet session
GET /api/auth/wallet/me
Authorization: Bearer <wallet-token>
Response:
{
wallet: string;
}
5. Admin API
5.1 Admin 登录
POST /api/admin/login
Content-Type: application/json
{ "username": "...", "password": "..." }
Response:
{
token: string;
}
5.2 Admin dashboard
GET /api/admin/dashboard
Authorization: Bearer <admin-token>
Response:
type AdminDashboard = {
totalResources: number; // 若迁移到 Post,可理解为 totalPosts
published: number;
todayNew: number;
totalViews: number;
totalDownloads: number;
totalFavorites: number; // 收藏下线后可返回 0,避免旧 admin UI 崩
totalShares: number;
hotResources: {
id: string;
title: string;
downloads: number;
favorites: number; // 可返回 0
views: number;
}[];
};
5.3 文件上传
POST /api/admin/upload
Authorization: Bearer <admin-token>
Content-Type: multipart/form-data
file=<File>
最低 Response:
{
url: string;
}
建议 Response(更方便前端自动建 Attachment):
{
url: string;
mime: string;
filename: string;
sizeBytes: number;
width?: number;
height?: number;
durationSec?: number;
thumbnailUrl?: string;
posterUrl?: string;
}
5.4 Admin Post 列表
GET /api/admin/posts?limit=25&page=1&status=&category=&type=&q=
Authorization: Bearer <admin-token>
Response:
{
items: AdminPost[];
total: number;
}
type AdminPost = Post & {
isPublic: boolean;
sortOrder: number;
status: "draft" | "published" | "archived";
viewCount?: number;
downloadCount?: number;
};
5.5 Admin Post 详情
GET /api/admin/posts/:id
Authorization: Bearer <admin-token>
Response:AdminPost。
5.6 创建 Post
POST /api/admin/posts
Authorization: Bearer <admin-token>
Content-Type: application/json
Request:
type UpsertPostPayload = {
categoryId: number;
language: "zh-CN" | "en" | "ja" | "ko" | "vi" | "id" | "ms";
text?: string;
attachments: Attachment[];
isPublic: boolean;
isRecommended: boolean;
sortOrder: number;
status: "draft" | "published" | "archived";
publishedAt?: string;
tags?: string[];
};
Response:AdminPost。
5.7 更新 Post
PUT /api/admin/posts/:id
Authorization: Bearer <admin-token>
Content-Type: application/json
Request:UpsertPostPayload。
Response:AdminPost。
5.8 删除 Post
DELETE /api/admin/posts/:id
Authorization: Bearer <admin-token>
Response:204 或 { ok: true }。
5.9 Admin 搜索日志
GET /api/admin/search-logs?limit=300
Authorization: Bearer <admin-token>
Response:
{
items: {
id: string;
query: string;
createdAt: string;
count?: number;
}[];
}
6. 过渡期旧 Resource API(如果 admin 尚未迁移)
当前部分前端/admin 代码仍可能使用旧接口。后端可以短期保留,或前端后续再统一切到 Post:
GET /api/resources?lang=&limit=&page=&sort=&q=&type=&language=&tag=
GET /api/resources/recommended?lang=&limit=
GET /api/resources/latest?lang=&limit=
POST /api/resources/:id/download
GET /api/admin/resources?limit=&page=
GET /api/admin/resources/:id
POST /api/admin/resources
PUT /api/admin/resources/:id
旧 Resource shape:
type Resource = {
id: string;
title: string;
description?: string;
type: string;
language: string;
categoryId: number;
categorySlug: string;
categoryName: string;
coverImage?: string;
fileUrl?: string;
previewUrl?: string;
externalUrl?: string;
bodyText?: string;
badgeLabel?: string;
isDownloadable: boolean;
isRecommended: boolean;
publishedAt?: string;
updatedAt: string;
tags?: string[];
};
7. 已下线 / 不需要实现
- 用户收藏:
/favorites页面已移除。 POST /api/resources/:id/favorite不需要。- Reaction / 点赞 / 评论不需要。
- Telegram 管理员标签、头像、群组名不需要。
8. 前后端切换计划
- 后端先实现
/api/posts、/api/posts/:id、/api/categories。 - 前端 staging 设置:
VITE_USE_MOCK_POSTS=false。 - 确认
/browse和/category/:slug正常拉真数据。 - 再实现
/api/posts/recommended、/api/posts/latest,前端把 Home 从旧 resources 切到 posts。 - 最后迁移 Admin 从
/api/admin/resources到/api/admin/posts。
9. 最小可上线优先级
P0(前台资料流必需)
GET /api/categoriesGET /api/postsGET /api/posts/:idPOST /api/admin/uploadPOST /api/admin/postsPUT /api/admin/posts/:idGET /api/admin/postsGET /api/admin/posts/:id
P1(首页/搜索/统计)
GET /api/posts/recommendedGET /api/posts/latestGET /api/posts/searchPOST /api/search-logGET /api/admin/dashboardGET /api/admin/search-logs
P2(账户)
- Wallet nonce / verify / me