- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
498 lines
12 KiB
YAML
498 lines
12 KiB
YAML
openapi: 3.0.0
|
|
info:
|
|
title: 课程管理模块API契约
|
|
description: 定义课程管理模块对外提供的所有API接口
|
|
version: 1.0.0
|
|
|
|
servers:
|
|
- url: http://localhost:8000/api/v1
|
|
description: 本地开发服务器
|
|
|
|
paths:
|
|
/courses:
|
|
get:
|
|
summary: 获取课程列表
|
|
description: 支持分页和多条件筛选
|
|
operationId: getCourses
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
default: 1
|
|
- name: size
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 100
|
|
default: 20
|
|
- name: status
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [draft, published, archived]
|
|
- name: category
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [technology, management, business, general]
|
|
- name: is_featured
|
|
in: query
|
|
schema:
|
|
type: boolean
|
|
- name: keyword
|
|
in: query
|
|
schema:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: 成功获取课程列表
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/CoursePageResponse"
|
|
"401":
|
|
$ref: "#/components/responses/UnauthorizedError"
|
|
|
|
post:
|
|
summary: 创建课程
|
|
description: 创建新课程(需要管理员权限)
|
|
operationId: createCourse
|
|
security:
|
|
- bearerAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/CourseCreate"
|
|
responses:
|
|
"201":
|
|
description: 成功创建课程
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/CourseResponse"
|
|
"401":
|
|
$ref: "#/components/responses/UnauthorizedError"
|
|
"403":
|
|
$ref: "#/components/responses/ForbiddenError"
|
|
"409":
|
|
$ref: "#/components/responses/ConflictError"
|
|
|
|
/courses/{courseId}:
|
|
get:
|
|
summary: 获取课程详情
|
|
operationId: getCourse
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: courseId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
"200":
|
|
description: 成功获取课程详情
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/CourseResponse"
|
|
"401":
|
|
$ref: "#/components/responses/UnauthorizedError"
|
|
"404":
|
|
$ref: "#/components/responses/NotFoundError"
|
|
|
|
put:
|
|
summary: 更新课程
|
|
description: 更新课程信息(需要管理员权限)
|
|
operationId: updateCourse
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: courseId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/CourseUpdate"
|
|
responses:
|
|
"200":
|
|
description: 成功更新课程
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/CourseResponse"
|
|
"401":
|
|
$ref: "#/components/responses/UnauthorizedError"
|
|
"403":
|
|
$ref: "#/components/responses/ForbiddenError"
|
|
"404":
|
|
$ref: "#/components/responses/NotFoundError"
|
|
|
|
delete:
|
|
summary: 删除课程
|
|
description: 软删除课程(需要管理员权限)
|
|
operationId: deleteCourse
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: courseId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
"200":
|
|
description: 成功删除课程
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DeleteResponse"
|
|
"400":
|
|
$ref: "#/components/responses/BadRequestError"
|
|
"401":
|
|
$ref: "#/components/responses/UnauthorizedError"
|
|
"403":
|
|
$ref: "#/components/responses/ForbiddenError"
|
|
"404":
|
|
$ref: "#/components/responses/NotFoundError"
|
|
|
|
/courses/{courseId}/knowledge-points:
|
|
get:
|
|
summary: 获取课程知识点列表
|
|
operationId: getCourseKnowledgePoints
|
|
security:
|
|
- bearerAuth: []
|
|
parameters:
|
|
- name: courseId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
- name: parent_id
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
nullable: true
|
|
responses:
|
|
"200":
|
|
description: 成功获取知识点列表
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/KnowledgePointListResponse"
|
|
"401":
|
|
$ref: "#/components/responses/UnauthorizedError"
|
|
"404":
|
|
$ref: "#/components/responses/NotFoundError"
|
|
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
|
|
schemas:
|
|
ResponseBase:
|
|
type: object
|
|
required:
|
|
- code
|
|
- message
|
|
properties:
|
|
code:
|
|
type: integer
|
|
default: 200
|
|
message:
|
|
type: string
|
|
request_id:
|
|
type: string
|
|
timestamp:
|
|
type: string
|
|
format: date-time
|
|
|
|
CourseBase:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 200
|
|
description:
|
|
type: string
|
|
category:
|
|
type: string
|
|
enum: [technology, management, business, general]
|
|
default: general
|
|
cover_image:
|
|
type: string
|
|
maxLength: 500
|
|
duration_hours:
|
|
type: number
|
|
format: float
|
|
minimum: 0
|
|
difficulty_level:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 5
|
|
tags:
|
|
type: array
|
|
items:
|
|
type: string
|
|
sort_order:
|
|
type: integer
|
|
default: 0
|
|
is_featured:
|
|
type: boolean
|
|
default: false
|
|
|
|
CourseCreate:
|
|
allOf:
|
|
- $ref: "#/components/schemas/CourseBase"
|
|
- type: object
|
|
required:
|
|
- name
|
|
properties:
|
|
status:
|
|
type: string
|
|
enum: [draft, published, archived]
|
|
default: draft
|
|
|
|
CourseUpdate:
|
|
allOf:
|
|
- $ref: "#/components/schemas/CourseBase"
|
|
- type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
enum: [draft, published, archived]
|
|
|
|
Course:
|
|
allOf:
|
|
- $ref: "#/components/schemas/CourseBase"
|
|
- type: object
|
|
required:
|
|
- id
|
|
- status
|
|
- created_at
|
|
- updated_at
|
|
properties:
|
|
id:
|
|
type: integer
|
|
status:
|
|
type: string
|
|
enum: [draft, published, archived]
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
published_at:
|
|
type: string
|
|
format: date-time
|
|
nullable: true
|
|
publisher_id:
|
|
type: integer
|
|
nullable: true
|
|
created_by:
|
|
type: integer
|
|
nullable: true
|
|
updated_by:
|
|
type: integer
|
|
nullable: true
|
|
|
|
CourseResponse:
|
|
allOf:
|
|
- $ref: "#/components/schemas/ResponseBase"
|
|
- type: object
|
|
properties:
|
|
data:
|
|
$ref: "#/components/schemas/Course"
|
|
|
|
CoursePageResponse:
|
|
allOf:
|
|
- $ref: "#/components/schemas/ResponseBase"
|
|
- type: object
|
|
properties:
|
|
data:
|
|
type: object
|
|
required:
|
|
- items
|
|
- total
|
|
- page
|
|
- size
|
|
- pages
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Course"
|
|
total:
|
|
type: integer
|
|
page:
|
|
type: integer
|
|
size:
|
|
type: integer
|
|
pages:
|
|
type: integer
|
|
|
|
KnowledgePoint:
|
|
type: object
|
|
required:
|
|
- id
|
|
- course_id
|
|
- name
|
|
- level
|
|
- created_at
|
|
- updated_at
|
|
properties:
|
|
id:
|
|
type: integer
|
|
course_id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
maxLength: 200
|
|
description:
|
|
type: string
|
|
parent_id:
|
|
type: integer
|
|
nullable: true
|
|
level:
|
|
type: integer
|
|
path:
|
|
type: string
|
|
nullable: true
|
|
sort_order:
|
|
type: integer
|
|
weight:
|
|
type: number
|
|
format: float
|
|
is_required:
|
|
type: boolean
|
|
estimated_hours:
|
|
type: number
|
|
format: float
|
|
nullable: true
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
updated_at:
|
|
type: string
|
|
format: date-time
|
|
|
|
KnowledgePointListResponse:
|
|
allOf:
|
|
- $ref: "#/components/schemas/ResponseBase"
|
|
- type: object
|
|
properties:
|
|
data:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/KnowledgePoint"
|
|
|
|
DeleteResponse:
|
|
allOf:
|
|
- $ref: "#/components/schemas/ResponseBase"
|
|
- type: object
|
|
properties:
|
|
data:
|
|
type: boolean
|
|
|
|
ErrorDetail:
|
|
type: object
|
|
required:
|
|
- message
|
|
properties:
|
|
message:
|
|
type: string
|
|
error_code:
|
|
type: string
|
|
field:
|
|
type: string
|
|
details:
|
|
type: object
|
|
|
|
responses:
|
|
BadRequestError:
|
|
description: 请求参数错误
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/ResponseBase"
|
|
- type: object
|
|
properties:
|
|
code:
|
|
example: 400
|
|
detail:
|
|
$ref: "#/components/schemas/ErrorDetail"
|
|
|
|
UnauthorizedError:
|
|
description: 未认证
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/ResponseBase"
|
|
- type: object
|
|
properties:
|
|
code:
|
|
example: 401
|
|
detail:
|
|
$ref: "#/components/schemas/ErrorDetail"
|
|
|
|
ForbiddenError:
|
|
description: 权限不足
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/ResponseBase"
|
|
- type: object
|
|
properties:
|
|
code:
|
|
example: 403
|
|
detail:
|
|
$ref: "#/components/schemas/ErrorDetail"
|
|
|
|
NotFoundError:
|
|
description: 资源不存在
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/ResponseBase"
|
|
- type: object
|
|
properties:
|
|
code:
|
|
example: 404
|
|
detail:
|
|
$ref: "#/components/schemas/ErrorDetail"
|
|
|
|
ConflictError:
|
|
description: 资源冲突
|
|
content:
|
|
application/json:
|
|
schema:
|
|
allOf:
|
|
- $ref: "#/components/schemas/ResponseBase"
|
|
- type: object
|
|
properties:
|
|
code:
|
|
example: 409
|
|
detail:
|
|
$ref: "#/components/schemas/ErrorDetail"
|