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
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();
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(6, student.getMajor());
stmt.setBoolean(7, student.isGraduating());
stmt.setString(8, student.getPassword());
int affectedRows = stmt.executeUpdate();
if (affectedRows == 0) {
@ -60,7 +61,7 @@ public class StudentDAOImpl implements StudentDAO {
@Override
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();
PreparedStatement stmt = conn.prepareStatement(sql)) {
@ -71,7 +72,8 @@ public class StudentDAOImpl implements StudentDAO {
stmt.setString(5, student.getCollege());
stmt.setString(6, student.getMajor());
stmt.setBoolean(7, student.isGraduating());
stmt.setInt(8, student.getId());
stmt.setString(8, student.getPassword());
stmt.setInt(9, student.getId());
return stmt.executeUpdate();
} catch (SQLException e) {
@ -184,6 +186,7 @@ public class StudentDAOImpl implements StudentDAO {
student.setCollege(rs.getString("college"));
student.setMajor(rs.getString("major"));
student.setGraduating(rs.getBoolean("is_graduating"));
student.setPassword(rs.getString("password"));
return student;
}
}

View File

@ -15,7 +15,7 @@ public class TeacherDAOImpl implements TeacherDAO {
@Override
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();
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(3, teacher.getDepartment());
stmt.setString(4, teacher.getContact());
stmt.setString(5, teacher.getPassword());
int affectedRows = stmt.executeUpdate();
if (affectedRows == 0) {
@ -57,7 +58,7 @@ public class TeacherDAOImpl implements TeacherDAO {
@Override
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();
PreparedStatement stmt = conn.prepareStatement(sql)) {
@ -65,7 +66,8 @@ public class TeacherDAOImpl implements TeacherDAO {
stmt.setString(2, teacher.getName());
stmt.setString(3, teacher.getDepartment());
stmt.setString(4, teacher.getContact());
stmt.setInt(5, teacher.getId());
stmt.setString(5, teacher.getPassword());
stmt.setInt(6, teacher.getId());
return stmt.executeUpdate();
} catch (SQLException e) {
@ -175,6 +177,7 @@ public class TeacherDAOImpl implements TeacherDAO {
teacher.setName(rs.getString("name"));
teacher.setDepartment(rs.getString("department"));
teacher.setContact(rs.getString("contact"));
teacher.setPassword(rs.getString("password"));
return teacher;
}
}

View File

@ -1,91 +1,144 @@
package gui;
import model.Student;
import model.Teacher;
import service.StudentService;
import service.TeacherService;
import service.ServiceFactory;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
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 {
private JComboBox<String> userTypeComboBox;
private JTextField idField;
private JPasswordField passwordField;
private JButton loginButton;
private final StudentService studentService = ServiceFactory.getStudentService();
private final TeacherService teacherService = ServiceFactory.getTeacherService();
public LoginFrame() {
setTitle("登录");
setSize(300, 200);
setTitle("平安校园 - 登录");
setSize(350, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLocationRelativeTo(null);
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(4, 2));
// 创建主面板使用BorderLayout
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[]{"学生", "教师"});
panel.add(userTypeComboBox);
userTypeComboBox.setFont(new Font("微软雅黑", Font.PLAIN, 14));
formPanel.add(userTypeComboBox, gbc);
panel.add(new JLabel("ID:"));
idField = new JTextField();
panel.add(idField);
// ID输入框
gbc.gridx = 0;
gbc.gridy = 1;
JLabel idLabel = new JLabel("ID:");
idLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
formPanel.add(idLabel, gbc);
panel.add(new JLabel("密码:"));
passwordField = new JPasswordField();
panel.add(passwordField);
gbc.gridx = 1;
idField = new JTextField(20);
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("登录");
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
public void actionPerformed(ActionEvent e) {
handleLogin();
}
});
// 添加事件监听
loginButton.addActionListener(e -> handleLogin());
add(panel);
// 组装界面
mainPanel.add(titlePanel, BorderLayout.NORTH);
mainPanel.add(formPanel, BorderLayout.CENTER);
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
add(mainPanel);
}
private void handleLogin() {
String userType = (String) userTypeComboBox.getSelectedItem();
String id = idField.getText();
String id = idField.getText().trim();
String password = new String(passwordField.getPassword());
String tableName = "学生".equals(userType) ? "students" : "teachers";
String idColumnName = "学生".equals(userType) ? "student_id" : "teacher_id";
String sql = "SELECT * FROM " + tableName + " WHERE " + idColumnName + " = ? AND password = ?";
if (id.isEmpty() || password.isEmpty()) {
JOptionPane.showMessageDialog(this, "请输入ID和密码", "提示", JOptionPane.WARNING_MESSAGE);
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();
} 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) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
SwingUtilities.invokeLater(() -> {
LoginFrame loginFrame = new LoginFrame();
loginFrame.setVisible(true);

View File

@ -14,11 +14,13 @@ public class RequestDetailDialog extends JDialog {
private final LeaveRequestService leaveRequestService;
private LeaveRequest currentRequest;
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);
this.leaveRequestService = ServiceFactory.getLeaveRequestService();
this.onApprovalComplete = onApprovalComplete;
this.isStudent = isStudent;
// 根据ID获取请假信息
this.currentRequest = leaveRequestService.getLeaveRequestById(requestId);
@ -78,130 +80,155 @@ public class RequestDetailDialog extends JDialog {
// 审批按钮
JPanel actionButtonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 10));
JButton approveButton = new JButton("通过");
JButton rejectButton = new JButton("驳回");
// 如果已经审批过禁用按钮
if (currentRequest.getStatus() != ApprovalStatus.PENDING) {
approveButton.setEnabled(false);
rejectButton.setEnabled(false);
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 rejectButton = new JButton("驳回");
// 如果已经审批过禁用按钮
if (currentRequest.getStatus() != ApprovalStatus.PENDING) {
approveButton.setEnabled(false);
rejectButton.setEnabled(false);
}
approveButton.setPreferredSize(new Dimension(100, 30));
rejectButton.setPreferredSize(new Dimension(100, 30));
// 设置按钮样式
approveButton.setBackground(new Color(39, 174, 96));
rejectButton.setBackground(new Color(231, 76, 60));
actionButtonPanel.add(approveButton);
actionButtonPanel.add(rejectButton);
// 添加教师审批按钮的事件监听
approveButton.addActionListener(e -> {
// 创建一个自定义对话框
JDialog approveDialog = new JDialog(this, "审批意见", true);
approveDialog.setLayout(new BorderLayout());
approveDialog.setSize(300, 200);
approveDialog.setLocationRelativeTo(this);
JPanel inputPanel = new JPanel(new BorderLayout(10, 10));
inputPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JLabel label = new JLabel("请输入审批意见:");
JTextArea commentArea = new JTextArea(4, 20);
commentArea.setLineWrap(true);
commentArea.setWrapStyleWord(true);
commentArea.setText("同意");
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
JButton confirmButton = new JButton("确定");
JButton cancelButton = new JButton("取消");
confirmButton.addActionListener(event -> {
String comment = commentArea.getText().trim();
if (!comment.isEmpty()) {
leaveRequestService.approveLeaveRequest(
currentRequest.getId(),
ApprovalStatus.APPROVED,
comment
);
approveDialog.dispose();
dispose();
if (onApprovalComplete != null) {
onApprovalComplete.run();
}
}
});
cancelButton.addActionListener(event -> approveDialog.dispose());
buttonPanel.add(confirmButton);
buttonPanel.add(cancelButton);
inputPanel.add(label, BorderLayout.NORTH);
inputPanel.add(new JScrollPane(commentArea), BorderLayout.CENTER);
inputPanel.add(buttonPanel, BorderLayout.SOUTH);
approveDialog.add(inputPanel);
approveDialog.setVisible(true);
});
rejectButton.addActionListener(e -> {
// 创建一个自定义对话框
JDialog rejectDialog = new JDialog(this, "驳回原因", true);
rejectDialog.setLayout(new BorderLayout());
rejectDialog.setSize(300, 200);
rejectDialog.setLocationRelativeTo(this);
JPanel inputPanel = new JPanel(new BorderLayout(10, 10));
inputPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JLabel label = new JLabel("请输入驳回原因:");
JTextArea commentArea = new JTextArea(4, 20);
commentArea.setLineWrap(true);
commentArea.setWrapStyleWord(true);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
JButton confirmButton = new JButton("确定");
JButton cancelButton = new JButton("取消");
confirmButton.addActionListener(event -> {
String comment = commentArea.getText().trim();
if (!comment.isEmpty()) {
leaveRequestService.approveLeaveRequest(
currentRequest.getId(),
ApprovalStatus.REJECTED,
comment
);
rejectDialog.dispose();
dispose();
if (onApprovalComplete != null) {
onApprovalComplete.run();
}
}
});
cancelButton.addActionListener(event -> rejectDialog.dispose());
buttonPanel.add(confirmButton);
buttonPanel.add(cancelButton);
inputPanel.add(label, BorderLayout.NORTH);
inputPanel.add(new JScrollPane(commentArea), BorderLayout.CENTER);
inputPanel.add(buttonPanel, BorderLayout.SOUTH);
rejectDialog.add(inputPanel);
rejectDialog.setVisible(true);
});
}
approveButton.setPreferredSize(new Dimension(100, 30));
rejectButton.setPreferredSize(new Dimension(100, 30));
// 设置按钮样式
approveButton.setBackground(new Color(39, 174, 96));
// approveButton.setForeground(Color.WHITE);
rejectButton.setBackground(new Color(231, 76, 60));
// rejectButton.setForeground(Color.WHITE);
actionButtonPanel.add(approveButton);
actionButtonPanel.add(rejectButton);
// 添加按钮面板
gbc.insets = new Insets(20, 10, 10, 10);
mainPanel.add(actionButtonPanel, gbc);
// 添加事件监听
approveButton.addActionListener(e -> {
// 创建一个自定义对话框
JDialog approveDialog = new JDialog(this, "审批意见", true);
approveDialog.setLayout(new BorderLayout());
approveDialog.setSize(300, 200);
approveDialog.setLocationRelativeTo(this);
JPanel inputPanel = new JPanel(new BorderLayout(10, 10));
inputPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JLabel label = new JLabel("请输入审批意见:");
JTextArea commentArea = new JTextArea(4, 20);
commentArea.setLineWrap(true);
commentArea.setWrapStyleWord(true);
commentArea.setText("同意");
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
JButton confirmButton = new JButton("确定");
JButton cancelButton = new JButton("取消");
confirmButton.addActionListener(event -> {
String comment = commentArea.getText().trim();
if (!comment.isEmpty()) {
leaveRequestService.approveLeaveRequest(
currentRequest.getId(),
ApprovalStatus.APPROVED,
comment
);
approveDialog.dispose();
dispose();
if (onApprovalComplete != null) {
onApprovalComplete.run();
}
}
});
cancelButton.addActionListener(event -> approveDialog.dispose());
buttonPanel.add(confirmButton);
buttonPanel.add(cancelButton);
inputPanel.add(label, BorderLayout.NORTH);
inputPanel.add(new JScrollPane(commentArea), BorderLayout.CENTER);
inputPanel.add(buttonPanel, BorderLayout.SOUTH);
approveDialog.add(inputPanel);
approveDialog.setVisible(true);
});
rejectButton.addActionListener(e -> {
// 创建一个自定义对话框
JDialog rejectDialog = new JDialog(this, "驳回原因", true);
rejectDialog.setLayout(new BorderLayout());
rejectDialog.setSize(300, 200);
rejectDialog.setLocationRelativeTo(this);
JPanel inputPanel = new JPanel(new BorderLayout(10, 10));
inputPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
JLabel label = new JLabel("请输入驳回原因:");
JTextArea commentArea = new JTextArea(4, 20);
commentArea.setLineWrap(true);
commentArea.setWrapStyleWord(true);
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
JButton confirmButton = new JButton("确定");
JButton cancelButton = new JButton("取消");
confirmButton.addActionListener(event -> {
String comment = commentArea.getText().trim();
if (!comment.isEmpty()) {
leaveRequestService.approveLeaveRequest(
currentRequest.getId(),
ApprovalStatus.REJECTED,
comment
);
rejectDialog.dispose();
dispose();
if (onApprovalComplete != null) {
onApprovalComplete.run();
}
}
});
cancelButton.addActionListener(event -> rejectDialog.dispose());
buttonPanel.add(confirmButton);
buttonPanel.add(cancelButton);
inputPanel.add(label, BorderLayout.NORTH);
inputPanel.add(new JScrollPane(commentArea), BorderLayout.CENTER);
inputPanel.add(buttonPanel, BorderLayout.SOUTH);
rejectDialog.add(inputPanel);
rejectDialog.setVisible(true);
});
// 添加滚动面板
JScrollPane scrollPane = new JScrollPane(mainPanel);
scrollPane.setBorder(null);

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(
this,
((Number)tableModel.getValueAt(row, 0)).intValue(), // 获取ID
() -> loadLeaveRequests() // 添加刷新列表的回调
() -> loadLeaveRequests(), // 添加刷新列表的回调
false // 教师视角
);
dialog.setVisible(true);
}

View File

@ -12,6 +12,7 @@ public class Student {
private String college; // 学院
private String major; // 专业
private boolean isGraduating; // 是否毕业班
private String password; // 登录密码
// Constructors
public Student() {}
@ -26,6 +27,17 @@ public class Student {
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
public int getId() {
return id;
@ -90,4 +102,12 @@ public class Student {
public void setGraduating(boolean 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 department; // 所属部门
private String contact; // 联系方式
private String password; // 登录密码
// Constructors
public Teacher() {}
@ -20,6 +21,14 @@ public class Teacher {
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
public int getId() {
return id;
@ -60,4 +69,12 @@ public class Teacher {
public void setContact(String 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 java.util.Date;
import java.util.List;
import java.util.Calendar;
/**
* 请假申请服务类
@ -24,11 +25,13 @@ public class LeaveRequestService {
// 检查学生是否存在
Student student = studentService.getStudentById(request.getStudent().getId());
if (student == null) {
System.out.println("提交请假失败学生不存在ID=" + request.getStudent().getId());
return false;
}
// 检查请假时间是否合理
if (!isValidLeaveTime(request.getStartTime(), request.getEndTime())) {
System.out.println("提交请假失败:请假时间不合理,开始时间=" + request.getStartTime() + ",结束时间=" + request.getEndTime());
return false;
}
@ -36,7 +39,13 @@ public class LeaveRequestService {
request.setStatus(ApprovalStatus.PENDING);
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);
}
/**
* 撤销请假申请
* @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 开始时间
@ -103,19 +133,28 @@ public class LeaveRequestService {
* @return 是否合理
*/
private boolean isValidLeaveTime(Date startTime, Date endTime) {
// 开始时间不能为空
// 开始时间和结束时间不能为空
if (startTime == null || endTime == null) {
return false;
}
// 结束时间必须在开始时间之后
if (endTime.before(startTime)) {
if (endTime.before(startTime) || endTime.equals(startTime)) {
return false;
}
// 开始时间不能是过去的时间
Date now = new Date();
if (startTime.before(now)) {
// 开始时间不能是过去24小时以前的时间
Calendar cal = Calendar.getInstance();
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;
}

View File

@ -95,4 +95,25 @@ public class StudentService {
public List<Student> searchStudentsByName(String 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) {
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;
}
}