2791 lines
75 KiB
Markdown
2791 lines
75 KiB
Markdown
# Muse 四仓开发 — 主执行计划
|
||
|
||
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
||
|
||
**目标:** 从零搭建 Muse 四仓(muse-cloud / muse-studio / muse-admin),实现 6 个业务模块全量 API + 双前端,完成集成切换和质量加固。
|
||
|
||
**架构:** API-first + 三仓并行。Phase 0 在本仓产出 OpenAPI 3.0 契约文件,Phase 1 三仓并行开发(后端逐步产出真实 API,前端先 Mock 独立开发),Phase 2 按模块逐个切换真实 API 并完成质量加固。
|
||
|
||
**技术栈:** Java 21 + Spring Boot 3 + PostgreSQL 16 + Yudao Cloud(后端)| React + Vite + TypeScript + TanStack Query + Tiptap(用户端)| Vue 3 + Vben Admin + TypeScript(管理端)
|
||
|
||
---
|
||
|
||
## 子计划索引
|
||
|
||
本计划覆盖 18 周、4 个代码仓库。按子系统拆分为 5 个子计划:
|
||
|
||
| # | 子计划 | 仓库 | 周期 | 状态 |
|
||
|---|--------|------|------|------|
|
||
| P0 | [API 契约冻结](#phase-0-api-契约冻结) | muse-design-docs | Week 1-2 | 就绪 |
|
||
| P1 | [muse-cloud 后端搭建](docs/superpowers/plans/2026-05-24-P1-muse-cloud.md)(待创建) | muse-cloud | Week 3-16 | P0 完成后 |
|
||
| P2 | [muse-studio 用户端搭建](docs/superpowers/plans/2026-05-24-P2-muse-studio.md)(待创建) | muse-studio | Week 3-16 | P0 完成后 |
|
||
| P3 | [muse-admin 管理端搭建](docs/superpowers/plans/2026-05-24-P3-muse-admin.md)(待创建) | muse-admin | Week 3-16 | P0 完成后 |
|
||
| P4 | [集成切换 + 质量加固](docs/superpowers/plans/2026-05-24-P4-集成切换.md)(待创建) | 四仓联合 | Week 9-18 | P1-P3 部分完成后 |
|
||
|
||
**依赖关系:**
|
||
|
||
```mermaid
|
||
graph TD
|
||
P0[P0: API 契约冻结] --> P1[P1: muse-cloud 后端]
|
||
P0 --> P2[P2: muse-studio 用户端]
|
||
P0 --> P3[P3: muse-admin 管理端]
|
||
P1 --> P4[P4: 集成切换]
|
||
P2 --> P4
|
||
P3 --> P4
|
||
```
|
||
|
||
---
|
||
|
||
## 前置条件
|
||
|
||
- [x] Spec: `docs/superpowers/specs/2026-05-24-Muse四仓开发计划-design.md`
|
||
- [x] 设计文档 SSOT: `design-docs/` 下 30+ 份正式文档
|
||
- [x] AI 开发管理基线: `docs/dev-baseline/` 下各仓规范
|
||
- [x] muse-cloud fork 完成(Yudao Cloud)
|
||
- [x] muse-admin fork 完成(Vben Admin)
|
||
- [ ] muse-studio 需从零创建
|
||
|
||
---
|
||
|
||
## Phase 0: API 契约冻结
|
||
|
||
**仓库:** muse-design-docs(本仓)
|
||
**周期:** Week 1-2
|
||
**输入:** `design-docs/后端-05-统一API契约-v1.md`(767 行,146+ 接口)
|
||
**输出:** 6 个模块的 OpenAPI 3.0 YAML + TypeScript 类型包 + Java DTO 骨架
|
||
|
||
### Task 0.0: 准备工作
|
||
|
||
**文件:**
|
||
- 创建: `docs/api-contracts/openapi-base.yaml`
|
||
- 创建: `docs/api-contracts/content/openapi.yaml`
|
||
- 创建: `docs/api-contracts/ai/openapi.yaml`
|
||
- 创建: `docs/api-contracts/knowledge/openapi.yaml`
|
||
- 创建: `docs/api-contracts/market/openapi.yaml`
|
||
- 创建: `docs/api-contracts/account/openapi.yaml`
|
||
- 创建: `docs/api-contracts/meta/openapi.yaml`
|
||
- 创建: `docs/api-contracts/generated/typescript/.gitkeep`
|
||
- 创建: `docs/api-contracts/generated/java/.gitkeep`
|
||
|
||
- [ ] **Step 1: 创建目录结构**
|
||
|
||
```bash
|
||
mkdir -p docs/api-contracts/{content,ai,knowledge,market,account,meta,generated/typescript,generated/java}
|
||
```
|
||
|
||
- [ ] **Step 2: 提交空目录结构(含 .gitkeep)**
|
||
|
||
```bash
|
||
touch docs/api-contracts/generated/typescript/.gitkeep
|
||
touch docs/api-contracts/generated/java/.gitkeep
|
||
git add docs/api-contracts/
|
||
git commit -m "feat(api): 初始化 API 契约目录结构"
|
||
```
|
||
|
||
### Task 0.1: 编写 openapi-base.yaml(全局配置)
|
||
|
||
**文件:**
|
||
- 创建: `docs/api-contracts/openapi-base.yaml`
|
||
- 参考: `design-docs/后端-05-统一API契约-v1.md` 全局约定章节
|
||
- 参考: `design-docs/架构-03-关键决策与原则(ADR).md` ADR-010 (API 版本)
|
||
|
||
- [ ] **Step 1: 从设计文档提取全局配置信息**
|
||
|
||
阅读 `后端-05` 中的:
|
||
- 认证方式(Bearer Token / OAuth2)
|
||
- 分页格式(pageNo + pageSize,CommonResult<T> 包裹)
|
||
- 错误格式(system-module-category-sequence 四段式错误码)
|
||
- API 版本策略(X-API-Version Header)
|
||
- 通用响应格式(code + message + data)
|
||
|
||
- [ ] **Step 2: 编写 openapi-base.yaml**
|
||
|
||
```yaml
|
||
openapi: 3.0.3
|
||
info:
|
||
title: Muse API
|
||
description: |
|
||
Muse AI 驱动长篇创作平台统一 API 契约。
|
||
所有接口通过 X-API-Version Header 进行版本控制。
|
||
version: 1.0.0
|
||
contact:
|
||
name: Muse Team
|
||
|
||
servers:
|
||
- url: http://localhost:48080
|
||
description: 本地开发环境
|
||
|
||
security:
|
||
- bearerAuth: []
|
||
|
||
components:
|
||
securitySchemes:
|
||
bearerAuth:
|
||
type: http
|
||
scheme: bearer
|
||
bearerFormat: JWT
|
||
description: |
|
||
用户端使用 app-api token,管理端使用 admin-api token。
|
||
两个端点的认证域独立,token 不互通。
|
||
|
||
parameters:
|
||
XApiVersion:
|
||
name: X-API-Version
|
||
in: header
|
||
required: false
|
||
schema:
|
||
type: string
|
||
default: "2026-05-01"
|
||
description: API 版本号,格式 YYYY-MM-DD
|
||
|
||
pageNo:
|
||
name: pageNo
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: integer
|
||
minimum: 1
|
||
default: 1
|
||
description: 页码,从 1 开始
|
||
|
||
pageSize:
|
||
name: pageSize
|
||
in: query
|
||
required: false
|
||
schema:
|
||
type: integer
|
||
minimum: 1
|
||
maximum: 100
|
||
default: 20
|
||
description: 每页条数,上限 100
|
||
|
||
schemas:
|
||
CommonResult:
|
||
type: object
|
||
required: [code, message]
|
||
properties:
|
||
code:
|
||
type: integer
|
||
description: 业务状态码,0 表示成功
|
||
example: 0
|
||
message:
|
||
type: string
|
||
description: 提示信息
|
||
example: "操作成功"
|
||
data:
|
||
description: 响应数据,类型视具体接口而定
|
||
|
||
PaginatedResult:
|
||
type: object
|
||
required: [total, pageNo, pageSize, list]
|
||
properties:
|
||
total:
|
||
type: integer
|
||
description: 总记录数
|
||
example: 150
|
||
pageNo:
|
||
type: integer
|
||
description: 当前页码
|
||
example: 1
|
||
pageSize:
|
||
type: integer
|
||
description: 每页条数
|
||
example: 20
|
||
list:
|
||
type: array
|
||
description: 当前页数据列表
|
||
|
||
ErrorResponse:
|
||
type: object
|
||
required: [code, message]
|
||
properties:
|
||
code:
|
||
type: string
|
||
description: |
|
||
错误码格式: {system}-{module}-{category}-{sequence}
|
||
示例: MUSE-CONTENT-001-0001
|
||
example: "MUSE-CONTENT-001-0001"
|
||
message:
|
||
type: string
|
||
description: 人类可读的错误描述
|
||
detail:
|
||
type: string
|
||
description: 详细错误信息(仅开发环境返回)
|
||
|
||
# 通用时间戳字段
|
||
TimestampMixin:
|
||
type: object
|
||
properties:
|
||
createdAt:
|
||
type: string
|
||
format: date-time
|
||
description: 创建时间
|
||
updatedAt:
|
||
type: string
|
||
format: date-time
|
||
description: 最后更新时间
|
||
|
||
responses:
|
||
BadRequest:
|
||
description: 请求参数有误
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
Unauthorized:
|
||
description: 未认证或 token 过期
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
Forbidden:
|
||
description: 无权限
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
NotFound:
|
||
description: 资源不存在
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
Conflict:
|
||
description: 资源冲突
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
InternalError:
|
||
description: 服务器内部错误
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '#/components/schemas/ErrorResponse'
|
||
|
||
tags:
|
||
- name: Content
|
||
description: 作品、章节、Block、导出
|
||
- name: AI
|
||
description: AI 生成、候选管理、智能体、质量门控
|
||
- name: Knowledge
|
||
description: 知识实体、关系、草稿、确认
|
||
- name: Market
|
||
description: 资产发布、安装绑定、审核
|
||
- name: Account
|
||
description: 权益、配额、用量、安全事件
|
||
- name: Meta
|
||
description: MetaSchema 字段定义、版本、scope
|
||
```
|
||
|
||
- [ ] **Step 3: 提交**
|
||
|
||
```bash
|
||
git add docs/api-contracts/openapi-base.yaml
|
||
git commit -m "feat(api): 添加 OpenAPI 全局基础配置(认证/分页/错误格式/版本)"
|
||
```
|
||
|
||
### Task 0.2: 编写 Content 模块 OpenAPI
|
||
|
||
**文件:**
|
||
- 创建: `docs/api-contracts/content/openapi.yaml`
|
||
- 参考: `design-docs/后端-05-统一API契约-v1.md` Content 模块章节
|
||
|
||
- [ ] **Step 1: 从 API 契约文档提取 Content 模块接口列表**
|
||
|
||
Content 模块包含:
|
||
- 作品(Work) CRUD
|
||
- 章节(Chapter) CRUD + 排序
|
||
- Block CRUD + 分割/合并
|
||
- 导出(TXT/EPUB/DOCX)
|
||
|
||
- [ ] **Step 2: 编写 content/openapi.yaml**
|
||
|
||
```yaml
|
||
openapi: 3.0.3
|
||
info:
|
||
title: Muse Content API
|
||
version: 1.0.0
|
||
|
||
paths:
|
||
# ========== 作品(Work) ==========
|
||
/app-api/content/works:
|
||
get:
|
||
tags: [Content]
|
||
summary: 获取作品列表
|
||
operationId: listWorks
|
||
parameters:
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageNo'
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageSize'
|
||
- name: status
|
||
in: query
|
||
schema:
|
||
type: string
|
||
enum: [draft, active, archived]
|
||
description: 作品状态过滤
|
||
responses:
|
||
'200':
|
||
description: 作品分页列表
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/PaginatedResult'
|
||
- type: object
|
||
properties:
|
||
list:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/WorkSummary'
|
||
post:
|
||
tags: [Content]
|
||
summary: 创建新作品
|
||
operationId: createWork
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [title]
|
||
properties:
|
||
title:
|
||
type: string
|
||
minLength: 1
|
||
maxLength: 200
|
||
description:
|
||
type: string
|
||
maxLength: 2000
|
||
genre:
|
||
type: string
|
||
coverImageUrl:
|
||
type: string
|
||
format: uri
|
||
responses:
|
||
'201':
|
||
description: 作品创建成功
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
$ref: '#/components/schemas/Work'
|
||
|
||
/app-api/content/works/{workId}:
|
||
get:
|
||
tags: [Content]
|
||
summary: 获取作品详情
|
||
operationId: getWork
|
||
parameters:
|
||
- name: workId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 作品详情
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
$ref: '#/components/schemas/Work'
|
||
put:
|
||
tags: [Content]
|
||
summary: 更新作品
|
||
operationId: updateWork
|
||
parameters:
|
||
- name: workId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
title:
|
||
type: string
|
||
maxLength: 200
|
||
description:
|
||
type: string
|
||
maxLength: 2000
|
||
genre:
|
||
type: string
|
||
coverImageUrl:
|
||
type: string
|
||
format: uri
|
||
status:
|
||
type: string
|
||
enum: [draft, active, archived]
|
||
responses:
|
||
'200':
|
||
description: 更新成功
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
delete:
|
||
tags: [Content]
|
||
summary: 删除作品
|
||
operationId: deleteWork
|
||
parameters:
|
||
- name: workId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 删除成功
|
||
'404':
|
||
$ref: '../openapi-base.yaml#/components/responses/NotFound'
|
||
|
||
# ========== 章节(Chapter) ==========
|
||
/app-api/content/works/{workId}/chapters:
|
||
get:
|
||
tags: [Content]
|
||
summary: 获取作品章节列表
|
||
operationId: listChapters
|
||
parameters:
|
||
- name: workId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 章节列表(按 sortOrder 排序)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Chapter'
|
||
post:
|
||
tags: [Content]
|
||
summary: 创建章节
|
||
operationId: createChapter
|
||
parameters:
|
||
- name: workId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [title]
|
||
properties:
|
||
title:
|
||
type: string
|
||
minLength: 1
|
||
maxLength: 500
|
||
sortOrder:
|
||
type: integer
|
||
description: 插入位置,默认追加到末尾
|
||
responses:
|
||
'201':
|
||
description: 创建成功
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
$ref: '#/components/schemas/Chapter'
|
||
|
||
/app-api/content/chapters/{chapterId}:
|
||
get:
|
||
tags: [Content]
|
||
summary: 获取章节详情
|
||
operationId: getChapter
|
||
parameters:
|
||
- name: chapterId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 章节详情(含 Block 列表)
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
$ref: '#/components/schemas/ChapterDetail'
|
||
put:
|
||
tags: [Content]
|
||
summary: 更新章节
|
||
operationId: updateChapter
|
||
parameters:
|
||
- name: chapterId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
title:
|
||
type: string
|
||
maxLength: 500
|
||
sortOrder:
|
||
type: integer
|
||
status:
|
||
type: string
|
||
enum: [draft, completed]
|
||
responses:
|
||
'200':
|
||
description: 更新成功
|
||
delete:
|
||
tags: [Content]
|
||
summary: 删除章节
|
||
operationId: deleteChapter
|
||
parameters:
|
||
- name: chapterId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 删除成功
|
||
|
||
/app-api/content/chapters/{chapterId}/reorder:
|
||
put:
|
||
tags: [Content]
|
||
summary: 调整章节排序
|
||
operationId: reorderChapters
|
||
parameters:
|
||
- name: chapterId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [newSortOrder]
|
||
properties:
|
||
newSortOrder:
|
||
type: integer
|
||
minimum: 0
|
||
responses:
|
||
'200':
|
||
description: 排序更新成功
|
||
|
||
# ========== Block ==========
|
||
/app-api/content/chapters/{chapterId}/blocks:
|
||
get:
|
||
tags: [Content]
|
||
summary: 获取章节 Block 列表
|
||
operationId: listBlocks
|
||
parameters:
|
||
- name: chapterId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: Block 列表
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Block'
|
||
post:
|
||
tags: [Content]
|
||
summary: 创建 Block
|
||
operationId: createBlock
|
||
parameters:
|
||
- name: chapterId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [content, blockType]
|
||
properties:
|
||
content:
|
||
type: string
|
||
description: Block 正文内容(JSON 格式的 ProseMirror 文档)
|
||
blockType:
|
||
type: string
|
||
enum: [scene, section, note]
|
||
description: Block 类型
|
||
sortOrder:
|
||
type: integer
|
||
title:
|
||
type: string
|
||
maxLength: 500
|
||
responses:
|
||
'201':
|
||
description: 创建成功
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
$ref: '#/components/schemas/Block'
|
||
|
||
/app-api/content/blocks/{blockId}:
|
||
get:
|
||
tags: [Content]
|
||
summary: 获取 Block 详情
|
||
operationId: getBlock
|
||
parameters:
|
||
- name: blockId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: Block 详情
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
$ref: '#/components/schemas/Block'
|
||
put:
|
||
tags: [Content]
|
||
summary: 保存 Block 正文
|
||
operationId: saveBlock
|
||
parameters:
|
||
- name: blockId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [content, sourceVersion]
|
||
properties:
|
||
content:
|
||
type: string
|
||
description: Block 正文(ProseMirror JSON)
|
||
sourceVersion:
|
||
type: integer
|
||
description: 客户端持有的版本号,用于乐观锁冲突检测
|
||
responses:
|
||
'200':
|
||
description: 保存成功
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
type: object
|
||
properties:
|
||
newVersion:
|
||
type: integer
|
||
description: 保存后的新版本号
|
||
'409':
|
||
description: 版本冲突,需客户端处理
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: '../openapi-base.yaml#/components/schemas/ErrorResponse'
|
||
delete:
|
||
tags: [Content]
|
||
summary: 删除 Block
|
||
operationId: deleteBlock
|
||
parameters:
|
||
- name: blockId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 删除成功
|
||
|
||
/app-api/content/blocks/{blockId}/split:
|
||
post:
|
||
tags: [Content]
|
||
summary: 分割 Block
|
||
operationId: splitBlock
|
||
parameters:
|
||
- name: blockId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [splitPosition]
|
||
properties:
|
||
splitPosition:
|
||
type: integer
|
||
description: 分割位置(字符偏移量)
|
||
responses:
|
||
'200':
|
||
description: 分割成功,返回两个新 Block
|
||
|
||
/app-api/content/blocks/{blockId}/merge:
|
||
post:
|
||
tags: [Content]
|
||
summary: 合并 Block
|
||
operationId: mergeBlocks
|
||
parameters:
|
||
- name: blockId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
description: 与下一个 Block 合并
|
||
responses:
|
||
'200':
|
||
description: 合并成功
|
||
|
||
# ========== 导出 ==========
|
||
/app-api/content/works/{workId}/export:
|
||
post:
|
||
tags: [Content]
|
||
summary: 导出作品
|
||
operationId: exportWork
|
||
parameters:
|
||
- name: workId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [format]
|
||
properties:
|
||
format:
|
||
type: string
|
||
enum: [txt, epub, docx]
|
||
includeChapters:
|
||
type: array
|
||
items:
|
||
type: string
|
||
format: uuid
|
||
description: 指定导出章节,空数组表示导出全部
|
||
responses:
|
||
'200':
|
||
description: 导出任务已创建,返回任务 ID 供轮询
|
||
'202':
|
||
description: 导出文件二进制流(小文件直接返回)
|
||
|
||
components:
|
||
schemas:
|
||
Work:
|
||
type: object
|
||
required: [id, title, status, createdAt, updatedAt]
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
title:
|
||
type: string
|
||
description:
|
||
type: string
|
||
genre:
|
||
type: string
|
||
coverImageUrl:
|
||
type: string
|
||
format: uri
|
||
status:
|
||
type: string
|
||
enum: [draft, active, archived]
|
||
wordCount:
|
||
type: integer
|
||
description: 总字数
|
||
chapterCount:
|
||
type: integer
|
||
description: 章节数
|
||
createdAt:
|
||
type: string
|
||
format: date-time
|
||
updatedAt:
|
||
type: string
|
||
format: date-time
|
||
|
||
WorkSummary:
|
||
type: object
|
||
required: [id, title, status, updatedAt]
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
title:
|
||
type: string
|
||
genre:
|
||
type: string
|
||
status:
|
||
type: string
|
||
enum: [draft, active, archived]
|
||
wordCount:
|
||
type: integer
|
||
chapterCount:
|
||
type: integer
|
||
updatedAt:
|
||
type: string
|
||
format: date-time
|
||
|
||
Chapter:
|
||
type: object
|
||
required: [id, workId, title, sortOrder, status, createdAt, updatedAt]
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
workId:
|
||
type: string
|
||
format: uuid
|
||
title:
|
||
type: string
|
||
sortOrder:
|
||
type: integer
|
||
status:
|
||
type: string
|
||
enum: [draft, completed]
|
||
wordCount:
|
||
type: integer
|
||
blockCount:
|
||
type: integer
|
||
createdAt:
|
||
type: string
|
||
format: date-time
|
||
updatedAt:
|
||
type: string
|
||
format: date-time
|
||
|
||
ChapterDetail:
|
||
allOf:
|
||
- $ref: '#/components/schemas/Chapter'
|
||
- type: object
|
||
properties:
|
||
blocks:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Block'
|
||
|
||
Block:
|
||
type: object
|
||
required: [id, chapterId, blockType, content, sortOrder, version, createdAt, updatedAt]
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
chapterId:
|
||
type: string
|
||
format: uuid
|
||
blockType:
|
||
type: string
|
||
enum: [scene, section, note]
|
||
title:
|
||
type: string
|
||
content:
|
||
type: string
|
||
description: ProseMirror JSON 格式的正文内容
|
||
sortOrder:
|
||
type: integer
|
||
version:
|
||
type: integer
|
||
description: 乐观锁版本号,每次保存 +1
|
||
wordCount:
|
||
type: integer
|
||
createdAt:
|
||
type: string
|
||
format: date-time
|
||
updatedAt:
|
||
type: string
|
||
format: date-time
|
||
```
|
||
|
||
- [ ] **Step 3: 提交**
|
||
|
||
```bash
|
||
git add docs/api-contracts/content/openapi.yaml
|
||
git commit -m "feat(api): 添加 Content 模块 OpenAPI 契约(作品/章节/Block/导出)"
|
||
```
|
||
|
||
### Task 0.3: 编写 AI 模块 OpenAPI
|
||
|
||
**文件:**
|
||
- 创建: `docs/api-contracts/ai/openapi.yaml`
|
||
- 参考: `design-docs/后端-05-统一API契约-v1.md` AI 模块章节
|
||
- 参考: `design-docs/专题-03-AI编排上下文与质量评测实现规范.md`
|
||
|
||
- [ ] **Step 1: 提取 AI 模块接口**
|
||
|
||
AI 模块包含:
|
||
- 生成请求(提交生成任务)
|
||
- 候选(Candidate)管理(列表、详情、接受/拒绝)
|
||
- SSE 流式传输(AI stream 独立端点)
|
||
- 智能体(Agent)管理(创建、配置、槽位绑定)
|
||
- 质量门控配置
|
||
|
||
- [ ] **Step 2: 编写 ai/openapi.yaml**
|
||
|
||
```yaml
|
||
openapi: 3.0.3
|
||
info:
|
||
title: Muse AI API
|
||
version: 1.0.0
|
||
|
||
paths:
|
||
# ========== AI 生成 ==========
|
||
/app-api/ai/generations:
|
||
post:
|
||
tags: [AI]
|
||
summary: 提交 AI 生成请求
|
||
operationId: requestGeneration
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [blockId, agentId]
|
||
properties:
|
||
blockId:
|
||
type: string
|
||
format: uuid
|
||
description: 目标 Block
|
||
agentId:
|
||
type: string
|
||
format: uuid
|
||
description: 使用的智能体
|
||
prompt:
|
||
type: string
|
||
description: 用户附加的提示词
|
||
contextBlocks:
|
||
type: array
|
||
items:
|
||
type: string
|
||
format: uuid
|
||
description: 上下文 Block ID 列表
|
||
responses:
|
||
'202':
|
||
description: 生成任务已提交
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
type: object
|
||
properties:
|
||
generationId:
|
||
type: string
|
||
format: uuid
|
||
|
||
/app-api/ai/generations/{generationId}:
|
||
get:
|
||
tags: [AI]
|
||
summary: 获取生成任务状态
|
||
operationId: getGenerationStatus
|
||
parameters:
|
||
- name: generationId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 生成状态
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
$ref: '#/components/schemas/Generation'
|
||
|
||
# ========== SSE: AI Stream(独立连接) ==========
|
||
/app-api/ai/generations/{generationId}/stream:
|
||
get:
|
||
tags: [AI]
|
||
summary: AI 生成 SSE 流
|
||
operationId: streamGeneration
|
||
parameters:
|
||
- name: generationId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: SSE 事件流
|
||
content:
|
||
text/event-stream:
|
||
schema:
|
||
type: string
|
||
description: |
|
||
事件类型:
|
||
- chunk: { "content": "文本片段", "sequenceNo": 1 }
|
||
- quality_check: { "dimension": "fluency", "score": 0.92, "passed": true }
|
||
- done: { "generationId": "uuid", "candidateId": "uuid" }
|
||
- error: { "code": "...", "message": "..." }
|
||
|
||
# ========== 候选(Candidate)管理 ==========
|
||
/app-api/ai/candidates:
|
||
get:
|
||
tags: [AI]
|
||
summary: 获取候选列表
|
||
operationId: listCandidates
|
||
parameters:
|
||
- name: blockId
|
||
in: query
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
- name: status
|
||
in: query
|
||
schema:
|
||
type: string
|
||
enum: [pending, accepted, rejected]
|
||
responses:
|
||
'200':
|
||
description: 候选列表
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Candidate'
|
||
|
||
/app-api/ai/candidates/{candidateId}:
|
||
get:
|
||
tags: [AI]
|
||
summary: 获取候选详情
|
||
operationId: getCandidate
|
||
parameters:
|
||
- name: candidateId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 候选详情(含生成内容 diff)
|
||
|
||
/app-api/ai/candidates/{candidateId}/accept:
|
||
post:
|
||
tags: [AI]
|
||
summary: 接受候选
|
||
operationId: acceptCandidate
|
||
parameters:
|
||
- name: candidateId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
modifications:
|
||
type: string
|
||
description: 用户在接受前对候选内容的手动修改
|
||
responses:
|
||
'200':
|
||
description: 候选已接受,Block 正文更新
|
||
'409':
|
||
description: 源版本已变更,需重新对比
|
||
$ref: '../openapi-base.yaml#/components/responses/Conflict'
|
||
|
||
/app-api/ai/candidates/{candidateId}/reject:
|
||
post:
|
||
tags: [AI]
|
||
summary: 拒绝候选
|
||
operationId: rejectCandidate
|
||
parameters:
|
||
- name: candidateId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
reason:
|
||
type: string
|
||
description: 拒绝原因(可选,用于改进生成质量)
|
||
responses:
|
||
'200':
|
||
description: 已拒绝
|
||
|
||
# ========== 智能体(Agent) ==========
|
||
/app-api/ai/agents:
|
||
get:
|
||
tags: [AI]
|
||
summary: 获取智能体列表
|
||
operationId: listAgents
|
||
parameters:
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageNo'
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageSize'
|
||
- name: type
|
||
in: query
|
||
schema:
|
||
type: string
|
||
enum: [config, custom]
|
||
description: 智能体类型
|
||
responses:
|
||
'200':
|
||
description: 智能体分页列表
|
||
post:
|
||
tags: [AI]
|
||
summary: 创建自定义智能体
|
||
operationId: createAgent
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [name]
|
||
properties:
|
||
name:
|
||
type: string
|
||
maxLength: 100
|
||
description:
|
||
type: string
|
||
maxLength: 1000
|
||
promptTemplate:
|
||
type: string
|
||
description: 系统提示词模板
|
||
slotBindings:
|
||
type: object
|
||
description: 槽位绑定配置(知识库/MetaSchema/模型参数)
|
||
responses:
|
||
'201':
|
||
description: 创建成功
|
||
|
||
/app-api/ai/agents/{agentId}:
|
||
get:
|
||
tags: [AI]
|
||
summary: 获取智能体详情
|
||
operationId: getAgent
|
||
parameters:
|
||
- name: agentId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 智能体详情
|
||
put:
|
||
tags: [AI]
|
||
summary: 更新智能体配置
|
||
operationId: updateAgent
|
||
parameters:
|
||
- name: agentId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
name:
|
||
type: string
|
||
description:
|
||
type: string
|
||
promptTemplate:
|
||
type: string
|
||
slotBindings:
|
||
type: object
|
||
status:
|
||
type: string
|
||
enum: [active, archived]
|
||
responses:
|
||
'200':
|
||
description: 更新成功
|
||
delete:
|
||
tags: [AI]
|
||
summary: 删除自定义智能体
|
||
operationId: deleteAgent
|
||
parameters:
|
||
- name: agentId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 删除成功
|
||
|
||
# ========== 管理端: Prompt 模板管理 ==========
|
||
/admin-api/ai/prompt-templates:
|
||
get:
|
||
tags: [AI]
|
||
summary: 获取 Prompt 模板列表(管理端)
|
||
operationId: adminListPromptTemplates
|
||
parameters:
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageNo'
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageSize'
|
||
responses:
|
||
'200':
|
||
description: 模板分页列表
|
||
post:
|
||
tags: [AI]
|
||
summary: 创建 Prompt 模板(管理端)
|
||
operationId: adminCreatePromptTemplate
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [name, template]
|
||
properties:
|
||
name:
|
||
type: string
|
||
template:
|
||
type: string
|
||
variables:
|
||
type: array
|
||
items:
|
||
type: object
|
||
properties:
|
||
name:
|
||
type: string
|
||
type:
|
||
type: string
|
||
enum: [string, number, boolean]
|
||
required:
|
||
type: boolean
|
||
defaultValue:
|
||
type: string
|
||
responses:
|
||
'201':
|
||
description: 创建成功
|
||
|
||
/admin-api/ai/prompt-templates/{templateId}:
|
||
put:
|
||
tags: [AI]
|
||
summary: 更新 Prompt 模板(管理端)
|
||
operationId: adminUpdatePromptTemplate
|
||
parameters:
|
||
- name: templateId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 更新成功
|
||
delete:
|
||
tags: [AI]
|
||
summary: 删除 Prompt 模板(管理端)
|
||
operationId: adminDeletePromptTemplate
|
||
parameters:
|
||
- name: templateId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 删除成功
|
||
|
||
# ========== 管理端: 质量门控配置 ==========
|
||
/admin-api/ai/quality-gates:
|
||
get:
|
||
tags: [AI]
|
||
summary: 获取质量门控维度列表
|
||
operationId: adminListQualityGates
|
||
responses:
|
||
'200':
|
||
description: 质量门控维度列表
|
||
post:
|
||
tags: [AI]
|
||
summary: 创建质量门控维度
|
||
operationId: adminCreateQualityGate
|
||
responses:
|
||
'201':
|
||
description: 创建成功
|
||
|
||
/admin-api/ai/protection-nodes:
|
||
get:
|
||
tags: [AI]
|
||
summary: 获取保护节点列表
|
||
operationId: adminListProtectionNodes
|
||
responses:
|
||
'200':
|
||
description: 保护节点列表
|
||
post:
|
||
tags: [AI]
|
||
summary: 注册保护节点
|
||
operationId: adminCreateProtectionNode
|
||
responses:
|
||
'201':
|
||
description: 注册成功
|
||
|
||
components:
|
||
schemas:
|
||
Generation:
|
||
type: object
|
||
required: [id, blockId, agentId, status, createdAt]
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
blockId:
|
||
type: string
|
||
format: uuid
|
||
agentId:
|
||
type: string
|
||
format: uuid
|
||
status:
|
||
type: string
|
||
enum: [pending, streaming, completed, failed]
|
||
candidateId:
|
||
type: string
|
||
format: uuid
|
||
description: 生成完成后关联的候选 ID
|
||
errorMessage:
|
||
type: string
|
||
createdAt:
|
||
type: string
|
||
format: date-time
|
||
|
||
Candidate:
|
||
type: object
|
||
required: [id, blockId, generationId, status, createdAt]
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
blockId:
|
||
type: string
|
||
format: uuid
|
||
generationId:
|
||
type: string
|
||
format: uuid
|
||
agentId:
|
||
type: string
|
||
format: uuid
|
||
agentName:
|
||
type: string
|
||
status:
|
||
type: string
|
||
enum: [pending, accepted, rejected]
|
||
sourceVersion:
|
||
type: integer
|
||
description: 生成时的源 Block 版本号
|
||
diffSummary:
|
||
type: string
|
||
description: 变更摘要
|
||
qualityScores:
|
||
type: object
|
||
description: 各质量维度的评分
|
||
createdAt:
|
||
type: string
|
||
format: date-time
|
||
```
|
||
|
||
- [ ] **Step 3: 提交**
|
||
|
||
```bash
|
||
git add docs/api-contracts/ai/openapi.yaml
|
||
git commit -m "feat(api): 添加 AI 模块 OpenAPI 契约(生成/候选/SSE/智能体/管理端配置)"
|
||
```
|
||
|
||
### Task 0.4: 编写 Knowledge 模块 OpenAPI
|
||
|
||
**文件:**
|
||
- 创建: `docs/api-contracts/knowledge/openapi.yaml`
|
||
- 参考: `design-docs/后端-05-统一API契约-v1.md` Knowledge 模块章节
|
||
|
||
- [ ] **Step 1: 提取 Knowledge 模块接口**
|
||
|
||
Knowledge 模块包含:
|
||
- 知识实体(Entity) CRUD
|
||
- 知识关系(Relation) CRUD
|
||
- 知识草稿(Draft)管理
|
||
- 自动确认 + 手动确认
|
||
- 实体/关系可视化数据
|
||
- 知识来源管理
|
||
|
||
- [ ] **Step 2: 编写 knowledge/openapi.yaml**
|
||
|
||
```yaml
|
||
openapi: 3.0.3
|
||
info:
|
||
title: Muse Knowledge API
|
||
version: 1.0.0
|
||
|
||
paths:
|
||
# ========== 知识实体(Entity) ==========
|
||
/app-api/knowledge/works/{workId}/entities:
|
||
get:
|
||
tags: [Knowledge]
|
||
summary: 获取作品知识实体列表
|
||
operationId: listEntities
|
||
parameters:
|
||
- name: workId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
- name: status
|
||
in: query
|
||
schema:
|
||
type: string
|
||
enum: [confirmed, draft, conflicted]
|
||
- name: type
|
||
in: query
|
||
schema:
|
||
type: string
|
||
enum: [character, location, event, item, concept, note]
|
||
responses:
|
||
'200':
|
||
description: 实体列表
|
||
|
||
/app-api/knowledge/entities/{entityId}:
|
||
get:
|
||
tags: [Knowledge]
|
||
summary: 获取知识实体详情
|
||
operationId: getEntity
|
||
parameters:
|
||
- name: entityId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 实体详情(含关联关系和来源引用)
|
||
put:
|
||
tags: [Knowledge]
|
||
summary: 更新知识实体
|
||
operationId: updateEntity
|
||
parameters:
|
||
- name: entityId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
name:
|
||
type: string
|
||
description:
|
||
type: string
|
||
attributes:
|
||
type: object
|
||
description: 自定义属性键值对
|
||
responses:
|
||
'200':
|
||
description: 更新成功
|
||
|
||
# ========== 知识确认 ==========
|
||
/app-api/knowledge/entities/{entityId}/confirm:
|
||
post:
|
||
tags: [Knowledge]
|
||
summary: 手动确认知识实体
|
||
operationId: confirmEntity
|
||
description: |
|
||
知识实体的默认确认规则:
|
||
- 无冲突 + 非外部来源 + 置信度 > 阈值 → 自动确认
|
||
- 有冲突 或 外部来源 或 低置信度 → 需手动确认
|
||
parameters:
|
||
- name: entityId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
overrides:
|
||
type: object
|
||
description: 手动修正的属性值
|
||
responses:
|
||
'200':
|
||
description: 确认成功
|
||
|
||
/app-api/knowledge/entities/{entityId}/reject:
|
||
post:
|
||
tags: [Knowledge]
|
||
summary: 拒绝知识实体草稿
|
||
operationId: rejectEntity
|
||
parameters:
|
||
- name: entityId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
reason:
|
||
type: string
|
||
responses:
|
||
'200':
|
||
description: 已拒绝
|
||
|
||
# ========== 知识关系(Relation) ==========
|
||
/app-api/knowledge/entities/{entityId}/relations:
|
||
get:
|
||
tags: [Knowledge]
|
||
summary: 获取实体关联关系
|
||
operationId: listRelations
|
||
parameters:
|
||
- name: entityId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 关系列表
|
||
post:
|
||
tags: [Knowledge]
|
||
summary: 创建知识关系
|
||
operationId: createRelation
|
||
parameters:
|
||
- name: entityId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
description: 源实体
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [targetEntityId, relationType]
|
||
properties:
|
||
targetEntityId:
|
||
type: string
|
||
format: uuid
|
||
relationType:
|
||
type: string
|
||
example: "knows"
|
||
description:
|
||
type: string
|
||
responses:
|
||
'201':
|
||
description: 创建成功
|
||
|
||
# ========== 知识图谱可视化 ==========
|
||
/app-api/knowledge/works/{workId}/graph:
|
||
get:
|
||
tags: [Knowledge]
|
||
summary: 获取知识图谱数据
|
||
operationId: getKnowledgeGraph
|
||
description: 返回节点和边的 JSON,用于前端可视化渲染
|
||
parameters:
|
||
- name: workId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
- name: depth
|
||
in: query
|
||
schema:
|
||
type: integer
|
||
minimum: 1
|
||
maximum: 3
|
||
default: 2
|
||
description: 图谱展开深度
|
||
responses:
|
||
'200':
|
||
description: 图谱数据(nodes + edges)
|
||
|
||
# ========== 知识草稿(Draft) ==========
|
||
/app-api/knowledge/works/{workId}/drafts:
|
||
get:
|
||
tags: [Knowledge]
|
||
summary: 获取待处理知识草稿列表
|
||
operationId: listDrafts
|
||
parameters:
|
||
- name: workId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 草稿列表
|
||
```
|
||
|
||
- [ ] **Step 3: 提交**
|
||
|
||
```bash
|
||
git add docs/api-contracts/knowledge/openapi.yaml
|
||
git commit -m "feat(api): 添加 Knowledge 模块 OpenAPI 契约(实体/关系/草稿/确认/图谱)"
|
||
```
|
||
|
||
### Task 0.5: 编写 Market 模块 OpenAPI
|
||
|
||
**文件:**
|
||
- 创建: `docs/api-contracts/market/openapi.yaml`
|
||
- 参考: `design-docs/后端-05-统一API契约-v1.md` Market 模块章节
|
||
|
||
- [ ] **Step 1: 提取 Market 模块接口**
|
||
|
||
Market 模块包含:
|
||
- 资产(Asset)浏览、搜索、安装
|
||
- 资产发布(用户端提交 + 管理端审核)
|
||
- 绑定管理
|
||
- 管理端审核(上架/驳回/下架/召回)
|
||
|
||
- [ ] **Step 2: 编写 market/openapi.yaml**
|
||
|
||
```yaml
|
||
openapi: 3.0.3
|
||
info:
|
||
title: Muse Market API
|
||
version: 1.0.0
|
||
|
||
paths:
|
||
# ========== 用户端: 市场浏览 ==========
|
||
/app-api/market/assets:
|
||
get:
|
||
tags: [Market]
|
||
summary: 浏览市场资产
|
||
operationId: listAssets
|
||
parameters:
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageNo'
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageSize'
|
||
- name: type
|
||
in: query
|
||
schema:
|
||
type: string
|
||
enum: [agent, prompt_template, knowledge_source, metaschema]
|
||
- name: keyword
|
||
in: query
|
||
schema:
|
||
type: string
|
||
description: 搜索关键词
|
||
- name: sortBy
|
||
in: query
|
||
schema:
|
||
type: string
|
||
enum: [popular, newest, rating]
|
||
default: popular
|
||
responses:
|
||
'200':
|
||
description: 资产分页列表
|
||
|
||
/app-api/market/assets/{assetId}:
|
||
get:
|
||
tags: [Market]
|
||
summary: 获取资产详情
|
||
operationId: getAsset
|
||
parameters:
|
||
- name: assetId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 资产详情
|
||
|
||
# ========== 用户端: 安装与绑定 ==========
|
||
/app-api/market/assets/{assetId}/install:
|
||
post:
|
||
tags: [Market]
|
||
summary: 安装资产到我的工作区
|
||
operationId: installAsset
|
||
parameters:
|
||
- name: assetId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'201':
|
||
description: 安装成功
|
||
|
||
/app-api/market/installations:
|
||
get:
|
||
tags: [Market]
|
||
summary: 获取我的已安装资产
|
||
operationId: listInstallations
|
||
responses:
|
||
'200':
|
||
description: 已安装资产列表
|
||
|
||
/app-api/market/installations/{installationId}/bindings:
|
||
post:
|
||
tags: [Market]
|
||
summary: 绑定已安装资产到作品
|
||
operationId: bindInstallation
|
||
parameters:
|
||
- name: installationId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [workId]
|
||
properties:
|
||
workId:
|
||
type: string
|
||
format: uuid
|
||
slotConfig:
|
||
type: object
|
||
description: 槽位配置
|
||
responses:
|
||
'201':
|
||
description: 绑定成功
|
||
get:
|
||
tags: [Market]
|
||
summary: 获取资产的作品绑定列表
|
||
operationId: listBindings
|
||
parameters:
|
||
- name: installationId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 绑定列表
|
||
|
||
# ========== 用户端: 资产发布 ==========
|
||
/app-api/market/publish:
|
||
post:
|
||
tags: [Market]
|
||
summary: 发布资产到市场
|
||
operationId: publishAsset
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [name, type, sourceId]
|
||
properties:
|
||
name:
|
||
type: string
|
||
maxLength: 200
|
||
description:
|
||
type: string
|
||
maxLength: 5000
|
||
type:
|
||
type: string
|
||
enum: [agent, prompt_template, knowledge_source, metaschema]
|
||
sourceId:
|
||
type: string
|
||
format: uuid
|
||
description: 来源对象 ID
|
||
tags:
|
||
type: array
|
||
items:
|
||
type: string
|
||
coverImageUrl:
|
||
type: string
|
||
format: uri
|
||
responses:
|
||
'201':
|
||
description: 发布申请已提交,待审核
|
||
|
||
# ========== 管理端: 资产审核 ==========
|
||
/admin-api/market/reviews:
|
||
get:
|
||
tags: [Market]
|
||
summary: 获取待审核资产列表
|
||
operationId: adminListReviews
|
||
parameters:
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageNo'
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageSize'
|
||
- name: status
|
||
in: query
|
||
schema:
|
||
type: string
|
||
enum: [pending, approved, rejected]
|
||
responses:
|
||
'200':
|
||
description: 审核列表
|
||
|
||
/admin-api/market/reviews/{reviewId}/approve:
|
||
post:
|
||
tags: [Market]
|
||
summary: 审核通过
|
||
operationId: adminApproveAsset
|
||
parameters:
|
||
- name: reviewId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
note:
|
||
type: string
|
||
responses:
|
||
'200':
|
||
description: 已上架
|
||
|
||
/admin-api/market/reviews/{reviewId}/reject:
|
||
post:
|
||
tags: [Market]
|
||
summary: 审核驳回
|
||
operationId: adminRejectAsset
|
||
parameters:
|
||
- name: reviewId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [reason]
|
||
properties:
|
||
reason:
|
||
type: string
|
||
responses:
|
||
'200':
|
||
description: 已驳回
|
||
|
||
/admin-api/market/assets/{assetId}/delist:
|
||
post:
|
||
tags: [Market]
|
||
summary: 下架资产
|
||
operationId: adminDelistAsset
|
||
parameters:
|
||
- name: assetId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [reason]
|
||
properties:
|
||
reason:
|
||
type: string
|
||
responses:
|
||
'200':
|
||
description: 已下架
|
||
|
||
/admin-api/market/assets/{assetId}/recall:
|
||
post:
|
||
tags: [Market]
|
||
summary: 召回已安装资产
|
||
operationId: adminRecallAsset
|
||
parameters:
|
||
- name: assetId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [reason]
|
||
properties:
|
||
reason:
|
||
type: string
|
||
responses:
|
||
'200':
|
||
description: 已触发召回
|
||
```
|
||
|
||
- [ ] **Step 3: 提交**
|
||
|
||
```bash
|
||
git add docs/api-contracts/market/openapi.yaml
|
||
git commit -m "feat(api): 添加 Market 模块 OpenAPI 契约(浏览/安装/绑定/审核)"
|
||
```
|
||
|
||
### Task 0.6: 编写 Account 模块 OpenAPI
|
||
|
||
**文件:**
|
||
- 创建: `docs/api-contracts/account/openapi.yaml`
|
||
- 参考: `design-docs/后端-05-统一API契约-v1.md` Account 模块章节
|
||
|
||
- [ ] **Step 1: 提取 Account 模块接口**
|
||
|
||
Account 模块包含:
|
||
- 权益(Entitlement)查询
|
||
- 配额(Quota)查询 + 消费
|
||
- Token 用量统计
|
||
- 安全事件记录
|
||
|
||
- [ ] **Step 2: 编写 account/openapi.yaml**
|
||
|
||
```yaml
|
||
openapi: 3.0.3
|
||
info:
|
||
title: Muse Account API
|
||
version: 1.0.0
|
||
|
||
paths:
|
||
# ========== 权益(Entitlement) ==========
|
||
/app-api/account/entitlements:
|
||
get:
|
||
tags: [Account]
|
||
summary: 获取当前用户权益列表
|
||
operationId: listEntitlements
|
||
responses:
|
||
'200':
|
||
description: 权益列表
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Entitlement'
|
||
|
||
# ========== 配额(Quota) ==========
|
||
/app-api/account/quotas:
|
||
get:
|
||
tags: [Account]
|
||
summary: 获取当前用户配额
|
||
operationId: listQuotas
|
||
responses:
|
||
'200':
|
||
description: 配额列表
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
type: array
|
||
items:
|
||
$ref: '#/components/schemas/Quota'
|
||
|
||
# ========== 用量(Usage) ==========
|
||
/app-api/account/usage/summary:
|
||
get:
|
||
tags: [Account]
|
||
summary: 获取用量摘要
|
||
operationId: getUsageSummary
|
||
parameters:
|
||
- name: period
|
||
in: query
|
||
schema:
|
||
type: string
|
||
enum: [today, week, month, billing_cycle]
|
||
default: month
|
||
responses:
|
||
'200':
|
||
description: 用量摘要
|
||
content:
|
||
application/json:
|
||
schema:
|
||
allOf:
|
||
- $ref: '../openapi-base.yaml#/components/schemas/CommonResult'
|
||
- type: object
|
||
properties:
|
||
data:
|
||
$ref: '#/components/schemas/UsageSummary'
|
||
|
||
/app-api/account/usage/tokens:
|
||
get:
|
||
tags: [Account]
|
||
summary: 获取 Token 用量明细
|
||
operationId: getTokenUsage
|
||
parameters:
|
||
- name: startDate
|
||
in: query
|
||
schema:
|
||
type: string
|
||
format: date
|
||
- name: endDate
|
||
in: query
|
||
schema:
|
||
type: string
|
||
format: date
|
||
responses:
|
||
'200':
|
||
description: Token 用量明细
|
||
|
||
# ========== 安全事件 ==========
|
||
/app-api/account/security-events:
|
||
get:
|
||
tags: [Account]
|
||
summary: 获取安全事件列表
|
||
operationId: listSecurityEvents
|
||
parameters:
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageNo'
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageSize'
|
||
responses:
|
||
'200':
|
||
description: 安全事件分页列表
|
||
|
||
# ========== 管理端 ==========
|
||
/admin-api/account/entitlements/{userId}:
|
||
get:
|
||
tags: [Account]
|
||
summary: 查看用户权益(管理端)
|
||
operationId: adminGetUserEntitlements
|
||
parameters:
|
||
- name: userId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 用户权益详情
|
||
put:
|
||
tags: [Account]
|
||
summary: 修改用户权益(管理端)
|
||
operationId: adminUpdateUserEntitlements
|
||
parameters:
|
||
- name: userId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [entitlements]
|
||
properties:
|
||
entitlements:
|
||
type: array
|
||
items:
|
||
type: object
|
||
properties:
|
||
resourceType:
|
||
type: string
|
||
limit:
|
||
type: integer
|
||
expiresAt:
|
||
type: string
|
||
format: date-time
|
||
reason:
|
||
type: string
|
||
description: 变更原因(写入审计日志)
|
||
responses:
|
||
'200':
|
||
description: 更新成功
|
||
|
||
components:
|
||
schemas:
|
||
Entitlement:
|
||
type: object
|
||
required: [id, resourceType, limit, used, expiresAt]
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
resourceType:
|
||
type: string
|
||
description: 权益资源类型
|
||
limit:
|
||
type: integer
|
||
description: 额度上限(-1 表示无限制)
|
||
used:
|
||
type: integer
|
||
description: 已使用量
|
||
expiresAt:
|
||
type: string
|
||
format: date-time
|
||
|
||
Quota:
|
||
type: object
|
||
required: [id, resourceType, total, remaining, resetAt]
|
||
properties:
|
||
id:
|
||
type: string
|
||
format: uuid
|
||
resourceType:
|
||
type: string
|
||
total:
|
||
type: integer
|
||
remaining:
|
||
type: integer
|
||
resetAt:
|
||
type: string
|
||
format: date-time
|
||
description: 配额重置时间
|
||
|
||
UsageSummary:
|
||
type: object
|
||
properties:
|
||
totalTokens:
|
||
type: integer
|
||
totalGenerations:
|
||
type: integer
|
||
byModel:
|
||
type: object
|
||
description: 按模型的用量分布
|
||
byDate:
|
||
type: array
|
||
items:
|
||
type: object
|
||
properties:
|
||
date:
|
||
type: string
|
||
format: date
|
||
tokens:
|
||
type: integer
|
||
generations:
|
||
type: integer
|
||
```
|
||
|
||
- [ ] **Step 3: 提交**
|
||
|
||
```bash
|
||
git add docs/api-contracts/account/openapi.yaml
|
||
git commit -m "feat(api): 添加 Account 模块 OpenAPI 契约(权益/配额/用量/安全事件)"
|
||
```
|
||
|
||
### Task 0.7: 编写 Meta 模块 OpenAPI
|
||
|
||
**文件:**
|
||
- 创建: `docs/api-contracts/meta/openapi.yaml`
|
||
- 参考: `design-docs/后端-05-统一API契约-v1.md` Meta 模块章节
|
||
|
||
- [ ] **Step 1: 提取 Meta 模块接口**
|
||
|
||
Meta 模块包含 MetaSchema 的完整管理:
|
||
- 字段定义 CRUD
|
||
- 版本管理
|
||
- Scope 配置(全局/租户/用户/作品)
|
||
|
||
- [ ] **Step 2: 编写 meta/openapi.yaml**
|
||
|
||
```yaml
|
||
openapi: 3.0.3
|
||
info:
|
||
title: Muse MetaSchema API
|
||
version: 1.0.0
|
||
|
||
paths:
|
||
# ========== 字段定义 ==========
|
||
/admin-api/meta/schemas:
|
||
get:
|
||
tags: [Meta]
|
||
summary: 获取 MetaSchema 列表
|
||
operationId: adminListSchemas
|
||
parameters:
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageNo'
|
||
- $ref: '../openapi-base.yaml#/components/parameters/pageSize'
|
||
- name: scope
|
||
in: query
|
||
schema:
|
||
type: string
|
||
enum: [global, tenant, user, work]
|
||
responses:
|
||
'200':
|
||
description: MetaSchema 分页列表
|
||
post:
|
||
tags: [Meta]
|
||
summary: 创建 MetaSchema 定义
|
||
operationId: adminCreateSchema
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [name, fieldType, scope]
|
||
properties:
|
||
name:
|
||
type: string
|
||
description: 字段名(英文标识)
|
||
displayName:
|
||
type: string
|
||
description: 显示名称
|
||
fieldType:
|
||
type: string
|
||
enum: [string, text, number, boolean, date, enum, relation, json]
|
||
scope:
|
||
type: string
|
||
enum: [global, tenant, user, work]
|
||
description: 作用域
|
||
defaultValue:
|
||
description: 默认值
|
||
required:
|
||
type: boolean
|
||
default: false
|
||
enumValues:
|
||
type: array
|
||
items:
|
||
type: string
|
||
description: fieldType=enum 时的可选值
|
||
validationRules:
|
||
type: object
|
||
description: 校验规则(min/max/pattern 等)
|
||
responses:
|
||
'201':
|
||
description: 创建成功
|
||
|
||
/admin-api/meta/schemas/{schemaId}:
|
||
get:
|
||
tags: [Meta]
|
||
summary: 获取 MetaSchema 详情
|
||
operationId: adminGetSchema
|
||
parameters:
|
||
- name: schemaId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: MetaSchema 详情(含版本历史)
|
||
put:
|
||
tags: [Meta]
|
||
summary: 更新 MetaSchema 定义
|
||
operationId: adminUpdateSchema
|
||
parameters:
|
||
- name: schemaId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
properties:
|
||
displayName:
|
||
type: string
|
||
defaultValue:
|
||
description: 默认值
|
||
required:
|
||
type: boolean
|
||
enumValues:
|
||
type: array
|
||
items:
|
||
type: string
|
||
validationRules:
|
||
type: object
|
||
responses:
|
||
'200':
|
||
description: 更新成功(自动创建新版本)
|
||
delete:
|
||
tags: [Meta]
|
||
summary: 删除 MetaSchema 定义
|
||
operationId: adminDeleteSchema
|
||
parameters:
|
||
- name: schemaId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 删除成功(软删除,已有数据不受影响)
|
||
'409':
|
||
description: 有数据引用时不允许删除
|
||
$ref: '../openapi-base.yaml#/components/responses/Conflict'
|
||
|
||
# ========== 版本管理 ==========
|
||
/admin-api/meta/schemas/{schemaId}/versions:
|
||
get:
|
||
tags: [Meta]
|
||
summary: 获取 MetaSchema 版本历史
|
||
operationId: adminListSchemaVersions
|
||
parameters:
|
||
- name: schemaId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
responses:
|
||
'200':
|
||
description: 版本历史列表
|
||
|
||
/admin-api/meta/schemas/{schemaId}/versions/{version}:
|
||
get:
|
||
tags: [Meta]
|
||
summary: 获取指定版本详情
|
||
operationId: adminGetSchemaVersion
|
||
parameters:
|
||
- name: schemaId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
- name: version
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: integer
|
||
responses:
|
||
'200':
|
||
description: 版本详情
|
||
|
||
/admin-api/meta/schemas/{schemaId}/rollback:
|
||
post:
|
||
tags: [Meta]
|
||
summary: 回滚到指定版本
|
||
operationId: adminRollbackSchema
|
||
parameters:
|
||
- name: schemaId
|
||
in: path
|
||
required: true
|
||
schema:
|
||
type: string
|
||
format: uuid
|
||
requestBody:
|
||
required: true
|
||
content:
|
||
application/json:
|
||
schema:
|
||
type: object
|
||
required: [targetVersion]
|
||
properties:
|
||
targetVersion:
|
||
type: integer
|
||
reason:
|
||
type: string
|
||
responses:
|
||
'200':
|
||
description: 回滚成功,创建新版本指向目标版本配置
|
||
```
|
||
|
||
- [ ] **Step 3: 提交**
|
||
|
||
```bash
|
||
git add docs/api-contracts/meta/openapi.yaml
|
||
git commit -m "feat(api): 添加 Meta 模块 OpenAPI 契约(MetaSchema CRUD/版本/回滚)"
|
||
```
|
||
|
||
### Task 0.8: 契约完整性校验
|
||
|
||
- [ ] **Step 1: 接口数量验证**
|
||
|
||
统计各模块接口数,与 `后端-05` 设计文档对照:
|
||
|
||
```bash
|
||
echo "=== Content ===" && grep -c "operationId:" docs/api-contracts/content/openapi.yaml
|
||
echo "=== AI ===" && grep -c "operationId:" docs/api-contracts/ai/openapi.yaml
|
||
echo "=== Knowledge ===" && grep -c "operationId:" docs/api-contracts/knowledge/openapi.yaml
|
||
echo "=== Market ===" && grep -c "operationId:" docs/api-contracts/market/openapi.yaml
|
||
echo "=== Account ===" && grep -c "operationId:" docs/api-contracts/account/openapi.yaml
|
||
echo "=== Meta ===" && grep -c "operationId:" docs/api-contracts/meta/openapi.yaml
|
||
echo "=== Total ===" && grep -r "operationId:" docs/api-contracts/*/openapi.yaml docs/api-contracts/openapi-base.yaml 2>/dev/null | wc -l
|
||
```
|
||
|
||
- [ ] **Step 2: YAML 语法校验**
|
||
|
||
```bash
|
||
# 使用 Python 校验所有 YAML 文件
|
||
python3 -c "
|
||
import yaml, sys, glob
|
||
errors = []
|
||
for f in glob.glob('docs/api-contracts/**/*.yaml', recursive=True):
|
||
try:
|
||
with open(f) as fh:
|
||
yaml.safe_load(fh)
|
||
print(f'OK: {f}')
|
||
except Exception as e:
|
||
errors.append(f'{f}: {e}')
|
||
print(f'FAIL: {f}: {e}')
|
||
if errors:
|
||
print(f'\n{len(errors)} file(s) failed')
|
||
sys.exit(1)
|
||
else:
|
||
print('\nAll files valid')
|
||
"
|
||
```
|
||
|
||
- [ ] **Step 3: 交叉引用检查**
|
||
|
||
确认各模块 YAML 中的 `$ref` 路径正确指向 `openapi-base.yaml`,且被引用的 schema/response/parameter 确实存在。
|
||
|
||
- [ ] **Step 4: 与设计文档一致性复查**
|
||
|
||
逐模块对比 `后端-05-统一API契约-v1.md`:
|
||
- 接口路径是否一致
|
||
- HTTP 方法是否一致
|
||
- 路径参数名是否一致
|
||
- Request/Response body 字段是否覆盖
|
||
|
||
- [ ] **Step 5: 提交**
|
||
|
||
```bash
|
||
git add docs/api-contracts/
|
||
git commit -m "feat(api): 完成 6 个模块 OpenAPI 契约文件 + 完整性校验通过"
|
||
```
|
||
|
||
### Task 0.9: 生成 TypeScript 类型包
|
||
|
||
**文件:**
|
||
- 创建: `docs/api-contracts/generated/typescript/` 下的类型文件
|
||
- 工具: `openapi-typescript` + `openapi-fetch`
|
||
|
||
- [ ] **Step 1: 安装代码生成工具**
|
||
|
||
```bash
|
||
# 在仓库根目录安装(或使用 npx)
|
||
npm init -y --prefix /tmp/muse-api-gen
|
||
cd /tmp/muse-api-gen
|
||
npm install openapi-typescript @hey-api/openapi-ts
|
||
```
|
||
|
||
- [ ] **Step 2: 合并所有模块 YAML 为单一入口**
|
||
|
||
```bash
|
||
# 创建合并入口文件
|
||
cat > /tmp/muse-api-gen/openapi-merged.yaml << 'YAMLEND'
|
||
openapi: 3.0.3
|
||
info:
|
||
title: Muse API (Merged)
|
||
version: 1.0.0
|
||
paths: {}
|
||
components:
|
||
schemas: {}
|
||
YAMLEND
|
||
|
||
# 使用 yq 或手动合并各模块 paths
|
||
# 此处用简单方式:为每个模块分别生成类型,再合并 index.ts
|
||
```
|
||
|
||
- [ ] **Step 3: 为每个模块生成 TypeScript 类型**
|
||
|
||
```bash
|
||
cd /tmp/muse-api-gen
|
||
for module in content ai knowledge market account meta; do
|
||
npx openapi-typescript \
|
||
"/Users/qingse/Sync/local-git/oh-my-muse/docs/api-contracts/${module}/openapi.yaml" \
|
||
--output "/Users/qingse/Sync/local-git/oh-my-muse/docs/api-contracts/generated/typescript/${module}.ts"
|
||
done
|
||
```
|
||
|
||
- [ ] **Step 4: 生成共享组件类型**
|
||
|
||
```bash
|
||
npx openapi-typescript \
|
||
"/Users/qingse/Sync/local-git/oh-my-muse/docs/api-contracts/openapi-base.yaml" \
|
||
--output "/Users/qingse/Sync/local-git/oh-my-muse/docs/api-contracts/generated/typescript/base.ts"
|
||
```
|
||
|
||
- [ ] **Step 5: 编写 barrel 导出文件**
|
||
|
||
```typescript
|
||
// docs/api-contracts/generated/typescript/index.ts
|
||
// Muse API TypeScript 类型包入口
|
||
// 自动生成于 OpenAPI 3.0 契约文件,请勿手动编辑
|
||
|
||
export * from './base';
|
||
export * from './content';
|
||
export * from './ai';
|
||
export * from './knowledge';
|
||
export * from './market';
|
||
export * from './account';
|
||
export * from './meta';
|
||
|
||
// 重新导出通用工具类型
|
||
export type {
|
||
CommonResult,
|
||
PaginatedResult,
|
||
ErrorResponse,
|
||
TimestampMixin,
|
||
} from './base';
|
||
```
|
||
|
||
- [ ] **Step 6: 提交**
|
||
|
||
```bash
|
||
git add docs/api-contracts/generated/typescript/
|
||
git commit -m "feat(api): 从 OpenAPI 生成 TypeScript 类型包(6 模块 + base)"
|
||
```
|
||
|
||
### Task 0.10: 生成 Java DTO 骨架
|
||
|
||
**文件:**
|
||
- 创建: `docs/api-contracts/generated/java/` 下的 DTO 类
|
||
- 工具: `openapi-generator-cli`
|
||
|
||
- [ ] **Step 1: 准备 OpenAPI Generator 配置**
|
||
|
||
```bash
|
||
# 创建生成器配置
|
||
cat > /tmp/muse-api-gen/openapi-generator-config.yaml << 'EOF'
|
||
# OpenAPI Generator 配置 for Java DTO
|
||
generatorName: spring
|
||
library: spring-boot
|
||
inputSpec: /tmp/muse-api-gen/openapi-merged.yaml
|
||
outputDir: /Users/qingse/Sync/local-git/oh-my-muse/docs/api-contracts/generated/java
|
||
apiPackage: com.muse.api
|
||
modelPackage: com.muse.dto
|
||
generateApis: false
|
||
generateModels: true
|
||
generateApiTests: false
|
||
generateModelTests: false
|
||
generateApiDocumentation: false
|
||
generateModelDocumentation: false
|
||
skipValidateSpec: true
|
||
additionalProperties:
|
||
java21: true
|
||
useSpringBoot3: true
|
||
useJakartaEe: true
|
||
dateLibrary: java8
|
||
serializableModel: true
|
||
openApiNullable: false
|
||
EOF
|
||
```
|
||
|
||
- [ ] **Step 2: 执行代码生成**
|
||
|
||
```bash
|
||
npx @openapitools/openapi-generator-cli generate \
|
||
-c /tmp/muse-api-gen/openapi-generator-config.yaml
|
||
```
|
||
|
||
- [ ] **Step 3: 清理不需要的生成文件**
|
||
|
||
```bash
|
||
# 只保留 model/DTO 类,删除 API 接口和测试文件
|
||
rm -rf docs/api-contracts/generated/java/api/
|
||
rm -rf docs/api-contracts/generated/java/test/
|
||
rm -f docs/api-contracts/generated/java/pom.xml
|
||
rm -f docs/api-contracts/generated/java/README.md
|
||
```
|
||
|
||
- [ ] **Step 4: 提交**
|
||
|
||
```bash
|
||
git add docs/api-contracts/generated/java/
|
||
git commit -m "feat(api): 从 OpenAPI 生成 Java DTO 骨架(6 模块)"
|
||
```
|
||
|
||
---
|
||
|
||
## Phase 0 完成标准
|
||
|
||
- [ ] 6 个模块的 openapi.yaml 全部通过 YAML 语法校验
|
||
- [ ] 接口总数 ≥ 146(与设计文档对齐)
|
||
- [ ] 交叉引用 $ref 路径全部有效
|
||
- [ ] TypeScript 类型包生成无报错
|
||
- [ ] Java DTO 骨架生成无报错
|
||
- [ ] 所有提交已推送到 gitea
|
||
|
||
---
|
||
|
||
## Phase 1-2 子计划概览
|
||
|
||
以下子计划在 Phase 0 完成后分别在各仓创建和展开:
|
||
|
||
### P1: muse-cloud 后端搭建(Week 3-16)
|
||
|
||
| Step | 内容 | 周期 | 关键输出 |
|
||
|------|------|------|----------|
|
||
| 1.1 | Yudao Cloud 基础调整(包名、Docker Compose、.idea) | Week 3 | 可启动的开发环境 |
|
||
| 1.2 | 数据库 Migration(全量 DDL + Flyway) | Week 3-4 | 建表 SQL 已执行 |
|
||
| 1.3 | 6 个业务模块骨架 | Week 5-8 | pom.xml + 包结构 + API 接口定义 |
|
||
| 1.4 | API 实现 Phase 1.1: content + account | Week 9-10 | 作品/章节/Block/权益/配额 API |
|
||
| 1.5 | API 实现 Phase 1.2: meta | Week 11 | MetaSchema CRUD API |
|
||
| 1.6 | API 实现 Phase 1.3: ai + knowledge | Week 12-14 | AI 生成/候选/智能体 + 知识实体/关系 |
|
||
| 1.7 | API 实现 Phase 1.4: market | Week 15-16 | 市场浏览/发布/审核 API |
|
||
|
||
### P2: muse-studio 用户端搭建(Week 3-16)
|
||
|
||
| Step | 内容 | 周期 | 关键输出 |
|
||
|------|------|------|----------|
|
||
| 2.1 | 工程脚手架(Vite + React + TS + Tailwind + 路由) | Week 3-4 | 可启动的空 SPA |
|
||
| 2.2 | 核心基础设施(MSW + SSE + IndexedDB + Zustand) | Week 5-8 | Mock API 全覆盖 |
|
||
| 2.3 | 写作台(编辑器 + AI 生成 + 候选面板) | Week 9-12 | 核心创作流程 |
|
||
| 2.4 | 我的作品 + 工作台(列表/章节/Block) | Week 13-14 | 作品管理 |
|
||
| 2.5 | 知识库 + 智能体 + 市场 + 个人中心 | Week 15-16 | 辅助功能 |
|
||
|
||
### P3: muse-admin 管理端搭建(Week 3-16)
|
||
|
||
| Step | 内容 | 周期 | 关键输出 |
|
||
|------|------|------|----------|
|
||
| 3.1 | 工程脚手架(Vben Admin + 目录组织 + Mock) | Week 3-4 | 可启动的管理端 |
|
||
| 3.2 | MetaSchema 管理页面 | Week 5-8 | 字段定义/版本/回滚 |
|
||
| 3.3 | 系统治理页面 | Week 9-12 | 用户/角色/审计 |
|
||
| 3.4 | AI 配置 + 市场治理 + 全局知识 | Week 13-16 | 管理端完整 |
|
||
|
||
### P4: 集成切换 + 质量加固(Week 9-18)
|
||
|
||
| Step | 内容 | 周期 |
|
||
|------|------|------|
|
||
| 4.1 | content+account 集成切换 | Week 9-10 |
|
||
| 4.2 | meta 集成切换 | Week 11 |
|
||
| 4.3 | ai+knowledge 集成切换 | Week 12-14 |
|
||
| 4.4 | market 集成切换 | Week 15-16 |
|
||
| 4.5 | 全量质量加固(测试/CI/安全) | Week 17-18 |
|
||
|
||
---
|
||
|
||
## 下一步
|
||
|
||
Phase 0 执行完成后:
|
||
1. 输出 6 个模块的 OpenAPI YAML + TypeScript 类型 + Java DTO
|
||
2. 创建 P1-P4 子计划(在各仓分别展开为详细任务)
|
||
3. 三仓并行启动 Phase 1 |