/** * 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; }; "/auth/password-change": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; get?: never; put?: never; /** * 修改密码 * @description 已认证用户修改自身密码:校验旧密码,成功后更新密码哈希并撤销该用户 * 除当前会话外的全部其他会话(当前会话保持有效,无需重新登录)。 * P3 Task 3 契约增补(需求 4.1「支持修改密码」,P1 契约缺口补齐)。 */ post: operations["changePassword"]; 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; /** * 软删除相册 * @description 标记 status=deleted(软删除):管理端列表与公开端即刻不可见,成员/上传/ 资产等全部子资源随之 404;数据保留(物理删除走独立运维流程),不提供 恢复端点。权限同「配置相册」(公司管理员或相册创建者)。事件走 album.updated(priority=high)同步 ov 副本下线。 */ delete: operations["deleteAlbum"]; options?: never; head?: never; /** * 更新相册配置 * @description 部分更新:仅提交的字段被修改,各开关互相独立。 * translations 为全量替换(须包含 defaultLocale 对应条目)。 */ patch: operations["updateAlbum"]; trace?: never; }; "/albums/{albumId}/watermark-jobs": { parameters: { query?: never; header?: never; path: { /** @description 相册 ID。 */ albumId: components["parameters"]["AlbumId"]; }; cookie?: never; }; /** * 水印配置版本与重生成任务状态 * @description 当前生效配置(current,从未配置为 null)与历史任务列表(创建时间倒序)。 * 任务进度(progress/total/failed)供前端轮询;state=failed 的任务可经 * POST 重新发起(按照片粒度幂等续跑)。 */ get: operations["getWatermarkJobs"]; put?: never; /** * 保存水印配置并发起历史重生成 * @description 保存新的水印配置版本(configVersion 递增)并创建历史照片重生成任务 * (A18/A20)。仅创建者或管理员可操作。语义约定: * 新照片发布默认套用最新版本;历史照片重生成须显式经本端点发起; * 任务为原子切换——全部照片处理完成前旧浏览图保持可用(失败照片保留 * 旧图,任务可重试);原图(original)永不覆盖。 */ post: operations["createWatermarkJob"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/albums/{albumId}/assets": { parameters: { query?: never; header?: never; path: { /** @description 相册 ID。 */ albumId: components["parameters"]["AlbumId"]; }; cookie?: never; }; /** * 各类资产当前生效项(管理端现状展示) * @description 返回每个 (kind, locale) 组合的最新 effective 资产行 + 现签短期 URL (同「替换语义」——同组再上传即整体替换)。未设置的组合不出现; 签名过期重取本端点刷新。权限同相册详情(可见即可读)。 */ get: operations["listAlbumAssetStatus"]; 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/duplicates/check": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; get?: never; put?: never; /** * 上传查重预检(批量,只读) * @description 批量查重预检:对每个请求条目判定「同相册 + 同上传者(当前用户)+ 同字节数」 * 的非 deleted 照片是否已存在——判定谓词与 initUpload 的 PHOTO_DUPLICATE * 查重逐字一致(含 uploaderId 隔离;filename 刻意不参与)。命中条目按请求 * 下标逐项返回(两个请求条目共享同一命中 bytes 时各返回一条)。 * 不校验 uploadEnabled:预检是只读预览,相册关闭上传时仍可查询历史重复 * (init 在真正入队时仍按开关 409 兜底)。 */ post: operations["checkUploadDuplicates"]; 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 稳定倒序 * 游标分页。 * * scope(UI-01 可选扩展,缺省 all=既有行为不变):协作者显式查询自己 * 上传的照片——服务端过滤 uploaderId=当前用户,成员资格逐请求校验; * 仅 owner/admin 可用 all(协作者 all → 403)。条目 preview 按请求者 * 权限逐张裁决(见 PhotoPreview)。 */ get: operations["listAlbumPhotos"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/albums/{albumId}/photos/hide-batch": { parameters: { query?: never; header?: never; path: { /** @description 相册 ID。 */ albumId: components["parameters"]["AlbumId"]; }; cookie?: never; }; get?: never; put?: never; /** * 批量隐藏照片 * @description 批量将 published 照片置为 hidden(A16)。逐项返回结果:不存在、已删除 * 或状态不可切换单项 ok=false 并携带 code,不影响其余项(部分成功语义)。 * 单批上限 200(minItems/maxItems)。权限与 403/404 语义同管理照片列表 * (仅创建者或管理员;ALBUM_NOT_FOUND 防枚举)。 */ post: operations["hidePhotosBatch"]; 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/albums/{albumId}/transfer": { parameters: { query?: never; header?: never; path: { /** @description 相册 ID。 */ albumId: components["parameters"]["AlbumId"]; }; cookie?: never; }; get?: never; put?: never; /** * 相册负责人交接 * @description 将相册 owner 移交给目标用户(A17)。仅 admin 可操作(负责人交接为 * 组织级治理动作,区别于相册级配置修改)。keepAsCollaborator=true 时 * 原 owner 转为 collaborator 成员,否则原 owner 移出成员表。历史上传人 * 不变(photos.uploaderId 不动);审计 album.transfer。 */ post: operations["transferAlbum"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/admin/users": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** * 用户查询与管理列表 * @description 双模式统一端点(P4a 决策:与 P1b 账号前缀查询合一,响应统一 * AdminUserList——条目为 AdminUser 字段超集,管理端 UI 按场景裁剪展示): * · 前缀模式(提供 accountPrefix):邀请协作者前置查询,沿用 P1b 语义 * ——大小写敏感前缀匹配(服务端按二进制校对执行 LIKE prefix%,匹配 * account **或 displayName** 前缀——2026-09-29 扩展:V1.1 账号=手机号, * 运营按姓名搜人是自然预期)、仅「激活资格」用户(credentialStatus= * active 且 sourceStatus≠disabled 且 !localLocked,与成员添加的目标 * 校验一致)、account 升序; * 访问策略沿用 P1b 决策:任何已认证工作人员可用(邀请发起方不限于 * 创建者/管理员,泄露面为已认证内部人员,风险可接受)。 * · 管理列表模式(未提供 accountPrefix):全量用户治理列表(游标分页, * 按 createdAt 与 ID 稳定倒序),可选 query/status 过滤(不做全文 * 搜索);仅 admin 可用(非 admin 403)。 * 两模式响应形状一致(AdminUserList);前缀模式小上限即取即用, * hasMore/nextCursor 同样按游标语义填充。 */ get: operations["listAdminUsers"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/admin/users/{userId}": { parameters: { query?: never; header?: never; path: { /** @description 用户 ID。 */ userId: components["parameters"]["UserId"]; }; cookie?: never; }; get?: never; put?: never; post?: never; delete?: never; options?: never; head?: never; /** * 更新用户治理属性 * @description 部分更新 role/localLocked/displayName;仅 admin。sourceStatus 只读 * (上游状态仅由同步任务维护,本地不越权改写——技术方案 3.1A 红线, * 需求侧只读展示)。localLocked 置 true 等价停用(撤销该用户全部会话); * 置 false 仅解除本地锁定,不改变上游停用状态。审计全程。 */ patch: operations["updateAdminUser"]; trace?: never; }; "/admin/users/{userId}/reset-password": { parameters: { query?: never; header?: never; path: { /** @description 用户 ID。 */ userId: components["parameters"]["UserId"]; }; cookie?: never; }; get?: never; put?: never; /** * 管理员重置用户密码 * @description 仅 admin。body 可选 newPassword(8-128):缺省由服务端生成随机密码 * (e2e 两种路径均覆盖)。重置成功后撤销该目标用户全部既有会话(须 * 重新登录);新密码仅在响应中返回一次(不入库明文、不留日志),管理 * 端一次性展示转交。审计全程。 */ post: operations["resetAdminUserPassword"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/admin/users/{userId}/activate": { parameters: { query?: never; header?: never; path: { /** @description 用户 ID。 */ userId: components["parameters"]["UserId"]; }; cookie?: never; }; get?: never; put?: never; /** * 激活待激活用户 * @description 仅 admin。credentialStatus pending→active(闭环用户同步创建的待激活 * 账号,§10 语义)。激活本身不出凭据:初始密码经 reset-password 出具 * (推荐流程 activate → reset-password 生成一次性初始密码 → 用户登录)。 * 幂等:对已是 active 的用户重复激活返回当前条目。 */ post: operations["activateAdminUser"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/admin/users/{userId}/deactivate": { parameters: { query?: never; header?: never; path: { /** @description 用户 ID。 */ userId: components["parameters"]["UserId"]; }; cookie?: never; }; get?: never; put?: never; /** * 停用用户 * @description 仅 admin。localLocked=true 并撤销该用户全部会话(既有令牌即刻 401)。 * 上游状态不动(sourceStatus 保持;上游恢复 active 不解除本地锁定—— * 本地锁定独立,技术方案 3.1A)。重新启用经 PATCH localLocked=false。 * 审计全程。 */ post: operations["deactivateAdminUser"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/admin/user-sync/status": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** * 用户同步状态 * @description 仅 admin。同步引擎当前状态、最近批次计数与源水位(A29)。当前为 mock * 源(G4:真实接口到位后仅替换 provider,契约不变)。 */ get: operations["getUserSyncStatus"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/admin/user-sync/runs": { parameters: { query?: { /** @description 分页游标(上一页响应的 nextCursor)。 */ cursor?: components["parameters"]["CursorQuery"]; /** @description 每页条数。 */ limit?: number; }; header?: never; path?: never; cookie?: never; }; /** * 同步运行历史 * @description 仅 admin。历史批次列表(startedAt 与 ID 稳定倒序游标分页)。 */ get: operations["listUserSyncRuns"]; put?: never; /** * 手动触发同步补拉 * @description 仅 admin。手动发起一次同步(与定时调度共用互斥锁;已有批次运行中时 * 不重复执行,返回进行中批次的 runId)。202 表示已受理,异步执行, * 结果经 status/runs 端点查询。 */ post: operations["triggerUserSyncRun"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/admin/user-sync/errors": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** * 同步失败明细 * @description 仅 admin。单批次失败行明细(state=partial/failed 批次的坏行记录, * 其余行照常应用的证据链);runId 必填。 */ get: operations["listUserSyncErrors"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/admin/usage/summary": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** * 用量汇总与阈值告警 * @description 仅 admin。按相册聚合存储用量(原图 + 变体,实时 SUM——P1 规模够用; * P5 接 OSS 用量 API/物化视图,登记偏差)、当前阈值与告警列表 * (A23 后台侧;告警接收人通知渠道 P5)。 */ get: operations["getUsageSummary"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/admin/usage/thresholds": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; get?: never; /** * 更新用量阈值 * @description 仅 admin。部分更新:缺省字段保持不变,显式 null 清除该阈值(清除后 * 对应告警维度停用)。修改后即刻重新评估(超阈产生新告警、阈值上调将 * 已回落旧告警标记 resolvedAt)。 */ put: operations["updateUsageThresholds"]; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/admin/embed-slots": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** * 展示位列表 * @description 展示位(悬浮轮播组件挂载点)治理列表,游标分页(按 createdAt 与 ID * 稳定倒序);仅公司 admin 可用(P4b 权限简化:成员授权面 P5 按需补)。 */ get: operations["listEmbedSlots"]; put?: never; /** * 创建展示位 * @description 创建展示位(仅 admin):服务端生成不可枚举 publicToken(嵌入代码 * data-slot 引用);初始 enabled=true、albumId=null(未绑定,公开端 * 404)、configVersion=1。settings 整体缺省时按各字段缺省值落库。 */ post: operations["createEmbedSlot"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/admin/embed-slots/{id}": { parameters: { query?: never; header?: never; path: { /** @description 展示位 ID。 */ id: components["parameters"]["EmbedSlotId"]; }; cookie?: never; }; get?: never; put?: never; post?: never; /** * 软删除展示位 * @description 标记 deletedAt(软删除):管理列表隐藏、公开拉取经 enabled=false 快照 同步 ov 后 404(已接入网站停止展示)。数据保留,无恢复端点。 admin 专属;幂等(重复删除 204)。 */ delete: operations["deleteEmbedSlot"]; options?: never; head?: never; /** * 更新展示位 * @description 展示位部分更新(仅 admin):name/enabled/settings/albumId 任一管理面 * 变更均递增 configVersion 并触发 slot-state 同步事件(嵌入端配置版本 * 变化即整体重置渲染)。albumId 语义:非 null 为绑定/换绑目标相册 * (相册须存在,不存在 404 ALBUM_NOT_FOUND),null 为解绑(公开端随即 * 404);albumId 值本身变化(含换绑与解绑)即视为配置变更。settings * 为整体替换(提供时字段齐全)。无删除端点:enabled=false 即下线。 */ patch: operations["updateEmbedSlot"]; trace?: never; }; "/admin/ads": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; /** * 广告位列表 * @description 广告位治理列表(仅 admin):按 sortOrder 升序、并列 createdAt 升序 * 全量返回(运营量级 <20,不分页);imageUrl 为现签 GET,过期后重拉 * 本列表刷新。albumIds=null 为全局投放。 */ get: operations["listAdminAds"]; put?: never; /** * 创建广告位 * @description 创建广告位(仅 admin):服务端核验 staging 对象(存在 + bytes + * contentType 与申明一致,banner complete 同口径)后 copyIfAbsent * 转存版本化终键,落库并写 outbox ad.updated(entityVersion=1)。 * albumIds 未提供或空数组归一为 null(全局投放);元素须为存在的相册 * ID(相册删除不级联清理,容失效见设计 §2.1)。 */ post: operations["createAd"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/admin/ads/uploads": { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; get?: never; put?: never; /** * 初始化广告图直传 * @description 广告图两步直传第一步(仅 admin):签发 staging 对象的临时直传凭证, * 键 photo-live/{env}/ads/staging/{cuid}.{ext}。字节上限收紧为 2MB * (AD_UPLOAD_MAX_BYTES:广告不走变体流水线、原图直出且轮播多张同屏, * 独立于照片域 UPLOAD_MAX_BYTES 的 50MB,设计 §3);类型白名单 * image/jpeg|png|heic。无会话概念(重复转存由创建端 copyIfAbsent * 禁止覆盖语义承担)。 */ post: operations["initAdUpload"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/admin/ads/{adId}": { parameters: { query?: never; header?: never; path: { /** @description 广告位 ID。 */ adId: components["parameters"]["AdId"]; }; cookie?: never; }; get?: never; put?: never; post?: never; /** * 硬删除广告位 * @description 硬删行并写 ad.deleted 墓碑(high 优先级;ov 删 ads_ov 投影行且不被 旧事件复活)。cn 侧数据不保留、无恢复端点;重复删除 404。 */ delete: operations["deleteAd"]; options?: never; head?: never; /** * 更新广告位 * @description 广告位部分更新(仅 admin):title/linkUrl/enabled/sortOrder/albumIds * 任一变更递增 entityVersion 并重发整行快照(ad.updated;停用 true→false * 走 high 优先级)。albumIds:未提供=不动,null=转全局,数组=整体替换; * 换图时 imageStagingKey/imageBytes/imageContentType 三者必须同时提供 * (核验后转存新版本键,旧对象不回收,OSS 生命周期兜底)。 */ patch: operations["updateAd"]; 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}/ads": { parameters: { query?: never; header?: never; path: { /** @description 相册公开令牌(不可枚举,持有即可访问)。 */ token: components["parameters"]["AlbumPublicToken"]; }; cookie?: never; }; /** * 公开广告列表 * @description 观众页相册头部轮播数据(ov 域部署):返回「全局投放(albumIds=null) * ∨ 绑定本相册」的启用广告,按 sortOrder 升序、并列 createdAt 升序; * imageUrl 为现签 GET(TTL=SIGNED_URL_TTL_SECONDS)。无广告返回空 * items(非 404)。量级假设广告 ≤ 百条:ads_ov 全表捞 + 应用层过滤, * 不加独立限速档(与公开相册读同量级,设计 §5.2)。 */ get: operations["listPublicAds"]; put?: never; post?: never; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/public/embed-slots/{slotToken}": { parameters: { query?: never; header?: never; path: { /** @description 展示位公开令牌(不可枚举,持有即可访问;格式见 EmbedSlot.publicToken)。 */ slotToken: components["parameters"]["EmbedSlotToken"]; }; cookie?: never; }; /** * 展示位公开数据(嵌入组件数据源) * @description 悬浮轮播组件的数据源(ov 域部署,匿名只读;嵌入 iframe 轮询调用): * 返回展示位绑定相册的近期已发布照片(≤20,按 publishedAt 与 ID 稳定 * 倒序,小尺寸缩略图省流量)与相册摘要。lang 语义:auto(缺省)或取值 * 不支持时按相册 defaultLocale 回退(不报 400,与公开相册一致)。 * settings(UI-01)返回后台配置的归一化全集(嵌入端应用后台配置, * data-* 覆盖优先)。 * * - 防探测:slotToken 不存在、展示位停用(enabled=false)或未绑定相册 * 一律 404 NOT_FOUND(同码同文案,不区分原因,避免枚举探测)。 * - 条件请求(A23 省流量):200/304 响应携带强 ETag,取值为四元组 * `"{configVersion}-{photoCount}-{maxPublishedAtMs}-{maxPhotoId}"` * (含照片条数与最新发布时间——新照片发布必变,避免仅比对实体版本 * 时新照片小版本导致 304 陈旧);请求携带 If-None-Match 且匹配时 * 返回 304(无响应体,仍携带 ETag)。 */ get: operations["getPublicEmbedSlot"]; 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 回显该 requestId 首次处理的结局 * (确认响应丢失后重试仍见 true),viewCount 恒为当前权威值,不重复计数。 * - 去重窗口(VISIT_WINDOW_MINUTES,默认 30 分钟,D07)内同一 visitorId * 不重复计数;窗口过后再上报按新访次计数。 * - 过期 requestId(VISIT_REQUEST_TTL_MINUTES,默认 35 分钟)拒绝重放 * (counted=false,无论原结局),不得重新加计。 * - 基础限速:visitorId+来源 IP 固定窗(VISIT_WINDOW_REQUESTS,默认 * 60/窗),超限 429(RATE_LIMITED);去重本身为主缓解。 * - 相册非公开/紧急停用 404(ALBUM_NOT_PUBLIC)。 */ post: operations["reportAlbumVisit"]; delete?: never; options?: never; head?: never; patch?: never; trace?: never; }; "/public/albums/{token}/photos/{photoId}/download": { parameters: { query?: never; header?: never; path: { /** @description 相册公开令牌(不可枚举,持有即可访问)。 */ token: components["parameters"]["AlbumPublicToken"]; /** @description 照片 ID。 */ photoId: components["parameters"]["PhotoId"]; }; cookie?: never; }; /** * 公开照片下载 * @description 匿名下载(ov 域部署,观众动作端点故归 interactions)。按相册两级下载 * 开关校验(A18):variant=browse 需 downloadEnabled;variant=original * 需 originalDownloadEnabled(在 downloadEnabled 基础上的更高级开关, * 两者均开才可下载原图)。对应级别开关关闭 → 403 DOWNLOAD_DISABLED; * 相册/照片不可见 404(ALBUM_NOT_PUBLIC/PHOTO_NOT_PUBLIC,不区分枚举)。 * URL 为短期签名凭证,禁止持久保存/写入分享链接,过期经本端点刷新; * 服务端日志不记完整签名 URL。 */ get: operations["downloadPublicPhoto"]; put?: never; post?: never; 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; export interface components { schemas: { /** * @description 稳定错误码(服务器生成,与 src/errors.ts 的 ErrorCodes 一一对应, * 1:1 类型守护见 __tests__/events.test.ts);P4a 起供批量逐项结果等 * 内嵌失败原因复用。 * @enum {string} */ ErrorCode: "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" | "DOWNLOAD_DISABLED" | "VALIDATION_FAILED" | "SYNC_AUTH_FAILED" | "INTERNAL_ERROR"; Error: { code: components["schemas"]["ErrorCode"]; /** @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 修改密码请求(P3 Task 3 契约增补)。 */ PasswordChangeRequest: { /** @description 当前密码。 */ oldPassword: string; /** @description 新密码(至少 8 位)。 */ newPassword: 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" | "deleted"; 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; /** * Format: date-time * @description 统计副本最近同步时间(P2 A27:ov→cn 统计快照在本相册的应用时刻); * null 表示尚无回传应用(viewCountReplica 副本位仍为初始 0)。照片级 * 点赞副本(PhotoRecord.likeCount)的同步时间不经相册行表达。 */ readonly statsSyncedAt: string | null; /** * @description 相册封面摘要(UI-01,readOnly 可选扩展):当前生效封面资产 * (album_assets kind=cover、state=effective 的最新一行)的短期 * 签名 URL;未配置封面为 null。宣传图/封面共用(2026-09-23 决策): * 未配置封面时回退最新生效宣传图(传一张即可两用)。列表端点按页 * 批量组装(非逐相册查询);旧客户端忽略本字段不受影响。 */ readonly cover?: components["schemas"]["SignedUrl"] | null; }; AlbumList: components["schemas"]["CursorPageMeta"] & { items: components["schemas"]["AlbumSummary"][]; }; Album: components["schemas"]["AlbumSummary"] & { /** @description 相册分类(按 sortOrder 升序)。 */ categories: components["schemas"]["Category"][]; }; /** * @description 水印配置(P4a A18,创建请求与当前配置响应共用)。enabled=false 表示 * 关闭水印(新照片不加水印),其余字段此时被忽略;可选字段缺省用服务端 * 默认值。 */ WatermarkConfig: { /** @description 是否开启浏览图水印。 */ enabled: boolean; /** * @description 水印位置;缺省服务端默认。 * @enum {string} */ position?: "topLeft" | "topRight" | "bottomLeft" | "bottomRight" | "center"; /** @description 不透明度百分比。 */ opacity?: number; /** @description 水印尺寸相对浏览图宽度的百分比。 */ scalePercent?: number; /** @description 文字水印参数;缺省不绘制文字。 */ text?: components["schemas"]["WatermarkTextConfig"]; }; /** @description 文字水印参数(SVG 渲染实现,Task 3 登记)。 */ WatermarkTextConfig: { /** @description 文字内容。 */ content?: string; /** @description 字号(像素)。 */ fontSize?: number; }; /** @description 重生成任务受理结果;configVersion 为本次保存的配置版本。 */ WatermarkJobCreated: { /** @description 重生成任务 ID。 */ readonly jobId: string; /** @description 本次保存的水印配置版本(新照片即刻套用)。 */ readonly configVersion: number; }; /** * @description 重生成任务状态;failed 可重新发起(按照片粒度幂等续跑)。 * @enum {string} */ WatermarkJobState: "pending" | "running" | "done" | "failed"; /** @description 历史重生成任务条目(进度供前端轮询)。 */ WatermarkJob: { /** @description 任务 ID。 */ readonly jobId: string; /** @description 目标配置版本。 */ readonly configVersion: number; state: components["schemas"]["WatermarkJobState"]; /** @description 已处理张数(含失败)。 */ readonly progress: number; /** @description 待处理总张数。 */ readonly total: number; /** @description 失败张数。 */ readonly failed: number; /** @description 任务失败原因(state=failed 时必有)。 */ errorCode?: components["schemas"]["ErrorCode"]; /** * Format: date-time * @description 任务创建时间。 */ readonly createdAt: string; }; /** @description 当前生效的水印配置。 */ WatermarkCurrent: { /** @description 当前配置版本(同 AlbumSummary.watermarkVersion)。 */ readonly configVersion: number; config: components["schemas"]["WatermarkConfig"]; }; /** @description 水印配置与任务状态;current 从未配置为 null(watermarkVersion=0)。 */ WatermarkJobsStatus: { /** @description 当前生效配置;从未配置为 null。 */ current: components["schemas"]["WatermarkCurrent"] | null; /** @description 历史任务(创建时间倒序)。 */ jobs: components["schemas"]["WatermarkJob"][]; }; /** * @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; }; /** @description 单个生效资产(管理端现状展示用)。 */ AssetStatusItem: { /** @enum {string} */ kind: "banner" | "cover" | "logo"; /** @description 语言标签(banner 可带;null=全局)。 */ locale: string | null; /** @description 现签短期 GET URL。 */ url: string; /** Format: date-time */ expiresAt: string; contentType: string; /** Format: date-time */ createdAt: string; }; /** @description 各 (kind, locale) 组合最新生效资产列表。 */ AssetStatusResponse: { items: components["schemas"]["AssetStatusItem"][]; }; 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 客户端首次生成并持久化的设备标识;服务端历史返回用于区分上传来源 * (A19)。可选;同一 clientTaskId 幂等重放时保留首次落库的值。 */ sourceDeviceId?: string; /** * @description 跳过服务端查重(P0-1 层 2)。仅相册 owner/admin 可用;协作者 * 传 true 无效。false(缺省)时:同 albumId+uploaderId+bytes * 已有非 deleted 照片 → 409 PHOTO_DUPLICATE。 * @default false */ force: boolean; }; /** @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"]; preview?: components["schemas"]["PhotoPreview"]; }; 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; /** * @description 发起该上传的设备标识(客户端首次生成并持久化;init 时未携带为 null)。 * P3 Task 3 契约增补(A19 设备来源语义)。 */ readonly sourceDeviceId?: string | null; photo: components["schemas"]["UploadSessionPhoto"]; }; UploadSessionList: components["schemas"]["CursorPageMeta"] & { items: components["schemas"]["UploadSessionRecord"][]; }; /** @description 查重预检请求条目(与 initUpload 入参同形;filename 仅元数据)。 */ UploadDuplicateCheckItem: { /** @description 原始文件名(仅元数据;查重谓词不使用,与 init 查重一致)。 */ filename: string; /** * Format: int64 * @description 申明文件字节数(查重键)。 */ bytes: number; }; /** @description 批量查重预检请求;单批上限 500 项,客户端按 500 分块顺序调用。 */ UploadDuplicateCheckRequest: { /** @description 目标相册 ID。 */ albumId: string; /** @description 待查重条目(1..500 项)。 */ items: components["schemas"]["UploadDuplicateCheckItem"][]; }; /** @description 单条命中结果;每个命中的「请求条目」一条(index 指向请求数组)。 */ UploadDuplicateCheckDuplicate: { /** @description 命中条目在请求 items 数组中的下标(0 起)。 */ index: number; /** * Format: int64 * @description 命中字节数(与对应请求条目一致)。 */ bytes: number; /** * Format: date-time * @description 服务端既有照片的上传时间(同 bytes 多条命中取最早)。 */ uploadedAt: string; }; /** @description 查重预检结果(命中子集,按请求下标升序)。 */ UploadDuplicateCheckResponse: { /** @description 命中子集;无命中为空数组。 */ duplicates: components["schemas"]["UploadDuplicateCheckDuplicate"][]; }; PhotoVisibilityUpdateRequest: { /** * @description 目标可见性;仅允许 hidden 与 published 间切换。 * @enum {string} */ visibility: "hidden" | "published"; }; /** @description 批量隐藏请求(P4a A16);逐项处理,部分成功。 */ PhotoHideBatchRequest: { /** @description 目标照片 ID 列表(单批上限 200,执行注意约定)。 */ photoIds: string[]; }; /** @description 单项隐藏结果;ok=false 时 code 说明原因(如 PHOTO_NOT_PUBLIC/PHOTO_NOT_FOUND)。 */ BatchHideItem: { /** @description 照片 ID。 */ readonly photoId: string; /** @description 本项是否隐藏成功。 */ readonly ok: boolean; /** @description 失败原因错误码(ok=false 时必有)。 */ code?: components["schemas"]["ErrorCode"]; }; /** @description 批量隐藏结果;results 与请求 photoIds 同序逐项对应。 */ BatchHideResult: { /** @description 逐项结果(与请求同序)。 */ results: components["schemas"]["BatchHideItem"][]; }; /** @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; }; /** * @description 管理端照片预览(UI-01,readOnly):thumb/browse 短期签名 URL 与过期 * 时间。签发条件(服务端逐张裁决):请求者有该照片管理权(admin 全部 / * 相册 owner 本相册全部 / 协作者仅自己上传)且照片有有效变体、未删除; * 隐藏照片仅 admin/owner 签发。不满足条件时 AdminPhoto.preview 为 null * (PhotoRecord 本身仍如实返回)。URL 过期后经列表重取刷新。 * 亦用于上传会话历史(UploadSessionPhoto.preview,uploader 本人视角): * 变体齐备且未隐藏/未删除时签发,否则字段缺省。 */ PhotoPreview: { thumb: components["schemas"]["SignedUrl"]; browse: components["schemas"]["SignedUrl"]; }; AdminPhoto: components["schemas"]["PhotoRecord"] & { uploader: components["schemas"]["AdminPhotoUploader"]; /** * @description 受权限管理的照片预览(UI-01,readOnly 可选扩展;无变体/已删除/ * 无权签发时为 null)。旧客户端忽略本字段不受影响。 */ readonly preview?: components["schemas"]["PhotoPreview"] | null; }; AdminPhotoList: components["schemas"]["CursorPageMeta"] & { items: components["schemas"]["AdminPhoto"][]; }; /** @description 相册负责人交接请求(A17)。 */ AlbumTransferRequest: { /** @description 新 owner 用户 ID(须为可被指定为 owner 的账号,见端点 400 说明)。 */ targetUserId: string; /** @description 原 owner 是否保留为 collaborator;false 时移出成员表。 */ keepAsCollaborator: boolean; }; /** * @description 用户治理条目(P4a;不含邮箱/手机/密码等凭据字段)。sourceStatus 只读 * 展示(上游状态仅同步任务维护)。id 用于邀请协作者 * (POST /albums/{albumId}/members 的 userId)。 */ AdminUser: { /** @description 用户 ID。 */ readonly id: string; /** @description 登录账号。 */ readonly account: string; /** @description 展示姓名。 */ readonly displayName: string; /** * @description 公司角色(staff/admin;相册角色另表)。 * @enum {string} */ readonly role: "staff" | "admin"; /** * @description 来源状态:local=本地创建;active/disabled=同步源状态(P4a 同步)。 * @enum {string} */ readonly sourceStatus: "local" | "active" | "disabled"; /** @description 本地锁定(停用/deactivate 置 true;与上游状态独立)。 */ readonly localLocked: boolean; /** * @description 凭据状态:active=可登录;pending=同步创建待激活(不可登录,待管理员激活并出初始凭据)。 * @enum {string} */ readonly credentialStatus: "active" | "pending"; /** @description 界面语言偏好;未设置为 null。 */ readonly locale?: string | null; /** * Format: date-time * @description 创建时间。 */ readonly createdAt: string; /** * @description 同步源档案快照(G4:工号/邮箱/公司/头像,来自用户同步、落 * external_user_mappings.profile 列);本地创建/未同步用户为 null。 * 纯展示维度,不参与任何治理判定。 */ readonly synced?: { /** @description 工号。 */ sn?: string; /** @description 企业邮箱。 */ email?: string; /** @description 公司全称。 */ companyName?: string; /** @description 公司简称。 */ companyAbbr?: string; /** @description 头像 URL。 */ avatar?: string; } | null; }; AdminUserList: components["schemas"]["CursorPageMeta"] & { /** @description 用户条目(前缀模式按 account 升序且仅激活资格用户;管理列表模式按 createdAt 与 ID 稳定倒序)。 */ items: components["schemas"]["AdminUser"][]; /** @description 过滤命中总数——仅管理列表 page 模式返回;游标/前缀模式为 null。 */ total?: number | null; }; /** * @description 管理列表治理状态过滤(单值归类):pending=待激活;disabled=上游停用; * locked=本地锁定;active=其余可正常登录。同时命中多状态时按 * pending > disabled > locked > active 优先级归类后匹配。 * @enum {string} */ AdminUserStatusFilter: "active" | "pending" | "disabled" | "locked"; /** @description 用户治理属性部分更新(仅提交的字段被修改;sourceStatus 不在可更新集)。 */ AdminUserUpdateRequest: { /** * @description 公司角色。 * @enum {string} */ role?: "staff" | "admin"; /** @description 本地锁定;置 true 撤销该用户全部会话。 */ localLocked?: boolean; /** @description 展示姓名。 */ displayName?: string; }; /** @description 管理员重置密码请求;newPassword 缺省由服务端生成随机密码。 */ AdminPasswordResetRequest: { /** @description 指定新密码(至少 8 位);缺省服务端生成。 */ newPassword?: string; }; /** @description 重置结果;newPassword 仅此一次返回(请求指定或服务端生成)。 */ AdminPasswordResetResponse: { /** @description 重置后的密码(一次性展示,转交用户后不再可见)。 */ readonly newPassword: string; }; /** * @description 同步引擎状态:idle=空闲/从未运行;其余为最近批次结局。 * @enum {string} */ UserSyncState: "idle" | "running" | "success" | "partial" | "failed"; /** * @description 批次状态(partial=部分行失败,其余行照常应用)。 * @enum {string} */ UserSyncRunState: "running" | "success" | "partial" | "failed"; /** @description 批次计数。 */ UserSyncCounts: { /** @description 新增用户数(建为待激活)。 */ added: number; /** @description 幂等更新数(改名等)。 */ updated: number; /** @description 上游停用数(撤会话)。 */ disabled: number; /** @description 失败行数(明细见 /admin/user-sync/errors)。 */ failed: number; }; /** @description 用户同步引擎状态(A29;mock 源先行,G4 后仅替换 provider)。 */ UserSyncStatus: { /** * Format: date-time * @description 最近批次开始时间;从未运行为 null。 */ readonly lastRunAt?: string | null; /** * Format: date-time * @description 最近完全成功批次开始时间;从未成功为 null。 */ readonly lastSuccessAt?: string | null; state: components["schemas"]["UserSyncState"]; /** * Format: int64 * @description 已提交的源水位(版本游标);从未同步为 null。 */ readonly sourceVersion?: number | null; /** @description 最近批次计数;从未运行为 null。 */ counts?: components["schemas"]["UserSyncCounts"] | null; }; /** @description 同步批次条目。 */ UserSyncRun: { /** @description 批次 ID。 */ readonly id: string; /** * @description 触发方式(定时/手动补拉)。 * @enum {string} */ readonly trigger: "cron" | "manual"; state: components["schemas"]["UserSyncRunState"]; /** * Format: int64 * @description 本批次已提交的源水位(同步游标,非分页游标);未提交为 null。 */ readonly cursor?: number | null; counts: components["schemas"]["UserSyncCounts"]; /** * Format: date-time * @description 批次开始时间。 */ readonly startedAt: string; /** * Format: date-time * @description 批次结束时间;运行中为 null。 */ readonly finishedAt?: string | null; /** @description 批次级失败摘要;无为 null。 */ readonly error?: string | null; }; UserSyncRunList: components["schemas"]["CursorPageMeta"] & { /** @description 批次列表(startedAt 与 ID 稳定倒序)。 */ items: components["schemas"]["UserSyncRun"][]; }; /** @description 手动触发受理结果。 */ UserSyncRunCreated: { /** @description 批次 ID(已有批次运行中时为该进行中批次)。 */ readonly runId: string; }; /** @description 同步失败行明细(坏行记录,其余行照常应用的证据链)。 */ UserSyncError: { /** @description 归属批次 ID。 */ readonly runId: string; /** @description 上游用户标识。 */ readonly externalUserId: string; /** @description 失败分类码(provider 级约定,如 upstream_timeout/invalid_record)。 */ readonly code: string; /** @description 失败详情(诊断用)。 */ readonly detail: string; /** * Format: date-time * @description 记录时间。 */ readonly createdAt: string; }; /** @description 失败明细列表(createdAt 倒序;无游标即取即用)。 */ UserSyncErrorList: { items: components["schemas"]["UserSyncError"][]; }; /** @description 单相册用量聚合(实时 SUM;P5 换物化/OSS 用量,登记偏差)。 */ UsageAlbum: { /** @description 相册 ID。 */ readonly albumId: string; /** @description 相册标题(defaultLocale 解析)。 */ readonly title: string; /** @description 照片总数(全部状态)。 */ readonly photoCount: number; /** * Format: int64 * @description 原图存储字节数。 */ readonly originalBytes: number; /** * Format: int64 * @description 变体(缩略/浏览/水印等)存储字节数。 */ readonly variantBytes: number; /** * Format: int64 * @description 合计字节数(originalBytes + variantBytes)。 */ readonly totalBytes: number; }; /** @description 全库用量合计。 */ UsageTotals: { /** @description 照片总数。 */ readonly photoCount: number; /** * Format: int64 * @description 存储总字节数。 */ readonly totalBytes: number; }; /** @description 用量阈值;null 表示该维度未设置(告警停用)。 */ UsageThresholds: { /** * Format: int64 * @description 全库存储阈值。 */ readonly storageBytes: number | null; /** * Format: int64 * @description 单相册存储阈值。 */ readonly perAlbumBytes: number | null; }; /** @description 阈值更新请求;字段缺省=保持不变,显式 null=清除该阈值。 */ UsageThresholdsUpdate: { /** * Format: int64 * @description 全库存储阈值;null 清除。 */ storageBytes?: number | null; /** * Format: int64 * @description 单相册存储阈值;null 清除。 */ perAlbumBytes?: number | null; }; /** * @description 阈值告警(A23 后台侧;接收人通知渠道 P5)。超阈写入一次直到回落 * (同 kind+albumId 活跃告警唯一——重复告警去重);resolvedAt 非空为 * 已解除。 */ UsageAlert: { /** @description 告警 ID。 */ readonly id: string; /** * @description 告警维度。 * @enum {string} */ readonly kind: "storage" | "perAlbum"; /** @description 相册 ID;kind=perAlbum 必有,storage 为 null。 */ readonly albumId?: string | null; /** @description 告警描述。 */ readonly message: string; /** * Format: date-time * @description 产生时间。 */ readonly createdAt: string; /** * Format: date-time * @description 解除时间(阈值上调/用量回落时标记);活跃告警为 null。 */ readonly resolvedAt?: string | null; }; /** @description 用量汇总(A23 后台侧)。 */ UsageSummary: { /** @description 相册用量(按 totalBytes 降序)。 */ albums: components["schemas"]["UsageAlbum"][]; totals: components["schemas"]["UsageTotals"]; thresholds: components["schemas"]["UsageThresholds"]; /** @description 告警列表(createdAt 倒序,含已解除)。 */ alerts: components["schemas"]["UsageAlert"][]; }; /** * @description 展示位内容语言(设置与公开查询共用):auto=按相册 defaultLocale, * 其余为指定语言(取值不支持时服务端静默回退相册 defaultLocale)。 * @enum {string} */ EmbedSlotLang: "auto" | "zh-CN" | "en"; /** * @description 展示位展示设置。整体提交语义:创建时 settings 可整体缺省(各字段按 * 下列缺省值落库),提供时字段齐全;更新为整体替换(未单独提交 * settings 则保持不变)。响应中字段恒齐全。UI-01 新增字段 * (imageFit/offsetX/offsetBottom/zIndex)为可选扩展:提交时可缺省 * (按默认值归一化落库),旧 JSON/旧客户端零影响;响应恒为归一化全集。 */ EmbedSlotSettings: { /** * @description 悬浮位置(宿主页面左/右侧)。 * @default right * @enum {string} */ position: "left" | "right"; /** * @description 组件尺寸(sm=窄屏降级档,宿主 viewport<480px 时自动降为 sm)。 * @default md * @enum {string} */ size: "sm" | "md"; /** * @description 轮播切换间隔毫秒。 * @default 5000 */ intervalMs: number; lang: components["schemas"]["EmbedSlotLang"]; /** * @description 初始是否收起(收起后仅展示小把手,点击展开)。 * @default false */ collapsedDefault: boolean; /** * @description 轮播图片适配方式(UI-01):contain=完整展示于 4:3 舞台(中性底); * cover=裁切填满舞台。可缺省(默认 contain)。 * @default contain * @enum {string} */ imageFit: "contain" | "cover"; /** * @description 组件距宿主页面边缘的水平偏移(像素,UI-01)。可缺省。 * @default 16 */ offsetX: number; /** * @description 组件距宿主页面底部的垂直偏移(像素,UI-01)。可缺省。 * @default 24 */ offsetBottom: number; /** * @description 组件在宿主页面的层级(UI-01)。可缺省。 * @default 1000 */ zIndex: number; /** * @description 展示模式(UI-04):carousel=旧版轮播(v1 loader,footer/舞台结构); * vertical-stream=新版垂直照片流(v2 loader,固定 195×280 连续上滚照片窗, * 忽略 size/intervalMs/imageFit 的布局作用)。可缺省(默认 carousel—— * UI-04 前旧记录读取归一为旧模式;新建走 v2 由管理端显式提交)。 * @default carousel * @enum {string} */ displayMode: "carousel" | "vertical-stream"; /** * @description vertical-stream 自动上滚速度(CSS px/秒,UI-04)。可缺省(默认 16); * 仅 v2 生效,carousel 模式忽略。 * @default 16 */ scrollSpeed: number; /** * @description vertical-stream 点赞心形气泡开关(UI-04)。可缺省(默认 true); * false 仅隐藏气泡(不产生 WS 订阅),照片滚动不受影响。仅 v2 生效。 * @default true */ reactionsEnabled: boolean; }; /** * @description 展示位条目(管理视角)。albumId/albumTitle 为当前绑定相册(null=未 * 绑定,公开端 404);albumTitle 按相册 defaultLocale 解析(管理列表 * 展示用)。任一管理面变更递增 configVersion。 */ EmbedSlot: { /** @description 展示位 ID。 */ readonly id: string; /** @description 展示位公开令牌(嵌入代码 data-slot 引用,不可枚举)。 */ readonly publicToken: string; /** @description 展示位名称(管理标识)。 */ name: string; /** @description 是否启用;false 即下线(公开端 404,等同删除语义)。 */ enabled: boolean; /** @description 绑定相册 ID;未绑定为 null。 */ readonly albumId: string | null; /** @description 绑定相册标题(按相册 defaultLocale 解析);未绑定为 null。 */ readonly albumTitle: string | null; /** @description 配置版本(任一管理面变更递增;嵌入端据此整体重置渲染,亦为公开端 ETag 组成部分)。 */ readonly configVersion: number; settings: components["schemas"]["EmbedSlotSettings"]; /** * Format: date-time * @description 最近更新时间。 */ readonly updatedAt: string; }; EmbedSlotList: components["schemas"]["CursorPageMeta"] & { /** @description 展示位条目(按 createdAt 与 ID 稳定倒序)。 */ items: components["schemas"]["EmbedSlot"][]; }; /** @description 创建展示位请求;settings 可整体缺省(各字段按缺省值落库),提供时字段齐全。 */ EmbedSlotCreateRequest: { /** @description 展示位名称。 */ name: string; settings?: components["schemas"]["EmbedSlotSettings"]; }; /** * @description 展示位部分更新请求(仅提交的字段被修改,空请求体 400)。settings 为 * 整体替换(提供时字段齐全);albumId:非 null 绑定/换绑目标相册(相册 * 须存在),null 解绑(公开端随即 404)——albumId 值变化即 configVersion+1。 */ EmbedSlotUpdateRequest: { /** @description 展示位名称。 */ name?: string; /** @description 启停;false 即下线(软停用,无删除端点)。 */ enabled?: boolean; settings?: components["schemas"]["EmbedSlotSettings"]; /** @description 绑定相册 ID;null 解绑。 */ albumId?: string | null; }; /** * @description 广告位条目(管理视角)。albumIds 为绑定相册 ID 列表(null=全局投放, * 空数组归一为 null);imageUrl 为现签 GET(TTL=SIGNED_URL_TTL_SECONDS), * 过期后重拉列表刷新。 */ AdminAdItem: { /** @description 广告位 ID。 */ readonly id: string; /** @description 后台备注名(不展示观众)。 */ title: string | null; /** @description 版本化终键(换图递增版本,禁止覆盖)。 */ readonly imageObjectKey: string; /** @description 现签 GET(TTL=SIGNED_URL_TTL_SECONDS)。 */ readonly imageUrl: string; /** @description 跳转链接(观众点击新开标签)。 */ linkUrl: string; /** @description 是否启用;false 公开端不可见(ov 投影行删除,无墓碑下线)。 */ enabled: boolean; /** @description 排序权重(升序,并列按 createdAt 升序决胜)。 */ sortOrder: number; /** @description 绑定相册 ID 列表;null=全局投放(未绑定)。 */ albumIds: string[] | null; /** * Format: date-time * @description 创建时间。 */ readonly createdAt: string; /** * Format: date-time * @description 最近更新时间。 */ readonly updatedAt: string; }; /** @description 广告位列表(全量不分页;sortOrder 升序、并列 createdAt 升序)。 */ AdminAdListResponse: { items: components["schemas"]["AdminAdItem"][]; }; /** * @description 创建广告位请求;albumIds 未提供或空数组=全局投放(落库归一 null), * 元素须为存在的相册 ID(去重后校验)。 */ AdCreateRequest: { /** @description 后台备注名(不展示观众)。 */ title?: string; /** @description 跳转链接(http/https)。 */ linkUrl: string; /** @description POST /admin/ads/uploads 返回的 staging 对象键。 */ imageStagingKey: string; /** @description 申明字节数(须与 staging 对象一致;上限 AD_UPLOAD_MAX_BYTES=2MB)。 */ imageBytes: number; /** * @description 申明类型(须与 staging 对象一致);heic 除外:广告无变体流水线、原图直出,桌面浏览器(Chromium/Firefox)不渲染。 * @enum {string} */ imageContentType: "image/jpeg" | "image/png"; /** @description 排序权重(缺省 0)。 */ sortOrder?: number; /** @description 绑定相册 ID 列表;未提供或空=全局。 */ albumIds?: string[]; }; /** * @description 部分更新请求(仅提交的字段被修改,空请求体 400 VALIDATION_FAILED, * 对照 EmbedSlotUpdateRequest 口径)。albumIds:未提供=不动,null=转 * 全局,数组=整体替换;imageStagingKey/imageBytes/imageContentType 三者 * 必须同时提供(换图,服务端核验 staging 后转存新版本键)。 */ AdUpdateRequest: { /** @description 后台备注名(不展示观众)。 */ title?: string; /** @description 跳转链接(http/https)。 */ linkUrl?: string; /** @description 启停;false 公开端不可见(停用事件走 high 优先级)。 */ enabled?: boolean; /** @description 排序权重。 */ sortOrder?: number; /** @description 绑定相册 ID 列表;null=转全局,数组=整体替换。 */ albumIds?: string[] | null; /** @description 换图用 staging 对象键(与 imageBytes/imageContentType 同时提供)。 */ imageStagingKey?: string; /** @description 换图申明字节数(上限 AD_UPLOAD_MAX_BYTES=2MB)。 */ imageBytes?: number; /** * @description 换图申明类型;heic 除外(同 AdCreateRequest.imageContentType:广告无变体流水线,桌面浏览器不渲染)。 * @enum {string} */ imageContentType?: "image/jpeg" | "image/png"; }; /** @description 广告图直传初始化请求(无会话概念,幂等由创建端 copyIfAbsent 承担)。 */ AdUploadInitRequest: { /** @description 原始文件名(取扩展名定 staging 键)。 */ filename: string; /** @description 申明字节数(上限 AD_UPLOAD_MAX_BYTES=2MB,超限 400)。 */ bytes: number; /** * @description MIME 类型白名单;heic 除外:广告无变体流水线、原图直出,桌面浏览器(Chromium/Firefox)不渲染。 * @enum {string} */ contentType: "image/jpeg" | "image/png"; }; AdUploadInitResponse: { /** @description staging 键 photo-live/{env}/ads/staging/{cuid}.{ext}(创建/更新时引用)。 */ readonly objectKey: string; credential: components["schemas"]["UploadCredential"]; }; /** @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。宣传图/封面共用(2026-09-23 决策): * 未配置宣传图时回退最新生效封面(传一张即可两用)。 */ 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 浏览图下载开关(P4a Task 4 / A18):false 时观众端不出现下载入口, * download 端点 browse/original 均 403 DOWNLOAD_DISABLED。 */ readonly downloadEnabled: boolean; /** * @description 原图下载开关(更高级:需与 downloadEnabled 同时开启才允许 * variant=original;单独开启不生效——两级级联语义)。 */ readonly originalDownloadEnabled: boolean; }; /** @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 展示位绑定相册摘要(title 已按 lang→相册 defaultLocale 回退解析)。 */ PublicEmbedAlbum: { /** @description 相册公开令牌(点击照片跳转 viewer 相册页用)。 */ readonly publicToken: string; /** @description 相册标题(实际返回语言)。 */ readonly title: string; defaultLocale: components["schemas"]["Locale"]; }; /** * @description 展示位照片条目(小尺寸缩略图省流量,与公开列表的 browse 大图区分; * 签名 URL 为短期凭证,过期后经本端点刷新)。 */ PublicEmbedPhoto: { /** @description 照片 ID(跳转 viewer 单图定位用)。 */ readonly photoId: string; thumb: components["schemas"]["SignedUrl"]; /** @description 缩略图宽度(像素);用于占位,减少加载跳动。 */ readonly width: number; /** @description 缩略图高度(像素)。 */ readonly height: number; }; /** * @description 展示位公开数据(嵌入组件数据源;ov 只读副本)。photos 为近期已发布 * 照片,按 publishedAt 与 ID 稳定倒序,上限 20(空数组=相册暂无已发布 * 照片,嵌入端展示空态卡)。album 当前恒非 null(未绑定/停用的展示位 * 公开端一律 404 防探测);null 为契约前瞻保留,嵌入端按空态处理。 * settings(UI-01 可选扩展)为后台配置的归一化全集(缺字段按默认值 * 补齐)——嵌入端据此应用后台配置,data-* 覆盖优先于它。 */ PublicEmbedSlot: { /** @description 展示位公开令牌(回显请求路径)。 */ readonly slotToken: string; /** @description 配置版本(嵌入端变更检测:版本变化即整体重置渲染)。 */ readonly configVersion: number; /** * @description 展示设置(UI-01 可选扩展;ov 副本 JSON 按契约默认值归一化后返回, * 恒为全集)。旧客户端忽略本字段不受影响。 */ readonly settings?: components["schemas"]["EmbedSlotSettings"]; /** @description 绑定相册摘要;未绑定为 null(当前部署不会出现,见 schema 描述)。 */ album: components["schemas"]["PublicEmbedAlbum"] | null; /** @description 近期照片(publishedAt 与 ID 稳定倒序,小尺寸缩略图)。 */ photos: components["schemas"]["PublicEmbedPhoto"][]; }; /** @description 观众端广告条目(仅展示所需字段,广告标识与关闭由前端渲染)。 */ PublicAd: { /** @description 广告位 ID。 */ readonly adId: string; /** @description 现签 GET(TTL=SIGNED_URL_TTL_SECONDS,过期后重拉本端点刷新)。 */ readonly imageUrl: string; /** @description 跳转链接(新开标签)。 */ linkUrl: string; }; /** @description 公开广告列表(无广告为空 items,非 404)。 */ PublicAdListResponse: { items: components["schemas"]["PublicAd"][]; }; /** * @description 下载版本(P4a A18):browse=当前生效浏览图(水印版); * original=原图(需 originalDownloadEnabled 更高级开关)。 * @enum {string} */ DownloadVariant: "browse" | "original"; PublicPhotoDownload: components["schemas"]["SignedUrl"] & { variant: components["schemas"]["DownloadVariant"]; }; /** * @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=新访次,或幂等重放已确认计入的 requestId * (回显原结局);false=去重窗口内重复或过期 requestId 重放 * (均不重复计数)。 */ readonly counted: boolean; }; /** * @description 同步实体类型(slot-state 为预留给后续阶段)。 * @enum {string} */ SyncEntityType: "album" | "category" | "photo" | "asset" | "slot-state" | "ad"; /** * @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 展示位 ID。 */ EmbedSlotId: string; /** @description 展示位公开令牌(不可枚举,持有即可访问;格式见 EmbedSlot.publicToken)。 */ EmbedSlotToken: string; /** @description 广告位 ID。 */ AdId: string; /** @description 分页游标(上一页响应的 nextCursor)。 */ CursorQuery: string; /** @description 请求语言;缺省或取值不支持时按相册 defaultLocale 回退(不报 400,响应 resolvedLocale 指示实际返回语言)。 */ LocaleQuery: components["schemas"]["Locale"]; }; requestBodies: never; headers: never; pathItems: never; } export type $defs = Record; 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"]; }; }; changePassword: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["PasswordChangeRequest"]; }; }; responses: { /** @description 修改成功,无响应体;当前会话保留,其他会话已撤销。 */ 204: { headers: { [name: string]: unknown; }; content?: never; }; /** @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"]; }; }; 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"]; }; }; deleteAlbum: { parameters: { query?: never; header?: never; path: { /** @description 相册 ID。 */ albumId: components["parameters"]["AlbumId"]; }; cookie?: never; }; requestBody?: never; responses: { /** @description 已删除(幂等:重复删除同样 204)。 */ 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"]; }; }; }; }; 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"]; }; }; getWatermarkJobs: { 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"]["WatermarkJobsStatus"]; }; }; 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"]; }; }; createWatermarkJob: { parameters: { query?: never; header?: never; path: { /** @description 相册 ID。 */ albumId: components["parameters"]["AlbumId"]; }; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["WatermarkConfig"]; }; }; responses: { /** @description 配置已保存、重生成任务已受理(异步执行,进度经 GET 查询)。 */ 202: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["WatermarkJobCreated"]; }; }; /** @description 参数校验失败(VALIDATION_FAILED;opacity/scalePercent/fontSize 越界等)。 */ 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"]; }; }; listAlbumAssetStatus: { 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"]["AssetStatusResponse"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 相册不存在(ALBUM_NOT_FOUND,含已删除)。 */ 404: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; }; }; 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"]; }; }; checkUploadDuplicates: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["UploadDuplicateCheckRequest"]; }; }; responses: { /** @description 查重结果(命中子集;无命中时 duplicates 为空数组)。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["UploadDuplicateCheckResponse"]; }; }; /** @description 参数校验失败(VALIDATION_FAILED):items 为空/超 500 项或条目字段非法。 */ 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"]; }; }; 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 数据范围(UI-01):all=本相册全部照片(缺省,仅 owner/admin); * own=仅当前用户上传(任何有效成员,服务端过滤)。 */ scope?: "all" | "own"; /** @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 仅创建者或管理员可访问全量管理列表(scope=all 或缺省时协作者 * AUTH_FORBIDDEN);scope=own 需相册有效成员。 */ 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"]; }; }; hidePhotosBatch: { parameters: { query?: never; header?: never; path: { /** @description 相册 ID。 */ albumId: components["parameters"]["AlbumId"]; }; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["PhotoHideBatchRequest"]; }; }; responses: { /** @description 批量处理结果(逐项;单项失败不影响其余项)。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["BatchHideResult"]; }; }; /** @description 参数校验失败(VALIDATION_FAILED;photoIds 空/超 200/含空串)。 */ 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"]; }; }; transferAlbum: { parameters: { query?: never; header?: never; path: { /** @description 相册 ID。 */ albumId: components["parameters"]["AlbumId"]; }; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["AlbumTransferRequest"]; }; }; responses: { /** @description 交接后的相册详情(ownerId 已变更)。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Album"]; }; }; /** * @description 参数校验失败(VALIDATION_FAILED;targetUserId 非法,或目标账号 * 不可被指定为 owner——不存在/停用/待激活/锁定)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可交接相册负责人(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"]; }; }; listAdminUsers: { parameters: { query?: { /** @description 账号或姓名前缀(≥2 字符以防过宽匹配;提供即进入前缀模式;大小写敏感——中文姓名无大小写语义)。 */ accountPrefix?: string; /** * @description 管理列表过滤:账号或展示名前缀(大小写敏感二进制前缀匹配,同 * accountPrefix 规则;不做全文搜索)。 */ query?: string; /** @description 管理列表过滤:治理状态单值归类(归类优先级见 AdminUserStatusFilter)。 */ status?: components["schemas"]["AdminUserStatusFilter"]; /** @description 分页游标(上一页响应的 nextCursor)。 */ cursor?: components["parameters"]["CursorQuery"]; /** @description 每页条数(游标模式)。 */ limit?: number; /** * @description 页码(偏移分页模式):提供 page 且不带 cursor 时启用,响应返回 * total 且 nextCursor=null / hasMore=false(翻页由 total 驱动)。 * 未提供 → 游标模式(keyset,兼容旧客户端);提供 cursor 时忽略 * page。仅管理列表模式有意义。 */ page?: number; /** @description 偏移分页每页条数(仅 page 模式生效,缺省 20)。 */ pageSize?: number; }; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description 用户列表页(前缀模式无匹配为空数组)。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["AdminUserList"]; }; }; /** * @description 查询参数校验失败(VALIDATION_FAILED;accountPrefix/query 长度非法、 * status 取值非法、cursor/limit 非法)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 管理列表模式仅 admin 可用(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; updateAdminUser: { parameters: { query?: never; header?: never; path: { /** @description 用户 ID。 */ userId: components["parameters"]["UserId"]; }; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["AdminUserUpdateRequest"]; }; }; responses: { /** @description 更新后的用户条目。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["AdminUser"]; }; }; /** @description 参数校验失败(VALIDATION_FAILED;role 取值非法、displayName 长度非法、空请求体)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可管理用户(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description 目标用户不存在(NOT_FOUND)。 */ 404: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; resetAdminUserPassword: { parameters: { query?: never; header?: never; path: { /** @description 用户 ID。 */ userId: components["parameters"]["UserId"]; }; cookie?: never; }; requestBody?: { content: { "application/json": components["schemas"]["AdminPasswordResetRequest"]; }; }; responses: { /** @description 重置成功(newPassword 为请求指定或服务端生成)。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["AdminPasswordResetResponse"]; }; }; /** @description 参数校验失败(VALIDATION_FAILED;newPassword 长度非法)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可重置密码(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description 目标用户不存在(NOT_FOUND)。 */ 404: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; activateAdminUser: { parameters: { query?: never; header?: never; path: { /** @description 用户 ID。 */ userId: components["parameters"]["UserId"]; }; cookie?: never; }; requestBody?: never; responses: { /** @description 激活后的用户条目(credentialStatus=active)。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["AdminUser"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可激活用户(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description 目标用户不存在(NOT_FOUND)。 */ 404: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; deactivateAdminUser: { parameters: { query?: never; header?: never; path: { /** @description 用户 ID。 */ userId: components["parameters"]["UserId"]; }; cookie?: never; }; requestBody?: never; responses: { /** @description 停用后的用户条目(localLocked=true)。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["AdminUser"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可停用用户(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description 目标用户不存在(NOT_FOUND)。 */ 404: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; getUserSyncStatus: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description 同步状态。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["UserSyncStatus"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可查看同步状态(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; listUserSyncRuns: { 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"]["UserSyncRunList"]; }; }; /** @description 查询参数校验失败(VALIDATION_FAILED;cursor/limit 非法)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可查看运行历史(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; triggerUserSyncRun: { parameters: { query?: { /** @description 分页游标(上一页响应的 nextCursor)。 */ cursor?: components["parameters"]["CursorQuery"]; /** @description 每页条数。 */ limit?: number; }; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description 已受理(或复用进行中批次)。 */ 202: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["UserSyncRunCreated"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可手动触发(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; listUserSyncErrors: { parameters: { query: { /** @description 批次 ID。 */ runId: string; }; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description 失败明细(createdAt 倒序;无失败为空数组)。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["UserSyncErrorList"]; }; }; /** @description 查询参数校验失败(VALIDATION_FAILED;runId 缺失)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可查看失败明细(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; getUsageSummary: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description 用量汇总。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["UsageSummary"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可查看用量(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; updateUsageThresholds: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["UsageThresholdsUpdate"]; }; }; responses: { /** @description 更新后的阈值。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["UsageThresholds"]; }; }; /** @description 参数校验失败(VALIDATION_FAILED;负值或非整数)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可更新阈值(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; listEmbedSlots: { 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"]["EmbedSlotList"]; }; }; /** @description 查询参数校验失败(VALIDATION_FAILED;cursor/limit 非法)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可管理展示位(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; createEmbedSlot: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["EmbedSlotCreateRequest"]; }; }; responses: { /** @description 创建后的展示位条目。 */ 201: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["EmbedSlot"]; }; }; /** @description 请求体校验失败(VALIDATION_FAILED;name 长度非法、settings 字段越界或取值非法)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可管理展示位(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; deleteEmbedSlot: { parameters: { query?: never; header?: never; path: { /** @description 展示位 ID。 */ id: components["parameters"]["EmbedSlotId"]; }; 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 展示位不存在(EMBED_SLOT_NOT_FOUND,含已删除)。 */ 404: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; }; }; updateEmbedSlot: { parameters: { query?: never; header?: never; path: { /** @description 展示位 ID。 */ id: components["parameters"]["EmbedSlotId"]; }; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["EmbedSlotUpdateRequest"]; }; }; responses: { /** @description 更新后的展示位条目。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["EmbedSlot"]; }; }; /** @description 参数校验失败(VALIDATION_FAILED;name 长度非法、settings 字段越界或取值非法、空请求体)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可管理展示位(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description 展示位不存在(NOT_FOUND),或绑定目标相册不存在(ALBUM_NOT_FOUND)。 */ 404: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; listAdminAds: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody?: never; responses: { /** @description 广告位列表(全量)。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["AdminAdListResponse"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可管理广告位(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; createAd: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["AdCreateRequest"]; }; }; responses: { /** @description 创建后的广告位条目。 */ 201: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["AdminAdItem"]; }; }; /** * @description 参数校验失败:linkUrl 非 http(s)/超长、albumIds 含不存在的相册 * (VALIDATION_FAILED),或 staging 核验失败——对象缺失/字节或类型 * 与申明不一致(UPLOAD_VERIFY_FAILED)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可管理广告位(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; initAdUpload: { parameters: { query?: never; header?: never; path?: never; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["AdUploadInitRequest"]; }; }; responses: { /** @description staging 对象键与临时直传凭证。 */ 201: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["AdUploadInitResponse"]; }; }; /** @description 参数校验失败(VALIDATION_FAILED):超过 2MB 限额、类型不接受或文件名扩展名非法。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可管理广告位(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; deleteAd: { parameters: { query?: never; header?: never; path: { /** @description 广告位 ID。 */ adId: components["parameters"]["AdId"]; }; cookie?: never; }; requestBody?: never; responses: { /** @description 已删除。 */ 204: { headers: { [name: string]: unknown; }; content?: never; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可管理广告位(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description 广告位不存在(NOT_FOUND)。 */ 404: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; }; }; updateAd: { parameters: { query?: never; header?: never; path: { /** @description 广告位 ID。 */ adId: components["parameters"]["AdId"]; }; cookie?: never; }; requestBody: { content: { "application/json": components["schemas"]["AdUpdateRequest"]; }; }; responses: { /** @description 更新后的广告位条目。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["AdminAdItem"]; }; }; /** * @description 参数校验失败(VALIDATION_FAILED):字段非法、空请求体、换图三字段 * 未同时提供或 staging 核验失败(UPLOAD_VERIFY_FAILED)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 401: components["responses"]["Unauthorized"]; /** @description 仅 admin 可管理广告位(AUTH_FORBIDDEN)。 */ 403: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description 广告位不存在(NOT_FOUND)。 */ 404: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 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"]; }; }; listPublicAds: { parameters: { query?: never; header?: never; path: { /** @description 相册公开令牌(不可枚举,持有即可访问)。 */ token: components["parameters"]["AlbumPublicToken"]; }; cookie?: never; }; requestBody?: never; responses: { /** @description 公开广告列表(可为空数组)。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["PublicAdListResponse"]; }; }; /** @description 相册不存在或未公开(ALBUM_NOT_PUBLIC,不区分以避免枚举)。 */ 404: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; 500: components["responses"]["InternalError"]; }; }; getPublicEmbedSlot: { parameters: { query?: { /** @description 内容语言;auto(缺省)按相册 defaultLocale,取值不支持时静默回退(不报 400)。 */ lang?: components["schemas"]["EmbedSlotLang"]; }; header?: { /** @description 条件请求:先前响应返回的 ETag 值;匹配则返回 304。 */ "If-None-Match"?: string; }; path: { /** @description 展示位公开令牌(不可枚举,持有即可访问;格式见 EmbedSlot.publicToken)。 */ slotToken: components["parameters"]["EmbedSlotToken"]; }; cookie?: never; }; requestBody?: never; responses: { /** @description 展示位公开数据。 */ 200: { headers: { /** @description 强校验器(组成与失效语义见端点 description)。 */ ETag?: string; [name: string]: unknown; }; content: { "application/json": components["schemas"]["PublicEmbedSlot"]; }; }; /** @description 内容未变(If-None-Match 匹配);无响应体。 */ 304: { headers: { /** @description 当前 ETag(与匹配值一致)。 */ ETag?: string; [name: string]: unknown; }; content?: never; }; /** @description 查询参数校验失败(VALIDATION_FAILED;lang 取值不支持时不报错,按相册 defaultLocale 回退)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description 展示位不存在、已停用或未绑定相册(NOT_FOUND;不区分以避免枚举)。 */ 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"]; }; }; downloadPublicPhoto: { parameters: { query: { /** @description 下载版本。 */ variant: components["schemas"]["DownloadVariant"]; }; header?: never; path: { /** @description 相册公开令牌(不可枚举,持有即可访问)。 */ token: components["parameters"]["AlbumPublicToken"]; /** @description 照片 ID。 */ photoId: components["parameters"]["PhotoId"]; }; cookie?: never; }; requestBody?: never; responses: { /** @description 下载凭证(短期签名 URL)。 */ 200: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["PublicPhotoDownload"]; }; }; /** @description 查询参数校验失败(VALIDATION_FAILED;variant 缺失或取值非法)。 */ 400: { headers: { [name: string]: unknown; }; content: { "application/json": components["schemas"]["Error"]; }; }; /** @description 相册下载开关关闭(DOWNLOAD_DISABLED;对应 variant 所需级别的开关未开)。 */ 403: { 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"]; }; }; 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"]; }; }; }