引入openspec管理
This commit is contained in:
@@ -1,233 +0,0 @@
|
||||
domains:
|
||||
- name: "User"
|
||||
description: "参与答题的用户"
|
||||
entities:
|
||||
- name: "User"
|
||||
description: "用户信息实体"
|
||||
attributes:
|
||||
- name: "id"
|
||||
type: "string"
|
||||
description: "用户唯一标识"
|
||||
- name: "name"
|
||||
type: "string"
|
||||
description: "用户姓名,2-20位中英文"
|
||||
- name: "phone"
|
||||
type: "string"
|
||||
description: "手机号,11位数字"
|
||||
- name: "password"
|
||||
type: "string"
|
||||
description: "登录密码 (敏感字段,仅管理员可见;当前版本为明文存储)"
|
||||
- name: "createdAt"
|
||||
type: "datetime"
|
||||
description: "创建时间"
|
||||
- name: "UserGroup"
|
||||
description: "用户组 (Note: The User Group feature (including management, assignment, and mixed selection) is implemented but currently UNTESTED. Missing Audit Log feature for User Group changes.)"
|
||||
attributes:
|
||||
- name: "id"
|
||||
type: "string"
|
||||
description: "用户组唯一标识"
|
||||
- name: "name"
|
||||
type: "string"
|
||||
description: "用户组名称"
|
||||
- name: "description"
|
||||
type: "string"
|
||||
description: "用户组描述"
|
||||
- name: "isSystem"
|
||||
type: "boolean"
|
||||
description: "是否为系统内置组 (如: 全体用户)"
|
||||
- name: "createdAt"
|
||||
type: "datetime"
|
||||
description: "创建时间"
|
||||
rules:
|
||||
- "All Users (全体用户) special group: Auto-join for new users; Cannot be deleted or modified; Users cannot exit."
|
||||
|
||||
- name: "Question"
|
||||
description: "题库管理"
|
||||
entities:
|
||||
- name: "QuestionCategory"
|
||||
description: "题目类别"
|
||||
attributes:
|
||||
- name: "id"
|
||||
type: "string"
|
||||
description: "类别唯一标识"
|
||||
- name: "name"
|
||||
type: "string"
|
||||
description: "类别名称 (例如:通用/网络/数据库等)"
|
||||
- name: "createdAt"
|
||||
type: "datetime"
|
||||
description: "创建时间"
|
||||
- name: "Question"
|
||||
description: "题目实体"
|
||||
attributes:
|
||||
- name: "id"
|
||||
type: "string"
|
||||
description: "题目唯一标识"
|
||||
- name: "content"
|
||||
type: "string"
|
||||
description: "题目内容"
|
||||
- name: "type"
|
||||
type: "enum"
|
||||
values: ["single", "multiple", "judgment", "text"]
|
||||
description: "题型"
|
||||
- name: "category"
|
||||
type: "string"
|
||||
description: "题目类别名称 (默认:通用)"
|
||||
- name: "options"
|
||||
type: "json"
|
||||
description: "选项内容 (JSON格式)"
|
||||
- name: "answer"
|
||||
type: "string"
|
||||
description: "标准答案"
|
||||
- name: "score"
|
||||
type: "integer"
|
||||
description: "分值"
|
||||
- name: "createdAt"
|
||||
type: "datetime"
|
||||
description: "创建时间"
|
||||
|
||||
- name: "Exam"
|
||||
description: "考试科目与考试任务"
|
||||
entities:
|
||||
- name: "ExamSubject"
|
||||
description: "考试科目 (一套出题规则)"
|
||||
attributes:
|
||||
- name: "id"
|
||||
type: "string"
|
||||
description: "科目唯一标识"
|
||||
- name: "name"
|
||||
type: "string"
|
||||
description: "科目名称"
|
||||
- name: "totalScore"
|
||||
type: "integer"
|
||||
description: "总分"
|
||||
- name: "timeLimitMinutes"
|
||||
type: "integer"
|
||||
description: "答题时间限制(分钟),默认60"
|
||||
- name: "typeRatios"
|
||||
type: "json"
|
||||
description: "题型比重 (single/multiple/judgment/text)"
|
||||
- name: "categoryRatios"
|
||||
type: "json"
|
||||
description: "题目类别比重 (categoryName -> ratio)"
|
||||
- name: "createdAt"
|
||||
type: "datetime"
|
||||
description: "创建时间"
|
||||
- name: "updatedAt"
|
||||
type: "datetime"
|
||||
description: "更新时间"
|
||||
- name: "ExamTask"
|
||||
description: "考试任务 (给用户分派某个科目)"
|
||||
attributes:
|
||||
- name: "id"
|
||||
type: "string"
|
||||
description: "任务唯一标识"
|
||||
- name: "name"
|
||||
type: "string"
|
||||
description: "任务名称"
|
||||
- name: "subjectId"
|
||||
type: "string"
|
||||
description: "关联科目ID"
|
||||
- name: "startAt"
|
||||
type: "datetime"
|
||||
description: "开始答题时间"
|
||||
- name: "endAt"
|
||||
type: "datetime"
|
||||
description: "截止答题时间"
|
||||
- name: "createdAt"
|
||||
type: "datetime"
|
||||
description: "创建时间"
|
||||
- name: "ExamTaskUser"
|
||||
description: "任务参与用户"
|
||||
attributes:
|
||||
- name: "id"
|
||||
type: "string"
|
||||
description: "关联唯一标识"
|
||||
- name: "taskId"
|
||||
type: "string"
|
||||
description: "任务ID"
|
||||
- name: "userId"
|
||||
type: "string"
|
||||
description: "用户ID"
|
||||
- name: "assignedAt"
|
||||
type: "datetime"
|
||||
description: "分派时间"
|
||||
|
||||
- name: "Quiz"
|
||||
description: "答题业务"
|
||||
entities:
|
||||
- name: "QuizRecord"
|
||||
description: "答题记录"
|
||||
attributes:
|
||||
- name: "id"
|
||||
type: "string"
|
||||
description: "记录唯一标识"
|
||||
- name: "userId"
|
||||
type: "string"
|
||||
description: "用户ID"
|
||||
- name: "totalScore"
|
||||
type: "integer"
|
||||
description: "总得分"
|
||||
- name: "correctCount"
|
||||
type: "integer"
|
||||
description: "正确题数"
|
||||
- name: "totalCount"
|
||||
type: "integer"
|
||||
description: "总题数"
|
||||
- name: "createdAt"
|
||||
type: "datetime"
|
||||
description: "答题时间"
|
||||
- name: "QuizAnswer"
|
||||
description: "单题答题详情"
|
||||
attributes:
|
||||
- name: "id"
|
||||
type: "string"
|
||||
description: "答案唯一标识"
|
||||
- name: "recordId"
|
||||
type: "string"
|
||||
description: "关联的答题记录ID"
|
||||
- name: "questionId"
|
||||
type: "string"
|
||||
description: "题目ID"
|
||||
- name: "userAnswer"
|
||||
type: "string"
|
||||
description: "用户提交的答案"
|
||||
- name: "isCorrect"
|
||||
type: "boolean"
|
||||
description: "是否正确"
|
||||
- name: "score"
|
||||
type: "integer"
|
||||
description: "该题得分"
|
||||
|
||||
- name: "System"
|
||||
description: "系统配置"
|
||||
entities:
|
||||
- name: "SystemConfig"
|
||||
description: "系统全局配置"
|
||||
attributes:
|
||||
- name: "id"
|
||||
type: "string"
|
||||
description: "配置唯一标识"
|
||||
- name: "configType"
|
||||
type: "string"
|
||||
description: "配置类型键"
|
||||
- name: "configValue"
|
||||
type: "string"
|
||||
description: "配置值 (通常为JSON字符串)"
|
||||
- name: "updatedAt"
|
||||
type: "datetime"
|
||||
description: "更新时间"
|
||||
|
||||
- name: "Backup"
|
||||
description: "数据备份与恢复"
|
||||
entities:
|
||||
- name: "BackupRestore"
|
||||
description: "数据导出与导入"
|
||||
attributes:
|
||||
- name: "dataType"
|
||||
type: "enum"
|
||||
values: ["users", "questions", "records", "answers"]
|
||||
description: "数据类型"
|
||||
- name: "action"
|
||||
type: "enum"
|
||||
values: ["export", "restore"]
|
||||
description: "操作类型"
|
||||
@@ -1,984 +0,0 @@
|
||||
openapi: "3.0.0"
|
||||
info:
|
||||
title: "Survey System API"
|
||||
version: "1.1.0"
|
||||
components:
|
||||
securitySchemes:
|
||||
AdminBearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT
|
||||
schemas:
|
||||
User:
|
||||
type: object
|
||||
required: ["id", "name", "phone", "createdAt"]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
phone:
|
||||
type: string
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
AdminUserView:
|
||||
type: object
|
||||
required: ["id", "name", "phone", "createdAt", "password"]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
phone:
|
||||
type: string
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
password:
|
||||
type: string
|
||||
description: "密码 (敏感字段;前端掩码显示)"
|
||||
groupIds:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: "所属用户组ID列表"
|
||||
UserGroup:
|
||||
type: object
|
||||
required: ["id", "name", "createdAt"]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
isSystem:
|
||||
type: boolean
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
memberCount:
|
||||
type: integer
|
||||
description: "成员数量"
|
||||
QuestionCategory:
|
||||
type: object
|
||||
required: ["id", "name", "createdAt"]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
createdAt:
|
||||
type: string
|
||||
format: date-time
|
||||
Question:
|
||||
type: object
|
||||
required: ["content", "type", "answer", "score"]
|
||||
properties:
|
||||
content:
|
||||
type: string
|
||||
type:
|
||||
type: string
|
||||
enum: ["single", "multiple", "judgment", "text"]
|
||||
category:
|
||||
type: string
|
||||
description: "题目类别名称,缺省为通用"
|
||||
default: "通用"
|
||||
options:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
answer:
|
||||
oneOf:
|
||||
- type: string
|
||||
- type: array
|
||||
items:
|
||||
type: string
|
||||
score:
|
||||
type: number
|
||||
ExamSubject:
|
||||
type: object
|
||||
required: ["id", "name", "totalScore", "timeLimitMinutes", "typeRatios", "categoryRatios"]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
totalScore:
|
||||
type: integer
|
||||
timeLimitMinutes:
|
||||
type: integer
|
||||
default: 60
|
||||
typeRatios:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
single:
|
||||
type: number
|
||||
multiple:
|
||||
type: number
|
||||
judgment:
|
||||
type: number
|
||||
text:
|
||||
type: number
|
||||
categoryRatios:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: number
|
||||
ExamTask:
|
||||
type: object
|
||||
required: ["id", "name", "subjectId", "startAt", "endAt"]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
subjectId:
|
||||
type: string
|
||||
startAt:
|
||||
type: string
|
||||
format: date-time
|
||||
endAt:
|
||||
type: string
|
||||
format: date-time
|
||||
selectionConfig:
|
||||
type: string
|
||||
description: "JSON string storing original selection of userIds and groupIds"
|
||||
Pagination:
|
||||
type: object
|
||||
required: ["page", "limit", "total", "pages"]
|
||||
properties:
|
||||
page:
|
||||
type: integer
|
||||
limit:
|
||||
type: integer
|
||||
total:
|
||||
type: integer
|
||||
pages:
|
||||
type: integer
|
||||
paths:
|
||||
/api/users:
|
||||
post:
|
||||
summary: "创建用户或登录"
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: ["name", "phone", "password"]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: "用户姓名,2-20位中英文"
|
||||
phone:
|
||||
type: string
|
||||
description: "手机号"
|
||||
password:
|
||||
type: string
|
||||
description: "登录密码"
|
||||
responses:
|
||||
"200":
|
||||
description: "User created"
|
||||
|
||||
/api/users/{id}:
|
||||
get:
|
||||
summary: "获取用户信息"
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "User details"
|
||||
|
||||
/api/questions/import:
|
||||
post:
|
||||
summary: "Excel导入题目"
|
||||
requestBody:
|
||||
content:
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
file:
|
||||
type: string
|
||||
format: binary
|
||||
responses:
|
||||
"200":
|
||||
description: "Import result"
|
||||
|
||||
/api/questions:
|
||||
get:
|
||||
summary: "获取题目列表"
|
||||
parameters:
|
||||
- name: "type"
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
enum: ["single", "multiple", "judgment", "text"]
|
||||
- name: "category"
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
- name: "page"
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
- name: "limit"
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
responses:
|
||||
"200":
|
||||
description: "List of questions"
|
||||
post:
|
||||
summary: "添加单题"
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Question"
|
||||
responses:
|
||||
"200":
|
||||
description: "Question created"
|
||||
|
||||
/api/questions/{id}:
|
||||
put:
|
||||
summary: "更新题目"
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/Question"
|
||||
responses:
|
||||
"200":
|
||||
description: "Question updated"
|
||||
delete:
|
||||
summary: "删除题目"
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Question deleted"
|
||||
|
||||
/api/quiz/generate:
|
||||
post:
|
||||
summary: "生成随机试卷"
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: ["userId", "subjectId"]
|
||||
properties:
|
||||
userId:
|
||||
type: string
|
||||
subjectId:
|
||||
type: string
|
||||
description: "考试科目ID"
|
||||
responses:
|
||||
"200":
|
||||
description: "Generated quiz"
|
||||
|
||||
/api/quiz/submit:
|
||||
post:
|
||||
summary: "提交答题"
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: ["userId", "answers"]
|
||||
properties:
|
||||
userId:
|
||||
type: string
|
||||
answers:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
responses:
|
||||
"200":
|
||||
description: "Submission result"
|
||||
|
||||
/api/quiz/records/{userId}:
|
||||
get:
|
||||
summary: "获取用户答题记录"
|
||||
parameters:
|
||||
- name: "userId"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "User quiz records"
|
||||
|
||||
/api/quiz/records/detail/{recordId}:
|
||||
get:
|
||||
summary: "获取答题记录详情"
|
||||
parameters:
|
||||
- name: "recordId"
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Record detail"
|
||||
|
||||
/api/admin/login:
|
||||
post:
|
||||
summary: "管理员登录"
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: ["username", "password"]
|
||||
properties:
|
||||
username:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Login success"
|
||||
|
||||
/api/admin/statistics:
|
||||
get:
|
||||
summary: "获取统计数据"
|
||||
responses:
|
||||
"200":
|
||||
description: "Statistics data"
|
||||
|
||||
/api/admin/users:
|
||||
get:
|
||||
summary: "获取用户列表 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: "page"
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
- name: "limit"
|
||||
in: query
|
||||
schema:
|
||||
type: integer
|
||||
- name: "keyword"
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
description: "搜索关键词(姓名/手机)"
|
||||
responses:
|
||||
"200":
|
||||
description: "User list"
|
||||
post:
|
||||
summary: "创建用户 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: ["name", "phone", "password"]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
phone:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
groupIds:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "User created"
|
||||
delete:
|
||||
summary: "删除用户 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: ["userId"]
|
||||
properties:
|
||||
userId:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Deleted"
|
||||
|
||||
/api/admin/users/{id}:
|
||||
put:
|
||||
summary: "更新用户 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
phone:
|
||||
type: string
|
||||
password:
|
||||
type: string
|
||||
groupIds:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "User updated"
|
||||
|
||||
/api/admin/user-groups:
|
||||
get:
|
||||
summary: "获取用户组列表"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: "Group list"
|
||||
post:
|
||||
summary: "创建用户组"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: ["name"]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Group created"
|
||||
|
||||
/api/admin/user-groups/{id}:
|
||||
put:
|
||||
summary: "更新用户组"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Group updated"
|
||||
delete:
|
||||
summary: "删除用户组"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Group deleted"
|
||||
|
||||
/api/admin/user-groups/{id}/members:
|
||||
get:
|
||||
summary: "获取用户组成员"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Group members"
|
||||
|
||||
/api/admin/users/export:
|
||||
get:
|
||||
summary: "导出用户 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: "Export users"
|
||||
|
||||
/api/admin/users/import:
|
||||
post:
|
||||
summary: "导入用户 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
requestBody:
|
||||
content:
|
||||
multipart/form-data:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
file:
|
||||
type: string
|
||||
format: binary
|
||||
responses:
|
||||
"200":
|
||||
description: "Import users"
|
||||
|
||||
/api/admin/users/{userId}/records:
|
||||
get:
|
||||
summary: "获取用户历史答题记录 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: userId
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "User records"
|
||||
|
||||
/api/admin/question-categories:
|
||||
get:
|
||||
summary: "获取题目类别列表 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: "Category list"
|
||||
post:
|
||||
summary: "新增题目类别 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: ["name"]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Created"
|
||||
|
||||
/api/admin/question-categories/{id}:
|
||||
put:
|
||||
summary: "更新题目类别 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: ["name"]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Updated"
|
||||
delete:
|
||||
summary: "删除题目类别 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Deleted"
|
||||
|
||||
/api/admin/subjects:
|
||||
get:
|
||||
summary: "获取考试科目列表 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: "Subjects"
|
||||
post:
|
||||
summary: "新增考试科目 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ExamSubject"
|
||||
responses:
|
||||
"200":
|
||||
description: "Created"
|
||||
|
||||
/api/admin/subjects/{id}:
|
||||
put:
|
||||
summary: "更新考试科目 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: "#/components/schemas/ExamSubject"
|
||||
responses:
|
||||
"200":
|
||||
description: "Updated"
|
||||
delete:
|
||||
summary: "删除考试科目 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Deleted"
|
||||
|
||||
/api/subjects:
|
||||
get:
|
||||
summary: "获取考试科目列表 (用户)"
|
||||
responses:
|
||||
"200":
|
||||
description: "Subjects"
|
||||
|
||||
/api/admin/tasks:
|
||||
get:
|
||||
summary: "获取考试任务列表 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: "Tasks"
|
||||
post:
|
||||
summary: "新增考试任务并分派用户 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
description: "Create task with mixed selection of users and groups (system handles de-duplication)"
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: ["name", "subjectId", "startAt", "endAt"]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
subjectId:
|
||||
type: string
|
||||
startAt:
|
||||
type: string
|
||||
format: date-time
|
||||
endAt:
|
||||
type: string
|
||||
format: date-time
|
||||
userIds:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
groupIds:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Created"
|
||||
|
||||
/api/admin/tasks/{id}:
|
||||
put:
|
||||
summary: "更新考试任务 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
requestBody:
|
||||
required: true
|
||||
description: "Update task with mixed selection (system handles de-duplication)"
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
subjectId:
|
||||
type: string
|
||||
startAt:
|
||||
type: string
|
||||
format: date-time
|
||||
endAt:
|
||||
type: string
|
||||
format: date-time
|
||||
userIds:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
groupIds:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Updated"
|
||||
delete:
|
||||
summary: "删除考试任务 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Deleted"
|
||||
|
||||
/api/admin/tasks/{id}/report:
|
||||
get:
|
||||
summary: "导出任务报表 (管理员)"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: id
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Task report"
|
||||
|
||||
/api/admin/config:
|
||||
get:
|
||||
summary: "获取抽题配置"
|
||||
responses:
|
||||
"200":
|
||||
description: "Quiz config"
|
||||
put:
|
||||
summary: "更新抽题配置"
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
responses:
|
||||
"200":
|
||||
description: "Config updated"
|
||||
|
||||
/api/admin/configs:
|
||||
get:
|
||||
summary: "获取所有系统配置"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: "All configs"
|
||||
|
||||
/api/admin/password:
|
||||
put:
|
||||
summary: "修改管理员密码"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: ["oldPassword", "newPassword"]
|
||||
properties:
|
||||
oldPassword:
|
||||
type: string
|
||||
newPassword:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Password updated"
|
||||
|
||||
/api/admin/export/{type}:
|
||||
get:
|
||||
summary: "通用数据导出"
|
||||
description: "type: users, questions, records, answers"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: "type"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
enum: ["users", "questions", "records", "answers"]
|
||||
responses:
|
||||
"200":
|
||||
description: "JSON export data"
|
||||
|
||||
/api/admin/restore:
|
||||
post:
|
||||
summary: "数据恢复"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
users:
|
||||
type: array
|
||||
questions:
|
||||
type: array
|
||||
records:
|
||||
type: array
|
||||
answers:
|
||||
type: array
|
||||
responses:
|
||||
"200":
|
||||
description: "Data restored"
|
||||
|
||||
/api/exam-tasks/user/{userId}:
|
||||
get:
|
||||
summary: "获取指定用户的考试任务"
|
||||
parameters:
|
||||
- name: "userId"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "User tasks"
|
||||
|
||||
/api/admin/tasks/{id}/users:
|
||||
get:
|
||||
summary: "获取任务分派的用户"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: "id"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Task users"
|
||||
|
||||
/api/admin/active-tasks:
|
||||
get:
|
||||
summary: "获取当前活跃任务统计"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
responses:
|
||||
"200":
|
||||
description: "Active tasks stats"
|
||||
|
||||
/api/users/validate:
|
||||
post:
|
||||
summary: "验证用户信息(用于导入校验)"
|
||||
requestBody:
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: ["phone"]
|
||||
properties:
|
||||
phone:
|
||||
type: string
|
||||
name:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Validation result"
|
||||
|
||||
/api/users/name/{name}:
|
||||
get:
|
||||
summary: "根据姓名查找用户"
|
||||
security:
|
||||
- AdminBearerAuth: []
|
||||
parameters:
|
||||
- name: "name"
|
||||
in: "path"
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: "Users found"
|
||||
@@ -1,300 +0,0 @@
|
||||
database:
|
||||
type: "sqlite"
|
||||
version: "3"
|
||||
tables:
|
||||
- name: "users"
|
||||
columns:
|
||||
- name: "id"
|
||||
type: "TEXT"
|
||||
primaryKey: true
|
||||
- name: "name"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
constraints: "CHECK(length(name) >= 2 AND length(name) <= 20)"
|
||||
- name: "phone"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
unique: true
|
||||
constraints: "CHECK(length(phone) = 11 AND phone LIKE '1%' AND substr(phone, 2, 1) BETWEEN '3' AND '9')"
|
||||
- name: "password"
|
||||
type: "TEXT"
|
||||
comment: "用户登录密码 (当前版本为明文存储)"
|
||||
- name: "created_at"
|
||||
type: "DATETIME"
|
||||
default: "CURRENT_TIMESTAMP"
|
||||
indexes:
|
||||
- name: "idx_users_phone"
|
||||
columns: ["phone"]
|
||||
- name: "idx_users_created_at"
|
||||
columns: ["created_at"]
|
||||
|
||||
- name: "user_groups"
|
||||
columns:
|
||||
- name: "id"
|
||||
type: "TEXT"
|
||||
primaryKey: true
|
||||
- name: "name"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
unique: true
|
||||
- name: "description"
|
||||
type: "TEXT"
|
||||
- name: "is_system"
|
||||
type: "INTEGER"
|
||||
default: "0"
|
||||
comment: "是否为系统内置组 (0:否, 1:是)"
|
||||
- name: "created_at"
|
||||
type: "DATETIME"
|
||||
default: "CURRENT_TIMESTAMP"
|
||||
indexes:
|
||||
- name: "idx_user_groups_name"
|
||||
columns: ["name"]
|
||||
|
||||
- name: "user_group_members"
|
||||
columns:
|
||||
- name: "group_id"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
foreignKey:
|
||||
table: "user_groups"
|
||||
column: "id"
|
||||
- name: "user_id"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
foreignKey:
|
||||
table: "users"
|
||||
column: "id"
|
||||
- name: "created_at"
|
||||
type: "DATETIME"
|
||||
default: "CURRENT_TIMESTAMP"
|
||||
indexes:
|
||||
- name: "idx_user_group_members_unique"
|
||||
columns: ["group_id", "user_id"]
|
||||
unique: true
|
||||
|
||||
- name: "question_categories"
|
||||
columns:
|
||||
- name: "id"
|
||||
type: "TEXT"
|
||||
primaryKey: true
|
||||
- name: "name"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
unique: true
|
||||
- name: "created_at"
|
||||
type: "DATETIME"
|
||||
default: "CURRENT_TIMESTAMP"
|
||||
indexes:
|
||||
- name: "idx_question_categories_name"
|
||||
columns: ["name"]
|
||||
|
||||
- name: "questions"
|
||||
columns:
|
||||
- name: "id"
|
||||
type: "TEXT"
|
||||
primaryKey: true
|
||||
- name: "content"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
- name: "type"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
constraints: "CHECK(type IN ('single', 'multiple', 'judgment', 'text'))"
|
||||
- name: "category"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
default: "'通用'"
|
||||
comment: "题目类别名称 (无类别时默认通用)"
|
||||
- name: "options"
|
||||
type: "TEXT"
|
||||
comment: "JSON格式存储选项"
|
||||
- name: "answer"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
- name: "score"
|
||||
type: "INTEGER"
|
||||
nullable: false
|
||||
constraints: "CHECK(score > 0)"
|
||||
- name: "created_at"
|
||||
type: "DATETIME"
|
||||
default: "CURRENT_TIMESTAMP"
|
||||
indexes:
|
||||
- name: "idx_questions_type"
|
||||
columns: ["type"]
|
||||
- name: "idx_questions_category"
|
||||
columns: ["category"]
|
||||
- name: "idx_questions_score"
|
||||
columns: ["score"]
|
||||
|
||||
- name: "exam_subjects"
|
||||
columns:
|
||||
- name: "id"
|
||||
type: "TEXT"
|
||||
primaryKey: true
|
||||
- name: "name"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
unique: true
|
||||
- name: "total_score"
|
||||
type: "INTEGER"
|
||||
nullable: false
|
||||
constraints: "CHECK(total_score > 0)"
|
||||
- name: "time_limit_minutes"
|
||||
type: "INTEGER"
|
||||
nullable: false
|
||||
default: "60"
|
||||
constraints: "CHECK(time_limit_minutes > 0)"
|
||||
- name: "type_ratios"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
comment: "题型比重 JSON (single/multiple/judgment/text)"
|
||||
- name: "category_ratios"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
comment: "题目类别比重 JSON (categoryName->ratio)"
|
||||
- name: "created_at"
|
||||
type: "DATETIME"
|
||||
default: "CURRENT_TIMESTAMP"
|
||||
- name: "updated_at"
|
||||
type: "DATETIME"
|
||||
default: "CURRENT_TIMESTAMP"
|
||||
indexes:
|
||||
- name: "idx_exam_subjects_name"
|
||||
columns: ["name"]
|
||||
|
||||
- name: "exam_tasks"
|
||||
columns:
|
||||
- name: "id"
|
||||
type: "TEXT"
|
||||
primaryKey: true
|
||||
- name: "name"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
- name: "subject_id"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
foreignKey:
|
||||
table: "exam_subjects"
|
||||
column: "id"
|
||||
- name: "start_at"
|
||||
type: "DATETIME"
|
||||
nullable: false
|
||||
- name: "end_at"
|
||||
type: "DATETIME"
|
||||
nullable: false
|
||||
- name: "created_at"
|
||||
type: "DATETIME"
|
||||
default: "CURRENT_TIMESTAMP"
|
||||
indexes:
|
||||
- name: "idx_exam_tasks_subject_id"
|
||||
columns: ["subject_id"]
|
||||
- name: "idx_exam_tasks_start_at"
|
||||
columns: ["start_at"]
|
||||
- name: "idx_exam_tasks_end_at"
|
||||
columns: ["end_at"]
|
||||
|
||||
- name: "exam_task_users"
|
||||
columns:
|
||||
- name: "id"
|
||||
type: "TEXT"
|
||||
primaryKey: true
|
||||
- name: "task_id"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
foreignKey:
|
||||
table: "exam_tasks"
|
||||
column: "id"
|
||||
- name: "user_id"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
foreignKey:
|
||||
table: "users"
|
||||
column: "id"
|
||||
- name: "assigned_at"
|
||||
type: "DATETIME"
|
||||
default: "CURRENT_TIMESTAMP"
|
||||
indexes:
|
||||
- name: "idx_exam_task_users_task_id"
|
||||
columns: ["task_id"]
|
||||
- name: "idx_exam_task_users_user_id"
|
||||
columns: ["user_id"]
|
||||
|
||||
- name: "quiz_records"
|
||||
columns:
|
||||
- name: "id"
|
||||
type: "TEXT"
|
||||
primaryKey: true
|
||||
- name: "user_id"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
foreignKey:
|
||||
table: "users"
|
||||
column: "id"
|
||||
- name: "total_score"
|
||||
type: "INTEGER"
|
||||
nullable: false
|
||||
- name: "correct_count"
|
||||
type: "INTEGER"
|
||||
nullable: false
|
||||
- name: "total_count"
|
||||
type: "INTEGER"
|
||||
nullable: false
|
||||
- name: "created_at"
|
||||
type: "DATETIME"
|
||||
default: "CURRENT_TIMESTAMP"
|
||||
indexes:
|
||||
- name: "idx_quiz_records_user_id"
|
||||
columns: ["user_id"]
|
||||
- name: "idx_quiz_records_created_at"
|
||||
columns: ["created_at"]
|
||||
|
||||
- name: "quiz_answers"
|
||||
columns:
|
||||
- name: "id"
|
||||
type: "TEXT"
|
||||
primaryKey: true
|
||||
- name: "record_id"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
foreignKey:
|
||||
table: "quiz_records"
|
||||
column: "id"
|
||||
- name: "question_id"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
foreignKey:
|
||||
table: "questions"
|
||||
column: "id"
|
||||
- name: "user_answer"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
- name: "score"
|
||||
type: "INTEGER"
|
||||
nullable: false
|
||||
- name: "is_correct"
|
||||
type: "BOOLEAN"
|
||||
nullable: false
|
||||
- name: "created_at"
|
||||
type: "DATETIME"
|
||||
default: "CURRENT_TIMESTAMP"
|
||||
indexes:
|
||||
- name: "idx_quiz_answers_record_id"
|
||||
columns: ["record_id"]
|
||||
- name: "idx_quiz_answers_question_id"
|
||||
columns: ["question_id"]
|
||||
|
||||
- name: "system_configs"
|
||||
columns:
|
||||
- name: "id"
|
||||
type: "TEXT"
|
||||
primaryKey: true
|
||||
- name: "config_type"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
unique: true
|
||||
- name: "config_value"
|
||||
type: "TEXT"
|
||||
nullable: false
|
||||
- name: "updated_at"
|
||||
type: "DATETIME"
|
||||
default: "CURRENT_TIMESTAMP"
|
||||
@@ -1,14 +0,0 @@
|
||||
specVersion: "0.1.0"
|
||||
info:
|
||||
title: "问卷调查系统 (Survey System)"
|
||||
description: "一个功能完善的在线考试/问卷调查平台,支持多种题型、随机抽题、免注册答题。"
|
||||
version: "1.1.0"
|
||||
license:
|
||||
name: "Proprietary"
|
||||
references:
|
||||
- path: "./100-business/domain.yaml"
|
||||
type: "domain"
|
||||
- path: "./200-api/api.yaml"
|
||||
type: "api"
|
||||
- path: "./300-database/schema.yaml"
|
||||
type: "database"
|
||||
Reference in New Issue
Block a user