From ab3914fc86efd70b54a5715440aa6e7fbe6d29e8 Mon Sep 17 00:00:00 2001 From: lsbp <2803234009@qq.com> Date: Fri, 3 Oct 2025 14:57:59 +0800 Subject: [PATCH] add design doc v2 --- .idea/.gitignore | 8 + .idea/PAIR.iml | 9 + .idea/misc.xml | 6 + .idea/modules.xml | 8 + .idea/vcs.xml | 6 + doc/设计文档/设计文档第二版.md | 189 ++++++++++++++++++ src/main/java/com/mathquiz/Main.java | 0 .../com/mathquiz/model/ChoiceQuestion.java | 0 src/main/java/com/mathquiz/model/Grade.java | 0 src/main/java/com/mathquiz/model/User.java | 0 10 files changed, 226 insertions(+) create mode 100644 .idea/.gitignore create mode 100644 .idea/PAIR.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 doc/设计文档/设计文档第二版.md create mode 100644 src/main/java/com/mathquiz/Main.java create mode 100644 src/main/java/com/mathquiz/model/ChoiceQuestion.java create mode 100644 src/main/java/com/mathquiz/model/Grade.java create mode 100644 src/main/java/com/mathquiz/model/User.java diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/PAIR.iml b/.idea/PAIR.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/PAIR.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..6f29fee --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..20bffb7 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/doc/设计文档/设计文档第二版.md b/doc/设计文档/设计文档第二版.md new file mode 100644 index 0000000..a6ada6e --- /dev/null +++ b/doc/设计文档/设计文档第二版.md @@ -0,0 +1,189 @@ +# 数学题库生成系统详细设计文档 + +## 项目概述 + +### 项目目标 +为小初高学生提供一个本地的桌面端图像化应用,支持用户注册和登录,根据学生年级按规则随机生成数学选择题,完成答题后自动计算分数 + +### 技术栈 + +| 类型 | 技术 | 说明 | +| -------- | -------------------------- | ---------------------------------------- | +| 开发语言 | Java 21+ | 保证跨平台兼容性,支持 JavaFX | +| GUI框架 | JavaFX 17+ | 实现桌面图形化界面,提供组件化开发能力 | +| 依赖管理 | Maven | 管理 JavaFX、JSON 解析等依赖 | +| JSON解析 | Gson 2.10+ | 序列化 / 反序列化用户数据、题目数据 | +| 邮件发送 | JavaMail API + 第三方 SMTP | 发送注册码(如 QQ 邮箱 / 网易邮箱 SMTP) | +| 数据加密 | BCrypt 0.9.0+ | 加密存储用户密码,避免明文泄露 | +| 构建打包 | Maven Shade Plugin | 打包成可执行 JAR,支持直接运行 | + +### 总体设计 + +#### 项目目录结构 + +MathQuizApp/ +├── src/ +│ └── main/ +│ └── java/ +│ └── com/ +│ └── mathquiz/ +│ ├── Main.java # 程序入口 +│ │ +│ ├── model/ # 数据模型 +│ │ ├── User.java +│ │ ├── Grade.java +│ │ └── ChoiceQuestion.java +│ │ +│ ├── service/ # 后端逻辑(无GUI) +│ │ ├── UserService.java +│ │ ├── QuestionGenerator.java +│ │ ├── FileIOService.java +│ │ └── QuizService.java +│ │ +│ ├── ui/ # 前端 GUI +│ │ ├── MainWindow.java +│ │ ├── RegisterPanel.java +│ │ ├── LoginPanel.java +| | ├── PasswordModifyPanel.java +│ │ ├── GradeSelectPanel.java +│ │ ├── QuizPanel.java +│ │ └── ResultPanel.java +│ │ +│ └── util/ # 工具类 +│ ├── PasswordValidator.java +| ├── EmailUtil.java +│ ├── RandomUtils.java +│ └── FileUtils.java +│ +├── data/ # 运行时生成(不提交) +│ ├── users/ # 用户信息 JSON +│ └── temp_codes/ # 临时注册码文件 +│ +├── pom.xml # Maven 依赖(含 JavaFX) +└── README.md + +## 详细模块设计 + +### 模型层设计 + +#### User类 +- String name // 用户ID +- String email // 用户邮箱 +- String encryptedPwd // 加密后的用户密码 +- Grade grade //学段 + +#### ChoiceQuestion +String questionId; // 题目唯一ID(UUID生成) +Grade grade; // 所属学段 +String questionContent; // 题干 +List options; // 选项列表(固定4个,顺序随机) +String correctAnswer; // 正确答案(如"A"/"B"/"C"/"D") + +#### Grade 枚举 +PRIMARY("小学", 1) +JUNIOR("初中", 2) +SENIOR("高中", 3) + +### 工具层设计 + +#### PasswordValidator + +| 方法名 | 参数列表 | 返回值 | 逻辑描述 | +| ------- | ---------------------------------- | ------- | ------------------------------------------------------------ | +| isValid | String rawPwd | boolean | 校验规则:1. 长度 6-10 位;2. 包含至少 1 个大写字母;3. 包含至少 1 个小写字母;4. 包含至少 1 个数字 | +| encrypt | String rawPwd | String | 使用 BCrypt 加密密码(自动生成盐值,无需额外存储盐) | +| matches | String rawPwd, String encryptedPwd | boolean | 校验明文密码与加密密码是否匹配(BCrypt 自带校验逻辑) | + +#### EmailUtil + +| 方法名 | 参数列表 | 返回值 | 逻辑描述 | +| ------------- | ----------------------------------------- | ------- | ------------------------------------------------------------ | +| sendTextEmail | String to, String subject, String content | boolean | 1. 配置 SMTP 服务器(主机、端口、SSL);2. 设置发件人账号 / 授权码;3. 构建邮件内容;4. 发送并返回结果 | + +### 服务层设计 + +#### UserService + +| 方法名 | 参数列表 | 返回值 | 逻辑描述 | +| -------------------- | ----------------------------------------------------------- | ------- | ------------------------------------------------------------ | +| sendRegistrationCode | String email | boolean | 生成 6 位数字注册码,调用 EmailUtil.sendTextEmail()发送(开发阶段可模拟),并将注册码写入 data/temp_codes/{email}.txt | +| verifyCode | String email, String code | boolean | 读取 data/temp_codes/{email}.txt,校验注册码是否匹配 | +| setPassword | String email, String pwd1, String pwd2 | boolean | 校验两次密码一致且符合规则(6–10位,含大小写+数字),使用 BCrypt加密后保存用户到 data/users/{hash}.json,成功后删除临时注册码文件 | +| login | String email, String password | User | 读取用户文件,用 BCrypt.matches() 验证密码,返回 User 对象或 null | +| changePassword | String email, String oldPwd, String newPwd1, String newPwd2 | boolean | 先验证原密码正确,再校验新密码格式,更新加密密码并保存 | + +#### QuestionGenerator (抽象类) + +| 方法名 | 参数列表 | 返回值 | 逻辑描述 | +| ------------- | ------------- | ------------------- | ------------------------------------------------------------ | +| create | Grade grade | QuestionGenerator | 静态工厂方法,根据年级返回对应子类实例(PrimaryGenerator / MiddleGenerator / SeniorGenerator) | +| generateOne | — | ChoiceQuestion | 抽象方法,由子类实现,生成一道符合年级要求的选择题(含题干、4选项、正确答案) | + +#### FileIOService + +| 方法名 | 参数列表 | 返回值 | 逻辑描述 | +| ----------------------- | --------------------------- | ------------- | ------------------------------------------------------------ | +| saveUser | User user | void | 将用户序列化为 JSON,保存到 data/users/{BCrypt.hash(email).substring(0,16)}.json | +| loadUserByEmail | String email | User | 遍历 data/users/ 下所有 JSON 文件,反序列化后匹配邮箱,返回 User 或 null | +| saveCode | String email, String code | void | 写入 data/temp_codes/{email}.txt | +| loadCode | String email | String | 读取 data/temp_codes/{email}.txt,返回注册码或 null | +| loadUsedQuestionStems | String email | Set | 遍历 data/users/{email}/papers/(若存在)下所有 .txt 文件,提取题干(每行以“1.”、“2.”开头的内容),用于查重 | + +#### QuizService + +| 方法名 | 参数列表 | 返回值 | 逻辑描述 | +| ------------------- | ---------------------------------------------------------- | ---------------------- | ------------------------------------------------------------ | +| generateQuestions | String email, int count | List | 调用 QuestionGenerator.generateOne() 循环生成,确保题干不重复(使用 loadUsedQuestionStems + 当前卷子 Set) | +| calculateScore | List questions, List userAnswers | int | 比对每题 correctAnswer 与用户答案,计算百分比得分(四舍五入) | +| savePaper | String email, List questions | void | 生成时间戳文件名(yyyy-MM-dd-HH-mm-ss.txt),保存题干到 data/users/{email}/papers/(目录自动创建) | + +### UI层接口设计 + +#### MainWindow + +| 方法名 | 参数列表 | 返回值 | 逻辑描述 | +| ---------------------- | --------------------------------------------------------- | ------ | ------------------------------------------------- | +| showPanel | Pane panel | void | 设置 BorderPane.center 为指定面板,实现页面切换 | +| showLoginPanel | — | void | 创建并显示 LoginPanel | +| showRegisterPanel | — | void | 创建并显示 RegisterPanel | +| showGradeSelectPanel | — | void | 创建并显示 GradeSelectPanel | +| showQuizPanel | List questions, QuizService quizService | void | 创建并显示 QuizPanel | +| showResultPanel | int score, Runnable onContinue | void | 创建并显示 ResultPanel | + +#### RegisterPanel + +| 方法名 | 参数列表 | 返回值 | 逻辑描述 | +| ---------------- | ----------------------- | ------ | ------------------------------------------------------------ | +| 构造函数 | MainWindow mainWindow | — | 初始化邮箱、注册码、密码输入框和按钮,绑定事件 | +| sendCodeAction | — | void | 调用 mainWindow.getUserService().sendRegistrationCode(),提示“注册码已发送(模拟)” | +| registerAction | — | void | 调用 setPassword(),成功则跳转到年级选择页 | + +#### LoginPanel + +| 方法名 | 参数列表 | 返回值 | 逻辑描述 | +| ------------- | ----------------------- | ------ | ----------------------------------------------------------- | +| 构造函数 | MainWindow mainWindow | — | 初始化登录表单,绑定“登录”按钮 | +| loginAction | — | void | 调用 login(),成功则设置 currentUser 并跳转到年级选择页 | + +#### GradeSelectPanel + +| 方法名 | 参数列表 | 返回值 | 逻辑描述 | +| ----------- | ----------------------- | ------ | ------------------------------------------------------------ | +| 构造函数 | MainWindow mainWindow | — | 创建三个年级按钮 | +| startQuiz | Grade grade | void | 弹出数量输入对话框(10–30),调用 QuizService.generateQuestions(),跳转到答题页 | + +#### QuizPanel + +| 方法名 | 参数列表 | 返回值 | 逻辑描述 | +| -------------- | ------------------------------------------------------------ | ------ | ------------------------------------------------------------ | +| 构造函数 | MainWindow mainWindow, List questions, QuizService quizService | — | 显示第1题 | +| showQuestion | int index | void | 渲染当前题干和4个选项(RadioButton),绑定“提交”按钮 | +| submitAction | — | void | 记录答案,若非最后一题则显示下一题,否则计算分数并跳转结果页 | + +#### ResultPanel + +| 方法名 | 参数列表 | 返回值 | 逻辑描述 | +| ---------------- | ------------------------------------------------------- | ------ | ----------------------------------------------------- | +| 构造函数 | MainWindow mainWindow, int score, Runnable onContinue | — | 显示得分,绑定“退出”和“继续做题”按钮 | +| exitAction | — | void | 跳转到登录页 | +| continueAction | — | void | 执行 onContinue.run()(保存试卷),跳转到年级选择页 | \ No newline at end of file diff --git a/src/main/java/com/mathquiz/Main.java b/src/main/java/com/mathquiz/Main.java new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/mathquiz/model/ChoiceQuestion.java b/src/main/java/com/mathquiz/model/ChoiceQuestion.java new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/mathquiz/model/Grade.java b/src/main/java/com/mathquiz/model/Grade.java new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/mathquiz/model/User.java b/src/main/java/com/mathquiz/model/User.java new file mode 100644 index 0000000..e69de29 -- 2.34.1