- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
855 lines
21 KiB
YAML
855 lines
21 KiB
YAML
openapi: 3.0.0
|
|
info:
|
|
title: Training Module API
|
|
description: 考培练系统陪练模块API契约
|
|
version: 1.0.0
|
|
|
|
servers:
|
|
- url: http://localhost:8000/api/v1
|
|
description: 本地开发服务器
|
|
|
|
paths:
|
|
/training/scenes:
|
|
get:
|
|
summary: 获取陪练场景列表
|
|
tags:
|
|
- 陪练场景
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: category
|
|
in: query
|
|
description: 场景分类
|
|
schema:
|
|
type: string
|
|
- name: status
|
|
in: query
|
|
description: 场景状态
|
|
schema:
|
|
type: string
|
|
enum: [draft, active, inactive]
|
|
- name: is_public
|
|
in: query
|
|
description: 是否公开
|
|
schema:
|
|
type: boolean
|
|
- name: search
|
|
in: query
|
|
description: 搜索关键词
|
|
schema:
|
|
type: string
|
|
- name: page
|
|
in: query
|
|
description: 页码
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
default: 1
|
|
- name: page_size
|
|
in: query
|
|
description: 每页数量
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 100
|
|
default: 20
|
|
responses:
|
|
'200':
|
|
description: 成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PaginatedScenesResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
|
|
post:
|
|
summary: 创建陪练场景(管理员)
|
|
tags:
|
|
- 陪练场景
|
|
security:
|
|
- bearerAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TrainingSceneCreate'
|
|
responses:
|
|
'200':
|
|
description: 成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TrainingSceneResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
|
|
/training/scenes/{scene_id}:
|
|
get:
|
|
summary: 获取陪练场景详情
|
|
tags:
|
|
- 陪练场景
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: scene_id
|
|
in: path
|
|
required: true
|
|
description: 场景ID
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: 成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TrainingSceneResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
put:
|
|
summary: 更新陪练场景(管理员)
|
|
tags:
|
|
- 陪练场景
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: scene_id
|
|
in: path
|
|
required: true
|
|
description: 场景ID
|
|
schema:
|
|
type: integer
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TrainingSceneUpdate'
|
|
responses:
|
|
'200':
|
|
description: 成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TrainingSceneResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
delete:
|
|
summary: 删除陪练场景(管理员)
|
|
tags:
|
|
- 陪练场景
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: scene_id
|
|
in: path
|
|
required: true
|
|
description: 场景ID
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: 成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: integer
|
|
example: 200
|
|
message:
|
|
type: string
|
|
example: "删除陪练场景成功"
|
|
data:
|
|
type: boolean
|
|
example: true
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
/training/sessions:
|
|
post:
|
|
summary: 开始陪练会话
|
|
tags:
|
|
- 陪练会话
|
|
security:
|
|
- bearerAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/StartTrainingRequest'
|
|
responses:
|
|
'200':
|
|
description: 成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/StartTrainingResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'404':
|
|
description: 场景不存在
|
|
|
|
get:
|
|
summary: 获取用户的陪练会话列表
|
|
tags:
|
|
- 陪练会话
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: scene_id
|
|
in: query
|
|
description: 场景ID
|
|
schema:
|
|
type: integer
|
|
- name: status
|
|
in: query
|
|
description: 会话状态
|
|
schema:
|
|
type: string
|
|
enum: [created, in_progress, completed, cancelled, error]
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
default: 1
|
|
- name: page_size
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 100
|
|
default: 20
|
|
responses:
|
|
'200':
|
|
description: 成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PaginatedSessionsResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
|
|
/training/sessions/{session_id}:
|
|
get:
|
|
summary: 获取陪练会话详情
|
|
tags:
|
|
- 陪练会话
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: session_id
|
|
in: path
|
|
required: true
|
|
description: 会话ID
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: 成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TrainingSessionResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
/training/sessions/{session_id}/end:
|
|
post:
|
|
summary: 结束陪练会话
|
|
tags:
|
|
- 陪练会话
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: session_id
|
|
in: path
|
|
required: true
|
|
description: 会话ID
|
|
schema:
|
|
type: integer
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EndTrainingRequest'
|
|
responses:
|
|
'200':
|
|
description: 成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/EndTrainingResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
/training/sessions/{session_id}/messages:
|
|
get:
|
|
summary: 获取陪练会话的消息列表
|
|
tags:
|
|
- 陪练消息
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: session_id
|
|
in: path
|
|
required: true
|
|
description: 会话ID
|
|
schema:
|
|
type: integer
|
|
- name: skip
|
|
in: query
|
|
description: 跳过数量
|
|
schema:
|
|
type: integer
|
|
minimum: 0
|
|
default: 0
|
|
- name: limit
|
|
in: query
|
|
description: 返回数量
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 500
|
|
default: 100
|
|
responses:
|
|
'200':
|
|
description: 成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: integer
|
|
message:
|
|
type: string
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/TrainingMessage'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
/training/reports:
|
|
get:
|
|
summary: 获取用户的陪练报告列表
|
|
tags:
|
|
- 陪练报告
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
default: 1
|
|
- name: page_size
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 100
|
|
default: 20
|
|
responses:
|
|
'200':
|
|
description: 成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/PaginatedReportsResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
|
|
/training/reports/{report_id}:
|
|
get:
|
|
summary: 获取陪练报告详情
|
|
tags:
|
|
- 陪练报告
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: report_id
|
|
in: path
|
|
required: true
|
|
description: 报告ID
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: 成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TrainingReportResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
/training/sessions/{session_id}/report:
|
|
get:
|
|
summary: 根据会话ID获取陪练报告
|
|
tags:
|
|
- 陪练报告
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: session_id
|
|
in: path
|
|
required: true
|
|
description: 会话ID
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: 成功
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/TrainingReportResponse'
|
|
'401':
|
|
$ref: '#/components/responses/Unauthorized'
|
|
'403':
|
|
$ref: '#/components/responses/Forbidden'
|
|
'404':
|
|
$ref: '#/components/responses/NotFound'
|
|
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
|
|
responses:
|
|
Unauthorized:
|
|
description: 未授权
|
|
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'
|
|
|
|
schemas:
|
|
ErrorResponse:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: integer
|
|
message:
|
|
type: string
|
|
detail:
|
|
type: object
|
|
|
|
BaseResponse:
|
|
type: object
|
|
properties:
|
|
code:
|
|
type: integer
|
|
example: 200
|
|
message:
|
|
type: string
|
|
example: "success"
|
|
request_id:
|
|
type: string
|
|
|
|
PaginationMeta:
|
|
type: object
|
|
properties:
|
|
total:
|
|
type: integer
|
|
page:
|
|
type: integer
|
|
page_size:
|
|
type: integer
|
|
pages:
|
|
type: integer
|
|
|
|
TrainingSceneCreate:
|
|
type: object
|
|
required:
|
|
- name
|
|
- category
|
|
properties:
|
|
name:
|
|
type: string
|
|
maxLength: 100
|
|
description: 场景名称
|
|
description:
|
|
type: string
|
|
description: 场景描述
|
|
category:
|
|
type: string
|
|
maxLength: 50
|
|
description: 场景分类
|
|
ai_config:
|
|
type: object
|
|
description: AI配置
|
|
prompt_template:
|
|
type: string
|
|
description: 提示词模板
|
|
evaluation_criteria:
|
|
type: object
|
|
description: 评估标准
|
|
is_public:
|
|
type: boolean
|
|
default: true
|
|
description: 是否公开
|
|
required_level:
|
|
type: integer
|
|
description: 所需用户等级
|
|
status:
|
|
type: string
|
|
enum: [draft, active, inactive]
|
|
default: draft
|
|
|
|
TrainingSceneUpdate:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
maxLength: 100
|
|
description:
|
|
type: string
|
|
category:
|
|
type: string
|
|
maxLength: 50
|
|
ai_config:
|
|
type: object
|
|
prompt_template:
|
|
type: string
|
|
evaluation_criteria:
|
|
type: object
|
|
status:
|
|
type: string
|
|
enum: [draft, active, inactive]
|
|
is_public:
|
|
type: boolean
|
|
required_level:
|
|
type: integer
|
|
|
|
TrainingScene:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
category:
|
|
type: string
|
|
ai_config:
|
|
type: object
|
|
prompt_template:
|
|
type: string
|
|
evaluation_criteria:
|
|
type: object
|
|
status:
|
|
type: string
|
|
enum: [draft, active, inactive]
|
|
is_public:
|
|
type: boolean
|
|
required_level:
|
|
type: integer
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
|
|
TrainingSceneResponse:
|
|
allOf:
|
|
- $ref: '#/components/schemas/BaseResponse'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/TrainingScene'
|
|
|
|
PaginatedScenesResponse:
|
|
allOf:
|
|
- $ref: '#/components/schemas/BaseResponse'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
type: object
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/TrainingScene'
|
|
total:
|
|
type: integer
|
|
page:
|
|
type: integer
|
|
page_size:
|
|
type: integer
|
|
pages:
|
|
type: integer
|
|
|
|
StartTrainingRequest:
|
|
type: object
|
|
required:
|
|
- scene_id
|
|
properties:
|
|
scene_id:
|
|
type: integer
|
|
description: 场景ID
|
|
config:
|
|
type: object
|
|
description: 会话配置
|
|
|
|
StartTrainingResponse:
|
|
allOf:
|
|
- $ref: '#/components/schemas/BaseResponse'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
type: object
|
|
properties:
|
|
session_id:
|
|
type: integer
|
|
coze_conversation_id:
|
|
type: string
|
|
scene:
|
|
$ref: '#/components/schemas/TrainingScene'
|
|
websocket_url:
|
|
type: string
|
|
|
|
EndTrainingRequest:
|
|
type: object
|
|
properties:
|
|
generate_report:
|
|
type: boolean
|
|
default: true
|
|
description: 是否生成报告
|
|
|
|
EndTrainingResponse:
|
|
allOf:
|
|
- $ref: '#/components/schemas/BaseResponse'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
type: object
|
|
properties:
|
|
session:
|
|
$ref: '#/components/schemas/TrainingSession'
|
|
report:
|
|
$ref: '#/components/schemas/TrainingReport'
|
|
|
|
TrainingSession:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
user_id:
|
|
type: integer
|
|
scene_id:
|
|
type: integer
|
|
coze_conversation_id:
|
|
type: string
|
|
start_time:
|
|
type: string
|
|
format: date-time
|
|
end_time:
|
|
type: string
|
|
format: date-time
|
|
duration_seconds:
|
|
type: integer
|
|
status:
|
|
type: string
|
|
enum: [created, in_progress, completed, cancelled, error]
|
|
session_config:
|
|
type: object
|
|
total_score:
|
|
type: number
|
|
evaluation_result:
|
|
type: object
|
|
scene:
|
|
$ref: '#/components/schemas/TrainingScene'
|
|
message_count:
|
|
type: integer
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
|
|
TrainingSessionResponse:
|
|
allOf:
|
|
- $ref: '#/components/schemas/BaseResponse'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/TrainingSession'
|
|
|
|
PaginatedSessionsResponse:
|
|
allOf:
|
|
- $ref: '#/components/schemas/BaseResponse'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
type: object
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/TrainingSession'
|
|
total:
|
|
type: integer
|
|
page:
|
|
type: integer
|
|
page_size:
|
|
type: integer
|
|
pages:
|
|
type: integer
|
|
|
|
TrainingMessage:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
session_id:
|
|
type: integer
|
|
role:
|
|
type: string
|
|
enum: [user, assistant, system]
|
|
type:
|
|
type: string
|
|
enum: [text, voice, system]
|
|
content:
|
|
type: string
|
|
voice_url:
|
|
type: string
|
|
voice_duration:
|
|
type: number
|
|
metadata:
|
|
type: object
|
|
coze_message_id:
|
|
type: string
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
|
|
TrainingReport:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
session_id:
|
|
type: integer
|
|
user_id:
|
|
type: integer
|
|
overall_score:
|
|
type: number
|
|
dimension_scores:
|
|
type: object
|
|
additionalProperties:
|
|
type: number
|
|
strengths:
|
|
type: array
|
|
items:
|
|
type: string
|
|
weaknesses:
|
|
type: array
|
|
items:
|
|
type: string
|
|
suggestions:
|
|
type: array
|
|
items:
|
|
type: string
|
|
detailed_analysis:
|
|
type: string
|
|
transcript:
|
|
type: string
|
|
statistics:
|
|
type: object
|
|
session:
|
|
$ref: '#/components/schemas/TrainingSession'
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
|
|
TrainingReportResponse:
|
|
allOf:
|
|
- $ref: '#/components/schemas/BaseResponse'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
$ref: '#/components/schemas/TrainingReport'
|
|
|
|
PaginatedReportsResponse:
|
|
allOf:
|
|
- $ref: '#/components/schemas/BaseResponse'
|
|
- type: object
|
|
properties:
|
|
data:
|
|
type: object
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/TrainingReport'
|
|
total:
|
|
type: integer
|
|
page:
|
|
type: integer
|
|
page_size:
|
|
type: integer
|
|
pages:
|
|
type: integer
|