diff --git a/src/backend/controller/interfaces/LoginController.java b/src/backend/controller/interfaces/LoginController.java deleted file mode 100644 index c41c52f..0000000 --- a/src/backend/controller/interfaces/LoginController.java +++ /dev/null @@ -1,26 +0,0 @@ -package backend.controller.interfaces; - -/** - * 登录控制器接口,用于处理用户登录和注册相关的业务逻辑 - */ -public interface LoginController { -// AuthService authService; - - //getter/setter - - /** - * 处理用户登录请求 - * @param username 用户名 - * @param password 密码 - */ - public void handleLogin(String username, String password); - - /** - * 处理用户注册请求 - * @param username 用户名 - * @param password 密码 - * @param email 邮箱地址 - */ - public void handleRegister(String username, String password, String email); -} - diff --git a/src/backend/controller/interfaces/QueryController.java b/src/backend/controller/interfaces/QueryController.java deleted file mode 100644 index 2f11a49..0000000 --- a/src/backend/controller/interfaces/QueryController.java +++ /dev/null @@ -1,33 +0,0 @@ -package backend.controller.interfaces; -import backend.service.interfaces.DataQueryService; - -/** - * 查询控制器接口 - * 定义了数据查询和管理的相关操作接口 - */ -public interface QueryController { -// DataQueryService dataService; - //getter/setter - - /** - * 显示所有数据项 - * 该方法用于获取并展示系统中的全部数据记录 - */ - void displayAll(); - - /** - * 根据关键字搜索数据 - * @param keyword 搜索关键字,用于匹配数据项的标题、描述等字段 - */ - void searchData(String keyword); - - /** - * 添加新的数据项 - * @param title 数据项标题 - * @param desc 数据项描述 - * @param category 数据项分类 - * @param userId 用户ID,标识数据项的创建者 - */ - void addDataItem(String title, String desc, String category, int userId); -} - diff --git a/src/backend/controller/interfaces/UserController.java b/src/backend/controller/interfaces/UserController.java deleted file mode 100644 index 58c7395..0000000 --- a/src/backend/controller/interfaces/UserController.java +++ /dev/null @@ -1,33 +0,0 @@ -package backend.controller.interfaces; -import backend.service.interfaces.UserService; - -/** - * 用户控制器接口 - * 定义了用户管理相关的核心操作方法 - */ -public interface UserController { -// UserService userService; - - //getter/setter - - /** - * 显示指定用户的详细信息 - * @param id 用户ID - */ - void showUserInfo(int id); - - /** - * 列出所有用户信息 - * @param adminId 管理员ID,用于权限验证 - */ - void listAllUsers(int adminId); - - /** - * 更新用户角色 - * @param targetId 目标用户ID - * @param newRole 新的角色名称 - * @param adminId 执行操作的管理员ID - */ - void updateRole(int targetId, String newRole, int adminId); -} - diff --git a/src/backend/dao/ChartsDao.java b/src/backend/dao/ChartsDao.java new file mode 100644 index 0000000..6ebc66a --- /dev/null +++ b/src/backend/dao/ChartsDao.java @@ -0,0 +1,160 @@ +package backend.dao; + +import backend.model.Charts; +import backend.utils.DBConnectionPool; +import backend.utils.DBHelper; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +public class ChartsDao { + List commonResultSet(ResultSet rs) throws SQLException { + List chartsPoList = new ArrayList<>(); + while(rs.next()){ + Charts charts = new Charts(); + charts.setUserid(rs.getInt("userid")); + charts.setCount(rs.getInt("count")); + charts.setScore(rs.getInt("score")); + chartsPoList.add(charts); + } + return chartsPoList; + } + public List findAll() { + List chartsPoList = new ArrayList<>(); + Connection conn = DBHelper.getInstance().getConnection(); + String sql = "select userid,count,score from charts"; + try { + PreparedStatement stmt = conn.prepareStatement(sql); + ResultSet rs = stmt.executeQuery(); + while (rs.next()) { + Charts charts = new Charts(); + charts.setUserid(rs.getInt("userid")); + charts.setCount(rs.getInt("count")); + charts.setScore(rs.getInt("score")); + chartsPoList.add(charts); + } + rs.close(); + stmt.close(); + } catch (SQLException e) { + System.out.println("查询所有用户失败: " + e.getMessage()); + } + return chartsPoList; + } + public Charts findById(int userid) { + Connection conn = DBHelper.getInstance().getConnection(); + Charts chartsPo = null; + if(conn==null) + return null; + String sql = "select userid,count,score from charts where userid = ?"; + try { + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setInt(1,userid); + ResultSet rs = stmt.executeQuery(); + while (rs.next()) { + chartsPo = new Charts(); + chartsPo.setUserid(rs.getInt("userid")); + chartsPo.setCount(rs.getInt("count")); + chartsPo.setScore(rs.getInt("score")); + + } + rs.close(); + stmt.close(); + } catch (SQLException e) { + System.out.println("查询用户失败: " + e.getMessage()); + } + return chartsPo; + } + public boolean insertCharts(Charts charts) { + Connection conn = DBHelper.getInstance().getConnection(); + int row = 0; + if(conn==null) + return false; + //查找是否已存在 + String findSql = "select * from charts where userid = ?"; + try{ + PreparedStatement stmt = conn.prepareStatement(findSql); + stmt.setInt(1,charts.getUserid()); + ResultSet rs = stmt.executeQuery(); + if(rs.next()){ + return false; + } + rs.close(); + } catch (SQLException e) { + System.out.println("查找用户失败: " + e.getMessage()); + } + String sql = "insert into charts (userid,count,score) values (?,?,?)"; + try{ + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setInt(1,charts.getUserid()); + stmt.setInt(2,charts.getCount()); + stmt.setInt(3,charts.getScore()); + row = stmt.executeUpdate(); + stmt.close(); + DBConnectionPool.releaseConnection(conn); + } catch (SQLException e) { + System.out.println("添加用户失败: " + e.getMessage()); + } + return row > 0; + } + public boolean updateCharts(Charts charts) { + Connection conn = DBHelper.getInstance().getConnection(); + Charts oldCharts = findById(charts.getUserid()); + int row = 0; + if(conn==null) + return false; + String sql = "update charts set count = ?,score = ? where userid = ?"; + try{ + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setInt(1,oldCharts.getCount()+1); + stmt.setInt(2,oldCharts.getScore()+charts.getScore()); + stmt.setInt(3,charts.getUserid()); + row = stmt.executeUpdate(); + stmt.close(); + } catch (SQLException e) { + System.out.println("更新用户失败: " + e.getMessage()); + } + return row > 0; + } + public boolean deleteCharts(int userid) { + Connection conn = DBHelper.getInstance().getConnection(); + String sql = "delete from charts where userid = ?"; + int row = 0; + try{ + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setInt(1,userid); + row = stmt.executeUpdate() ; + } catch (SQLException e) { + System.out.println("删除用户失败: " + e.getMessage()); + } + return row>0; + } + public List sortByScoreUp() { + List chartsPoList = new ArrayList<>(); + List list = findAll(); + for(int i = 0; i < list.size() - 1; i++) { + for(int j = i + 1; j < list.size(); j++) { + if(list.get(i).getScore() < list.get(j).getScore()) { + Charts temp = list.get(i); + list.set(i, list.get(j)); + list.set(j, temp); + } + } + } + return list; + } + public List sortByScoreDown() { + List chartsPoList = new ArrayList<>(); + List list = findAll(); + for(int i = 0; i < list.size() - 1; i++) { + for(int j = i + 1; j < list.size(); j++) { + if(list.get(i).getScore() > list.get(j).getScore()) { + Charts temp = list.get(i); + list.set(i, list.get(j)); + list.set(j, temp); + } + } + } + return list; + } +} diff --git a/src/backend/dao/impl/QuestionsDao.java b/src/backend/dao/QuestionsDao.java similarity index 69% rename from src/backend/dao/impl/QuestionsDao.java rename to src/backend/dao/QuestionsDao.java index ad0ccad..a6a5788 100644 --- a/src/backend/dao/impl/QuestionsDao.java +++ b/src/backend/dao/QuestionsDao.java @@ -1,9 +1,11 @@ -package backend.dao.impl; +package backend.dao; import backend.model.Questions; +import backend.model.TestRecord; import backend.utils.DBConnectionPool; import java.sql.*; import java.util.ArrayList; import java.util.List; +import java.util.Random; public class QuestionsDao { List commonResultSet(ResultSet rs) throws SQLException{ @@ -41,6 +43,44 @@ public class QuestionsDao { } return questionPoList; } + + public Questions getById(Integer id) { + Connection conn = DBConnectionPool.getConnection(); + if (conn == null) + return null; + + Questions questionPo = null; + PreparedStatement stmt = null; + ResultSet rs = null; + + try { + stmt = conn.prepareStatement("select id,name,description,answer,frequency from questions where id = ?"); + stmt.setInt(1, id); + rs = stmt.executeQuery(); + + if (rs.next()) { // 检查是否有数据 + questionPo = new Questions(); + questionPo.setId(rs.getInt("id")); + questionPo.setName(rs.getString("name")); + questionPo.setDescription(rs.getString("description")); + questionPo.setAnswer(rs.getString("answer")); + questionPo.setFrequency(rs.getInt("frequency")); + } + } catch (SQLException e) { + System.out.println("数据库异常:" + e.getMessage()); + } finally { + // 释放资源 + try { + if (rs != null) rs.close(); + if (stmt != null) stmt.close(); + } catch (SQLException e) { + System.out.println("资源释放异常:" + e.getMessage()); + } + DBConnectionPool.releaseConnection(conn); + } + return questionPo; + } + public List getByCondition(Integer frequency,String key) { List questionPoList = null; //1. 从连接池中拿到连接 @@ -147,6 +187,37 @@ public class QuestionsDao { } + public Questions getRandomQuestion() { + List questionPoList = getAll(); + Random random = new Random(); + //生成随机索引 + int index = random.nextInt(questionPoList.size()); + return questionPoList.get(index); + } + + public Questions getByName(String name) { + Questions questionPo = null; + //1. 从连接池中拿到连接 + Connection conn = DBConnectionPool.getConnection(); + if(conn==null) + return null; + //2. 创建Statement对象 + String sql = "select id,name,description,answer,frequency from questions where name = ?"; + try{ + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, name); + ResultSet rs = stmt.executeQuery(); + questionPo = commonResultSet(rs).get(0); + rs.close(); + stmt.close(); + } catch(SQLException e){ + System.out.println("数据库异常:"+ e.getMessage()); + } finally { + DBConnectionPool.releaseConnection(conn); + } + return questionPo; + } + // public static void main(String[] args) { // WordDao wordDao = new WordDao(); // //查询 diff --git a/src/backend/dao/TestRecordDao.java b/src/backend/dao/TestRecordDao.java new file mode 100644 index 0000000..925f52c --- /dev/null +++ b/src/backend/dao/TestRecordDao.java @@ -0,0 +1,163 @@ +package backend.dao; + +import backend.model.TestRecord; +import backend.utils.DBConnectionPool; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +public class TestRecordDao { + List commonResultSet(ResultSet rs) throws SQLException{ + List testRecordPoList = new ArrayList<>(); + while(rs.next()){ + TestRecord testRecord = new TestRecord(); + testRecord.setId(rs.getInt("id")); + testRecord.setUserId(rs.getInt("userId")); + testRecord.setQuestionId(rs.getInt("questionId")); + testRecord.setScore(rs.getInt("score")); + testRecord.setAnswer(rs.getString("answer")); + testRecord.setTime(rs.getDate("time")); + testRecordPoList.add(testRecord); + } + return testRecordPoList; + } + + public List getAll() { + List testRecordPoList = new ArrayList<>(); + //1. 从连接池中拿到连接 + Connection conn = DBConnectionPool.getConnection(); + if(conn==null) + return null; + //2. 创建Statement对象 + String sql = "select id,userId,questionId,score,answer,time from testRecord"; + try{ + PreparedStatement stmt = conn.prepareStatement(sql); + ResultSet rs = stmt.executeQuery(); + testRecordPoList=commonResultSet(rs); + rs.close(); + stmt.close(); + } catch(SQLException e){ + System.out.println("数据库异常:"+ e.getMessage()); + } + finally { + DBConnectionPool.releaseConnection(conn); + } + return testRecordPoList; + } + public List getByUserId(Integer userId) { + List testRecordPoList = new ArrayList<>(); + //1. 从连接池中拿到连接 + Connection conn = DBConnectionPool.getConnection(); + if(conn==null) + return null; + //2. 创建Statement对象 + String sql = "select id,userId,questionId,score,answer,time from testRecord where userId = ?"; + try{ + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setInt(1, userId); + ResultSet rs = stmt.executeQuery(); + testRecordPoList=commonResultSet(rs); + rs.close(); + stmt.close(); + } catch(SQLException e){ + System.out.println("数据库异常:"+ e.getMessage()); + } finally { + DBConnectionPool.releaseConnection(conn); + } + return testRecordPoList; + } + public List getByQuestionId(Integer questionId) { + List testRecordPoList = new ArrayList<>(); + //1. 从连接池中拿到连接 + Connection conn = DBConnectionPool.getConnection(); + if(conn==null) + return null; + //2. 创建Statement对象 + String sql = "select id,userId,questionId,score,answer,time from testRecord where questionId = ?"; + try{ + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setInt(1, questionId); + ResultSet rs = stmt.executeQuery(); + testRecordPoList=commonResultSet(rs); + rs.close(); + stmt.close(); + } + catch(SQLException e){ + System.out.println("数据库异常:"+ e.getMessage()); + } finally { + DBConnectionPool.releaseConnection(conn); + } + return testRecordPoList; + } + public List getByUserIdAndQuestionId(Integer userId, Integer questionId) { + List testRecordPoList = new ArrayList<>(); + //1. 从连接池中拿到连接 + Connection conn = DBConnectionPool.getConnection(); + if(conn==null) + return null; + //2. 创建Statement对象 + String sql = "select id,userId,questionId,score,answer,time from testRecord where userId = ? and questionId = ?"; + try{ + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setInt(1, userId); + stmt.setInt(2, questionId); + ResultSet rs = stmt.executeQuery(); + testRecordPoList = commonResultSet(rs); + rs.close(); + stmt.close(); + } catch(SQLException e){ + System.out.println("数据库异常:"+ e.getMessage()); + } finally { + DBConnectionPool.releaseConnection(conn); + } + return testRecordPoList; + } + + + public boolean insert(TestRecord testRecord){ + int row = 0; + //1. 从连接池中拿到连接 + Connection conn = DBConnectionPool.getConnection(); + if(conn==null) + return false; + //2. 创建Statement对象 + String sql = "insert into testRecord(userId,questionId,score,answer,time) values(?,?,?,?,?)"; + try{ + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setInt(1, testRecord.getUserId()); + stmt.setInt(2, testRecord.getQuestionId()); + stmt.setInt(3, testRecord.getScore()); + stmt.setString(4, testRecord.getAnswer()); + stmt.setDate(5, testRecord.getTime()); + row = stmt.executeUpdate(); + stmt.close(); + } catch(SQLException e){ + System.out.println("数据库异常:"+ e.getMessage()); + } finally { + DBConnectionPool.releaseConnection(conn); + } + return row > 0; + } + public boolean delete(Integer id){ + int row = 0; + //1. 从连接池中拿到连接 + Connection conn = DBConnectionPool.getConnection(); + if(conn==null) + return false; + //2. 创建Statement对象 + String sql = "delete from testRecord where id = ?"; + try{ + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setInt(1, id); + row = stmt.executeUpdate(); + stmt.close(); + } catch(SQLException e){ + System.out.println("数据库异常:"+ e.getMessage()); + } finally { + DBConnectionPool.releaseConnection(conn); + } + return row > 0; + } + +} diff --git a/src/backend/dao/impl/UserDao.java b/src/backend/dao/UserDao.java similarity index 61% rename from src/backend/dao/impl/UserDao.java rename to src/backend/dao/UserDao.java index d8d32bb..7c2e21d 100644 --- a/src/backend/dao/impl/UserDao.java +++ b/src/backend/dao/UserDao.java @@ -1,57 +1,74 @@ -package backend.dao.impl; +package backend.dao; -import backend.dao.interfaces.UserDaoIF; import backend.model.User; +import backend.service.AuthService; import backend.utils.DBConnectionPool; import backend.utils.DBHelper; import java.sql.*; +import java.util.ArrayList; import java.util.List; -public class UserDao implements UserDaoIF { +public class UserDao { + + List commonResultSet(ResultSet rs) throws SQLException{ + List userPoList = new ArrayList<>(); + while(rs.next()){ + User user = new User(); + user.setId(rs.getInt("id")); + user.setUsername(rs.getString("username")); + user.setPassword(rs.getString("password")); + user.setRole(rs.getString("role")); + user.setEmail(rs.getString("email")); + user.setCreatedAt(rs.getDate("createdAt")); + userPoList.add(user); + } + return userPoList; + } - @Override public User findByUsername(String username) { User user = null; //1. 从连接池中创建数据库连接 Connection conn = DBHelper.getInstance().getConnection(); //2. 创建Statement对象 - String sql = "select username,password,role,email,createdAt from USER where username = ?"; + String sql = "select id,username,password,role,email,createdAt from USER where username = ?"; try { PreparedStatement stmt = conn.prepareStatement(sql); stmt.setString(1, username); ResultSet rs = stmt.executeQuery(); while (rs.next()) { user = new User(); + user.setId(rs.getInt("id")); user.setUsername(rs.getString("username")); user.setPassword(rs.getString("password")); user.setRole(rs.getString("role")); user.setEmail(rs.getString("email")); - user.setCreatedAt(String.valueOf(rs.getTimestamp("createdAt"))); + user.setCreatedAt(rs.getDate("createdAt")); } } catch (SQLException e) { System.out.println("查询用户失败: " + e.getMessage()); } return user; } - @Override + public User findById(int id) { User user = null; //1. 从连接池中创建数据库连接 Connection conn = DBHelper.getInstance().getConnection(); //2. 创建Statement对象 - String sql = "select username,password,role,email,createdAt from USER where id = ?"; + String sql = "select id,username,password,role,email,createdAt from USER where id = ?"; try{ PreparedStatement stmt = conn.prepareStatement(sql); stmt.setInt(1,id); ResultSet rs = stmt.executeQuery(); while(rs.next()) { user = new User(); + user.setId(rs.getInt("id")); user.setUsername(rs.getString("username")); user.setPassword(rs.getString("password")); user.setRole(rs.getString("role")); user.setEmail(rs.getString("email")); - user.setCreatedAt(String.valueOf(rs.getTimestamp("createdAt"))); + user.setCreatedAt(rs.getDate("createdAt")); } }catch (SQLException e) { System.out.println("查询用户失败: " + e.getMessage()); @@ -59,12 +76,11 @@ public class UserDao implements UserDaoIF { return user; } - @Override - public int addUser(User user) { + public boolean addUser(User user) { Connection conn = DBHelper.getInstance().getConnection(); int row=0; if(conn==null) - return 0; + return false; String sql = "insert into USER (username,password,role,email,createdAt) values (?,?,?,?,?)"; try{ PreparedStatement stmt = conn.prepareStatement(sql); @@ -79,15 +95,14 @@ public class UserDao implements UserDaoIF { } catch (SQLException e) { System.out.println("添加用户失败: " + e.getMessage()); } - return row; + return row>0; } - @Override - public int updateUser(User user) { + public boolean updateUser(User user) { Connection conn = DBHelper.getInstance().getConnection(); int row = 0; if(conn==null) - return 0; + return false; String sql = "update USER set username = ?,password = ?,role = ?,email = ?,createdAt = ? where id = ?"; try{ @@ -100,15 +115,15 @@ public class UserDao implements UserDaoIF { stmt.setInt(6,user.getId()); row = stmt.executeUpdate(); stmt.close(); - DBConnectionPool.releaseConnection(conn); } catch (SQLException e) { System.out.println("更新用户失败: " + e.getMessage()); + }finally { + DBConnectionPool.releaseConnection(conn); } - return row; + return row>0; } - @Override - public int deleteUser(int id) { + public boolean deleteUser(int id) { Connection conn = DBHelper.getInstance().getConnection(); String sql = "delete from USER where id = ?"; int row = 0; @@ -119,11 +134,11 @@ public class UserDao implements UserDaoIF { } catch (SQLException e) { System.out.println("删除用户失败: " + e.getMessage()); } - return row; + return row>0; } - @Override public List findAll() { + List userPoList = new ArrayList<>(); Connection conn = DBHelper.getInstance().getConnection(); String sql = "select id,username,password,role,email,createdAt from USER"; try { @@ -136,12 +151,53 @@ public class UserDao implements UserDaoIF { user.setPassword(rs.getString("password")); user.setRole(rs.getString("role")); user.setEmail(rs.getString("email")); - user.setCreatedAt(String.valueOf(rs.getTimestamp("createdAt"))); - return List.of(user); + user.setCreatedAt(rs.getDate("createdAt")); + userPoList.add(user); } }catch (SQLException e) { System.out.println("查询所有用户失败: " + e.getMessage()); } - return List.of(); + return userPoList; } + + + public List findByCondition(String role, String key) { + List userPoList = null; + //1. 从连接池中拿到连接 + Connection conn = DBConnectionPool.getConnection(); + if(conn==null) + return null; + //2. 创建Statement对象 + String sql = "select id,username,password,role,email,createdAt from USER where username like ?"; + if(role != null) + sql += " and role = ?"; + try{ + PreparedStatement stmt = conn.prepareStatement(sql); + stmt.setString(1, "%"+key+"%"); + if(role != null) + stmt.setString(2, role); + ResultSet rs = stmt.executeQuery(); + userPoList =commonResultSet(rs); + rs.close(); + stmt.close(); + + }catch(SQLException e){ + System.out.println("数据库异常:"+ e.getMessage()); + }finally { + DBConnectionPool.releaseConnection(conn); + } + return userPoList; + } + + public static void main(String[] args) { + UserDao userDao = new UserDao(); + AuthService authService = new AuthService(); + User user= userDao.findById(2); + System.out.println(user.getRole()); + user.setRole("admin"); + System.out.println(user.getRole()); + userDao.updateUser(user); + System.out.println(userDao.findById(2).getRole()); + } + } diff --git a/src/backend/dao/interfaces/DataItemDao.java b/src/backend/dao/interfaces/DataItemDao.java deleted file mode 100644 index c6217fb..0000000 --- a/src/backend/dao/interfaces/DataItemDao.java +++ /dev/null @@ -1,51 +0,0 @@ -package backend.dao.interfaces; -import backend.model.DataItem; -import java.util.*; -import java.sql.*; - -/** - * 数据项DAO接口,提供数据项的增删改查操作 - */ -public interface DataItemDao { - /** - * 根据ID查找数据项 - * @param id 数据项ID - * @return 找到的数据项对象,如果未找到则返回null - */ - DataItem findById(int id); - - /** - * 查找所有数据项 - * @return 包含所有数据项的列表 - */ - List findAll(); - - /** - * 根据关键字搜索数据项 - * @param keyword 搜索关键字 - * @return 匹配关键字的数据项列表 - */ - List searchByKeyword(String keyword); - - /** - * 添加数据项 - * @param item 要添加的数据项对象 - * @return 添加成功返回true,失败返回false - */ - boolean addItem(DataItem item); - - /** - * 更新数据项 - * @param item 包含更新信息的数据项对象 - * @return 更新成功返回true,失败返回false - */ - boolean updateItem(DataItem item); - - /** - * 删除数据项 - * @param id 要删除的数据项ID - * @return 删除成功返回true,失败返回false - */ - boolean deleteItem(int id); -} - diff --git a/src/backend/dao/interfaces/QueryRecordDao.java b/src/backend/dao/interfaces/QueryRecordDao.java deleted file mode 100644 index d017030..0000000 --- a/src/backend/dao/interfaces/QueryRecordDao.java +++ /dev/null @@ -1,28 +0,0 @@ -package backend.dao.interfaces; -import backend.model.QueryRecord; -import java.util.*; - -/** - * 查询记录数据访问接口 - * 定义了对查询记录进行持久化操作的方法 - */ -public interface QueryRecordDao { - /** - * 添加查询记录 - * 将指定的查询记录保存到数据存储中 - * - * @param record 要添加的查询记录对象,不能为null - * @return 添加成功返回true,否则返回false - */ - boolean addRecord(QueryRecord record); - - /** - * 根据用户ID查找查询记录 - * 返回指定用户的所有查询记录列表 - * - * @param userId 用户唯一标识符 - * @return 查询记录列表,如果未找到则返回空列表 - */ - List findByUserId(int userId); -} - diff --git a/src/backend/dao/interfaces/UserDaoIF.java b/src/backend/dao/interfaces/UserDaoIF.java deleted file mode 100644 index 78d5624..0000000 --- a/src/backend/dao/interfaces/UserDaoIF.java +++ /dev/null @@ -1,52 +0,0 @@ -package backend.dao.interfaces; - -import backend.model.User; -import java.util.*; - -/** - * 用户数据访问接口 - * 定义了用户相关的数据库操作方法 - */ -public interface UserDaoIF { - /** - * 根据用户名查找用户 - * @param username 用户名 - * @return 查找到的用户对象,如果未找到则返回null - */ - User findByUsername(String username); - - /** - * 根据用户ID查找用户 - * @param id 用户ID - * @return 查找到的用户对象,如果未找到则返回null - */ - User findById(int id); - - /** - * 添加新用户 - * @param user 要添加的用户对象 - * @return 添加成功返回true,失败返回false - */ - int addUser(User user); - - /** - * 更新用户信息 - * @param user 包含更新信息的用户对象 - * @return 更新成功返回true,失败返回false - */ - int updateUser(User user); - - /** - * 删除用户 - * @param id 要删除的用户ID - * @return 删除成功返回true,失败返回false - */ - int deleteUser(int id); - - /** - * 查找所有用户 - * @return 包含所有用户对象的列表 - */ - List findAll(); -} - diff --git a/src/backend/model/Charts.java b/src/backend/model/Charts.java new file mode 100644 index 0000000..449ab18 --- /dev/null +++ b/src/backend/model/Charts.java @@ -0,0 +1,40 @@ +package backend.model; + +public class Charts { + private int userid; + private int count; + private int score; + + public Charts() { + } + + public Charts(int userid, int count, int score) { + this.userid = userid; + this.count = count; + this.score = score; + } + + public int getUserid() { + return userid; + } + + public void setUserid(int userid) { + this.userid = userid; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } + + public int getScore() { + return score; + } + + public void setScore(int score) { + this.score = score; + } +} diff --git a/src/backend/model/TestRecord.java b/src/backend/model/TestRecord.java new file mode 100644 index 0000000..495b507 --- /dev/null +++ b/src/backend/model/TestRecord.java @@ -0,0 +1,71 @@ +package backend.model; +import java.sql.*; + +public class TestRecord { + private int id; + private int userId; + private int questionId; + private int score; + private String answer; + private Date time; + + public TestRecord() { + } + + public TestRecord(int id, int userId, int questionId, int score, String answer, Date time) { + this.id = id; + this.userId = userId; + this.questionId = questionId; + this.score = score; + this.answer = answer; + this.time = time; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public int getUserId() { + return userId; + } + + public void setUserId(int userId) { + this.userId = userId; + } + + public int getQuestionId() { + return questionId; + } + + public void setQuestionId(int questionId) { + this.questionId = questionId; + } + + public int getScore() { + return score; + } + + public void setScore(int score) { + this.score = score; + } + + public String getAnswer() { + return answer; + } + + public void setAnswer(String answer) { + this.answer = answer; + } + + public Date getTime() { + return time; + } + + public void setTime(Date time) { + this.time = time; + } +} diff --git a/src/backend/model/User.java b/src/backend/model/User.java index 14a3e4f..00692ce 100644 --- a/src/backend/model/User.java +++ b/src/backend/model/User.java @@ -85,9 +85,6 @@ public class User { * @param role 用户角色,可选值为"admin"或"user" */ public void setRole(String role) { - if(this.getUsername().equals("admin")) - this.role = "admin"; - else this.role = role; } @@ -114,15 +111,12 @@ public class User { * * @param createdAt 用户创建时间 */ -public void setCreatedAt(String createdAt) { - try { - long timestamp = Long.parseLong(createdAt); - this.createdAt = new Date(timestamp); - } catch (NumberFormatException e) { - // 如果不是有效的时间戳,可以设置为当前日期或处理异常 + public void setCreatedAt(Date createdAt) { + this.createdAt = createdAt; + } + public void setCreatedAt() { this.createdAt = new Date(System.currentTimeMillis()); } -} /** @@ -176,7 +170,8 @@ public void setCreatedAt(String createdAt) { * @return 用户创建时间 */ public Date getCreatedAt() { - return Date.valueOf(String.valueOf(createdAt)); + return createdAt; } + } diff --git a/src/backend/model/enums/ScoreKey.java b/src/backend/model/enums/ScoreKey.java new file mode 100644 index 0000000..9ea9e42 --- /dev/null +++ b/src/backend/model/enums/ScoreKey.java @@ -0,0 +1,20 @@ +package backend.model.enums; + +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class ScoreKey { + public static final Map SCORE_MAP = new HashMap<>(); + static{ + SCORE_MAP.put(0,5); + SCORE_MAP.put(1,10); + SCORE_MAP.put(2,20); + SCORE_MAP.put(3,50); + } + public static Integer getScoreByKey(Integer key) { + return SCORE_MAP.getOrDefault(key, 0); + } + +} + diff --git a/src/backend/service/AuthService.java b/src/backend/service/AuthService.java new file mode 100644 index 0000000..f653058 --- /dev/null +++ b/src/backend/service/AuthService.java @@ -0,0 +1,85 @@ +package backend.service; +import backend.dao.UserDao; +import backend.model.enums.LoginStatus; +import backend.model.User; + +import java.util.List; +import java.util.Vector; + +public class AuthService { + private UserDao userDao = new UserDao(); + + public boolean addUser(User user) { + return userDao.addUser(user); + } + + public boolean deleteUser(int id) { + return userDao.deleteUser(id); + } + + public LoginStatus login(User user) { + User dbUser = userDao.findByUsername(user.getUsername()); + if(dbUser==null) + return LoginStatus.USER_NOT_FOUND; + if(dbUser.getUsername().equals(user.getUsername())&&dbUser.getPassword().equals(user.getPassword())) + return LoginStatus.SUCCESS; + else if (!dbUser.getUsername().equals(user.getUsername())) { + return LoginStatus.USER_NOT_FOUND; + } + return LoginStatus.PASSWORD_ERROR; + } + + public LoginStatus register(User user) { + User dbAccount = userDao.findByUsername(user.getUsername()); + if(dbAccount!=null) + return LoginStatus.REGISTER_FAILED; + //点击注册按钮后的事件 + if(userDao.addUser(user)) + return LoginStatus.REGISTER_SUCCESS; + else + return LoginStatus.REGISTER_FAILED; + } + + public boolean updateUser(User user) { + return userDao.updateUser(user); + } + + private Vector> commonHandler(List usersList){ + //加工数据 把数据库查到的List转成Vector> + Vector> usersData = new Vector<>(); + if(usersList != null) { + for (User usersPo : usersList) { + Vector row = new Vector<>(); + row.add(String.valueOf(usersPo.getId())); + row.add(usersPo.getUsername()); + row.add(usersPo.getRole()); + row.add(usersPo.getEmail()); + row.add(String.valueOf(usersPo.getCreatedAt())); + usersData.add(row); + } + } + return usersData; + } + + public Vector> getAll(){ + //从数据库中获取所有用户 + List usersList = userDao.findAll(); + //把List转成表格所需的格式 + return commonHandler(usersList); + //返回给前端 + } + public Vector> getByCondition(String role, String key){ + //从数据库中获取所有用户 + List usersList = userDao.findByCondition(role,key); + //把List转成表格所需的格式 + return commonHandler(usersList); + //返回给前端 + } + public static void main(String[] args) { + UserDao userDao = new UserDao(); + AuthService authService = new AuthService(); + Vector> users= authService.commonHandler(userDao.findAll()); + System.out.println(users); + } +} + diff --git a/src/backend/service/ChartsService.java b/src/backend/service/ChartsService.java new file mode 100644 index 0000000..7803381 --- /dev/null +++ b/src/backend/service/ChartsService.java @@ -0,0 +1,52 @@ +package backend.service; + +import backend.dao.ChartsDao; +import backend.dao.QuestionsDao; +import backend.dao.UserDao; +import backend.model.Charts; + +import java.util.*; + +public class ChartsService { + private ChartsDao chartsDao = new ChartsDao(); + private UserDao userDao = new UserDao(); + + public Vector> commonHandler(List chartsList){ + Vector> chartsData = new Vector<>(); + if(chartsList != null) { + int i = 1; + for (Charts chartsPo : chartsList) { + Vector row = new Vector<>(); + row.add(String.valueOf(i++)); + row.add(String.valueOf(userDao.findById(chartsPo.getUserid()).getUsername())); + row.add(String.valueOf(chartsPo.getCount())); + row.add(String.valueOf(chartsPo.getScore())); + chartsData.add(row); + } + } + return chartsData; + } + public Vector> getAll(){ + List chartsList = chartsDao.findAll(); + return commonHandler(chartsList); + } + public Vector> sortByScoreUp(){ + List chartsList = chartsDao.sortByScoreUp(); + return commonHandler(chartsList); + } + public Vector> sortByScoreDown(){ + List chartsList = chartsDao.sortByScoreDown(); + return commonHandler(chartsList); + } + public boolean updateCharts(Charts charts){ + return chartsDao.updateCharts(charts); + } + public boolean deleteCharts(int userid){ + return chartsDao.deleteCharts(userid); + } + + public boolean insertCharts(Charts charts){ + return chartsDao.insertCharts(charts); + } + +} diff --git a/src/backend/service/impl/QuestionsService.java b/src/backend/service/QuestionsService.java similarity index 68% rename from src/backend/service/impl/QuestionsService.java rename to src/backend/service/QuestionsService.java index 09a35ef..4c206ff 100644 --- a/src/backend/service/impl/QuestionsService.java +++ b/src/backend/service/QuestionsService.java @@ -1,14 +1,16 @@ -package backend.service.impl; +package backend.service; -import backend.dao.impl.QuestionsDao; +import backend.dao.QuestionsDao; import backend.model.Questions; import backend.model.enums.GlobalData; +import java.util.HashSet; import java.util.List; import java.util.Vector; public class QuestionsService { private QuestionsDao questionsDao = new QuestionsDao(); + private static HashSet questionsSet = new HashSet<>(); private Vector> commonHandler(List questionsList){ //加工数据 把数据库查到的List转成Vector> Vector> questionsData = new Vector<>(); @@ -26,7 +28,7 @@ public class QuestionsService { return questionsData; } public Vector> getAll(){ - //从数据库中获取所有单词 + //从数据库中获取所有题目 List questionsList = questionsDao.getAll(); //把List转成表格所需的格式 return commonHandler(questionsList); @@ -34,7 +36,7 @@ public class QuestionsService { } public Vector> getByCondition(Integer frequency,String key){ - //从数据库中获取所有单词 + //从数据库中获取所有题目 List wordPoList = questionsDao.getByCondition(frequency,key); //把List转成表格所需的格式 return commonHandler(wordPoList); @@ -48,4 +50,20 @@ public class QuestionsService { public boolean update(Questions question){ return questionsDao.update(question); } + + public Questions getRandomQuestion() { + //使用红黑树实现的集合防止重复刷同一个题 + if(questionsSet.isEmpty()) { + Questions question = questionsDao.getRandomQuestion(); + questionsSet.add(question); + return question; + } + while(true) { + Questions question = questionsDao.getRandomQuestion(); + if(!questionsSet.contains(question)) { + questionsSet.add(question); + return question; + } + } + } } diff --git a/src/backend/service/TestRecordService.java b/src/backend/service/TestRecordService.java new file mode 100644 index 0000000..a8a833b --- /dev/null +++ b/src/backend/service/TestRecordService.java @@ -0,0 +1,78 @@ +package backend.service; +import backend.dao.QuestionsDao; +import backend.dao.TestRecordDao; +import backend.dao.UserDao; +import backend.model.Charts; +import backend.model.TestRecord; + +import java.util.*; + +public class TestRecordService { + private TestRecordDao testRecordDao = new TestRecordDao(); + private UserDao userDao = new UserDao(); + private QuestionsDao questionsDao = new QuestionsDao(); + + private Vector> commonHandler(List testRecordList){ + //加工数据 把数据库查到的List转成Vector> + Vector> testRecordData = new Vector<>(); + if(testRecordList != null) { + for (TestRecord testRecordPo : testRecordList) { + Vector row = new Vector<>(); + row.add(String.valueOf(testRecordPo.getId())); + row.add(String.valueOf(userDao.findById(testRecordPo.getUserId()).getUsername())); + row.add(String.valueOf(questionsDao.getById(testRecordPo.getQuestionId()).getName())); + row.add(String.valueOf(testRecordPo.getScore())); + row.add(testRecordPo.getAnswer()); + row.add(String.valueOf(testRecordPo.getTime())); + testRecordData.add(row); + } + } + return testRecordData; + } + //获取所有记录 用于管理员 + public Vector> getAll(){ + //从数据库中获取所有记录 + List testRecordList = testRecordDao.getAll(); + //把List转成表格所需的格式 + return commonHandler(testRecordList); + //返回给前端 + } + //获取指定用户的所有记录 用于用户和管理员 + public Vector> getByUserId(Integer userId){ + //从数据库中获取所有记录 + List testRecordList = testRecordDao.getByUserId(userId); + //把List转成表格所需的格式 + return commonHandler(testRecordList); + //返回给前端 + } + //获取指定题目的所有记录 用于管理员和 用户 + public Vector> getByQuestionId(Integer questionId){ + //从数据库中获取所有记录 + List testRecordList = testRecordDao.getByQuestionId(questionId); + //把List转成表格所需的格式 + return commonHandler(testRecordList); + //返回给前端 + } + //获取指定用户指定题目的所有记录 用于用户和管理员 + public Vector> getByUserIdAndQuestionId(Integer userId, Integer questionId){ + //从数据库中获取所有记录 + List testRecordList = testRecordDao.getByUserIdAndQuestionId(userId, questionId); + //把List转成表格所需的格式 + return commonHandler(testRecordList); + //返回给前端 + } + public boolean insert(TestRecord testRecord){ + //插入新的记录的同时,更新排行榜 + ChartsService chartsService = new ChartsService(); + Charts charts = new Charts(); + charts.setUserid(testRecord.getUserId()); + charts.setScore(testRecord.getScore()); + chartsService.updateCharts(charts); + return testRecordDao.insert(testRecord); + } + public boolean delete(Integer id){ + return testRecordDao.delete(id); + } + + +} diff --git a/src/backend/service/impl/AuthService.java b/src/backend/service/impl/AuthService.java deleted file mode 100644 index ac6e59d..0000000 --- a/src/backend/service/impl/AuthService.java +++ /dev/null @@ -1,43 +0,0 @@ -package backend.service.impl; -import backend.dao.impl.UserDao; -import backend.model.enums.LoginStatus; -import backend.model.User; -import backend.utils.impl.*; - -public class AuthService { - private UserDao userDao = new UserDao(); - public LoginStatus login(User user) { - User dbUser = userDao.findByUsername(user.getUsername()); - if(dbUser==null) - return LoginStatus.USER_NOT_FOUND; - if(dbUser.getUsername().equals(user.getUsername())&&dbUser.getPassword().equals(user.getPassword())) - return LoginStatus.SUCCESS; - else if (!dbUser.getUsername().equals(user.getUsername())) { - return LoginStatus.USER_NOT_FOUND; - } - return LoginStatus.PASSWORD_ERROR; - } - - public LoginStatus register(User user) { - User dbAccount = userDao.findByUsername(user.getUsername()); - if(dbAccount!=null) - return LoginStatus.REGISTER_FAILED; - //点击注册按钮后的事件 - int row = userDao.addUser(user); - if(row>0) - return LoginStatus.REGISTER_SUCCESS; - else - return LoginStatus.REGISTER_FAILED; - } - - - public boolean hasPermission(int userId, String requiredRole) { - UserDao userDao = new UserDao(); - User user = userDao.findById(userId); - if (user != null) { - return user.getRole().equals(requiredRole); - } - return false; - } -} - diff --git a/src/backend/service/interfaces/DataQueryService.java b/src/backend/service/interfaces/DataQueryService.java deleted file mode 100644 index 1447089..0000000 --- a/src/backend/service/interfaces/DataQueryService.java +++ /dev/null @@ -1,49 +0,0 @@ -package backend.service.interfaces; -import backend.model.DataItem; -import backend.model.QueryRecord; -import backend.model.User; -import java.util.*; - -/** - * 数据查询服务接口 - * 提供数据项的增删改查功能 - */ -public interface DataQueryService { - /** - * 查询所有数据项 - * @return 包含所有数据项的列表 - */ - List queryAll(); - - /** - * 根据关键字搜索数据项 - * @param keyword 搜索关键字 - * @return 匹配关键字的数据项列表 - */ - List search(String keyword); - - /** - * 添加数据项 - * @param item 要添加的数据项对象 - * @param userId 执行操作的用户ID - * @return 添加成功返回true,失败返回false - */ - boolean addDataItem(DataItem item, int userId); - - /** - * 更新数据项 - * @param item 要更新的数据项对象 - * @param userId 执行操作的用户ID - * @return 更新成功返回true,失败返回false - */ - boolean updateDataItem(DataItem item, int userId); - - /** - * 删除数据项 - * @param id 要删除的数据项ID - * @param userId 执行操作的用户ID - * @return 删除成功返回true,失败返回false - */ - boolean deleteDataItem(int id, int userId); -} - diff --git a/src/backend/service/interfaces/UserService.java b/src/backend/service/interfaces/UserService.java deleted file mode 100644 index f5c7efc..0000000 --- a/src/backend/service/interfaces/UserService.java +++ /dev/null @@ -1,33 +0,0 @@ -package backend.service.interfaces; -import backend.model.User; -import java.util.*; - -/** - * 用户服务接口 - * 定义了用户相关的业务操作方法 - */ -public interface UserService { - /** - * 根据用户ID获取用户信息 - * @param id 用户ID - * @return 用户对象,如果未找到则返回null - */ - User getUserInfo(int id); - - /** - * 列出所有用户信息 - * @param requesterId 请求者用户ID,用于权限验证 - * @return 用户列表 - */ - List listAllUsers(int requesterId); - - /** - * 更新用户角色权限 - * @param targetId 目标用户ID - * @param newRole 新的角色权限 - * @param adminId 管理员用户ID - * @return 操作是否成功 - */ - boolean updateUserRole(int targetId, String newRole, int adminId);//用户权限 -} - diff --git a/src/backend/utils/impl/CaptchaUtils.java b/src/backend/utils/CaptchaUtils.java similarity index 92% rename from src/backend/utils/impl/CaptchaUtils.java rename to src/backend/utils/CaptchaUtils.java index ec00dd6..2e67be2 100644 --- a/src/backend/utils/impl/CaptchaUtils.java +++ b/src/backend/utils/CaptchaUtils.java @@ -1,8 +1,8 @@ -package backend.utils.impl; +package backend.utils; import java.util.Random; -public class CaptchaUtils implements backend.utils.interfaces.CaptchaUtils{ +public class CaptchaUtils{ /** * 字符集常量,包含大小写字母和数字 */ diff --git a/src/backend/utils/impl/PasswordUtils.java b/src/backend/utils/PasswordUtils.java similarity index 99% rename from src/backend/utils/impl/PasswordUtils.java rename to src/backend/utils/PasswordUtils.java index 3f8bc12..c016566 100644 --- a/src/backend/utils/impl/PasswordUtils.java +++ b/src/backend/utils/PasswordUtils.java @@ -1,4 +1,4 @@ -package backend.utils.impl; +package backend.utils; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; diff --git a/src/backend/utils/interfaces/CaptchaUtils.java b/src/backend/utils/interfaces/CaptchaUtils.java deleted file mode 100644 index abaae81..0000000 --- a/src/backend/utils/interfaces/CaptchaUtils.java +++ /dev/null @@ -1,41 +0,0 @@ -package backend.utils.interfaces; - -import java.util.Random; - -/** - * 验证码工具类接口 - * 提供验证码的生成和验证功能 - */ -public interface CaptchaUtils { - /** - * 字符集常量,包含大小写字母和数字 - */ - static final String CHAR_SET="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - - /** - * 验证码长度常量,默认为4位 - */ - static final int CAPTCHA_LENGTH=4; - - /** - * 私有构造函数,防止实例化 - */ - //private CaptchaUtils(); - - /** - * 生成随机验证码 - * - * @return 生成的验证码字符串 - */ - //static String generateCaptcha(); - - /** - * 验证用户输入的验证码是否正确 - * - * @param inputCaptcha 用户输入的验证码 - * @param systemCaptcha 系统生成的验证码 - * @return 验证结果,正确返回true,错误返回false - */ - //static boolean verifyCaptcha(String inputCaptcha,String systemCaptcha); -} - diff --git a/src/backend/utils/interfaces/PasswordUtil.java b/src/backend/utils/interfaces/PasswordUtil.java deleted file mode 100644 index 5f003df..0000000 --- a/src/backend/utils/interfaces/PasswordUtil.java +++ /dev/null @@ -1,24 +0,0 @@ -package backend.utils.interfaces; - -/** - * 密码工具接口,提供密码加密和验证功能 - */ -public interface PasswordUtil { - /** - * 对明文密码进行加密处理 - * - * @param plainText 需要加密的明文密码字符串 - * @return 加密后的密码字符串 - */ - //static String encrypt(String plainText); - - /** - * 验证明文密码与已加密密码是否匹配 - * - * @param plainText 明文密码字符串 - * @param hashed 已加密的密码字符串 - * @return 如果匹配返回true,否则返回false - */ - //static boolean verify(String plainText, String hashed); -} - diff --git a/src/backend/utils/interfaces/RoleUtil.java b/src/backend/utils/interfaces/RoleUtil.java deleted file mode 100644 index d24f9af..0000000 --- a/src/backend/utils/interfaces/RoleUtil.java +++ /dev/null @@ -1,21 +0,0 @@ -package backend.utils.interfaces; - -/** - * 角色工具类接口,提供角色判断功能 - */ -public interface RoleUtil { - /** - * 判断给定的角色是否为管理员角色 - * @param role 待判断的角色字符串 - * @return 如果是管理员角色返回true,否则返回false - */ - //static boolean isAdmin(String role); - - /** - * 判断给定的角色是否为普通用户角色 - * @param role 待判断的角色字符串 - * @return 如果是普通用户角色返回true,否则返回false - */ - //static boolean isUser(String role); -} - diff --git a/src/view/EditQuestionDialog.java b/src/view/EditQuestionDialog.java index c6bc439..23e5e9f 100644 --- a/src/view/EditQuestionDialog.java +++ b/src/view/EditQuestionDialog.java @@ -1,7 +1,7 @@ package view; import backend.model.Questions; -import backend.service.impl.QuestionsService; +import backend.service.QuestionsService; import javax.swing.*; import java.awt.*; @@ -17,6 +17,12 @@ public class EditQuestionDialog extends JDialog{ private Questions question; private QuestionsService questionsService = new QuestionsService(); + // 颜色常量定义 + private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色 + private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景 + private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色 + private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景 + public EditQuestionDialog(int type, Questions question) { this.type = type; this.question = question; @@ -58,16 +64,30 @@ public class EditQuestionDialog extends JDialog{ dispose(); }); } + private void initView(){ - setSize(400,300); + setSize(400, 350); setLocationRelativeTo(null);//居中 - add(initPanel()); + setLayout(new BorderLayout()); + + // 创建顶部标题面板 + JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + titlePanel.setBackground(PRIMARY_COLOR); + JLabel titleLabel = new JLabel(type == 0 ? "添加题目" : "编辑题目"); + titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16)); + titleLabel.setForeground(Color.WHITE); + titlePanel.add(titleLabel); + add(titlePanel, BorderLayout.NORTH); + + // 添加主内容面板 + add(initPanel(), BorderLayout.CENTER); + setDefaultCloseOperation(DISPOSE_ON_CLOSE); setModal(true);//设置模态 if(type==0) - setTitle("添加问题"); + setTitle("添加题目"); else{ - setTitle("修改问题"); + setTitle("编辑题目"); nameTextField.setText(question.getName()); descriptionTextField.setText(question.getDescription()); answerTextField.setText(question.getAnswer()); @@ -79,31 +99,102 @@ public class EditQuestionDialog extends JDialog{ //显示界面 setVisible(true); } + private JPanel initPanel(){ - JPanel mainPanel = new JPanel(); - mainPanel.setLayout(new GridLayout(5,2)); - //第一行 单词 - mainPanel.add(new JLabel("问题")); + JPanel mainPanel = new JPanel(new GridBagLayout()); + mainPanel.setBackground(BACKGROUND_COLOR); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.insets = new Insets(10, 10, 10, 10); + + // 第一行 - 问题 + gbc.gridx = 0; gbc.gridy = 0; + gbc.anchor = GridBagConstraints.WEST; + mainPanel.add(new JLabel("问题:"), gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; nameTextField = new JTextField(); - mainPanel.add(nameTextField); - //第二行 定义 - mainPanel.add(new JLabel("描述")); + nameTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + nameTextField.setPreferredSize(new Dimension(200, 25)); + mainPanel.add(nameTextField, gbc); + + // 第二行 - 描述 + gbc.gridx = 0; gbc.gridy = 1; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + mainPanel.add(new JLabel("描述:"), gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; descriptionTextField = new JTextField(); - mainPanel.add(descriptionTextField); - //第三行 例句 - mainPanel.add(new JLabel("答案")); + descriptionTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + descriptionTextField.setPreferredSize(new Dimension(200, 25)); + mainPanel.add(descriptionTextField, gbc); + + // 第三行 - 答案 + gbc.gridx = 0; gbc.gridy = 2; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + mainPanel.add(new JLabel("答案:"), gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; answerTextField = new JTextField(); - mainPanel.add(answerTextField); - //第四行 频率 - mainPanel.add(new JLabel("频率")); + answerTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + answerTextField.setPreferredSize(new Dimension(200, 25)); + mainPanel.add(answerTextField, gbc); + + // 第四行 - 频率 + gbc.gridx = 0; gbc.gridy = 3; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + mainPanel.add(new JLabel("频率:"), gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; frequencyCombobox = new JComboBox<>(new String[]{"未指定","低频","中频","高频"}); - mainPanel.add(frequencyCombobox); - //第五行 按钮 + frequencyCombobox.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + frequencyCombobox.setPreferredSize(new Dimension(200, 25)); + mainPanel.add(frequencyCombobox, gbc); + + // 第五行 - 按钮 + gbc.gridx = 0; gbc.gridy = 4; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + gbc.anchor = GridBagConstraints.CENTER; + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 0)); + buttonPanel.setBackground(BACKGROUND_COLOR); + saveButton = new JButton("保存"); cancelButton = new JButton("取消"); - mainPanel.add(saveButton); - mainPanel.add(cancelButton); + + // 设置按钮样式 + setButtonStyle(saveButton); + setButtonStyle(cancelButton); + + buttonPanel.add(saveButton); + buttonPanel.add(cancelButton); + + mainPanel.add(buttonPanel, gbc); + + // 添加边距 + mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); + return mainPanel; } + // 设置按钮样式 + private void setButtonStyle(JButton button) { + button.setFont(new Font("微软雅黑", Font.BOLD, 14)); + button.setPreferredSize(new Dimension(80, 30)); + button.setBackground(PRIMARY_COLOR); + button.setForeground(Color.WHITE); + button.setFocusPainted(false); + button.setBorder(BorderFactory.createRaisedBevelBorder()); + } + } diff --git a/src/view/EditUserDialog.java b/src/view/EditUserDialog.java new file mode 100644 index 0000000..7f1d387 --- /dev/null +++ b/src/view/EditUserDialog.java @@ -0,0 +1,192 @@ +package view; + +import javax.swing.*; + +import backend.model.User; +import backend.service.AuthService; + +import java.awt.*; + +public class EditUserDialog extends JDialog { + private JTextField nameTextField; + private JTextField emailTextField; + private JComboBox roleCombobox; + private JButton saveButton; + private JButton cancelButton; + private int type; + private User user; + private AuthService userService = new AuthService(); + + // 颜色常量定义 + private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色 + private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景 + private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色 + private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景 + + public EditUserDialog(int type, User user) { + this.type = type; + this.user = user; + initView(); + } + + public void initListener(){ + saveButton.addActionListener(e->{ + String name = nameTextField.getText().trim(); + String email = emailTextField.getText().trim(); + if(name.equals("")|| email.equals("")) { + JOptionPane.showMessageDialog(this, "请填写完整!"); + return; + } + User userPo = new User(); + userPo.setUsername(name); + userPo.setEmail(email); + + + Integer index= roleCombobox.getSelectedIndex(); + userPo.setRole(index==0 ? "user":"admin"); + String message; + boolean res; + if(type==0) { + userPo.setPassword("123456"); + userPo.setCreatedAt(); + res = userService.addUser(userPo); + message = "添加"; + } + else{ + userPo.setCreatedAt(user.getCreatedAt()); + userPo.setPassword(user.getPassword()); + userPo.setId(user.getId()); + res = userService.updateUser(userPo); + message = "修改"; + } + if(res) + dispose(); + else + JOptionPane.showMessageDialog(this, message+"失败"); + }); + cancelButton.addActionListener(e->{ + dispose(); + }); + } + + private void initView(){ + setSize(400, 300); + setLocationRelativeTo(null);//居中 + setLayout(new BorderLayout()); + + // 创建顶部标题面板 + JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + titlePanel.setBackground(PRIMARY_COLOR); + JLabel titleLabel = new JLabel(type == 0 ? "添加用户" : "编辑用户"); + titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16)); + titleLabel.setForeground(Color.WHITE); + titlePanel.add(titleLabel); + add(titlePanel, BorderLayout.NORTH); + + // 添加主内容面板 + add(initPanel(), BorderLayout.CENTER); + + setDefaultCloseOperation(DISPOSE_ON_CLOSE); + setModal(true);//设置模态 + if(type==0) + setTitle("添加用户"); + else{ + setTitle("编辑用户"); + nameTextField.setText(user.getUsername()); + emailTextField.setText(user.getEmail()); + roleCombobox.setSelectedIndex(user.getRole().equals("admin")? 1:0); + } + //细节:要先初始化监听器,再初始化界面 + //初始化监听器 + initListener(); + //显示界面 + setVisible(true); + } + + private JPanel initPanel(){ + JPanel mainPanel = new JPanel(new GridBagLayout()); + mainPanel.setBackground(BACKGROUND_COLOR); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.insets = new Insets(10, 10, 10, 10); + + // 第一行 - 用户名 + gbc.gridx = 0; gbc.gridy = 0; + gbc.anchor = GridBagConstraints.WEST; + mainPanel.add(new JLabel("用户名:"), gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + nameTextField = new JTextField(); + nameTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + nameTextField.setPreferredSize(new Dimension(200, 25)); + mainPanel.add(nameTextField, gbc); + + // 第二行 - 邮箱 + gbc.gridx = 0; gbc.gridy = 1; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + mainPanel.add(new JLabel("邮箱:"), gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + emailTextField = new JTextField(); + emailTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + emailTextField.setPreferredSize(new Dimension(200, 25)); + mainPanel.add(emailTextField, gbc); + + // 第三行 - 权限 + gbc.gridx = 0; gbc.gridy = 2; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + mainPanel.add(new JLabel("权限:"), gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + roleCombobox = new JComboBox<>(new String[]{"user","admin"}); + roleCombobox.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + roleCombobox.setPreferredSize(new Dimension(200, 25)); + mainPanel.add(roleCombobox, gbc); + + // 第四行 - 按钮 + gbc.gridx = 0; gbc.gridy = 3; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + gbc.anchor = GridBagConstraints.CENTER; + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 0)); + buttonPanel.setBackground(BACKGROUND_COLOR); + + saveButton = new JButton("保存"); + cancelButton = new JButton("取消"); + + // 设置按钮样式 + setButtonStyle(saveButton); + setButtonStyle(cancelButton); + + buttonPanel.add(saveButton); + buttonPanel.add(cancelButton); + + mainPanel.add(buttonPanel, gbc); + + // 添加边距 + mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); + + return mainPanel; + } + + // 设置按钮样式 + private void setButtonStyle(JButton button) { + button.setFont(new Font("微软雅黑", Font.BOLD, 14)); + button.setPreferredSize(new Dimension(80, 30)); + button.setBackground(PRIMARY_COLOR); + button.setForeground(Color.WHITE); + button.setFocusPainted(false); + button.setBorder(BorderFactory.createRaisedBevelBorder()); + } + +// public static void main(String[] args) { +// new EditUserDialog(0,null); +// } +} diff --git a/src/view/ExamPanel.java b/src/view/ExamPanel.java index 3bea4a4..39ec771 100644 --- a/src/view/ExamPanel.java +++ b/src/view/ExamPanel.java @@ -1,11 +1,639 @@ package view; +import backend.dao.QuestionsDao; +import backend.dao.UserDao; +import backend.model.Charts; +import backend.model.Questions; +import backend.model.TestRecord; +import backend.model.enums.ScoreKey; +import backend.service.ChartsService; +import backend.service.QuestionsService; +import backend.service.TestRecordService; + import javax.swing.*; -public class ExamPanel extends JPanel{ +import javax.swing.table.DefaultTableModel; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.sql.Date; +import java.util.Vector; + +public class ExamPanel extends JPanel { + private QuestionsService questionsService = new QuestionsService(); + private Questions currentQuestion; + private JButton startButton; + private JButton submitButton; + private JButton nextButton; + private JButton exitButton; + private JLabel questionLabel; + private JLabel descriptionLabel; + private JLabel progressLabel; + private JTextField answerTextField; + private JMenuBar menuBar; + private String role = MainFrame.role; + private int userId = MainFrame.userId; + + // 颜色常量定义 + private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色 + private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景 + private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色 + private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景 + public ExamPanel() { + initializeComponents(); initView(); + initListener(); } - private void initView(){ - add(new JLabel("考试管理")); + + // 初始化所有UI组件 + private void initializeComponents() { + // 题目标题标签 + questionLabel = new JLabel("点击开始测试获取题目"); + questionLabel.setFont(new Font("微软雅黑", Font.BOLD, 18)); + questionLabel.setForeground(new Color(50, 50, 50)); + questionLabel.setHorizontalAlignment(JLabel.CENTER); + questionLabel.setVerticalAlignment(JLabel.TOP); + + // 题目描述标签 + descriptionLabel = new JLabel("描述将在这里显示"); + descriptionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14)); + descriptionLabel.setForeground(new Color(100, 100, 100)); + descriptionLabel.setHorizontalAlignment(JLabel.CENTER); + descriptionLabel.setVerticalAlignment(JLabel.TOP); + + // 进度标签 + progressLabel = new JLabel("题目进度: 0/0"); + progressLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + progressLabel.setForeground(new Color(120, 120, 120)); + progressLabel.setHorizontalAlignment(JLabel.RIGHT); + + // 答案输入框 + answerTextField = new JTextField(20); + answerTextField.setFont(new Font("微软雅黑", Font.PLAIN, 14)); + answerTextField.setHorizontalAlignment(JLabel.CENTER); + answerTextField.setPreferredSize(new Dimension(250, 35)); + + // 初始化按钮 + startButton = new JButton("开始测试"); + submitButton = new JButton("提交"); + nextButton = new JButton("下一题"); + exitButton = new JButton("退出"); + + // 设置按钮样式 + setButtonStyle(startButton); + setButtonStyle(submitButton); + setButtonStyle(nextButton); + setButtonStyle(exitButton); + + // 隐藏非初始按钮 + submitButton.setVisible(false); + nextButton.setVisible(false); + exitButton.setVisible(false); } + + // 设置按钮样式 + private void setButtonStyle(JButton button) { + button.setFont(new Font("微软雅黑", Font.BOLD, 14)); + button.setPreferredSize(new Dimension(100, 35)); + button.setBackground(PRIMARY_COLOR); + button.setForeground(Color.WHITE); + button.setFocusPainted(false); + button.setBorder(BorderFactory.createRaisedBevelBorder()); + } + + private void initView() { + setLayout(new BorderLayout()); + setBackground(BACKGROUND_COLOR); + + // 创建顶部工具栏 + JPanel topPanel = new JPanel(new BorderLayout()); + topPanel.setBackground(PRIMARY_COLOR); + topPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); + + JLabel titleLabel = new JLabel("测试管理"); + titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16)); + titleLabel.setForeground(Color.WHITE); + topPanel.add(titleLabel, BorderLayout.WEST); + topPanel.add(progressLabel, BorderLayout.EAST); + topPanel.add(initMenuBar(), BorderLayout.CENTER); + + add(topPanel, BorderLayout.NORTH); + + // 创建中央内容面板 + JPanel centerPanel = new JPanel(); + centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS)); + centerPanel.setBackground(BACKGROUND_COLOR); + centerPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30)); + + // 添加初始显示内容 + centerPanel.add(Box.createVerticalGlue()); + + // 题目展示区域 + JPanel questionPanel = new JPanel(new BorderLayout()); + questionPanel.setBackground(Color.WHITE); + questionPanel.setBorder(BorderFactory.createCompoundBorder( + BorderFactory.createLineBorder(BORDER_COLOR, 1), + BorderFactory.createEmptyBorder(20, 20, 20, 20) + )); + questionPanel.setMaximumSize(new Dimension(600, 300)); + questionPanel.setAlignmentX(Component.CENTER_ALIGNMENT); + + questionPanel.add(questionLabel, BorderLayout.CENTER); + questionPanel.add(descriptionLabel, BorderLayout.SOUTH); + + centerPanel.add(questionPanel); + centerPanel.add(Box.createVerticalStrut(20)); + + // 答案输入区域 + JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5)); + inputPanel.setBackground(BACKGROUND_COLOR); + inputPanel.add(new JLabel("请输入答案: ")); + inputPanel.add(answerTextField); + centerPanel.add(inputPanel); + centerPanel.add(Box.createVerticalStrut(15)); + + // 按钮区域 + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 5)); + buttonPanel.setBackground(BACKGROUND_COLOR); + buttonPanel.add(startButton); + buttonPanel.add(submitButton); + buttonPanel.add(nextButton); + buttonPanel.add(exitButton); + centerPanel.add(buttonPanel); + + centerPanel.add(Box.createVerticalGlue()); + add(centerPanel, BorderLayout.CENTER); + + // 更新按钮可见性 + updateButtonVisibility(); + } + + private void updateButtonVisibility() { + startButton.setVisible(true); + submitButton.setVisible(false); + nextButton.setVisible(false); + exitButton.setVisible(false); + } + + private void showQuestion() { + // 更新按钮可见性 + startButton.setVisible(false); + submitButton.setVisible(true); + nextButton.setVisible(false); + exitButton.setVisible(false); + + // 更新进度显示 + progressLabel.setText("题目进度: 1/1"); + + // 重新验证和重绘界面 + revalidate(); + repaint(); + } + + private void showNextQuestionOption() { + // 更新按钮可见性 + startButton.setVisible(false); + submitButton.setVisible(false); + nextButton.setVisible(true); + exitButton.setVisible(true); + + // 重新验证和重绘界面 + revalidate(); + repaint(); + } + + private void initListener() { + startButton.addActionListener(e -> { + // 获取随机题目并显示 + currentQuestion = questionsService.getRandomQuestion(); + if (currentQuestion != null) { + //在排行榜中创建角色(若没有) + ChartsService chartsService = new ChartsService(); + Charts charts = new Charts(); + charts.setUserid(userId); + chartsService.insertCharts(charts); + updateQuestionDisplay(); + showQuestion(); + } else { + JOptionPane.showMessageDialog(this, + "没有可用的题目", "错误", JOptionPane.ERROR_MESSAGE); + } + }); + + submitButton.addActionListener(e -> handleAnswerSubmission()); + + // 为 nextButton 和 exitButton 添加监听器 + if (nextButton != null) { + nextButton.addActionListener(e -> { + currentQuestion = questionsService.getRandomQuestion(); + if (currentQuestion != null) { + updateQuestionDisplay(); + showQuestion(); + } else { + JOptionPane.showMessageDialog(this, + "没有更多题目", "提示", JOptionPane.INFORMATION_MESSAGE); + } + }); + } + + if (exitButton != null) { + exitButton.addActionListener(e -> { + int choice = JOptionPane.showConfirmDialog( + this, + "确定要退出测试吗?", + "确认退出", + JOptionPane.YES_NO_OPTION + ); + if (choice == JOptionPane.YES_OPTION) { + resetToInitialState(); + } + }); + } + // 为菜单项添加监听器 + JMenu testMenu = (JMenu) menuBar.getMenu(0); + JMenuItem testContentItem = testMenu.getItem(0); + testContentItem.addActionListener(e -> { + resetToInitialState(); + }); + + JMenu recordMenu = (JMenu) menuBar.getMenu(1); + JMenuItem recordItem = recordMenu.getItem(0); + recordItem.addActionListener(e -> { + initRecordView(); + }); + + JMenu chartMenu = (JMenu) menuBar.getMenu(2); + JMenuItem chartItem = chartMenu.getItem(0); + chartItem.addActionListener(e -> { + // 这里可以添加排行榜页面的切换逻辑 + initRankView(); + }); + + } + + private void updateQuestionDisplay() { + if (currentQuestion != null) { + questionLabel.setText(currentQuestion.getName()); + descriptionLabel.setText(currentQuestion.getDescription()); + answerTextField.setText(""); + } + } + + private void handleAnswerSubmission() { + int user=userId, questionId= currentQuestion.getId(), score=0; + if (currentQuestion == null) { + JOptionPane.showMessageDialog(this, + "请先开始测试", "提示", JOptionPane.WARNING_MESSAGE); + return; + } + + String userAnswer = answerTextField.getText().trim(); + if (userAnswer.isEmpty()) { + JOptionPane.showMessageDialog(this, + "请输入答案", "提示", JOptionPane.WARNING_MESSAGE); + return; + } + + if (userAnswer.equalsIgnoreCase(currentQuestion.getAnswer())) { + // 答案正确时高亮输入框 + answerTextField.setBackground(HIGHLIGHT_COLOR); + JOptionPane.showMessageDialog(this, + "答案正确!", "正确", JOptionPane.INFORMATION_MESSAGE); + answerTextField.setBackground(Color.WHITE); + score= ScoreKey.getScoreByKey(currentQuestion.getFrequency()); + showNextQuestionOption(); + } else { + // 答案错误时改变输入框颜色 + answerTextField.setBackground(new Color(255, 220, 220)); // 淡红色 + int choice = JOptionPane.showConfirmDialog( + this, + "答案错误,正确答案是:" + currentQuestion.getAnswer() + "\n是否重新尝试?", + "错误", + JOptionPane.YES_NO_OPTION + ); + + if (choice == JOptionPane.NO_OPTION) { + answerTextField.setBackground(Color.WHITE); + showNextQuestionOption(); + } else { + // 清空输入框,允许重新尝试 + answerTextField.setText(""); + answerTextField.setBackground(Color.WHITE); + } + } + // 保存测试记录 + TestRecord testRecord = new TestRecord(); + testRecord.setUserId(user); + testRecord.setQuestionId(questionId); + testRecord.setScore(score); + testRecord.setAnswer(userAnswer); + testRecord.setTime(new Date(System.currentTimeMillis())); + TestRecordService testRecordService = new TestRecordService(); + testRecordService.insert(testRecord); + } + + private void resetToInitialState() { + // 重置所有组件状态 + questionLabel.setText("点击开始测试获取题目"); + descriptionLabel.setText("描述将在这里显示"); + answerTextField.setText(""); + answerTextField.setBackground(Color.WHITE); + + // 重置按钮状态 + updateButtonVisibility(); + + // 重置进度 + progressLabel.setText("题目进度: 0/0"); + + revalidate(); + repaint(); + } + + private JMenuBar initMenuBar() { + menuBar = new JMenuBar(); + menuBar.setBackground(PRIMARY_COLOR); + + JMenu testMenu = new JMenu("测试内容"); + testMenu.setForeground(Color.WHITE); + testMenu.add(new JMenuItem("开始测试")); + menuBar.add(testMenu); + + JMenu recordMenu = new JMenu("测试记录"); + recordMenu.setForeground(Color.WHITE); + if(role.equals("user")) + recordMenu.add(new JMenuItem("我的记录")); + else + recordMenu.add(new JMenuItem("查看所有记录")); + menuBar.add(recordMenu); + + JMenu chartMenu = new JMenu("排行榜"); + chartMenu.setForeground(Color.WHITE); + chartMenu.add(new JMenuItem("查看排行榜")); + menuBar.add(chartMenu); + + return menuBar; + } + + private void initRecordView() { + // 清空当前面板 + removeAll(); + setLayout(new BorderLayout()); + + // 创建顶部查询面板 + JPanel queryPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + queryPanel.setBackground(PRIMARY_COLOR); + queryPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); + + // 添加查询输入框和按钮 + JLabel userLabel = new JLabel("用户:"); + userLabel.setForeground(Color.WHITE); + JTextField userIdField = new JTextField(8); + userIdField.setPreferredSize(new Dimension(80, 25)); + + JLabel questionLabel = new JLabel("题目:"); + questionLabel.setForeground(Color.WHITE); + JTextField questionIdField = new JTextField(8); + questionIdField.setPreferredSize(new Dimension(80, 25)); + + JButton searchButton = new JButton("查询"); + setButtonStyle(searchButton); + + JButton resetButton = new JButton("重置"); + setButtonStyle(resetButton); + + queryPanel.add(userLabel); + queryPanel.add(userIdField); + queryPanel.add(questionLabel); + queryPanel.add(questionIdField); + queryPanel.add(searchButton); + queryPanel.add(resetButton); + + // 创建表格展示面板 + JPanel tablePanel = new JPanel(new BorderLayout()); + tablePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + // 初始化表格 + String[] columnNames = {"记录ID", "用户名", "题目", "得分", "答案", "时间"}; + DefaultTableModel tableModel = new DefaultTableModel(columnNames, 0) { + @Override + public boolean isCellEditable(int row, int column) { + return false; // 表格不可编辑 + } + }; + + JTable recordTable = new JTable(tableModel); + recordTable.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + recordTable.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 13)); + recordTable.getTableHeader().setBackground(PRIMARY_COLOR); + recordTable.getTableHeader().setForeground(Color.WHITE); + recordTable.setSelectionBackground(new Color(176, 224, 230)); + recordTable.setRowHeight(25); + + // 设置列宽 + recordTable.getColumnModel().getColumn(0).setPreferredWidth(60); // 记录ID + recordTable.getColumnModel().getColumn(1).setPreferredWidth(100); // 用户名 + recordTable.getColumnModel().getColumn(2).setPreferredWidth(200); // 题目 + recordTable.getColumnModel().getColumn(3).setPreferredWidth(60); // 得分 + recordTable.getColumnModel().getColumn(4).setPreferredWidth(150); // 答案 + recordTable.getColumnModel().getColumn(5).setPreferredWidth(120); // 时间 + + JScrollPane scrollPane = new JScrollPane(recordTable); + scrollPane.setPreferredSize(new Dimension(700, 400)); + + tablePanel.add(scrollPane, BorderLayout.CENTER); + + // 添加到主面板 + add(queryPanel, BorderLayout.NORTH); + add(tablePanel, BorderLayout.CENTER); + + // 查询按钮事件处理 + searchButton.addActionListener(e -> { + UserDao userDao = new UserDao(); + QuestionsDao questionsDao = new QuestionsDao(); + String userIdText = userIdField.getText().trim(); + String questionIdText = questionIdField.getText().trim(); + + TestRecordService testRecordService = new TestRecordService(); + Vector> records; + + try { + if (!userIdText.isEmpty() && !questionIdText.isEmpty()) { + userIdText = String.valueOf(userDao.findByUsername(userIdField.getText().trim()).getId()); + questionIdText = String.valueOf(questionsDao.getByName(questionIdField.getText().trim()).getId()); + // 同时查询用户ID和题目ID + Integer userId = Integer.parseInt(userIdText); + Integer questionId = Integer.parseInt(questionIdText); + records = testRecordService.getByUserIdAndQuestionId(userId, questionId); + } else if (!userIdText.isEmpty()) { + // 只查询用户ID + userIdText = String.valueOf(userDao.findByUsername(userIdField.getText().trim()).getId()); + Integer userId = Integer.parseInt(userIdText); + records = testRecordService.getByUserId(userId); + } else if (!questionIdText.isEmpty()) { + // 只查询题目ID + questionIdText = String.valueOf(questionsDao.getByName(questionIdField.getText().trim()).getId()); + Integer questionId = Integer.parseInt(questionIdText); + records = testRecordService.getByQuestionId(questionId); + } else { + // 查询所有记录(根据角色权限) + if (role.equals("user")) { + records = testRecordService.getByUserId(this.userId); + } else { + records = testRecordService.getAll(); + } + } + + // 清空表格 + tableModel.setRowCount(0); + + // 添加数据到表格 + for (Vector record : records) { + tableModel.addRow(record); + } + + // 如果没有找到记录,显示提示 + if (records.isEmpty()) { + JOptionPane.showMessageDialog(this, "没有找到匹配的记录", "提示", JOptionPane.INFORMATION_MESSAGE); + } + + } catch (NumberFormatException ex) { + JOptionPane.showMessageDialog(this, "请输入有效的数字ID", "错误", JOptionPane.ERROR_MESSAGE); + } + }); + + // 重置按钮事件处理 + resetButton.addActionListener(e -> { + userIdField.setText(""); + questionIdField.setText(""); + + // 根据角色加载默认数据 + TestRecordService testRecordService = new TestRecordService(); + Vector> records; + + if (role.equals("user")) { + records = testRecordService.getByUserId(this.userId); + } else { + records = testRecordService.getAll(); + } + + // 清空表格 + tableModel.setRowCount(0); + + // 添加数据到表格 + for (Vector record : records) { + tableModel.addRow(record); + } + }); + + // 初始加载数据 + SwingUtilities.invokeLater(() -> { + TestRecordService testRecordService = new TestRecordService(); + Vector> records; + + if (role.equals("user")) { + records = testRecordService.getByUserId(this.userId); + } else { + records = testRecordService.getAll(); + } + + // 添加数据到表格 + for (Vector record : records) { + tableModel.addRow(record); + } + }); + + revalidate(); + repaint(); + } + + private void initRankView() { + // 清空当前面板 + removeAll(); + setLayout(new BorderLayout()); + + // 创建顶部控制面板 + JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.LEFT)); + controlPanel.setBackground(PRIMARY_COLOR); + controlPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); + + JButton sortByScoreUpButton = new JButton("按分数升序"); + JButton sortByScoreDownButton = new JButton("按分数降序"); + setButtonStyle(sortByScoreUpButton); + setButtonStyle(sortByScoreDownButton); + + controlPanel.add(sortByScoreUpButton); + controlPanel.add(sortByScoreDownButton); + + // 创建表格展示面板 + JPanel tablePanel = new JPanel(new BorderLayout()); + tablePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + // 初始化表格 + String[] columnNames = {"排名", "用户名", "答题次数", "总得分"}; + DefaultTableModel tableModel = new DefaultTableModel(columnNames, 0) { + @Override + public boolean isCellEditable(int row, int column) { + return false; // 表格不可编辑 + } + }; + + JTable rankTable = new JTable(tableModel); + rankTable.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + rankTable.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 13)); + rankTable.getTableHeader().setBackground(PRIMARY_COLOR); + rankTable.getTableHeader().setForeground(Color.WHITE); + rankTable.setSelectionBackground(new Color(176, 224, 230)); + rankTable.setRowHeight(25); + + // 设置列宽 + rankTable.getColumnModel().getColumn(0).setPreferredWidth(60); // 排名 + rankTable.getColumnModel().getColumn(1).setPreferredWidth(120); // 用户名 + rankTable.getColumnModel().getColumn(2).setPreferredWidth(100); // 答题次数 + rankTable.getColumnModel().getColumn(3).setPreferredWidth(100); // 总得分 + + JScrollPane scrollPane = new JScrollPane(rankTable); + scrollPane.setPreferredSize(new Dimension(600, 400)); + + tablePanel.add(scrollPane, BorderLayout.CENTER); + + // 添加到主面板 + add(controlPanel, BorderLayout.NORTH); + add(tablePanel, BorderLayout.CENTER); + + // 加载默认数据(升序) + loadRankData(tableModel, true); + + // 按分数升序按钮事件 + sortByScoreUpButton.addActionListener(e -> { + loadRankData(tableModel, true); + }); + + // 按分数降序按钮事件 + sortByScoreDownButton.addActionListener(e -> { + loadRankData(tableModel, false); + }); + + revalidate(); + repaint(); + } + + private void loadRankData(DefaultTableModel tableModel, boolean isAscending) { + ChartsService chartsService = new ChartsService(); + Vector> rankData; + + if (isAscending) { + rankData = chartsService.sortByScoreUp(); + } else { + rankData = chartsService.sortByScoreDown(); + } + + // 清空表格 + tableModel.setRowCount(0); + + // 添加数据到表格 + for (Vector rankItem : rankData) { + tableModel.addRow(rankItem); + } + } + + } diff --git a/src/view/LoginFrame.java b/src/view/LoginFrame.java index ead2761..5137c39 100644 --- a/src/view/LoginFrame.java +++ b/src/view/LoginFrame.java @@ -1,8 +1,9 @@ package view; +import backend.dao.UserDao; import backend.model.enums.LoginStatus; import backend.model.User; -import backend.service.impl.AuthService; -import backend.utils.impl.CaptchaUtils; +import backend.service.AuthService; +import backend.utils.CaptchaUtils; import javax.swing.*; import java.awt.*; @@ -18,11 +19,15 @@ public class LoginFrame extends JFrame{ private JButton loginButton;//登录按钮 private JButton registerButton;//注册按钮 private AuthService authService = new AuthService(); - private LoginStatus flag; + private UserDao userDao = new UserDao(); + protected static String loginRole; + protected static int userId; - public LoginStatus Flag(){ - return this.flag; - } + // 颜色常量定义 + private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色 + private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景 + private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色 + private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景 public LoginFrame() { //初始化界面 @@ -33,19 +38,22 @@ public class LoginFrame extends JFrame{ passwordField.setText("123456"); captchaTextField.setText(captchaLabel.getText()); } + private void initView(){ //1.设置标题 - setTitle("登录"); + setTitle("中医药知识测试系统 - 登录"); //2.设置点击关闭时的动作 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - //3.中间层容器 + //3.设置窗口背景色 + getContentPane().setBackground(BACKGROUND_COLOR); + //4.中间层容器 add(initPanel()); - //4.不允许窗口改变大小 + //5.不允许窗口改变大小 setResizable(false); - //5.自动调整窗口大小 居中显示 - pack();//自动调整窗口大小 - setLocationRelativeTo(null);//剧中 - //6.显示窗口 + //6.设置窗口大小 居中显示 + setSize(400, 350); + setLocationRelativeTo(null); + //7.显示窗口 setVisible(true); } @@ -76,6 +84,10 @@ public class LoginFrame extends JFrame{ account.setPassword(password); LoginStatus loginStatus = authService.login(account); if(loginStatus == LoginStatus.SUCCESS) { + //记录登陆角色的权限 + account=userDao.findByUsername(username); + loginRole = account.getRole(); + userId = account.getId(); //进入主界面 new MainFrame(); this.dispose(); @@ -102,23 +114,134 @@ public class LoginFrame extends JFrame{ private JPanel initPanel(){ - mainPanel = new JPanel(); - GridLayout gridLayout = new GridLayout(6,1,10,10); - mainPanel.setLayout(gridLayout); - //第1层 空白面板 占用 - mainPanel.add(new JPanel()); - //第2层 账号面板 - mainPanel.add(initAcountPanel()); - //第3层 密码面板 - mainPanel.add(initPasswordPanel()); - //第4层 验证码面板 - mainPanel.add(initCaptchaPanel()); - //第5层 按钮面板 - mainPanel.add(initButtonPanel()); - //第6层 空白面板 占用 + mainPanel = new JPanel(new BorderLayout()); + mainPanel.setBackground(BACKGROUND_COLOR); + + // 创建顶部标题面板 + JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + titlePanel.setBackground(PRIMARY_COLOR); + JLabel titleLabel = new JLabel("中医药知识测试系统"); + titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 18)); + titleLabel.setForeground(Color.WHITE); + titlePanel.add(titleLabel); + mainPanel.add(titlePanel, BorderLayout.NORTH); + + // 创建中央登录表单面板 + JPanel formPanel = new JPanel(new GridBagLayout()); + formPanel.setBackground(BACKGROUND_COLOR); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.insets = new Insets(10, 10, 10, 10); + + // 第1行 - 标题 + gbc.gridx = 0; gbc.gridy = 0; + gbc.gridwidth = 2; + gbc.anchor = GridBagConstraints.CENTER; + JLabel formTitleLabel = new JLabel("用户登录"); + formTitleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16)); + formTitleLabel.setForeground(PRIMARY_COLOR); + formPanel.add(formTitleLabel, gbc); + + // 第2行 - 用户名 + gbc.gridx = 0; gbc.gridy = 1; + gbc.gridwidth = 1; + gbc.anchor = GridBagConstraints.WEST; + JLabel usernameLabel = new JLabel("用户名:"); + usernameLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + formPanel.add(usernameLabel, gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + usernameTextField = new JTextField(15); + usernameTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + usernameTextField.setPreferredSize(new Dimension(200, 25)); + formPanel.add(usernameTextField, gbc); + + // 第3行 - 密码 + gbc.gridx = 0; gbc.gridy = 2; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + gbc.anchor = GridBagConstraints.WEST; + JLabel passwordLabel = new JLabel("密 码:"); + passwordLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + formPanel.add(passwordLabel, gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + passwordField = new JPasswordField(15); + passwordField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + passwordField.setPreferredSize(new Dimension(200, 25)); + formPanel.add(passwordField, gbc); + + // 第4行 - 验证码 + gbc.gridx = 0; gbc.gridy = 3; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + gbc.anchor = GridBagConstraints.WEST; + JLabel captchaLabel = new JLabel("验证码:"); + captchaLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + formPanel.add(captchaLabel, gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + JPanel captchaPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); + captchaPanel.setBackground(BACKGROUND_COLOR); + captchaTextField = new JTextField(8); + captchaTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + captchaTextField.setPreferredSize(new Dimension(80, 25)); + captchaPanel.add(captchaTextField); + + this.captchaLabel = new JLabel(CaptchaUtils.generateCaptcha()); + this.captchaLabel.setFont(new Font("微软雅黑", Font.BOLD, 16)); + this.captchaLabel.setBackground(Color.WHITE); + this.captchaLabel.setOpaque(true); + this.captchaLabel.setBorder(BorderFactory.createLineBorder(BORDER_COLOR)); + this.captchaLabel.setPreferredSize(new Dimension(80, 25)); + this.captchaLabel.setHorizontalAlignment(JLabel.CENTER); + captchaPanel.add(this.captchaLabel); + + formPanel.add(captchaPanel, gbc); + + // 第5行 - 按钮 + gbc.gridx = 0; gbc.gridy = 4; + gbc.gridwidth = 2; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + gbc.anchor = GridBagConstraints.CENTER; + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 0)); + buttonPanel.setBackground(BACKGROUND_COLOR); + + loginButton = new JButton("登录"); + registerButton = new JButton("注册"); + + // 设置按钮样式 + setButtonStyle(loginButton); + setButtonStyle(registerButton); + + buttonPanel.add(loginButton); + buttonPanel.add(registerButton); + + formPanel.add(buttonPanel, gbc); + + // 添加边距 + formPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); + mainPanel.add(formPanel, BorderLayout.CENTER); + return mainPanel; } + // 设置按钮样式 + private void setButtonStyle(JButton button) { + button.setFont(new Font("微软雅黑", Font.BOLD, 14)); + button.setPreferredSize(new Dimension(80, 30)); + button.setBackground(PRIMARY_COLOR); + button.setForeground(Color.WHITE); + button.setFocusPainted(false); + button.setBorder(BorderFactory.createRaisedBevelBorder()); + } + private JPanel initAcountPanel(){ JPanel panel = new JPanel(); panel.setLayout(new GridLayout(1,4,10,0)); @@ -199,7 +322,3 @@ public class LoginFrame extends JFrame{ }); } } - - - - diff --git a/src/view/MainFrame.java b/src/view/MainFrame.java index 49533f2..2797ac7 100644 --- a/src/view/MainFrame.java +++ b/src/view/MainFrame.java @@ -3,6 +3,7 @@ package view; import backend.model.Questions; import javax.swing.*; +import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -11,40 +12,60 @@ public class MainFrame extends JFrame{ private JMenuBar menuBar; private JMenu questionsMenu; private JMenu examMenu; + private JMenu userMenu; + protected static String role = LoginFrame.loginRole; + protected static int userId = LoginFrame.userId; + + // 颜色常量定义 + private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色 + private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景 + private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色 + private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景 public MainFrame(){ initView(); initListener(); } + private void initView(){ //1.设置标题 - setTitle("主界面"); + setTitle("中医药知识测试系统"); //2.设置点击关闭时的动作 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - //3.中间层容器 + //3.设置窗口背景色 + getContentPane().setBackground(BACKGROUND_COLOR); + //4.中间层容器 add(initPanel()); - //4.不允许窗口改变大小 + //5.不允许窗口改变大小 setResizable(false); - //5.自动调整窗口大小 居中显示 - setSize(600,600); - //pack();//自动调整窗口大小 + //6.设置窗口大小 居中显示 + setSize(800, 600); setLocationRelativeTo(null); - //6.注册监听器 - initListener(); //7.显示窗口 setVisible(true); } private void initListener(){ - questionsMenu.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - mainPanel.removeAll(); - mainPanel.add(new QuestionsPanel()); - mainPanel.revalidate(); - mainPanel.repaint(); - } - }); + if(role.equals("admin")) { + questionsMenu.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + mainPanel.removeAll(); + mainPanel.add(new QuestionsPanel()); + mainPanel.revalidate(); + mainPanel.repaint(); + } + }); + userMenu.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + mainPanel.removeAll(); + mainPanel.add(new UserPanel()); + mainPanel.revalidate(); + mainPanel.repaint(); + } + }); + } examMenu.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { @@ -55,23 +76,46 @@ public class MainFrame extends JFrame{ } }); } + private JPanel initPanel(){ - mainPanel = new JPanel(); - mainPanel.setLayout(new BoxLayout(mainPanel,BoxLayout.Y_AXIS)); + mainPanel = new JPanel(new BorderLayout()); + mainPanel.setBackground(BACKGROUND_COLOR); setJMenuBar(initMenuBar()); - //默认为单词库界面 - mainPanel.add(new QuestionsPanel()); - mainPanel.setVisible(true); + if(MainFrame.role.equals("admin")) { + //默认为问题库界面 + mainPanel.add(new QuestionsPanel(), BorderLayout.CENTER); + } + else{ + //默认为考试界面 + mainPanel.add(new ExamPanel(), BorderLayout.CENTER); + } return mainPanel; } + private JMenuBar initMenuBar(){ menuBar = new JMenuBar(); - questionsMenu = new JMenu("问题库管理"); - examMenu = new JMenu("考试管理"); - menuBar.add(questionsMenu); + menuBar.setBackground(PRIMARY_COLOR); + + if(role.equals("admin")) { + questionsMenu = new JMenu("问题库管理"); + questionsMenu.setForeground(Color.WHITE); + questionsMenu.setFont(new Font("微软雅黑", Font.BOLD, 14)); + menuBar.add(questionsMenu); + + userMenu = new JMenu("用户管理"); + userMenu.setForeground(Color.WHITE); + userMenu.setFont(new Font("微软雅黑", Font.BOLD, 14)); + menuBar.add(userMenu); + } + + examMenu = new JMenu("测试管理"); + examMenu.setForeground(Color.WHITE); + examMenu.setFont(new Font("微软雅黑", Font.BOLD, 14)); menuBar.add(examMenu); + return menuBar; } + public static void main(String[] args) { new MainFrame().initView(); } diff --git a/src/view/QuestionsPanel.java b/src/view/QuestionsPanel.java index 03289f6..e7284c3 100644 --- a/src/view/QuestionsPanel.java +++ b/src/view/QuestionsPanel.java @@ -7,7 +7,7 @@ import java.awt.event.MouseEvent; import java.util.Vector; import backend.model.Questions; -import backend.service.impl.QuestionsService; +import backend.service.QuestionsService; import backend.model.enums.GlobalData; public class QuestionsPanel extends JPanel{ @@ -25,6 +25,13 @@ public class QuestionsPanel extends JPanel{ private JComboBox frequencyComboBox; private JTextField keyTextField; private JButton queryButton; + + // 颜色常量定义 + private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色 + private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景 + private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色 + private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景 + static { columNames.add("ID"); columNames.add("题目"); @@ -32,6 +39,7 @@ public class QuestionsPanel extends JPanel{ columNames.add("答案"); columNames.add("频率"); } + public void initListener(){ queryButton.addActionListener(e->{ Integer frequency = frequencyComboBox.getSelectedIndex()==0?null:frequencyComboBox.getSelectedIndex(); @@ -44,6 +52,8 @@ public class QuestionsPanel extends JPanel{ refreshData(); }); deleteButton.addActionListener(e->{ + if(MainFrame.role.equals("user")) + return; int row = table.getSelectedRow(); if(row!=-1){ int id = Integer.valueOf(tableData.get(row).get(0)); @@ -57,9 +67,13 @@ public class QuestionsPanel extends JPanel{ }); //添加事件:打开对话框 addButton.addActionListener(e->{ + if(MainFrame.role.equals("user")) + return; new EditQuestionDialog(0,null); }); editButton.addActionListener(e->{ + if(MainFrame.role.equals("user")) + return; int row = table.getSelectedRow(); if(row>=0) openEditDialog(row); @@ -69,6 +83,8 @@ public class QuestionsPanel extends JPanel{ table.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { + if(MainFrame.role.equals("user")) + return; if(e.getClickCount()==2){ int row = table.getSelectedRow(); openEditDialog(row); @@ -94,55 +110,111 @@ public class QuestionsPanel extends JPanel{ scrollPane.getHorizontalScrollBar().setValue(0); scrollPane.revalidate(); } + public QuestionsPanel(){ initView(); initListener(); } + private void initView(){ - //设置主面板的布局为盒子布局,垂直方向 - setLayout(new BoxLayout(this,BoxLayout.Y_AXIS)); - //1.按钮界面 - JPanel buttonPanel = new JPanel(); - buttonPanel.setLayout(new GridLayout(1,3,5,5)); + setLayout(new BorderLayout()); + setBackground(BACKGROUND_COLOR); + + // 创建顶部工具栏 + JPanel topPanel = new JPanel(new BorderLayout()); + topPanel.setBackground(PRIMARY_COLOR); + topPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); + + JLabel titleLabel = new JLabel("题目管理"); + titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16)); + titleLabel.setForeground(Color.WHITE); + topPanel.add(titleLabel, BorderLayout.WEST); + + add(topPanel, BorderLayout.NORTH); + + // 创建中央内容面板 + JPanel centerPanel = new JPanel(); + centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS)); + centerPanel.setBackground(BACKGROUND_COLOR); + centerPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + // 1.按钮界面 + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5)); + buttonPanel.setBackground(BACKGROUND_COLOR); addButton = new JButton("添加"); deleteButton = new JButton("删除"); editButton = new JButton("修改"); + // 设置按钮样式 + setButtonStyle(addButton); + setButtonStyle(deleteButton); + setButtonStyle(editButton); + buttonPanel.add(addButton); buttonPanel.add(deleteButton); buttonPanel.add(editButton); - buttonPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE,50)); - add(buttonPanel); - //添加垂直间隔 - add(Box.createVerticalStrut(10)); - //2.搜索界面 - JPanel queryPanel = new JPanel(); - queryPanel.setLayout(new GridLayout(1,3,5,5)); + + centerPanel.add(buttonPanel); + centerPanel.add(Box.createVerticalStrut(10)); + + // 2.搜索界面 + JPanel queryPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5)); + queryPanel.setBackground(BACKGROUND_COLOR); frequencyComboBox = new JComboBox(new String[]{"全部","低频","中频","高频"}); keyTextField = new JTextField(15); queryButton = new JButton("查询"); + + // 设置查询按钮样式 + setButtonStyle(queryButton); + + queryPanel.add(new JLabel("频率:")); queryPanel.add(frequencyComboBox); + queryPanel.add(new JLabel("关键词:")); queryPanel.add(keyTextField); queryPanel.add(queryButton); - queryPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE,30)); - add(queryPanel); - //添加垂直间隔 - add(Box.createVerticalStrut(10)); - //3.表格界面 + + centerPanel.add(queryPanel); + centerPanel.add(Box.createVerticalStrut(10)); + + // 3.表格界面 model = new DefaultTableModel(){ @Override public boolean isCellEditable(int row, int column) { return false; } }; + table = new JTable(model); + table.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + table.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 13)); + table.getTableHeader().setBackground(PRIMARY_COLOR); + table.getTableHeader().setForeground(Color.WHITE); + table.setSelectionBackground(new Color(176, 224, 230)); + table.setRowHeight(25); + scrollPane = new JScrollPane(table); - add(scrollPane); + scrollPane.setPreferredSize(new Dimension(700, 400)); + scrollPane.setBorder(BorderFactory.createLineBorder(BORDER_COLOR, 1)); + + centerPanel.add(scrollPane); + + add(centerPanel, BorderLayout.CENTER); tableData = questionsService.getAll(); //刷新数据 refreshData(); } + + // 设置按钮样式 + private void setButtonStyle(JButton button) { + button.setFont(new Font("微软雅黑", Font.BOLD, 14)); + button.setPreferredSize(new Dimension(80, 30)); + button.setBackground(PRIMARY_COLOR); + button.setForeground(Color.WHITE); + button.setFocusPainted(false); + button.setBorder(BorderFactory.createRaisedBevelBorder()); + } + private void refreshData(){ model.setDataVector(tableData,columNames); model.fireTableDataChanged(); diff --git a/src/view/RegisterFrame.java b/src/view/RegisterFrame.java index 777fa8c..767f022 100644 --- a/src/view/RegisterFrame.java +++ b/src/view/RegisterFrame.java @@ -2,8 +2,8 @@ package view; import backend.model.User; import backend.model.enums.LoginStatus; -import backend.service.impl.AuthService; -import backend.utils.impl.CaptchaUtils; +import backend.service.AuthService; +import backend.utils.CaptchaUtils; import javax.swing.*; import java.awt.*; @@ -21,6 +21,13 @@ public class RegisterFrame extends JFrame{ private JButton registerButton;//注册按钮 private JButton backButton;//返回按钮 private AuthService authService = new AuthService(); + + // 颜色常量定义 + private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色 + private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景 + private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色 + private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景 + public RegisterFrame() { //初始化界面 initView(); @@ -32,19 +39,22 @@ public class RegisterFrame extends JFrame{ emailTextField.setText("123456@qq.com"); confirmPasswordField.setText(passwordField.getText()); } + private void initView(){ //1.设置标题 - setTitle("注册"); + setTitle("中医药知识测试系统 - 注册"); //2.设置点击关闭时的动作 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - //3.中间层容器 + //3.设置窗口背景色 + getContentPane().setBackground(BACKGROUND_COLOR); + //4.中间层容器 add(initPanel()); - //4.不允许窗口改变大小 + //5.不允许窗口改变大小 setResizable(false); - //5.自动调整窗口大小 居中显示 - pack();//自动调整窗口大小 - setLocationRelativeTo(null);//剧中 - //6.显示窗口 + //6.设置窗口大小 居中显示 + setSize(400, 400); + setLocationRelativeTo(null); + //7.显示窗口 setVisible(true); } @@ -78,7 +88,7 @@ public class RegisterFrame extends JFrame{ account.setPassword(password); account.setEmail(emailTextField.getText()); account.setRole("user"); - account.setCreatedAt(String.valueOf(System.currentTimeMillis())); + account.setCreatedAt(); LoginStatus loginStatus = authService.register(account); if(loginStatus==LoginStatus.REGISTER_SUCCESS) { this.dispose(); @@ -110,27 +120,168 @@ public class RegisterFrame extends JFrame{ private JPanel initPanel(){ - mainPanel = new JPanel(); - GridLayout gridLayout = new GridLayout(8,1,10,10); - mainPanel.setLayout(gridLayout); - //第1层 空白面板 占用 - mainPanel.add(new JPanel()); - //第2层 账号面板 - mainPanel.add(initAcountPanel()); - //第3层 密码面板 - mainPanel.add(initPasswordPanel()); - //第4层 密码确认面板 - mainPanel.add(initConfirmPasswordPanel()); - //第5层 邮箱面板 - mainPanel.add(initEmailPanel()); - //第6层 验证码面板 - mainPanel.add(initCaptchaPanel()); - //第7层 按钮面板 - mainPanel.add(initButtonPanel()); - //第8层 空白面板 占用 + mainPanel = new JPanel(new BorderLayout()); + mainPanel.setBackground(BACKGROUND_COLOR); + + // 创建顶部标题面板 + JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + titlePanel.setBackground(PRIMARY_COLOR); + JLabel titleLabel = new JLabel("用户注册"); + titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 18)); + titleLabel.setForeground(Color.WHITE); + titlePanel.add(titleLabel); + mainPanel.add(titlePanel, BorderLayout.NORTH); + + // 创建中央注册表单面板 + JPanel formPanel = new JPanel(new GridBagLayout()); + formPanel.setBackground(BACKGROUND_COLOR); + GridBagConstraints gbc = new GridBagConstraints(); + gbc.insets = new Insets(10, 10, 10, 10); + + // 第1行 - 标题 + gbc.gridx = 0; gbc.gridy = 0; + gbc.gridwidth = 2; + gbc.anchor = GridBagConstraints.CENTER; + JLabel formTitleLabel = new JLabel("创建新账户"); + formTitleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16)); + formTitleLabel.setForeground(PRIMARY_COLOR); + formPanel.add(formTitleLabel, gbc); + + // 第2行 - 用户名 + gbc.gridx = 0; gbc.gridy = 1; + gbc.gridwidth = 1; + gbc.anchor = GridBagConstraints.WEST; + JLabel usernameLabel = new JLabel("用户名:"); + usernameLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + formPanel.add(usernameLabel, gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + usernameTextField = new JTextField(15); + usernameTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + usernameTextField.setPreferredSize(new Dimension(200, 25)); + formPanel.add(usernameTextField, gbc); + + // 第3行 - 密码 + gbc.gridx = 0; gbc.gridy = 2; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + gbc.anchor = GridBagConstraints.WEST; + JLabel passwordLabel = new JLabel("密 码:"); + passwordLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + formPanel.add(passwordLabel, gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + passwordField = new JPasswordField(15); + passwordField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + passwordField.setPreferredSize(new Dimension(200, 25)); + formPanel.add(passwordField, gbc); + + // 第4行 - 确认密码 + gbc.gridx = 0; gbc.gridy = 3; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + gbc.anchor = GridBagConstraints.WEST; + JLabel confirmPasswordLabel = new JLabel("确认密码:"); + confirmPasswordLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + formPanel.add(confirmPasswordLabel, gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + confirmPasswordField = new JPasswordField(15); + confirmPasswordField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + confirmPasswordField.setPreferredSize(new Dimension(200, 25)); + formPanel.add(confirmPasswordField, gbc); + + // 第5行 - 邮箱 + gbc.gridx = 0; gbc.gridy = 4; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + gbc.anchor = GridBagConstraints.WEST; + JLabel emailLabel = new JLabel("邮 箱:"); + emailLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + formPanel.add(emailLabel, gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + emailTextField = new JTextField(15); + emailTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + emailTextField.setPreferredSize(new Dimension(200, 25)); + formPanel.add(emailTextField, gbc); + + // 第6行 - 验证码 + gbc.gridx = 0; gbc.gridy = 5; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + gbc.anchor = GridBagConstraints.WEST; + JLabel captchaLabel = new JLabel("验证码:"); + captchaLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + formPanel.add(captchaLabel, gbc); + + gbc.gridx = 1; + gbc.fill = GridBagConstraints.HORIZONTAL; + gbc.weightx = 1.0; + JPanel captchaPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0)); + captchaPanel.setBackground(BACKGROUND_COLOR); + captchaTextField = new JTextField(8); + captchaTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + captchaTextField.setPreferredSize(new Dimension(80, 25)); + captchaPanel.add(captchaTextField); + + this.captchaLabel = new JLabel(CaptchaUtils.generateCaptcha()); + this.captchaLabel.setFont(new Font("微软雅黑", Font.BOLD, 16)); + this.captchaLabel.setBackground(Color.WHITE); + this.captchaLabel.setOpaque(true); + this.captchaLabel.setBorder(BorderFactory.createLineBorder(BORDER_COLOR)); + this.captchaLabel.setPreferredSize(new Dimension(80, 25)); + this.captchaLabel.setHorizontalAlignment(JLabel.CENTER); + captchaPanel.add(this.captchaLabel); + + formPanel.add(captchaPanel, gbc); + + // 第7行 - 按钮 + gbc.gridx = 0; gbc.gridy = 6; + gbc.gridwidth = 2; + gbc.fill = GridBagConstraints.NONE; + gbc.weightx = 0.0; + gbc.anchor = GridBagConstraints.CENTER; + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 0)); + buttonPanel.setBackground(BACKGROUND_COLOR); + + registerButton = new JButton("注册"); + backButton = new JButton("返回"); + + // 设置按钮样式 + setButtonStyle(registerButton); + setButtonStyle(backButton); + + buttonPanel.add(registerButton); + buttonPanel.add(backButton); + + formPanel.add(buttonPanel, gbc); + + // 添加边距 + formPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20)); + mainPanel.add(formPanel, BorderLayout.CENTER); + return mainPanel; } + // 设置按钮样式 + private void setButtonStyle(JButton button) { + button.setFont(new Font("微软雅黑", Font.BOLD, 14)); + button.setPreferredSize(new Dimension(80, 30)); + button.setBackground(PRIMARY_COLOR); + button.setForeground(Color.WHITE); + button.setFocusPainted(false); + button.setBorder(BorderFactory.createRaisedBevelBorder()); + } + private JPanel initAcountPanel(){ JPanel panel = new JPanel(); panel.setLayout(new GridLayout(1,4,10,0)); diff --git a/src/view/UserPanel.java b/src/view/UserPanel.java new file mode 100644 index 0000000..bd280b9 --- /dev/null +++ b/src/view/UserPanel.java @@ -0,0 +1,225 @@ +package view; + +import javax.swing.*; +import javax.swing.table.DefaultTableModel; +import java.awt.*; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.Vector; + +import backend.dao.UserDao; +import backend.model.User; +import backend.service.AuthService; + +public class UserPanel extends JPanel { + private AuthService authService = new AuthService(); + private static Vector columNames = new Vector<>(); + private DefaultTableModel model; + private JTable table; + private JScrollPane scrollPane; + private Vector> tableData; + //按钮界面 + private JButton addButton; + private JButton deleteButton; + private JButton editButton; + //搜索界面 + private JComboBox roleComboBox; + private JTextField keyTextField; + private JButton queryButton; + + // 颜色常量定义 + private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色 + private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景 + private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色 + private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景 + + static { + columNames.add("ID"); + columNames.add("昵称"); + columNames.add("权限"); + columNames.add("邮箱"); + columNames.add("创建时间"); + } + + public void initListener(){ + queryButton.addActionListener(e->{ + Integer r = roleComboBox.getSelectedIndex()==0? null:roleComboBox.getSelectedIndex(); + String role; + if(r==null) + role=null; + else if(r==1) + role="user"; + else role="admin"; + String key = keyTextField.getText(); + //清楚已有数据 + model.setRowCount(0); + //条件查询 + tableData = authService.getByCondition(role,key); + //刷新表格 + refreshData(); + }); + deleteButton.addActionListener(e->{ + if(MainFrame.role.equals("user")) + return; + int row = table.getSelectedRow(); + if(row!=-1){ + int id = Integer.valueOf(tableData.get(row).get(0)); + String word = tableData.get(row).get(1); + int option = JOptionPane.showConfirmDialog(this,"确认删除"+word+"吗?","提示",JOptionPane.YES_NO_CANCEL_OPTION); + if(option == JOptionPane.YES_OPTION){ + authService.deleteUser(id); + model.removeRow(row); + } + } + }); + //添加事件:打开对话框 + addButton.addActionListener(e->{ + if(MainFrame.role.equals("user")) + return; + new EditUserDialog(0,null); + }); + editButton.addActionListener(e->{ + if(MainFrame.role.equals("user")) + return; + int row = table.getSelectedRow(); + if(row>=0) + openEditDialog(row); + + }); + //双击某行弹出修改对话框 + table.addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + if(MainFrame.role.equals("user")) + return; + if(e.getClickCount()==2){ + int row = table.getSelectedRow(); + openEditDialog(row); + } + } + }); + } + + private void initView(){ + setLayout(new BorderLayout()); + setBackground(BACKGROUND_COLOR); + + // 创建顶部工具栏 + JPanel topPanel = new JPanel(new BorderLayout()); + topPanel.setBackground(PRIMARY_COLOR); + topPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10)); + + JLabel titleLabel = new JLabel("用户管理"); + titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16)); + titleLabel.setForeground(Color.WHITE); + topPanel.add(titleLabel, BorderLayout.WEST); + + add(topPanel, BorderLayout.NORTH); + + // 创建中央内容面板 + JPanel centerPanel = new JPanel(); + centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS)); + centerPanel.setBackground(BACKGROUND_COLOR); + centerPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); + + // 1.按钮界面 + JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5)); + buttonPanel.setBackground(BACKGROUND_COLOR); + addButton = new JButton("添加"); + deleteButton = new JButton("删除"); + editButton = new JButton("修改"); + + // 设置按钮样式 + setButtonStyle(addButton); + setButtonStyle(deleteButton); + setButtonStyle(editButton); + + buttonPanel.add(addButton); + buttonPanel.add(deleteButton); + buttonPanel.add(editButton); + + centerPanel.add(buttonPanel); + centerPanel.add(Box.createVerticalStrut(10)); + + // 2.搜索界面 + JPanel queryPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5)); + queryPanel.setBackground(BACKGROUND_COLOR); + roleComboBox = new JComboBox(new String[]{"全部","user","admin"}); + keyTextField = new JTextField(15); + queryButton = new JButton("查询"); + + // 设置查询按钮样式 + setButtonStyle(queryButton); + + queryPanel.add(new JLabel("角色:")); + queryPanel.add(roleComboBox); + queryPanel.add(new JLabel("关键词:")); + queryPanel.add(keyTextField); + queryPanel.add(queryButton); + + centerPanel.add(queryPanel); + centerPanel.add(Box.createVerticalStrut(10)); + + // 3.表格界面 + model = new DefaultTableModel(){ + @Override + public boolean isCellEditable(int row, int column) { + return false; + } + }; + + table = new JTable(model); + table.setFont(new Font("微软雅黑", Font.PLAIN, 12)); + table.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 13)); + table.getTableHeader().setBackground(PRIMARY_COLOR); + table.getTableHeader().setForeground(Color.WHITE); + table.setSelectionBackground(new Color(176, 224, 230)); + table.setRowHeight(25); + + scrollPane = new JScrollPane(table); + scrollPane.setPreferredSize(new Dimension(700, 400)); + scrollPane.setBorder(BorderFactory.createLineBorder(BORDER_COLOR, 1)); + + centerPanel.add(scrollPane); + + add(centerPanel, BorderLayout.CENTER); + + tableData = authService.getAll(); + //刷新数据 + refreshData(); + } + + // 设置按钮样式 + private void setButtonStyle(JButton button) { + button.setFont(new Font("微软雅黑", Font.BOLD, 14)); + button.setPreferredSize(new Dimension(80, 30)); + button.setBackground(PRIMARY_COLOR); + button.setForeground(Color.WHITE); + button.setFocusPainted(false); + button.setBorder(BorderFactory.createRaisedBevelBorder()); + } + + private void openEditDialog(int row){ + Vector data = tableData.get(row); + UserDao userDao = new UserDao(); + User userPo = userDao.findById(Integer.parseInt(data.get(0))); + new EditUserDialog(1, userPo); + //修改成功后刷新并定位修改位置 + tableData = authService.getAll(); + refreshData(); + table.setRowSelectionInterval(row,row); + scrollPane.getVerticalScrollBar().setValue(row*table.getRowHeight()); + scrollPane.getHorizontalScrollBar().setValue(0); + scrollPane.revalidate(); + } + + public UserPanel(){ + initView(); + initListener(); + } + + private void refreshData(){ + model.setDataVector(tableData,columNames); + model.fireTableDataChanged(); + } +}