openapi: 3.0.3
info:
  title: Shortdramas Center API
  version: 0.1.0
  description: |
    创作者中心独立服务。鉴权：X-Admin-Key（维护）或 X-Api-Key（平台）。
    不挂钩中台 SSO。支持登录会话与短剧明细·分销明细导出。

    可视化调试：打开 `/docs`；YAML 下载：`/docs/openapi.yaml?download=1`。
servers:
  - url: http://127.0.0.1:8090
components:
  securitySchemes:
    AdminKey:
      type: apiKey
      in: header
      name: X-Admin-Key
      description: 管理台 Key（本地默认见 env）
    ApiKey:
      type: apiKey
      in: header
      name: X-Api-Key
      description: 平台调用 Key
security:
  - AdminKey: []
  - ApiKey: []
paths:
  /healthz:
    get:
      summary: Health
      responses:
        '200':
          description: ok
  /api/v1/accounts:
    get:
      summary: 账号列表
      parameters:
        - in: header
          name: X-Api-Key
          required: true
          schema: { type: string }
      responses:
        '200':
          description: items
    put:
      summary: 创建/更新账号
      parameters:
        - in: header
          name: X-Api-Key
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [orgName, copyrightCenter, phone]
              properties:
                id: { type: string }
                orgName: { type: string }
                copyrightCenter: { type: string }
                phone: { type: string }
                loginAccount: { type: string }
                enabled: { type: boolean }
                clearSession: { type: boolean }
      responses:
        '200':
          description: account
  /api/v1/accounts/{id}/login:
    post:
      summary: 异步登录建会话
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
        - in: header
          name: X-Api-Key
          required: true
          schema: { type: string }
      responses:
        '200':
          description: accepted + jobId
  /api/v1/accounts/{id}/session:
    get:
      summary: 会话探针
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
      responses:
        '200':
          description: alive
  /api/v1/accounts/{id}/open-home-ticket:
    post:
      summary: 签发本机打开首页票据
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
      responses:
        '200':
          description: ticket + helperHttpUrl
  /api/v1/accounts/{id}/login-link:
    post:
      summary: 签发外出 H5 登录链接（复制给同事）
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
      responses:
        '200':
          description: url + token（约 30 分钟）
  /api/v1/accounts/{id}/export-distributor-detail:
    post:
      summary: 导出分销明细（默认同步等待）
      description: |
        对应页面 https://shortdramas.com/page/settlement/books-details 分销明细。
        固定 settlement_genre=203。默认同步等待本请求完成，直接返回 fileBase64（xlsx）与 rows。
        多账户请并发多个 HTTP 请求（各等各的）；勿依赖轮询。
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [settlementWeek]
              properties:
                settlementWeek: { type: string, example: "2026-07-R3" }
                pageSize: { type: integer, default: 500 }
                bookId: { type: string, description: "可选作品ID过滤" }
                async: { type: boolean, default: false, description: "true 时仅返回 jobId" }
      responses:
        '200':
          description: fileName / fileBase64 / rows / rowCount
  /api/v1/export/distributor-detail:
    post:
      summary: 对外导出分销明细（accountId 或 copyrightCenter）
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required: [settlementWeek]
              properties:
                accountId: { type: string }
                copyrightCenter: { type: string }
                settlementWeek: { type: string, example: "2026-07-R3" }
                bookId: { type: string }
                async: { type: boolean, default: false }
      responses:
        '200':
          description: 默认同步返回 xlsx base64
  /api/v1/jobs/{id}:
    get:
      summary: 查询任务摘要（不含大结果）
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
      responses:
        '200':
          description: status / rowCount / hasResult
  /api/v1/jobs/{id}/result:
    get:
      summary: 导出任务完整结果（含 rows / fileBase64）
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
      responses:
        '200':
          description: rows + xlsx base64
  /api/v1/jobs/{id}/download.xlsx:
    get:
      summary: 下载导出 xlsx（表头对齐短剧明细·分销明细）
      parameters:
        - in: path
          name: id
          required: true
          schema: { type: string }
      responses:
        '200':
          description: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
  /api/v1/public/login-assist:
    get:
      summary: H5 查询登录链状态
      parameters:
        - in: query
          name: t
          required: true
          schema: { type: string }
      responses:
        '200':
          description: phoneMasked / hasSession / jobStatus
  /api/v1/public/login-assist/start:
    post:
      summary: H5 触发 Playwright 登录
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                t: { type: string }
      responses:
        '200':
          description: jobId
  /api/v1/public/login-assist/sms:
    post:
      summary: H5 提交短信验证码
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                t: { type: string }
                code: { type: string }
      responses:
        '200':
          description: ok
  /api/v1/sms-code:
    post:
      summary: 提交短信验证码
      requestBody:
        content:
          application/json:
            schema:
              type: object
              properties:
                phone: { type: string }
                code: { type: string }
      responses:
        '200':
          description: ok
  /api/v1/internal/sms-code:
    get:
      summary: Worker 轮询取码
      parameters:
        - in: header
          name: X-SMS-Token
          schema: { type: string }
        - in: query
          name: phone
          schema: { type: string }
      responses:
        '200':
          description: code
  /api/v1/internal/open-home/redeem:
    get:
      summary: 本机助手兑票
      parameters:
        - in: query
          name: ticket
          required: true
          schema: { type: string }
      responses:
        '200':
          description: sessionState
