feat: add student page

fix: resolve login issues
This commit is contained in:
seahi 2024-12-17 10:47:10 +08:00
parent b8f3ca130b
commit 5877055879
11 changed files with 729 additions and 180 deletions

View File

@ -15,7 +15,7 @@ public class StudentDAOImpl implements StudentDAO {
@Override @Override
public int insert(Student student) { public int insert(Student student) {
String sql = "INSERT INTO students (student_id, name, class_name, contact, college, major, is_graduating) VALUES (?, ?, ?, ?, ?, ?, ?)"; String sql = "INSERT INTO students (student_id, name, class_name, contact, college, major, is_graduating, password) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
try (Connection conn = DatabaseUtil.getConnection(); try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
@ -26,6 +26,7 @@ public class StudentDAOImpl implements StudentDAO {
stmt.setString(5, student.getCollege()); stmt.setString(5, student.getCollege());
stmt.setString(6, student.getMajor()); stmt.setString(6, student.getMajor());
stmt.setBoolean(7, student.isGraduating()); stmt.setBoolean(7, student.isGraduating());
stmt.setString(8, student.getPassword());
int affectedRows = stmt.executeUpdate(); int affectedRows = stmt.executeUpdate();
if (affectedRows == 0) { if (affectedRows == 0) {
@ -60,7 +61,7 @@ public class StudentDAOImpl implements StudentDAO {
@Override @Override
public int update(Student student) { public int update(Student student) {
String sql = "UPDATE students SET student_id = ?, name = ?, class_name = ?, contact = ?, college = ?, major = ?, is_graduating = ? WHERE id = ?"; String sql = "UPDATE students SET student_id = ?, name = ?, class_name = ?, contact = ?, college = ?, major = ?, is_graduating = ?, password = ? WHERE id = ?";
try (Connection conn = DatabaseUtil.getConnection(); try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) { PreparedStatement stmt = conn.prepareStatement(sql)) {
@ -71,7 +72,8 @@ public class StudentDAOImpl implements StudentDAO {
stmt.setString(5, student.getCollege()); stmt.setString(5, student.getCollege());
stmt.setString(6, student.getMajor()); stmt.setString(6, student.getMajor());
stmt.setBoolean(7, student.isGraduating()); stmt.setBoolean(7, student.isGraduating());
stmt.setInt(8, student.getId()); stmt.setString(8, student.getPassword());
stmt.setInt(9, student.getId());
return stmt.executeUpdate(); return stmt.executeUpdate();
} catch (SQLException e) { } catch (SQLException e) {
@ -184,6 +186,7 @@ public class StudentDAOImpl implements StudentDAO {
student.setCollege(rs.getString("college")); student.setCollege(rs.getString("college"));
student.setMajor(rs.getString("major")); student.setMajor(rs.getString("major"));
student.setGraduating(rs.getBoolean("is_graduating")); student.setGraduating(rs.getBoolean("is_graduating"));
student.setPassword(rs.getString("password"));
return student; return student;
} }
} }

View File

@ -15,7 +15,7 @@ public class TeacherDAOImpl implements TeacherDAO {
@Override @Override
public int insert(Teacher teacher) { public int insert(Teacher teacher) {
String sql = "INSERT INTO teachers (teacher_id, name, department, contact) VALUES (?, ?, ?, ?)"; String sql = "INSERT INTO teachers (teacher_id, name, department, contact, password) VALUES (?, ?, ?, ?, ?)";
try (Connection conn = DatabaseUtil.getConnection(); try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { PreparedStatement stmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
@ -23,6 +23,7 @@ public class TeacherDAOImpl implements TeacherDAO {
stmt.setString(2, teacher.getName()); stmt.setString(2, teacher.getName());
stmt.setString(3, teacher.getDepartment()); stmt.setString(3, teacher.getDepartment());
stmt.setString(4, teacher.getContact()); stmt.setString(4, teacher.getContact());
stmt.setString(5, teacher.getPassword());
int affectedRows = stmt.executeUpdate(); int affectedRows = stmt.executeUpdate();
if (affectedRows == 0) { if (affectedRows == 0) {
@ -57,7 +58,7 @@ public class TeacherDAOImpl implements TeacherDAO {
@Override @Override
public int update(Teacher teacher) { public int update(Teacher teacher) {
String sql = "UPDATE teachers SET teacher_id = ?, name = ?, department = ?, contact = ? WHERE id = ?"; String sql = "UPDATE teachers SET teacher_id = ?, name = ?, department = ?, contact = ?, password = ? WHERE id = ?";
try (Connection conn = DatabaseUtil.getConnection(); try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) { PreparedStatement stmt = conn.prepareStatement(sql)) {
@ -65,7 +66,8 @@ public class TeacherDAOImpl implements TeacherDAO {
stmt.setString(2, teacher.getName()); stmt.setString(2, teacher.getName());
stmt.setString(3, teacher.getDepartment()); stmt.setString(3, teacher.getDepartment());
stmt.setString(4, teacher.getContact()); stmt.setString(4, teacher.getContact());
stmt.setInt(5, teacher.getId()); stmt.setString(5, teacher.getPassword());
stmt.setInt(6, teacher.getId());
return stmt.executeUpdate(); return stmt.executeUpdate();
} catch (SQLException e) { } catch (SQLException e) {
@ -175,6 +177,7 @@ public class TeacherDAOImpl implements TeacherDAO {
teacher.setName(rs.getString("name")); teacher.setName(rs.getString("name"));
teacher.setDepartment(rs.getString("department")); teacher.setDepartment(rs.getString("department"));
teacher.setContact(rs.getString("contact")); teacher.setContact(rs.getString("contact"));
teacher.setPassword(rs.getString("password"));
return teacher; return teacher;
} }
} }

View File

@ -1,14 +1,15 @@
package gui; package gui;
import model.Student;
import model.Teacher;
import service.StudentService;
import service.TeacherService;
import service.ServiceFactory;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import util.DatabaseUtil;
public class LoginFrame extends JFrame { public class LoginFrame extends JFrame {
private JComboBox<String> userTypeComboBox; private JComboBox<String> userTypeComboBox;
@ -16,76 +17,128 @@ public class LoginFrame extends JFrame {
private JPasswordField passwordField; private JPasswordField passwordField;
private JButton loginButton; private JButton loginButton;
private final StudentService studentService = ServiceFactory.getStudentService();
private final TeacherService teacherService = ServiceFactory.getTeacherService();
public LoginFrame() { public LoginFrame() {
setTitle("登录"); setTitle("平安校园 - 登录");
setSize(300, 200); setSize(350, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null); setLocationRelativeTo(null);
JPanel panel = new JPanel(); // 创建主面板使用BorderLayout
panel.setLayout(new GridLayout(4, 2)); JPanel mainPanel = new JPanel(new BorderLayout(20, 20));
mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 30, 20, 30));
panel.add(new JLabel("用户类型:")); // 标题面板
JPanel titlePanel = new JPanel();
JLabel titleLabel = new JLabel("日常出校申请系统");
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 20));
titlePanel.add(titleLabel);
// 登录表单面板
JPanel formPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(8, 8, 8, 8);
gbc.weightx = 1.0;
// 用户类型
gbc.gridx = 0;
gbc.gridy = 0;
JLabel userTypeLabel = new JLabel("用户类型:");
userTypeLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
formPanel.add(userTypeLabel, gbc);
gbc.gridx = 1;
userTypeComboBox = new JComboBox<>(new String[]{"学生", "教师"}); userTypeComboBox = new JComboBox<>(new String[]{"学生", "教师"});
panel.add(userTypeComboBox); userTypeComboBox.setFont(new Font("微软雅黑", Font.PLAIN, 14));
formPanel.add(userTypeComboBox, gbc);
panel.add(new JLabel("ID:")); // ID输入框
idField = new JTextField(); gbc.gridx = 0;
panel.add(idField); gbc.gridy = 1;
JLabel idLabel = new JLabel("ID:");
idLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
formPanel.add(idLabel, gbc);
panel.add(new JLabel("密码:")); gbc.gridx = 1;
passwordField = new JPasswordField(); idField = new JTextField(20);
panel.add(passwordField); idField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
formPanel.add(idField, gbc);
// 密码输入框
gbc.gridx = 0;
gbc.gridy = 2;
JLabel passwordLabel = new JLabel("密码:");
passwordLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
formPanel.add(passwordLabel, gbc);
gbc.gridx = 1;
passwordField = new JPasswordField(20);
passwordField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
formPanel.add(passwordField, gbc);
// 登录按钮面板
JPanel buttonPanel = new JPanel();
buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
loginButton = new JButton("登录"); loginButton = new JButton("登录");
panel.add(loginButton); loginButton.setFont(new Font("微软雅黑", Font.PLAIN, 14));
loginButton.setPreferredSize(new Dimension(100, 35));
loginButton.setBackground(new Color(52, 152, 219));
// loginButton.setForeground(Color.WHITE);
loginButton.setFocusPainted(false);
buttonPanel.add(loginButton);
loginButton.addActionListener(new ActionListener() { // 添加事件监听
@Override loginButton.addActionListener(e -> handleLogin());
public void actionPerformed(ActionEvent e) {
handleLogin();
}
});
add(panel); // 组装界面
mainPanel.add(titlePanel, BorderLayout.NORTH);
mainPanel.add(formPanel, BorderLayout.CENTER);
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
add(mainPanel);
} }
private void handleLogin() { private void handleLogin() {
String userType = (String) userTypeComboBox.getSelectedItem(); String userType = (String) userTypeComboBox.getSelectedItem();
String id = idField.getText(); String id = idField.getText().trim();
String password = new String(passwordField.getPassword()); String password = new String(passwordField.getPassword());
String tableName = "学生".equals(userType) ? "students" : "teachers"; if (id.isEmpty() || password.isEmpty()) {
String idColumnName = "学生".equals(userType) ? "student_id" : "teacher_id"; JOptionPane.showMessageDialog(this, "请输入ID和密码", "提示", JOptionPane.WARNING_MESSAGE);
String sql = "SELECT * FROM " + tableName + " WHERE " + idColumnName + " = ? AND password = ?"; return;
try (Connection conn = DatabaseUtil.getConnection();
PreparedStatement stmt = conn.prepareStatement(sql)) {
stmt.setString(1, id);
stmt.setString(2, password);
ResultSet rs = stmt.executeQuery();
if (rs.next()) {
if ("教师".equals(userType)) {
TeacherMainFrame teacherMainFrame = new TeacherMainFrame();
teacherMainFrame.setVisible(true);
} else {
// TODO: 打开学生主界面
JOptionPane.showMessageDialog(this, "学生登录成功!", "提示", JOptionPane.INFORMATION_MESSAGE);
} }
if ("学生".equals(userType)) {
Student student = studentService.login(id, password);
if (student != null) {
StudentMainFrame studentMainFrame = new StudentMainFrame(student);
studentMainFrame.setVisible(true);
dispose(); dispose();
} else { } else {
JOptionPane.showMessageDialog(this, "无效的ID或密码", "错误", JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(this, "无效的学号或密码", "错误", JOptionPane.ERROR_MESSAGE);
}
} else {
Teacher teacher = teacherService.login(id, password);
if (teacher != null) {
TeacherMainFrame teacherMainFrame = new TeacherMainFrame();
teacherMainFrame.setVisible(true);
dispose();
} else {
JOptionPane.showMessageDialog(this, "无效的教师ID或密码", "错误", JOptionPane.ERROR_MESSAGE);
} }
} catch (SQLException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(this, "数据库错误:" + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
} }
} }
public static void main(String[] args) { public static void main(String[] args) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(() -> { SwingUtilities.invokeLater(() -> {
LoginFrame loginFrame = new LoginFrame(); LoginFrame loginFrame = new LoginFrame();
loginFrame.setVisible(true); loginFrame.setVisible(true);

View File

@ -14,11 +14,13 @@ public class RequestDetailDialog extends JDialog {
private final LeaveRequestService leaveRequestService; private final LeaveRequestService leaveRequestService;
private LeaveRequest currentRequest; private LeaveRequest currentRequest;
private Runnable onApprovalComplete; // 添加回调接口 private Runnable onApprovalComplete; // 添加回调接口
private boolean isStudent; // 添加标识是否为学生
public RequestDetailDialog(JFrame parent, int requestId, Runnable onApprovalComplete) { public RequestDetailDialog(JFrame parent, int requestId, Runnable onApprovalComplete, boolean isStudent) {
super(parent, "请假详情", true); super(parent, "请假详情", true);
this.leaveRequestService = ServiceFactory.getLeaveRequestService(); this.leaveRequestService = ServiceFactory.getLeaveRequestService();
this.onApprovalComplete = onApprovalComplete; this.onApprovalComplete = onApprovalComplete;
this.isStudent = isStudent;
// 根据ID获取请假信息 // 根据ID获取请假信息
this.currentRequest = leaveRequestService.getLeaveRequestById(requestId); this.currentRequest = leaveRequestService.getLeaveRequestById(requestId);
@ -78,6 +80,33 @@ public class RequestDetailDialog extends JDialog {
// 审批按钮 // 审批按钮
JPanel actionButtonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10)); JPanel actionButtonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
if (isStudent) {
// 学生只能看到撤销按钮且仅在待审批状态下可用
if (currentRequest.getStatus() == ApprovalStatus.PENDING) {
JButton cancelButton = new JButton("撤销申请");
cancelButton.setPreferredSize(new Dimension(100, 30));
cancelButton.setBackground(new Color(231, 76, 60));
cancelButton.addActionListener(e -> {
int confirm = JOptionPane.showConfirmDialog(
this,
"确定要撤销这条请假申请吗?",
"确认撤销",
JOptionPane.YES_NO_OPTION
);
if (confirm == JOptionPane.YES_OPTION) {
leaveRequestService.cancelLeaveRequest(currentRequest.getId());
dispose();
if (onApprovalComplete != null) {
onApprovalComplete.run();
}
JOptionPane.showMessageDialog(getParent(), "申请已撤销", "提示", JOptionPane.INFORMATION_MESSAGE);
}
});
actionButtonPanel.add(cancelButton);
}
} else {
// 教师可以看到通过和驳回按钮
JButton approveButton = new JButton("通过"); JButton approveButton = new JButton("通过");
JButton rejectButton = new JButton("驳回"); JButton rejectButton = new JButton("驳回");
@ -92,19 +121,12 @@ public class RequestDetailDialog extends JDialog {
// 设置按钮样式 // 设置按钮样式
approveButton.setBackground(new Color(39, 174, 96)); approveButton.setBackground(new Color(39, 174, 96));
// approveButton.setForeground(Color.WHITE);
rejectButton.setBackground(new Color(231, 76, 60)); rejectButton.setBackground(new Color(231, 76, 60));
// rejectButton.setForeground(Color.WHITE);
actionButtonPanel.add(approveButton); actionButtonPanel.add(approveButton);
actionButtonPanel.add(rejectButton); actionButtonPanel.add(rejectButton);
// 添加按钮面板 // 添加教师审批按钮的事件监听
gbc.insets = new Insets(20, 10, 10, 10);
mainPanel.add(actionButtonPanel, gbc);
// 添加事件监听
approveButton.addActionListener(e -> { approveButton.addActionListener(e -> {
// 创建一个自定义对话框 // 创建一个自定义对话框
JDialog approveDialog = new JDialog(this, "审批意见", true); JDialog approveDialog = new JDialog(this, "审批意见", true);
@ -201,6 +223,11 @@ public class RequestDetailDialog extends JDialog {
rejectDialog.add(inputPanel); rejectDialog.add(inputPanel);
rejectDialog.setVisible(true); rejectDialog.setVisible(true);
}); });
}
// 添加按钮面板
gbc.insets = new Insets(20, 10, 10, 10);
mainPanel.add(actionButtonPanel, gbc);
// 添加滚动面板 // 添加滚动面板
JScrollPane scrollPane = new JScrollPane(mainPanel); JScrollPane scrollPane = new JScrollPane(mainPanel);

View File

@ -0,0 +1,344 @@
package gui;
import model.ApprovalStatus;
import model.LeaveRequest;
import model.Student;
import service.LeaveRequestService;
import service.ServiceFactory;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
public class StudentMainFrame extends JFrame {
private final LeaveRequestService leaveRequestService;
private final Student currentStudent;
private JTable requestTable;
private DefaultTableModel tableModel;
private int currentPage = 1;
private static final int PAGE_SIZE = 10;
public StudentMainFrame(Student student) {
this.currentStudent = student;
leaveRequestService = ServiceFactory.getLeaveRequestService();
initComponents();
loadLeaveRequests();
}
private void initComponents() {
setTitle("平安校园 - 日常出校申请");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(400, 600);
setLocationRelativeTo(null);
// 主面板
JPanel mainPanel = new JPanel(new BorderLayout(10, 10));
mainPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// 顶部面板
JPanel topPanel = new JPanel(new BorderLayout());
// 标题
JLabel titleLabel = new JLabel("日常出校申请记录", SwingConstants.CENTER);
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 18));
topPanel.add(titleLabel, BorderLayout.CENTER);
// 学生信息和申请按钮面板
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT, 20, 5));
// 添加学生信息
JLabel studentInfoLabel = new JLabel(String.format("%s - %s", currentStudent.getClassName(), currentStudent.getName()));
studentInfoLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
buttonPanel.add(studentInfoLabel);
// 申请按钮
JButton newRequestButton = new JButton("日常出校申请");
newRequestButton.setFont(new Font("微软雅黑", Font.PLAIN, 14));
newRequestButton.setBackground(new Color(52, 152, 219));
// newRequestButton.setForeground(Color.WHITE);
newRequestButton.setFocusPainted(false);
newRequestButton.addActionListener(e -> showNewRequestDialog());
buttonPanel.add(newRequestButton);
topPanel.add(buttonPanel, BorderLayout.NORTH);
// 表格
String[] columnNames = {"ID", "状态", "申请时间", "外出开始时间", "外出结束时间", "外出事由"};
tableModel = new DefaultTableModel(columnNames, 0) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
requestTable = new JTable(tableModel);
requestTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
// 设置表格样式
requestTable.setRowHeight(30);
requestTable.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 12));
requestTable.setFont(new Font("微软雅黑", Font.PLAIN, 12));
// 设置列宽
TableColumnModel columnModel = requestTable.getColumnModel();
columnModel.getColumn(0).setPreferredWidth(40); // ID
columnModel.getColumn(1).setPreferredWidth(60); // 状态
columnModel.getColumn(2).setPreferredWidth(100); // 申请时间
columnModel.getColumn(3).setPreferredWidth(100); // 开始时间
columnModel.getColumn(4).setPreferredWidth(100); // 结束时间
columnModel.getColumn(5).setPreferredWidth(100); // 外出事由
// 添加表格点击事件
requestTable.addMouseListener(new java.awt.event.MouseAdapter() {
@Override
public void mouseClicked(java.awt.event.MouseEvent evt) {
if (evt.getClickCount() == 2) {
int row = requestTable.getSelectedRow();
if (row != -1) {
showRequestDetails(row);
}
}
}
});
// 分页控制
JPanel pagePanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
JButton prevButton = new JButton("上一页");
JButton nextButton = new JButton("下一页");
JLabel pageLabel = new JLabel("1/1");
pagePanel.add(prevButton);
pagePanel.add(pageLabel);
pagePanel.add(nextButton);
// 分页按钮事件
prevButton.addActionListener(e -> {
if (currentPage > 1) {
currentPage--;
loadLeaveRequests();
}
});
nextButton.addActionListener(e -> {
List<LeaveRequest> requests = leaveRequestService.getStudentLeaveRequests(currentStudent.getId());
int totalPages = (requests.size() + PAGE_SIZE - 1) / PAGE_SIZE;
if (currentPage < totalPages) {
currentPage++;
loadLeaveRequests();
}
});
// 布局
mainPanel.add(topPanel, BorderLayout.NORTH);
mainPanel.add(new JScrollPane(requestTable), BorderLayout.CENTER);
mainPanel.add(pagePanel, BorderLayout.SOUTH);
add(mainPanel);
}
private void showNewRequestDialog() {
JDialog dialog = new JDialog(this, "新建日常出校申请", true);
dialog.setSize(400, 500);
dialog.setLocationRelativeTo(this);
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
GridBagConstraints gbc = new GridBagConstraints();
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.insets = new Insets(5, 5, 5, 5);
// 开始时间
gbc.gridx = 0;
gbc.gridy = 0;
panel.add(new JLabel("开始时间:"), gbc);
gbc.gridx = 1;
SpinnerDateModel startModel = new SpinnerDateModel();
JSpinner startTimeSpinner = new JSpinner(startModel);
startTimeSpinner.setEditor(new JSpinner.DateEditor(startTimeSpinner, "yyyy-MM-dd HH:mm"));
panel.add(startTimeSpinner, gbc);
// 结束时间
gbc.gridx = 0;
gbc.gridy = 1;
panel.add(new JLabel("结束时间:"), gbc);
gbc.gridx = 1;
SpinnerDateModel endModel = new SpinnerDateModel();
JSpinner endTimeSpinner = new JSpinner(endModel);
endTimeSpinner.setEditor(new JSpinner.DateEditor(endTimeSpinner, "yyyy-MM-dd HH:mm"));
panel.add(endTimeSpinner, gbc);
// 外出地址
gbc.gridx = 0;
gbc.gridy = 2;
panel.add(new JLabel("外出地址:"), gbc);
gbc.gridx = 1;
JTextField locationField = new JTextField(20);
panel.add(locationField, gbc);
// 事由类型
gbc.gridx = 0;
gbc.gridy = 3;
panel.add(new JLabel("事由类型:"), gbc);
gbc.gridx = 1;
String[] reasonTypes = {"学习", "就医", "办事", "活动", "返乡", "实习", "其他"};
JComboBox<String> reasonTypeCombo = new JComboBox<>(reasonTypes);
panel.add(reasonTypeCombo, gbc);
// 详细事由
gbc.gridx = 0;
gbc.gridy = 4;
panel.add(new JLabel("详细事由:"), gbc);
gbc.gridx = 1;
JTextArea reasonArea = new JTextArea(4, 20);
reasonArea.setLineWrap(true);
reasonArea.setWrapStyleWord(true);
JScrollPane scrollPane = new JScrollPane(reasonArea);
panel.add(scrollPane, gbc);
// 是否离津
gbc.gridx = 0;
gbc.gridy = 5;
panel.add(new JLabel("是否离津:"), gbc);
gbc.gridx = 1;
JCheckBox leavingCityCheckBox = new JCheckBox();
panel.add(leavingCityCheckBox, gbc);
// 按钮面板
gbc.gridx = 0;
gbc.gridy = 6;
gbc.gridwidth = 2;
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
JButton submitButton = new JButton("提交");
JButton cancelButton = new JButton("取消");
submitButton.addActionListener(e -> {
Date startTime = (Date) startTimeSpinner.getValue();
Date endTime = (Date) endTimeSpinner.getValue();
String location = locationField.getText().trim();
String reasonType = (String) reasonTypeCombo.getSelectedItem();
String reasonDetail = reasonArea.getText().trim();
boolean isLeavingCity = leavingCityCheckBox.isSelected();
if (location.isEmpty()) {
JOptionPane.showMessageDialog(dialog, "请填写外出地址", "提示", JOptionPane.WARNING_MESSAGE);
return;
}
if (reasonDetail.isEmpty()) {
JOptionPane.showMessageDialog(dialog, "请填写详细事由", "提示", JOptionPane.WARNING_MESSAGE);
return;
}
if (startTime.after(endTime)) {
JOptionPane.showMessageDialog(dialog, "开始时间不能晚于结束时间", "提示", JOptionPane.WARNING_MESSAGE);
return;
}
LeaveRequest request = new LeaveRequest();
request.setStudent(currentStudent);
request.setStartTime(startTime);
request.setEndTime(endTime);
request.setLocation(location);
request.setReasonType(reasonType);
request.setReasonDetail(reasonDetail);
request.setLeavingCity(isLeavingCity);
request.setStatus(ApprovalStatus.PENDING);
request.setRequestTime(new Date());
// 计算请假时长小时
double duration = (endTime.getTime() - startTime.getTime()) / (1000.0 * 60 * 60);
request.setDuration(duration);
if (leaveRequestService.submitLeaveRequest(request)) {
loadLeaveRequests();
dialog.dispose();
JOptionPane.showMessageDialog(this, "申请提交成功", "提示", JOptionPane.INFORMATION_MESSAGE);
} else {
JOptionPane.showMessageDialog(this, "申请提交失败,请稍后重试", "错误", JOptionPane.ERROR_MESSAGE);
}
});
cancelButton.addActionListener(e -> dialog.dispose());
buttonPanel.add(submitButton);
buttonPanel.add(cancelButton);
panel.add(buttonPanel, gbc);
dialog.add(panel);
dialog.setVisible(true);
}
private void showRequestDetails(int row) {
Long requestId = (Long) tableModel.getValueAt(row, 0);
RequestDetailDialog dialog = new RequestDetailDialog(this, requestId.intValue(), this::loadLeaveRequests, true);
dialog.setVisible(true);
}
private void loadLeaveRequests() {
tableModel.setRowCount(0);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
List<LeaveRequest> requests = leaveRequestService.getStudentLeaveRequests(currentStudent.getId());
// Calculate total pages
int totalRequests = requests.size();
int totalPages = (totalRequests + PAGE_SIZE - 1) / PAGE_SIZE;
// Update page label
Component[] components = getContentPane().getComponents();
for (Component comp : components) {
if (comp instanceof JPanel) {
JPanel panel = (JPanel) comp;
for (Component innerComp : panel.getComponents()) {
if (innerComp instanceof JPanel && ((JPanel) innerComp).getComponentCount() == 3) {
JPanel pagePanel = (JPanel) innerComp;
JLabel pageLabel = (JLabel) pagePanel.getComponent(1);
pageLabel.setText(currentPage + "/" + totalPages);
break;
}
}
}
}
// Get current page's requests
int fromIndex = (currentPage - 1) * PAGE_SIZE;
int toIndex = Math.min(fromIndex + PAGE_SIZE, totalRequests);
List<LeaveRequest> pageRequests = fromIndex < totalRequests ? requests.subList(fromIndex, toIndex) : requests;
for (LeaveRequest request : pageRequests) {
tableModel.addRow(new Object[]{
Long.valueOf(request.getId()),
request.getStatus().getDescription(),
sdf.format(request.getRequestTime()),
sdf.format(request.getStartTime()),
sdf.format(request.getEndTime()),
request.getReasonDetail()
});
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
// 使用实际学生数据
Student student = ServiceFactory.getStudentService().login("2023208145", "123456");
if (student != null) {
new StudentMainFrame(student).setVisible(true);
} else {
JOptionPane.showMessageDialog(null, "无法加载学生信息", "错误", JOptionPane.ERROR_MESSAGE);
}
} catch (Exception e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null, "系统错误: " + e.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
}
});
}
}

View File

@ -229,7 +229,8 @@ public class TeacherMainFrame extends JFrame {
RequestDetailDialog dialog = new RequestDetailDialog( RequestDetailDialog dialog = new RequestDetailDialog(
this, this,
((Number)tableModel.getValueAt(row, 0)).intValue(), // 获取ID ((Number)tableModel.getValueAt(row, 0)).intValue(), // 获取ID
() -> loadLeaveRequests() // 添加刷新列表的回调 () -> loadLeaveRequests(), // 添加刷新列表的回调
false // 教师视角
); );
dialog.setVisible(true); dialog.setVisible(true);
} }

View File

@ -12,6 +12,7 @@ public class Student {
private String college; // 学院 private String college; // 学院
private String major; // 专业 private String major; // 专业
private boolean isGraduating; // 是否毕业班 private boolean isGraduating; // 是否毕业班
private String password; // 登录密码
// Constructors // Constructors
public Student() {} public Student() {}
@ -26,6 +27,17 @@ public class Student {
this.isGraduating = isGraduating; this.isGraduating = isGraduating;
} }
public Student(String studentId, String name, String className, String contact, String college, String major, boolean isGraduating, String password) {
this.studentId = studentId;
this.name = name;
this.className = className;
this.contact = contact;
this.college = college;
this.major = major;
this.isGraduating = isGraduating;
this.password = password;
}
// Getters and Setters // Getters and Setters
public int getId() { public int getId() {
return id; return id;
@ -90,4 +102,12 @@ public class Student {
public void setGraduating(boolean graduating) { public void setGraduating(boolean graduating) {
isGraduating = graduating; isGraduating = graduating;
} }
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
} }

View File

@ -9,6 +9,7 @@ public class Teacher {
private String name; // 教师姓名 private String name; // 教师姓名
private String department; // 所属部门 private String department; // 所属部门
private String contact; // 联系方式 private String contact; // 联系方式
private String password; // 登录密码
// Constructors // Constructors
public Teacher() {} public Teacher() {}
@ -20,6 +21,14 @@ public class Teacher {
this.contact = contact; this.contact = contact;
} }
public Teacher(String teacherId, String name, String department, String contact, String password) {
this.teacherId = teacherId;
this.name = name;
this.department = department;
this.contact = contact;
this.password = password;
}
// Getters and Setters // Getters and Setters
public int getId() { public int getId() {
return id; return id;
@ -60,4 +69,12 @@ public class Teacher {
public void setContact(String contact) { public void setContact(String contact) {
this.contact = contact; this.contact = contact;
} }
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
} }

View File

@ -7,6 +7,7 @@ import model.Student;
import model.ApprovalStatus; import model.ApprovalStatus;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Calendar;
/** /**
* 请假申请服务类 * 请假申请服务类
@ -24,11 +25,13 @@ public class LeaveRequestService {
// 检查学生是否存在 // 检查学生是否存在
Student student = studentService.getStudentById(request.getStudent().getId()); Student student = studentService.getStudentById(request.getStudent().getId());
if (student == null) { if (student == null) {
System.out.println("提交请假失败学生不存在ID=" + request.getStudent().getId());
return false; return false;
} }
// 检查请假时间是否合理 // 检查请假时间是否合理
if (!isValidLeaveTime(request.getStartTime(), request.getEndTime())) { if (!isValidLeaveTime(request.getStartTime(), request.getEndTime())) {
System.out.println("提交请假失败:请假时间不合理,开始时间=" + request.getStartTime() + ",结束时间=" + request.getEndTime());
return false; return false;
} }
@ -36,7 +39,13 @@ public class LeaveRequestService {
request.setStatus(ApprovalStatus.PENDING); request.setStatus(ApprovalStatus.PENDING);
request.setRequestTime(new Date()); request.setRequestTime(new Date());
return leaveRequestDAO.insert(request) > 0; int result = leaveRequestDAO.insert(request);
if (result == 0) {
System.out.println("提交请假失败:数据库插入失败");
return false;
}
System.out.println("提交请假成功ID=" + request.getId());
return true;
} }
/** /**
@ -96,6 +105,27 @@ public class LeaveRequestService {
return leaveRequestDAO.findById(requestId); return leaveRequestDAO.findById(requestId);
} }
/**
* 撤销请假申请
* @param requestId 请假申请ID
* @return 是否撤销成功
*/
public boolean cancelLeaveRequest(int requestId) {
// 检查请假申请是否存在
LeaveRequest request = leaveRequestDAO.findById(requestId);
if (request == null) {
return false;
}
// 检查是否可以撤销只有待审批状态可以撤销
if (request.getStatus() != ApprovalStatus.PENDING) {
return false;
}
// 删除请假申请
return leaveRequestDAO.deleteById(requestId) > 0;
}
/** /**
* 检查请假时间是否合理 * 检查请假时间是否合理
* @param startTime 开始时间 * @param startTime 开始时间
@ -103,19 +133,28 @@ public class LeaveRequestService {
* @return 是否合理 * @return 是否合理
*/ */
private boolean isValidLeaveTime(Date startTime, Date endTime) { private boolean isValidLeaveTime(Date startTime, Date endTime) {
// 开始时间不能为空 // 开始时间和结束时间不能为空
if (startTime == null || endTime == null) { if (startTime == null || endTime == null) {
return false; return false;
} }
// 结束时间必须在开始时间之后 // 结束时间必须在开始时间之后
if (endTime.before(startTime)) { if (endTime.before(startTime) || endTime.equals(startTime)) {
return false; return false;
} }
// 开始时间不能是过去的时间 // 开始时间不能是过去24小时以前的时间
Date now = new Date(); Calendar cal = Calendar.getInstance();
if (startTime.before(now)) { cal.add(Calendar.HOUR, -24);
Date oneDayAgo = cal.getTime();
if (startTime.before(oneDayAgo)) {
return false;
}
// 请假时长不能超过30天
long durationInDays = (endTime.getTime() - startTime.getTime()) / (1000 * 60 * 60 * 24);
if (durationInDays > 30) {
return false; return false;
} }

View File

@ -95,4 +95,25 @@ public class StudentService {
public List<Student> searchStudentsByName(String name) { public List<Student> searchStudentsByName(String name) {
return studentDAO.findByNameLike(name); return studentDAO.findByNameLike(name);
} }
/**
* 学生登录
* @param studentId 学号
* @param password 密码
* @return 登录成功返回学生信息失败返回null
*/
public Student login(String studentId, String password) {
Student student = studentDAO.findByStudentId(studentId);
System.out.println("Login attempt - StudentID: " + studentId);
System.out.println("Student found: " + (student != null));
if (student != null) {
System.out.println("Stored password: " + student.getPassword());
System.out.println("Input password: " + password);
System.out.println("Password match: " + password.equals(student.getPassword()));
}
if (student != null && password.equals(student.getPassword())) {
return student;
}
return null;
}
} }

View File

@ -95,4 +95,25 @@ public class TeacherService {
public List<Teacher> searchTeachersByName(String name) { public List<Teacher> searchTeachersByName(String name) {
return teacherDAO.findByNameLike(name); return teacherDAO.findByNameLike(name);
} }
/**
* 教师登录
* @param teacherId 教师工号
* @param password 密码
* @return 登录成功返回教师信息失败返回null
*/
public Teacher login(String teacherId, String password) {
Teacher teacher = teacherDAO.findByTeacherId(teacherId);
System.out.println("Login attempt - TeacherID: " + teacherId);
System.out.println("Teacher found: " + (teacher != null));
if (teacher != null) {
System.out.println("Stored password: " + teacher.getPassword());
System.out.println("Input password: " + password);
System.out.println("Password match: " + password.equals(teacher.getPassword()));
}
if (teacher != null && password.equals(teacher.getPassword())) {
return teacher;
}
return null;
}
} }