feat: align frontend languages with posts api

This commit is contained in:
TerryM
2026-05-26 07:36:53 +08:00
parent 453abfcec7
commit e7a5952d58
19 changed files with 565 additions and 544 deletions

View File

@@ -15,7 +15,7 @@ status: draft
- API base前端通过 `VITE_API_URL` 指向后端;本地可同源 `/api`
- 上传文件可通过 `/uploads/...` 或完整 URL 返回;前端会用 `assetUrl()` 处理相对路径。
- 所有时间字段使用 ISO 8601 字符串,例如 `2026-05-24T14:42:00.000Z`
- 语言字段:`zh-TW` / `zh-CN` / `en`
- 语言字段:`zh` / `en` / `ja` / `ko` / `vi` / `id` / `ms`;默认语言为 `en`。中文只有简体 `zh`,没有繁体中文
- 错误格式:非 2xx + text/plain 或 JSON 均可;前端会显示错误文本。
- Admin 接口需要 `Authorization: Bearer <token>`
@@ -26,10 +26,10 @@ status: draft
```ts
type Category = {
id: number;
slug: string; // 用于 /category/:slug 和 GET /api/posts?category=<slug>
name: string; // 已按 lang 返回本地化名称
slug: string; // 用于 /category/:slug 和 GET /api/posts?category=<slug>
name: string; // 已按 lang 返回本地化名称
description?: string;
iconKey: string; // folder/calendar/megaphone/video/image 等,前端已有 icon map
iconKey: string; // folder/calendar/megaphone/video/image 等,前端已有 icon map
sortOrder: number;
};
```
@@ -42,22 +42,22 @@ type AttachmentKind = "image" | "video" | "document";
type Attachment = {
id: string;
kind: AttachmentKind;
url: string; // 原始文件或可访问文件 URL
mime: string; // image/jpeg, application/pdf, video/mp4, ...
url: string; // 原始文件或可访问文件 URL
mime: string; // image/jpeg, application/pdf, video/mp4, ...
filename: string;
sizeBytes: number;
width?: number; // image/video 建议提供
width?: number; // image/video 建议提供
height?: number;
durationSec?: number; // video 建议提供
posterUrl?: string; // video preview
thumbnailUrl?: string; // image/document preview
durationSec?: number; // video 建议提供
posterUrl?: string; // video preview
thumbnailUrl?: string; // image/document preview
};
type Post = {
id: string;
categoryId: number;
categorySlug: string;
language: "zh-TW" | "zh-CN" | "en";
language: "zh" | "en" | "ja" | "ko" | "vi" | "id" | "ms";
text?: string;
attachments: Attachment[];
isRecommended: boolean;
@@ -88,7 +88,7 @@ type PostListResponse = {
### 2.1 分类列表
```http
GET /api/categories?lang=zh-CN
GET /api/categories?lang=en
```
Response:
@@ -104,29 +104,30 @@ Category[]
### 2.2 全部资料 / 分类资料流
```http
GET /api/posts?lang=zh-CN&limit=20&cursor=<cursor>&type=all&language=&category=<slug>
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-TW/zh-CN/en` |
| 参数 | 必填 | 说明 |
| ---------- | ---: | ------------------------------------------- |
| `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:
```ts
PostListResponse
PostListResponse;
```
排序:`publishedAt DESC`
用途:
- `/browse`:不传 `category`
- `/category/:slug`:传 `category=<slug>`
@@ -135,7 +136,7 @@ PostListResponse
### 2.3 Home 推荐资料
```http
GET /api/posts/recommended?lang=zh-CN&limit=12
GET /api/posts/recommended?lang=en&limit=12
```
Response:
@@ -153,7 +154,7 @@ Response:
### 2.4 Home 最新资料
```http
GET /api/posts/latest?lang=zh-CN&limit=8
GET /api/posts/latest?lang=en&limit=8
```
Response:
@@ -177,7 +178,7 @@ GET /api/posts/:id
Response:
```ts
Post
Post;
```
用途:旧 `/resource/:id` 前端重定向:拿 `categorySlug` 后跳到 `/category/<slug>#post-<id>`
@@ -189,13 +190,13 @@ Post
建议新接口:
```http
GET /api/posts/search?q=<keyword>&lang=zh-CN&type=all&language=&cursor=&limit=20
GET /api/posts/search?q=<keyword>&lang=en&type=all&language=&cursor=&limit=20
```
Response:
```ts
PostListResponse
PostListResponse;
```
搜索范围建议:`text``filename``categoryName`、tags。
@@ -245,16 +246,16 @@ Response204 或 `{ ok: true }`。
`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?://` |
| 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
@@ -270,7 +271,9 @@ Content-Type: application/json
Response:
```ts
{ message: string }
{
message: string;
}
```
### 4.2 验证签名并签发 token
@@ -289,7 +292,9 @@ Content-Type: application/json
Response:
```ts
{ token: string }
{
token: string;
}
```
### 4.3 验证当前 wallet session
@@ -302,7 +307,9 @@ Authorization: Bearer <wallet-token>
Response:
```ts
{ wallet: string }
{
wallet: string;
}
```
## 5. Admin API
@@ -319,7 +326,9 @@ Content-Type: application/json
Response:
```ts
{ token: string }
{
token: string;
}
```
---
@@ -335,18 +344,18 @@ Response:
```ts
type AdminDashboard = {
totalResources: number; // 若迁移到 Post可理解为 totalPosts
totalResources: number; // 若迁移到 Post可理解为 totalPosts
published: number;
todayNew: number;
totalViews: number;
totalDownloads: number;
totalFavorites: number; // 收藏下线后可返回 0避免旧 admin UI 崩
totalFavorites: number; // 收藏下线后可返回 0避免旧 admin UI 崩
totalShares: number;
hotResources: {
id: string;
title: string;
downloads: number;
favorites: number; // 可返回 0
favorites: number; // 可返回 0
views: number;
}[];
};
@@ -367,7 +376,9 @@ file=<File>
最低 Response:
```ts
{ url: string }
{
url: string;
}
```
建议 Response更方便前端自动建 Attachment
@@ -438,7 +449,7 @@ Request:
```ts
type UpsertPostPayload = {
categoryId: number;
language: "zh-TW" | "zh-CN" | "en";
language: "zh" | "en" | "ja" | "ko" | "vi" | "id" | "ms";
text?: string;
attachments: Attachment[];
isPublic: boolean;