Files
photo-live/packages/contracts/src/generated/openapi.d.ts
T
浅念 0fcf18cc5c feat(ov): public read api on replicas with hot sorting
P2 Task 6(ov 公开读 API + viewer 切换):
- ov 装配 PublicOvModule(仅 app-ov.module):/public/albums/{token}、
  /photos、/photos/{id} 三端点同契约读 ov 副本——translations/categories
  自 JSON 列解析(防御性过滤),banner 经 ov 侧 STORAGE_PORT_OV 预签名
  (同本地 MinIO;只读属约定,真实 OSS 只读凭证 P5),viewCount 取
  album_stats 权威累计(无行默认 0;计数端点 Task 8 接线)
- 排序:latest=发布时间 keyset(shared/cursor.ts 同 cn);hot=likeTotal
  desc + photoId desc 决胜,顺序按 `${albumId}|${category}` 短期快照
  (内存 TTL 默认 30s,HOT_SORT_TTL_MS 惰性读取)——计数逐请求现读、
  顺序冻结窗口内一致,偏移游标(base64url 整数)在快照内严格稳定;
  非法 sort 400 VALIDATION_FAILED(cn 不感知该参数)
- 契约:viewCount 放宽为 integer|null(cn null、ov 权威值);
  listPublicPhotos 增 sort 枚举(latest|hot,缺省 latest);
  PhotoPublishedPayload 增 categoryId——补上 Tasks 3/4 管线缺口
  (payloads/publish.service/sync-inbox 投影 + 关联测试随改)
- e2e(services/api/test/public-ov.e2e-spec.ts,7 用例):双入口同进程
  起 cn+ov,cn API 种子→真实发送管线投递;断言相册/列表/单图与 cn
  深等(仅签名 URL 剔除)、banner 真字节、参数矩阵 400/404、hot 排序
  TTL 内快照(计数新/顺序旧)+TTL 过期翻转+偏移翻页、隐藏/下线/紧急
  停用逐态撤下
- viewer 切 ov:API 基址 VITE_API_BASE(缺省 http://127.0.0.1:8081,
  空串=同源网关;Vite 只读 apps/viewer/.env*,根 .env 对前端无效),
  移除 /v1 dev 代理(CORS_ORIGINS 增 127.0.0.1:5175 直连两形);
  playwright webServer 增 dev:ov;e2e 夹具 flushSync(albumId)=cn
  bootstrap 快照 + deliverPendingOnce(sender 新导出)经真实管线投影
  种子,deleteSeededPhoto 改软删让墓碑可同步;14 个 Playwright 全绿
  (journey 管理/staffB 腿仍走 cn 8080)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-18 17:05:56 +08:00

