You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1305 lines
31 KiB
1305 lines
31 KiB
openapi: 3.1.0
|
|
info:
|
|
title: Mach-CMS API
|
|
description: |
|
|
Mach-CMS 后端 API 规范。前后端契约文件,任何接口变更必须同步修改此文件。
|
|
|
|
- 所有业务接口返回统一包装体 `Response<T>`
|
|
- 列表查询返回 `PageResult<T>`
|
|
- 认证方式:JWT Bearer Token
|
|
- 时间格式:ISO-8601(`2024-01-15T08:30:00Z`)
|
|
version: 0.3.1
|
|
contact:
|
|
name: Mach-CMS Team
|
|
|
|
servers:
|
|
- url: http://localhost:8080
|
|
description: 本地开发环境
|
|
|
|
security:
|
|
- bearerAuth: []
|
|
|
|
tags:
|
|
- name: Auth
|
|
description: 认证与授权
|
|
- name: Public
|
|
description: 公开接口(无需认证)
|
|
- name: Article
|
|
description: 文章(前台只读)
|
|
- name: ArticleAdmin
|
|
description: 文章管理(需 ADMIN/EDITOR)
|
|
- name: Tag
|
|
description: 标签(前台只读)
|
|
- name: TagAdmin
|
|
description: 标签管理(需 ADMIN)
|
|
- name: Media
|
|
description: 媒体文件上传
|
|
- name: Search
|
|
description: 全文搜索
|
|
- name: Comment
|
|
description: 评论(前台免登录提交,展示已审核)
|
|
- name: CommentAdmin
|
|
description: 评论管理(需 ADMIN)
|
|
- name: User
|
|
description: 用户管理(需 ADMIN)
|
|
|
|
paths:
|
|
# ==================== Public ====================
|
|
/api/public/health:
|
|
get:
|
|
tags: [Public]
|
|
summary: 健康检查
|
|
security: []
|
|
responses:
|
|
'200':
|
|
description: 服务正常
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseString'
|
|
example:
|
|
code: 0
|
|
message: success
|
|
data: UP
|
|
|
|
# ==================== Auth ====================
|
|
/api/auth/register:
|
|
post:
|
|
tags: [Auth]
|
|
summary: 用户注册
|
|
security: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RegisterRequest'
|
|
responses:
|
|
'200':
|
|
description: 注册成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseTokenPair'
|
|
|
|
/api/auth/login:
|
|
post:
|
|
tags: [Auth]
|
|
summary: 用户登录
|
|
security: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/LoginRequest'
|
|
responses:
|
|
'200':
|
|
description: 登录成功,返回双 Token
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseTokenPair'
|
|
|
|
/api/auth/refresh:
|
|
post:
|
|
tags: [Auth]
|
|
summary: 刷新 Access Token
|
|
security: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/RefreshTokenRequest'
|
|
responses:
|
|
'200':
|
|
description: 刷新成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseTokenPair'
|
|
|
|
/api/auth/logout:
|
|
post:
|
|
tags: [Auth]
|
|
summary: 退出登录(吊销 Refresh Token)
|
|
responses:
|
|
'200':
|
|
description: 退出成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseVoid'
|
|
|
|
# ==================== Article (Public) ====================
|
|
/api/articles:
|
|
get:
|
|
tags: [Article]
|
|
summary: 文章列表(分页)
|
|
security: []
|
|
parameters:
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 1
|
|
- name: size
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 10
|
|
maximum: 100
|
|
- name: status
|
|
in: query
|
|
schema:
|
|
$ref: '#/components/schemas/ArticleStatus'
|
|
default: PUBLISHED
|
|
- name: tag
|
|
in: query
|
|
description: 标签 slug 过滤
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: 文章列表
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponsePageArticleListItem'
|
|
|
|
/api/articles/popular:
|
|
get:
|
|
tags: [Article]
|
|
summary: 热门文章(按浏览量降序,仅 PUBLISHED)
|
|
security: []
|
|
parameters:
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 5
|
|
maximum: 10
|
|
minimum: 1
|
|
responses:
|
|
'200':
|
|
description: 热门文章列表
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseListArticleListItem'
|
|
|
|
/api/articles/{slug}:
|
|
get:
|
|
tags: [Article]
|
|
summary: 文章详情(按 slug)
|
|
security: []
|
|
parameters:
|
|
- name: slug
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: 文章详情
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseArticleDetail'
|
|
'404':
|
|
description: 文章不存在
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseVoid'
|
|
|
|
/api/articles/{slug}/meta:
|
|
get:
|
|
tags: [Article]
|
|
summary: 文章 OpenGraph 元数据(分享预览)
|
|
security: []
|
|
parameters:
|
|
- name: slug
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: 元数据(文章不存在时为 null)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseOpenGraphMeta'
|
|
|
|
/api/articles/{slug}/star:
|
|
post:
|
|
tags: [Article]
|
|
summary: 点赞文章(已登录)
|
|
parameters:
|
|
- name: slug
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: 点赞成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseVoid'
|
|
'401':
|
|
description: 未登录
|
|
|
|
delete:
|
|
tags: [Article]
|
|
summary: 取消点赞文章(已登录)
|
|
parameters:
|
|
- name: slug
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: 取消成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseVoid'
|
|
'401':
|
|
description: 未登录
|
|
|
|
/api/comments/{id}/star:
|
|
post:
|
|
tags: [Comment]
|
|
summary: 点赞评论(已登录)
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
responses:
|
|
'200':
|
|
description: 点赞成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseVoid'
|
|
'401':
|
|
description: 未登录
|
|
|
|
delete:
|
|
tags: [Comment]
|
|
summary: 取消点赞评论(已登录)
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
responses:
|
|
'200':
|
|
description: 取消成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseVoid'
|
|
'401':
|
|
description: 未登录
|
|
|
|
# ==================== Comment (Public) ====================
|
|
/api/articles/{slug}/comments:
|
|
get:
|
|
tags: [Comment]
|
|
summary: 文章评论列表(仅返回已审核 APPROVED)
|
|
security: []
|
|
parameters:
|
|
- name: slug
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: 评论列表
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseListComment'
|
|
|
|
post:
|
|
tags: [Comment]
|
|
summary: 提交评论(免登录,提交后为 PENDING 待审核)
|
|
security: []
|
|
parameters:
|
|
- name: slug
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/CommentSubmitRequest'
|
|
responses:
|
|
'200':
|
|
description: 提交成功,返回待审核评论
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseComment'
|
|
|
|
/api/articles/search:
|
|
get:
|
|
tags: [Search]
|
|
summary: 全文搜索文章
|
|
security: []
|
|
parameters:
|
|
- name: q
|
|
in: query
|
|
required: true
|
|
description: 搜索关键词
|
|
schema:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 100
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 1
|
|
- name: size
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 10
|
|
maximum: 50
|
|
responses:
|
|
'200':
|
|
description: 搜索结果
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponsePageArticleListItem'
|
|
|
|
# ==================== ArticleAdmin ====================
|
|
/api/admin/articles:
|
|
post:
|
|
tags: [ArticleAdmin]
|
|
summary: 创建文章
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ArticleCreateRequest'
|
|
responses:
|
|
'200':
|
|
description: 创建成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseArticleDetail'
|
|
|
|
/api/admin/articles/{id}:
|
|
get:
|
|
tags: [ArticleAdmin]
|
|
summary: 文章详情(按 id,管理端,含草稿/归档等任意状态)
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
responses:
|
|
'200':
|
|
description: 文章详情
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseArticleDetail'
|
|
'404':
|
|
description: 文章不存在
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseVoid'
|
|
|
|
put:
|
|
tags: [ArticleAdmin]
|
|
summary: 更新文章
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ArticleUpdateRequest'
|
|
responses:
|
|
'200':
|
|
description: 更新成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseArticleDetail'
|
|
|
|
delete:
|
|
tags: [ArticleAdmin]
|
|
summary: 删除文章
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
responses:
|
|
'200':
|
|
description: 删除成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseVoid'
|
|
|
|
/api/admin/articles/{id}/publish:
|
|
patch:
|
|
tags: [ArticleAdmin]
|
|
summary: 发布文章(状态机:DRAFT → PUBLISHED)
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
responses:
|
|
'200':
|
|
description: 发布成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseArticleDetail'
|
|
|
|
/api/admin/articles/{id}/archive:
|
|
patch:
|
|
tags: [ArticleAdmin]
|
|
summary: 归档文章
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
responses:
|
|
'200':
|
|
description: 归档成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseArticleDetail'
|
|
|
|
# ==================== Tag (Public) ====================
|
|
/api/tags:
|
|
get:
|
|
tags: [Tag]
|
|
summary: 标签列表(带文章计数)
|
|
security: []
|
|
responses:
|
|
'200':
|
|
description: 标签列表
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseListTagWithCount'
|
|
|
|
# ==================== TagAdmin ====================
|
|
/api/admin/tags:
|
|
post:
|
|
tags: [TagAdmin]
|
|
summary: 创建标签
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TagCreateRequest'
|
|
responses:
|
|
'200':
|
|
description: 创建成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseTag'
|
|
|
|
/api/admin/tags/{id}:
|
|
put:
|
|
tags: [TagAdmin]
|
|
summary: 更新标签
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TagUpdateRequest'
|
|
responses:
|
|
'200':
|
|
description: 更新成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseTag'
|
|
|
|
delete:
|
|
tags: [TagAdmin]
|
|
summary: 删除标签
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
responses:
|
|
'200':
|
|
description: 删除成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseVoid'
|
|
|
|
# ==================== Media ====================
|
|
/api/media/upload:
|
|
post:
|
|
tags: [Media]
|
|
summary: 上传文件
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
multipart/form-data:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
file:
|
|
type: string
|
|
format: binary
|
|
description: 文件内容
|
|
directory:
|
|
type: string
|
|
default: images
|
|
description: 存储目录
|
|
responses:
|
|
'200':
|
|
description: 上传成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseStoredFile'
|
|
|
|
# ==================== CommentAdmin ====================
|
|
/api/admin/comments:
|
|
get:
|
|
tags: [CommentAdmin]
|
|
summary: 待审核评论列表(分页,状态 PENDING)
|
|
parameters:
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 1
|
|
- name: size
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 20
|
|
responses:
|
|
'200':
|
|
description: 待审核评论列表
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponsePageComment'
|
|
|
|
/api/admin/comments/{id}:
|
|
delete:
|
|
tags: [CommentAdmin]
|
|
summary: 删除评论
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
responses:
|
|
'200':
|
|
description: 删除成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseVoid'
|
|
|
|
/api/admin/comments/{id}/approve:
|
|
patch:
|
|
tags: [CommentAdmin]
|
|
summary: 审核通过评论(PENDING → APPROVED)
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
responses:
|
|
'200':
|
|
description: 审核成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseComment'
|
|
|
|
/api/admin/comments/{id}/reject:
|
|
patch:
|
|
tags: [CommentAdmin]
|
|
summary: 驳回评论(PENDING → REJECTED)
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
responses:
|
|
'200':
|
|
description: 驳回成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseComment'
|
|
|
|
# ==================== User ====================
|
|
/api/admin/users:
|
|
get:
|
|
tags: [User]
|
|
summary: 用户列表(分页)
|
|
parameters:
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 1
|
|
- name: size
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 20
|
|
responses:
|
|
'200':
|
|
description: 用户列表
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponsePageUserInfo'
|
|
|
|
/api/admin/users/{id}/role:
|
|
patch:
|
|
tags: [User]
|
|
summary: 修改用户角色
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UpdateRoleRequest'
|
|
responses:
|
|
'200':
|
|
description: 修改成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseUserInfo'
|
|
|
|
/api/admin/users/{id}/status:
|
|
patch:
|
|
tags: [User]
|
|
summary: 启用/禁用用户
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
format: int64
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/UpdateStatusRequest'
|
|
responses:
|
|
'200':
|
|
description: 修改成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ResponseUserInfo'
|
|
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
description: |
|
|
在请求头中携带 `Authorization: Bearer <access_token>`。
|
|
Access Token 有效期 15 分钟,过期后用 Refresh Token 调用 `/api/auth/refresh` 换取新的 Access Token。
|
|
|
|
schemas:
|
|
# ---------- 通用包装体 ----------
|
|
Response:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: integer
|
|
description: 0 表示成功,非 0 为业务错误码
|
|
message:
|
|
type: string
|
|
data:
|
|
description: 业务数据,类型由具体接口决定
|
|
required: [code, message]
|
|
|
|
PageResult:
|
|
type: object
|
|
properties:
|
|
list:
|
|
type: array
|
|
items: {}
|
|
total:
|
|
type: integer
|
|
format: int64
|
|
page:
|
|
type: integer
|
|
size:
|
|
type: integer
|
|
totalPages:
|
|
type: integer
|
|
required: [list, total, page, size, totalPages]
|
|
|
|
# ---------- 枚举 ----------
|
|
ArticleStatus:
|
|
type: string
|
|
enum: [DRAFT, PUBLISHED, ARCHIVED]
|
|
description: |
|
|
- DRAFT: 草稿,仅后台可见
|
|
- PUBLISHED: 已发布,前台可见
|
|
- ARCHIVED: 已归档,前台不可见但保留数据
|
|
|
|
UserRole:
|
|
type: string
|
|
enum: [ADMIN, EDITOR, VISITOR]
|
|
|
|
# ---------- Auth ----------
|
|
RegisterRequest:
|
|
type: object
|
|
properties:
|
|
username:
|
|
type: string
|
|
minLength: 3
|
|
maxLength: 50
|
|
password:
|
|
type: string
|
|
minLength: 6
|
|
maxLength: 100
|
|
email:
|
|
type: string
|
|
format: email
|
|
required: [username, password]
|
|
|
|
LoginRequest:
|
|
type: object
|
|
properties:
|
|
username:
|
|
type: string
|
|
password:
|
|
type: string
|
|
required: [username, password]
|
|
|
|
RefreshTokenRequest:
|
|
type: object
|
|
properties:
|
|
refreshToken:
|
|
type: string
|
|
required: [refreshToken]
|
|
|
|
TokenPair:
|
|
type: object
|
|
properties:
|
|
accessToken:
|
|
type: string
|
|
refreshToken:
|
|
type: string
|
|
expiresIn:
|
|
type: integer
|
|
description: Access Token 有效期(秒)
|
|
required: [accessToken, refreshToken, expiresIn]
|
|
|
|
# ---------- Article ----------
|
|
ArticleCreateRequest:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
maxLength: 200
|
|
summary:
|
|
type: string
|
|
maxLength: 500
|
|
content:
|
|
type: string
|
|
coverImage:
|
|
type: string
|
|
description: 封面图 URL
|
|
tagIds:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
format: int64
|
|
required: [title, content]
|
|
|
|
ArticleUpdateRequest:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
maxLength: 200
|
|
summary:
|
|
type: string
|
|
maxLength: 500
|
|
content:
|
|
type: string
|
|
coverImage:
|
|
type: string
|
|
tagIds:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
format: int64
|
|
required: [title, content]
|
|
|
|
ArticleListItem:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
format: int64
|
|
title:
|
|
type: string
|
|
slug:
|
|
type: string
|
|
summary:
|
|
type: string
|
|
coverImage:
|
|
type: string
|
|
status:
|
|
$ref: '#/components/schemas/ArticleStatus'
|
|
publishedAt:
|
|
type: string
|
|
format: date-time
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
authorName:
|
|
type: string
|
|
tagNames:
|
|
type: array
|
|
items:
|
|
type: string
|
|
starCount:
|
|
type: integer
|
|
format: int64
|
|
description: 点赞数
|
|
hasStarred:
|
|
type: boolean
|
|
nullable: true
|
|
description: 当前用户是否已点赞(null 表示未登录)
|
|
required: [id, title, slug, status, createdAt, authorName, tagNames, starCount]
|
|
|
|
ArticleDetail:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
format: int64
|
|
title:
|
|
type: string
|
|
slug:
|
|
type: string
|
|
summary:
|
|
type: string
|
|
content:
|
|
type: string
|
|
coverImage:
|
|
type: string
|
|
status:
|
|
$ref: '#/components/schemas/ArticleStatus'
|
|
viewCount:
|
|
type: integer
|
|
format: int64
|
|
publishedAt:
|
|
type: string
|
|
format: date-time
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
updatedAt:
|
|
type: string
|
|
format: date-time
|
|
authorName:
|
|
type: string
|
|
tagNames:
|
|
type: array
|
|
items:
|
|
type: string
|
|
starCount:
|
|
type: integer
|
|
format: int64
|
|
description: 点赞数
|
|
hasStarred:
|
|
type: boolean
|
|
nullable: true
|
|
description: 当前用户是否已点赞(null 表示未登录)
|
|
required: [id, title, slug, content, status, viewCount, createdAt, updatedAt, authorName, tagNames, starCount]
|
|
|
|
OpenGraphMeta:
|
|
type: object
|
|
properties:
|
|
title:
|
|
type: string
|
|
description:
|
|
type: string
|
|
image:
|
|
type: string
|
|
url:
|
|
type: string
|
|
type:
|
|
type: string
|
|
default: article
|
|
required: [title, description, url, type]
|
|
|
|
# ---------- Tag ----------
|
|
Tag:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
format: int64
|
|
name:
|
|
type: string
|
|
slug:
|
|
type: string
|
|
description:
|
|
type: string
|
|
articleCount:
|
|
type: integer
|
|
description: 关联文章数量(查询时计算)
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
required: [id, name, slug, articleCount, createdAt]
|
|
|
|
TagCreateRequest:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
maxLength: 50
|
|
description:
|
|
type: string
|
|
maxLength: 200
|
|
required: [name]
|
|
|
|
TagUpdateRequest:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
maxLength: 50
|
|
description:
|
|
type: string
|
|
maxLength: 200
|
|
required: [name]
|
|
|
|
# ---------- Media ----------
|
|
StoredFile:
|
|
type: object
|
|
properties:
|
|
originalName:
|
|
type: string
|
|
storedPath:
|
|
type: string
|
|
url:
|
|
type: string
|
|
thumbnailUrl:
|
|
type: string
|
|
description: 图片缩略图 URL(非图片为 null)
|
|
size:
|
|
type: integer
|
|
format: int64
|
|
contentType:
|
|
type: string
|
|
required: [originalName, storedPath, url, size]
|
|
|
|
# ---------- User ----------
|
|
UserInfo:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
format: int64
|
|
username:
|
|
type: string
|
|
email:
|
|
type: string
|
|
avatar:
|
|
type: string
|
|
role:
|
|
$ref: '#/components/schemas/UserRole'
|
|
enabled:
|
|
type: boolean
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
required: [id, username, role, enabled, createdAt]
|
|
|
|
# ---------- Comment ----------
|
|
CommentStatus:
|
|
type: string
|
|
enum: [PENDING, APPROVED, REJECTED]
|
|
description: |
|
|
- PENDING: 待审核
|
|
- APPROVED: 已通过,前台可见
|
|
- REJECTED: 已驳回
|
|
|
|
CommentSubmitRequest:
|
|
type: object
|
|
properties:
|
|
parentId:
|
|
type: integer
|
|
format: int64
|
|
description: 父评论 ID(回复场景,可空)
|
|
authorName:
|
|
type: string
|
|
maxLength: 100
|
|
authorEmail:
|
|
type: string
|
|
format: email
|
|
content:
|
|
type: string
|
|
maxLength: 2000
|
|
required: [authorName, content]
|
|
|
|
CommentResponse:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
format: int64
|
|
articleId:
|
|
type: integer
|
|
format: int64
|
|
parentId:
|
|
type: integer
|
|
format: int64
|
|
authorName:
|
|
type: string
|
|
authorEmail:
|
|
type: string
|
|
content:
|
|
type: string
|
|
status:
|
|
$ref: '#/components/schemas/CommentStatus'
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
starCount:
|
|
type: integer
|
|
format: int64
|
|
description: 评论点赞数
|
|
hasStarred:
|
|
type: boolean
|
|
nullable: true
|
|
description: 当前用户是否已点赞(null 表示未登录)
|
|
required: [id, articleId, authorName, content, status, createdAt]
|
|
|
|
# ---------- User Admin ----------
|
|
UpdateRoleRequest:
|
|
type: object
|
|
properties:
|
|
role:
|
|
$ref: '#/components/schemas/UserRole'
|
|
required: [role]
|
|
|
|
UpdateStatusRequest:
|
|
type: object
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
required: [enabled]
|
|
|
|
# ---------- 包装体实例化 ----------
|
|
ResponseString:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
type: string
|
|
|
|
ResponseVoid:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
type: "null"
|
|
|
|
ResponseTokenPair:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/TokenPair'
|
|
|
|
ResponseArticleDetail:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/ArticleDetail'
|
|
|
|
ResponseOpenGraphMeta:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/OpenGraphMeta'
|
|
|
|
ResponsePageArticleListItem:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
allOf:
|
|
- $ref: '#/components/schemas/PageResult'
|
|
properties:
|
|
list:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ArticleListItem'
|
|
|
|
ResponseListArticleListItem:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ArticleListItem'
|
|
|
|
ResponseTag:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/Tag'
|
|
|
|
ResponseListTagWithCount:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Tag'
|
|
|
|
ResponseStoredFile:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/StoredFile'
|
|
|
|
ResponsePageUserInfo:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
allOf:
|
|
- $ref: '#/components/schemas/PageResult'
|
|
properties:
|
|
list:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/UserInfo'
|
|
|
|
ResponseComment:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/CommentResponse'
|
|
|
|
ResponseListComment:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/CommentResponse'
|
|
|
|
ResponseUserInfo:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/UserInfo'
|
|
|
|
ResponsePageComment:
|
|
allOf:
|
|
- $ref: '#/components/schemas/Response'
|
|
properties:
|
|
data:
|
|
allOf:
|
|
- $ref: '#/components/schemas/PageResult'
|
|
properties:
|
|
list:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/CommentResponse'
|