feat: 完成分类、worksheet 接口开发,资源迁移到七牛
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# 公共接口契约
|
||||
|
||||
仅包含可公开的基础响应和健康检查类型。服务端通过 `workspace:*` 引用,使用 `import type` 避免引入无必要的运行时逻辑。
|
||||
包含可公开的基础响应、健康检查、微信登录请求/结果、本人摘要、分类查询/创建/更新、题型查询/公开 DTO/分页及有限错误原因类型。题型计数为含 seed 的十进制展示字符串,previewImg 可空。服务端通过 `workspace:*` 引用,使用 `import type` 避免引入无必要的运行时逻辑。
|
||||
|
||||
后续可以加入公开请求/响应类型及枚举,但禁止包含 Prisma Client、数据库模型、密钥、管理权限实现或私有生成器。
|
||||
|
||||
|
||||
@@ -10,3 +10,165 @@ export interface HealthStatus {
|
||||
status: 'ok';
|
||||
service: 'doodle-store-server';
|
||||
}
|
||||
|
||||
/** 安全、有限的失败原因;HTTP code 仍承担错误大类,不暴露内部异常。 */
|
||||
export type ApiErrorReason =
|
||||
| 'AUTH_REQUIRED'
|
||||
| 'AUTH_INVALID'
|
||||
| 'AUTH_EXPIRED'
|
||||
| 'AUTH_REVOKED'
|
||||
| 'ACCOUNT_NOT_FOUND'
|
||||
| 'ACCOUNT_DISABLED'
|
||||
| 'WECHAT_CODE_INVALID'
|
||||
| 'WECHAT_LOGIN_BLOCKED'
|
||||
| 'RATE_LIMITED'
|
||||
| 'AUTH_UPSTREAM_UNAVAILABLE'
|
||||
| 'DATABASE_UNAVAILABLE';
|
||||
|
||||
export interface ApiError {
|
||||
code: number;
|
||||
message: string;
|
||||
requestId?: string;
|
||||
reason?: ApiErrorReason;
|
||||
}
|
||||
|
||||
export type WechatLoginMode = 'start' | 'resume';
|
||||
export interface WechatLoginRequest {
|
||||
code: string;
|
||||
mode: WechatLoginMode;
|
||||
}
|
||||
|
||||
/** 显式白名单摘要,不含微信身份或凭证版本。头像签名由后续资产模块补齐。 */
|
||||
export interface UserSummary {
|
||||
id: string;
|
||||
nickName: string | null;
|
||||
avatarUrl: string | null;
|
||||
avatarUrlExpiresAt: string | null;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export interface WechatLoginResult {
|
||||
accessToken: string;
|
||||
tokenType: 'Bearer';
|
||||
expiresIn: number;
|
||||
expiresAt: string;
|
||||
user: UserSummary;
|
||||
}
|
||||
|
||||
export interface CurrentUserProfile extends UserSummary {
|
||||
role: 'user' | 'admin';
|
||||
}
|
||||
|
||||
export type ContentStatus = 'draft' | 'active' | 'hidden';
|
||||
|
||||
/** 分类 ID 沿用云数据库原值;列表为扁平结构,parentId=null 表示根分类。 */
|
||||
export interface Category {
|
||||
status: ContentStatus;
|
||||
id: string;
|
||||
name: string;
|
||||
icon: string;
|
||||
color: string;
|
||||
sortOrder: number;
|
||||
parentId: string | null;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface CreateCategoryRequest {
|
||||
status?: ContentStatus;
|
||||
id: string;
|
||||
name: string;
|
||||
icon: string;
|
||||
color: string;
|
||||
sortOrder?: number;
|
||||
parentId?: string | null;
|
||||
}
|
||||
|
||||
/** PATCH 不允许修改 ID;省略父级保持原值,null 或空串移到根级。 */
|
||||
export type UpdateCategoryRequest = Partial<Omit<CreateCategoryRequest, 'id'>>;
|
||||
|
||||
export type WorksheetAgeBand = '3-4' | '4-5' | '5-6' | '6-7' | '7-8';
|
||||
export type WorksheetSort = 'default' | 'latest' | 'hot';
|
||||
|
||||
/** 筛选条件可组合;grade 与 grades、age 与 ageBand 分别互斥。 */
|
||||
export interface WorksheetQuery {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
categoryId?: string;
|
||||
grade?: number;
|
||||
grades?: number[];
|
||||
ageBand?: WorksheetAgeBand;
|
||||
age?: number;
|
||||
tag?: string;
|
||||
sort?: WorksheetSort;
|
||||
isHot?: boolean;
|
||||
isNew?: boolean;
|
||||
}
|
||||
|
||||
/** 公开题型白名单;64 位展示计数使用十进制字符串,避免 JavaScript 精度丢失。 */
|
||||
export interface PublicWorksheet {
|
||||
id: string;
|
||||
title: string;
|
||||
subtitle: string;
|
||||
category: string;
|
||||
subcategory: string | null;
|
||||
path: string;
|
||||
ageMin: number;
|
||||
ageMax: number;
|
||||
grades: number[];
|
||||
difficulty: number;
|
||||
previewImg: string | null;
|
||||
tags: string[];
|
||||
isNew: boolean;
|
||||
isHot: boolean;
|
||||
sortOrder: number;
|
||||
downloads: string;
|
||||
likes: string;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
contentUpdatedAt: string | null;
|
||||
firstPublishedAt: string | null;
|
||||
}
|
||||
|
||||
export interface WorksheetPage {
|
||||
items: PublicWorksheet[];
|
||||
total: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
hasNext: boolean;
|
||||
}
|
||||
|
||||
/** 管理预览沿用公开字段白名单,额外标明自身状态和整条所属关系是否可见。 */
|
||||
export interface AdminWorksheet extends PublicWorksheet {
|
||||
status: ContentStatus;
|
||||
visible: boolean;
|
||||
}
|
||||
export interface AdminWorksheetPage extends Omit<WorksheetPage, 'items'> {
|
||||
items: AdminWorksheet[];
|
||||
}
|
||||
export interface UpdateContentStatusRequest {
|
||||
status: ContentStatus;
|
||||
}
|
||||
export interface ContentPublication {
|
||||
id: string;
|
||||
status: ContentStatus;
|
||||
firstPublishedAt: string | null;
|
||||
updatedAt: string;
|
||||
}
|
||||
/** 资源管理预览不返回配置覆盖、源文件地址、私有对象或签名 URL。 */
|
||||
export interface AdminWorksheetResource extends ContentPublication {
|
||||
worksheetId: string;
|
||||
title: string;
|
||||
previewImg: string | null;
|
||||
sortOrder: number;
|
||||
downloads: string;
|
||||
createdAt: string;
|
||||
visible: boolean;
|
||||
}
|
||||
export interface AdminResourcePage {
|
||||
items: AdminWorksheetResource[];
|
||||
total: number;
|
||||
page: number;
|
||||
pageSize: number;
|
||||
hasNext: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user