Files
Arkie-Library-Frontend/.unipi/docs/specs/2026-05-25-frontend-backend-api-requirements.md
2026-05-26 07:36:53 +08:00

12 KiB
Raw Blame History

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 / en / ja / ko / vi / id / ms;默认语言为 en。中文只有简体 zh,没有繁体中文。
  • 错误格式:非 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" | "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 === 1kind: "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;

搜索范围建议:textfilenamecategoryName、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" }

Response204 或 { ok: true }

用途:记录用户搜索词;失败不阻断用户体验。


2.8 下载统计(可选)

文件下载目前前端可直接打开 Attachment.url。如果后端需要统计下载,提供:

POST /api/posts/:postId/attachments/:attachmentId/download

Response204 或 { ok: true }

过渡期旧 Home 推荐卡还可能调用 POST /api/resources/:id/download

3. Filter 语义

GET /api/poststype 参数建议按以下规则命中:

type 命中条件
all 全部
image 任一 attachment kind === "image"
video 任一 attachment kind === "video"mime.startsWith("video/")
pdf 任一 attachment 扩展名 pdfmime === "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>

ResponseAdminPost


5.6 创建 Post

POST /api/admin/posts
Authorization: Bearer <admin-token>
Content-Type: application/json

Request:

type UpsertPostPayload = {
  categoryId: number;
  language: "zh" | "en" | "ja" | "ko" | "vi" | "id" | "ms";
  text?: string;
  attachments: Attachment[];
  isPublic: boolean;
  isRecommended: boolean;
  sortOrder: number;
  status: "draft" | "published" | "archived";
  publishedAt?: string;
  tags?: string[];
};

ResponseAdminPost


5.7 更新 Post

PUT /api/admin/posts/:id
Authorization: Bearer <admin-token>
Content-Type: application/json

RequestUpsertPostPayload。 ResponseAdminPost


5.8 删除 Post

DELETE /api/admin/posts/:id
Authorization: Bearer <admin-token>

Response204 或 { 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. 前后端切换计划

  1. 后端先实现 /api/posts/api/posts/:id/api/categories
  2. 前端 staging 设置:VITE_USE_MOCK_POSTS=false
  3. 确认 /browse/category/:slug 正常拉真数据。
  4. 再实现 /api/posts/recommended/api/posts/latest,前端把 Home 从旧 resources 切到 posts。
  5. 最后迁移 Admin 从 /api/admin/resources/api/admin/posts

9. 最小可上线优先级

P0前台资料流必需

  • GET /api/categories
  • GET /api/posts
  • GET /api/posts/:id
  • POST /api/admin/upload
  • POST /api/admin/posts
  • PUT /api/admin/posts/:id
  • GET /api/admin/posts
  • GET /api/admin/posts/:id

P1首页/搜索/统计)

  • GET /api/posts/recommended
  • GET /api/posts/latest
  • GET /api/posts/search
  • POST /api/search-log
  • GET /api/admin/dashboard
  • GET /api/admin/search-logs

P2账户

  • Wallet nonce / verify / me