3181 lines
117 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* This file was auto-generated by openapi-typescript.
* Do not make direct changes to the file.
*/
export interface paths {
"/auth/password": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* 密码登录
* @description 校验账号密码,签发会话令牌。
*/
post: operations["loginWithPassword"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/auth/refresh": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* 会话滑动续期
* @description 携带有效 Bearer 令牌滑动续期,返回新的过期时间。
*/
post: operations["refreshSession"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/auth/logout": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* 退出登录
* @description 使当前 Bearer 令牌失效。
*/
post: operations["logout"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/albums": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* 相册列表
* @description 当前用户可见(参与)的相册列表;管理员可见全部。按创建时间倒序。
*/
get: operations["listAlbums"];
put?: never;
/**
* 创建相册
* @description 创建相册并写入多语言内容;创建者自动成为 owner 成员。
* 初始默认值:uploadEnabled/publicEnabled/downloadEnabled=true、
* originalDownloadEnabled=false、status=active、watermarkVersion=0。
*/
post: operations["createAlbum"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/albums/{albumId}": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
};
cookie?: never;
};
/**
* 相册详情
* @description 相册完整配置、多语言内容与分类列表。
*/
get: operations["getAlbum"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
/**
* 更新相册配置
* @description 部分更新:仅提交的字段被修改,各开关互相独立。
* translations 为全量替换(须包含 defaultLocale 对应条目)。
*/
patch: operations["updateAlbum"];
trace?: never;
};
"/albums/{albumId}/assets": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
};
cookie?: never;
};
get?: never;
put?: never;
/**
* 初始化资产上传
* @description 为相册宣传图/封面/Logo 创建上传会话,返回 staging 对象的临时直传凭证
* (凭证结构与照片直传同形)。无 clientTaskId 幂等键:assetId 即一次性会话,
* 失败重试重新初始化即可。替换语义:同一 (kind, locale) 再次上传→新行生效,
* 旧行保留作历史(P1b 无删除端点);公开相册响应始终取该 kind 最新生效行
* (P1a 公开服务已按 latest 实现)。
*/
post: operations["initAlbumAssetUpload"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/albums/{albumId}/assets/{assetId}/complete": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
/** @description 相册资产 ID。 */
assetId: components["parameters"]["AssetId"];
};
cookie?: never;
};
get?: never;
put?: never;
/**
* 完成资产上传核验
* @description 核验 staging 对象(存在性、字节数与可用完整性信息)后将资产挂到相册生效,
* 并返回短期签名访问 URL。幂等:已核验通过的资产重复调用返回 200
* (URL 重新现签,本端点即签名刷新入口)。
*/
post: operations["completeAlbumAssetUpload"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/albums/{albumId}/members": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
};
cookie?: never;
};
/**
* 相册成员列表
* @description 相册全部成员(含 owner)。
*/
get: operations["listAlbumMembers"];
put?: never;
/**
* 添加相册成员
* @description 将已开通的同事添加为协作者;仅创建者或管理员可操作。
*/
post: operations["addAlbumMember"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/albums/{albumId}/members/{userId}": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
/** @description 用户 ID。 */
userId: components["parameters"]["UserId"];
};
cookie?: never;
};
get?: never;
put?: never;
post?: never;
/**
* 移除相册成员
* @description 移除协作者;仅创建者或管理员可操作。不能移除创建者(403)。
* 目标成员不存在时幂等返回 204。
*/
delete: operations["removeAlbumMember"];
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/albums/{albumId}/categories": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
};
cookie?: never;
};
get?: never;
put?: never;
/**
* 创建分类
* @description 在相册下创建分类;仅创建者或管理员可操作。
*/
post: operations["createCategory"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/categories/{categoryId}": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 分类 ID。 */
categoryId: components["parameters"]["CategoryId"];
};
cookie?: never;
};
get?: never;
put?: never;
post?: never;
/**
* 删除分类
* @description 删除分类(分类下仍有照片时是否允许删除由服务端策略决定,400 拒绝)。
*/
delete: operations["deleteCategory"];
options?: never;
head?: never;
/**
* 更新分类
* @description 部分更新;translations 为全量替换。
*/
patch: operations["updateCategory"];
trace?: never;
};
"/uploads": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* 上传会话记录
* @description 当前用户的上传会话历史(新在前),用于任务队列恢复与状态展示。
*/
get: operations["listUploads"];
put?: never;
/**
* 初始化上传任务
* @description 幂等初始化:预创建上传会话与照片 ID,返回 staging 对象的临时直传凭证。
* 相同 clientTaskId 且参数一致时返回原会话,不重复创建照片;
* 参数不一致时返回 409(UPLOAD_SESSION_CONFLICT)。
*/
post: operations["initUpload"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/uploads/{uploadId}/renew": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 上传会话 ID。 */
uploadId: components["parameters"]["UploadId"];
};
cookie?: never;
};
get?: never;
put?: never;
/**
* 续签上传凭证
* @description 为仍处于 pending 状态的会话重新签发直传凭证(结构同初始化响应)。
*/
post: operations["renewUploadCredential"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/uploads/{uploadId}/complete": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 上传会话 ID。 */
uploadId: components["parameters"]["UploadId"];
};
cookie?: never;
};
get?: never;
put?: never;
/**
* 完成核验
* @description 核验 staging 对象(存在性、字节数与可用完整性信息)后进入处理流水线。
* 幂等:核验通过的会话重复调用返回相同结果。
*/
post: operations["completeUpload"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/albums/{albumId}/photos": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
};
cookie?: never;
};
/**
* 管理端照片列表
* @description 相册照片管理列表(区别于公开列表):全部状态可见(unpublished/published/
* hidden/deleted),条目含 uploader 脱敏信息。按 uploadedAt 与 ID 稳定倒序
* 游标分页。
*/
get: operations["listAlbumPhotos"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/photos/{photoId}": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 照片 ID。 */
photoId: components["parameters"]["PhotoId"];
};
cookie?: never;
};
get?: never;
put?: never;
post?: never;
/**
* 软删除照片
* @description 标记 deleted(软删除),公开端点即刻不可见;物理删除走独立运维流程。
*/
delete: operations["deletePhoto"];
options?: never;
head?: never;
/**
* 调整照片可见性
* @description 在 hidden 与 published 间切换(隐藏/恢复发布);按相册角色与上传人共同判定权限。
*/
patch: operations["updatePhoto"];
trace?: never;
};
"/admin/users": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* 账号前缀查询
* @description 邀请协作者的前置查询:按账号前缀搜索激活用户,返回脱敏列表
* (id/account/displayName,不含邮箱、手机与状态字段)。
* 访问策略(P1b 决策):任何已认证工作人员可用——邀请的发起方不限于
* 创建者/管理员,而泄露面仅为激活用户的最小展示字段、接收方为已认证
* 内部人员,风险可接受;未认证一律 401。前缀匹配为大小写敏感
* (服务端按二进制校对执行 LIKE prefix%);按账号升序返回,无游标
* (前缀搜索 + 小上限即取即用)。
*/
get: operations["lookupUsersByAccount"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/public/albums/{token}": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册公开令牌(不可枚举,持有即可访问)。 */
token: components["parameters"]["AlbumPublicToken"];
};
cookie?: never;
};
/**
* 公开相册信息
* @description 观众页入口:按「请求 locale → defaultLocale」回退解析为单语言对象。
* publicToken 不可枚举,但持有链接者均可访问。
*/
get: operations["getPublicAlbum"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/public/albums/{token}/photos": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册公开令牌(不可枚举,持有即可访问)。 */
token: components["parameters"]["AlbumPublicToken"];
};
cookie?: never;
};
/**
* 公开照片列表
* @description 仅返回公开相册中 published 的照片,按 publishedAt 与 ID 稳定倒序游标分页。
* 签名 URL 为短期凭证,过期后凭同一入口刷新。
*/
get: operations["listPublicPhotos"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/public/albums/{token}/photos/{photoId}": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册公开令牌(不可枚举,持有即可访问)。 */
token: components["parameters"]["AlbumPublicToken"];
/** @description 照片 ID。 */
photoId: components["parameters"]["PhotoId"];
};
cookie?: never;
};
/**
* 公开单图
* @description 深度链接定位单图,同时作为签名 URL 过期后的刷新入口。
* 服务端校验相册与照片归属;隐藏/删除后的旧链接返回 404。
*/
get: operations["getPublicPhoto"];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/public/albums/{token}/photos/{photoId}/likes": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册公开令牌(不可枚举,持有即可访问)。 */
token: components["parameters"]["AlbumPublicToken"];
/** @description 照片 ID。 */
photoId: components["parameters"]["PhotoId"];
};
cookie?: never;
};
get?: never;
put?: never;
/**
* 点赞批次上报
* @description 匿名点赞批次(ov 域部署;路径前缀与 cn 相同,按部署域名区分)。
* 客户端将短时间内的多次点击合并为批次提交,delta 为本批新增点赞数。
*
* - 幂等:同一 (photoId, sessionId, batchId) 重复提交返回已确认结果
* (batchAccepted=true、total 为权威累计值),不重复加计;失败重试
* 必须复用同一 batchId。
* - 窗口外过期批次(LIKE_BATCH_WINDOW_HOURS,默认 24h,清理任务保留窗口)
* 拒绝重放:不加计,返回当前权威 total(batchAccepted=false),
* 客户端据此校准本地乐观计数。
* - 基础限速:sessionId+来源 IP 滑窗,超限 429(RATE_LIMITED)。
* - 相册非公开/紧急停用 404(ALBUM_NOT_PUBLIC);照片不存在、未发布、
* 不属于该相册或相册非公开 404(PHOTO_NOT_PUBLIC)。
*/
post: operations["likePhotoBatch"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/public/albums/{token}/visits": {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册公开令牌(不可枚举,持有即可访问)。 */
token: components["parameters"]["AlbumPublicToken"];
};
cookie?: never;
};
get?: never;
put?: never;
/**
* 浏览上报
* @description 匿名浏览上报(ov 域部署)。仅由客户端显式调用:页面可见且相册信息
* 加载成功后上报一次(列表/图片/WS 等接口调用一律不触发计数)。
*
* - requestId 为上报幂等键(建议 UUID),counted 确认前跨刷新/重试持久复用;
* 重复 requestId 返回 counted=false 与权威 viewCount,不重复计数。
* - 去重窗口(VISIT_WINDOW_MINUTES,默认 30 分钟,D07)内同一 visitorId
* 不重复计数;窗口过后再上报按新访次计数。
* - 过期 requestId(VISIT_REQUEST_TTL_MINUTES,默认 35 分钟)拒绝重放
* (counted=false),不得重新加计。
* - 基础限速:visitorId 滑窗,超限 429(RATE_LIMITED);去重本身为主缓解。
* - 相册非公开/紧急停用 404(ALBUM_NOT_PUBLIC)。
*/
post: operations["reportAlbumVisit"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/internal/sync/content-batches": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* 内容事件批量推送
* @description cn→ov 方向:cn outbox 未投递事件批量推送(默认每 2s 一批、单批
* SYNC_BATCH_SIZE 条;priority=high 的下线/隐藏/删除类事件即时单发)。
* ov 侧语义:eventId 幂等(重复推送忽略)、entityVersion 单调
* (旧版本忽略)、tombstone 墓碑优先(副本删除且不被旧事件复活)、
* 依赖缺失暂存待补。acceptedEventIds 为本批受理(含幂等重复)的事件 ID,
* applied 为实际应用(新版本生效)条数。鉴权见 [internal] tag 描述。
*/
post: operations["syncContentBatches"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/internal/sync/stat-snapshots": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* 统计快照回传
* @description ov→cn 方向:ov 侧聚合的统计快照(likes/views 权威累计值,默认每 60s
* 增量回传)。cn 按 statVersion 单调替换副本列(仅更高版本替换、
* 绝不相加),重复回传幂等。kind=likes 时 photoId 必填(照片点赞数);
* kind=views 为相册级浏览数(无 photoId)。鉴权见 [internal] tag 描述。
*/
post: operations["syncStatSnapshots"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/internal/sync/reconcile": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* 缺失事件对账
* @description ov 侧按 sync_state 水位向 cn 请求指定实体类型在 sinceVersion 之后
* 的事件清单(albumId 可选过滤;中断恢复=水位重放)。cn 返回按版本
* 升序的事件数组,ov 重放补漏;全量快照(bootstrap)的事件本体也经
* 本通道分批拉取。鉴权见 [internal] tag 描述。
*/
post: operations["syncReconcile"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/internal/sync/bootstrap": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* 全量快照引导
* @description ov 冷启动或新建副本时请求 cn 生成当前全量快照事件序列
* (album → categories → assets → photos,含各实体当前 entityVersion)。
* 本端点仅返回事件计数 eventCount 与快照水位 watermark;事件本体经
* 对账通道(/internal/sync/reconcile)以 watermark 为起点分批拉取。
* albumId 缺省表示全部相册。鉴权见 [internal] tag 描述。
*/
post: operations["syncBootstrap"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/internal/sync/digest": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* 每相册实体计数摘要
* @description cn 侧权威计数(P2 Task 4):每相册 {categoryCount, publishedPhotoCount,
* photoCount, assetCount}。ov 对账调度定期拉取并与副本计数比对——不一致
* 的相册触发该相册 bootstrap(当前状态快照重发,含分类全量清单整体替换),
* 收敛错过的墓碑与漏掉的事件。albumId 缺省表示全部相册。鉴权见 [internal]
* tag 描述。
*/
post: operations["syncDigest"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/internal/emergency/disable": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* 海外紧急停用相册(ov 域)
* @description ov 侧独立于同步链路的紧急停用入口:直接置 albums_ov.emergency_disabled
* =true(ov 本地写,不经同步版本链——后续任何同步事件不得解除,恢复仅经
* /internal/emergency/enable 显式操作)。停用相册在 ov 公开 API/WS 侧按
* 404 ALBUM_NOT_PUBLIC 语义处理;cn 侧不感知(同步照常)。albumToken 与
* albumId 二选一(都缺省 400)。审计:ov 侧结构化日志以 audit=emergency
* 字段标记(P2 决策:不做独立文件通道,P5 运维按字段路由聚合)。
* 鉴权见 [internal] tag 描述。
*/
post: operations["emergencyDisable"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
"/internal/emergency/enable": {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
get?: never;
put?: never;
/**
* 解除海外紧急停用(ov 域,显式唯一恢复通道)
* @description 唯一能清除 albums_ov.emergency_disabled 的入口(显式操作,任何同步
* 事件都不会代为解除)。albumToken 与 albumId 二选一(都缺省 400)。
* 审计同 disable(audit=emergency 字段)。鉴权见 [internal] tag 描述。
*/
post: operations["emergencyEnable"];
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
}
export type webhooks = Record<string, never>;
export interface components {
schemas: {
Error: {
/**
* @description 稳定错误码,与 src/errors.ts 的 ErrorCodes 一一对应。
* @enum {string}
*/
readonly code: "AUTH_INVALID_CREDENTIALS" | "AUTH_TOKEN_EXPIRED" | "AUTH_RATE_LIMITED" | "RATE_LIMITED" | "AUTH_FORBIDDEN" | "NOT_FOUND" | "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" | "SYNC_AUTH_FAILED" | "INTERNAL_ERROR";
/** @description 服务器生成的可读消息(诊断用,不作为客户端展示文案依据)。 */
readonly message: string;
/** @description 请求追踪 ID。 */
readonly requestId: string;
};
/** @description 游标分页元信息;各列表响应以 allOf 内嵌本结构(条目 schema 在业务端点中定义)。不变式:hasMore=true 当且仅当 nextCursor≠null,两者必须成对填充。 */
CursorPageMeta: {
/** @description 下一页游标;null 表示没有更多数据。 */
readonly nextCursor: string | null;
/** @description 是否还有下一页。 */
readonly hasMore: boolean;
};
/**
* @description P1a 支持的语言。
* @enum {string}
*/
Locale: "zh-CN" | "en";
LoginRequest: {
/** @description 账号(用户名或邮箱)。 */
account: string;
/** @description 密码。 */
password: string;
};
LoginResponse: {
/** @description 会话令牌(Bearer)。 */
readonly sessionToken: string;
/**
* Format: date-time
* @description 会话过期时间。
*/
readonly expiresAt: string;
};
RefreshResponse: {
/**
* Format: date-time
* @description 续期后的过期时间。
*/
readonly expiresAt: string;
};
/** @description 相册多语言条目(创建/更新与响应共用;未填的可选字段存储为 null)。 */
AlbumTranslation: {
locale: components["schemas"]["Locale"];
/** @description 相册标题。 */
title: string;
/** @description 相册描述。 */
description?: string | null;
/** @description 场地名称。 */
venue?: string | null;
/** @description 场地地址。 */
address?: string | null;
};
AlbumCreateRequest: {
/** @description 多语言内容;必须包含 defaultLocale 对应条目。 */
translations: components["schemas"]["AlbumTranslation"][];
defaultLocale: components["schemas"]["Locale"];
/**
* Format: date-time
* @description 活动开始时间(UTC 存储,展示按 timezone)。
*/
startAt: string;
/**
* Format: date-time
* @description 活动结束时间;null 或缺省表示未定。
*/
endAt?: string | null;
/**
* @description 活动 IANA 时区。
* @default Asia/Shanghai
* @example Asia/Shanghai
*/
timezone: string;
/**
* @description 允许下载浏览版本。
* @default true
*/
downloadEnabled: boolean;
/**
* @description 允许下载原图。
* @default false
*/
originalDownloadEnabled: boolean;
};
/** @description 部分更新:仅提交的字段被修改,各开关互相独立;endAt 传 null 清除。 */
AlbumUpdateRequest: {
/** @description 全量替换多语言内容;须包含 defaultLocale 对应条目。 */
translations?: components["schemas"]["AlbumTranslation"][];
defaultLocale?: components["schemas"]["Locale"];
/**
* Format: date-time
* @description 活动开始时间。
*/
startAt?: string;
/**
* Format: date-time
* @description 活动结束时间;null 清除。
*/
endAt?: string | null;
/** @description 活动 IANA 时区。 */
timezone?: string;
/** @description 是否允许新上传任务。 */
uploadEnabled?: boolean;
/** @description 是否公开可见。 */
publicEnabled?: boolean;
/** @description 允许下载浏览版本。 */
downloadEnabled?: boolean;
/** @description 允许下载原图。 */
originalDownloadEnabled?: boolean;
};
/** @description 相册列表条目(完整开关与多语言标题,管理列表无需二次请求详情)。 */
AlbumSummary: {
/** @description 相册 ID。 */
readonly id: string;
/** @description 公开访问令牌(不可枚举)。 */
readonly publicToken: string;
/** @description 创建者用户 ID。 */
readonly ownerId: string;
/**
* @description 相册状态;offline 表示下线(停止公开访问与新授权签发)。
* @default active
* @enum {string}
*/
readonly status: "active" | "offline";
defaultLocale: components["schemas"]["Locale"];
/** @description 活动 IANA 时区。 */
timezone: string;
/**
* Format: date-time
* @description 活动开始时间。
*/
startAt: string;
/**
* Format: date-time
* @description 活动结束时间;null 表示未定。
*/
endAt: string | null;
/** @description 是否允许新上传任务。 */
uploadEnabled: boolean;
/** @description 是否公开可见。 */
publicEnabled: boolean;
/** @description 允许下载浏览版本。 */
downloadEnabled: boolean;
/** @description 允许下载原图。 */
originalDownloadEnabled: boolean;
/**
* @description 当前水印配置版本。
* @default 0
*/
readonly watermarkVersion: number;
/** @description 各语言内容。 */
translations: components["schemas"]["AlbumTranslation"][];
/**
* Format: date-time
* @description 创建时间。
*/
readonly createdAt: string;
/**
* Format: date-time
* @description 最近更新时间。
*/
readonly updatedAt: string;
};
AlbumList: components["schemas"]["CursorPageMeta"] & {
items: components["schemas"]["AlbumSummary"][];
};
Album: components["schemas"]["AlbumSummary"] & {
/** @description 相册分类(按 sortOrder 升序)。 */
categories: components["schemas"]["Category"][];
};
/**
* @description 相册资产类型(技术实施方案 §4 album_assets.kind)。banner 为观众页宣传图
* (PublicAlbum.banner,P1b 消费方);cover/logo 建表与上传链路就绪,展示
* 消费随后续阶段。
* @enum {string}
*/
AssetKind: "banner" | "cover" | "logo";
/**
* @description 资产上传初始化请求;大小与类型白名单与照片直传一致(UPLOAD_MAX_BYTES
* 环境策略,逐请求惰性读取)。locale 为可选语言维度:同一 (kind, locale)
* 的再次上传即替换(新行生效);语言无关的资产(如 logo)可不传。
*/
AssetInitRequest: {
kind: components["schemas"]["AssetKind"];
locale?: components["schemas"]["Locale"];
/** @description 原始文件名(仅元数据,不作对象唯一标识)。 */
filename: string;
/**
* Format: int64
* @description 申明文件字节数;完成核验时逐一比对。
*/
bytes: number;
/**
* @description MIME 类型白名单;image/heic 为暂定项,解码能力待 G2 真机验证后确认。
* @enum {string}
*/
contentType: "image/jpeg" | "image/png" | "image/heic";
};
AssetInitResponse: {
/** @description 资产 ID(完成核验的寻址凭据,一次性会话)。 */
readonly assetId: string;
/** @description staging 对象键(photo-live/{env}/albums/{albumId}/assets/{assetId}.{ext})。 */
readonly objectKey: string;
credential: components["schemas"]["UploadCredential"];
};
AssetCompleteResponse: components["schemas"]["SignedUrl"] & {
/** @description 资产 ID。 */
readonly assetId: string;
};
MemberAddRequest: {
/** @description 被添加用户的 ID(须为已开通账号)。 */
userId: string;
/**
* @description 成员角色;P1a 仅协作者(owner 由创建流程产生)。
* @default collaborator
* @enum {string}
*/
role: "collaborator";
};
Member: {
/** @description 用户 ID。 */
readonly userId: string;
/** @description 登录账号。 */
readonly account: string;
/** @description 展示姓名(来自用户资料同步)。 */
readonly displayName: string;
/**
* @description 相册角色。
* @enum {string}
*/
readonly role: "owner" | "collaborator";
/**
* @description 成员状态;P1a 仅 active,预留扩展。
* @enum {string}
*/
readonly status: "active";
};
MemberList: components["schemas"]["CursorPageMeta"] & {
items: components["schemas"]["Member"][];
};
CategoryTranslation: {
locale: components["schemas"]["Locale"];
/** @description 分类名称。 */
name: string;
};
CategoryCreateRequest: {
/**
* @description 排序序号(升序)。
* @default 0
*/
sortOrder: number;
/** @description 分类多语言名称。 */
translations: components["schemas"]["CategoryTranslation"][];
};
/** @description 部分更新;translations 为全量替换。 */
CategoryUpdateRequest: {
/** @description 排序序号(升序)。 */
sortOrder?: number;
/** @description 全量替换多语言名称。 */
translations?: components["schemas"]["CategoryTranslation"][];
};
Category: {
/** @description 分类 ID。 */
readonly id: string;
/** @description 所属相册 ID。 */
readonly albumId: string;
/** @description 排序序号(升序)。 */
sortOrder: number;
/** @description 各语言名称。 */
translations: components["schemas"]["CategoryTranslation"][];
};
/**
* @description 上传会话状态(服务端视角;本地任务状态见技术实施方案 §5.5)。
* 会话没有 failed 状态:完成核验失败属于单次请求错误(UPLOAD_VERIFY_FAILED),
* 会话保持 pending 可重试;cancelled 为用户主动取消;
* expired 为超过 expiresAt 未完成(核验时推导或由补偿扫描落定)。
* @enum {string}
*/
UploadSessionState: "pending" | "confirmed" | "cancelled" | "expired";
/**
* @description 照片服务端处理状态(技术实施方案 §5.5「服务端处理」链路)。
* @enum {string}
*/
PhotoProcessingState: "pending_upload" | "uploaded" | "processing" | "ready" | "processing_failed";
/**
* @description 照片对外可见性(技术实施方案 §5.5「对外可见性」;deleted 为软删除)。
* @enum {string}
*/
PhotoVisibility: "unpublished" | "published" | "hidden" | "deleted";
UploadInitRequest: {
/** @description 目标相册 ID。 */
albumId: string;
/** @description 目标分类 ID;缺省为相册默认分类。 */
categoryId?: string;
/** @description 客户端任务幂等键;同一任务的重试必须复用(会话与照片 ID 均复用)。 */
clientTaskId: string;
/** @description 原始文件名(仅元数据,不作对象唯一标识)。 */
filename: string;
/**
* Format: int64
* @description 申明文件字节数;完成核验时逐一比对。
*/
bytes: number;
/**
* @description MIME 类型白名单;image/heic 为暂定项,解码能力待 G2 真机验证后确认。
* @enum {string}
*/
contentType: "image/jpeg" | "image/png" | "image/heic";
};
/** @description staging 对象的临时直传凭证;仅可写入指定 objectKey,不可访问 originals/variants。 */
UploadCredential: {
/**
* @description 凭证模式;P1a 仅预签名 URL,预留 STS 扩展。
* @default presigned
* @enum {string}
*/
readonly mode: "presigned";
/** @description 预签名上传 URL。 */
readonly url: string;
/**
* @description 上传 HTTP 方法。
* @enum {string}
*/
readonly method: "PUT";
/** @description 上传时必须携带的请求头(如 Content-Type)。 */
readonly headers: {
[key: string]: string;
};
/**
* Format: date-time
* @description 凭证过期时间;过期后续签(renew)再重试。
*/
readonly expiresAt: string;
};
UploadInitResponse: {
/** @description 上传会话 ID。 */
readonly uploadId: string;
/** @description 预创建的照片 ID(重试复用,不重复建照片)。 */
readonly photoId: string;
/** @description staging 对象键(photo-live/{env}/staging/{uploadId}/{photoId}.{ext})。 */
readonly objectKey: string;
credential: components["schemas"]["UploadCredential"];
};
UploadCompleteResponse: {
/** @description 照片 ID。 */
readonly photoId: string;
processingState: components["schemas"]["PhotoProcessingState"];
};
/** @description 会话关联照片的当前状态(会话记录内嵌,客户端据此展示服务端进度)。 */
UploadSessionPhoto: {
/** @description 照片 ID。 */
readonly photoId: string;
processingState: components["schemas"]["PhotoProcessingState"];
visibility: components["schemas"]["PhotoVisibility"];
};
UploadSessionRecord: {
/** @description 上传会话 ID。 */
readonly uploadId: string;
/** @description 目标相册 ID。 */
readonly albumId: string;
/** @description 客户端任务幂等键。 */
readonly clientTaskId: string;
state: components["schemas"]["UploadSessionState"];
/**
* Format: int64
* @description 申明文件字节数。
*/
readonly expectedBytes: number;
/** @description 申明 MIME 类型。 */
readonly contentType: string;
/**
* Format: date-time
* @description 会话创建时间。
*/
readonly createdAt: string;
photo: components["schemas"]["UploadSessionPhoto"];
};
UploadSessionList: components["schemas"]["CursorPageMeta"] & {
items: components["schemas"]["UploadSessionRecord"][];
};
PhotoVisibilityUpdateRequest: {
/**
* @description 目标可见性;仅允许 hidden 与 published 间切换。
* @enum {string}
*/
visibility: "hidden" | "published";
};
/** @description 管理端照片记录(技术实施方案 §4 photos 表字段)。 */
PhotoRecord: {
/** @description 照片 ID。 */
readonly photoId: string;
/** @description 所属相册 ID。 */
readonly albumId: string;
/** @description 分类 ID;null 表示未分类。 */
readonly categoryId: string | null;
/** @description 上传人用户 ID。 */
readonly uploaderId: string;
visibility: components["schemas"]["PhotoVisibility"];
processingState: components["schemas"]["PhotoProcessingState"];
/**
* Format: int64
* @description 原图字节数。
*/
readonly bytes: number;
/** @description 原图宽度(像素);处理前为 null。 */
readonly width: number | null;
/** @description 原图高度(像素);处理前为 null。 */
readonly height: number | null;
/**
* Format: date-time
* @description 拍摄时间(EXIF);无有效值时为 null。
*/
readonly shotAt: string | null;
/**
* Format: date-time
* @description 上传完成时间。
*/
readonly uploadedAt: string;
/**
* Format: date-time
* @description 发布时间;未发布为 null。
*/
readonly publishedAt: string | null;
/** @description 累计点赞数。 */
readonly likeCount: number;
};
/** @description 管理列表条目内嵌的上传人脱敏信息(不含邮箱、手机等凭据字段)。 */
AdminPhotoUploader: {
/** @description 上传人用户 ID(与 PhotoRecord.uploaderId 一致)。 */
readonly userId: string;
/** @description 登录账号。 */
readonly account: string;
/** @description 展示姓名(来自用户资料)。 */
readonly displayName: string;
};
AdminPhoto: components["schemas"]["PhotoRecord"] & {
uploader: components["schemas"]["AdminPhotoUploader"];
};
AdminPhotoList: components["schemas"]["CursorPageMeta"] & {
items: components["schemas"]["AdminPhoto"][];
};
/** @description 账号查询条目(脱敏:仅邀请协作者所需的最小字段,不含邮箱/手机/状态)。 */
AdminUserLookupItem: {
/** @description 用户 ID(用于 POST /albums/{albumId}/members 的 userId)。 */
readonly id: string;
/** @description 登录账号。 */
readonly account: string;
/** @description 展示姓名。 */
readonly displayName: string;
};
/** @description 账号前缀查询结果;无游标(前缀搜索 + 小上限即取即用)。 */
AdminUserLookupList: {
/** @description 匹配的激活用户(按账号升序)。 */
items: components["schemas"]["AdminUserLookupItem"][];
};
/** @description 私有对象的短期签名 URL;不得写入持久分享链接,过期后经原入口刷新。 */
SignedUrl: {
/** @description 签名访问 URL。 */
readonly url: string;
/**
* Format: date-time
* @description URL 失效时间。
*/
readonly expiresAt: string;
};
/** @description 按请求 locale 回退解析后的单语言相册内容(locale 为实际返回语言)。 */
PublicAlbumTranslation: {
locale: components["schemas"]["Locale"];
/** @description 相册标题。 */
title: string;
/** @description 相册描述;无内容为 null。 */
description: string | null;
/** @description 场地名称;无内容为 null。 */
venue: string | null;
/** @description 场地地址;无内容为 null。 */
address: string | null;
};
/** @description 公开分类(名称已按请求 locale 回退解析)。 */
PublicCategory: {
/** @description 分类 ID。 */
readonly id: string;
/** @description 分类名称。 */
readonly name: string;
/** @description 排序序号(升序)。 */
readonly sortOrder: number;
};
/** @description 观众端相册信息(不泄露工作人员信息与内部存储键)。 */
PublicAlbum: {
/** @description 相册公开令牌。 */
readonly publicToken: string;
resolvedLocale: components["schemas"]["Locale"];
defaultLocale: components["schemas"]["Locale"];
/** @description 活动 IANA 时区(展示用,不随请求语言变化)。 */
readonly timezone: string;
/**
* Format: date-time
* @description 活动开始时间(UTC,客户端按时区格式化)。
*/
readonly startAt: string;
/**
* Format: date-time
* @description 活动结束时间;未定为 null。
*/
readonly endAt: string | null;
translation: components["schemas"]["PublicAlbumTranslation"];
/** @description 分类列表(按 sortOrder 升序)。 */
categories: components["schemas"]["PublicCategory"][];
/** @description 封面图签名 URL;未设置为 null。 */
banner: components["schemas"]["SignedUrl"] | null;
/**
* Format: int64
* @description 累计浏览数。cn 部署返回 null(P1a 占位,Task 9 起由统计副本回填);
* ov 部署返回 album_stats 权威累计值(无行默认 0;计数由 /visits
* 端点维护,技术实施方案 §7.1)。
*/
readonly viewCount: number | null;
};
/** @description 公开照片条目(仅 published 照片,处理完成即有宽高;URL 为短期签名,需在过期前刷新)。 */
PublicPhoto: {
/** @description 照片 ID。 */
readonly photoId: string;
/** @description 浏览图宽度(像素);用于列表占位,减少加载跳动。 */
readonly width: number;
/** @description 浏览图高度(像素)。 */
readonly height: number;
thumb: components["schemas"]["SignedUrl"];
browse: components["schemas"]["SignedUrl"];
/** @description 累计点赞数。 */
readonly likeCount: number;
/**
* Format: date-time
* @description 发布时间(列表排序依据)。
*/
readonly publishedAt: string;
};
PublicPhotoDetail: components["schemas"]["PublicPhoto"] & {
/** @description 所属分类 ID;未分类为 null。 */
readonly categoryId: string | null;
};
PublicPhotoList: components["schemas"]["CursorPageMeta"] & {
items: components["schemas"]["PublicPhoto"][];
};
/**
* @description 点赞批次上报请求。sessionId 为客户端生成的会话随机标识(会话期间复用);
* batchId 为批次幂等键,同一批的失败重试必须复用,跨批次不得复用。
*/
LikeBatchRequest: {
/** @description 会话标识(客户端随机生成,会话期间复用)。 */
sessionId: string;
/** @description 批次幂等键;同批重试复用,重复提交不加计。 */
batchId: string;
/** @description 本批新增点赞数(客户端短窗合并后的累计点击数)。 */
delta: number;
};
/**
* @description 点赞批次处理结果。total 恒为服务端权威累计值;batchAccepted 区分
* 本批是否被计入(幂等重复=true;窗口外过期批次=false 且不加计)。
*/
LikeBatchResponse: {
/**
* Format: int64
* @description 照片权威累计点赞数(客户端据此校准乐观计数)。
*/
readonly total: number;
/** @description 计数版本(单调递增,实时消息与校准的乱序判别依据)。 */
readonly countVersion: number;
/**
* @description 本批是否被计入:true=新批次或幂等重放已确认批次;
* false=窗口外过期批次(拒绝重放,返回权威 total)。
*/
readonly batchAccepted: boolean;
};
/**
* @description 浏览上报请求。visitorId 跨标签页共享(同一访客);requestId 为本次
* 访次的上报幂等键(建议 UUID),counted 确认前持久复用。
*/
VisitReportRequest: {
/** @description 访客标识(客户端持久化并在标签页间共享)。 */
visitorId: string;
/** @description 上报幂等键;重复提交不重复计数。 */
requestId: string;
};
/** @description 浏览上报结果。viewCount 恒为相册权威累计浏览数。 */
VisitReportResponse: {
/**
* Format: int64
* @description 相册权威累计浏览数。
*/
readonly viewCount: number;
/**
* @description 本次是否实际计数:true=新访次;false=去重窗口内重复、重复
* requestId 或过期 requestId 重放(均不重复计数)。
*/
readonly counted: boolean;
};
/**
* @description 同步实体类型(slot-state 为预留给后续阶段)。
* @enum {string}
*/
SyncEntityType: "album" | "category" | "photo" | "asset" | "slot-state";
/**
* @description 推送优先级:high 为相册下线、照片隐藏/删除等需即时生效的事件
* (发送器即发,不等批间隔);normal 走常规批量推送。
* @enum {string}
*/
SyncPriority: "normal" | "high";
/**
* @description cn→ov 内容同步事件(线格式)。与 cn outbox 事件(src/events.ts)
* 一一对应:eventId 幂等、entityVersion 单调、tombstone 墓碑优先。
* payload 为实体类型相关载荷(album.updated 携带 translations/开关/
* banner 对象键,photo.* 携带对象键与宽高等展示字段)。
*/
SyncEvent: {
/** @description 事件 ID(全局唯一,接收方幂等键)。 */
eventId: string;
/** @description 载荷 schema 版本;当前为 1。 */
schemaVersion: number;
entityType: components["schemas"]["SyncEntityType"];
/** @description 实体 ID(albumId/categoryId/photoId/assetId 等)。 */
entityId: string;
/** @description 归属相册 ID(album 实体时与 entityId 相同)。 */
albumId: string;
/**
* Format: int64
* @description 实体版本(单调递增;接收方仅应用更高版本)。
*/
entityVersion: number;
/**
* @description 墓碑标记:true 表示实体删除,副本删除且不被旧事件复活。
* @default false
*/
tombstone: boolean;
priority: components["schemas"]["SyncPriority"];
/** @description 实体类型相关载荷;结构由发送方按 schemaVersion 约定。 */
payload: {
[key: string]: unknown;
};
};
/** @description 内容事件批量推送请求体。 */
ContentBatchRequest: {
/** @description 事件批次(单批上限对齐 SYNC_BATCH_SIZE,默认 100)。 */
batch: components["schemas"]["SyncEvent"][];
};
/** @description 批量推送受理结果。 */
ContentBatchResponse: {
/** @description 本批受理的事件 ID(含此前已应用的同 eventId 幂等重复)。 */
acceptedEventIds: string[];
/** @description 本批实际应用(新版本生效)的条数。 */
applied: number;
};
/**
* @description 统计快照种类。
* @enum {string}
*/
SyncStatKind: "likes" | "views";
/**
* @description ov→cn 统计快照:权威累计值的版本化替换单元(cn 侧仅更高 statVersion
* 替换副本列,绝不相加)。
*/
StatSnapshot: {
/** @description 照片 ID;kind=likes 时必填,kind=views 无此字段。 */
photoId?: string;
/** @description 归属相册 ID。 */
albumId: string;
kind: components["schemas"]["SyncStatKind"];
/**
* Format: int64
* @description 权威累计值(点赞数或浏览数)。
*/
total: number;
/**
* Format: int64
* @description 统计版本(单调递增;接收方幂等与替换依据)。
*/
statVersion: number;
/** @description 快照来源标识(如 ov)。 */
source: string;
/**
* Format: date-time
* @description 快照确认时间。
*/
confirmedAt: string;
};
/** @description 统计快照回传请求体。 */
StatSnapshotRequest: {
/** @description 增量快照批次。 */
snapshots: components["schemas"]["StatSnapshot"][];
};
/** @description 快照回传受理结果。 */
StatSnapshotResponse: {
/** @description 接受(应用或幂等确认)的快照条数;旧版本被忽略的不计。 */
accepted: number;
};
/** @description 对账拉取请求:某实体类型在 sinceVersion 之后的事件清单。 */
ReconcileRequest: {
entityType: components["schemas"]["SyncEntityType"];
/** @description 可选:限定单相册;缺省为该实体类型全部。 */
albumId?: string;
/**
* Format: int64
* @description 起始版本(exclusive;0 表示从头拉取,配合 bootstrap)。
*/
sinceVersion: number;
/**
* @description 本批拉取上限(分批重放,对齐 SYNC_BATCH_SIZE)。
* @default 100
*/
limit: number;
};
/**
* @description 对账结果:按 entityVersion 升序的**当前状态事件**(可直接重放的完整
* SyncEvent,非仅版本清单——P2 Task 4 设计决策:重放走既有
* content-batches 管道,无需第二条拉取通道;sinceVersion 之后无实体时为
* 空数组)。
*/
ReconcileResponse: {
/** @description 当前状态事件(升序);请求方按序经 content-batches 重放。 */
events: components["schemas"]["SyncEvent"][];
};
/** @description 全量快照引导请求。 */
BootstrapRequest: {
/** @description 指定相册;缺省为全部相册。 */
albumId?: string;
};
/** @description 全量快照规模与水位;事件本体经 reconcile 通道分批拉取。 */
BootstrapResponse: {
/** @description 快照事件总数(供拉取分批与完成校验)。 */
eventCount: number;
/**
* Format: int64
* @description 快照水位:后续增量对账的 sinceVersion 起点。
*/
watermark: number;
};
/** @description 对账摘要请求(P2 Task 4)。 */
DigestRequest: {
/** @description 指定相册;缺省为全部相册。 */
albumId?: string;
};
/**
* @description 单相册权威计数摘要。ov 侧比对口径:albums_ov.categories 元素数应等于
* categoryCount;photos_ov 行数落在 [publishedPhotoCount, photoCount]
* 区间内即视为一致(hidden/deleted 照片若从未以 published 态同步过,ov
* 合法地无行——缺席即撤下语义);相册行缺失即不一致。assetCount 供观测
* (ov 无 asset 副本行,不参与比对)。
*/
AlbumDigest: {
/** @description 相册 ID。 */
albumId: string;
/** @description 当前分类数(cn 权威行数)。 */
categoryCount: number;
/** @description 可见(published)照片数——ov 必须持有的副本行数下界。 */
publishedPhotoCount: number;
/** @description published+hidden+deleted 照片总数——ov 副本行数上界。 */
photoCount: number;
/** @description 生效(effective)资产数(观测用;ov 无 asset 副本行)。 */
assetCount: number;
};
/** @description 每相册计数摘要(albumId 升序)。 */
DigestResponse: {
/** @description 相册摘要清单;空库为空数组。 */
albums: components["schemas"]["AlbumDigest"][];
};
/** @description 紧急停用请求(albumToken 与 albumId 恰好提供其一)。 */
EmergencyDisableRequest: {
/** @description 公开令牌定位相册(与 albumId 二选一)。 */
albumToken?: string;
/** @description 相册 ID 定位(与 albumToken 二选一)。 */
albumId?: string;
/** @description 停用原因(审计留痕)。 */
reason: string;
};
/** @description 解除停用请求(albumToken 与 albumId 恰好提供其一)。 */
EmergencyEnableRequest: {
/** @description 公开令牌定位相册(与 albumId 二选一)。 */
albumToken?: string;
/** @description 相册 ID 定位(与 albumToken 二选一)。 */
albumId?: string;
};
/** @description 紧急停用通道操作结果。 */
EmergencyStatus: {
/** @description 操作后的停用状态(disable 恒 true / enable 恒 false)。 */
disabled: boolean;
/** @description 相册 ID。 */
albumId: string;
};
};
responses: {
/** @description 未认证:令牌缺失、无效或已过期(AUTH_TOKEN_EXPIRED)。 */
Unauthorized: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 服务器内部错误(INTERNAL_ERROR)。 */
InternalError: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
};
parameters: {
/** @description 相册 ID。 */
AlbumId: string;
/** @description 用户 ID。 */
UserId: string;
/** @description 分类 ID。 */
CategoryId: string;
/** @description 相册资产 ID。 */
AssetId: string;
/** @description 上传会话 ID。 */
UploadId: string;
/** @description 照片 ID。 */
PhotoId: string;
/** @description 相册公开令牌(不可枚举,持有即可访问)。 */
AlbumPublicToken: string;
/** @description 分页游标(上一页响应的 nextCursor)。 */
CursorQuery: string;
/** @description 请求语言;缺省或取值不支持时按相册 defaultLocale 回退(不报 400,响应 resolvedLocale 指示实际返回语言)。 */
LocaleQuery: components["schemas"]["Locale"];
};
requestBodies: never;
headers: never;
pathItems: never;
}
export type $defs = Record<string, never>;
export interface operations {
loginWithPassword: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["LoginRequest"];
};
};
responses: {
/** @description 登录成功,返回会话令牌与过期时间。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["LoginResponse"];
};
};
/** @description 参数校验失败(VALIDATION_FAILED,经全局校验管道)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 账号或密码错误(AUTH_INVALID_CREDENTIALS)。 */
401: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/**
* @description 登录失败次数过多(AUTH_RATE_LIMITED,Task 13 契约修订)。
* 同账号+来源 IP 在窗口期内连续失败达到阈值后锁定一段时间。
*/
429: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
refreshSession: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 续期成功。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["RefreshResponse"];
};
};
/** @description 参数校验失败(VALIDATION_FAILED,经全局校验管道)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
500: components["responses"]["InternalError"];
};
};
logout: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 已退出,无响应体。 */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
/** @description 请求体不可解析(VALIDATION_FAILED,经全局校验管道)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
500: components["responses"]["InternalError"];
};
};
listAlbums: {
parameters: {
query?: {
/** @description 分页游标(上一页响应的 nextCursor)。 */
cursor?: components["parameters"]["CursorQuery"];
/** @description 每页条数。 */
limit?: number;
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 相册列表页。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AlbumList"];
};
};
/** @description 查询参数校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
500: components["responses"]["InternalError"];
};
};
createAlbum: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["AlbumCreateRequest"];
};
};
responses: {
/** @description 相册已创建(新相册 categories 为空数组)。 */
201: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Album"];
};
};
/** @description 参数校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
500: components["responses"]["InternalError"];
};
};
getAlbum: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 相册详情。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Album"];
};
};
401: components["responses"]["Unauthorized"];
/** @description 相册不存在,或当前用户非成员不可见(ALBUM_NOT_FOUND,避免枚举)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
updateAlbum: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["AlbumUpdateRequest"];
};
};
responses: {
/** @description 更新后的相册详情。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Album"];
};
};
/** @description 参数校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
/** @description 仅创建者或管理员可修改(AUTH_FORBIDDEN)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 相册不存在,或当前用户不可见(ALBUM_NOT_FOUND)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
initAlbumAssetUpload: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["AssetInitRequest"];
};
};
responses: {
/** @description 资产上传会话已创建。 */
201: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AssetInitResponse"];
};
};
/** @description 参数校验失败(VALIDATION_FAILED):文件超过大小限额或类型不接受。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
/** @description 仅创建者或管理员可管理资产(AUTH_FORBIDDEN)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 相册不存在,或当前用户不可见(ALBUM_NOT_FOUND)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
completeAlbumAssetUpload: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
/** @description 相册资产 ID。 */
assetId: components["parameters"]["AssetId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 核验通过,资产已生效。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AssetCompleteResponse"];
};
};
/**
* @description 核验失败(UPLOAD_VERIFY_FAILED):对象缺失、字节数与申明不符
* 或完整性信息不可用。
*/
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
/** @description 资产不存在或无权操作(AUTH_FORBIDDEN,不区分以避免枚举)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 相册不存在,或当前用户不可见(ALBUM_NOT_FOUND)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
listAlbumMembers: {
parameters: {
query?: {
/** @description 分页游标(上一页响应的 nextCursor)。 */
cursor?: components["parameters"]["CursorQuery"];
/** @description 每页条数。 */
limit?: number;
};
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 成员列表页。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["MemberList"];
};
};
/** @description 查询参数校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
/** @description 相册不存在,或当前用户不可见(ALBUM_NOT_FOUND)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
addAlbumMember: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["MemberAddRequest"];
};
};
responses: {
/** @description 成员已添加。 */
201: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Member"];
};
};
/** @description 参数校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
/** @description 仅创建者或管理员可管理成员(AUTH_FORBIDDEN)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 相册不存在,或当前用户不可见(ALBUM_NOT_FOUND)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 该用户已是相册成员(MEMBER_CONFLICT)。 */
409: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
removeAlbumMember: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
/** @description 用户 ID。 */
userId: components["parameters"]["UserId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 已移除,无响应体。 */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
401: components["responses"]["Unauthorized"];
/** @description 无管理权限,或试图移除创建者(AUTH_FORBIDDEN)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 相册不存在,或当前用户不可见(ALBUM_NOT_FOUND)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
createCategory: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["CategoryCreateRequest"];
};
};
responses: {
/** @description 分类已创建。 */
201: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Category"];
};
};
/** @description 参数校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
/** @description 仅创建者或管理员可管理分类(AUTH_FORBIDDEN)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 相册不存在,或当前用户不可见(ALBUM_NOT_FOUND)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
deleteCategory: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 分类 ID。 */
categoryId: components["parameters"]["CategoryId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 已删除,无响应体。 */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
401: components["responses"]["Unauthorized"];
/** @description 无所属相册的管理权限(AUTH_FORBIDDEN)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 分类不存在,或所属相册不存在/不可见(ALBUM_NOT_FOUND)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
updateCategory: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 分类 ID。 */
categoryId: components["parameters"]["CategoryId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["CategoryUpdateRequest"];
};
};
responses: {
/** @description 更新后的分类。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Category"];
};
};
/** @description 参数校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
/** @description 无所属相册的管理权限(AUTH_FORBIDDEN)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 分类不存在,或所属相册不存在/不可见(ALBUM_NOT_FOUND)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
listUploads: {
parameters: {
query?: {
/** @description 分页游标(上一页响应的 nextCursor)。 */
cursor?: components["parameters"]["CursorQuery"];
/** @description 每页条数。 */
limit?: number;
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 会话记录列表页。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadSessionList"];
};
};
/** @description 查询参数校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
500: components["responses"]["InternalError"];
};
};
initUpload: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["UploadInitRequest"];
};
};
responses: {
/** @description 上传会话已创建(幂等重复调用返回原会话)。 */
201: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadInitResponse"];
};
};
/** @description 参数校验失败(VALIDATION_FAILED):文件超过大小限额或类型不接受。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
/** @description 无该相册的上传权限(AUTH_FORBIDDEN)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/**
* @description 相册已关闭上传(ALBUM_UPLOAD_DISABLED),或同 clientTaskId 已存在
* 且参数不一致(UPLOAD_SESSION_CONFLICT)。
*/
409: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
renewUploadCredential: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 上传会话 ID。 */
uploadId: components["parameters"]["UploadId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 新凭证已签发(credential 为新值,其余字段回显原会话)。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadInitResponse"];
};
};
401: components["responses"]["Unauthorized"];
/** @description 无权操作该会话或会话不存在(AUTH_FORBIDDEN,不区分以避免枚举)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/**
* @description 相册已关闭上传(ALBUM_UPLOAD_DISABLED),或会话状态不允许续签
* (已完成/取消/过期,UPLOAD_SESSION_CONFLICT)。
*/
409: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
completeUpload: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 上传会话 ID。 */
uploadId: components["parameters"]["UploadId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 核验通过,照片进入处理流水线。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["UploadCompleteResponse"];
};
};
/**
* @description 核验失败(UPLOAD_VERIFY_FAILED):对象缺失、字节数与申明不符
* 或完整性信息不可用。
*/
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
/** @description 无权操作该会话或会话不存在(AUTH_FORBIDDEN,不区分以避免枚举)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 会话状态不允许完成(已取消或已过期,UPLOAD_SESSION_CONFLICT)。 */
409: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
listAlbumPhotos: {
parameters: {
query?: {
/** @description 可见性过滤;缺省为全部状态。 */
visibility?: components["schemas"]["PhotoVisibility"];
/** @description 分类 ID 过滤。 */
categoryId?: string;
/** @description 分页游标(上一页响应的 nextCursor)。 */
cursor?: components["parameters"]["CursorQuery"];
/** @description 每页条数。 */
limit?: number;
};
header?: never;
path: {
/** @description 相册 ID。 */
albumId: components["parameters"]["AlbumId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 管理照片列表页。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AdminPhotoList"];
};
};
/** @description 查询参数校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
/** @description 仅创建者或管理员可访问管理列表(AUTH_FORBIDDEN)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 相册不存在,或当前用户不可见(ALBUM_NOT_FOUND)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
deletePhoto: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 照片 ID。 */
photoId: components["parameters"]["PhotoId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 已软删除,无响应体。 */
204: {
headers: {
[name: string]: unknown;
};
content?: never;
};
401: components["responses"]["Unauthorized"];
/** @description 无该照片的管理权限(AUTH_FORBIDDEN)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 照片不存在(PHOTO_NOT_FOUND)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
updatePhoto: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 照片 ID。 */
photoId: components["parameters"]["PhotoId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["PhotoVisibilityUpdateRequest"];
};
};
responses: {
/** @description 更新后的照片记录。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["PhotoRecord"];
};
};
/** @description 参数校验失败(VALIDATION_FAILED,visibility 取值非法)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
/** @description 无该照片的管理权限(AUTH_FORBIDDEN)。 */
403: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 照片不存在(PHOTO_NOT_FOUND)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
lookupUsersByAccount: {
parameters: {
query: {
/** @description 账号前缀(≥2 字符以防过宽匹配)。 */
accountPrefix: string;
/** @description 返回条数上限。 */
limit?: number;
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 匹配的激活用户列表(无匹配为空数组)。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["AdminUserLookupList"];
};
};
/** @description 查询参数校验失败(VALIDATION_FAILED;accountPrefix 缺失或长度非法)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
401: components["responses"]["Unauthorized"];
500: components["responses"]["InternalError"];
};
};
getPublicAlbum: {
parameters: {
query?: {
/** @description 请求语言;缺省或取值不支持时按相册 defaultLocale 回退(不报 400,响应 resolvedLocale 指示实际返回语言)。 */
locale?: components["parameters"]["LocaleQuery"];
};
header?: never;
path: {
/** @description 相册公开令牌(不可枚举,持有即可访问)。 */
token: components["parameters"]["AlbumPublicToken"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 相册公开信息。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["PublicAlbum"];
};
};
/** @description 查询参数校验失败(VALIDATION_FAILED;locale 取值不支持时不报错,按 defaultLocale 回退)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 相册不存在或未公开(ALBUM_NOT_PUBLIC,不区分以避免枚举)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
listPublicPhotos: {
parameters: {
query?: {
/** @description 分类 ID 过滤(来自 PublicAlbum.categories 的 id)。 */
category?: string;
/**
* @description 排序模式:latest=发布时间倒序(缺省);hot=点赞数倒序(photoId 倒序
* 决胜,短期快照语义——服务端约 30s 缓冲,窗口内顺序不随点赞变化,
* 技术实施方案 §7)。hot 仅 ov 部署实现;cn 部署不感知该参数(固定
* latest 语义)。ov 部署对非法取值返回 400 VALIDATION_FAILED。
*/
sort?: "latest" | "hot";
/** @description 请求语言;缺省或取值不支持时按相册 defaultLocale 回退(不报 400,响应 resolvedLocale 指示实际返回语言)。 */
locale?: components["parameters"]["LocaleQuery"];
/** @description 分页游标(上一页响应的 nextCursor)。 */
cursor?: components["parameters"]["CursorQuery"];
/** @description 每页张数(技术实施方案 §7 建议 30-60)。 */
limit?: number;
};
header?: never;
path: {
/** @description 相册公开令牌(不可枚举,持有即可访问)。 */
token: components["parameters"]["AlbumPublicToken"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 公开照片列表页。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["PublicPhotoList"];
};
};
/** @description 查询参数校验失败(category/cursor/limit;locale 取值不支持时不报错,按 defaultLocale 回退)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 相册不存在或未公开(ALBUM_NOT_PUBLIC,不区分以避免枚举)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
getPublicPhoto: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册公开令牌(不可枚举,持有即可访问)。 */
token: components["parameters"]["AlbumPublicToken"];
/** @description 照片 ID。 */
photoId: components["parameters"]["PhotoId"];
};
cookie?: never;
};
requestBody?: never;
responses: {
/** @description 单图信息(含新签名的 thumb/browse URL)。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["PublicPhotoDetail"];
};
};
/**
* @description 相册不存在或未公开(ALBUM_NOT_PUBLIC),或照片不存在、未发布、
* 不属于该相册(PHOTO_NOT_PUBLIC)。
*/
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
likePhotoBatch: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册公开令牌(不可枚举,持有即可访问)。 */
token: components["parameters"]["AlbumPublicToken"];
/** @description 照片 ID。 */
photoId: components["parameters"]["PhotoId"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["LikeBatchRequest"];
};
};
responses: {
/**
* @description 本批处理结果(含被拒绝的过期批次——拒绝也返回 200 与权威 total,
* 语义由 batchAccepted 表达,避免客户端把重放当失败重试)。
*/
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["LikeBatchResponse"];
};
};
/** @description 参数校验失败(VALIDATION_FAILED;delta 越界 1..20 或字段长度非法)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/**
* @description 相册不存在或未公开(ALBUM_NOT_PUBLIC),或照片不存在、未发布、
* 不属于该相册(PHOTO_NOT_PUBLIC)。
*/
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 基础限速触发(RATE_LIMITED;sessionId+IP 滑窗)。 */
429: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
reportAlbumVisit: {
parameters: {
query?: never;
header?: never;
path: {
/** @description 相册公开令牌(不可枚举,持有即可访问)。 */
token: components["parameters"]["AlbumPublicToken"];
};
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["VisitReportRequest"];
};
};
responses: {
/** @description 上报结果(窗口内重复/重复 requestId/过期重放均 200 + counted=false)。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["VisitReportResponse"];
};
};
/** @description 参数校验失败(VALIDATION_FAILED;visitorId/requestId 长度非法)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 相册不存在或未公开(ALBUM_NOT_PUBLIC)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 基础限速触发(RATE_LIMITED;visitorId 滑窗)。 */
429: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
syncContentBatches: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["ContentBatchRequest"];
};
};
responses: {
/** @description 本批受理结果。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ContentBatchResponse"];
};
};
/** @description 请求体校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
syncStatSnapshots: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["StatSnapshotRequest"];
};
};
responses: {
/** @description 回传受理结果。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["StatSnapshotResponse"];
};
};
/** @description 请求体校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
syncReconcile: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["ReconcileRequest"];
};
};
responses: {
/** @description 缺失事件清单(按 entityVersion 升序)。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["ReconcileResponse"];
};
};
/** @description 请求体校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
syncBootstrap: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["BootstrapRequest"];
};
};
responses: {
/** @description 快照规模与水位。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["BootstrapResponse"];
};
};
/** @description 请求体校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
syncDigest: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["DigestRequest"];
};
};
responses: {
/** @description 每相册计数摘要(albumId 升序)。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["DigestResponse"];
};
};
/** @description 请求体校验失败(VALIDATION_FAILED)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
emergencyDisable: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["EmergencyDisableRequest"];
};
};
responses: {
/** @description 已停用(幂等:重复停用返回同一结果)。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["EmergencyStatus"];
};
};
/** @description 请求体校验失败(VALIDATION_FAILED;含 albumToken/albumId 均缺省)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 相册副本不存在(ALBUM_NOT_FOUND——ov 尚未同步该相册)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
emergencyEnable: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody: {
content: {
"application/json": components["schemas"]["EmergencyEnableRequest"];
};
};
responses: {
/** @description 已恢复(幂等:重复启用返回同一结果)。 */
200: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["EmergencyStatus"];
};
};
/** @description 请求体校验失败(VALIDATION_FAILED;含 albumToken/albumId 均缺省)。 */
400: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
/** @description 相册副本不存在(ALBUM_NOT_FOUND)。 */
404: {
headers: {
[name: string]: unknown;
};
content: {
"application/json": components["schemas"]["Error"];
};
};
500: components["responses"]["InternalError"];
};
};
}