This commit is contained in:
大哥大哥的大哥哥
2026-09-09 14:47:29 +08:00
parent 4d9da40abd
commit 65755c9e96
832 changed files with 412085 additions and 0 deletions
+240
View File
@@ -0,0 +1,240 @@
openapi: 3.1.0
info:
title: 唐侦探独立章节存档
version: 1.0.0
description: >-
使用原小程序 token,仅操作登录用户自己的 season-01 ID 存档。
不接收健康回答、正文、快照或客户端用户身份。业务错误沿用 HTTP 200/code 约定。
servers:
- url: /api
security:
- MiniProgramToken: []
paths:
/tang/catalog:
get:
operationId: getTangDetectiveCatalog
summary: 读取部署版本的 ID 白名单
responses:
'200':
description: code=1 为目录,code=0/-1 为错误
content:
application/json:
schema:
oneOf:
- type: object
required: [code, show, msg, data]
properties:
code: {const: 1}
show: {const: 0}
msg: {type: string}
data: {$ref: '#/components/schemas/Catalog'}
- {$ref: '#/components/schemas/Failure'}
/tang/progress:
get:
operationId: getTangDetectiveProgress
summary: 只读当前登录用户存档,无存档返回 revision=0 的默认值
responses:
'200':
$ref: '#/components/responses/ProgressResponse'
/tang/saveProgress:
post:
operationId: saveTangDetectiveProgress
summary: 版本匹配时替换整份 ID 投影或重新开始故事
description: >-
原始请求体最多 32768 字节。最后一次 request_id 的相同规范化内容可幂等重试。
必须匹配 base_revision 和 story_generation;冲突不覆盖、不自动合并。
reset_story 必须提交空故事字段,收藏为当前服务器与该请求的已验证卡 ID 并集。
requestBody:
required: true
content:
application/json:
schema: {$ref: '#/components/schemas/SaveRequest'}
responses:
'200':
$ref: '#/components/responses/ProgressResponse'
components:
securitySchemes:
MiniProgramToken:
type: apiKey
in: header
name: token
description: 沿用现有 LoginMiddleware;不是 Authorization,也不放入请求正文。
responses:
ProgressResponse:
description: >-
必须检查 codecode=1 的 data 是本人确认存档。
此控制器的响应含 Cache-Control no-store。
headers:
Cache-Control:
schema: {type: string, const: no-store}
content:
application/json:
schema:
oneOf:
- {$ref: '#/components/schemas/ProgressSuccess'}
- {$ref: '#/components/schemas/Failure'}
schemas:
ChapterId:
type: string
pattern: '^S01-C(0[1-9]|1[0-5])$'
EventId:
type: string
pattern: '^S01-H(0[1-9]|[1-5][0-9]|60)$'
PageId:
type: string
pattern: '^S01-C(0[1-9]|1[0-5])-P0[1-8]$'
CardId:
type: string
pattern: '^S01-C(0[1-9]|1[0-5])-MC01$'
Catalog:
type: object
additionalProperties: false
required: [game_id, schema_version, content_version, max_body_bytes, chapters]
properties:
game_id: {const: tang-detective}
schema_version: {const: 1}
content_version: {const: season-01}
max_body_bytes: {const: 32768}
chapters:
type: array
minItems: 15
maxItems: 15
items:
type: object
additionalProperties: false
required: [chapter_id, chapter_number, hotspot_ids, page_ids, memory_card_id]
properties:
chapter_id: {$ref: '#/components/schemas/ChapterId'}
chapter_number: {type: integer, minimum: 1, maximum: 15}
hotspot_ids:
type: array
minItems: 4
maxItems: 4
uniqueItems: true
items: {$ref: '#/components/schemas/EventId'}
page_ids:
type: array
minItems: 8
maxItems: 8
uniqueItems: true
items: {$ref: '#/components/schemas/PageId'}
memory_card_id: {$ref: '#/components/schemas/CardId'}
Reader:
type: object
additionalProperties: false
required: [currentPageId, completedEventIds, chapterFinished]
properties:
currentPageId: {$ref: '#/components/schemas/PageId'}
completedEventIds:
type: array
maxItems: 4
uniqueItems: true
items: {$ref: '#/components/schemas/EventId'}
chapterFinished: {type: boolean}
description: >-
事件必须是所属章节的连续前缀且与 completedHotspots 相同;
chapterFinished 必须与 completedChapters 成员关系一致,为 true 时须有四事件。
未 finished 仅允许 P01 至 P(03+事件数),最多 P07P08 必须 finished。
Progress:
type: object
additionalProperties: false
required: [completedHotspots, completedChapters, lastChapter, collectedMemoryCards, comicReaderByChapter, lastPageId]
properties:
completedHotspots:
type: object
maxProperties: 15
propertyNames: {$ref: '#/components/schemas/ChapterId'}
additionalProperties:
type: array
maxItems: 4
uniqueItems: true
items: {$ref: '#/components/schemas/EventId'}
completedChapters:
type: array
maxItems: 15
uniqueItems: true
items: {$ref: '#/components/schemas/ChapterId'}
lastChapter: {type: integer, minimum: 1, maximum: 15}
collectedMemoryCards:
type: array
maxItems: 15
uniqueItems: true
items: {$ref: '#/components/schemas/CardId'}
comicReaderByChapter:
type: object
maxProperties: 15
propertyNames: {$ref: '#/components/schemas/ChapterId'}
additionalProperties: {$ref: '#/components/schemas/Reader'}
lastPageId:
oneOf:
- {const: ''}
- {$ref: '#/components/schemas/PageId'}
description: >-
空映射必须是 {},不是 []。有已完成事件或 finished 的章节必须有 reader。
非空 lastPageId 必须等于 lastChapter 对应 reader.currentPageId。
跨字段成员关系、顺序和解锁约束由 TangDetectiveProgress 验证。
SaveRequest:
type: object
additionalProperties: false
required: [schema_version, content_version, base_revision, story_generation, request_id, operation, progress]
properties:
schema_version: {type: integer, const: 1}
content_version: {const: season-01}
base_revision: {type: integer, minimum: 0, maximum: 2147483646}
story_generation: {type: integer, minimum: 0, maximum: 2147483646}
request_id: {type: string, pattern: '^[A-Za-z0-9_-]{16,64}$'}
operation: {enum: [replace, reset_story]}
progress: {$ref: '#/components/schemas/Progress'}
allOf:
- if:
properties:
operation: {const: reset_story}
then:
properties:
progress:
properties:
completedHotspots: {maxProperties: 0}
completedChapters: {maxItems: 0}
lastChapter: {const: 1}
comicReaderByChapter: {maxProperties: 0}
lastPageId: {const: ''}
State:
type: object
additionalProperties: false
required: [user_id, schema_version, content_version, revision, story_generation, progress]
properties:
user_id: {type: integer, minimum: 1}
schema_version: {const: 1}
content_version: {const: season-01}
revision: {type: integer, minimum: 0}
story_generation: {type: integer, minimum: 0}
progress: {$ref: '#/components/schemas/Progress'}
idempotent:
type: boolean
description: 仅保存响应提供;true 表示重复确认最后一次提交,未重复写入。
ProgressSuccess:
type: object
required: [code, show, msg, data]
properties:
code: {const: 1}
show: {const: 0}
msg: {type: string}
data: {$ref: '#/components/schemas/State'}
Failure:
type: object
required: [code, show, msg, data]
properties:
code: {type: integer, enum: [0, -1]}
show: {type: integer, enum: [0, 1]}
msg: {type: string}
data:
oneOf:
- type: object
additionalProperties: false
required: [error_code]
properties:
error_code:
enum: [INVALID_REQUEST, PAYLOAD_TOO_LARGE, UNSUPPORTED_CONTENT_VERSION, PROGRESS_CONFLICT, IDEMPOTENCY_CONFLICT, METHOD_NOT_ALLOWED, UNSUPPORTED_MEDIA_TYPE, AUTH_REQUIRED, STORAGE_UNAVAILABLE]
- type: array
maxItems: 0
description: 原登录中间件可能提前返回空 data;登录过期 code=-1。