diff --git a/doc/README.md b/doc/README.md index 6fa1bee..aacf4a3 100644 --- a/doc/README.md +++ b/doc/README.md @@ -1,206 +1,2 @@ # Pair-Programming -## **项目概述** - -数学学习系统是一个面向小初高学生的数学学习软件,旨在通过生成针对性的数学题目帮助学生进行练习和巩固数学知识。该系统采用前后端分离架构,前端基于 Electron 构建桌面应用,后端使用 Java 提供 API 服务。 - -## **项目结构** - -pair-programming/ - -├── src/ - -│ ├── electron-frontend/ # Electron前端 - -│ │ ├── resources/ - -│ │ │ ├── renderer/ # 渲染进程页面 - -│ │ │ │ ├── main.html # 主页面 - -│ │ │ │ ├── login.html # 登录页面 - -│ │ │ │ └── result.html # 结果页面 - -│ │ │ │ └── quiz.html # 答题页面 - -│ │ │ │ └── register.html # 注册页面 - -│ │ │ ├── main.js # 主进程代码 - -│ │ │ └── preload.js # 预加载脚本 - -│ │ ├── package.json # 前端依赖配置 - -│ │ └── package-lock.json # 依赖版本锁定文件 - -│ └── java-backend/ # Java后端 - -│ └── math\_learn/ # 数学学习系统后端代码 - -│ ├── .idea/ # IntelliJ IDEA配置 - -│ ├── src/ # 源代码 - -│ │ └── com/mathlearn/ - -│ │ ├── Main.java # 主程序入口 - -│ │ ├── generator/ # 题目生成业务 - -│ │ │ ├── QuestionGenerator # 题目生成器接口 - -│ │ │ └── SeniorHighGenerator.java # 高中题目生成器 - -│ │ └──model/ # 实体类 - -│ │ ├── api/ # API响应类 - -│ │ ├── exam/ # 题目试卷类 - -│ │ └── user/ # 用户类 - -│ └── .gitignore # Git忽略文件 - -└──doc/ #说明文档 - - └── README.md - -## **功能说明** - -**核心功能** - -1.用户认证:支持用户注册、登录、退出、修改密码功能 - -2.题目生成:根据用户选择的学段(小学、初中、高中)生成相应难度的数学题目 - -3.答题系统:提供交互式答题界面 - -4.成绩评估:答题完成后计算并展示得分和评价 - - - -## **题目生成** - -系统根据不同学段生成相应难度的题目: - -高中阶段包含对数等高级数学题目 - -题目数量可在 10-30 之间选择 - -生成过程包含详细日志记录,便于调试和跟踪 - - - -## **技术栈** - -前端技术 - -Electron:用于构建跨平台桌面应用 - -HTML/CSS:页面结构和样式 - -JavaScript:交互逻辑 - -node-fetch:网络请求 - -后端技术 - -Java:后端服务开发 - -JDK 21:Java 开发环境 - - - -## **环境配置与运行** - -后端运行: - -1.确保安装 JDK 21 - -2.在 IDE(如 IntelliJ IDEA)中打开math\_learn项目 - -3.运行com.mathlearn.Main主类启动后端服务 - - - -## **API 接口说明** - -生成试卷 - -端点:/generate-exam - -方法:POST - -参数: - - sessionId:用户会话 ID - - userType:用户类型(小学 / 初中 / 高中) - - questionCount:题目数量(10-30) - -返回:包含试卷信息和第一题的 JSON 响应 - - - -## **退出登录** - -端点:/logout - -方法:POST - -参数: - -sessionId:用户会话 ID - -返回:退出结果 - - - -## **注意事项** - -确保后端服务在本地 8080 端口运行,否则前端无法正常获取数据 - -题目生成可能需要一定时间,系统设置了 15 秒超时控制 - -若遇到连接问题,请检查: - -1.后端 Java 程序是否运行 - -2.网络连接是否正常 - -3.端口 8080 是否被占用 - - - -## **使用教程** - -1.后端启动 - -两种路径: - - 1)安装mathlearn\_setup.exe安装包,根据指示完成下载 - - 确保端口8080未被占用 - - backend目录有jar和exe两种方式启动后端服务器 - - 2)在 IDE(如 IntelliJ IDEA,或其他编程软件)中打开math\_learn项目 - - 确保端口8080未被占用 - - 运行com.mathlearn.Main主类启动后端服务 - -2.前端运行: - -安装mathlearn\_setup.exe安装包,根据指示完成下载 - -3.根据邮箱注册自己的账号并完成登录 - -4\.根据用户类型选择不同的题目类型,并输入所需题目数量(10-30题) - -5\.完成答题并查看所得分数 - -6\.安装目录下backend/math_questions文件夹里存储用户答题数据 - diff --git a/src/electron-frontend/package.json b/src/electron-frontend/package.json index 8a20168..85b1de1 100644 --- a/src/electron-frontend/package.json +++ b/src/electron-frontend/package.json @@ -2,16 +2,15 @@ "name": "math-learning-app", "version": "1.0.0", "description": "小初高数学学习软件", - "main": "resources/main.js", + "main": "src/main.js", "scripts": { "start": "electron .", "dev": "electron . --dev", - "build": "electron-builder", - "dist": "electron-builder --publish=never" + "build": "electron-builder" }, "devDependencies": { - "electron": "^22.3.27", - "electron-builder": "^24.13.3" + "electron": "^22.0.0", + "electron-builder": "^24.0.0" }, "build": { "appId": "com.mathlearning.app", @@ -20,33 +19,16 @@ "output": "dist" }, "files": [ - "resources/**/*", - "!resources/node_modules", - "!**/*.map", - "!**/*.log" + "src/**/*", + "styles/**/*", + "assets/**/*" ], "win": { - "target": [ - { - "target": "nsis", - "arch": [ - "x64" - ] - } - ], - "icon": "resources/icon.ico" - }, - "nsis": { - "oneClick": false, - "allowToChangeInstallationDirectory": true, - "createDesktopShortcut": true, - "createStartMenuShortcut": true, - "shortcutName": "数学学习系统" - }, - "compression": "maximum", - "asar": true + "target": "nsis", + "icon": "assets/icon.ico" + } }, "dependencies": { "node-fetch": "^2.7.0" } -} \ No newline at end of file +} diff --git a/src/electron-frontend/resources/main.js b/src/electron-frontend/resources/main.js index 80668d2..688dacc 100644 --- a/src/electron-frontend/resources/main.js +++ b/src/electron-frontend/resources/main.js @@ -4,43 +4,24 @@ const path = require('path'); let mainWindow; -function createWindow(initialPage = 'login') { - // 如果已存在窗口,先关闭 - if (mainWindow) { - mainWindow.close(); - mainWindow = null; - } - +function createWindow() { mainWindow = new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: false, contextIsolation: true, - preload: path.join(__dirname, 'preload.js'), - webSecurity: false, - backgroundThrottling: false + preload: path.join(__dirname, 'preload.js'), // 确保路径正确 + webSecurity: false // 开发时可以关闭,避免CORS问题 }, - show: false, - backgroundColor: '#ffffff' + icon: path.join(__dirname, 'assets/icon.png') // 可选 }); - // 在窗口准备好后显示 - mainWindow.once('ready-to-show', () => { - mainWindow.show(); - mainWindow.focus(); - }); + // 加载登录页面 + mainWindow.loadFile(path.join(__dirname, 'renderer/login.html')); - // 根据参数加载不同页面 - if (initialPage === 'login') { - mainWindow.loadFile(path.join(__dirname, 'renderer/login.html')); - } else { - mainWindow.loadFile(path.join(__dirname, `renderer/${initialPage}.html`)); - } - + // 开发时打开开发者工具 mainWindow.webContents.openDevTools(); - - return mainWindow; } function createMenu() { @@ -99,22 +80,12 @@ ipcMain.handle('api-request', async (event, { endpoint, method = 'POST', data = } }); -// 修改导航处理 - 对于登录页面完全重新创建窗口 +// 页面导航 ipcMain.handle('navigate-to', (event, page) => { - if (page === 'login') { - // 对于登录页面,完全重新创建窗口 - createWindow('login'); - } else { - // 其他页面使用普通导航 - mainWindow.loadFile(path.join(__dirname, `renderer/${page}.html`)); - } + mainWindow.loadFile(path.join(__dirname, `renderer/${page}.html`)); }); -// 修复:只有一个 app.whenReady() 调用 -app.whenReady().then(() => { - createWindow('login'); - createMenu(); // 在这里创建菜单 -}); +app.whenReady().then(createWindow); app.on('window-all-closed', () => { if (process.platform !== 'darwin') { @@ -124,6 +95,6 @@ app.on('window-all-closed', () => { app.on('activate', () => { if (BrowserWindow.getAllWindows().length === 0) { - createWindow('login'); + createWindow(); } }); \ No newline at end of file diff --git a/src/electron-frontend/resources/preload.js b/src/electron-frontend/resources/preload.js index dd844a6..5f08f7e 100644 --- a/src/electron-frontend/resources/preload.js +++ b/src/electron-frontend/resources/preload.js @@ -1,8 +1,60 @@ const { contextBridge, ipcRenderer } = require('electron'); +// 统一的会话管理器 +const SessionManager = { + // 获取当前用户会话(强制从存储读取) + getCurrentUser() { + try { + const session = localStorage.getItem('userSession'); + return session ? JSON.parse(session) : null; + } catch (error) { + console.error('获取用户会话失败:', error); + return null; + } + }, + + // 获取当前考试会话 + getCurrentExam() { + try { + const exam = localStorage.getItem('currentExam'); + return exam ? JSON.parse(exam) : null; + } catch (error) { + console.error('获取考试会话失败:', error); + return null; + } + }, + + // 清除所有会话 + clearAllSessions() { + localStorage.removeItem('userSession'); + localStorage.removeItem('currentExam'); + localStorage.removeItem('examResult'); + console.log('所有会话已清除'); + }, + + // 验证会话是否有效 + validateUserSession() { + const user = this.getCurrentUser(); + if (!user || !user.sessionId) { + return false; + } + + // 可以添加更多验证逻辑,比如检查过期时间等 + return true; + }, + + // 刷新用户会话(在修改密码等操作后) + refreshUserSession(updatedUserData) { + if (updatedUserData) { + localStorage.setItem('userSession', JSON.stringify(updatedUserData)); + } + } + +}; + // 暴露安全的API给渲染进程 contextBridge.exposeInMainWorld('electronAPI', { - // 简单的导航功能 + // 页面导航 navigateTo: (page) => ipcRenderer.invoke('navigate-to', page), // 存储会话数据 @@ -17,13 +69,34 @@ contextBridge.exposeInMainWorld('electronAPI', { removeSession: (key) => { localStorage.removeItem(key); + }, + + // 新增:获取当前会话状态 + getSessionState: () => { + return SessionManager.validateSession(); + }, + + // 新增:强制清除所有会话 + clearAllSessions: () => { + SessionManager.clearAllSessions(); + }, + // 新增会话验证方法 + validateSession: () => { + return SessionManager.validateUserSession(); + }, + + // 新增会话刷新方法 + refreshSession: (userData) => { + SessionManager.refreshUserSession(userData); } }); -// API 请求 +// 直接在渲染进程中暴露 API 调用函数 contextBridge.exposeInMainWorld('api', { request: async (endpoint, method = 'POST', data = {}) => { try { + console.log('API Request:', endpoint, method, data); + const url = `http://localhost:8080/api${endpoint}`; const formData = new URLSearchParams(); @@ -40,8 +113,10 @@ contextBridge.exposeInMainWorld('api', { }); const result = await response.json(); + console.log('API Response:', result); return result; } catch (error) { + console.error('API Error:', error); return { success: false, message: `网络错误: ${error.message}`, @@ -49,4 +124,6 @@ contextBridge.exposeInMainWorld('api', { }; } } -}); \ No newline at end of file +}); + +console.log('Preload script loaded successfully'); \ No newline at end of file diff --git a/src/electron-frontend/resources/renderer/login.html b/src/electron-frontend/resources/renderer/login.html index 60fa060..7d51f60 100644 --- a/src/electron-frontend/resources/renderer/login.html +++ b/src/electron-frontend/resources/renderer/login.html @@ -27,12 +27,6 @@ font-size: 16px; } - input:focus { - border-color: #007acc; - outline: none; - box-shadow: 0 0 0 2px rgba(0, 122, 204, 0.2); - } - button { width: 100%; padding: 12px; @@ -63,10 +57,10 @@