From 6454f5291fab284a01c05dc39e7df183ce5925cc Mon Sep 17 00:00:00 2001 From: root <2816025006@qq.com> Date: Thu, 4 Dec 2025 16:15:16 +0800 Subject: [PATCH 1/2] =?UTF-8?q?#1.0.1=20=E7=99=BB=E5=BD=95=E6=B3=A8?= =?UTF-8?q?=E5=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 102 +++++++++++------- readme.md | 65 ++++++++++- .../com/campus/controller/PageController.java | 45 ++++++++ .../campus/controller/StudentController.java | 68 +++++++++++- src/main/java/com/campus/entity/User.java | 41 +++---- .../java/com/campus/mapper/StudentMapper.java | 5 + .../com/campus/service/StudentService.java | 17 ++- src/main/resources/mapper/StudentMapper.xml | 29 ++++- src/main/resources/spring-mvc.xml | 23 +++- 9 files changed, 317 insertions(+), 78 deletions(-) diff --git a/pom.xml b/pom.xml index 361eac3..3275414 100644 --- a/pom.xml +++ b/pom.xml @@ -6,22 +6,28 @@ 4.0.0 com.campus - campus-attendance + student-attendance 1.0-SNAPSHOT war UTF-8 - 17 - 17 + 1.8 + 1.8 5.3.23 3.5.11 - 2.0.7 + 2.1.1 + 8.0.33 + 1.2.15 + 4.0.1 + 1.2 + 2.14.2 + 2.0.7 + 1.4.7 - - + org.springframework spring-context @@ -37,6 +43,11 @@ spring-jdbc ${spring.version} + + org.springframework + spring-tx + ${spring.version} + @@ -50,73 +61,86 @@ ${mybatis.spring.version} - + mysql mysql-connector-java - 8.0.33 + ${mysql.version} com.alibaba druid - 1.2.15 + ${druid.version} - + javax.servlet javax.servlet-api - 4.0.1 + ${servlet.version} provided + + javax.servlet + jstl + ${jstl.version} + javax.servlet.jsp javax.servlet.jsp-api 2.3.3 provided - - jstl - jstl - 1.2 - - + com.fasterxml.jackson.core jackson-databind - 2.14.1 + ${jackson.version} + + + + + org.slf4j + slf4j-api + ${slf4j.version} + + + ch.qos.logback + logback-classic + ${logback.version} + + + + + junit + junit + 4.13.2 + test - campus-attendance + student-attendance + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + ${maven.compiler.source} + ${maven.compiler.target} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins maven-war-plugin 3.3.2 - - - org.apache.maven.plugins - maven-compiler-plugin - 3.10.1 - 1.8 - 1.8 - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.10.1 - - 17 - 17 - - - --enable-preview - + false diff --git a/readme.md b/readme.md index f4c38af..2338ae8 100644 --- a/readme.md +++ b/readme.md @@ -32,4 +32,67 @@ INSERT INTO user (username, password, role) VALUES ('teacher1', 'teacher123', 'TEACHER'); -![img.png](img.png) \ No newline at end of file +![img.png](img.png) + + + +-- 在已有的数据库基础上,添加考勤相关表 + +-- 考勤记录表 +CREATE TABLE attendance_record ( +id INT PRIMARY KEY AUTO_INCREMENT, +student_id VARCHAR(20) NOT NULL, +course_name VARCHAR(100) NOT NULL, +attendance_date DATE NOT NULL, +attendance_time TIME, +status VARCHAR(20) NOT NULL DEFAULT 'PRESENT', -- PRESENT/ABSENT/LATE +remarks VARCHAR(500), +created_by VARCHAR(50), -- 记录创建人(教师用户名) +create_time DATETIME DEFAULT CURRENT_TIMESTAMP, +FOREIGN KEY (student_id) REFERENCES student(student_id) ON DELETE CASCADE +); + +-- 创建索引提高查询效率 +CREATE INDEX idx_student_date ON attendance_record(student_id, attendance_date); +CREATE INDEX idx_date_status ON attendance_record(attendance_date, status); + +-- 课程表(可选) +CREATE TABLE course ( +id INT PRIMARY KEY AUTO_INCREMENT, +course_name VARCHAR(100) NOT NULL, +teacher_id INT, -- 关联user表的id +class_name VARCHAR(50), +schedule_time VARCHAR(100), -- 上课时间描述 +status INT DEFAULT 1 -- 1启用,0停用 +); + + + + +-- 添加更多测试数据到数据库 + +-- 添加更多学生 +INSERT INTO student (name, student_id, class, major) VALUES +('王五', '2023003', '计算机1班', '计算机科学与技术'), +('赵六', '2023004', '软件1班', '软件工程'), +('钱七', '2023005', '网络1班', '网络工程'), +('孙八', '2023006', '计算机1班', '计算机科学与技术'); + +-- 添加更多用户(密码都是123456经过MD5加盐加密后的值) +-- 实际密码需要加密存储,这里先用明文,系统会自动加密 +INSERT INTO user (username, password, role) VALUES +('2023001', '123456', 'STUDENT'), +('2023002', '123456', 'STUDENT'), +('2023003', '123456', 'STUDENT'), +('teacher2', '123456', 'TEACHER'), +('admin','123456','ADMIN'), +('student1', '123456', 'STUDENT'); + +-- 添加考勤测试数据 +INSERT INTO attendance_record (student_id, course_name, attendance_date, attendance_time, status, remarks, created_by) VALUES +('2023001', '高等数学', DATE_SUB(CURDATE(), INTERVAL 3 DAY), '08:30:00', 'PRESENT', '', 'teacher1'), +('2023002', '高等数学', DATE_SUB(CURDATE(), INTERVAL 3 DAY), '08:35:00', 'LATE', '迟到5分钟', 'teacher1'), +('2023001', '大学英语', DATE_SUB(CURDATE(), INTERVAL 2 DAY), '10:00:00', 'PRESENT', '', 'teacher1'), +('2023003', '高等数学', DATE_SUB(CURDATE(), INTERVAL 3 DAY), '08:30:00', 'ABSENT', '请假', 'teacher1'), +('2023001', '数据结构', DATE_SUB(CURDATE(), INTERVAL 1 DAY), '14:00:00', 'PRESENT', '', 'teacher1'), +('2023002', '数据结构', DATE_SUB(CURDATE(), INTERVAL 1 DAY), '14:00:00', 'PRESENT', '', 'teacher1'); \ No newline at end of file diff --git a/src/main/java/com/campus/controller/PageController.java b/src/main/java/com/campus/controller/PageController.java index 0ac41cd..f38da69 100644 --- a/src/main/java/com/campus/controller/PageController.java +++ b/src/main/java/com/campus/controller/PageController.java @@ -1,8 +1,13 @@ +// com/campus/controller/PageController.java package com.campus.controller; +import com.campus.entity.User; import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; +import javax.servlet.http.HttpSession; + @Controller public class PageController { @@ -15,4 +20,44 @@ public class PageController { public String studentList() { return "student_list"; } + + @GetMapping("/login") + public String login() { + return "login"; + } + + @GetMapping("/register") + public String register() { + return "register"; + } + + @GetMapping("/admin") + public String adminPage(HttpSession session, Model model) { + User user = (User) session.getAttribute("currentUser"); + if (user == null || !"ADMIN".equals(user.getRole())) { + return "redirect:/login"; + } + model.addAttribute("user", user); + return "admin"; + } + + @GetMapping("/teacher") + public String teacherPage(HttpSession session, Model model) { + User user = (User) session.getAttribute("currentUser"); + if (user == null || !"TEACHER".equals(user.getRole())) { + return "redirect:/login"; + } + model.addAttribute("user", user); + return "teacher"; + } + + @GetMapping("/student") + public String studentPage(HttpSession session, Model model) { + User user = (User) session.getAttribute("currentUser"); + if (user == null || !"STUDENT".equals(user.getRole())) { + return "redirect:/login"; + } + model.addAttribute("user", user); + return "student"; + } } \ No newline at end of file diff --git a/src/main/java/com/campus/controller/StudentController.java b/src/main/java/com/campus/controller/StudentController.java index 87373ce..72daf88 100644 --- a/src/main/java/com/campus/controller/StudentController.java +++ b/src/main/java/com/campus/controller/StudentController.java @@ -1,3 +1,4 @@ +// com/campus/controller/StudentController.java package com.campus.controller; import com.campus.entity.Student; @@ -5,9 +6,10 @@ import com.campus.service.StudentService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; +import java.util.HashMap; import java.util.List; +import java.util.Map; -// StudentController.java @RestController @RequestMapping("/student") public class StudentController { @@ -19,9 +21,67 @@ public class StudentController { return studentService.listAll(); } + @GetMapping("/{studentId}") + public Map getByStudentId(@PathVariable String studentId) { + Map result = new HashMap<>(); + Student student = studentService.getByStudentId(studentId); + + if (student != null) { + result.put("success", true); + result.put("student", student); + } else { + result.put("success", false); + result.put("message", "学生不存在"); + } + + return result; + } + @PostMapping("/add") - public String add(@RequestBody Student student) { - studentService.add(student); - return "success"; + public Map add(@RequestBody Student student) { + Map result = new HashMap<>(); + + try { + studentService.add(student); + result.put("success", true); + result.put("message", "添加成功"); + } catch (Exception e) { + result.put("success", false); + result.put("message", "添加失败:" + e.getMessage()); + } + + return result; + } + + @PutMapping("/update") + public Map update(@RequestBody Student student) { + Map result = new HashMap<>(); + + try { + studentService.update(student); + result.put("success", true); + result.put("message", "更新成功"); + } catch (Exception e) { + result.put("success", false); + result.put("message", "更新失败:" + e.getMessage()); + } + + return result; + } + + @DeleteMapping("/delete/{id}") + public Map delete(@PathVariable Integer id) { + Map result = new HashMap<>(); + + try { + studentService.delete(id); + result.put("success", true); + result.put("message", "删除成功"); + } catch (Exception e) { + result.put("success", false); + result.put("message", "删除失败:" + e.getMessage()); + } + + return result; } } \ No newline at end of file diff --git a/src/main/java/com/campus/entity/User.java b/src/main/java/com/campus/entity/User.java index 3c4f8ae..3d8d9e7 100644 --- a/src/main/java/com/campus/entity/User.java +++ b/src/main/java/com/campus/entity/User.java @@ -1,41 +1,28 @@ +// com/campus/entity/User.java package com.campus.entity; -// User.java public class User { private Integer id; private String username; private String password; private String role; // ADMIN/TEACHER/STUDENT - public Integer getId() { - return id; - } + // 新增构造方法 + public User() {} - public void setId(Integer id) { - this.id = id; - } - - public String getUsername() { - return username; - } - - public void setUsername(String username) { + public User(String username, String password, String role) { this.username = username; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { this.password = password; - } - - public String getRole() { - return role; - } - - public void setRole(String role) { this.role = role; } + + // 已有的getter和setter方法... + public Integer getId() { return id; } + public void setId(Integer id) { this.id = id; } + public String getUsername() { return username; } + public void setUsername(String username) { this.username = username; } + public String getPassword() { return password; } + public void setPassword(String password) { this.password = password; } + public String getRole() { return role; } + public void setRole(String role) { this.role = role; } } \ No newline at end of file diff --git a/src/main/java/com/campus/mapper/StudentMapper.java b/src/main/java/com/campus/mapper/StudentMapper.java index 538191b..afcd3be 100644 --- a/src/main/java/com/campus/mapper/StudentMapper.java +++ b/src/main/java/com/campus/mapper/StudentMapper.java @@ -1,7 +1,9 @@ +// com/campus/mapper/StudentMapper.java package com.campus.mapper; import com.campus.entity.Student; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; import java.util.List; @@ -11,4 +13,7 @@ public interface StudentMapper { void insert(Student student); void update(Student student); void delete(Integer id); + + // 新增:根据学号查询学生 + Student selectByStudentId(@Param("studentId") String studentId); } \ No newline at end of file diff --git a/src/main/java/com/campus/service/StudentService.java b/src/main/java/com/campus/service/StudentService.java index 8452b00..ae8e9c8 100644 --- a/src/main/java/com/campus/service/StudentService.java +++ b/src/main/java/com/campus/service/StudentService.java @@ -1,3 +1,4 @@ +// com/campus/service/StudentService.java package com.campus.service; import com.campus.entity.Student; @@ -7,7 +8,6 @@ import org.springframework.stereotype.Service; import java.util.List; -// StudentService.java @Service public class StudentService { @Autowired @@ -20,4 +20,19 @@ public class StudentService { public void add(Student student) { studentMapper.insert(student); } + + // 添加新方法:根据学号查询学生 + public Student getByStudentId(String studentId) { + return studentMapper.selectByStudentId(studentId); + } + + // 添加更新方法 + public void update(Student student) { + studentMapper.update(student); + } + + // 添加删除方法 + public void delete(Integer id) { + studentMapper.delete(id); + } } \ No newline at end of file diff --git a/src/main/resources/mapper/StudentMapper.xml b/src/main/resources/mapper/StudentMapper.xml index 72759e6..74a8a15 100644 --- a/src/main/resources/mapper/StudentMapper.xml +++ b/src/main/resources/mapper/StudentMapper.xml @@ -3,20 +3,39 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> - SELECT * FROM student - - - INSERT INTO student(name, student_id, `class`, major) + + + + + INSERT INTO student(name, student_id, `class`, major) VALUES(#{name}, #{studentId}, #{class_}, #{major}) + UPDATE student - SET name = #{name}, student_id = #{studentId}, `class` = #{class_}, major = #{major} + SET name = #{name}, + student_id = #{studentId}, + `class` = #{class_}, + major = #{major} WHERE id = #{id} + DELETE FROM student WHERE id = #{id} + \ No newline at end of file diff --git a/src/main/resources/spring-mvc.xml b/src/main/resources/spring-mvc.xml index 3a3a6e3..ff3516c 100644 --- a/src/main/resources/spring-mvc.xml +++ b/src/main/resources/spring-mvc.xml @@ -13,7 +13,6 @@ - @@ -27,4 +26,26 @@ + + + + + + + + + + + + + + + text/html;charset=UTF-8 + application/json;charset=UTF-8 + + + + + + \ No newline at end of file From e9dfa6570dfa749bed4a3052536c0d12916bbc0d Mon Sep 17 00:00:00 2001 From: root <2816025006@qq.com> Date: Thu, 4 Dec 2025 16:15:53 +0800 Subject: [PATCH 2/2] =?UTF-8?q?#1.0.1=20=E7=99=BB=E5=BD=95=E6=B3=A8?= =?UTF-8?q?=E5=86=8C2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/AttendanceController.java | 234 +++++++ .../com/campus/controller/UserController.java | 141 ++++ .../com/campus/entity/AttendanceRecord.java | 44 ++ .../campus/interceptor/AuthInterceptor.java | 61 ++ .../com/campus/mapper/AttendanceMapper.java | 40 ++ .../java/com/campus/mapper/UserMapper.java | 14 + .../com/campus/service/AttendanceService.java | 32 + .../java/com/campus/service/UserService.java | 15 + .../service/impl/AttendanceServiceImpl.java | 100 +++ .../campus/service/impl/UserServiceImpl.java | 45 ++ .../resources/mapper/AttendanceMapper.xml | 79 +++ src/main/resources/mapper/UserMapper.xml | 23 + src/main/webapp/WEB-INF/jsp/admin.jsp | 112 ++++ src/main/webapp/WEB-INF/jsp/login.jsp | 83 +++ src/main/webapp/WEB-INF/jsp/register.jsp | 102 +++ src/main/webapp/WEB-INF/jsp/student.jsp | 140 ++++ src/main/webapp/WEB-INF/jsp/teacher.jsp | 609 ++++++++++++++++++ 17 files changed, 1874 insertions(+) create mode 100644 src/main/java/com/campus/controller/AttendanceController.java create mode 100644 src/main/java/com/campus/controller/UserController.java create mode 100644 src/main/java/com/campus/entity/AttendanceRecord.java create mode 100644 src/main/java/com/campus/interceptor/AuthInterceptor.java create mode 100644 src/main/java/com/campus/mapper/AttendanceMapper.java create mode 100644 src/main/java/com/campus/mapper/UserMapper.java create mode 100644 src/main/java/com/campus/service/AttendanceService.java create mode 100644 src/main/java/com/campus/service/UserService.java create mode 100644 src/main/java/com/campus/service/impl/AttendanceServiceImpl.java create mode 100644 src/main/java/com/campus/service/impl/UserServiceImpl.java create mode 100644 src/main/resources/mapper/AttendanceMapper.xml create mode 100644 src/main/resources/mapper/UserMapper.xml create mode 100644 src/main/webapp/WEB-INF/jsp/admin.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/login.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/register.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/student.jsp create mode 100644 src/main/webapp/WEB-INF/jsp/teacher.jsp diff --git a/src/main/java/com/campus/controller/AttendanceController.java b/src/main/java/com/campus/controller/AttendanceController.java new file mode 100644 index 0000000..706ea28 --- /dev/null +++ b/src/main/java/com/campus/controller/AttendanceController.java @@ -0,0 +1,234 @@ +// com/campus/controller/AttendanceController.java +package com.campus.controller; + +import com.campus.entity.AttendanceRecord; +import com.campus.entity.User; +import com.campus.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpSession; +import java.util.*; + +@RestController +@RequestMapping("/api/attendance") +public class AttendanceController { + + @Autowired + private AttendanceService attendanceService; + + /** + * 记录考勤(教师使用) + */ + @PostMapping("/record") + public Map recordAttendance(@RequestBody Map params, + HttpSession session) { + Map result = new HashMap<>(); + + // 检查用户是否登录且为教师 + User user = (User) session.getAttribute("currentUser"); + if (user == null) { + result.put("success", false); + result.put("message", "请先登录"); + return result; + } + + if (!"TEACHER".equals(user.getRole()) && !"ADMIN".equals(user.getRole())) { + result.put("success", false); + result.put("message", "只有教师和管理员可以记录考勤"); + return result; + } + + try { + String studentId = params.get("studentId"); + String courseName = params.get("courseName"); + String status = params.get("status"); + + if (studentId == null || courseName == null || status == null) { + result.put("success", false); + result.put("message", "参数不完整"); + return result; + } + + AttendanceRecord record = new AttendanceRecord(); + record.setStudentId(studentId); + record.setCourseName(courseName); + record.setAttendanceDate(new Date()); + record.setStatus(status); + record.setRemarks(params.get("remarks")); + record.setCreatedBy(user.getUsername()); + + boolean success = attendanceService.recordAttendance(record); + + if (success) { + result.put("success", true); + result.put("message", "考勤记录成功"); + } else { + result.put("success", false); + result.put("message", "考勤记录失败"); + } + } catch (Exception e) { + result.put("success", false); + result.put("message", e.getMessage()); + } + + return result; + } + + /** + * 补签考勤(教师使用) + */ + @PostMapping("/makeup") + public Map makeupAttendance(@RequestBody Map params, + HttpSession session) { + Map result = new HashMap<>(); + + User user = (User) session.getAttribute("currentUser"); + if (user == null || !"TEACHER".equals(user.getRole())) { + result.put("success", false); + result.put("message", "只有教师可以进行补签"); + return result; + } + + try { + AttendanceRecord record = new AttendanceRecord(); + record.setStudentId(params.get("studentId")); + record.setCourseName(params.get("courseName")); + record.setStatus(params.get("status")); + record.setRemarks(params.get("remarks")); + record.setCreatedBy(user.getUsername()); + + // 解析日期 + String dateStr = params.get("attendanceDate"); + if (dateStr != null) { + record.setAttendanceDate(new Date(Long.parseLong(dateStr))); + } else { + record.setAttendanceDate(new Date()); + } + + boolean success = attendanceService.makeUpAttendance(record); + + if (success) { + result.put("success", true); + result.put("message", "补签成功"); + } else { + result.put("success", false); + result.put("message", "补签失败"); + } + } catch (Exception e) { + result.put("success", false); + result.put("message", e.getMessage()); + } + + return result; + } + + /** + * 获取我的考勤记录(学生使用) + */ + @GetMapping("/my") + public Map getMyAttendance(HttpSession session) { + Map result = new HashMap<>(); + + User user = (User) session.getAttribute("currentUser"); + if (user == null) { + result.put("success", false); + result.put("message", "请先登录"); + return result; + } + + // 学生只能查看自己的考勤记录 + // 注意:这里需要关联学生ID和用户ID,暂时简化处理 + // 实际应用中,应该在User表中存储student_id字段 + if ("STUDENT".equals(user.getRole())) { + // 假设学生用户名为学号(简化处理) + List records = attendanceService.getAttendanceByStudentId(user.getUsername()); + result.put("success", true); + result.put("records", records); + } else { + result.put("success", false); + result.put("message", "只有学生可以查看个人考勤"); + } + + return result; + } + + /** + * 查询考勤记录(教师/管理员使用) + */ + @GetMapping("/query") + public Map queryAttendance( + @RequestParam(required = false) String studentId, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date date, + HttpSession session) { + + Map result = new HashMap<>(); + + User user = (User) session.getAttribute("currentUser"); + if (user == null || (!"TEACHER".equals(user.getRole()) && !"ADMIN".equals(user.getRole()))) { + result.put("success", false); + result.put("message", "权限不足"); + return result; + } + + List records; + + if (studentId != null && !studentId.trim().isEmpty()) { + records = attendanceService.getAttendanceByStudentId(studentId); + } else if (date != null) { + records = attendanceService.getAttendanceByDate(date); + } else { + // 默认查询今天的考勤 + records = attendanceService.getAttendanceByDate(new Date()); + } + + result.put("success", true); + result.put("records", records); + return result; + } + + /** + * 获取考勤统计 + */ + @GetMapping("/statistics") + public Map getStatistics( + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate, + @RequestParam(required = false) String studentId, + HttpSession session) { + + Map result = new HashMap<>(); + + User user = (User) session.getAttribute("currentUser"); + if (user == null || (!"TEACHER".equals(user.getRole()) && !"ADMIN".equals(user.getRole()))) { + result.put("success", false); + result.put("message", "权限不足"); + return result; + } + + if (studentId != null && !studentId.trim().isEmpty()) { + // 学生考勤统计 + Map summary = attendanceService.getStudentAttendanceSummary(studentId); + result.put("success", true); + result.put("summary", summary); + } else { + // 时间段统计 + if (startDate == null) { + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_MONTH, -30); + startDate = calendar.getTime(); + } + + if (endDate == null) { + endDate = new Date(); + } + + List> statistics = attendanceService.getAttendanceStatistics(startDate, endDate); + result.put("success", true); + result.put("statistics", statistics); + } + + return result; + } +} \ No newline at end of file diff --git a/src/main/java/com/campus/controller/UserController.java b/src/main/java/com/campus/controller/UserController.java new file mode 100644 index 0000000..54465eb --- /dev/null +++ b/src/main/java/com/campus/controller/UserController.java @@ -0,0 +1,141 @@ +// com/campus/controller/UserController.java +package com.campus.controller; + +import com.campus.entity.User; +import com.campus.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.DigestUtils; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpSession; +import java.util.HashMap; +import java.util.Map; + +@RestController +@RequestMapping("/api/user") +public class UserController { + + @Autowired + private UserService userService; + + /** + * 登录 - 使用POST方法 + */ + @PostMapping("/login") + public Map login(@RequestBody Map params, HttpSession session) { + Map result = new HashMap<>(); + + String username = params.get("username"); + String password = params.get("password"); + + if (username == null || username.trim().isEmpty() || + password == null || password.trim().isEmpty()) { + result.put("success", false); + result.put("message", "用户名和密码不能为空"); + return result; + } + + User loginUser = userService.login(username, password); + + if (loginUser != null) { + // 存储用户信息到session(移除密码) + User sessionUser = new User(); + sessionUser.setId(loginUser.getId()); + sessionUser.setUsername(loginUser.getUsername()); + sessionUser.setRole(loginUser.getRole()); + session.setAttribute("currentUser", sessionUser); + + result.put("success", true); + result.put("message", "登录成功"); + result.put("role", loginUser.getRole()); + result.put("userId", loginUser.getId()); + } else { + result.put("success", false); + result.put("message", "用户名或密码错误"); + } + return result; + } + + /** + * 注册 - 使用POST方法 + */ + @PostMapping("/register") + public Map register(@RequestBody Map params) { + Map result = new HashMap<>(); + + String username = params.get("username"); + String password = params.get("password"); + String role = params.get("role"); + + // 验证参数 + if (username == null || username.trim().isEmpty()) { + result.put("success", false); + result.put("message", "用户名不能为空"); + return result; + } + + if (password == null || password.trim().isEmpty()) { + result.put("success", false); + result.put("message", "密码不能为空"); + return result; + } + + if (role == null) { + role = "STUDENT"; // 默认角色为学生 + } + + // 验证角色是否合法 + if (!"ADMIN".equals(role) && !"TEACHER".equals(role) && !"STUDENT".equals(role)) { + result.put("success", false); + result.put("message", "角色必须是ADMIN、TEACHER或STUDENT"); + return result; + } + + // 创建用户对象 + User user = new User(); + user.setUsername(username); + user.setPassword(password); // Service层会加密 + user.setRole(role); + + boolean success = userService.register(user); + + if (success) { + result.put("success", true); + result.put("message", "注册成功"); + } else { + result.put("success", false); + result.put("message", "用户名已存在"); + } + return result; + } + + /** + * 退出登录 + */ + @PostMapping("/logout") + public Map logout(HttpSession session) { + Map result = new HashMap<>(); + session.invalidate(); + result.put("success", true); + result.put("message", "退出成功"); + return result; + } + + /** + * 获取当前登录用户信息 + */ + @GetMapping("/current") + public Map getCurrentUser(HttpSession session) { + Map result = new HashMap<>(); + User user = (User) session.getAttribute("currentUser"); + + if (user != null) { + result.put("success", true); + result.put("user", user); + } else { + result.put("success", false); + result.put("message", "未登录"); + } + return result; + } +} \ No newline at end of file diff --git a/src/main/java/com/campus/entity/AttendanceRecord.java b/src/main/java/com/campus/entity/AttendanceRecord.java new file mode 100644 index 0000000..0006932 --- /dev/null +++ b/src/main/java/com/campus/entity/AttendanceRecord.java @@ -0,0 +1,44 @@ +// com/campus/entity/AttendanceRecord.java +package com.campus.entity; + +import java.util.Date; + +public class AttendanceRecord { + private Integer id; + private String studentId; + private String courseName; + private Date attendanceDate; + private Date attendanceTime; + private String status; // PRESENT/ABSENT/LATE + private String remarks; + private String createdBy; + private Date createTime; + + // getters and setters + public Integer getId() { return id; } + public void setId(Integer id) { this.id = id; } + + public String getStudentId() { return studentId; } + public void setStudentId(String studentId) { this.studentId = studentId; } + + public String getCourseName() { return courseName; } + public void setCourseName(String courseName) { this.courseName = courseName; } + + public Date getAttendanceDate() { return attendanceDate; } + public void setAttendanceDate(Date attendanceDate) { this.attendanceDate = attendanceDate; } + + public Date getAttendanceTime() { return attendanceTime; } + public void setAttendanceTime(Date attendanceTime) { this.attendanceTime = attendanceTime; } + + public String getStatus() { return status; } + public void setStatus(String status) { this.status = status; } + + public String getRemarks() { return remarks; } + public void setRemarks(String remarks) { this.remarks = remarks; } + + public String getCreatedBy() { return createdBy; } + public void setCreatedBy(String createdBy) { this.createdBy = createdBy; } + + public Date getCreateTime() { return createTime; } + public void setCreateTime(Date createTime) { this.createTime = createTime; } +} \ No newline at end of file diff --git a/src/main/java/com/campus/interceptor/AuthInterceptor.java b/src/main/java/com/campus/interceptor/AuthInterceptor.java new file mode 100644 index 0000000..b4cbb52 --- /dev/null +++ b/src/main/java/com/campus/interceptor/AuthInterceptor.java @@ -0,0 +1,61 @@ +// com/campus/interceptor/AuthInterceptor.java +package com.campus.interceptor; + +import com.campus.entity.User; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; +import java.io.PrintWriter; + +public class AuthInterceptor implements HandlerInterceptor { + + @Override + public boolean preHandle(HttpServletRequest request, + HttpServletResponse response, + Object handler) throws Exception { + + String requestURI = request.getRequestURI(); + + // 公共接口,不需要登录 + if (requestURI.contains("/api/user/login") || + requestURI.contains("/api/user/register") || + requestURI.contains("/static/") || + requestURI.startsWith("/error")) { + return true; + } + + // API接口需要登录 + if (requestURI.startsWith("/api/")) { + HttpSession session = request.getSession(false); + if (session == null || session.getAttribute("currentUser") == null) { + // 未登录,返回JSON格式错误信息 + response.setContentType("application/json;charset=UTF-8"); + PrintWriter out = response.getWriter(); + out.write("{\"success\":false,\"message\":\"请先登录\",\"code\":401}"); + out.flush(); + return false; + } + + // 权限验证(简单版) + User user = (User) session.getAttribute("currentUser"); + String role = user.getRole(); + + // 学生只能访问特定接口 + if ("STUDENT".equals(role)) { + if (!requestURI.contains("/api/attendance/my") && + !requestURI.contains("/api/user/current") && + !requestURI.contains("/api/user/logout")) { + response.setContentType("application/json;charset=UTF-8"); + PrintWriter out = response.getWriter(); + out.write("{\"success\":false,\"message\":\"权限不足\",\"code\":403}"); + out.flush(); + return false; + } + } + } + + return true; + } +} \ No newline at end of file diff --git a/src/main/java/com/campus/mapper/AttendanceMapper.java b/src/main/java/com/campus/mapper/AttendanceMapper.java new file mode 100644 index 0000000..0c3e6be --- /dev/null +++ b/src/main/java/com/campus/mapper/AttendanceMapper.java @@ -0,0 +1,40 @@ +// com/campus/mapper/AttendanceMapper.java +package com.campus.mapper; + +import com.campus.entity.AttendanceRecord; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +@Mapper +public interface AttendanceMapper { + + // 添加考勤记录 + int insert(AttendanceRecord record); + + // 根据学生ID查询考勤记录 + List selectByStudentId(@Param("studentId") String studentId); + + // 根据日期查询考勤记录 + List selectByDate(@Param("date") Date date); + + // 根据学生ID和日期查询 + AttendanceRecord selectByStudentAndDate(@Param("studentId") String studentId, + @Param("date") Date date); + + // 更新考勤记录(补签) + int update(AttendanceRecord record); + + // 删除考勤记录 + int delete(Integer id); + + // 统计考勤情况 + List> getAttendanceStatistics(@Param("startDate") Date startDate, + @Param("endDate") Date endDate); + + // 查询某个学生的考勤统计 + Map getStudentAttendanceSummary(@Param("studentId") String studentId); +} \ No newline at end of file diff --git a/src/main/java/com/campus/mapper/UserMapper.java b/src/main/java/com/campus/mapper/UserMapper.java new file mode 100644 index 0000000..df7bb9f --- /dev/null +++ b/src/main/java/com/campus/mapper/UserMapper.java @@ -0,0 +1,14 @@ +// com/campus/mapper/UserMapper.java +package com.campus.mapper; + +import com.campus.entity.User; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface UserMapper { + // 根据用户名查询用户 + User selectByUsername(String username); + + // 新增用户(注册) + void insert(User user); +} \ No newline at end of file diff --git a/src/main/java/com/campus/service/AttendanceService.java b/src/main/java/com/campus/service/AttendanceService.java new file mode 100644 index 0000000..36de845 --- /dev/null +++ b/src/main/java/com/campus/service/AttendanceService.java @@ -0,0 +1,32 @@ +// com/campus/service/AttendanceService.java +package com.campus.service; + +import com.campus.entity.AttendanceRecord; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +public interface AttendanceService { + + // 记录考勤 + boolean recordAttendance(AttendanceRecord record); + + // 补签考勤 + boolean makeUpAttendance(AttendanceRecord record); + + // 查询学生考勤记录 + List getAttendanceByStudentId(String studentId); + + // 查询日期考勤记录 + List getAttendanceByDate(Date date); + + // 查询统计信息 + List> getAttendanceStatistics(Date startDate, Date endDate); + + // 查询学生考勤统计 + Map getStudentAttendanceSummary(String studentId); + + // 检查是否已考勤 + boolean checkAttendanceExists(String studentId, Date date); +} \ No newline at end of file diff --git a/src/main/java/com/campus/service/UserService.java b/src/main/java/com/campus/service/UserService.java new file mode 100644 index 0000000..35e7e05 --- /dev/null +++ b/src/main/java/com/campus/service/UserService.java @@ -0,0 +1,15 @@ +// com/campus/service/UserService.java +package com.campus.service; + +import com.campus.entity.User; + +public interface UserService { + // 登录 + User login(String username, String password); + + // 注册 + boolean register(User user); + + // 检查用户名是否已存在 + boolean checkUsernameExists(String username); +} \ No newline at end of file diff --git a/src/main/java/com/campus/service/impl/AttendanceServiceImpl.java b/src/main/java/com/campus/service/impl/AttendanceServiceImpl.java new file mode 100644 index 0000000..363079b --- /dev/null +++ b/src/main/java/com/campus/service/impl/AttendanceServiceImpl.java @@ -0,0 +1,100 @@ +// com/campus/service/impl/AttendanceServiceImpl.java +package com.campus.service.impl; + +import com.campus.entity.AttendanceRecord; +import com.campus.entity.Student; +import com.campus.mapper.AttendanceMapper; +import com.campus.mapper.StudentMapper; +import com.campus.service.AttendanceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Date; +import java.util.List; +import java.util.Map; + +@Service +public class AttendanceServiceImpl implements AttendanceService { + + @Autowired + private AttendanceMapper attendanceMapper; + + @Autowired + private StudentMapper studentMapper; // 使用你定义的StudentMapper + + @Override + @Transactional + public boolean recordAttendance(AttendanceRecord record) { + // 验证学生是否存在 - 使用 selectByStudentId 方法 + Student student = studentMapper.selectByStudentId(record.getStudentId()); + + if (student == null) { + throw new RuntimeException("学生不存在,学号:" + record.getStudentId()); + } + + // 检查是否已考勤 + if (checkAttendanceExists(record.getStudentId(), record.getAttendanceDate())) { + throw new RuntimeException("该学生今天已考勤,学号:" + record.getStudentId()); + } + + // 设置创建时间 + if (record.getAttendanceTime() == null) { + record.setAttendanceTime(new Date()); + } + + return attendanceMapper.insert(record) > 0; + } + + @Override + @Transactional + public boolean makeUpAttendance(AttendanceRecord record) { + // 验证学生是否存在 + Student student = studentMapper.selectByStudentId(record.getStudentId()); + if (student == null) { + throw new RuntimeException("学生不存在,学号:" + record.getStudentId()); + } + + // 检查是否已有记录 + AttendanceRecord existing = attendanceMapper.selectByStudentAndDate( + record.getStudentId(), record.getAttendanceDate()); + + if (existing != null) { + // 更新现有记录 + existing.setStatus(record.getStatus()); + existing.setRemarks(record.getRemarks()); + existing.setAttendanceTime(new Date()); + existing.setCreatedBy(record.getCreatedBy()); + return attendanceMapper.update(existing) > 0; + } else { + // 创建新记录 + return recordAttendance(record); + } + } + + @Override + public List getAttendanceByStudentId(String studentId) { + return attendanceMapper.selectByStudentId(studentId); + } + + @Override + public List getAttendanceByDate(Date date) { + return attendanceMapper.selectByDate(date); + } + + @Override + public List> getAttendanceStatistics(Date startDate, Date endDate) { + return attendanceMapper.getAttendanceStatistics(startDate, endDate); + } + + @Override + public Map getStudentAttendanceSummary(String studentId) { + return attendanceMapper.getStudentAttendanceSummary(studentId); + } + + @Override + public boolean checkAttendanceExists(String studentId, Date date) { + AttendanceRecord record = attendanceMapper.selectByStudentAndDate(studentId, date); + return record != null; + } +} \ No newline at end of file diff --git a/src/main/java/com/campus/service/impl/UserServiceImpl.java b/src/main/java/com/campus/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..88f5bf4 --- /dev/null +++ b/src/main/java/com/campus/service/impl/UserServiceImpl.java @@ -0,0 +1,45 @@ +// com/campus/service/impl/UserServiceImpl.java +package com.campus.service.impl; + +import com.campus.entity.User; +import com.campus.mapper.UserMapper; +import com.campus.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +@Service +public class UserServiceImpl implements UserService { + + @Autowired + private UserMapper userMapper; + + @Override + public User login(String username, String password) { + // 1. 根据用户名查询用户 + User user = userMapper.selectByUsername(username); + // 2. 直接比对明文密码(作业简化版) + if (user != null && password.equals(user.getPassword())) { + return user; + } + return null; + } + + @Override + public boolean register(User user) { + // 检查用户名是否已存在 + if (checkUsernameExists(user.getUsername())) { + return false; + } + // 密码直接存明文(作业简化版) + // 注意:实际生产环境绝不允许这样做! + userMapper.insert(user); + return true; + } + + @Override + public boolean checkUsernameExists(String username) { + return userMapper.selectByUsername(username) != null; + } + + // 完全删除原来的 encryptPassword 方法 +} \ No newline at end of file diff --git a/src/main/resources/mapper/AttendanceMapper.xml b/src/main/resources/mapper/AttendanceMapper.xml new file mode 100644 index 0000000..3cf4a62 --- /dev/null +++ b/src/main/resources/mapper/AttendanceMapper.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + INSERT INTO attendance_record(student_id, course_name, attendance_date, attendance_time, status, remarks, created_by) + VALUES(#{studentId}, #{courseName}, #{attendanceDate}, #{attendanceTime}, #{status}, #{remarks}, #{createdBy}) + + + + + + + + + + UPDATE attendance_record + SET status = #{status}, + remarks = #{remarks}, + attendance_time = #{attendanceTime}, + created_by = #{createdBy} + WHERE id = #{id} + + + + DELETE FROM attendance_record WHERE id = #{id} + + + + + + + \ No newline at end of file diff --git a/src/main/resources/mapper/UserMapper.xml b/src/main/resources/mapper/UserMapper.xml new file mode 100644 index 0000000..8bd368e --- /dev/null +++ b/src/main/resources/mapper/UserMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + INSERT INTO user(username, password, role) + VALUES(#{username}, #{password}, #{role}) + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/admin.jsp b/src/main/webapp/WEB-INF/jsp/admin.jsp new file mode 100644 index 0000000..974f72f --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/admin.jsp @@ -0,0 +1,112 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + 管理员主页 + + + + +
+

