## 1. 架构设计 ```mermaid 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 | 创建时间 | 请求示例: ```json { "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. 服务端架构图 ```mermaid 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 数据库实体关系图 ```mermaid 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 数据定义语言 #### 用户表 ```sql 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); ``` #### 题目表 ```sql 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); ``` #### 答题记录表 ```sql 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); ``` #### 答题答案表 ```sql 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); ``` #### 系统配置表 ```sql 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 环境变量 ```env # 服务器配置 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/ # 构建输出目录 ```