2026-09-17 17:04:12 +08:00
|
|
|
|
openapi: 3.1.0
|
|
|
|
|
|
info:
|
|
|
|
|
|
title: photo-live
|
|
|
|
|
|
version: 0.1.0
|
|
|
|
|
|
license:
|
|
|
|
|
|
name: UNLICENSED
|
|
|
|
|
|
identifier: UNLICENSED
|
|
|
|
|
|
description: |
|
|
|
|
|
|
photo-live 直播相册系统 API 契约(单一事实来源)。
|
|
|
|
|
|
|
|
|
|
|
|
- 类型经 `openapi-typescript` 生成并提交入库(`src/generated/openapi.d.ts`),
|
|
|
|
|
|
三端(services/api、apps/admin、apps/viewer)直接消费生成类型,不自行跑 gen。
|
|
|
|
|
|
- 错误响应使用稳定 `code`(见 `components.schemas.Error` 的枚举,与
|
|
|
|
|
|
`src/errors.ts` 的 `ErrorCodes` 一一对应),客户端按 code 映射多语言文案,
|
|
|
|
|
|
`message` 仅供诊断。
|
|
|
|
|
|
- 列表接口统一游标分页,元信息见 `components.schemas.CursorPageMeta`。
|
2026-09-17 17:31:11 +08:00
|
|
|
|
- 业务端点一律 Bearer 认证;`/public/**` 匿名访问(`security: []`)。
|
|
|
|
|
|
- 状态码通用映射:401 → AUTH_TOKEN_EXPIRED、500 → INTERNAL_ERROR;
|
|
|
|
|
|
其余状态码对应的 code 在各响应的 description 中标注。
|
|
|
|
|
|
- 多语言内容按「请求 locale → 相册 defaultLocale」回退解析为单语言对象,
|
|
|
|
|
|
响应携带 `resolvedLocale` 供界面判断实际语言。
|
2026-09-17 17:04:12 +08:00
|
|
|
|
|
|
|
|
|
|
servers:
|
|
|
|
|
|
- url: /v1
|
|
|
|
|
|
|
|
|
|
|
|
tags:
|
|
|
|
|
|
- name: auth
|
|
|
|
|
|
description: 密码登录会话(签发、滑动续期、退出)
|
2026-09-17 17:31:11 +08:00
|
|
|
|
- name: albums
|
|
|
|
|
|
description: 相册创建、列表、详情与配置(工作人员)
|
|
|
|
|
|
- name: members
|
|
|
|
|
|
description: 相册成员管理(创建者或管理员)
|
|
|
|
|
|
- name: categories
|
|
|
|
|
|
description: 相册分类管理(创建者或管理员)
|
|
|
|
|
|
- name: uploads
|
|
|
|
|
|
description: 直传任务初始化、授权续签、完成核验与会话记录
|
|
|
|
|
|
- name: photos
|
|
|
|
|
|
description: 照片可见性调整与软删除(工作人员)
|
|
|
|
|
|
- name: public
|
|
|
|
|
|
description: 观众匿名只读(相册信息与公开照片)
|
2026-09-17 17:04:12 +08:00
|
|
|
|
|
|
|
|
|
|
paths:
|
2026-09-17 17:31:11 +08:00
|
|
|
|
# ─────────────────────────── auth ───────────────────────────
|
|
|
|
|
|
|
2026-09-17 17:04:12 +08:00
|
|
|
|
/auth/password:
|
|
|
|
|
|
post:
|
|
|
|
|
|
operationId: loginWithPassword
|
|
|
|
|
|
tags: [auth]
|
|
|
|
|
|
summary: 密码登录
|
|
|
|
|
|
description: 校验账号密码,签发会话令牌。
|
|
|
|
|
|
security: []
|
|
|
|
|
|
requestBody:
|
|
|
|
|
|
required: true
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/LoginRequest'
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 登录成功,返回会话令牌与过期时间。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/LoginResponse'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'400':
|
|
|
|
|
|
description: 参数校验失败(VALIDATION_FAILED,经全局校验管道)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
2026-09-17 17:04:12 +08:00
|
|
|
|
'401':
|
2026-09-17 17:31:11 +08:00
|
|
|
|
description: 账号或密码错误(AUTH_INVALID_CREDENTIALS)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
2026-09-17 17:04:12 +08:00
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:04:12 +08:00
|
|
|
|
|
|
|
|
|
|
/auth/refresh:
|
|
|
|
|
|
post:
|
|
|
|
|
|
operationId: refreshSession
|
|
|
|
|
|
tags: [auth]
|
|
|
|
|
|
summary: 会话滑动续期
|
|
|
|
|
|
description: 携带有效 Bearer 令牌滑动续期,返回新的过期时间。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 续期成功。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/RefreshResponse'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'400':
|
|
|
|
|
|
description: 参数校验失败(VALIDATION_FAILED,经全局校验管道)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
2026-09-17 17:04:12 +08:00
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:04:12 +08:00
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:04:12 +08:00
|
|
|
|
|
|
|
|
|
|
/auth/logout:
|
|
|
|
|
|
post:
|
|
|
|
|
|
operationId: logout
|
|
|
|
|
|
tags: [auth]
|
|
|
|
|
|
summary: 退出登录
|
|
|
|
|
|
description: 使当前 Bearer 令牌失效。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'204':
|
|
|
|
|
|
description: 已退出,无响应体。
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'400':
|
|
|
|
|
|
description: 请求体不可解析(VALIDATION_FAILED,经全局校验管道)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
# ─────────────────────────── albums ───────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
/albums:
|
|
|
|
|
|
post:
|
|
|
|
|
|
operationId: createAlbum
|
|
|
|
|
|
tags: [albums]
|
|
|
|
|
|
summary: 创建相册
|
|
|
|
|
|
description: |
|
|
|
|
|
|
创建相册并写入多语言内容;创建者自动成为 owner 成员。
|
|
|
|
|
|
初始默认值:uploadEnabled/publicEnabled/downloadEnabled=true、
|
|
|
|
|
|
originalDownloadEnabled=false、status=active、watermarkVersion=0。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
requestBody:
|
|
|
|
|
|
required: true
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/AlbumCreateRequest'
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'201':
|
|
|
|
|
|
description: 相册已创建(新相册 categories 为空数组)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Album'
|
|
|
|
|
|
'400':
|
|
|
|
|
|
description: 参数校验失败(VALIDATION_FAILED)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
get:
|
|
|
|
|
|
operationId: listAlbums
|
|
|
|
|
|
tags: [albums]
|
|
|
|
|
|
summary: 相册列表
|
|
|
|
|
|
description: 当前用户可见(参与)的相册列表;管理员可见全部。按创建时间倒序。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/CursorQuery'
|
|
|
|
|
|
- name: limit
|
|
|
|
|
|
in: query
|
|
|
|
|
|
description: 每页条数。
|
|
|
|
|
|
schema:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
minimum: 1
|
|
|
|
|
|
maximum: 100
|
|
|
|
|
|
default: 20
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 相册列表页。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/AlbumList'
|
|
|
|
|
|
'400':
|
|
|
|
|
|
description: 查询参数校验失败(VALIDATION_FAILED)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
/albums/{albumId}:
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/AlbumId'
|
|
|
|
|
|
get:
|
|
|
|
|
|
operationId: getAlbum
|
|
|
|
|
|
tags: [albums]
|
|
|
|
|
|
summary: 相册详情
|
|
|
|
|
|
description: 相册完整配置、多语言内容与分类列表。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 相册详情。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Album'
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'404':
|
|
|
|
|
|
description: 相册不存在,或当前用户非成员不可见(ALBUM_NOT_FOUND,避免枚举)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
patch:
|
|
|
|
|
|
operationId: updateAlbum
|
|
|
|
|
|
tags: [albums]
|
|
|
|
|
|
summary: 更新相册配置
|
|
|
|
|
|
description: |
|
|
|
|
|
|
部分更新:仅提交的字段被修改,各开关互相独立。
|
|
|
|
|
|
translations 为全量替换(须包含 defaultLocale 对应条目)。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
requestBody:
|
|
|
|
|
|
required: true
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/AlbumUpdateRequest'
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 更新后的相册详情。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Album'
|
|
|
|
|
|
'400':
|
|
|
|
|
|
description: 参数校验失败(VALIDATION_FAILED)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'403':
|
|
|
|
|
|
description: 仅创建者或管理员可修改(AUTH_FORBIDDEN)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'404':
|
|
|
|
|
|
description: 相册不存在,或当前用户不可见(ALBUM_NOT_FOUND)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
# ─────────────────────────── members ───────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
/albums/{albumId}/members:
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/AlbumId'
|
|
|
|
|
|
post:
|
|
|
|
|
|
operationId: addAlbumMember
|
|
|
|
|
|
tags: [members]
|
|
|
|
|
|
summary: 添加相册成员
|
|
|
|
|
|
description: 将已开通的同事添加为协作者;仅创建者或管理员可操作。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
requestBody:
|
|
|
|
|
|
required: true
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/MemberAddRequest'
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'201':
|
|
|
|
|
|
description: 成员已添加。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Member'
|
|
|
|
|
|
'400':
|
|
|
|
|
|
description: 参数校验失败(VALIDATION_FAILED)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'403':
|
|
|
|
|
|
description: 仅创建者或管理员可管理成员(AUTH_FORBIDDEN)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'404':
|
|
|
|
|
|
description: 相册不存在,或当前用户不可见(ALBUM_NOT_FOUND)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'409':
|
|
|
|
|
|
description: 该用户已是相册成员(MEMBER_CONFLICT)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
get:
|
|
|
|
|
|
operationId: listAlbumMembers
|
|
|
|
|
|
tags: [members]
|
|
|
|
|
|
summary: 相册成员列表
|
|
|
|
|
|
description: 相册全部成员(含 owner)。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/CursorQuery'
|
|
|
|
|
|
- name: limit
|
|
|
|
|
|
in: query
|
|
|
|
|
|
description: 每页条数。
|
|
|
|
|
|
schema:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
minimum: 1
|
|
|
|
|
|
maximum: 100
|
|
|
|
|
|
default: 20
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 成员列表页。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/MemberList'
|
|
|
|
|
|
'400':
|
|
|
|
|
|
description: 查询参数校验失败(VALIDATION_FAILED)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'404':
|
|
|
|
|
|
description: 相册不存在,或当前用户不可见(ALBUM_NOT_FOUND)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
/albums/{albumId}/members/{userId}:
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/AlbumId'
|
|
|
|
|
|
- $ref: '#/components/parameters/UserId'
|
|
|
|
|
|
delete:
|
|
|
|
|
|
operationId: removeAlbumMember
|
|
|
|
|
|
tags: [members]
|
|
|
|
|
|
summary: 移除相册成员
|
|
|
|
|
|
description: |
|
|
|
|
|
|
移除协作者;仅创建者或管理员可操作。不能移除创建者(403)。
|
|
|
|
|
|
目标成员不存在时幂等返回 204。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'204':
|
|
|
|
|
|
description: 已移除,无响应体。
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'403':
|
|
|
|
|
|
description: 无管理权限,或试图移除创建者(AUTH_FORBIDDEN)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'404':
|
|
|
|
|
|
description: 相册不存在,或当前用户不可见(ALBUM_NOT_FOUND)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
# ─────────────────────────── categories ───────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
/albums/{albumId}/categories:
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/AlbumId'
|
|
|
|
|
|
post:
|
|
|
|
|
|
operationId: createCategory
|
|
|
|
|
|
tags: [categories]
|
|
|
|
|
|
summary: 创建分类
|
|
|
|
|
|
description: 在相册下创建分类;仅创建者或管理员可操作。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
requestBody:
|
|
|
|
|
|
required: true
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/CategoryCreateRequest'
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'201':
|
|
|
|
|
|
description: 分类已创建。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Category'
|
|
|
|
|
|
'400':
|
|
|
|
|
|
description: 参数校验失败(VALIDATION_FAILED)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'403':
|
|
|
|
|
|
description: 仅创建者或管理员可管理分类(AUTH_FORBIDDEN)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'404':
|
|
|
|
|
|
description: 相册不存在,或当前用户不可见(ALBUM_NOT_FOUND)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
/categories/{categoryId}:
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/CategoryId'
|
|
|
|
|
|
patch:
|
|
|
|
|
|
operationId: updateCategory
|
|
|
|
|
|
tags: [categories]
|
|
|
|
|
|
summary: 更新分类
|
|
|
|
|
|
description: 部分更新;translations 为全量替换。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
requestBody:
|
|
|
|
|
|
required: true
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/CategoryUpdateRequest'
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 更新后的分类。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Category'
|
|
|
|
|
|
'400':
|
|
|
|
|
|
description: 参数校验失败(VALIDATION_FAILED)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'403':
|
|
|
|
|
|
description: 无所属相册的管理权限(AUTH_FORBIDDEN)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'404':
|
|
|
|
|
|
description: 分类不存在,或所属相册不存在/不可见(ALBUM_NOT_FOUND)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
delete:
|
|
|
|
|
|
operationId: deleteCategory
|
|
|
|
|
|
tags: [categories]
|
|
|
|
|
|
summary: 删除分类
|
|
|
|
|
|
description: 删除分类(分类下仍有照片时是否允许删除由服务端策略决定,400 拒绝)。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'204':
|
|
|
|
|
|
description: 已删除,无响应体。
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'403':
|
|
|
|
|
|
description: 无所属相册的管理权限(AUTH_FORBIDDEN)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'404':
|
|
|
|
|
|
description: 分类不存在,或所属相册不存在/不可见(ALBUM_NOT_FOUND)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
# ─────────────────────────── uploads ───────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
/uploads:
|
|
|
|
|
|
post:
|
|
|
|
|
|
operationId: initUpload
|
|
|
|
|
|
tags: [uploads]
|
|
|
|
|
|
summary: 初始化上传任务
|
|
|
|
|
|
description: |
|
|
|
|
|
|
幂等初始化:预创建上传会话与照片 ID,返回 staging 对象的临时直传凭证。
|
|
|
|
|
|
相同 clientTaskId 且参数一致时返回原会话,不重复创建照片;
|
|
|
|
|
|
参数不一致时返回 409(UPLOAD_SESSION_CONFLICT)。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
requestBody:
|
|
|
|
|
|
required: true
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/UploadInitRequest'
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'201':
|
|
|
|
|
|
description: 上传会话已创建(幂等重复调用返回原会话)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/UploadInitResponse'
|
|
|
|
|
|
'400':
|
|
|
|
|
|
description: 参数校验失败(VALIDATION_FAILED):文件超过大小限额或类型不接受。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
2026-09-17 17:04:12 +08:00
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'403':
|
|
|
|
|
|
description: 无该相册的上传权限(AUTH_FORBIDDEN)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'409':
|
|
|
|
|
|
description: |
|
|
|
|
|
|
相册已关闭上传(ALBUM_UPLOAD_DISABLED),或同 clientTaskId 已存在
|
|
|
|
|
|
且参数不一致(UPLOAD_SESSION_CONFLICT)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
get:
|
|
|
|
|
|
operationId: listUploads
|
|
|
|
|
|
tags: [uploads]
|
|
|
|
|
|
summary: 上传会话记录
|
|
|
|
|
|
description: 当前用户的上传会话历史(新在前),用于任务队列恢复与状态展示。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/CursorQuery'
|
|
|
|
|
|
- name: limit
|
|
|
|
|
|
in: query
|
|
|
|
|
|
description: 每页条数。
|
|
|
|
|
|
schema:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
minimum: 1
|
|
|
|
|
|
maximum: 100
|
|
|
|
|
|
default: 20
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 会话记录列表页。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/UploadSessionList'
|
|
|
|
|
|
'400':
|
|
|
|
|
|
description: 查询参数校验失败(VALIDATION_FAILED)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
/uploads/{uploadId}/renew:
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/UploadId'
|
|
|
|
|
|
post:
|
|
|
|
|
|
operationId: renewUploadCredential
|
|
|
|
|
|
tags: [uploads]
|
|
|
|
|
|
summary: 续签上传凭证
|
|
|
|
|
|
description: 为仍处于 pending 状态的会话重新签发直传凭证(结构同初始化响应)。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 新凭证已签发(credential 为新值,其余字段回显原会话)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/UploadInitResponse'
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'403':
|
|
|
|
|
|
description: 无权操作该会话或会话不存在(AUTH_FORBIDDEN,不区分以避免枚举)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'409':
|
|
|
|
|
|
description: |
|
|
|
|
|
|
相册已关闭上传(ALBUM_UPLOAD_DISABLED),或会话状态不允许续签
|
|
|
|
|
|
(已完成/取消/过期,UPLOAD_SESSION_CONFLICT)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
/uploads/{uploadId}/complete:
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/UploadId'
|
|
|
|
|
|
post:
|
|
|
|
|
|
operationId: completeUpload
|
|
|
|
|
|
tags: [uploads]
|
|
|
|
|
|
summary: 完成核验
|
|
|
|
|
|
description: |
|
|
|
|
|
|
核验 staging 对象(存在性、字节数与可用完整性信息)后进入处理流水线。
|
|
|
|
|
|
幂等:核验通过的会话重复调用返回相同结果。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 核验通过,照片进入处理流水线。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/UploadCompleteResponse'
|
|
|
|
|
|
'400':
|
|
|
|
|
|
description: |
|
|
|
|
|
|
核验失败(UPLOAD_VERIFY_FAILED):对象缺失、字节数与申明不符
|
|
|
|
|
|
或完整性信息不可用。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'403':
|
|
|
|
|
|
description: 无权操作该会话或会话不存在(AUTH_FORBIDDEN,不区分以避免枚举)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'409':
|
|
|
|
|
|
description: 会话状态不允许完成(已取消或已过期,UPLOAD_SESSION_CONFLICT)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
# ─────────────────────────── photos ───────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
/photos/{photoId}:
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/PhotoId'
|
|
|
|
|
|
patch:
|
|
|
|
|
|
operationId: updatePhoto
|
|
|
|
|
|
tags: [photos]
|
|
|
|
|
|
summary: 调整照片可见性
|
|
|
|
|
|
description: 在 hidden 与 published 间切换(隐藏/恢复发布);按相册角色与上传人共同判定权限。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
requestBody:
|
|
|
|
|
|
required: true
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/PhotoVisibilityUpdateRequest'
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 更新后的照片记录。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/PhotoRecord'
|
|
|
|
|
|
'400':
|
|
|
|
|
|
description: 参数校验失败(VALIDATION_FAILED,visibility 取值非法)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'403':
|
|
|
|
|
|
description: 无该照片的管理权限(AUTH_FORBIDDEN)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'404':
|
|
|
|
|
|
description: 照片不存在(PHOTO_NOT_FOUND)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
delete:
|
|
|
|
|
|
operationId: deletePhoto
|
|
|
|
|
|
tags: [photos]
|
|
|
|
|
|
summary: 软删除照片
|
|
|
|
|
|
description: 标记 deleted(软删除),公开端点即刻不可见;物理删除走独立运维流程。
|
|
|
|
|
|
security:
|
|
|
|
|
|
- bearerAuth: []
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'204':
|
|
|
|
|
|
description: 已软删除,无响应体。
|
|
|
|
|
|
'401':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/Unauthorized'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
'403':
|
|
|
|
|
|
description: 无该照片的管理权限(AUTH_FORBIDDEN)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'404':
|
|
|
|
|
|
description: 照片不存在(PHOTO_NOT_FOUND)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
# ─────────────────────────── public ───────────────────────────
|
|
|
|
|
|
|
|
|
|
|
|
/public/albums/{token}:
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/AlbumPublicToken'
|
|
|
|
|
|
get:
|
|
|
|
|
|
operationId: getPublicAlbum
|
|
|
|
|
|
tags: [public]
|
|
|
|
|
|
summary: 公开相册信息
|
|
|
|
|
|
description: |
|
|
|
|
|
|
观众页入口:按「请求 locale → defaultLocale」回退解析为单语言对象。
|
|
|
|
|
|
publicToken 不可枚举,但持有链接者均可访问。
|
|
|
|
|
|
security: []
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/LocaleQuery'
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 相册公开信息。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/PublicAlbum'
|
|
|
|
|
|
'400':
|
2026-09-17 18:11:21 +08:00
|
|
|
|
description: 查询参数校验失败(VALIDATION_FAILED;locale 取值不支持时不报错,按 defaultLocale 回退)。
|
2026-09-17 17:31:11 +08:00
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'404':
|
|
|
|
|
|
description: 相册不存在或未公开(ALBUM_NOT_PUBLIC,不区分以避免枚举)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
/public/albums/{token}/photos:
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/AlbumPublicToken'
|
|
|
|
|
|
get:
|
|
|
|
|
|
operationId: listPublicPhotos
|
|
|
|
|
|
tags: [public]
|
|
|
|
|
|
summary: 公开照片列表
|
|
|
|
|
|
description: |
|
|
|
|
|
|
仅返回公开相册中 published 的照片,按 publishedAt 与 ID 稳定倒序游标分页。
|
|
|
|
|
|
签名 URL 为短期凭证,过期后凭同一入口刷新。
|
|
|
|
|
|
security: []
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- name: category
|
|
|
|
|
|
in: query
|
|
|
|
|
|
description: 分类 ID 过滤(来自 PublicAlbum.categories 的 id)。
|
|
|
|
|
|
schema:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
- $ref: '#/components/parameters/LocaleQuery'
|
|
|
|
|
|
- $ref: '#/components/parameters/CursorQuery'
|
|
|
|
|
|
- name: limit
|
|
|
|
|
|
in: query
|
|
|
|
|
|
description: 每页张数(技术实施方案 §7 建议 30-60)。
|
|
|
|
|
|
schema:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
minimum: 1
|
|
|
|
|
|
maximum: 60
|
|
|
|
|
|
default: 30
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 公开照片列表页。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/PublicPhotoList'
|
|
|
|
|
|
'400':
|
2026-09-17 18:11:21 +08:00
|
|
|
|
description: 查询参数校验失败(category/cursor/limit;locale 取值不支持时不报错,按 defaultLocale 回退)。
|
2026-09-17 17:31:11 +08:00
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'404':
|
|
|
|
|
|
description: 相册不存在或未公开(ALBUM_NOT_PUBLIC,不区分以避免枚举)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
/public/albums/{token}/photos/{photoId}:
|
|
|
|
|
|
parameters:
|
|
|
|
|
|
- $ref: '#/components/parameters/AlbumPublicToken'
|
|
|
|
|
|
- $ref: '#/components/parameters/PhotoId'
|
|
|
|
|
|
get:
|
|
|
|
|
|
operationId: getPublicPhoto
|
|
|
|
|
|
tags: [public]
|
|
|
|
|
|
summary: 公开单图
|
|
|
|
|
|
description: |
|
|
|
|
|
|
深度链接定位单图,同时作为签名 URL 过期后的刷新入口。
|
|
|
|
|
|
服务端校验相册与照片归属;隐藏/删除后的旧链接返回 404。
|
|
|
|
|
|
security: []
|
|
|
|
|
|
responses:
|
|
|
|
|
|
'200':
|
|
|
|
|
|
description: 单图信息(含新签名的 thumb/browse URL)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/PublicPhotoDetail'
|
|
|
|
|
|
'404':
|
|
|
|
|
|
description: |
|
|
|
|
|
|
相册不存在或未公开(ALBUM_NOT_PUBLIC),或照片不存在、未发布、
|
|
|
|
|
|
不属于该相册(PHOTO_NOT_PUBLIC)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
2026-09-17 17:04:12 +08:00
|
|
|
|
'500':
|
2026-09-17 18:06:54 +08:00
|
|
|
|
$ref: '#/components/responses/InternalError'
|
2026-09-17 17:04:12 +08:00
|
|
|
|
|
|
|
|
|
|
components:
|
|
|
|
|
|
securitySchemes:
|
|
|
|
|
|
bearerAuth:
|
|
|
|
|
|
type: http
|
|
|
|
|
|
scheme: bearer
|
|
|
|
|
|
|
2026-09-17 17:31:11 +08:00
|
|
|
|
parameters:
|
|
|
|
|
|
AlbumId:
|
|
|
|
|
|
name: albumId
|
|
|
|
|
|
in: path
|
|
|
|
|
|
required: true
|
|
|
|
|
|
description: 相册 ID。
|
|
|
|
|
|
schema:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
UserId:
|
|
|
|
|
|
name: userId
|
|
|
|
|
|
in: path
|
|
|
|
|
|
required: true
|
|
|
|
|
|
description: 用户 ID。
|
|
|
|
|
|
schema:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
CategoryId:
|
|
|
|
|
|
name: categoryId
|
|
|
|
|
|
in: path
|
|
|
|
|
|
required: true
|
|
|
|
|
|
description: 分类 ID。
|
|
|
|
|
|
schema:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
UploadId:
|
|
|
|
|
|
name: uploadId
|
|
|
|
|
|
in: path
|
|
|
|
|
|
required: true
|
|
|
|
|
|
description: 上传会话 ID。
|
|
|
|
|
|
schema:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
PhotoId:
|
|
|
|
|
|
name: photoId
|
|
|
|
|
|
in: path
|
|
|
|
|
|
required: true
|
|
|
|
|
|
description: 照片 ID。
|
|
|
|
|
|
schema:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
AlbumPublicToken:
|
|
|
|
|
|
name: token
|
|
|
|
|
|
in: path
|
|
|
|
|
|
required: true
|
|
|
|
|
|
description: 相册公开令牌(不可枚举,持有即可访问)。
|
|
|
|
|
|
schema:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
CursorQuery:
|
|
|
|
|
|
name: cursor
|
|
|
|
|
|
in: query
|
|
|
|
|
|
description: 分页游标(上一页响应的 nextCursor)。
|
|
|
|
|
|
schema:
|
|
|
|
|
|
type: string
|
2026-09-17 18:06:54 +08:00
|
|
|
|
maxLength: 512
|
2026-09-17 17:31:11 +08:00
|
|
|
|
LocaleQuery:
|
|
|
|
|
|
name: locale
|
|
|
|
|
|
in: query
|
2026-09-17 18:11:21 +08:00
|
|
|
|
description: 请求语言;缺省或取值不支持时按相册 defaultLocale 回退(不报 400,响应 resolvedLocale 指示实际返回语言)。
|
2026-09-17 17:31:11 +08:00
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Locale'
|
2026-09-17 17:04:12 +08:00
|
|
|
|
|
2026-09-17 18:06:54 +08:00
|
|
|
|
responses:
|
|
|
|
|
|
Unauthorized:
|
|
|
|
|
|
description: 未认证:令牌缺失、无效或已过期(AUTH_TOKEN_EXPIRED)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
InternalError:
|
|
|
|
|
|
description: 服务器内部错误(INTERNAL_ERROR)。
|
|
|
|
|
|
content:
|
|
|
|
|
|
application/json:
|
|
|
|
|
|
schema:
|
|
|
|
|
|
$ref: '#/components/schemas/Error'
|
|
|
|
|
|
|
2026-09-17 17:04:12 +08:00
|
|
|
|
schemas:
|
2026-09-17 17:31:11 +08:00
|
|
|
|
# ── 通用 ──
|
|
|
|
|
|
|
2026-09-17 17:04:12 +08:00
|
|
|
|
Error:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [code, message, requestId]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
code:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 稳定错误码,与 src/errors.ts 的 ErrorCodes 一一对应。
|
|
|
|
|
|
enum:
|
|
|
|
|
|
- AUTH_INVALID_CREDENTIALS
|
|
|
|
|
|
- AUTH_TOKEN_EXPIRED
|
|
|
|
|
|
- AUTH_FORBIDDEN
|
|
|
|
|
|
- ALBUM_NOT_FOUND
|
|
|
|
|
|
- ALBUM_NOT_PUBLIC
|
|
|
|
|
|
- ALBUM_UPLOAD_DISABLED
|
|
|
|
|
|
- MEMBER_CONFLICT
|
|
|
|
|
|
- UPLOAD_SESSION_CONFLICT
|
|
|
|
|
|
- UPLOAD_VERIFY_FAILED
|
|
|
|
|
|
- PHOTO_NOT_FOUND
|
|
|
|
|
|
- PHOTO_NOT_PUBLIC
|
|
|
|
|
|
- VALIDATION_FAILED
|
|
|
|
|
|
- INTERNAL_ERROR
|
|
|
|
|
|
message:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 服务器生成的可读消息(诊断用,不作为客户端展示文案依据)。
|
|
|
|
|
|
requestId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 请求追踪 ID。
|
|
|
|
|
|
|
|
|
|
|
|
CursorPageMeta:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [nextCursor, hasMore]
|
2026-09-17 18:06:54 +08:00
|
|
|
|
description: 游标分页元信息;各列表响应以 allOf 内嵌本结构(条目 schema 在业务端点中定义)。不变式:hasMore=true 当且仅当 nextCursor≠null,两者必须成对填充。
|
2026-09-17 17:04:12 +08:00
|
|
|
|
properties:
|
|
|
|
|
|
nextCursor:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 下一页游标;null 表示没有更多数据。
|
|
|
|
|
|
hasMore:
|
|
|
|
|
|
type: boolean
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 是否还有下一页。
|
|
|
|
|
|
|
2026-09-17 17:31:11 +08:00
|
|
|
|
Locale:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
description: P1a 支持的语言。
|
|
|
|
|
|
enum:
|
|
|
|
|
|
- zh-CN
|
|
|
|
|
|
- en
|
|
|
|
|
|
|
|
|
|
|
|
# ── 认证 ──
|
|
|
|
|
|
|
2026-09-17 17:04:12 +08:00
|
|
|
|
LoginRequest:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [account, password]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
account:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
description: 账号(用户名或邮箱)。
|
|
|
|
|
|
password:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
description: 密码。
|
|
|
|
|
|
LoginResponse:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [sessionToken, expiresAt]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
sessionToken:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 会话令牌(Bearer)。
|
|
|
|
|
|
expiresAt:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 会话过期时间。
|
|
|
|
|
|
RefreshResponse:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [expiresAt]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
expiresAt:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 续期后的过期时间。
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
# ── 相册 ──
|
|
|
|
|
|
|
|
|
|
|
|
AlbumTranslation:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [locale, title]
|
|
|
|
|
|
description: 相册多语言条目(创建/更新与响应共用;未填的可选字段存储为 null)。
|
|
|
|
|
|
properties:
|
|
|
|
|
|
locale:
|
|
|
|
|
|
$ref: '#/components/schemas/Locale'
|
|
|
|
|
|
title:
|
|
|
|
|
|
type: string
|
2026-09-17 18:06:54 +08:00
|
|
|
|
minLength: 1
|
2026-09-17 17:31:11 +08:00
|
|
|
|
description: 相册标题。
|
|
|
|
|
|
description:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
description: 相册描述。
|
|
|
|
|
|
venue:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
description: 场地名称。
|
|
|
|
|
|
address:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
description: 场地地址。
|
|
|
|
|
|
|
|
|
|
|
|
AlbumCreateRequest:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [translations, defaultLocale, startAt]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
translations:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
minItems: 1
|
|
|
|
|
|
description: 多语言内容;必须包含 defaultLocale 对应条目。
|
|
|
|
|
|
items:
|
|
|
|
|
|
$ref: '#/components/schemas/AlbumTranslation'
|
|
|
|
|
|
defaultLocale:
|
|
|
|
|
|
$ref: '#/components/schemas/Locale'
|
|
|
|
|
|
startAt:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
description: 活动开始时间(UTC 存储,展示按 timezone)。
|
|
|
|
|
|
endAt:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
description: 活动结束时间;null 或缺省表示未定。
|
|
|
|
|
|
timezone:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
default: Asia/Shanghai
|
|
|
|
|
|
description: 活动 IANA 时区。
|
|
|
|
|
|
examples:
|
|
|
|
|
|
- Asia/Shanghai
|
|
|
|
|
|
downloadEnabled:
|
|
|
|
|
|
type: boolean
|
|
|
|
|
|
default: true
|
|
|
|
|
|
description: 允许下载浏览版本。
|
|
|
|
|
|
originalDownloadEnabled:
|
|
|
|
|
|
type: boolean
|
|
|
|
|
|
default: false
|
|
|
|
|
|
description: 允许下载原图。
|
|
|
|
|
|
|
|
|
|
|
|
AlbumUpdateRequest:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
minProperties: 1
|
|
|
|
|
|
description: 部分更新:仅提交的字段被修改,各开关互相独立;endAt 传 null 清除。
|
|
|
|
|
|
properties:
|
|
|
|
|
|
translations:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
minItems: 1
|
|
|
|
|
|
description: 全量替换多语言内容;须包含 defaultLocale 对应条目。
|
|
|
|
|
|
items:
|
|
|
|
|
|
$ref: '#/components/schemas/AlbumTranslation'
|
|
|
|
|
|
defaultLocale:
|
|
|
|
|
|
$ref: '#/components/schemas/Locale'
|
|
|
|
|
|
startAt:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
description: 活动开始时间。
|
|
|
|
|
|
endAt:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
description: 活动结束时间;null 清除。
|
|
|
|
|
|
timezone:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
description: 活动 IANA 时区。
|
|
|
|
|
|
uploadEnabled:
|
|
|
|
|
|
type: boolean
|
|
|
|
|
|
description: 是否允许新上传任务。
|
|
|
|
|
|
publicEnabled:
|
|
|
|
|
|
type: boolean
|
|
|
|
|
|
description: 是否公开可见。
|
|
|
|
|
|
downloadEnabled:
|
|
|
|
|
|
type: boolean
|
|
|
|
|
|
description: 允许下载浏览版本。
|
|
|
|
|
|
originalDownloadEnabled:
|
|
|
|
|
|
type: boolean
|
|
|
|
|
|
description: 允许下载原图。
|
|
|
|
|
|
|
|
|
|
|
|
AlbumSummary:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
description: 相册列表条目(完整开关与多语言标题,管理列表无需二次请求详情)。
|
|
|
|
|
|
required:
|
|
|
|
|
|
- id
|
|
|
|
|
|
- publicToken
|
|
|
|
|
|
- ownerId
|
|
|
|
|
|
- status
|
|
|
|
|
|
- defaultLocale
|
|
|
|
|
|
- timezone
|
|
|
|
|
|
- startAt
|
|
|
|
|
|
- endAt
|
|
|
|
|
|
- uploadEnabled
|
|
|
|
|
|
- publicEnabled
|
|
|
|
|
|
- downloadEnabled
|
|
|
|
|
|
- originalDownloadEnabled
|
|
|
|
|
|
- watermarkVersion
|
|
|
|
|
|
- translations
|
|
|
|
|
|
- createdAt
|
|
|
|
|
|
- updatedAt
|
|
|
|
|
|
properties:
|
|
|
|
|
|
id:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 相册 ID。
|
|
|
|
|
|
publicToken:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
2026-09-17 18:06:54 +08:00
|
|
|
|
pattern: '^[0-9a-z]{20,32}$'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
description: 公开访问令牌(不可枚举)。
|
|
|
|
|
|
ownerId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 创建者用户 ID。
|
|
|
|
|
|
status:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
default: active
|
2026-09-17 18:06:54 +08:00
|
|
|
|
description: 相册状态;offline 表示下线(停止公开访问与新授权签发)。
|
2026-09-17 17:31:11 +08:00
|
|
|
|
enum:
|
|
|
|
|
|
- active
|
2026-09-17 18:06:54 +08:00
|
|
|
|
- offline
|
2026-09-17 17:31:11 +08:00
|
|
|
|
defaultLocale:
|
|
|
|
|
|
$ref: '#/components/schemas/Locale'
|
|
|
|
|
|
timezone:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
description: 活动 IANA 时区。
|
|
|
|
|
|
startAt:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
description: 活动开始时间。
|
|
|
|
|
|
endAt:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
description: 活动结束时间;null 表示未定。
|
|
|
|
|
|
uploadEnabled:
|
|
|
|
|
|
type: boolean
|
|
|
|
|
|
description: 是否允许新上传任务。
|
|
|
|
|
|
publicEnabled:
|
|
|
|
|
|
type: boolean
|
|
|
|
|
|
description: 是否公开可见。
|
|
|
|
|
|
downloadEnabled:
|
|
|
|
|
|
type: boolean
|
|
|
|
|
|
description: 允许下载浏览版本。
|
|
|
|
|
|
originalDownloadEnabled:
|
|
|
|
|
|
type: boolean
|
|
|
|
|
|
description: 允许下载原图。
|
|
|
|
|
|
watermarkVersion:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
minimum: 0
|
|
|
|
|
|
default: 0
|
|
|
|
|
|
description: 当前水印配置版本。
|
|
|
|
|
|
translations:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
description: 各语言内容。
|
|
|
|
|
|
items:
|
|
|
|
|
|
$ref: '#/components/schemas/AlbumTranslation'
|
|
|
|
|
|
createdAt:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 创建时间。
|
|
|
|
|
|
updatedAt:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 最近更新时间。
|
|
|
|
|
|
|
|
|
|
|
|
AlbumList:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- $ref: '#/components/schemas/CursorPageMeta'
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
required: [items]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
items:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
items:
|
|
|
|
|
|
$ref: '#/components/schemas/AlbumSummary'
|
|
|
|
|
|
|
|
|
|
|
|
Album:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- $ref: '#/components/schemas/AlbumSummary'
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
required: [categories]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
categories:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
description: 相册分类(按 sortOrder 升序)。
|
|
|
|
|
|
items:
|
|
|
|
|
|
$ref: '#/components/schemas/Category'
|
|
|
|
|
|
|
|
|
|
|
|
# ── 成员 ──
|
|
|
|
|
|
|
|
|
|
|
|
MemberAddRequest:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [userId]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
userId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
description: 被添加用户的 ID(须为已开通账号)。
|
|
|
|
|
|
role:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
default: collaborator
|
|
|
|
|
|
description: 成员角色;P1a 仅协作者(owner 由创建流程产生)。
|
|
|
|
|
|
enum:
|
|
|
|
|
|
- collaborator
|
|
|
|
|
|
|
|
|
|
|
|
Member:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [userId, account, displayName, role, status]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
userId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 用户 ID。
|
|
|
|
|
|
account:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 登录账号。
|
|
|
|
|
|
displayName:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 展示姓名(来自用户资料同步)。
|
|
|
|
|
|
role:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 相册角色。
|
|
|
|
|
|
enum:
|
|
|
|
|
|
- owner
|
|
|
|
|
|
- collaborator
|
|
|
|
|
|
status:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 成员状态;P1a 仅 active,预留扩展。
|
|
|
|
|
|
enum:
|
|
|
|
|
|
- active
|
|
|
|
|
|
|
|
|
|
|
|
MemberList:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- $ref: '#/components/schemas/CursorPageMeta'
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
required: [items]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
items:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
items:
|
|
|
|
|
|
$ref: '#/components/schemas/Member'
|
|
|
|
|
|
|
|
|
|
|
|
# ── 分类 ──
|
|
|
|
|
|
|
|
|
|
|
|
CategoryTranslation:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [locale, name]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
locale:
|
|
|
|
|
|
$ref: '#/components/schemas/Locale'
|
|
|
|
|
|
name:
|
|
|
|
|
|
type: string
|
2026-09-17 18:06:54 +08:00
|
|
|
|
minLength: 1
|
2026-09-17 17:31:11 +08:00
|
|
|
|
description: 分类名称。
|
|
|
|
|
|
|
|
|
|
|
|
CategoryCreateRequest:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [translations]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
sortOrder:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
default: 0
|
|
|
|
|
|
description: 排序序号(升序)。
|
|
|
|
|
|
translations:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
minItems: 1
|
|
|
|
|
|
description: 分类多语言名称。
|
|
|
|
|
|
items:
|
|
|
|
|
|
$ref: '#/components/schemas/CategoryTranslation'
|
|
|
|
|
|
|
|
|
|
|
|
CategoryUpdateRequest:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
minProperties: 1
|
|
|
|
|
|
description: 部分更新;translations 为全量替换。
|
|
|
|
|
|
properties:
|
|
|
|
|
|
sortOrder:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
description: 排序序号(升序)。
|
|
|
|
|
|
translations:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
minItems: 1
|
|
|
|
|
|
description: 全量替换多语言名称。
|
|
|
|
|
|
items:
|
|
|
|
|
|
$ref: '#/components/schemas/CategoryTranslation'
|
|
|
|
|
|
|
|
|
|
|
|
Category:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [id, albumId, sortOrder, translations]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
id:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 分类 ID。
|
|
|
|
|
|
albumId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 所属相册 ID。
|
|
|
|
|
|
sortOrder:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
description: 排序序号(升序)。
|
|
|
|
|
|
translations:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
description: 各语言名称。
|
|
|
|
|
|
items:
|
|
|
|
|
|
$ref: '#/components/schemas/CategoryTranslation'
|
|
|
|
|
|
|
|
|
|
|
|
# ── 上传 ──
|
|
|
|
|
|
|
|
|
|
|
|
UploadSessionState:
|
|
|
|
|
|
type: string
|
2026-09-17 18:06:54 +08:00
|
|
|
|
description: |
|
|
|
|
|
|
上传会话状态(服务端视角;本地任务状态见技术实施方案 §5.5)。
|
|
|
|
|
|
会话没有 failed 状态:完成核验失败属于单次请求错误(UPLOAD_VERIFY_FAILED),
|
|
|
|
|
|
会话保持 pending 可重试;cancelled 为用户主动取消;
|
|
|
|
|
|
expired 为超过 expiresAt 未完成(核验时推导或由补偿扫描落定)。
|
2026-09-17 17:31:11 +08:00
|
|
|
|
enum:
|
|
|
|
|
|
- pending
|
|
|
|
|
|
- confirmed
|
|
|
|
|
|
- cancelled
|
|
|
|
|
|
- expired
|
|
|
|
|
|
|
|
|
|
|
|
PhotoProcessingState:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
description: 照片服务端处理状态(技术实施方案 §5.5「服务端处理」链路)。
|
|
|
|
|
|
enum:
|
|
|
|
|
|
- pending_upload
|
|
|
|
|
|
- uploaded
|
|
|
|
|
|
- processing
|
|
|
|
|
|
- ready
|
|
|
|
|
|
- processing_failed
|
|
|
|
|
|
|
|
|
|
|
|
PhotoVisibility:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
description: 照片对外可见性(技术实施方案 §5.5「对外可见性」;deleted 为软删除)。
|
|
|
|
|
|
enum:
|
|
|
|
|
|
- unpublished
|
|
|
|
|
|
- published
|
|
|
|
|
|
- hidden
|
|
|
|
|
|
- deleted
|
|
|
|
|
|
|
|
|
|
|
|
UploadInitRequest:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [albumId, clientTaskId, filename, bytes, contentType]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
albumId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
description: 目标相册 ID。
|
|
|
|
|
|
categoryId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
description: 目标分类 ID;缺省为相册默认分类。
|
|
|
|
|
|
clientTaskId:
|
|
|
|
|
|
type: string
|
2026-09-17 18:06:54 +08:00
|
|
|
|
maxLength: 128
|
2026-09-17 17:31:11 +08:00
|
|
|
|
description: 客户端任务幂等键;同一任务的重试必须复用(会话与照片 ID 均复用)。
|
|
|
|
|
|
filename:
|
|
|
|
|
|
type: string
|
2026-09-17 18:06:54 +08:00
|
|
|
|
maxLength: 255
|
2026-09-17 17:31:11 +08:00
|
|
|
|
description: 原始文件名(仅元数据,不作对象唯一标识)。
|
|
|
|
|
|
bytes:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
format: int64
|
|
|
|
|
|
minimum: 1
|
|
|
|
|
|
description: 申明文件字节数;完成核验时逐一比对。
|
|
|
|
|
|
contentType:
|
|
|
|
|
|
type: string
|
2026-09-17 18:06:54 +08:00
|
|
|
|
enum: [image/jpeg, image/png, image/heic]
|
|
|
|
|
|
description: MIME 类型白名单;image/heic 为暂定项,解码能力待 G2 真机验证后确认。
|
2026-09-17 17:31:11 +08:00
|
|
|
|
|
|
|
|
|
|
UploadCredential:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
description: staging 对象的临时直传凭证;仅可写入指定 objectKey,不可访问 originals/variants。
|
|
|
|
|
|
required: [mode, url, method, headers, expiresAt]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
mode:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
default: presigned
|
|
|
|
|
|
description: 凭证模式;P1a 仅预签名 URL,预留 STS 扩展。
|
|
|
|
|
|
enum:
|
|
|
|
|
|
- presigned
|
|
|
|
|
|
url:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 预签名上传 URL。
|
|
|
|
|
|
method:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 上传 HTTP 方法。
|
|
|
|
|
|
enum:
|
|
|
|
|
|
- PUT
|
|
|
|
|
|
headers:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 上传时必须携带的请求头(如 Content-Type)。
|
|
|
|
|
|
additionalProperties:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
expiresAt:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 凭证过期时间;过期后续签(renew)再重试。
|
|
|
|
|
|
|
|
|
|
|
|
UploadInitResponse:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [uploadId, photoId, objectKey, credential]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
uploadId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 上传会话 ID。
|
|
|
|
|
|
photoId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 预创建的照片 ID(重试复用,不重复建照片)。
|
|
|
|
|
|
objectKey:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: staging 对象键(photo-live/{env}/staging/{uploadId}/{photoId}.{ext})。
|
|
|
|
|
|
credential:
|
|
|
|
|
|
$ref: '#/components/schemas/UploadCredential'
|
|
|
|
|
|
|
|
|
|
|
|
UploadCompleteResponse:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [photoId, processingState]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
photoId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 照片 ID。
|
|
|
|
|
|
processingState:
|
|
|
|
|
|
$ref: '#/components/schemas/PhotoProcessingState'
|
|
|
|
|
|
|
|
|
|
|
|
UploadSessionPhoto:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [photoId, processingState, visibility]
|
|
|
|
|
|
description: 会话关联照片的当前状态(会话记录内嵌,客户端据此展示服务端进度)。
|
|
|
|
|
|
properties:
|
|
|
|
|
|
photoId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 照片 ID。
|
|
|
|
|
|
processingState:
|
|
|
|
|
|
$ref: '#/components/schemas/PhotoProcessingState'
|
|
|
|
|
|
visibility:
|
|
|
|
|
|
$ref: '#/components/schemas/PhotoVisibility'
|
|
|
|
|
|
|
|
|
|
|
|
UploadSessionRecord:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required:
|
|
|
|
|
|
- uploadId
|
|
|
|
|
|
- albumId
|
|
|
|
|
|
- clientTaskId
|
|
|
|
|
|
- state
|
|
|
|
|
|
- expectedBytes
|
|
|
|
|
|
- contentType
|
|
|
|
|
|
- createdAt
|
|
|
|
|
|
- photo
|
|
|
|
|
|
properties:
|
|
|
|
|
|
uploadId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 上传会话 ID。
|
|
|
|
|
|
albumId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 目标相册 ID。
|
|
|
|
|
|
clientTaskId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 客户端任务幂等键。
|
|
|
|
|
|
state:
|
|
|
|
|
|
$ref: '#/components/schemas/UploadSessionState'
|
|
|
|
|
|
expectedBytes:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
format: int64
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 申明文件字节数。
|
|
|
|
|
|
contentType:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 申明 MIME 类型。
|
|
|
|
|
|
createdAt:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 会话创建时间。
|
|
|
|
|
|
photo:
|
|
|
|
|
|
$ref: '#/components/schemas/UploadSessionPhoto'
|
|
|
|
|
|
|
|
|
|
|
|
UploadSessionList:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- $ref: '#/components/schemas/CursorPageMeta'
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
required: [items]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
items:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
items:
|
|
|
|
|
|
$ref: '#/components/schemas/UploadSessionRecord'
|
|
|
|
|
|
|
|
|
|
|
|
# ── 照片(管理端) ──
|
|
|
|
|
|
|
|
|
|
|
|
PhotoVisibilityUpdateRequest:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
required: [visibility]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
visibility:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
description: 目标可见性;仅允许 hidden 与 published 间切换。
|
|
|
|
|
|
enum:
|
|
|
|
|
|
- hidden
|
|
|
|
|
|
- published
|
|
|
|
|
|
|
|
|
|
|
|
PhotoRecord:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
description: 管理端照片记录(技术实施方案 §4 photos 表字段)。
|
|
|
|
|
|
required:
|
|
|
|
|
|
- photoId
|
|
|
|
|
|
- albumId
|
|
|
|
|
|
- categoryId
|
|
|
|
|
|
- uploaderId
|
|
|
|
|
|
- visibility
|
|
|
|
|
|
- processingState
|
|
|
|
|
|
- bytes
|
|
|
|
|
|
- width
|
|
|
|
|
|
- height
|
|
|
|
|
|
- shotAt
|
|
|
|
|
|
- uploadedAt
|
|
|
|
|
|
- publishedAt
|
|
|
|
|
|
- likeCount
|
|
|
|
|
|
properties:
|
|
|
|
|
|
photoId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 照片 ID。
|
|
|
|
|
|
albumId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 所属相册 ID。
|
|
|
|
|
|
categoryId:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 分类 ID;null 表示未分类。
|
|
|
|
|
|
uploaderId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 上传人用户 ID。
|
|
|
|
|
|
visibility:
|
|
|
|
|
|
$ref: '#/components/schemas/PhotoVisibility'
|
|
|
|
|
|
processingState:
|
|
|
|
|
|
$ref: '#/components/schemas/PhotoProcessingState'
|
|
|
|
|
|
bytes:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
format: int64
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 原图字节数。
|
|
|
|
|
|
width:
|
|
|
|
|
|
type: [integer, 'null']
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 原图宽度(像素);处理前为 null。
|
|
|
|
|
|
height:
|
|
|
|
|
|
type: [integer, 'null']
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 原图高度(像素);处理前为 null。
|
|
|
|
|
|
shotAt:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 拍摄时间(EXIF);无有效值时为 null。
|
|
|
|
|
|
uploadedAt:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 上传完成时间。
|
|
|
|
|
|
publishedAt:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 发布时间;未发布为 null。
|
|
|
|
|
|
likeCount:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
minimum: 0
|
|
|
|
|
|
description: 累计点赞数。
|
|
|
|
|
|
|
|
|
|
|
|
# ── 公开(观众端) ──
|
|
|
|
|
|
|
|
|
|
|
|
SignedUrl:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
description: 私有对象的短期签名 URL;不得写入持久分享链接,过期后经原入口刷新。
|
|
|
|
|
|
required: [url, expiresAt]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
url:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 签名访问 URL。
|
|
|
|
|
|
expiresAt:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: URL 失效时间。
|
|
|
|
|
|
|
|
|
|
|
|
PublicAlbumTranslation:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
description: 按请求 locale 回退解析后的单语言相册内容(locale 为实际返回语言)。
|
|
|
|
|
|
required: [locale, title, description, venue, address]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
locale:
|
|
|
|
|
|
$ref: '#/components/schemas/Locale'
|
|
|
|
|
|
title:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
description: 相册标题。
|
|
|
|
|
|
description:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
description: 相册描述;无内容为 null。
|
|
|
|
|
|
venue:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
description: 场地名称;无内容为 null。
|
|
|
|
|
|
address:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
description: 场地地址;无内容为 null。
|
|
|
|
|
|
|
|
|
|
|
|
PublicCategory:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
description: 公开分类(名称已按请求 locale 回退解析)。
|
|
|
|
|
|
required: [id, name, sortOrder]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
id:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 分类 ID。
|
|
|
|
|
|
name:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 分类名称。
|
|
|
|
|
|
sortOrder:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 排序序号(升序)。
|
|
|
|
|
|
|
|
|
|
|
|
PublicAlbum:
|
|
|
|
|
|
type: object
|
|
|
|
|
|
description: 观众端相册信息(不泄露工作人员信息与内部存储键)。
|
|
|
|
|
|
required:
|
|
|
|
|
|
- publicToken
|
|
|
|
|
|
- resolvedLocale
|
|
|
|
|
|
- defaultLocale
|
|
|
|
|
|
- timezone
|
|
|
|
|
|
- startAt
|
|
|
|
|
|
- endAt
|
2026-09-17 18:06:54 +08:00
|
|
|
|
- translation
|
2026-09-17 17:31:11 +08:00
|
|
|
|
- categories
|
|
|
|
|
|
- banner
|
|
|
|
|
|
- viewCount
|
|
|
|
|
|
properties:
|
|
|
|
|
|
publicToken:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
2026-09-17 18:06:54 +08:00
|
|
|
|
pattern: '^[0-9a-z]{20,32}$'
|
2026-09-17 17:31:11 +08:00
|
|
|
|
description: 相册公开令牌。
|
|
|
|
|
|
resolvedLocale:
|
|
|
|
|
|
$ref: '#/components/schemas/Locale'
|
|
|
|
|
|
defaultLocale:
|
|
|
|
|
|
$ref: '#/components/schemas/Locale'
|
|
|
|
|
|
timezone:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 活动 IANA 时区(展示用,不随请求语言变化)。
|
|
|
|
|
|
startAt:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 活动开始时间(UTC,客户端按时区格式化)。
|
|
|
|
|
|
endAt:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 活动结束时间;未定为 null。
|
2026-09-17 18:06:54 +08:00
|
|
|
|
translation:
|
2026-09-17 17:31:11 +08:00
|
|
|
|
$ref: '#/components/schemas/PublicAlbumTranslation'
|
|
|
|
|
|
categories:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
description: 分类列表(按 sortOrder 升序)。
|
|
|
|
|
|
items:
|
|
|
|
|
|
$ref: '#/components/schemas/PublicCategory'
|
|
|
|
|
|
banner:
|
|
|
|
|
|
description: 封面图签名 URL;未设置为 null。
|
|
|
|
|
|
anyOf:
|
|
|
|
|
|
- $ref: '#/components/schemas/SignedUrl'
|
|
|
|
|
|
- type: 'null'
|
|
|
|
|
|
viewCount:
|
|
|
|
|
|
type: 'null'
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: P1a 占位 null;浏览计数由后续 /visits 端点提供(技术实施方案 §7.1)。
|
|
|
|
|
|
|
|
|
|
|
|
PublicPhoto:
|
|
|
|
|
|
type: object
|
2026-09-17 18:06:54 +08:00
|
|
|
|
description: 公开照片条目(仅 published 照片,处理完成即有宽高;URL 为短期签名,需在过期前刷新)。
|
|
|
|
|
|
required: [photoId, width, height, thumb, browse, likeCount, publishedAt]
|
2026-09-17 17:31:11 +08:00
|
|
|
|
properties:
|
|
|
|
|
|
photoId:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 照片 ID。
|
|
|
|
|
|
width:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 浏览图宽度(像素);用于列表占位,减少加载跳动。
|
|
|
|
|
|
height:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 浏览图高度(像素)。
|
|
|
|
|
|
thumb:
|
|
|
|
|
|
$ref: '#/components/schemas/SignedUrl'
|
|
|
|
|
|
browse:
|
|
|
|
|
|
$ref: '#/components/schemas/SignedUrl'
|
|
|
|
|
|
likeCount:
|
|
|
|
|
|
type: integer
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
minimum: 0
|
|
|
|
|
|
description: 累计点赞数。
|
|
|
|
|
|
publishedAt:
|
|
|
|
|
|
type: string
|
|
|
|
|
|
format: date-time
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 发布时间(列表排序依据)。
|
|
|
|
|
|
|
|
|
|
|
|
PublicPhotoDetail:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- $ref: '#/components/schemas/PublicPhoto'
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
required: [categoryId]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
categoryId:
|
|
|
|
|
|
type: [string, 'null']
|
|
|
|
|
|
readOnly: true
|
|
|
|
|
|
description: 所属分类 ID;未分类为 null。
|
|
|
|
|
|
|
|
|
|
|
|
PublicPhotoList:
|
|
|
|
|
|
allOf:
|
|
|
|
|
|
- $ref: '#/components/schemas/CursorPageMeta'
|
|
|
|
|
|
- type: object
|
|
|
|
|
|
required: [items]
|
|
|
|
|
|
properties:
|
|
|
|
|
|
items:
|
|
|
|
|
|
type: array
|
|
|
|
|
|
items:
|
|
|
|
|
|
$ref: '#/components/schemas/PublicPhoto'
|