学生考勤系统 - 管理员

+
+ 欢迎,${user.username}(管理员) | + 退出 +
+
+ + + +
+

欢迎使用学生考勤管理系统

+

请选择左侧菜单进行操作

+
+ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/login.jsp b/src/main/webapp/WEB-INF/jsp/login.jsp new file mode 100644 index 0000000..b4570c7 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/login.jsp @@ -0,0 +1,83 @@ + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + 登录 - 学生考勤系统 + + + + +
+

学生考勤系统登录

+
+ + +
+
+ + +
+ + +
+
+ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/register.jsp b/src/main/webapp/WEB-INF/jsp/register.jsp new file mode 100644 index 0000000..2718c6c --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/register.jsp @@ -0,0 +1,102 @@ + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + 注册 - 学生考勤系统 + + + + +
+

用户注册

+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
+
+ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/student.jsp b/src/main/webapp/WEB-INF/jsp/student.jsp new file mode 100644 index 0000000..3b8d195 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/student.jsp @@ -0,0 +1,140 @@ + +<%@ page contentType="text/html;charset=UTF-8" language="java" %> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> + + + 学生主页 + + + + + +
+

学生考勤系统 - 学生

+
+ 欢迎,${user.username}(学生) | + 退出 +
+
+ +
+
+

我的考勤统计

+
+

加载中...

+
+
+ +

我的考勤记录

+
+

加载中...

+
+
+ + + + \ No newline at end of file diff --git a/src/main/webapp/WEB-INF/jsp/teacher.jsp b/src/main/webapp/WEB-INF/jsp/teacher.jsp new file mode 100644 index 0000000..dcd7ee2 --- /dev/null +++ b/src/main/webapp/WEB-INF/jsp/teacher.jsp @@ -0,0 +1,609 @@ +<%@ page contentType="text/html;charset=UTF-8" language="java" %> + + + 教师主页 - 学生考勤系统 + + + + +
+

学生考勤系统 - 教师

+
+ 欢迎,${user.username}(教师) | + 退出 +
+
+ + + +
+

欢迎使用学生考勤系统

+

请选择上方菜单进行操作

+
+
+ + + + \ No newline at end of file