9.1 KiB
9.1 KiB
1. 架构设计
graph TD
A[用户浏览器] --> B[React前端应用]
B --> C[Express后端服务]
C --> D[SQLite数据库]
C --> E[文件存储服务]
subgraph "前端层"
B
end
subgraph "后端服务层"
C
E
end
subgraph "数据存储层"
D
end
2. 技术选型
- 前端框架:React@18 + TypeScript
- 初始化工具:vite-init
- UI组件库:Ant Design@5
- 状态管理:React Context + useReducer
- 后端框架:Express@4 + TypeScript
- 数据库:SQLite3
- 文件处理:multer + xlsx
- 数据验证:Joi
- 开发工具:nodemon + concurrently
3. 路由定义
前端路由
| 路由 | 用途 |
|---|---|
| / | 用户答题首页 |
| /quiz | 答题页面 |
| /result/:id | 答题结果页面 |
| /admin/login | 管理员登录 |
| /admin/dashboard | 管理后台首页 |
| /admin/questions | 题库管理 |
| /admin/config | 抽题配置 |
| /admin/statistics | 数据统计 |
后端API路由
| 路由 | 方法 | 用途 |
|---|---|---|
| /api/users | POST | 创建用户 |
| /api/users/:id | GET | 获取用户信息 |
| /api/questions/import | POST | Excel导入题目 |
| /api/questions | GET | 获取题目列表 |
| /api/questions | POST | 添加单题 |
| /api/questions/:id | PUT | 更新题目 |
| /api/questions/:id | DELETE | 删除题目 |
| /api/quiz/generate | POST | 生成随机试卷 |
| /api/quiz/submit | POST | 提交答题 |
| /api/quiz/results/:userId | GET | 获取用户答题记录 |
| /api/admin/login | POST | 管理员登录 |
| /api/admin/statistics | GET | 获取统计数据 |
| /api/admin/config | GET/PUT | 获取/更新抽题配置 |
4. API接口定义
4.1 用户相关接口
创建用户
POST /api/users
请求参数:
| 参数名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| name | string | 是 | 用户姓名,2-20位中英文 |
| phone | string | 是 | 手机号,11位数字,1开头,第二位3-9 |
响应参数:
| 参数名 | 类型 | 描述 |
|---|---|---|
| id | string | 用户唯一标识 |
| name | string | 用户姓名 |
| phone | string | 手机号 |
| createdAt | string | 创建时间 |
请求示例:
{
"name": "张三",
"phone": "13812345678"
}
生成随机试卷
POST /api/quiz/generate
请求参数:
| 参数名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| userId | string | 是 | 用户ID |
响应参数:
| 参数名 | 类型 | 描述 |
|---|---|---|
| questions | array | 题目数组 |
| totalScore | number | 总分 |
| timeLimit | number | 时间限制(分钟) |
4.2 题库管理接口
Excel导入题目
POST /api/questions/import
请求参数(form-data):
| 参数名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| file | file | 是 | Excel文件 |
响应参数:
| 参数名 | 类型 | 描述 |
|---|---|---|
| success | boolean | 导入是否成功 |
| imported | number | 成功导入数量 |
| errors | array | 错误信息数组 |
添加单题
POST /api/questions
请求参数:
| 参数名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| content | string | 是 | 题目内容 |
| type | string | 是 | 题型:single/multiple/judgment/text |
| options | array | 条件 | 选项数组(单选/多选) |
| answer | string/array | 是 | 标准答案 |
| score | number | 是 | 分值 |
4.3 答题相关接口
提交答题
POST /api/quiz/submit
请求参数:
| 参数名 | 类型 | 必填 | 描述 |
|---|---|---|---|
| userId | string | 是 | 用户ID |
| answers | array | 是 | 答案数组 |
答案对象结构:
| 参数名 | 类型 | 描述 |
|---|---|---|
| questionId | string | 题目ID |
| userAnswer | string/array | 用户答案 |
| score | number | 得分 |
响应参数:
| 参数名 | 类型 | 描述 |
|---|---|---|
| totalScore | number | 总得分 |
| correctCount | number | 正确题数 |
| totalCount | number | 总题数 |
5. 服务端架构图
graph TD
A[客户端请求] --> B[路由层]
B --> C[中间件层]
C --> D[控制器层]
D --> E[服务层]
E --> F[数据访问层]
F --> G[(SQLite数据库)]
subgraph "Express服务端"
B
C
D
E
F
end
5.1 分层设计
- 路由层:定义API端点,处理请求分发
- 中间件层:身份验证、错误处理、请求日志
- 控制器层:处理HTTP请求,调用服务层
- 服务层:业务逻辑处理,数据验证
- 数据访问层:数据库操作,SQL查询执行
6. 数据模型
6.1 数据库实体关系图
erDiagram
USER ||--o{ QUIZ_RECORD : takes
USER ||--o{ QUIZ_ANSWER : submits
QUESTION ||--o{ QUIZ_ANSWER : answered
QUESTION ||--o{ QUIZ_CONFIG : included
USER {
string id PK
string name
string phone
datetime created_at
}
QUESTION {
string id PK
string content
string type
string options
string answer
integer score
datetime created_at
}
QUIZ_RECORD {
string id PK
string user_id FK
integer total_score
integer correct_count
datetime created_at
}
QUIZ_ANSWER {
string id PK
string record_id FK
string question_id FK
string user_answer
integer score
boolean is_correct
}
QUIZ_CONFIG {
string id PK
string config_type
string config_value
datetime updated_at
}
6.2 数据定义语言
用户表
CREATE TABLE users (
id TEXT PRIMARY KEY,
name TEXT NOT NULL CHECK(length(name) >= 2 AND length(name) <= 20),
phone TEXT UNIQUE NOT NULL CHECK(length(phone) = 11 AND phone LIKE '1%' AND substr(phone, 2, 1) BETWEEN '3' AND '9'),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_users_phone ON users(phone);
CREATE INDEX idx_users_created_at ON users(created_at);
题目表
CREATE TABLE questions (
id TEXT PRIMARY KEY,
content TEXT NOT NULL,
type TEXT NOT NULL CHECK(type IN ('single', 'multiple', 'judgment', 'text')),
options TEXT, -- JSON格式存储选项
answer TEXT NOT NULL,
score INTEGER NOT NULL CHECK(score > 0),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX idx_questions_type ON questions(type);
CREATE INDEX idx_questions_score ON questions(score);
答题记录表
CREATE TABLE quiz_records (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL,
total_score INTEGER NOT NULL,
correct_count INTEGER NOT NULL,
total_count INTEGER NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (user_id) REFERENCES users(id)
);
CREATE INDEX idx_quiz_records_user_id ON quiz_records(user_id);
CREATE INDEX idx_quiz_records_created_at ON quiz_records(created_at);
答题答案表
CREATE TABLE quiz_answers (
id TEXT PRIMARY KEY,
record_id TEXT NOT NULL,
question_id TEXT NOT NULL,
user_answer TEXT NOT NULL,
score INTEGER NOT NULL,
is_correct BOOLEAN NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (record_id) REFERENCES quiz_records(id),
FOREIGN KEY (question_id) REFERENCES questions(id)
);
CREATE INDEX idx_quiz_answers_record_id ON quiz_answers(record_id);
CREATE INDEX idx_quiz_answers_question_id ON quiz_answers(question_id);
系统配置表
CREATE TABLE system_configs (
id TEXT PRIMARY KEY,
config_type TEXT UNIQUE NOT NULL,
config_value TEXT NOT NULL,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
-- 初始化抽题配置
INSERT INTO system_configs (id, config_type, config_value) VALUES
('1', 'quiz_config', '{"singleRatio":40,"multipleRatio":30,"judgmentRatio":20,"textRatio":10,"totalScore":100}');
6.3 索引优化
- 用户手机号索引:加速用户查询和防重复验证
- 题目类型索引:优化按类型筛选题目性能
- 答题记录时间索引:支持按时间范围查询统计
- 外键索引:确保关联查询性能
7. 部署配置
7.1 环境变量
# 服务器配置
PORT=3000
NODE_ENV=development
# 数据库配置
DB_PATH=./data/survey.db
# 管理员配置
ADMIN_USERNAME=admin
ADMIN_PASSWORD=admin123
# 文件上传配置
UPLOAD_MAX_SIZE=10MB
UPLOAD_DIR=./uploads
7.2 目录结构
survey-system/
├── src/
│ ├── frontend/ # React前端代码
│ ├── backend/ # Express后端代码
│ │ ├── controllers/ # 控制器
│ │ ├── services/ # 服务层
│ │ ├── models/ # 数据模型
│ │ ├── middlewares/ # 中间件
│ │ └── utils/ # 工具函数
│ ├── shared/ # 共享类型定义
│ └── data/ # 数据库文件
├── uploads/ # 文件上传目录
├── public/ # 静态资源
└── dist/ # 构建输出目录