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"