commit
8bfdda3cd5
199 changed files with 17149 additions and 0 deletions
@ -0,0 +1,67 @@ |
|||||
|
# ========================================================================= |
||||
|
# 1. Java 编译与运行环境产生的垃圾文件(必须忽略) |
||||
|
# ========================================================================= |
||||
|
*.class |
||||
|
*.log |
||||
|
*.ctxt |
||||
|
*.jar |
||||
|
*.war |
||||
|
*.nar |
||||
|
*.ear |
||||
|
*.zip |
||||
|
*.tar.gz |
||||
|
*.rar |
||||
|
|
||||
|
# ========================================================================= |
||||
|
# 2. 构建工具及服务器临时目录 |
||||
|
# ========================================================================= |
||||
|
# 如果你使用的是 Maven 构建 |
||||
|
target/ |
||||
|
pom.xml.tag |
||||
|
pom.xml.releaseBackup |
||||
|
pom.xml.nextDevelopmentVersion |
||||
|
pom.xml.releaseProperties |
||||
|
pom.xml.used |
||||
|
release.properties |
||||
|
dependency-reduced-pom.xml |
||||
|
|
||||
|
# 如果是普通的 Web 项目,忽略 Tomcat 或 Jetty 的临时和部署目录 |
||||
|
bin/ |
||||
|
build/ |
||||
|
dist/ |
||||
|
out/ |
||||
|
.tomcat/ |
||||
|
WEB-INF/classes/ |
||||
|
|
||||
|
# ========================================================================= |
||||
|
# 3. IDE(集成开发环境)个性化配置文件(防止与同学冲突) |
||||
|
# ========================================================================= |
||||
|
# IntelliJ IDEA |
||||
|
.idea/ |
||||
|
*.iws |
||||
|
*.iml |
||||
|
*.ipr |
||||
|
out/ |
||||
|
|
||||
|
# Eclipse |
||||
|
.metadata/ |
||||
|
.classpath |
||||
|
.project |
||||
|
.settings/ |
||||
|
*.launch |
||||
|
|
||||
|
# VS Code (如果你用 VS Code 写前端/后端) |
||||
|
.vscode/ |
||||
|
|
||||
|
# ========================================================================= |
||||
|
# 4. 操作系统及前端打包临时文件 |
||||
|
# ========================================================================= |
||||
|
# 系统文件 |
||||
|
Thumbs.db |
||||
|
ehthumbs.db |
||||
|
Desktop.ini |
||||
|
.DS_Store |
||||
|
|
||||
|
# 前端可能产生的 node 依赖(如果有使用 npm) |
||||
|
node_modules/ |
||||
|
/dist/ |
||||
@ -0,0 +1,9 @@ |
|||||
|
MIT License |
||||
|
|
||||
|
Copyright (c) <year> <copyright holders> |
||||
|
|
||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
||||
|
|
||||
|
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. |
||||
|
|
||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||||
@ -0,0 +1,119 @@ |
|||||
|
<<<<<<< HEAD |
||||
|
# 学生信息管理系统 v2.0 |
||||
|
|
||||
|
基于 **JSP + Servlet + JavaBean + JDBC + DAO + Service** 架构的全功能学生信息管理系统。 |
||||
|
|
||||
|
## 技术栈 |
||||
|
|
||||
|
| 层次 | 技术 | |
||||
|
|------|------| |
||||
|
| 表现层 | JSP、EL、JSTL、jQuery、Ajax、ECharts | |
||||
|
| 控制层 | Servlet(@WebServlet)、Filter、Listener | |
||||
|
| 业务层 | Service | |
||||
|
| 数据层 | DAO、JDBC、HikariCP 连接池 | |
||||
|
| 工具 | Gson、Apache POI、Commons FileUpload | |
||||
|
| 数据库 | MySQL 8.x | |
||||
|
|
||||
|
## 已实现扩展功能(37/37) |
||||
|
|
||||
|
### 模块 A — 安全与账户 |
||||
|
- [x] A-01 密码 SHA-256 加密存储 |
||||
|
- [x] A-02 登录失败 5 次锁定 30 分钟 |
||||
|
- [x] A-03 找回密码(演示模式验证码) |
||||
|
- [x] A-04 记住我 / 7 天自动登录 |
||||
|
- [x] A-05 在线用户管理与强制下线 |
||||
|
- [x] A-06 三级角色(学生/教师/管理员) |
||||
|
|
||||
|
### 模块 B — 学生档案 |
||||
|
- [x] B-01 院系 / 专业 / 班级 |
||||
|
- [x] B-02 学号自动生成 |
||||
|
- [x] B-03 学生状态管理 |
||||
|
- [x] B-04 头像上传 |
||||
|
- [x] B-05 学生详情页 |
||||
|
- [x] B-06 Excel 导出 |
||||
|
- [x] B-07 高级组合搜索 |
||||
|
|
||||
|
### 模块 C — 课程与成绩 |
||||
|
- [x] C-01 课程管理 CRUD |
||||
|
- [x] C-02 学生选课 |
||||
|
- [x] C-03 成绩录入 |
||||
|
- [x] C-04 成绩查询 + GPA |
||||
|
- [x] C-05 成绩统计报表 |
||||
|
- [x] C-06 个人课表 |
||||
|
|
||||
|
### 模块 D — 考勤与请假 |
||||
|
- [x] D-01 考勤记录 |
||||
|
- [x] D-02 请假申请 |
||||
|
- [x] D-03 请假审批 |
||||
|
- [x] D-04 考勤统计 |
||||
|
|
||||
|
### 模块 E — 通知与日志 |
||||
|
- [x] E-01 系统公告 |
||||
|
- [x] E-02 站内消息 |
||||
|
- [x] E-03 操作日志 |
||||
|
- [x] E-04 登录日志 |
||||
|
|
||||
|
### 模块 F — 数据统计 |
||||
|
- [x] F-01 管理员 Dashboard |
||||
|
- [x] F-02 ECharts 图表 |
||||
|
- [x] F-03 数据大屏 |
||||
|
|
||||
|
### 模块 G — 流程审批 |
||||
|
- [x] G-01 信息变更审批 |
||||
|
- [x] G-02 注册审核 |
||||
|
- [x] G-03 批量导入预览确认 |
||||
|
|
||||
|
### 模块 H — 工程化 |
||||
|
- [x] H-01 Service 业务层 |
||||
|
- [x] H-02 HikariCP 连接池 |
||||
|
- [x] H-03 统一 JSON API(/api/stats 等) |
||||
|
- [x] H-04 JSP 公共片段(jspf) |
||||
|
|
||||
|
## 测试账号 |
||||
|
|
||||
|
| 角色 | 用户名 | 密码 | 登录后跳转 | |
||||
|
|------|--------|------|-----------| |
||||
|
| 管理员 | admin | admin123 | /admin/dashboard | |
||||
|
| 教师 | teacher | teacher123 | /teacher/home | |
||||
|
| 学生 | zhangsan | user123 | /user/profile | |
||||
|
|
||||
|
## 快速部署 |
||||
|
|
||||
|
```bash |
||||
|
# 1. 重新初始化数据库(v2 表结构有变化,需重建) |
||||
|
mysql -u root -p < src/main/resources/db_init.sql |
||||
|
|
||||
|
# 2. 修改 db.properties |
||||
|
|
||||
|
# 3. 打包 |
||||
|
mvn clean package |
||||
|
|
||||
|
# 4. 部署 WAR 到 Tomcat,访问 |
||||
|
http://localhost:8080/student-management/ |
||||
|
``` |
||||
|
|
||||
|
## 主要功能入口 |
||||
|
|
||||
|
| 角色 | 功能 | 路径 | |
||||
|
|------|------|------| |
||||
|
| 管理员 | 仪表盘 | /admin/dashboard | |
||||
|
| 管理员 | 用户管理 | /admin/userList | |
||||
|
| 管理员 | 注册审核 | /admin/regAudit | |
||||
|
| 管理员 | 变更审批 | /admin/changeAudit | |
||||
|
| 管理员 | 组织管理 | /admin/org | |
||||
|
| 管理员 | 课程管理 | /admin/courseList | |
||||
|
| 管理员 | 数据大屏 | /admin/bigscreen | |
||||
|
| 教师 | 工作台 | /teacher/home | |
||||
|
| 学生 | 在线选课 | /user/enroll | |
||||
|
| 学生 | 我的成绩 | /user/myScores | |
||||
|
| 学生 | 请假申请 | /user/leaveApply | |
||||
|
|
||||
|
## 文档 |
||||
|
|
||||
|
- [部署与常见问题](docs/DEPLOYMENT.md) |
||||
|
- [扩展任务清单](docs/EXTENSION_TASKS.md) |
||||
|
======= |
||||
|
# student-management |
||||
|
|
||||
|
学生管理系统作业 |
||||
|
>>>>>>> 199973ecc1a80cb639a57f856f6f18735ccff863 |
||||
@ -0,0 +1,571 @@ |
|||||
|
# 部署与常见问题手册 |
||||
|
|
||||
|
本文档整理了项目部署过程中遇到的典型错误及解决方案,分别提供 **Windows** 和 **Mac M1(Apple Silicon)** 两套操作说明。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 目录 |
||||
|
|
||||
|
- [环境要求](#环境要求) |
||||
|
- [通用部署流程](#通用部署流程) |
||||
|
- [Windows 部署指南](#windows-部署指南) |
||||
|
- [Mac M1 部署指南](#mac-m1-部署指南) |
||||
|
- [常见错误与解决方案](#常见错误与解决方案) |
||||
|
- [Maven 推荐配置](#maven-推荐配置) |
||||
|
- [更新部署流程](#更新部署流程) |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 环境要求 |
||||
|
|
||||
|
| 组件 | 版本要求 | 说明 | |
||||
|
|------|----------|------| |
||||
|
| JDK | 1.8+(推荐 8 或 11) | Tomcat 9 支持 Java 8–21 | |
||||
|
| Maven | 3.6+ | 构建 WAR 包 | |
||||
|
| MySQL | 8.x | 数据存储 | |
||||
|
| Tomcat | 9.x | Web 容器 | |
||||
|
|
||||
|
**Mac M1 注意**:请安装 **ARM64(aarch64)** 版本的 JDK 和 Tomcat,或通过 Homebrew 安装(会自动选择正确架构)。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 通用部署流程 |
||||
|
|
||||
|
无论 Windows 还是 Mac,基本步骤一致: |
||||
|
|
||||
|
``` |
||||
|
1. 初始化 MySQL 数据库 |
||||
|
2. 修改 db.properties 数据库连接配置 |
||||
|
3. mvn clean package 打包 |
||||
|
4. 复制 WAR 到 Tomcat/webapps |
||||
|
5. 启动 Tomcat |
||||
|
6. 浏览器访问 http://localhost:8080/student-management/ |
||||
|
``` |
||||
|
|
||||
|
### 1. 初始化数据库 |
||||
|
|
||||
|
```bash |
||||
|
mysql -u root -p < src/main/resources/db_init.sql |
||||
|
``` |
||||
|
|
||||
|
### 2. 修改数据库配置 |
||||
|
|
||||
|
编辑 `src/main/resources/db.properties`: |
||||
|
|
||||
|
```properties |
||||
|
jdbc.driver=com.mysql.cj.jdbc.Driver |
||||
|
jdbc.url=jdbc:mysql://localhost:3306/student_db?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false |
||||
|
jdbc.username=root |
||||
|
jdbc.password=你的密码 |
||||
|
``` |
||||
|
|
||||
|
> 修改后需重新执行 `mvn clean package`。 |
||||
|
|
||||
|
### 3. 编译打包 |
||||
|
|
||||
|
```bash |
||||
|
mvn clean package |
||||
|
``` |
||||
|
|
||||
|
成功后 WAR 包路径: |
||||
|
|
||||
|
``` |
||||
|
target/student-management.war |
||||
|
``` |
||||
|
|
||||
|
### 4. 访问地址 |
||||
|
|
||||
|
``` |
||||
|
http://localhost:8080/student-management/ |
||||
|
``` |
||||
|
|
||||
|
### 5. 测试账号 |
||||
|
|
||||
|
| 角色 | 用户名 | 密码 | |
||||
|
|------|--------|------| |
||||
|
| 管理员 | admin | admin123 | |
||||
|
| 一般用户 | zhangsan | user123 | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## Windows 部署指南 |
||||
|
|
||||
|
### 安装 JDK 并配置 JAVA_HOME |
||||
|
|
||||
|
1. 安装 JDK(如 `C:\Program Files\Java\jdk-21`) |
||||
|
2. `Win + R` → 输入 `sysdm.cpl` → **高级** → **环境变量** |
||||
|
3. 新建系统变量: |
||||
|
- 变量名:`JAVA_HOME` |
||||
|
- 变量值:`C:\Program Files\Java\jdk-21`(按实际路径填写) |
||||
|
4. 编辑 `Path`,新增:`%JAVA_HOME%\bin` |
||||
|
5. 新开 cmd 验证: |
||||
|
|
||||
|
```cmd |
||||
|
echo %JAVA_HOME% |
||||
|
java -version |
||||
|
``` |
||||
|
|
||||
|
### 安装 Tomcat |
||||
|
|
||||
|
1. 下载 Tomcat 9:https://tomcat.apache.org/download-90.cgi |
||||
|
2. 选择 **64-bit Windows zip**,解压到如 `D:\apache-tomcat-9.0.98` |
||||
|
|
||||
|
### 部署 WAR |
||||
|
|
||||
|
**方法一:资源管理器** |
||||
|
|
||||
|
1. 复制 `target\student-management.war` |
||||
|
2. 粘贴到 `D:\apache-tomcat-9.0.98\webapps\` |
||||
|
|
||||
|
**方法二:PowerShell** |
||||
|
|
||||
|
```powershell |
||||
|
Copy-Item "D:\codefiles\javaweb-homework\student-management\target\student-management.war" ` |
||||
|
"D:\apache-tomcat-9.0.98\webapps\" |
||||
|
``` |
||||
|
|
||||
|
### 启动 / 停止 Tomcat |
||||
|
|
||||
|
```cmd |
||||
|
:: 启动(需先设置 JAVA_HOME,见下方临时方案) |
||||
|
D:\apache-tomcat-9.0.98\bin\startup.bat |
||||
|
|
||||
|
:: 停止 |
||||
|
D:\apache-tomcat-9.0.98\bin\shutdown.bat |
||||
|
``` |
||||
|
|
||||
|
**临时设置 JAVA_HOME 后启动(未配环境变量时):** |
||||
|
|
||||
|
```cmd |
||||
|
set JAVA_HOME=C:\Program Files\Java\jdk-21 |
||||
|
set JRE_HOME=C:\Program Files\Java\jdk-21 |
||||
|
cd /d D:\apache-tomcat-9.0.98\bin |
||||
|
startup.bat |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## Mac M1 部署指南 |
||||
|
|
||||
|
### 安装依赖(Homebrew) |
||||
|
|
||||
|
```bash |
||||
|
# 安装 Homebrew(如未安装) |
||||
|
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" |
||||
|
|
||||
|
# 安装 JDK(ARM64 原生版本) |
||||
|
brew install openjdk@17 |
||||
|
|
||||
|
# 配置 JAVA_HOME(Apple Silicon 路径) |
||||
|
echo 'export JAVA_HOME="/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home"' >> ~/.zshrc |
||||
|
echo 'export PATH="$JAVA_HOME/bin:$PATH"' >> ~/.zshrc |
||||
|
source ~/.zshrc |
||||
|
|
||||
|
# 验证 |
||||
|
java -version |
||||
|
echo $JAVA_HOME |
||||
|
|
||||
|
# 安装 Maven |
||||
|
brew install maven |
||||
|
|
||||
|
# 安装 MySQL |
||||
|
brew install mysql |
||||
|
brew services start mysql |
||||
|
|
||||
|
# 安装 Tomcat 9 |
||||
|
brew install tomcat@9 |
||||
|
``` |
||||
|
|
||||
|
> **Intel Mac** 用户:Homebrew 前缀为 `/usr/local` 而非 `/opt/homebrew`,JDK 路径类似 `/usr/local/opt/openjdk@17/...`。 |
||||
|
|
||||
|
### 初始化数据库(Mac) |
||||
|
|
||||
|
```bash |
||||
|
# 首次安装 MySQL 后设置 root 密码(按提示操作) |
||||
|
mysql_secure_installation |
||||
|
|
||||
|
# 导入数据 |
||||
|
cd /path/to/student-management |
||||
|
mysql -u root -p < src/main/resources/db_init.sql |
||||
|
``` |
||||
|
|
||||
|
### 编译打包(Mac) |
||||
|
|
||||
|
```bash |
||||
|
cd /path/to/student-management |
||||
|
mvn clean package |
||||
|
``` |
||||
|
|
||||
|
### 部署 WAR 到 Tomcat(Mac) |
||||
|
|
||||
|
**Homebrew 安装的 Tomcat 9:** |
||||
|
|
||||
|
```bash |
||||
|
# Tomcat 目录(M1 默认) |
||||
|
TOMCAT_HOME="/opt/homebrew/opt/tomcat@9/libexec" |
||||
|
|
||||
|
# 复制 WAR |
||||
|
cp target/student-management.war "$TOMCAT_HOME/webapps/" |
||||
|
|
||||
|
# 启动 Tomcat |
||||
|
brew services start tomcat@9 |
||||
|
|
||||
|
# 停止 Tomcat |
||||
|
brew services stop tomcat@9 |
||||
|
|
||||
|
# 查看日志 |
||||
|
tail -f "$TOMCAT_HOME/logs/catalina.out" |
||||
|
``` |
||||
|
|
||||
|
**手动解压的 Tomcat:** |
||||
|
|
||||
|
```bash |
||||
|
TOMCAT_HOME="$HOME/apache-tomcat-9.0.98" |
||||
|
|
||||
|
cp target/student-management.war "$TOMCAT_HOME/webapps/" |
||||
|
"$TOMCAT_HOME/bin/startup.sh" |
||||
|
``` |
||||
|
|
||||
|
### Mac 访问地址 |
||||
|
|
||||
|
``` |
||||
|
http://localhost:8080/student-management/ |
||||
|
``` |
||||
|
|
||||
|
Homebrew 版 Tomcat 9 默认端口为 **8080**。若端口冲突,编辑: |
||||
|
|
||||
|
```bash |
||||
|
# M1 |
||||
|
/opt/homebrew/opt/tomcat@9/libexec/conf/server.xml |
||||
|
|
||||
|
# 修改 <Connector port="8080" ...> 为其他端口 |
||||
|
``` |
||||
|
|
||||
|
### Mac 常用命令对照 |
||||
|
|
||||
|
| 操作 | Windows | Mac M1 | |
||||
|
|------|---------|--------| |
||||
|
| 环境变量文件 | 系统设置 / cmd `set` | `~/.zshrc` | |
||||
|
| 启动 Tomcat | `startup.bat` | `startup.sh` 或 `brew services start tomcat@9` | |
||||
|
| 停止 Tomcat | `shutdown.bat` | `shutdown.sh` 或 `brew services stop tomcat@9` | |
||||
|
| 复制 WAR | `Copy-Item` / 资源管理器 | `cp` | |
||||
|
| Maven 配置 | `C:\Users\用户名\.m2\settings.xml` | `~/.m2/settings.xml` | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 常见错误与解决方案 |
||||
|
|
||||
|
### 错误 1:Maven 代理连接失败 |
||||
|
|
||||
|
**报错信息:** |
||||
|
|
||||
|
``` |
||||
|
Connect to 127.0.0.1:7890 failed: Connection refused: no further information |
||||
|
Could not transfer artifact ... from/to central (https://repo.maven.apache.org/maven2) |
||||
|
``` |
||||
|
|
||||
|
**原因:** |
||||
|
|
||||
|
`~/.m2/settings.xml`(Windows:`C:\Users\用户名\.m2\settings.xml`)中配置了 HTTP 代理 `127.0.0.1:7890`(Clash、V2Ray 等),但代理软件未启动。 |
||||
|
|
||||
|
**解决方案(二选一):** |
||||
|
|
||||
|
| 方案 | 操作 | |
||||
|
|------|------| |
||||
|
| A. 不使用代理 | 将 settings.xml 中 proxy 的 `<active>true</active>` 改为 `<active>false</active>` | |
||||
|
| B. 使用代理 | 先启动 Clash 等代理软件,保持 `<active>true</active>` | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 错误 2:依赖下载失败被缓存,无法重试 |
||||
|
|
||||
|
**报错信息:** |
||||
|
|
||||
|
``` |
||||
|
failed to transfer from https://repo.maven.apache.org/maven2 during a previous attempt. |
||||
|
This failure was cached in the local repository and resolution is not reattempted |
||||
|
until the update interval of central has elapsed or updates are forced. |
||||
|
|
||||
|
未解析的依赖项: 'javax.servlet:javax.servlet-api:jar:4.0.1' |
||||
|
未解析的依赖项: 'mysql:mysql-connector-java:jar:8.0.33' |
||||
|
... |
||||
|
``` |
||||
|
|
||||
|
**原因:** |
||||
|
|
||||
|
错误 1 导致的下载失败被 Maven 写入本地仓库缓存(`.lastUpdated` 文件),后续不会自动重试。 |
||||
|
|
||||
|
**解决方案:** |
||||
|
|
||||
|
**步骤 1 — 清理失败缓存** |
||||
|
|
||||
|
Windows PowerShell: |
||||
|
|
||||
|
```powershell |
||||
|
$paths = @( |
||||
|
"$env:USERPROFILE\.m2\repository\javax\servlet\javax.servlet-api\4.0.1", |
||||
|
"$env:USERPROFILE\.m2\repository\javax\servlet\jsp\javax.servlet.jsp-api\2.3.3", |
||||
|
"$env:USERPROFILE\.m2\repository\javax\servlet\jstl\1.2", |
||||
|
"$env:USERPROFILE\.m2\repository\mysql\mysql-connector-java\8.0.33", |
||||
|
"$env:USERPROFILE\.m2\repository\commons-fileupload\commons-fileupload\1.5", |
||||
|
"$env:USERPROFILE\.m2\repository\commons-io\commons-io\2.11.0" |
||||
|
) |
||||
|
foreach ($p in $paths) { if (Test-Path $p) { Remove-Item $p -Recurse -Force } } |
||||
|
Get-ChildItem "$env:USERPROFILE\.m2\repository" -Recurse -Filter "*.lastUpdated" | Remove-Item -Force |
||||
|
``` |
||||
|
|
||||
|
Mac / Linux: |
||||
|
|
||||
|
```bash |
||||
|
rm -rf ~/.m2/repository/javax/servlet/javax.servlet-api/4.0.1 |
||||
|
rm -rf ~/.m2/repository/javax/servlet/jsp/javax.servlet.jsp-api/2.3.3 |
||||
|
rm -rf ~/.m2/repository/javax/servlet/jstl/1.2 |
||||
|
rm -rf ~/.m2/repository/mysql/mysql-connector-java/8.0.33 |
||||
|
rm -rf ~/.m2/repository/commons-fileupload/commons-fileupload/1.5 |
||||
|
rm -rf ~/.m2/repository/commons-io/commons-io/2.11.0 |
||||
|
find ~/.m2/repository -name "*.lastUpdated" -delete |
||||
|
``` |
||||
|
|
||||
|
**步骤 2 — 强制重新下载** |
||||
|
|
||||
|
```bash |
||||
|
mvn -U clean compile |
||||
|
``` |
||||
|
|
||||
|
`-U` 表示强制更新,忽略失败缓存。 |
||||
|
|
||||
|
**步骤 3 — IDEA 刷新** |
||||
|
|
||||
|
右侧 Maven 面板 → 点击 **Reload All Maven Projects**(刷新按钮)。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 错误 3:Tomcat 启动报 JAVA_HOME 未定义 |
||||
|
|
||||
|
**报错信息:** |
||||
|
|
||||
|
``` |
||||
|
Neither the JAVA_HOME nor the JRE_HOME environment variable is defined |
||||
|
At least one of these environment variable is needed to run this program |
||||
|
``` |
||||
|
|
||||
|
**原因:** |
||||
|
|
||||
|
系统未配置 `JAVA_HOME`,Tomcat 找不到 Java。 |
||||
|
|
||||
|
**解决方案:** |
||||
|
|
||||
|
**Windows — 永久配置:** |
||||
|
|
||||
|
1. `Win + R` → `sysdm.cpl` → **高级** → **环境变量** |
||||
|
2. 新建系统变量 `JAVA_HOME` = JDK 安装目录(如 `C:\Program Files\Java\jdk-21`) |
||||
|
3. `Path` 中添加 `%JAVA_HOME%\bin` |
||||
|
4. **重新打开** cmd,执行 `startup.bat` |
||||
|
|
||||
|
**Windows — 临时配置:** |
||||
|
|
||||
|
```cmd |
||||
|
set JAVA_HOME=C:\Program Files\Java\jdk-21 |
||||
|
set JRE_HOME=C:\Program Files\Java\jdk-21 |
||||
|
cd /d D:\apache-tomcat-9.0.98\bin |
||||
|
startup.bat |
||||
|
``` |
||||
|
|
||||
|
**Mac M1 — 永久配置:** |
||||
|
|
||||
|
```bash |
||||
|
# 查看 JDK 路径 |
||||
|
/usr/libexec/java_home -V |
||||
|
|
||||
|
# 写入 ~/.zshrc(以 OpenJDK 17 为例) |
||||
|
echo 'export JAVA_HOME="/opt/homebrew/opt/openjdk@17/libexec/openjdk.jdk/Contents/Home"' >> ~/.zshrc |
||||
|
echo 'export PATH="$JAVA_HOME/bin:$PATH"' >> ~/.zshrc |
||||
|
source ~/.zshrc |
||||
|
|
||||
|
# 验证 |
||||
|
echo $JAVA_HOME |
||||
|
java -version |
||||
|
``` |
||||
|
|
||||
|
**Mac — 临时配置:** |
||||
|
|
||||
|
```bash |
||||
|
export JAVA_HOME=$(/usr/libexec/java_home) |
||||
|
export JRE_HOME=$JAVA_HOME |
||||
|
~/apache-tomcat-9.0.98/bin/startup.sh |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 错误 4:页面 404 Not Found |
||||
|
|
||||
|
**原因:** |
||||
|
|
||||
|
- WAR 未放入 `webapps`,或 Tomcat 未完成解压 |
||||
|
- 访问 URL 缺少项目上下文路径 |
||||
|
|
||||
|
**解决方案:** |
||||
|
|
||||
|
1. 确认 `webapps` 下存在 `student-management.war` 或 `student-management/` 文件夹 |
||||
|
2. 访问:`http://localhost:8080/student-management/`(注意含项目名) |
||||
|
3. 查看 Tomcat 日志确认部署是否成功 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 错误 5:页面 500 / 数据库连接失败 |
||||
|
|
||||
|
**原因:** |
||||
|
|
||||
|
- MySQL 未启动 |
||||
|
- `db.properties` 账号密码错误 |
||||
|
- 未执行 `db_init.sql` 初始化数据库 |
||||
|
|
||||
|
**解决方案:** |
||||
|
|
||||
|
```bash |
||||
|
# 检查 MySQL 是否运行 |
||||
|
# Windows |
||||
|
sc query mysql |
||||
|
|
||||
|
# Mac |
||||
|
brew services list | grep mysql |
||||
|
|
||||
|
# 测试连接 |
||||
|
mysql -u root -p -e "USE student_db; SHOW TABLES;" |
||||
|
``` |
||||
|
|
||||
|
确认 `db.properties` 配置正确后,**重新打包并部署** WAR。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 错误 6:8080 端口被占用 |
||||
|
|
||||
|
**报错信息(Tomcat 日志):** |
||||
|
|
||||
|
``` |
||||
|
Address already in use: bind |
||||
|
``` |
||||
|
|
||||
|
**解决方案:** |
||||
|
|
||||
|
**Windows:** |
||||
|
|
||||
|
```cmd |
||||
|
netstat -ano | findstr :8080 |
||||
|
taskkill /PID <进程号> /F |
||||
|
``` |
||||
|
|
||||
|
**Mac:** |
||||
|
|
||||
|
```bash |
||||
|
lsof -i :8080 |
||||
|
kill -9 <PID> |
||||
|
``` |
||||
|
|
||||
|
或修改 Tomcat `conf/server.xml` 中 `<Connector port="8080">` 为其他端口(如 8081)。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## Maven 推荐配置 |
||||
|
|
||||
|
将以下内容写入 Maven 用户配置文件: |
||||
|
|
||||
|
- **Windows:** `C:\Users\你的用户名\.m2\settings.xml` |
||||
|
- **Mac:** `~/.m2/settings.xml` |
||||
|
|
||||
|
```xml |
||||
|
<settings> |
||||
|
<mirrors> |
||||
|
<mirror> |
||||
|
<id>aliyunmaven</id> |
||||
|
<mirrorOf>central</mirrorOf> |
||||
|
<name>Aliyun Maven</name> |
||||
|
<url>https://maven.aliyun.com/repository/public</url> |
||||
|
</mirror> |
||||
|
</mirrors> |
||||
|
|
||||
|
<!-- 代理软件(Clash 等)未启动时请将 active 设为 false --> |
||||
|
<proxies> |
||||
|
<proxy> |
||||
|
<id>http-proxy</id> |
||||
|
<active>false</active> |
||||
|
<protocol>http</protocol> |
||||
|
<host>127.0.0.1</host> |
||||
|
<port>7890</port> |
||||
|
</proxy> |
||||
|
<proxy> |
||||
|
<id>https-proxy</id> |
||||
|
<active>false</active> |
||||
|
<protocol>https</protocol> |
||||
|
<host>127.0.0.1</host> |
||||
|
<port>7890</port> |
||||
|
</proxy> |
||||
|
</proxies> |
||||
|
</settings> |
||||
|
``` |
||||
|
|
||||
|
**IDEA 中确认 Maven 使用该配置:** |
||||
|
|
||||
|
`File → Settings → Build Tools → Maven → User settings file` 指向上述 `settings.xml`。 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 更新部署流程 |
||||
|
|
||||
|
代码或配置修改后,按以下步骤重新部署: |
||||
|
|
||||
|
### Windows |
||||
|
|
||||
|
```powershell |
||||
|
# 1. 重新打包 |
||||
|
cd D:\codefiles\javaweb-homework\student-management |
||||
|
mvn clean package |
||||
|
|
||||
|
# 2. 停止 Tomcat(shutdown.bat) |
||||
|
|
||||
|
# 3. 删除旧部署 |
||||
|
Remove-Item "D:\apache-tomcat-9.0.98\webapps\student-management" -Recurse -Force |
||||
|
Remove-Item "D:\apache-tomcat-9.0.98\webapps\student-management.war" -Force |
||||
|
|
||||
|
# 4. 复制新 WAR |
||||
|
Copy-Item "target\student-management.war" "D:\apache-tomcat-9.0.98\webapps\" |
||||
|
|
||||
|
# 5. 启动 Tomcat(startup.bat) |
||||
|
``` |
||||
|
|
||||
|
### Mac M1 |
||||
|
|
||||
|
```bash |
||||
|
# 1. 重新打包 |
||||
|
cd /path/to/student-management |
||||
|
mvn clean package |
||||
|
|
||||
|
# 2. 停止 Tomcat |
||||
|
brew services stop tomcat@9 |
||||
|
|
||||
|
# 3. 删除旧部署 |
||||
|
TOMCAT_HOME="/opt/homebrew/opt/tomcat@9/libexec" |
||||
|
rm -rf "$TOMCAT_HOME/webapps/student-management" |
||||
|
rm -f "$TOMCAT_HOME/webapps/student-management.war" |
||||
|
|
||||
|
# 4. 复制新 WAR |
||||
|
cp target/student-management.war "$TOMCAT_HOME/webapps/" |
||||
|
|
||||
|
# 5. 启动 Tomcat |
||||
|
brew services start tomcat@9 |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 快速排查清单 |
||||
|
|
||||
|
遇到问题时按顺序检查: |
||||
|
|
||||
|
- [ ] MySQL 已启动,`student_db` 数据库存在 |
||||
|
- [ ] `db.properties` 用户名密码正确 |
||||
|
- [ ] `JAVA_HOME` 已配置,`java -version` 正常 |
||||
|
- [ ] Maven `settings.xml` 代理已关闭或代理软件已启动 |
||||
|
- [ ] 依赖无红色报错(必要时 `mvn -U clean compile`) |
||||
|
- [ ] WAR 包已复制到 Tomcat `webapps/` |
||||
|
- [ ] Tomcat 已成功启动(日志无 ERROR) |
||||
|
- [ ] 浏览器访问 URL 含 `/student-management/` |
||||
@ -0,0 +1,231 @@ |
|||||
|
# 学生信息管理系统 — 业务扩展任务表 |
||||
|
|
||||
|
> 基于现有 **JSP + Servlet + JavaBean + JDBC + DAO** 架构,按模块划分扩展任务。 |
||||
|
> 难度:⭐ 入门 · ⭐⭐ 中等 · ⭐⭐⭐ 较难 · ⭐⭐⭐⭐ 高级 |
||||
|
> 优先级:P0 必做推荐 · P1 建议做 · P2 进阶 · P3 选做 |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 一、总览 |
||||
|
|
||||
|
| 阶段 | 目标 | 建议任务数 | 预估总工时 | |
||||
|
|------|------|-----------|-----------| |
||||
|
| 第一阶段 | 夯实基础安全与数据规范 | 5 项 | 15~20 h | |
||||
|
| 第二阶段 | 丰富核心业务实体 | 6 项 | 25~35 h | |
||||
|
| 第三阶段 | 流程、统计与高级功能 | 6 项 | 30~40 h | |
||||
|
| 第四阶段 | 架构升级与工程化 | 4 项 | 20~30 h | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 二、扩展任务明细 |
||||
|
|
||||
|
### 模块 A:安全与账户体系 |
||||
|
|
||||
|
| 编号 | 功能任务 | 业务说明 | 主要改动 | 技术要点 | 难度 | 优先级 | 工时 | |
||||
|
|------|----------|----------|----------|----------|------|--------|------| |
||||
|
| A-01 | 密码加密存储 | 数据库不再明文存密码,提升安全性 | `User` 表、`UserDao`、登录/注册 Servlet | MD5 或 BCrypt;注册加密、登录比对 | ⭐⭐ | P0 | 3 h | |
||||
|
| A-02 | 登录失败锁定 | 连续输错密码 5 次锁定账户 30 分钟 | 新增 `login_log` 表、登录 Servlet | Session/Redis 计数;Ajax 提示剩余次数 | ⭐⭐ | P1 | 4 h | |
||||
|
| A-03 | 找回密码 | 用户通过邮箱验证码重置密码 | 邮件发送工具类、重置密码 Servlet/JSP | JavaMail 或模拟验证码;验证码有效期 | ⭐⭐⭐ | P1 | 6 h | |
||||
|
| A-04 | 记住我 / 自动登录 | 勾选后 7 天内免登录 | Cookie 工具类、LoginServlet、Filter | Token 存 Cookie + 数据库;HttpOnly | ⭐⭐⭐ | P2 | 5 h | |
||||
|
| A-05 | 在线用户管理 | 管理员查看当前在线用户并强制下线 | Session 监听器、在线用户列表页 | `HttpSessionListener`;Session 映射表 | ⭐⭐⭐ | P2 | 5 h | |
||||
|
| A-06 | 三级角色权限 | 新增「教师」角色,三类用户权限隔离 | `User.role` 扩展、RBAC 表、AuthFilter | 角色-权限-菜单;Filter 细粒度拦截 | ⭐⭐⭐⭐ | P1 | 8 h | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 模块 B:学生档案扩展 |
||||
|
|
||||
|
| 编号 | 功能任务 | 业务说明 | 主要改动 | 技术要点 | 难度 | 优先级 | 工时 | |
||||
|
|------|----------|----------|----------|----------|------|--------|------| |
||||
|
| B-01 | 院系 / 专业 / 班级 | 学生归属组织结构,支持按班级查询 | 新增 `department`、`major`、`clazz` 表 | 多表关联;下拉级联 Ajax | ⭐⭐ | P0 | 6 h | |
||||
|
| B-02 | 学号自动生成 | 注册或录入时按规则生成唯一学号 | 学号生成工具类、新增用户逻辑 | 规则如 `2026CS001`;唯一约束 | ⭐⭐ | P1 | 3 h | |
||||
|
| B-03 | 学生状态管理 | 在读 / 休学 / 毕业 / 退学等状态流转 | `users` 增加 `status` 字段、状态变更 Servlet | 状态枚举;变更记录;列表筛选 | ⭐⭐ | P1 | 4 h | |
||||
|
| B-04 | 头像上传 | 用户上传个人头像并展示 | 文件上传 Servlet、存储路径配置 | `commons-fileupload`;大小/格式校验 | ⭐⭐ | P1 | 4 h | |
||||
|
| B-05 | 学生详情页 | 单独页面展示完整档案(含班级、状态等) | 详情 Servlet、详情 JSP | 多表 JOIN 查询;EL/JSTL 展示 | ⭐⭐ | P1 | 3 h | |
||||
|
| B-06 | 批量导出 Excel | 管理员按条件导出学生信息为 `.xlsx` | 导出 Servlet、Apache POI 依赖 | POI 写 Excel;条件筛选与 CSV 导出并存 | ⭐⭐⭐ | P1 | 5 h | |
||||
|
| B-07 | 高级组合搜索 | 多条件(班级+性别+年龄区间+状态)联合查询 | 列表 Servlet、DAO 动态 SQL | `StringBuilder` 拼接 SQL;防注入用 PreparedStatement | ⭐⭐⭐ | P2 | 6 h | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 模块 C:课程与成绩 |
||||
|
|
||||
|
| 编号 | 功能任务 | 业务说明 | 主要改动 | 技术要点 | 难度 | 优先级 | 工时 | |
||||
|
|------|----------|----------|----------|----------|------|--------|------| |
||||
|
| C-01 | 课程管理 CRUD | 管理员维护课程(编号、名称、学分、授课教师) | `course` 表、CourseDao、Servlet、JSP | 标准 DAO CRUD;分页列表 | ⭐⭐ | P1 | 6 h | |
||||
|
| C-02 | 学生选课 | 一般用户在线选课,限制人数与重复选课 | `enrollment` 表、选课 Servlet | 事务控制;名额校验;已选课程列表 | ⭐⭐⭐ | P1 | 8 h | |
||||
|
| C-03 | 成绩录入 | 教师/管理员录入课程成绩 | `score` 表、成绩 Servlet | 权限校验;批量录入表单 | ⭐⭐⭐ | P1 | 6 h | |
||||
|
| C-04 | 成绩查询 | 学生查看本人成绩,管理员查看全班成绩 | 成绩列表 JSP、查询 Servlet | 按角色过滤数据;GPA 简单计算 | ⭐⭐ | P1 | 4 h | |
||||
|
| C-05 | 成绩统计报表 | 按课程统计平均分、最高/最低分、及格率 | 统计 DAO、报表 JSP | SQL 聚合函数 `AVG/MAX/MIN/COUNT` | ⭐⭐⭐ | P2 | 5 h | |
||||
|
| C-06 | 课表展示 | 学生个人课表(按周视图或列表) | 课表查询 Servlet、课表 JSP | 多表关联;前端表格布局 | ⭐⭐ | P2 | 4 h | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 模块 D:考勤与请假 |
||||
|
|
||||
|
| 编号 | 功能任务 | 业务说明 | 主要改动 | 技术要点 | 难度 | 优先级 | 工时 | |
||||
|
|------|----------|----------|----------|----------|------|--------|------| |
||||
|
| D-01 | 考勤记录 | 教师记录学生出勤(出勤/迟到/缺勤) | `attendance` 表、考勤 Servlet | 按日期+课程+学生唯一;批量提交 | ⭐⭐⭐ | P2 | 6 h | |
||||
|
| D-02 | 请假申请 | 学生提交请假,填写起止时间与原因 | `leave_request` 表、申请 JSP/Servlet | 表单校验;状态:待审/通过/驳回 | ⭐⭐⭐ | P2 | 6 h | |
||||
|
| D-03 | 请假审批 | 教师/管理员审批请假申请 | 审批 Servlet、待办列表 JSP | 工作流状态机;审批意见字段 | ⭐⭐⭐ | P2 | 5 h | |
||||
|
| D-04 | 考勤统计 | 按学生/班级统计出勤率 | 统计 DAO、图表 JSP | 聚合查询;可选 ECharts 展示 | ⭐⭐⭐ | P3 | 6 h | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 模块 E:通知与日志 |
||||
|
|
||||
|
| 编号 | 功能任务 | 业务说明 | 主要改动 | 技术要点 | 难度 | 优先级 | 工时 | |
||||
|
|------|----------|----------|----------|----------|------|--------|------| |
||||
|
| E-01 | 系统公告 | 管理员发布公告,登录后所有用户可见 | `announcement` 表、公告 CRUD | 置顶、有效期;首页滚动展示 | ⭐⭐ | P1 | 4 h | |
||||
|
| E-02 | 站内消息 | 管理员向指定用户/send 全体发消息 | `message` 表、收件箱/发件箱 JSP | 已读/未读;Ajax 未读数角标 | ⭐⭐⭐ | P2 | 6 h | |
||||
|
| E-03 | 操作日志 | 记录增删改等关键操作(谁、何时、做了什么) | `operation_log` 表、日志 Filter/AOP 式拦截 | Filter 或 Servlet 基类;日志分页查询 | ⭐⭐⭐ | P1 | 6 h | |
||||
|
| E-04 | 登录日志 | 记录每次登录 IP、时间、结果 | `login_log` 表、LoginServlet 埋点 | 获取客户端 IP;失败/成功分类 | ⭐⭐ | P1 | 3 h | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 模块 F:数据统计与可视化 |
||||
|
|
||||
|
| 编号 | 功能任务 | 业务说明 | 主要改动 | 技术要点 | 难度 | 优先级 | 工时 | |
||||
|
|------|----------|----------|----------|----------|------|--------|------| |
||||
|
| F-01 | 管理员 Dashboard | 首页展示用户数、今日注册、班级分布等 | 仪表盘 JSP、统计 Servlet | 多指标卡片;SQL 聚合 | ⭐⭐ | P1 | 5 h | |
||||
|
| F-02 | 图表可视化 | 性别比例、年龄分布、院系人数饼图/柱状图 | 引入 ECharts、统计 API Servlet | Servlet 返回 JSON;Ajax 渲染图表 | ⭐⭐⭐ | P2 | 6 h | |
||||
|
| F-03 | 数据大屏(选做) | 全屏展示核心指标,适合答辩演示 | 单独大屏 JSP + ECharts | CSS 全屏布局;定时 Ajax 刷新 | ⭐⭐⭐ | P3 | 8 h | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 模块 G:流程与审批 |
||||
|
|
||||
|
| 编号 | 功能任务 | 业务说明 | 主要改动 | 技术要点 | 难度 | 优先级 | 工时 | |
||||
|
|------|----------|----------|----------|----------|------|--------|------| |
||||
|
| G-01 | 信息变更审批 | 学生修改关键信息(姓名、学号)需管理员审核 | `change_request` 表、审批 Servlet | 暂存待审;通过后更新主表 | ⭐⭐⭐⭐ | P2 | 8 h | |
||||
|
| G-02 | 新生注册审核 | 注册后状态为「待审核」,管理员通过后激活 | 注册流程改造、审核列表 | 状态字段;邮件/站内信通知 | ⭐⭐⭐ | P2 | 5 h | |
||||
|
| G-03 | 批量导入审核 | CSV 导入先进临时表,确认后再写入正式表 | 临时表 + 确认 Servlet | 两阶段导入;预览与回滚 | ⭐⭐⭐⭐ | P3 | 8 h | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
### 模块 H:工程化与架构升级 |
||||
|
|
||||
|
| 编号 | 功能任务 | 业务说明 | 主要改动 | 技术要点 | 难度 | 优先级 | 工时 | |
||||
|
|------|----------|----------|----------|----------|------|--------|------| |
||||
|
| H-01 | 引入 Service 层 | DAO 之上增加业务层,Servlet 只调 Service | 新增 `service` 包、重构 Servlet | 分层解耦;事务放 Service | ⭐⭐⭐ | P1 | 8 h | |
||||
|
| H-02 | DBUtils / Druid 连接池 | 替换原生 JDBC 连接管理 | 引入依赖、改造 `DBUtil` | 连接池配置;SQL 性能提升 | ⭐⭐⭐ | P1 | 4 h | |
||||
|
| H-03 | 统一 JSON 接口 | 列表/删除等改为 REST 风格 Ajax API | 统一响应 JavaBean、JsonServlet 基类 | ` Gson/Jackson`;前后端分离雏形 | ⭐⭐⭐ | P2 | 6 h | |
||||
|
| H-04 | JSP 标签 / 公共片段 | 抽取 header、sidebar、分页为 `jsp:include` | `WEB-INF/jspf/` 公共片段 | 减少重复代码;统一布局 | ⭐⭐ | P0 | 4 h | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 三、推荐实施路线 |
||||
|
|
||||
|
### 路线 1:课程设计 / 作业答辩(约 2~3 周) |
||||
|
|
||||
|
| 顺序 | 任务编号 | 理由 | |
||||
|
|------|----------|------| |
||||
|
| 1 | A-01 密码加密 | 必讲安全,改动小见效快 | |
||||
|
| 2 | H-04 公共 JSP 片段 | 为后续页面扩展打基础 | |
||||
|
| 3 | B-01 院系班级 | 业务实体明显变复杂 | |
||||
|
| 4 | E-03 操作日志 | 体现系统完整性 | |
||||
|
| 5 | F-01 Dashboard | 答辩展示效果好 | |
||||
|
| 6 | C-01 + C-04 课程与成绩 | 核心业务闭环 | |
||||
|
|
||||
|
### 路线 2:功能丰富型(约 4~6 周) |
||||
|
|
||||
|
在路线 1 基础上增加: |
||||
|
|
||||
|
| 顺序 | 任务编号 | |
||||
|
|------|----------| |
||||
|
| 7 | A-06 三级角色 | |
||||
|
| 8 | C-02 学生选课 | |
||||
|
| 9 | D-02 + D-03 请假与审批 | |
||||
|
| 10 | E-01 系统公告 | |
||||
|
| 11 | F-02 图表可视化 | |
||||
|
| 12 | B-06 Excel 导出 | |
||||
|
|
||||
|
### 路线 3:架构进阶型(约 6~8 周) |
||||
|
|
||||
|
在路线 2 基础上增加: |
||||
|
|
||||
|
| 顺序 | 任务编号 | |
||||
|
|------|----------| |
||||
|
| 13 | H-01 Service 层 | |
||||
|
| 14 | H-02 连接池 | |
||||
|
| 15 | G-01 信息变更审批 | |
||||
|
| 16 | H-03 统一 JSON 接口 | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 四、任务依赖关系 |
||||
|
|
||||
|
``` |
||||
|
A-01 密码加密 |
||||
|
└── A-02 登录锁定 |
||||
|
└── A-03 找回密码 |
||||
|
|
||||
|
B-01 院系/班级 |
||||
|
└── B-02 学号生成 |
||||
|
└── B-07 高级搜索 |
||||
|
└── C-02 学生选课 |
||||
|
|
||||
|
C-01 课程管理 |
||||
|
└── C-02 选课 |
||||
|
└── C-03 成绩录入 |
||||
|
└── C-04 成绩查询 |
||||
|
└── D-01 考勤记录 |
||||
|
|
||||
|
E-04 登录日志 |
||||
|
└── A-02 登录锁定 |
||||
|
|
||||
|
H-04 JSP 公共片段 |
||||
|
└── F-01 Dashboard |
||||
|
└── 所有新增 JSP 页面 |
||||
|
|
||||
|
H-01 Service 层 |
||||
|
└── H-03 JSON 接口 |
||||
|
└── G-01 审批流程 |
||||
|
``` |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 五、答辩可强调的「业务复杂度」亮点 |
||||
|
|
||||
|
| 亮点 | 对应任务 | 答辩话术要点 | |
||||
|
|------|----------|-------------| |
||||
|
| 安全体系 | A-01、A-02、E-04 | 密码加密、防暴力破解、审计追踪 | |
||||
|
| 组织模型 | B-01、B-03 | 院系-专业-班级三级结构,状态流转 | |
||||
|
| 教学业务 | C-01~C-05 | 选课-成绩完整链路,含统计报表 | |
||||
|
| 流程控制 | D-02、G-01、G-02 | 请假/变更/注册多级审批 | |
||||
|
| 数据可视化 | F-01、F-02 | Dashboard + ECharts 图表 | |
||||
|
| 架构演进 | H-01、H-02 | 三层架构 + 连接池,体现工程能力 | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 六、数据库扩展预览(核心新增表) |
||||
|
|
||||
|
| 表名 | 说明 | 关联任务 | |
||||
|
|------|------|----------| |
||||
|
| `department` | 院系 | B-01 | |
||||
|
| `major` | 专业 | B-01 | |
||||
|
| `clazz` | 班级 | B-01 | |
||||
|
| `course` | 课程 | C-01 | |
||||
|
| `enrollment` | 选课记录 | C-02 | |
||||
|
| `score` | 成绩 | C-03 | |
||||
|
| `attendance` | 考勤 | D-01 | |
||||
|
| `leave_request` | 请假 | D-02 | |
||||
|
| `announcement` | 公告 | E-01 | |
||||
|
| `message` | 站内消息 | E-02 | |
||||
|
| `operation_log` | 操作日志 | E-03 | |
||||
|
| `login_log` | 登录日志 | E-04 | |
||||
|
| `change_request` | 变更审批 | G-01 | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
## 七、选型建议 |
||||
|
|
||||
|
| 如果目标是… | 优先选这些任务 | |
||||
|
|------------|---------------| |
||||
|
| 快速加分 | A-01、F-01、E-01、B-04 | |
||||
|
| 业务深度 | B-01、C-01~C-04、D-02~D-03 | |
||||
|
| 技术深度 | H-01、H-02、H-03、A-06 | |
||||
|
| 演示效果好 | F-01、F-02、C-06、E-01 | |
||||
|
| 工作量可控 | 选 **路线 1** 的 6 项即可 | |
||||
|
|
||||
|
--- |
||||
|
|
||||
|
*可根据课程要求和时间,从表中勾选 5~10 项组成你的扩展计划。* |
||||
@ -0,0 +1,103 @@ |
|||||
|
<?xml version="1.0" encoding="UTF-8"?> |
||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" |
||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> |
||||
|
<modelVersion>4.0.0</modelVersion> |
||||
|
<groupId>com.student</groupId> |
||||
|
<artifactId>student-management</artifactId> |
||||
|
<version>2.0-SNAPSHOT</version> |
||||
|
<packaging>war</packaging> |
||||
|
<name>student-management</name> |
||||
|
<properties> |
||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> |
||||
|
<maven.compiler.source>1.8</maven.compiler.source> |
||||
|
<maven.compiler.target>1.8</maven.compiler.target> |
||||
|
</properties> |
||||
|
<dependencies> |
||||
|
<dependency> |
||||
|
<groupId>javax.servlet</groupId> |
||||
|
<artifactId>javax.servlet-api</artifactId> |
||||
|
<version>4.0.1</version> |
||||
|
<scope>provided</scope> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>javax.servlet.jsp</groupId> |
||||
|
<artifactId>javax.servlet.jsp-api</artifactId> |
||||
|
<version>2.3.3</version> |
||||
|
<scope>provided</scope> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>javax.servlet</groupId> |
||||
|
<artifactId>jstl</artifactId> |
||||
|
<version>1.2</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.mysql</groupId> |
||||
|
<artifactId>mysql-connector-j</artifactId> |
||||
|
<version>8.0.33</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.zaxxer</groupId> |
||||
|
<artifactId>HikariCP</artifactId> |
||||
|
<version>4.0.3</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>commons-fileupload</groupId> |
||||
|
<artifactId>commons-fileupload</artifactId> |
||||
|
<version>1.5</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>commons-io</groupId> |
||||
|
<artifactId>commons-io</artifactId> |
||||
|
<version>2.11.0</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>com.google.code.gson</groupId> |
||||
|
<artifactId>gson</artifactId> |
||||
|
<version>2.10.1</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.apache.poi</groupId> |
||||
|
<artifactId>poi-ooxml</artifactId> |
||||
|
<version>5.2.3</version> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.junit.jupiter</groupId> |
||||
|
<artifactId>junit-jupiter</artifactId> |
||||
|
<version>5.10.2</version> |
||||
|
<scope>test</scope> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.mockito</groupId> |
||||
|
<artifactId>mockito-core</artifactId> |
||||
|
<version>4.11.0</version> |
||||
|
<scope>test</scope> |
||||
|
</dependency> |
||||
|
<dependency> |
||||
|
<groupId>org.mockito</groupId> |
||||
|
<artifactId>mockito-junit-jupiter</artifactId> |
||||
|
<version>4.11.0</version> |
||||
|
<scope>test</scope> |
||||
|
</dependency> |
||||
|
</dependencies> |
||||
|
<build> |
||||
|
<finalName>student-management</finalName> |
||||
|
<plugins> |
||||
|
<plugin> |
||||
|
<groupId>org.apache.maven.plugins</groupId> |
||||
|
<artifactId>maven-war-plugin</artifactId> |
||||
|
<version>3.3.2</version> |
||||
|
</plugin> |
||||
|
<plugin> |
||||
|
<groupId>org.apache.maven.plugins</groupId> |
||||
|
<artifactId>maven-compiler-plugin</artifactId> |
||||
|
<version>3.11.0</version> |
||||
|
</plugin> |
||||
|
<plugin> |
||||
|
<groupId>org.apache.maven.plugins</groupId> |
||||
|
<artifactId>maven-surefire-plugin</artifactId> |
||||
|
<version>3.2.5</version> |
||||
|
</plugin> |
||||
|
</plugins> |
||||
|
</build> |
||||
|
</project> |
||||
@ -0,0 +1,82 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
public class Announcement implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private String title; |
||||
|
private String content; |
||||
|
private Integer publisherId; |
||||
|
private Integer isTop; |
||||
|
private Date expireDate; |
||||
|
private Date createTime; |
||||
|
private String publisherName; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public String getTitle() { |
||||
|
return title; |
||||
|
} |
||||
|
|
||||
|
public void setTitle(String title) { |
||||
|
this.title = title; |
||||
|
} |
||||
|
|
||||
|
public String getContent() { |
||||
|
return content; |
||||
|
} |
||||
|
|
||||
|
public void setContent(String content) { |
||||
|
this.content = content; |
||||
|
} |
||||
|
|
||||
|
public Integer getPublisherId() { |
||||
|
return publisherId; |
||||
|
} |
||||
|
|
||||
|
public void setPublisherId(Integer publisherId) { |
||||
|
this.publisherId = publisherId; |
||||
|
} |
||||
|
|
||||
|
public Integer getIsTop() { |
||||
|
return isTop; |
||||
|
} |
||||
|
|
||||
|
public void setIsTop(Integer isTop) { |
||||
|
this.isTop = isTop; |
||||
|
} |
||||
|
|
||||
|
public Date getExpireDate() { |
||||
|
return expireDate; |
||||
|
} |
||||
|
|
||||
|
public void setExpireDate(Date expireDate) { |
||||
|
this.expireDate = expireDate; |
||||
|
} |
||||
|
|
||||
|
public Date getCreateTime() { |
||||
|
return createTime; |
||||
|
} |
||||
|
|
||||
|
public void setCreateTime(Date createTime) { |
||||
|
this.createTime = createTime; |
||||
|
} |
||||
|
|
||||
|
public String getPublisherName() { |
||||
|
return publisherName; |
||||
|
} |
||||
|
|
||||
|
public void setPublisherName(String publisherName) { |
||||
|
this.publisherName = publisherName; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,64 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
/** |
||||
|
* 统一 API 响应结构 |
||||
|
*/ |
||||
|
public class ApiResult<T> { |
||||
|
|
||||
|
private int code; |
||||
|
private String message; |
||||
|
private T data; |
||||
|
|
||||
|
public ApiResult() { |
||||
|
} |
||||
|
|
||||
|
public ApiResult(int code, String message, T data) { |
||||
|
this.code = code; |
||||
|
this.message = message; |
||||
|
this.data = data; |
||||
|
} |
||||
|
|
||||
|
public static <T> ApiResult<T> ok() { |
||||
|
return ok(null); |
||||
|
} |
||||
|
|
||||
|
public static <T> ApiResult<T> ok(T data) { |
||||
|
return new ApiResult<>(200, "success", data); |
||||
|
} |
||||
|
|
||||
|
public static <T> ApiResult<T> ok(String message, T data) { |
||||
|
return new ApiResult<>(200, message, data); |
||||
|
} |
||||
|
|
||||
|
public static <T> ApiResult<T> fail(String message) { |
||||
|
return fail(500, message); |
||||
|
} |
||||
|
|
||||
|
public static <T> ApiResult<T> fail(int code, String message) { |
||||
|
return new ApiResult<>(code, message, null); |
||||
|
} |
||||
|
|
||||
|
public int getCode() { |
||||
|
return code; |
||||
|
} |
||||
|
|
||||
|
public void setCode(int code) { |
||||
|
this.code = code; |
||||
|
} |
||||
|
|
||||
|
public String getMessage() { |
||||
|
return message; |
||||
|
} |
||||
|
|
||||
|
public void setMessage(String message) { |
||||
|
this.message = message; |
||||
|
} |
||||
|
|
||||
|
public T getData() { |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
public void setData(T data) { |
||||
|
this.data = data; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,86 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
public class Attendance implements Serializable { |
||||
|
|
||||
|
public static final int STATUS_PRESENT = 1; |
||||
|
public static final int STATUS_LATE = 2; |
||||
|
public static final int STATUS_ABSENT = 3; |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private Integer studentId; |
||||
|
private Integer courseId; |
||||
|
private Date attDate; |
||||
|
private Integer status; |
||||
|
private String remark; |
||||
|
private String studentName; |
||||
|
private String courseName; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public Integer getStudentId() { |
||||
|
return studentId; |
||||
|
} |
||||
|
|
||||
|
public void setStudentId(Integer studentId) { |
||||
|
this.studentId = studentId; |
||||
|
} |
||||
|
|
||||
|
public Integer getCourseId() { |
||||
|
return courseId; |
||||
|
} |
||||
|
|
||||
|
public void setCourseId(Integer courseId) { |
||||
|
this.courseId = courseId; |
||||
|
} |
||||
|
|
||||
|
public Date getAttDate() { |
||||
|
return attDate; |
||||
|
} |
||||
|
|
||||
|
public void setAttDate(Date attDate) { |
||||
|
this.attDate = attDate; |
||||
|
} |
||||
|
|
||||
|
public Integer getStatus() { |
||||
|
return status; |
||||
|
} |
||||
|
|
||||
|
public void setStatus(Integer status) { |
||||
|
this.status = status; |
||||
|
} |
||||
|
|
||||
|
public String getRemark() { |
||||
|
return remark; |
||||
|
} |
||||
|
|
||||
|
public void setRemark(String remark) { |
||||
|
this.remark = remark; |
||||
|
} |
||||
|
|
||||
|
public String getStudentName() { |
||||
|
return studentName; |
||||
|
} |
||||
|
|
||||
|
public void setStudentName(String studentName) { |
||||
|
this.studentName = studentName; |
||||
|
} |
||||
|
|
||||
|
public String getCourseName() { |
||||
|
return courseName; |
||||
|
} |
||||
|
|
||||
|
public void setCourseName(String courseName) { |
||||
|
this.courseName = courseName; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
|
||||
|
public class AttendanceStats implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private int present; |
||||
|
private int late; |
||||
|
private int absent; |
||||
|
private int total; |
||||
|
|
||||
|
public int getPresent() { |
||||
|
return present; |
||||
|
} |
||||
|
|
||||
|
public void setPresent(int present) { |
||||
|
this.present = present; |
||||
|
} |
||||
|
|
||||
|
public int getLate() { |
||||
|
return late; |
||||
|
} |
||||
|
|
||||
|
public void setLate(int late) { |
||||
|
this.late = late; |
||||
|
} |
||||
|
|
||||
|
public int getAbsent() { |
||||
|
return absent; |
||||
|
} |
||||
|
|
||||
|
public void setAbsent(int absent) { |
||||
|
this.absent = absent; |
||||
|
} |
||||
|
|
||||
|
public int getTotal() { |
||||
|
return total; |
||||
|
} |
||||
|
|
||||
|
public void setTotal(int total) { |
||||
|
this.total = total; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,122 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
public class ChangeRequest implements Serializable { |
||||
|
|
||||
|
public static final int STATUS_PENDING = 0; |
||||
|
public static final int STATUS_APPROVED = 1; |
||||
|
public static final int STATUS_REJECTED = 2; |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private Integer userId; |
||||
|
private String fieldName; |
||||
|
private String oldValue; |
||||
|
private String newValue; |
||||
|
private Integer status; |
||||
|
private Integer approverId; |
||||
|
private String approveNote; |
||||
|
private Date createTime; |
||||
|
private String username; |
||||
|
private String realName; |
||||
|
private String approverName; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public Integer getUserId() { |
||||
|
return userId; |
||||
|
} |
||||
|
|
||||
|
public void setUserId(Integer userId) { |
||||
|
this.userId = userId; |
||||
|
} |
||||
|
|
||||
|
public String getFieldName() { |
||||
|
return fieldName; |
||||
|
} |
||||
|
|
||||
|
public void setFieldName(String fieldName) { |
||||
|
this.fieldName = fieldName; |
||||
|
} |
||||
|
|
||||
|
public String getOldValue() { |
||||
|
return oldValue; |
||||
|
} |
||||
|
|
||||
|
public void setOldValue(String oldValue) { |
||||
|
this.oldValue = oldValue; |
||||
|
} |
||||
|
|
||||
|
public String getNewValue() { |
||||
|
return newValue; |
||||
|
} |
||||
|
|
||||
|
public void setNewValue(String newValue) { |
||||
|
this.newValue = newValue; |
||||
|
} |
||||
|
|
||||
|
public Integer getStatus() { |
||||
|
return status; |
||||
|
} |
||||
|
|
||||
|
public void setStatus(Integer status) { |
||||
|
this.status = status; |
||||
|
} |
||||
|
|
||||
|
public Integer getApproverId() { |
||||
|
return approverId; |
||||
|
} |
||||
|
|
||||
|
public void setApproverId(Integer approverId) { |
||||
|
this.approverId = approverId; |
||||
|
} |
||||
|
|
||||
|
public String getApproveNote() { |
||||
|
return approveNote; |
||||
|
} |
||||
|
|
||||
|
public void setApproveNote(String approveNote) { |
||||
|
this.approveNote = approveNote; |
||||
|
} |
||||
|
|
||||
|
public Date getCreateTime() { |
||||
|
return createTime; |
||||
|
} |
||||
|
|
||||
|
public void setCreateTime(Date createTime) { |
||||
|
this.createTime = createTime; |
||||
|
} |
||||
|
|
||||
|
public String getUsername() { |
||||
|
return username; |
||||
|
} |
||||
|
|
||||
|
public void setUsername(String username) { |
||||
|
this.username = username; |
||||
|
} |
||||
|
|
||||
|
public String getRealName() { |
||||
|
return realName; |
||||
|
} |
||||
|
|
||||
|
public void setRealName(String realName) { |
||||
|
this.realName = realName; |
||||
|
} |
||||
|
|
||||
|
public String getApproverName() { |
||||
|
return approverName; |
||||
|
} |
||||
|
|
||||
|
public void setApproverName(String approverName) { |
||||
|
this.approverName = approverName; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,63 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
|
||||
|
public class Clazz implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private Integer majorId; |
||||
|
private String name; |
||||
|
private String grade; |
||||
|
private String majorName; |
||||
|
private String departmentName; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public Integer getMajorId() { |
||||
|
return majorId; |
||||
|
} |
||||
|
|
||||
|
public void setMajorId(Integer majorId) { |
||||
|
this.majorId = majorId; |
||||
|
} |
||||
|
|
||||
|
public String getName() { |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
public void setName(String name) { |
||||
|
this.name = name; |
||||
|
} |
||||
|
|
||||
|
public String getGrade() { |
||||
|
return grade; |
||||
|
} |
||||
|
|
||||
|
public void setGrade(String grade) { |
||||
|
this.grade = grade; |
||||
|
} |
||||
|
|
||||
|
public String getMajorName() { |
||||
|
return majorName; |
||||
|
} |
||||
|
|
||||
|
public void setMajorName(String majorName) { |
||||
|
this.majorName = majorName; |
||||
|
} |
||||
|
|
||||
|
public String getDepartmentName() { |
||||
|
return departmentName; |
||||
|
} |
||||
|
|
||||
|
public void setDepartmentName(String departmentName) { |
||||
|
this.departmentName = departmentName; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,101 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.math.BigDecimal; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
public class Course implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private String courseNo; |
||||
|
private String name; |
||||
|
private BigDecimal credit; |
||||
|
private Integer teacherId; |
||||
|
private Integer maxStudents; |
||||
|
private String schedule; |
||||
|
private Date createTime; |
||||
|
private String teacherName; |
||||
|
private Integer enrolledCount; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public String getCourseNo() { |
||||
|
return courseNo; |
||||
|
} |
||||
|
|
||||
|
public void setCourseNo(String courseNo) { |
||||
|
this.courseNo = courseNo; |
||||
|
} |
||||
|
|
||||
|
public String getName() { |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
public void setName(String name) { |
||||
|
this.name = name; |
||||
|
} |
||||
|
|
||||
|
public BigDecimal getCredit() { |
||||
|
return credit; |
||||
|
} |
||||
|
|
||||
|
public void setCredit(BigDecimal credit) { |
||||
|
this.credit = credit; |
||||
|
} |
||||
|
|
||||
|
public Integer getTeacherId() { |
||||
|
return teacherId; |
||||
|
} |
||||
|
|
||||
|
public void setTeacherId(Integer teacherId) { |
||||
|
this.teacherId = teacherId; |
||||
|
} |
||||
|
|
||||
|
public Integer getMaxStudents() { |
||||
|
return maxStudents; |
||||
|
} |
||||
|
|
||||
|
public void setMaxStudents(Integer maxStudents) { |
||||
|
this.maxStudents = maxStudents; |
||||
|
} |
||||
|
|
||||
|
public String getSchedule() { |
||||
|
return schedule; |
||||
|
} |
||||
|
|
||||
|
public void setSchedule(String schedule) { |
||||
|
this.schedule = schedule; |
||||
|
} |
||||
|
|
||||
|
public Date getCreateTime() { |
||||
|
return createTime; |
||||
|
} |
||||
|
|
||||
|
public void setCreateTime(Date createTime) { |
||||
|
this.createTime = createTime; |
||||
|
} |
||||
|
|
||||
|
public String getTeacherName() { |
||||
|
return teacherName; |
||||
|
} |
||||
|
|
||||
|
public void setTeacherName(String teacherName) { |
||||
|
this.teacherName = teacherName; |
||||
|
} |
||||
|
|
||||
|
public Integer getEnrolledCount() { |
||||
|
return enrolledCount; |
||||
|
} |
||||
|
|
||||
|
public void setEnrolledCount(Integer enrolledCount) { |
||||
|
this.enrolledCount = enrolledCount; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,64 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.math.BigDecimal; |
||||
|
|
||||
|
public class CourseStats implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer courseId; |
||||
|
private BigDecimal avg; |
||||
|
private BigDecimal max; |
||||
|
private BigDecimal min; |
||||
|
private BigDecimal passRate; |
||||
|
private int totalCount; |
||||
|
|
||||
|
public Integer getCourseId() { |
||||
|
return courseId; |
||||
|
} |
||||
|
|
||||
|
public void setCourseId(Integer courseId) { |
||||
|
this.courseId = courseId; |
||||
|
} |
||||
|
|
||||
|
public BigDecimal getAvg() { |
||||
|
return avg; |
||||
|
} |
||||
|
|
||||
|
public void setAvg(BigDecimal avg) { |
||||
|
this.avg = avg; |
||||
|
} |
||||
|
|
||||
|
public BigDecimal getMax() { |
||||
|
return max; |
||||
|
} |
||||
|
|
||||
|
public void setMax(BigDecimal max) { |
||||
|
this.max = max; |
||||
|
} |
||||
|
|
||||
|
public BigDecimal getMin() { |
||||
|
return min; |
||||
|
} |
||||
|
|
||||
|
public void setMin(BigDecimal min) { |
||||
|
this.min = min; |
||||
|
} |
||||
|
|
||||
|
public BigDecimal getPassRate() { |
||||
|
return passRate; |
||||
|
} |
||||
|
|
||||
|
public void setPassRate(BigDecimal passRate) { |
||||
|
this.passRate = passRate; |
||||
|
} |
||||
|
|
||||
|
public int getTotalCount() { |
||||
|
return totalCount; |
||||
|
} |
||||
|
|
||||
|
public void setTotalCount(int totalCount) { |
||||
|
this.totalCount = totalCount; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,83 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.HashMap; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
public class DashboardStats implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private int totalUsers; |
||||
|
private int todayRegister; |
||||
|
private int totalCourses; |
||||
|
private int pendingLeave; |
||||
|
private int pendingChange; |
||||
|
private int pendingRegister; |
||||
|
private Map<String, Integer> genderStats = new HashMap<>(); |
||||
|
private Map<String, Integer> deptStats = new HashMap<>(); |
||||
|
|
||||
|
public int getTotalUsers() { |
||||
|
return totalUsers; |
||||
|
} |
||||
|
|
||||
|
public void setTotalUsers(int totalUsers) { |
||||
|
this.totalUsers = totalUsers; |
||||
|
} |
||||
|
|
||||
|
public int getTodayRegister() { |
||||
|
return todayRegister; |
||||
|
} |
||||
|
|
||||
|
public void setTodayRegister(int todayRegister) { |
||||
|
this.todayRegister = todayRegister; |
||||
|
} |
||||
|
|
||||
|
public int getTotalCourses() { |
||||
|
return totalCourses; |
||||
|
} |
||||
|
|
||||
|
public void setTotalCourses(int totalCourses) { |
||||
|
this.totalCourses = totalCourses; |
||||
|
} |
||||
|
|
||||
|
public int getPendingLeave() { |
||||
|
return pendingLeave; |
||||
|
} |
||||
|
|
||||
|
public void setPendingLeave(int pendingLeave) { |
||||
|
this.pendingLeave = pendingLeave; |
||||
|
} |
||||
|
|
||||
|
public int getPendingChange() { |
||||
|
return pendingChange; |
||||
|
} |
||||
|
|
||||
|
public void setPendingChange(int pendingChange) { |
||||
|
this.pendingChange = pendingChange; |
||||
|
} |
||||
|
|
||||
|
public int getPendingRegister() { |
||||
|
return pendingRegister; |
||||
|
} |
||||
|
|
||||
|
public void setPendingRegister(int pendingRegister) { |
||||
|
this.pendingRegister = pendingRegister; |
||||
|
} |
||||
|
|
||||
|
public Map<String, Integer> getGenderStats() { |
||||
|
return genderStats; |
||||
|
} |
||||
|
|
||||
|
public void setGenderStats(Map<String, Integer> genderStats) { |
||||
|
this.genderStats = genderStats; |
||||
|
} |
||||
|
|
||||
|
public Map<String, Integer> getDeptStats() { |
||||
|
return deptStats; |
||||
|
} |
||||
|
|
||||
|
public void setDeptStats(Map<String, Integer> deptStats) { |
||||
|
this.deptStats = deptStats; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
|
||||
|
public class Department implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private String name; |
||||
|
private String code; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public String getName() { |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
public void setName(String name) { |
||||
|
this.name = name; |
||||
|
} |
||||
|
|
||||
|
public String getCode() { |
||||
|
return code; |
||||
|
} |
||||
|
|
||||
|
public void setCode(String code) { |
||||
|
this.code = code; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,82 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
public class Enrollment implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private Integer studentId; |
||||
|
private Integer courseId; |
||||
|
private Date createTime; |
||||
|
private String studentName; |
||||
|
private String studentNo; |
||||
|
private String courseName; |
||||
|
private String courseNo; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public Integer getStudentId() { |
||||
|
return studentId; |
||||
|
} |
||||
|
|
||||
|
public void setStudentId(Integer studentId) { |
||||
|
this.studentId = studentId; |
||||
|
} |
||||
|
|
||||
|
public Integer getCourseId() { |
||||
|
return courseId; |
||||
|
} |
||||
|
|
||||
|
public void setCourseId(Integer courseId) { |
||||
|
this.courseId = courseId; |
||||
|
} |
||||
|
|
||||
|
public Date getCreateTime() { |
||||
|
return createTime; |
||||
|
} |
||||
|
|
||||
|
public void setCreateTime(Date createTime) { |
||||
|
this.createTime = createTime; |
||||
|
} |
||||
|
|
||||
|
public String getStudentName() { |
||||
|
return studentName; |
||||
|
} |
||||
|
|
||||
|
public void setStudentName(String studentName) { |
||||
|
this.studentName = studentName; |
||||
|
} |
||||
|
|
||||
|
public String getStudentNo() { |
||||
|
return studentNo; |
||||
|
} |
||||
|
|
||||
|
public void setStudentNo(String studentNo) { |
||||
|
this.studentNo = studentNo; |
||||
|
} |
||||
|
|
||||
|
public String getCourseName() { |
||||
|
return courseName; |
||||
|
} |
||||
|
|
||||
|
public void setCourseName(String courseName) { |
||||
|
this.courseName = courseName; |
||||
|
} |
||||
|
|
||||
|
public String getCourseNo() { |
||||
|
return courseNo; |
||||
|
} |
||||
|
|
||||
|
public void setCourseNo(String courseNo) { |
||||
|
this.courseNo = courseNo; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,131 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
public class LeaveRequest implements Serializable { |
||||
|
|
||||
|
public static final int STATUS_PENDING = 0; |
||||
|
public static final int STATUS_APPROVED = 1; |
||||
|
public static final int STATUS_REJECTED = 2; |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private Integer studentId; |
||||
|
private Date startDate; |
||||
|
private Date endDate; |
||||
|
private String reason; |
||||
|
private Integer status; |
||||
|
private Integer approverId; |
||||
|
private String approveNote; |
||||
|
private Date approveTime; |
||||
|
private Date createTime; |
||||
|
private String studentName; |
||||
|
private String studentNo; |
||||
|
private String approverName; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public Integer getStudentId() { |
||||
|
return studentId; |
||||
|
} |
||||
|
|
||||
|
public void setStudentId(Integer studentId) { |
||||
|
this.studentId = studentId; |
||||
|
} |
||||
|
|
||||
|
public Date getStartDate() { |
||||
|
return startDate; |
||||
|
} |
||||
|
|
||||
|
public void setStartDate(Date startDate) { |
||||
|
this.startDate = startDate; |
||||
|
} |
||||
|
|
||||
|
public Date getEndDate() { |
||||
|
return endDate; |
||||
|
} |
||||
|
|
||||
|
public void setEndDate(Date endDate) { |
||||
|
this.endDate = endDate; |
||||
|
} |
||||
|
|
||||
|
public String getReason() { |
||||
|
return reason; |
||||
|
} |
||||
|
|
||||
|
public void setReason(String reason) { |
||||
|
this.reason = reason; |
||||
|
} |
||||
|
|
||||
|
public Integer getStatus() { |
||||
|
return status; |
||||
|
} |
||||
|
|
||||
|
public void setStatus(Integer status) { |
||||
|
this.status = status; |
||||
|
} |
||||
|
|
||||
|
public Integer getApproverId() { |
||||
|
return approverId; |
||||
|
} |
||||
|
|
||||
|
public void setApproverId(Integer approverId) { |
||||
|
this.approverId = approverId; |
||||
|
} |
||||
|
|
||||
|
public String getApproveNote() { |
||||
|
return approveNote; |
||||
|
} |
||||
|
|
||||
|
public void setApproveNote(String approveNote) { |
||||
|
this.approveNote = approveNote; |
||||
|
} |
||||
|
|
||||
|
public Date getApproveTime() { |
||||
|
return approveTime; |
||||
|
} |
||||
|
|
||||
|
public void setApproveTime(Date approveTime) { |
||||
|
this.approveTime = approveTime; |
||||
|
} |
||||
|
|
||||
|
public Date getCreateTime() { |
||||
|
return createTime; |
||||
|
} |
||||
|
|
||||
|
public void setCreateTime(Date createTime) { |
||||
|
this.createTime = createTime; |
||||
|
} |
||||
|
|
||||
|
public String getStudentName() { |
||||
|
return studentName; |
||||
|
} |
||||
|
|
||||
|
public void setStudentName(String studentName) { |
||||
|
this.studentName = studentName; |
||||
|
} |
||||
|
|
||||
|
public String getStudentNo() { |
||||
|
return studentNo; |
||||
|
} |
||||
|
|
||||
|
public void setStudentNo(String studentNo) { |
||||
|
this.studentNo = studentNo; |
||||
|
} |
||||
|
|
||||
|
public String getApproverName() { |
||||
|
return approverName; |
||||
|
} |
||||
|
|
||||
|
public void setApproverName(String approverName) { |
||||
|
this.approverName = approverName; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
public class LoginLog implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private Integer userId; |
||||
|
private String username; |
||||
|
private String ip; |
||||
|
private Integer result; |
||||
|
private String message; |
||||
|
private Date createTime; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public Integer getUserId() { |
||||
|
return userId; |
||||
|
} |
||||
|
|
||||
|
public void setUserId(Integer userId) { |
||||
|
this.userId = userId; |
||||
|
} |
||||
|
|
||||
|
public String getUsername() { |
||||
|
return username; |
||||
|
} |
||||
|
|
||||
|
public void setUsername(String username) { |
||||
|
this.username = username; |
||||
|
} |
||||
|
|
||||
|
public String getIp() { |
||||
|
return ip; |
||||
|
} |
||||
|
|
||||
|
public void setIp(String ip) { |
||||
|
this.ip = ip; |
||||
|
} |
||||
|
|
||||
|
public Integer getResult() { |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
public void setResult(Integer result) { |
||||
|
this.result = result; |
||||
|
} |
||||
|
|
||||
|
public String getMessage() { |
||||
|
return message; |
||||
|
} |
||||
|
|
||||
|
public void setMessage(String message) { |
||||
|
this.message = message; |
||||
|
} |
||||
|
|
||||
|
public Date getCreateTime() { |
||||
|
return createTime; |
||||
|
} |
||||
|
|
||||
|
public void setCreateTime(Date createTime) { |
||||
|
this.createTime = createTime; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,54 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
|
||||
|
public class Major implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private Integer departmentId; |
||||
|
private String name; |
||||
|
private String code; |
||||
|
private String departmentName; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public Integer getDepartmentId() { |
||||
|
return departmentId; |
||||
|
} |
||||
|
|
||||
|
public void setDepartmentId(Integer departmentId) { |
||||
|
this.departmentId = departmentId; |
||||
|
} |
||||
|
|
||||
|
public String getName() { |
||||
|
return name; |
||||
|
} |
||||
|
|
||||
|
public void setName(String name) { |
||||
|
this.name = name; |
||||
|
} |
||||
|
|
||||
|
public String getCode() { |
||||
|
return code; |
||||
|
} |
||||
|
|
||||
|
public void setCode(String code) { |
||||
|
this.code = code; |
||||
|
} |
||||
|
|
||||
|
public String getDepartmentName() { |
||||
|
return departmentName; |
||||
|
} |
||||
|
|
||||
|
public void setDepartmentName(String departmentName) { |
||||
|
this.departmentName = departmentName; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,82 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
public class Message implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private Integer senderId; |
||||
|
private Integer receiverId; |
||||
|
private String title; |
||||
|
private String content; |
||||
|
private Integer isRead; |
||||
|
private Date createTime; |
||||
|
private String senderName; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public Integer getSenderId() { |
||||
|
return senderId; |
||||
|
} |
||||
|
|
||||
|
public void setSenderId(Integer senderId) { |
||||
|
this.senderId = senderId; |
||||
|
} |
||||
|
|
||||
|
public Integer getReceiverId() { |
||||
|
return receiverId; |
||||
|
} |
||||
|
|
||||
|
public void setReceiverId(Integer receiverId) { |
||||
|
this.receiverId = receiverId; |
||||
|
} |
||||
|
|
||||
|
public String getTitle() { |
||||
|
return title; |
||||
|
} |
||||
|
|
||||
|
public void setTitle(String title) { |
||||
|
this.title = title; |
||||
|
} |
||||
|
|
||||
|
public String getContent() { |
||||
|
return content; |
||||
|
} |
||||
|
|
||||
|
public void setContent(String content) { |
||||
|
this.content = content; |
||||
|
} |
||||
|
|
||||
|
public Integer getIsRead() { |
||||
|
return isRead; |
||||
|
} |
||||
|
|
||||
|
public void setIsRead(Integer isRead) { |
||||
|
this.isRead = isRead; |
||||
|
} |
||||
|
|
||||
|
public Date getCreateTime() { |
||||
|
return createTime; |
||||
|
} |
||||
|
|
||||
|
public void setCreateTime(Date createTime) { |
||||
|
this.createTime = createTime; |
||||
|
} |
||||
|
|
||||
|
public String getSenderName() { |
||||
|
return senderName; |
||||
|
} |
||||
|
|
||||
|
public void setSenderName(String senderName) { |
||||
|
this.senderName = senderName; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
public class OperationLog implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private Integer userId; |
||||
|
private String username; |
||||
|
private String module; |
||||
|
private String action; |
||||
|
private String ip; |
||||
|
private Date createTime; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public Integer getUserId() { |
||||
|
return userId; |
||||
|
} |
||||
|
|
||||
|
public void setUserId(Integer userId) { |
||||
|
this.userId = userId; |
||||
|
} |
||||
|
|
||||
|
public String getUsername() { |
||||
|
return username; |
||||
|
} |
||||
|
|
||||
|
public void setUsername(String username) { |
||||
|
this.username = username; |
||||
|
} |
||||
|
|
||||
|
public String getModule() { |
||||
|
return module; |
||||
|
} |
||||
|
|
||||
|
public void setModule(String module) { |
||||
|
this.module = module; |
||||
|
} |
||||
|
|
||||
|
public String getAction() { |
||||
|
return action; |
||||
|
} |
||||
|
|
||||
|
public void setAction(String action) { |
||||
|
this.action = action; |
||||
|
} |
||||
|
|
||||
|
public String getIp() { |
||||
|
return ip; |
||||
|
} |
||||
|
|
||||
|
public void setIp(String ip) { |
||||
|
this.ip = ip; |
||||
|
} |
||||
|
|
||||
|
public Date getCreateTime() { |
||||
|
return createTime; |
||||
|
} |
||||
|
|
||||
|
public void setCreateTime(Date createTime) { |
||||
|
this.createTime = createTime; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,78 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 分页 JavaBean |
||||
|
*/ |
||||
|
public class PageBean<T> { |
||||
|
|
||||
|
private int currentPage = 1; |
||||
|
private int pageSize = 10; |
||||
|
private int totalCount; |
||||
|
private int totalPage; |
||||
|
private List<T> data; |
||||
|
|
||||
|
public PageBean() { |
||||
|
} |
||||
|
|
||||
|
public PageBean(int currentPage, int pageSize) { |
||||
|
this.currentPage = currentPage > 0 ? currentPage : 1; |
||||
|
this.pageSize = pageSize > 0 ? pageSize : 10; |
||||
|
} |
||||
|
|
||||
|
public int getCurrentPage() { |
||||
|
return currentPage; |
||||
|
} |
||||
|
|
||||
|
public void setCurrentPage(int currentPage) { |
||||
|
this.currentPage = currentPage; |
||||
|
} |
||||
|
|
||||
|
public int getPageSize() { |
||||
|
return pageSize; |
||||
|
} |
||||
|
|
||||
|
public void setPageSize(int pageSize) { |
||||
|
this.pageSize = pageSize; |
||||
|
} |
||||
|
|
||||
|
public int getTotalCount() { |
||||
|
return totalCount; |
||||
|
} |
||||
|
|
||||
|
public void setTotalCount(int totalCount) { |
||||
|
this.totalCount = totalCount; |
||||
|
this.totalPage = (totalCount + pageSize - 1) / pageSize; |
||||
|
if (this.totalPage == 0) { |
||||
|
this.totalPage = 1; |
||||
|
} |
||||
|
if (this.currentPage > this.totalPage) { |
||||
|
this.currentPage = this.totalPage; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public int getTotalPage() { |
||||
|
return totalPage; |
||||
|
} |
||||
|
|
||||
|
public List<T> getData() { |
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
public void setData(List<T> data) { |
||||
|
this.data = data; |
||||
|
} |
||||
|
|
||||
|
public int getStartIndex() { |
||||
|
return (currentPage - 1) * pageSize; |
||||
|
} |
||||
|
|
||||
|
public boolean hasPrevious() { |
||||
|
return currentPage > 1; |
||||
|
} |
||||
|
|
||||
|
public boolean hasNext() { |
||||
|
return currentPage < totalPage; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,46 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
public class RememberToken implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private Integer userId; |
||||
|
private String token; |
||||
|
private Date expireTime; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public Integer getUserId() { |
||||
|
return userId; |
||||
|
} |
||||
|
|
||||
|
public void setUserId(Integer userId) { |
||||
|
this.userId = userId; |
||||
|
} |
||||
|
|
||||
|
public String getToken() { |
||||
|
return token; |
||||
|
} |
||||
|
|
||||
|
public void setToken(String token) { |
||||
|
this.token = token; |
||||
|
} |
||||
|
|
||||
|
public Date getExpireTime() { |
||||
|
return expireTime; |
||||
|
} |
||||
|
|
||||
|
public void setExpireTime(Date expireTime) { |
||||
|
this.expireTime = expireTime; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,82 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.math.BigDecimal; |
||||
|
|
||||
|
public class Score implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private Integer studentId; |
||||
|
private Integer courseId; |
||||
|
private BigDecimal score; |
||||
|
private String remark; |
||||
|
private String studentName; |
||||
|
private String studentNo; |
||||
|
private String courseName; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public Integer getStudentId() { |
||||
|
return studentId; |
||||
|
} |
||||
|
|
||||
|
public void setStudentId(Integer studentId) { |
||||
|
this.studentId = studentId; |
||||
|
} |
||||
|
|
||||
|
public Integer getCourseId() { |
||||
|
return courseId; |
||||
|
} |
||||
|
|
||||
|
public void setCourseId(Integer courseId) { |
||||
|
this.courseId = courseId; |
||||
|
} |
||||
|
|
||||
|
public BigDecimal getScore() { |
||||
|
return score; |
||||
|
} |
||||
|
|
||||
|
public void setScore(BigDecimal score) { |
||||
|
this.score = score; |
||||
|
} |
||||
|
|
||||
|
public String getRemark() { |
||||
|
return remark; |
||||
|
} |
||||
|
|
||||
|
public void setRemark(String remark) { |
||||
|
this.remark = remark; |
||||
|
} |
||||
|
|
||||
|
public String getStudentName() { |
||||
|
return studentName; |
||||
|
} |
||||
|
|
||||
|
public void setStudentName(String studentName) { |
||||
|
this.studentName = studentName; |
||||
|
} |
||||
|
|
||||
|
public String getStudentNo() { |
||||
|
return studentNo; |
||||
|
} |
||||
|
|
||||
|
public void setStudentNo(String studentNo) { |
||||
|
this.studentNo = studentNo; |
||||
|
} |
||||
|
|
||||
|
public String getCourseName() { |
||||
|
return courseName; |
||||
|
} |
||||
|
|
||||
|
public void setCourseName(String courseName) { |
||||
|
this.courseName = courseName; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,250 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
/** |
||||
|
* 用户 JavaBean |
||||
|
*/ |
||||
|
public class User implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
/** 0=学生 */ |
||||
|
public static final int ROLE_STUDENT = 0; |
||||
|
public static final int ROLE_USER = ROLE_STUDENT; |
||||
|
public static final int ROLE_ADMIN = 1; |
||||
|
public static final int ROLE_TEACHER = 2; |
||||
|
|
||||
|
/** 0=待审核 1=在读 2=休学 3=毕业 4=退学 */ |
||||
|
public static final int STATUS_PENDING = 0; |
||||
|
public static final int STATUS_ACTIVE = 1; |
||||
|
public static final int STATUS_SUSPEND = 2; |
||||
|
public static final int STATUS_GRAD = 3; |
||||
|
public static final int STATUS_GRADUATED = STATUS_GRAD; |
||||
|
public static final int STATUS_DROP = 4; |
||||
|
public static final int STATUS_DROPPED = STATUS_DROP; |
||||
|
|
||||
|
private Integer id; |
||||
|
private String username; |
||||
|
private String password; |
||||
|
private String salt; |
||||
|
private String studentNo; |
||||
|
private String realName; |
||||
|
private String gender; |
||||
|
private Integer age; |
||||
|
private String email; |
||||
|
private String phone; |
||||
|
private String address; |
||||
|
private String avatar; |
||||
|
private Integer clazzId; |
||||
|
private Integer role; |
||||
|
private Integer status; |
||||
|
private Integer failCount; |
||||
|
private Date lockUntil; |
||||
|
private Date createTime; |
||||
|
|
||||
|
private String clazzName; |
||||
|
private String majorName; |
||||
|
private String departmentName; |
||||
|
|
||||
|
public User() { |
||||
|
} |
||||
|
|
||||
|
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 getSalt() { |
||||
|
return salt; |
||||
|
} |
||||
|
|
||||
|
public void setSalt(String salt) { |
||||
|
this.salt = salt; |
||||
|
} |
||||
|
|
||||
|
public String getStudentNo() { |
||||
|
return studentNo; |
||||
|
} |
||||
|
|
||||
|
public void setStudentNo(String studentNo) { |
||||
|
this.studentNo = studentNo; |
||||
|
} |
||||
|
|
||||
|
public String getRealName() { |
||||
|
return realName; |
||||
|
} |
||||
|
|
||||
|
public void setRealName(String realName) { |
||||
|
this.realName = realName; |
||||
|
} |
||||
|
|
||||
|
public String getGender() { |
||||
|
return gender; |
||||
|
} |
||||
|
|
||||
|
public void setGender(String gender) { |
||||
|
this.gender = gender; |
||||
|
} |
||||
|
|
||||
|
public Integer getAge() { |
||||
|
return age; |
||||
|
} |
||||
|
|
||||
|
public void setAge(Integer age) { |
||||
|
this.age = age; |
||||
|
} |
||||
|
|
||||
|
public String getEmail() { |
||||
|
return email; |
||||
|
} |
||||
|
|
||||
|
public void setEmail(String email) { |
||||
|
this.email = email; |
||||
|
} |
||||
|
|
||||
|
public String getPhone() { |
||||
|
return phone; |
||||
|
} |
||||
|
|
||||
|
public void setPhone(String phone) { |
||||
|
this.phone = phone; |
||||
|
} |
||||
|
|
||||
|
public String getAddress() { |
||||
|
return address; |
||||
|
} |
||||
|
|
||||
|
public void setAddress(String address) { |
||||
|
this.address = address; |
||||
|
} |
||||
|
|
||||
|
public String getAvatar() { |
||||
|
return avatar; |
||||
|
} |
||||
|
|
||||
|
public void setAvatar(String avatar) { |
||||
|
this.avatar = avatar; |
||||
|
} |
||||
|
|
||||
|
public Integer getClazzId() { |
||||
|
return clazzId; |
||||
|
} |
||||
|
|
||||
|
public void setClazzId(Integer clazzId) { |
||||
|
this.clazzId = clazzId; |
||||
|
} |
||||
|
|
||||
|
public Integer getRole() { |
||||
|
return role; |
||||
|
} |
||||
|
|
||||
|
public void setRole(Integer role) { |
||||
|
this.role = role; |
||||
|
} |
||||
|
|
||||
|
public Integer getStatus() { |
||||
|
return status; |
||||
|
} |
||||
|
|
||||
|
public void setStatus(Integer status) { |
||||
|
this.status = status; |
||||
|
} |
||||
|
|
||||
|
public Integer getFailCount() { |
||||
|
return failCount; |
||||
|
} |
||||
|
|
||||
|
public void setFailCount(Integer failCount) { |
||||
|
this.failCount = failCount; |
||||
|
} |
||||
|
|
||||
|
public Date getLockUntil() { |
||||
|
return lockUntil; |
||||
|
} |
||||
|
|
||||
|
public void setLockUntil(Date lockUntil) { |
||||
|
this.lockUntil = lockUntil; |
||||
|
} |
||||
|
|
||||
|
public Date getCreateTime() { |
||||
|
return createTime; |
||||
|
} |
||||
|
|
||||
|
public void setCreateTime(Date createTime) { |
||||
|
this.createTime = createTime; |
||||
|
} |
||||
|
|
||||
|
public String getClazzName() { |
||||
|
return clazzName; |
||||
|
} |
||||
|
|
||||
|
public void setClazzName(String clazzName) { |
||||
|
this.clazzName = clazzName; |
||||
|
} |
||||
|
|
||||
|
public String getMajorName() { |
||||
|
return majorName; |
||||
|
} |
||||
|
|
||||
|
public void setMajorName(String majorName) { |
||||
|
this.majorName = majorName; |
||||
|
} |
||||
|
|
||||
|
public String getDepartmentName() { |
||||
|
return departmentName; |
||||
|
} |
||||
|
|
||||
|
public void setDepartmentName(String departmentName) { |
||||
|
this.departmentName = departmentName; |
||||
|
} |
||||
|
|
||||
|
public String getDeptName() { |
||||
|
return departmentName; |
||||
|
} |
||||
|
|
||||
|
public void setDeptName(String deptName) { |
||||
|
this.departmentName = deptName; |
||||
|
} |
||||
|
|
||||
|
public boolean isAdmin() { |
||||
|
return role != null && role == ROLE_ADMIN; |
||||
|
} |
||||
|
|
||||
|
public boolean isTeacher() { |
||||
|
return role != null && role == ROLE_TEACHER; |
||||
|
} |
||||
|
|
||||
|
public boolean isStudent() { |
||||
|
return role != null && role == ROLE_STUDENT; |
||||
|
} |
||||
|
|
||||
|
public boolean isActive() { |
||||
|
return status != null && status == STATUS_ACTIVE; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public String toString() { |
||||
|
return "User{id=" + id + ", username='" + username + "', realName='" + realName + "'}"; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,109 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
public class UserImportTemp implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private Integer id; |
||||
|
private String batchId; |
||||
|
private String username; |
||||
|
private String password; |
||||
|
private String realName; |
||||
|
private String gender; |
||||
|
private Integer age; |
||||
|
private String email; |
||||
|
private String phone; |
||||
|
private String address; |
||||
|
private Date createTime; |
||||
|
|
||||
|
public Integer getId() { |
||||
|
return id; |
||||
|
} |
||||
|
|
||||
|
public void setId(Integer id) { |
||||
|
this.id = id; |
||||
|
} |
||||
|
|
||||
|
public String getBatchId() { |
||||
|
return batchId; |
||||
|
} |
||||
|
|
||||
|
public void setBatchId(String batchId) { |
||||
|
this.batchId = batchId; |
||||
|
} |
||||
|
|
||||
|
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 getRealName() { |
||||
|
return realName; |
||||
|
} |
||||
|
|
||||
|
public void setRealName(String realName) { |
||||
|
this.realName = realName; |
||||
|
} |
||||
|
|
||||
|
public String getGender() { |
||||
|
return gender; |
||||
|
} |
||||
|
|
||||
|
public void setGender(String gender) { |
||||
|
this.gender = gender; |
||||
|
} |
||||
|
|
||||
|
public Integer getAge() { |
||||
|
return age; |
||||
|
} |
||||
|
|
||||
|
public void setAge(Integer age) { |
||||
|
this.age = age; |
||||
|
} |
||||
|
|
||||
|
public String getEmail() { |
||||
|
return email; |
||||
|
} |
||||
|
|
||||
|
public void setEmail(String email) { |
||||
|
this.email = email; |
||||
|
} |
||||
|
|
||||
|
public String getPhone() { |
||||
|
return phone; |
||||
|
} |
||||
|
|
||||
|
public void setPhone(String phone) { |
||||
|
this.phone = phone; |
||||
|
} |
||||
|
|
||||
|
public String getAddress() { |
||||
|
return address; |
||||
|
} |
||||
|
|
||||
|
public void setAddress(String address) { |
||||
|
this.address = address; |
||||
|
} |
||||
|
|
||||
|
public Date getCreateTime() { |
||||
|
return createTime; |
||||
|
} |
||||
|
|
||||
|
public void setCreateTime(Date createTime) { |
||||
|
this.createTime = createTime; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,90 @@ |
|||||
|
package com.student.bean; |
||||
|
|
||||
|
import java.io.Serializable; |
||||
|
|
||||
|
public class UserQuery implements Serializable { |
||||
|
|
||||
|
private static final long serialVersionUID = 1L; |
||||
|
|
||||
|
private String keyword; |
||||
|
private Integer clazzId; |
||||
|
private String gender; |
||||
|
private Integer ageMin; |
||||
|
private Integer ageMax; |
||||
|
private Integer status; |
||||
|
private Integer role; |
||||
|
private int currentPage = 1; |
||||
|
private int pageSize = 10; |
||||
|
|
||||
|
public String getKeyword() { |
||||
|
return keyword; |
||||
|
} |
||||
|
|
||||
|
public void setKeyword(String keyword) { |
||||
|
this.keyword = keyword; |
||||
|
} |
||||
|
|
||||
|
public Integer getClazzId() { |
||||
|
return clazzId; |
||||
|
} |
||||
|
|
||||
|
public void setClazzId(Integer clazzId) { |
||||
|
this.clazzId = clazzId; |
||||
|
} |
||||
|
|
||||
|
public String getGender() { |
||||
|
return gender; |
||||
|
} |
||||
|
|
||||
|
public void setGender(String gender) { |
||||
|
this.gender = gender; |
||||
|
} |
||||
|
|
||||
|
public Integer getAgeMin() { |
||||
|
return ageMin; |
||||
|
} |
||||
|
|
||||
|
public void setAgeMin(Integer ageMin) { |
||||
|
this.ageMin = ageMin; |
||||
|
} |
||||
|
|
||||
|
public Integer getAgeMax() { |
||||
|
return ageMax; |
||||
|
} |
||||
|
|
||||
|
public void setAgeMax(Integer ageMax) { |
||||
|
this.ageMax = ageMax; |
||||
|
} |
||||
|
|
||||
|
public Integer getStatus() { |
||||
|
return status; |
||||
|
} |
||||
|
|
||||
|
public void setStatus(Integer status) { |
||||
|
this.status = status; |
||||
|
} |
||||
|
|
||||
|
public Integer getRole() { |
||||
|
return role; |
||||
|
} |
||||
|
|
||||
|
public void setRole(Integer role) { |
||||
|
this.role = role; |
||||
|
} |
||||
|
|
||||
|
public int getCurrentPage() { |
||||
|
return currentPage; |
||||
|
} |
||||
|
|
||||
|
public void setCurrentPage(int currentPage) { |
||||
|
this.currentPage = currentPage; |
||||
|
} |
||||
|
|
||||
|
public int getPageSize() { |
||||
|
return pageSize; |
||||
|
} |
||||
|
|
||||
|
public void setPageSize(int pageSize) { |
||||
|
this.pageSize = pageSize; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.Announcement; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface AnnouncementDao { |
||||
|
|
||||
|
Announcement findById(int id); |
||||
|
|
||||
|
boolean insert(Announcement announcement); |
||||
|
|
||||
|
boolean update(Announcement announcement); |
||||
|
|
||||
|
boolean delete(int id); |
||||
|
|
||||
|
List<Announcement> findAll(); |
||||
|
|
||||
|
List<Announcement> findActive(); |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.Attendance; |
||||
|
import com.student.bean.AttendanceStats; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface AttendanceDao { |
||||
|
|
||||
|
boolean saveBatch(List<Attendance> records); |
||||
|
|
||||
|
List<Attendance> findByStudent(int studentId); |
||||
|
|
||||
|
List<Attendance> findByCourse(int courseId); |
||||
|
|
||||
|
List<Attendance> findRecent(int limit); |
||||
|
|
||||
|
AttendanceStats getStatsByStudent(int studentId); |
||||
|
|
||||
|
AttendanceStats getStatsByClazz(int clazzId); |
||||
|
|
||||
|
AttendanceStats getStatsByCourse(int courseId); |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.ChangeRequest; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface ChangeRequestDao { |
||||
|
|
||||
|
boolean submit(ChangeRequest request); |
||||
|
|
||||
|
boolean approve(int id, int approverId, String note); |
||||
|
|
||||
|
boolean reject(int id, int approverId, String note); |
||||
|
|
||||
|
List<ChangeRequest> findPending(); |
||||
|
|
||||
|
ChangeRequest findById(int id); |
||||
|
|
||||
|
List<ChangeRequest> findByUser(int userId); |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.Course; |
||||
|
import com.student.bean.PageBean; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface CourseDao { |
||||
|
|
||||
|
Course findById(int id); |
||||
|
|
||||
|
Course findByCourseNo(String courseNo); |
||||
|
|
||||
|
boolean insert(Course course); |
||||
|
|
||||
|
boolean update(Course course); |
||||
|
|
||||
|
boolean delete(int id); |
||||
|
|
||||
|
int count(String keyword); |
||||
|
|
||||
|
List<Course> findList(String keyword, int startIndex, int pageSize); |
||||
|
|
||||
|
PageBean<Course> findPage(String keyword, int currentPage, int pageSize); |
||||
|
|
||||
|
List<Course> findByTeacher(int teacherId); |
||||
|
|
||||
|
List<Course> findAll(); |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.Enrollment; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface EnrollmentDao { |
||||
|
|
||||
|
boolean enroll(int studentId, int courseId); |
||||
|
|
||||
|
boolean cancel(int studentId, int courseId); |
||||
|
|
||||
|
boolean exists(int studentId, int courseId); |
||||
|
|
||||
|
List<Enrollment> findByStudent(int studentId); |
||||
|
|
||||
|
List<Enrollment> findByCourse(int courseId); |
||||
|
|
||||
|
int countByCourse(int courseId); |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.UserImportTemp; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface ImportTempDao { |
||||
|
|
||||
|
boolean batchInsert(List<UserImportTemp> records); |
||||
|
|
||||
|
List<UserImportTemp> findByBatch(String batchId); |
||||
|
|
||||
|
boolean deleteBatch(String batchId); |
||||
|
|
||||
|
int confirmImport(String batchId); |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.LeaveRequest; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface LeaveDao { |
||||
|
|
||||
|
boolean submit(LeaveRequest request); |
||||
|
|
||||
|
boolean approve(int id, int approverId, String note); |
||||
|
|
||||
|
boolean reject(int id, int approverId, String note); |
||||
|
|
||||
|
List<LeaveRequest> findPending(); |
||||
|
|
||||
|
List<LeaveRequest> findByStudent(int studentId); |
||||
|
|
||||
|
LeaveRequest findById(int id); |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.LoginLog; |
||||
|
import com.student.bean.OperationLog; |
||||
|
import com.student.bean.PageBean; |
||||
|
|
||||
|
public interface LogDao { |
||||
|
|
||||
|
boolean saveLoginLog(LoginLog log); |
||||
|
|
||||
|
boolean saveOperationLog(OperationLog log); |
||||
|
|
||||
|
PageBean<LoginLog> findLoginLogs(int currentPage, int pageSize); |
||||
|
|
||||
|
PageBean<OperationLog> findOperationLogs(int currentPage, int pageSize); |
||||
|
} |
||||
@ -0,0 +1,20 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.Message; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface MessageDao { |
||||
|
|
||||
|
boolean send(Message message); |
||||
|
|
||||
|
boolean sendAll(Message message); |
||||
|
|
||||
|
List<Message> findInbox(int receiverId); |
||||
|
|
||||
|
int countUnread(int receiverId); |
||||
|
|
||||
|
boolean markRead(int messageId); |
||||
|
|
||||
|
boolean markAllRead(int receiverId); |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.Clazz; |
||||
|
import com.student.bean.Department; |
||||
|
import com.student.bean.Major; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface OrgDao { |
||||
|
|
||||
|
List<Department> findAllDepts(); |
||||
|
|
||||
|
Department findDeptById(int id); |
||||
|
|
||||
|
boolean insertDept(Department dept); |
||||
|
|
||||
|
boolean updateDept(Department dept); |
||||
|
|
||||
|
boolean deleteDept(int id); |
||||
|
|
||||
|
List<Major> findMajorsByDept(int deptId); |
||||
|
|
||||
|
List<Major> findAllMajors(); |
||||
|
|
||||
|
Major findMajorById(int id); |
||||
|
|
||||
|
boolean insertMajor(Major major); |
||||
|
|
||||
|
boolean updateMajor(Major major); |
||||
|
|
||||
|
boolean deleteMajor(int id); |
||||
|
|
||||
|
List<Clazz> findClazzByMajor(int majorId); |
||||
|
|
||||
|
List<Clazz> findAllClazz(); |
||||
|
|
||||
|
Clazz findClazzById(int id); |
||||
|
|
||||
|
boolean insertClazz(Clazz clazz); |
||||
|
|
||||
|
boolean updateClazz(Clazz clazz); |
||||
|
|
||||
|
boolean deleteClazz(int id); |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.RememberToken; |
||||
|
|
||||
|
public interface RememberTokenDao { |
||||
|
|
||||
|
boolean save(RememberToken token); |
||||
|
|
||||
|
RememberToken findByToken(String token); |
||||
|
|
||||
|
boolean deleteByUser(int userId); |
||||
|
|
||||
|
int deleteExpired(); |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.CourseStats; |
||||
|
import com.student.bean.Score; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public interface ScoreDao { |
||||
|
|
||||
|
boolean saveOrUpdate(Score score); |
||||
|
|
||||
|
boolean saveOrUpdateBatch(List<Score> scores); |
||||
|
|
||||
|
List<Score> findByStudent(int studentId); |
||||
|
|
||||
|
List<Score> findByCourse(int courseId); |
||||
|
|
||||
|
CourseStats getCourseStats(int courseId); |
||||
|
} |
||||
@ -0,0 +1,16 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.DashboardStats; |
||||
|
|
||||
|
import java.util.Map; |
||||
|
|
||||
|
public interface StatDao { |
||||
|
|
||||
|
DashboardStats getDashboardStats(); |
||||
|
|
||||
|
Map<String, Integer> genderDistribution(); |
||||
|
|
||||
|
Map<String, Integer> ageDistribution(); |
||||
|
|
||||
|
Map<String, Integer> deptDistribution(); |
||||
|
} |
||||
@ -0,0 +1,52 @@ |
|||||
|
package com.student.dao; |
||||
|
|
||||
|
import com.student.bean.PageBean; |
||||
|
import com.student.bean.User; |
||||
|
import com.student.bean.UserQuery; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 用户 DAO 接口 |
||||
|
*/ |
||||
|
public interface UserDao { |
||||
|
|
||||
|
User findByUsername(String username); |
||||
|
|
||||
|
User findById(int id); |
||||
|
|
||||
|
User findByStudentNo(String studentNo); |
||||
|
|
||||
|
boolean insert(User user); |
||||
|
|
||||
|
boolean update(User user); |
||||
|
|
||||
|
boolean updateProfile(User user); |
||||
|
|
||||
|
boolean updateAvatar(int userId, String avatar); |
||||
|
|
||||
|
boolean delete(int id); |
||||
|
|
||||
|
int count(UserQuery query); |
||||
|
|
||||
|
List<User> findList(UserQuery query, int startIndex, int pageSize); |
||||
|
|
||||
|
PageBean<User> findPage(UserQuery query); |
||||
|
|
||||
|
PageBean<User> findPendingRegister(int currentPage, int pageSize); |
||||
|
|
||||
|
boolean updatePassword(int userId, String password, String salt); |
||||
|
|
||||
|
boolean updateFailCount(int userId, int failCount); |
||||
|
|
||||
|
boolean lockUser(int userId, java.util.Date lockUntil); |
||||
|
|
||||
|
boolean updateStatus(int userId, int status); |
||||
|
|
||||
|
List<User> findAllStudents(); |
||||
|
|
||||
|
List<User> findAllTeachers(); |
||||
|
|
||||
|
/** 兼容旧版登录 */ |
||||
|
User findByUsernameAndPassword(String username, String password); |
||||
|
} |
||||
@ -0,0 +1,155 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.Announcement; |
||||
|
import com.student.dao.AnnouncementDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import java.sql.Connection; |
||||
|
import java.sql.Date; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.sql.Timestamp; |
||||
|
import java.sql.Types; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class AnnouncementDaoImpl implements AnnouncementDao { |
||||
|
|
||||
|
private static final String BASE_SQL = |
||||
|
"SELECT a.id, a.title, a.content, a.publisher_id, a.is_top, a.expire_date, a.create_time, " |
||||
|
+ "u.real_name AS publisher_name FROM announcement a " |
||||
|
+ "LEFT JOIN users u ON a.publisher_id = u.id "; |
||||
|
|
||||
|
@Override |
||||
|
public Announcement findById(int id) { |
||||
|
List<Announcement> list = queryList(BASE_SQL + " WHERE a.id = ?", id); |
||||
|
return list.isEmpty() ? null : list.get(0); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean insert(Announcement announcement) { |
||||
|
String sql = "INSERT INTO announcement (title, content, publisher_id, is_top, expire_date) VALUES (?, ?, ?, ?, ?)"; |
||||
|
return executeUpdate(sql, announcement); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean update(Announcement announcement) { |
||||
|
String sql = "UPDATE announcement SET title=?, content=?, publisher_id=?, is_top=?, expire_date=? WHERE id=?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
fillParams(ps, announcement); |
||||
|
ps.setInt(6, announcement.getId()); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("更新公告失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean delete(int id) { |
||||
|
String sql = "DELETE FROM announcement WHERE id = ?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, id); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("删除公告失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Announcement> findAll() { |
||||
|
return queryList(BASE_SQL + " ORDER BY a.is_top DESC, a.create_time DESC"); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Announcement> findActive() { |
||||
|
return queryList(BASE_SQL + " WHERE (a.expire_date IS NULL OR a.expire_date >= CURDATE()) " |
||||
|
+ "ORDER BY a.is_top DESC, a.create_time DESC"); |
||||
|
} |
||||
|
|
||||
|
private boolean executeUpdate(String sql, Announcement announcement) { |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
fillParams(ps, announcement); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("保存公告失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void fillParams(PreparedStatement ps, Announcement a) throws SQLException { |
||||
|
ps.setString(1, a.getTitle()); |
||||
|
ps.setString(2, a.getContent()); |
||||
|
if (a.getPublisherId() != null) { |
||||
|
ps.setInt(3, a.getPublisherId()); |
||||
|
} else { |
||||
|
ps.setNull(3, Types.INTEGER); |
||||
|
} |
||||
|
ps.setInt(4, a.getIsTop() != null ? a.getIsTop() : 0); |
||||
|
if (a.getExpireDate() != null) { |
||||
|
ps.setDate(5, new Date(a.getExpireDate().getTime())); |
||||
|
} else { |
||||
|
ps.setNull(5, Types.DATE); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private List<Announcement> queryList(String sql, Object... params) { |
||||
|
List<Announcement> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
for (int i = 0; i < params.length; i++) { |
||||
|
ps.setObject(i + 1, params[i]); |
||||
|
} |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapRow(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询公告失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
private Announcement mapRow(ResultSet rs) throws SQLException { |
||||
|
Announcement a = new Announcement(); |
||||
|
a.setId(rs.getInt("id")); |
||||
|
a.setTitle(rs.getString("title")); |
||||
|
a.setContent(rs.getString("content")); |
||||
|
int publisherId = rs.getInt("publisher_id"); |
||||
|
a.setPublisherId(rs.wasNull() ? null : publisherId); |
||||
|
a.setIsTop(rs.getInt("is_top")); |
||||
|
Date expireDate = rs.getDate("expire_date"); |
||||
|
if (expireDate != null) { |
||||
|
a.setExpireDate(new java.util.Date(expireDate.getTime())); |
||||
|
} |
||||
|
Timestamp createTime = rs.getTimestamp("create_time"); |
||||
|
if (createTime != null) { |
||||
|
a.setCreateTime(new java.util.Date(createTime.getTime())); |
||||
|
} |
||||
|
a.setPublisherName(rs.getString("publisher_name")); |
||||
|
return a; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,177 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.Attendance; |
||||
|
import com.student.bean.AttendanceStats; |
||||
|
import com.student.dao.AttendanceDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import java.sql.Connection; |
||||
|
import java.sql.Date; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.sql.Timestamp; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class AttendanceDaoImpl implements AttendanceDao { |
||||
|
|
||||
|
private static final String BASE_SQL = |
||||
|
"SELECT a.id, a.student_id, a.course_id, a.att_date, a.status, a.remark, " |
||||
|
+ "u.real_name AS student_name, c.name AS course_name " |
||||
|
+ "FROM attendance a " |
||||
|
+ "JOIN users u ON a.student_id = u.id " |
||||
|
+ "JOIN course c ON a.course_id = c.id "; |
||||
|
|
||||
|
@Override |
||||
|
public boolean saveBatch(List<Attendance> records) { |
||||
|
if (records == null || records.isEmpty()) { |
||||
|
return true; |
||||
|
} |
||||
|
String sql = "INSERT INTO attendance (student_id, course_id, att_date, status, remark) " |
||||
|
+ "VALUES (?, ?, ?, ?, ?) " |
||||
|
+ "ON DUPLICATE KEY UPDATE status=VALUES(status), remark=VALUES(remark)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
for (Attendance att : records) { |
||||
|
ps.setInt(1, att.getStudentId()); |
||||
|
ps.setInt(2, att.getCourseId()); |
||||
|
ps.setDate(3, new Date(att.getAttDate().getTime())); |
||||
|
ps.setInt(4, att.getStatus()); |
||||
|
ps.setString(5, att.getRemark()); |
||||
|
ps.addBatch(); |
||||
|
} |
||||
|
ps.executeBatch(); |
||||
|
return true; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("批量保存考勤失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Attendance> findByStudent(int studentId) { |
||||
|
return queryList(BASE_SQL + " WHERE a.student_id = ? ORDER BY a.att_date DESC", studentId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Attendance> findByCourse(int courseId) { |
||||
|
return queryList(BASE_SQL + " WHERE a.course_id = ? ORDER BY a.att_date DESC", courseId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Attendance> findRecent(int limit) { |
||||
|
int size = limit > 0 ? limit : 50; |
||||
|
List<Attendance> list = new ArrayList<>(); |
||||
|
String sql = BASE_SQL + " ORDER BY a.att_date DESC, a.id DESC LIMIT ?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, size); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapRow(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询最近考勤记录失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public AttendanceStats getStatsByStudent(int studentId) { |
||||
|
String sql = "SELECT status, COUNT(*) AS cnt FROM attendance WHERE student_id = ? GROUP BY status"; |
||||
|
return queryStats(sql, studentId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public AttendanceStats getStatsByClazz(int clazzId) { |
||||
|
String sql = "SELECT a.status, COUNT(*) AS cnt FROM attendance a " |
||||
|
+ "JOIN users u ON a.student_id = u.id WHERE u.clazz_id = ? GROUP BY a.status"; |
||||
|
return queryStats(sql, clazzId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public AttendanceStats getStatsByCourse(int courseId) { |
||||
|
String sql = "SELECT status, COUNT(*) AS cnt FROM attendance WHERE course_id = ? GROUP BY status"; |
||||
|
return queryStats(sql, courseId); |
||||
|
} |
||||
|
|
||||
|
private AttendanceStats queryStats(String sql, int id) { |
||||
|
AttendanceStats stats = new AttendanceStats(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, id); |
||||
|
rs = ps.executeQuery(); |
||||
|
int total = 0; |
||||
|
while (rs.next()) { |
||||
|
int status = rs.getInt("status"); |
||||
|
int cnt = rs.getInt("cnt"); |
||||
|
total += cnt; |
||||
|
if (status == Attendance.STATUS_PRESENT) { |
||||
|
stats.setPresent(cnt); |
||||
|
} else if (status == Attendance.STATUS_LATE) { |
||||
|
stats.setLate(cnt); |
||||
|
} else if (status == Attendance.STATUS_ABSENT) { |
||||
|
stats.setAbsent(cnt); |
||||
|
} |
||||
|
} |
||||
|
stats.setTotal(total); |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询考勤统计失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return stats; |
||||
|
} |
||||
|
|
||||
|
private List<Attendance> queryList(String sql, int id) { |
||||
|
List<Attendance> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, id); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapRow(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询考勤记录失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
private Attendance mapRow(ResultSet rs) throws SQLException { |
||||
|
Attendance att = new Attendance(); |
||||
|
att.setId(rs.getInt("id")); |
||||
|
att.setStudentId(rs.getInt("student_id")); |
||||
|
att.setCourseId(rs.getInt("course_id")); |
||||
|
Date attDate = rs.getDate("att_date"); |
||||
|
if (attDate != null) { |
||||
|
att.setAttDate(new java.util.Date(attDate.getTime())); |
||||
|
} |
||||
|
att.setStatus(rs.getInt("status")); |
||||
|
att.setRemark(rs.getString("remark")); |
||||
|
att.setStudentName(rs.getString("student_name")); |
||||
|
att.setCourseName(rs.getString("course_name")); |
||||
|
return att; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,135 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.ChangeRequest; |
||||
|
import com.student.dao.ChangeRequestDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import java.sql.Connection; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.sql.Timestamp; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class ChangeRequestDaoImpl implements ChangeRequestDao { |
||||
|
|
||||
|
private static final String BASE_SQL = |
||||
|
"SELECT cr.id, cr.user_id, cr.field_name, cr.old_value, cr.new_value, cr.status, " |
||||
|
+ "cr.approver_id, cr.approve_note, cr.create_time, " |
||||
|
+ "u.username, u.real_name, a.real_name AS approver_name " |
||||
|
+ "FROM change_request cr " |
||||
|
+ "JOIN users u ON cr.user_id = u.id " |
||||
|
+ "LEFT JOIN users a ON cr.approver_id = a.id "; |
||||
|
|
||||
|
@Override |
||||
|
public boolean submit(ChangeRequest request) { |
||||
|
String sql = "INSERT INTO change_request (user_id, field_name, old_value, new_value, status) " |
||||
|
+ "VALUES (?, ?, ?, ?, ?)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, request.getUserId()); |
||||
|
ps.setString(2, request.getFieldName()); |
||||
|
ps.setString(3, request.getOldValue()); |
||||
|
ps.setString(4, request.getNewValue()); |
||||
|
ps.setInt(5, ChangeRequest.STATUS_PENDING); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("提交变更申请失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean approve(int id, int approverId, String note) { |
||||
|
return updateStatus(id, approverId, note, ChangeRequest.STATUS_APPROVED); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean reject(int id, int approverId, String note) { |
||||
|
return updateStatus(id, approverId, note, ChangeRequest.STATUS_REJECTED); |
||||
|
} |
||||
|
|
||||
|
private boolean updateStatus(int id, int approverId, String note, int status) { |
||||
|
String sql = "UPDATE change_request SET status=?, approver_id=?, approve_note=? WHERE id=?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, status); |
||||
|
ps.setInt(2, approverId); |
||||
|
ps.setString(3, note); |
||||
|
ps.setInt(4, id); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("审批变更申请失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<ChangeRequest> findPending() { |
||||
|
return queryList(BASE_SQL + " WHERE cr.status = 0 ORDER BY cr.create_time ASC"); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public ChangeRequest findById(int id) { |
||||
|
List<ChangeRequest> list = queryList(BASE_SQL + " WHERE cr.id = ?", id); |
||||
|
return list.isEmpty() ? null : list.get(0); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<ChangeRequest> findByUser(int userId) { |
||||
|
return queryList(BASE_SQL + " WHERE cr.user_id = ? ORDER BY cr.create_time DESC", userId); |
||||
|
} |
||||
|
|
||||
|
private List<ChangeRequest> queryList(String sql, Object... params) { |
||||
|
List<ChangeRequest> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
for (int i = 0; i < params.length; i++) { |
||||
|
ps.setObject(i + 1, params[i]); |
||||
|
} |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapRow(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询变更申请失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
private ChangeRequest mapRow(ResultSet rs) throws SQLException { |
||||
|
ChangeRequest cr = new ChangeRequest(); |
||||
|
cr.setId(rs.getInt("id")); |
||||
|
cr.setUserId(rs.getInt("user_id")); |
||||
|
cr.setFieldName(rs.getString("field_name")); |
||||
|
cr.setOldValue(rs.getString("old_value")); |
||||
|
cr.setNewValue(rs.getString("new_value")); |
||||
|
cr.setStatus(rs.getInt("status")); |
||||
|
int approverId = rs.getInt("approver_id"); |
||||
|
cr.setApproverId(rs.wasNull() ? null : approverId); |
||||
|
cr.setApproveNote(rs.getString("approve_note")); |
||||
|
Timestamp createTime = rs.getTimestamp("create_time"); |
||||
|
if (createTime != null) { |
||||
|
cr.setCreateTime(new java.util.Date(createTime.getTime())); |
||||
|
} |
||||
|
cr.setUsername(rs.getString("username")); |
||||
|
cr.setRealName(rs.getString("real_name")); |
||||
|
cr.setApproverName(rs.getString("approver_name")); |
||||
|
return cr; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,260 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.Course; |
||||
|
import com.student.bean.PageBean; |
||||
|
import com.student.dao.CourseDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
import java.sql.Connection; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.sql.Timestamp; |
||||
|
import java.sql.Types; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class CourseDaoImpl implements CourseDao { |
||||
|
|
||||
|
private static final String BASE_SQL = |
||||
|
"SELECT c.id, c.course_no, c.name, c.credit, c.teacher_id, c.max_students, c.schedule, c.create_time, " |
||||
|
+ "u.real_name AS teacher_name, " |
||||
|
+ "(SELECT COUNT(*) FROM enrollment e WHERE e.course_id = c.id) AS enrolled_count " |
||||
|
+ "FROM course c LEFT JOIN users u ON c.teacher_id = u.id "; |
||||
|
|
||||
|
@Override |
||||
|
public Course findById(int id) { |
||||
|
return queryOne(BASE_SQL + " WHERE c.id = ?", id); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Course findByCourseNo(String courseNo) { |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(BASE_SQL + " WHERE c.course_no = ?"); |
||||
|
ps.setString(1, courseNo); |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return mapRow(rs); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询课程失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean insert(Course course) { |
||||
|
String sql = "INSERT INTO course (course_no, name, credit, teacher_id, max_students, schedule) " |
||||
|
+ "VALUES (?, ?, ?, ?, ?, ?)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setString(1, course.getCourseNo()); |
||||
|
ps.setString(2, course.getName()); |
||||
|
ps.setBigDecimal(3, course.getCredit() != null ? course.getCredit() : new BigDecimal("2.0")); |
||||
|
if (course.getTeacherId() != null) { |
||||
|
ps.setInt(4, course.getTeacherId()); |
||||
|
} else { |
||||
|
ps.setNull(4, Types.INTEGER); |
||||
|
} |
||||
|
ps.setInt(5, course.getMaxStudents() != null ? course.getMaxStudents() : 50); |
||||
|
ps.setString(6, course.getSchedule()); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("新增课程失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean update(Course course) { |
||||
|
String sql = "UPDATE course SET course_no=?, name=?, credit=?, teacher_id=?, max_students=?, schedule=? WHERE id=?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setString(1, course.getCourseNo()); |
||||
|
ps.setString(2, course.getName()); |
||||
|
ps.setBigDecimal(3, course.getCredit()); |
||||
|
if (course.getTeacherId() != null) { |
||||
|
ps.setInt(4, course.getTeacherId()); |
||||
|
} else { |
||||
|
ps.setNull(4, Types.INTEGER); |
||||
|
} |
||||
|
ps.setInt(5, course.getMaxStudents()); |
||||
|
ps.setString(6, course.getSchedule()); |
||||
|
ps.setInt(7, course.getId()); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("更新课程失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean delete(int id) { |
||||
|
String sql = "DELETE FROM course WHERE id = ?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, id); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("删除课程失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int count(String keyword) { |
||||
|
String sql = "SELECT COUNT(*) FROM course c WHERE 1=1"; |
||||
|
if (keyword != null && !keyword.isEmpty()) { |
||||
|
sql += " AND (c.course_no LIKE ? OR c.name LIKE ?)"; |
||||
|
} |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
if (keyword != null && !keyword.isEmpty()) { |
||||
|
String pattern = "%" + keyword + "%"; |
||||
|
ps.setString(1, pattern); |
||||
|
ps.setString(2, pattern); |
||||
|
} |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return rs.getInt(1); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("统计课程数量失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Course> findList(String keyword, int startIndex, int pageSize) { |
||||
|
StringBuilder sql = new StringBuilder(BASE_SQL + " WHERE 1=1"); |
||||
|
if (keyword != null && !keyword.isEmpty()) { |
||||
|
sql.append(" AND (c.course_no LIKE ? OR c.name LIKE ?)"); |
||||
|
} |
||||
|
sql.append(" ORDER BY c.id DESC LIMIT ?, ?"); |
||||
|
|
||||
|
List<Course> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql.toString()); |
||||
|
int idx = 1; |
||||
|
if (keyword != null && !keyword.isEmpty()) { |
||||
|
String pattern = "%" + keyword + "%"; |
||||
|
ps.setString(idx++, pattern); |
||||
|
ps.setString(idx++, pattern); |
||||
|
} |
||||
|
ps.setInt(idx++, startIndex); |
||||
|
ps.setInt(idx, pageSize); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapRow(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("分页查询课程失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public PageBean<Course> findPage(String keyword, int currentPage, int pageSize) { |
||||
|
PageBean<Course> page = new PageBean<>(currentPage, pageSize); |
||||
|
page.setTotalCount(count(keyword)); |
||||
|
page.setData(findList(keyword, page.getStartIndex(), page.getPageSize())); |
||||
|
return page; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Course> findByTeacher(int teacherId) { |
||||
|
List<Course> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(BASE_SQL + " WHERE c.teacher_id = ? ORDER BY c.id"); |
||||
|
ps.setInt(1, teacherId); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapRow(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询教师课程失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Course> findAll() { |
||||
|
return findList(null, 0, Integer.MAX_VALUE); |
||||
|
} |
||||
|
|
||||
|
private Course queryOne(String sql, int id) { |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, id); |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return mapRow(rs); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询课程失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
private Course mapRow(ResultSet rs) throws SQLException { |
||||
|
Course course = new Course(); |
||||
|
course.setId(rs.getInt("id")); |
||||
|
course.setCourseNo(rs.getString("course_no")); |
||||
|
course.setName(rs.getString("name")); |
||||
|
course.setCredit(rs.getBigDecimal("credit")); |
||||
|
int teacherId = rs.getInt("teacher_id"); |
||||
|
course.setTeacherId(rs.wasNull() ? null : teacherId); |
||||
|
course.setMaxStudents(rs.getInt("max_students")); |
||||
|
course.setSchedule(rs.getString("schedule")); |
||||
|
Timestamp createTime = rs.getTimestamp("create_time"); |
||||
|
if (createTime != null) { |
||||
|
course.setCreateTime(new java.util.Date(createTime.getTime())); |
||||
|
} |
||||
|
course.setTeacherName(rs.getString("teacher_name")); |
||||
|
course.setEnrolledCount(rs.getInt("enrolled_count")); |
||||
|
return course; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,151 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.Enrollment; |
||||
|
import com.student.dao.EnrollmentDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import java.sql.Connection; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.sql.Timestamp; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class EnrollmentDaoImpl implements EnrollmentDao { |
||||
|
|
||||
|
private static final String BASE_SQL = |
||||
|
"SELECT e.id, e.student_id, e.course_id, e.create_time, " |
||||
|
+ "u.real_name AS student_name, u.student_no, c.name AS course_name, c.course_no " |
||||
|
+ "FROM enrollment e " |
||||
|
+ "JOIN users u ON e.student_id = u.id " |
||||
|
+ "JOIN course c ON e.course_id = c.id "; |
||||
|
|
||||
|
@Override |
||||
|
public boolean enroll(int studentId, int courseId) { |
||||
|
String sql = "INSERT INTO enrollment (student_id, course_id) VALUES (?, ?)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, studentId); |
||||
|
ps.setInt(2, courseId); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("选课失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean cancel(int studentId, int courseId) { |
||||
|
String sql = "DELETE FROM enrollment WHERE student_id = ? AND course_id = ?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, studentId); |
||||
|
ps.setInt(2, courseId); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("退课失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean exists(int studentId, int courseId) { |
||||
|
String sql = "SELECT COUNT(*) FROM enrollment WHERE student_id = ? AND course_id = ?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, studentId); |
||||
|
ps.setInt(2, courseId); |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return rs.getInt(1) > 0; |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询选课记录失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Enrollment> findByStudent(int studentId) { |
||||
|
return queryList(BASE_SQL + " WHERE e.student_id = ? ORDER BY e.create_time DESC", studentId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Enrollment> findByCourse(int courseId) { |
||||
|
return queryList(BASE_SQL + " WHERE e.course_id = ? ORDER BY e.create_time DESC", courseId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int countByCourse(int courseId) { |
||||
|
String sql = "SELECT COUNT(*) FROM enrollment WHERE course_id = ?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, courseId); |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return rs.getInt(1); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("统计选课人数失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
private List<Enrollment> queryList(String sql, int id) { |
||||
|
List<Enrollment> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, id); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapRow(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询选课记录失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
private Enrollment mapRow(ResultSet rs) throws SQLException { |
||||
|
Enrollment e = new Enrollment(); |
||||
|
e.setId(rs.getInt("id")); |
||||
|
e.setStudentId(rs.getInt("student_id")); |
||||
|
e.setCourseId(rs.getInt("course_id")); |
||||
|
Timestamp createTime = rs.getTimestamp("create_time"); |
||||
|
if (createTime != null) { |
||||
|
e.setCreateTime(new java.util.Date(createTime.getTime())); |
||||
|
} |
||||
|
e.setStudentName(rs.getString("student_name")); |
||||
|
e.setStudentNo(rs.getString("student_no")); |
||||
|
e.setCourseName(rs.getString("course_name")); |
||||
|
e.setCourseNo(rs.getString("course_no")); |
||||
|
return e; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,184 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.User; |
||||
|
import com.student.bean.UserImportTemp; |
||||
|
import com.student.dao.ImportTempDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
import com.student.util.PasswordUtil; |
||||
|
|
||||
|
import java.sql.Connection; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.sql.Timestamp; |
||||
|
import java.sql.Types; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class ImportTempDaoImpl implements ImportTempDao { |
||||
|
|
||||
|
@Override |
||||
|
public boolean batchInsert(List<UserImportTemp> records) { |
||||
|
if (records == null || records.isEmpty()) { |
||||
|
return true; |
||||
|
} |
||||
|
String sql = "INSERT INTO user_import_temp (batch_id, username, password, real_name, gender, age, email, phone, address) " |
||||
|
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
for (UserImportTemp temp : records) { |
||||
|
ps.setString(1, temp.getBatchId()); |
||||
|
ps.setString(2, temp.getUsername()); |
||||
|
ps.setString(3, temp.getPassword()); |
||||
|
ps.setString(4, temp.getRealName()); |
||||
|
ps.setString(5, temp.getGender()); |
||||
|
if (temp.getAge() != null) { |
||||
|
ps.setInt(6, temp.getAge()); |
||||
|
} else { |
||||
|
ps.setNull(6, Types.INTEGER); |
||||
|
} |
||||
|
ps.setString(7, temp.getEmail()); |
||||
|
ps.setString(8, temp.getPhone()); |
||||
|
ps.setString(9, temp.getAddress()); |
||||
|
ps.addBatch(); |
||||
|
} |
||||
|
ps.executeBatch(); |
||||
|
return true; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("批量导入临时数据失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<UserImportTemp> findByBatch(String batchId) { |
||||
|
String sql = "SELECT id, batch_id, username, password, real_name, gender, age, email, phone, address, create_time " |
||||
|
+ "FROM user_import_temp WHERE batch_id = ? ORDER BY id"; |
||||
|
List<UserImportTemp> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setString(1, batchId); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapRow(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询导入临时数据失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean deleteBatch(String batchId) { |
||||
|
String sql = "DELETE FROM user_import_temp WHERE batch_id = ?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setString(1, batchId); |
||||
|
ps.executeUpdate(); |
||||
|
return true; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("删除导入临时数据失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int confirmImport(String batchId) { |
||||
|
List<UserImportTemp> temps = findByBatch(batchId); |
||||
|
if (temps.isEmpty()) { |
||||
|
return 0; |
||||
|
} |
||||
|
String sql = "INSERT INTO users (username, password, salt, real_name, gender, age, email, phone, address, role, status) " |
||||
|
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
int count = 0; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
conn.setAutoCommit(false); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
for (UserImportTemp temp : temps) { |
||||
|
String salt = PasswordUtil.generateSalt(); |
||||
|
String hashed = PasswordUtil.hash(temp.getPassword(), salt); |
||||
|
ps.setString(1, temp.getUsername()); |
||||
|
ps.setString(2, hashed); |
||||
|
ps.setString(3, salt); |
||||
|
ps.setString(4, temp.getRealName()); |
||||
|
ps.setString(5, temp.getGender()); |
||||
|
if (temp.getAge() != null) { |
||||
|
ps.setInt(6, temp.getAge()); |
||||
|
} else { |
||||
|
ps.setNull(6, Types.INTEGER); |
||||
|
} |
||||
|
ps.setString(7, temp.getEmail()); |
||||
|
ps.setString(8, temp.getPhone()); |
||||
|
ps.setString(9, temp.getAddress()); |
||||
|
ps.setInt(10, User.ROLE_STUDENT); |
||||
|
ps.setInt(11, User.STATUS_ACTIVE); |
||||
|
ps.addBatch(); |
||||
|
} |
||||
|
int[] results = ps.executeBatch(); |
||||
|
for (int r : results) { |
||||
|
if (r > 0) { |
||||
|
count++; |
||||
|
} |
||||
|
} |
||||
|
PreparedStatement delPs = conn.prepareStatement("DELETE FROM user_import_temp WHERE batch_id = ?"); |
||||
|
delPs.setString(1, batchId); |
||||
|
delPs.executeUpdate(); |
||||
|
delPs.close(); |
||||
|
conn.commit(); |
||||
|
} catch (SQLException e) { |
||||
|
if (conn != null) { |
||||
|
try { |
||||
|
conn.rollback(); |
||||
|
} catch (SQLException ignored) { |
||||
|
} |
||||
|
} |
||||
|
throw new RuntimeException("确认导入失败", e); |
||||
|
} finally { |
||||
|
if (conn != null) { |
||||
|
try { |
||||
|
conn.setAutoCommit(true); |
||||
|
} catch (SQLException ignored) { |
||||
|
} |
||||
|
} |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
return count; |
||||
|
} |
||||
|
|
||||
|
private UserImportTemp mapRow(ResultSet rs) throws SQLException { |
||||
|
UserImportTemp temp = new UserImportTemp(); |
||||
|
temp.setId(rs.getInt("id")); |
||||
|
temp.setBatchId(rs.getString("batch_id")); |
||||
|
temp.setUsername(rs.getString("username")); |
||||
|
temp.setPassword(rs.getString("password")); |
||||
|
temp.setRealName(rs.getString("real_name")); |
||||
|
temp.setGender(rs.getString("gender")); |
||||
|
int age = rs.getInt("age"); |
||||
|
temp.setAge(rs.wasNull() ? null : age); |
||||
|
temp.setEmail(rs.getString("email")); |
||||
|
temp.setPhone(rs.getString("phone")); |
||||
|
temp.setAddress(rs.getString("address")); |
||||
|
Timestamp createTime = rs.getTimestamp("create_time"); |
||||
|
if (createTime != null) { |
||||
|
temp.setCreateTime(new java.util.Date(createTime.getTime())); |
||||
|
} |
||||
|
return temp; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,146 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.LeaveRequest; |
||||
|
import com.student.dao.LeaveDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import java.sql.Connection; |
||||
|
import java.sql.Date; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.sql.Timestamp; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class LeaveDaoImpl implements LeaveDao { |
||||
|
|
||||
|
private static final String BASE_SQL = |
||||
|
"SELECT l.id, l.student_id, l.start_date, l.end_date, l.reason, l.status, " |
||||
|
+ "l.approver_id, l.approve_note, l.approve_time, l.create_time, " |
||||
|
+ "u.real_name AS student_name, u.student_no, a.real_name AS approver_name " |
||||
|
+ "FROM leave_request l " |
||||
|
+ "JOIN users u ON l.student_id = u.id " |
||||
|
+ "LEFT JOIN users a ON l.approver_id = a.id "; |
||||
|
|
||||
|
@Override |
||||
|
public boolean submit(LeaveRequest request) { |
||||
|
String sql = "INSERT INTO leave_request (student_id, start_date, end_date, reason, status) " |
||||
|
+ "VALUES (?, ?, ?, ?, ?)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, request.getStudentId()); |
||||
|
ps.setDate(2, new Date(request.getStartDate().getTime())); |
||||
|
ps.setDate(3, new Date(request.getEndDate().getTime())); |
||||
|
ps.setString(4, request.getReason()); |
||||
|
ps.setInt(5, LeaveRequest.STATUS_PENDING); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("提交请假申请失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean approve(int id, int approverId, String note) { |
||||
|
return updateStatus(id, approverId, note, LeaveRequest.STATUS_APPROVED); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean reject(int id, int approverId, String note) { |
||||
|
return updateStatus(id, approverId, note, LeaveRequest.STATUS_REJECTED); |
||||
|
} |
||||
|
|
||||
|
private boolean updateStatus(int id, int approverId, String note, int status) { |
||||
|
String sql = "UPDATE leave_request SET status=?, approver_id=?, approve_note=?, approve_time=NOW() WHERE id=?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, status); |
||||
|
ps.setInt(2, approverId); |
||||
|
ps.setString(3, note); |
||||
|
ps.setInt(4, id); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("审批请假失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<LeaveRequest> findPending() { |
||||
|
return queryList(BASE_SQL + " WHERE l.status = 0 ORDER BY l.create_time ASC"); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<LeaveRequest> findByStudent(int studentId) { |
||||
|
return queryList(BASE_SQL + " WHERE l.student_id = ? ORDER BY l.create_time DESC", studentId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public LeaveRequest findById(int id) { |
||||
|
List<LeaveRequest> list = queryList(BASE_SQL + " WHERE l.id = ?", id); |
||||
|
return list.isEmpty() ? null : list.get(0); |
||||
|
} |
||||
|
|
||||
|
private List<LeaveRequest> queryList(String sql, Object... params) { |
||||
|
List<LeaveRequest> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
for (int i = 0; i < params.length; i++) { |
||||
|
ps.setObject(i + 1, params[i]); |
||||
|
} |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapRow(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询请假记录失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
private LeaveRequest mapRow(ResultSet rs) throws SQLException { |
||||
|
LeaveRequest req = new LeaveRequest(); |
||||
|
req.setId(rs.getInt("id")); |
||||
|
req.setStudentId(rs.getInt("student_id")); |
||||
|
Date startDate = rs.getDate("start_date"); |
||||
|
if (startDate != null) { |
||||
|
req.setStartDate(new java.util.Date(startDate.getTime())); |
||||
|
} |
||||
|
Date endDate = rs.getDate("end_date"); |
||||
|
if (endDate != null) { |
||||
|
req.setEndDate(new java.util.Date(endDate.getTime())); |
||||
|
} |
||||
|
req.setReason(rs.getString("reason")); |
||||
|
req.setStatus(rs.getInt("status")); |
||||
|
int approverId = rs.getInt("approver_id"); |
||||
|
req.setApproverId(rs.wasNull() ? null : approverId); |
||||
|
req.setApproveNote(rs.getString("approve_note")); |
||||
|
Timestamp approveTime = rs.getTimestamp("approve_time"); |
||||
|
if (approveTime != null) { |
||||
|
req.setApproveTime(new java.util.Date(approveTime.getTime())); |
||||
|
} |
||||
|
Timestamp createTime = rs.getTimestamp("create_time"); |
||||
|
if (createTime != null) { |
||||
|
req.setCreateTime(new java.util.Date(createTime.getTime())); |
||||
|
} |
||||
|
req.setStudentName(rs.getString("student_name")); |
||||
|
req.setStudentNo(rs.getString("student_no")); |
||||
|
req.setApproverName(rs.getString("approver_name")); |
||||
|
return req; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,184 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.LoginLog; |
||||
|
import com.student.bean.OperationLog; |
||||
|
import com.student.bean.PageBean; |
||||
|
import com.student.dao.LogDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import java.sql.Connection; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.sql.Timestamp; |
||||
|
import java.sql.Types; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class LogDaoImpl implements LogDao { |
||||
|
|
||||
|
@Override |
||||
|
public boolean saveLoginLog(LoginLog log) { |
||||
|
String sql = "INSERT INTO login_log (user_id, username, ip, result, message) VALUES (?, ?, ?, ?, ?)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
if (log.getUserId() != null) { |
||||
|
ps.setInt(1, log.getUserId()); |
||||
|
} else { |
||||
|
ps.setNull(1, Types.INTEGER); |
||||
|
} |
||||
|
ps.setString(2, log.getUsername()); |
||||
|
ps.setString(3, log.getIp()); |
||||
|
ps.setInt(4, log.getResult()); |
||||
|
ps.setString(5, log.getMessage()); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("保存登录日志失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean saveOperationLog(OperationLog log) { |
||||
|
String sql = "INSERT INTO operation_log (user_id, username, module, action, ip) VALUES (?, ?, ?, ?, ?)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
if (log.getUserId() != null) { |
||||
|
ps.setInt(1, log.getUserId()); |
||||
|
} else { |
||||
|
ps.setNull(1, Types.INTEGER); |
||||
|
} |
||||
|
ps.setString(2, log.getUsername()); |
||||
|
ps.setString(3, log.getModule()); |
||||
|
ps.setString(4, log.getAction()); |
||||
|
ps.setString(5, log.getIp()); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("保存操作日志失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public PageBean<LoginLog> findLoginLogs(int currentPage, int pageSize) { |
||||
|
PageBean<LoginLog> page = new PageBean<>(currentPage, pageSize); |
||||
|
page.setTotalCount(countLoginLogs()); |
||||
|
page.setData(queryLoginLogs(page.getStartIndex(), page.getPageSize())); |
||||
|
return page; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public PageBean<OperationLog> findOperationLogs(int currentPage, int pageSize) { |
||||
|
PageBean<OperationLog> page = new PageBean<>(currentPage, pageSize); |
||||
|
page.setTotalCount(countOperationLogs()); |
||||
|
page.setData(queryOperationLogs(page.getStartIndex(), page.getPageSize())); |
||||
|
return page; |
||||
|
} |
||||
|
|
||||
|
private int countLoginLogs() { |
||||
|
return count("SELECT COUNT(*) FROM login_log"); |
||||
|
} |
||||
|
|
||||
|
private int countOperationLogs() { |
||||
|
return count("SELECT COUNT(*) FROM operation_log"); |
||||
|
} |
||||
|
|
||||
|
private int count(String sql) { |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return rs.getInt(1); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("统计日志数量失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
private List<LoginLog> queryLoginLogs(int startIndex, int pageSize) { |
||||
|
String sql = "SELECT id, user_id, username, ip, result, message, create_time " |
||||
|
+ "FROM login_log ORDER BY create_time DESC LIMIT ?, ?"; |
||||
|
List<LoginLog> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, startIndex); |
||||
|
ps.setInt(2, pageSize); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
LoginLog log = new LoginLog(); |
||||
|
log.setId(rs.getInt("id")); |
||||
|
int userId = rs.getInt("user_id"); |
||||
|
log.setUserId(rs.wasNull() ? null : userId); |
||||
|
log.setUsername(rs.getString("username")); |
||||
|
log.setIp(rs.getString("ip")); |
||||
|
log.setResult(rs.getInt("result")); |
||||
|
log.setMessage(rs.getString("message")); |
||||
|
Timestamp createTime = rs.getTimestamp("create_time"); |
||||
|
if (createTime != null) { |
||||
|
log.setCreateTime(new java.util.Date(createTime.getTime())); |
||||
|
} |
||||
|
list.add(log); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询登录日志失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
private List<OperationLog> queryOperationLogs(int startIndex, int pageSize) { |
||||
|
String sql = "SELECT id, user_id, username, module, action, ip, create_time " |
||||
|
+ "FROM operation_log ORDER BY create_time DESC LIMIT ?, ?"; |
||||
|
List<OperationLog> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, startIndex); |
||||
|
ps.setInt(2, pageSize); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
OperationLog log = new OperationLog(); |
||||
|
log.setId(rs.getInt("id")); |
||||
|
int userId = rs.getInt("user_id"); |
||||
|
log.setUserId(rs.wasNull() ? null : userId); |
||||
|
log.setUsername(rs.getString("username")); |
||||
|
log.setModule(rs.getString("module")); |
||||
|
log.setAction(rs.getString("action")); |
||||
|
log.setIp(rs.getString("ip")); |
||||
|
Timestamp createTime = rs.getTimestamp("create_time"); |
||||
|
if (createTime != null) { |
||||
|
log.setCreateTime(new java.util.Date(createTime.getTime())); |
||||
|
} |
||||
|
list.add(log); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询操作日志失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,173 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.Message; |
||||
|
import com.student.dao.MessageDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import java.sql.Connection; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.sql.Timestamp; |
||||
|
import java.sql.Types; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class MessageDaoImpl implements MessageDao { |
||||
|
|
||||
|
private static final String BASE_SQL = |
||||
|
"SELECT m.id, m.sender_id, m.receiver_id, m.title, m.content, m.is_read, m.create_time, " |
||||
|
+ "u.real_name AS sender_name FROM message m " |
||||
|
+ "LEFT JOIN users u ON m.sender_id = u.id "; |
||||
|
|
||||
|
@Override |
||||
|
public boolean send(Message message) { |
||||
|
String sql = "INSERT INTO message (sender_id, receiver_id, title, content, is_read) VALUES (?, ?, ?, ?, 0)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
if (message.getSenderId() != null) { |
||||
|
ps.setInt(1, message.getSenderId()); |
||||
|
} else { |
||||
|
ps.setNull(1, Types.INTEGER); |
||||
|
} |
||||
|
ps.setInt(2, message.getReceiverId()); |
||||
|
ps.setString(3, message.getTitle()); |
||||
|
ps.setString(4, message.getContent()); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("发送消息失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean sendAll(Message message) { |
||||
|
String sql = "INSERT INTO message (sender_id, receiver_id, title, content, is_read) " |
||||
|
+ "SELECT ?, id, ?, ?, 0 FROM users WHERE role = 0 AND status = 1"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
if (message.getSenderId() != null) { |
||||
|
ps.setInt(1, message.getSenderId()); |
||||
|
} else { |
||||
|
ps.setNull(1, Types.INTEGER); |
||||
|
} |
||||
|
ps.setString(2, message.getTitle()); |
||||
|
ps.setString(3, message.getContent()); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("群发消息失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Message> findInbox(int receiverId) { |
||||
|
return queryList(BASE_SQL + " WHERE m.receiver_id = ? OR m.receiver_id IS NULL " |
||||
|
+ "ORDER BY m.create_time DESC", receiverId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int countUnread(int receiverId) { |
||||
|
String sql = "SELECT COUNT(*) FROM message WHERE is_read = 0 AND (receiver_id = ? OR receiver_id IS NULL)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, receiverId); |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return rs.getInt(1); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("统计未读消息失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean markRead(int messageId) { |
||||
|
String sql = "UPDATE message SET is_read = 1 WHERE id = ?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, messageId); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("标记已读失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean markAllRead(int receiverId) { |
||||
|
String sql = "UPDATE message SET is_read = 1 WHERE is_read = 0 AND (receiver_id = ? OR receiver_id IS NULL)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, receiverId); |
||||
|
return ps.executeUpdate() >= 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("全部标记已读失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private List<Message> queryList(String sql, Object... params) { |
||||
|
List<Message> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
for (int i = 0; i < params.length; i++) { |
||||
|
ps.setObject(i + 1, params[i]); |
||||
|
} |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapRow(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询消息失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
private Message mapRow(ResultSet rs) throws SQLException { |
||||
|
Message m = new Message(); |
||||
|
m.setId(rs.getInt("id")); |
||||
|
int senderId = rs.getInt("sender_id"); |
||||
|
m.setSenderId(rs.wasNull() ? null : senderId); |
||||
|
int receiverId = rs.getInt("receiver_id"); |
||||
|
m.setReceiverId(rs.wasNull() ? null : receiverId); |
||||
|
m.setTitle(rs.getString("title")); |
||||
|
m.setContent(rs.getString("content")); |
||||
|
m.setIsRead(rs.getInt("is_read")); |
||||
|
Timestamp createTime = rs.getTimestamp("create_time"); |
||||
|
if (createTime != null) { |
||||
|
m.setCreateTime(new java.util.Date(createTime.getTime())); |
||||
|
} |
||||
|
m.setSenderName(rs.getString("sender_name")); |
||||
|
return m; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,323 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.Clazz; |
||||
|
import com.student.bean.Department; |
||||
|
import com.student.bean.Major; |
||||
|
import com.student.dao.OrgDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import java.sql.Connection; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class OrgDaoImpl implements OrgDao { |
||||
|
|
||||
|
@Override |
||||
|
public List<Department> findAllDepts() { |
||||
|
String sql = "SELECT id, name, code FROM department ORDER BY id"; |
||||
|
List<Department> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapDept(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询院系列表失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Department findDeptById(int id) { |
||||
|
String sql = "SELECT id, name, code FROM department WHERE id = ?"; |
||||
|
return queryDept(sql, id); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean insertDept(Department dept) { |
||||
|
String sql = "INSERT INTO department (name, code) VALUES (?, ?)"; |
||||
|
return executeUpdate(sql, dept.getName(), dept.getCode()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean updateDept(Department dept) { |
||||
|
String sql = "UPDATE department SET name=?, code=? WHERE id=?"; |
||||
|
return executeUpdate(sql, dept.getName(), dept.getCode(), dept.getId()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean deleteDept(int id) { |
||||
|
String sql = "DELETE FROM department WHERE id = ?"; |
||||
|
return executeUpdate(sql, id); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Major> findMajorsByDept(int deptId) { |
||||
|
String sql = "SELECT m.id, m.department_id, m.name, m.code, d.name AS department_name " |
||||
|
+ "FROM major m LEFT JOIN department d ON m.department_id = d.id " |
||||
|
+ "WHERE m.department_id = ? ORDER BY m.id"; |
||||
|
return queryMajors(sql, deptId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Major> findAllMajors() { |
||||
|
String sql = "SELECT m.id, m.department_id, m.name, m.code, d.name AS department_name " |
||||
|
+ "FROM major m LEFT JOIN department d ON m.department_id = d.id ORDER BY m.id"; |
||||
|
List<Major> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapMajor(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询专业列表失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Major findMajorById(int id) { |
||||
|
String sql = "SELECT m.id, m.department_id, m.name, m.code, d.name AS department_name " |
||||
|
+ "FROM major m LEFT JOIN department d ON m.department_id = d.id WHERE m.id = ?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, id); |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return mapMajor(rs); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询专业失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean insertMajor(Major major) { |
||||
|
String sql = "INSERT INTO major (department_id, name, code) VALUES (?, ?, ?)"; |
||||
|
return executeUpdate(sql, major.getDepartmentId(), major.getName(), major.getCode()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean updateMajor(Major major) { |
||||
|
String sql = "UPDATE major SET department_id=?, name=?, code=? WHERE id=?"; |
||||
|
return executeUpdate(sql, major.getDepartmentId(), major.getName(), major.getCode(), major.getId()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean deleteMajor(int id) { |
||||
|
String sql = "DELETE FROM major WHERE id = ?"; |
||||
|
return executeUpdate(sql, id); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Clazz> findClazzByMajor(int majorId) { |
||||
|
String sql = "SELECT c.id, c.major_id, c.name, c.grade, m.name AS major_name, d.name AS department_name " |
||||
|
+ "FROM clazz c LEFT JOIN major m ON c.major_id = m.id " |
||||
|
+ "LEFT JOIN department d ON m.department_id = d.id " |
||||
|
+ "WHERE c.major_id = ? ORDER BY c.id"; |
||||
|
return queryClazzList(sql, majorId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Clazz> findAllClazz() { |
||||
|
String sql = "SELECT c.id, c.major_id, c.name, c.grade, m.name AS major_name, d.name AS department_name " |
||||
|
+ "FROM clazz c LEFT JOIN major m ON c.major_id = m.id " |
||||
|
+ "LEFT JOIN department d ON m.department_id = d.id ORDER BY c.id"; |
||||
|
List<Clazz> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapClazz(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询班级列表失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Clazz findClazzById(int id) { |
||||
|
String sql = "SELECT c.id, c.major_id, c.name, c.grade, m.name AS major_name, d.name AS department_name " |
||||
|
+ "FROM clazz c LEFT JOIN major m ON c.major_id = m.id " |
||||
|
+ "LEFT JOIN department d ON m.department_id = d.id WHERE c.id = ?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, id); |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return mapClazz(rs); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询班级失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean insertClazz(Clazz clazz) { |
||||
|
String sql = "INSERT INTO clazz (major_id, name, grade) VALUES (?, ?, ?)"; |
||||
|
return executeUpdate(sql, clazz.getMajorId(), clazz.getName(), clazz.getGrade()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean updateClazz(Clazz clazz) { |
||||
|
String sql = "UPDATE clazz SET major_id=?, name=?, grade=? WHERE id=?"; |
||||
|
return executeUpdate(sql, clazz.getMajorId(), clazz.getName(), clazz.getGrade(), clazz.getId()); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean deleteClazz(int id) { |
||||
|
String sql = "DELETE FROM clazz WHERE id = ?"; |
||||
|
return executeUpdate(sql, id); |
||||
|
} |
||||
|
|
||||
|
private Department queryDept(String sql, int id) { |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, id); |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return mapDept(rs); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询院系失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
private List<Major> queryMajors(String sql, int deptId) { |
||||
|
List<Major> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, deptId); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapMajor(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询专业列表失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
private List<Clazz> queryClazzList(String sql, int majorId) { |
||||
|
List<Clazz> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, majorId); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapClazz(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询班级列表失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
private boolean executeUpdate(String sql, Object... params) { |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
for (int i = 0; i < params.length; i++) { |
||||
|
Object p = params[i]; |
||||
|
if (p instanceof Integer) { |
||||
|
ps.setInt(i + 1, (Integer) p); |
||||
|
} else if (p instanceof String) { |
||||
|
ps.setString(i + 1, (String) p); |
||||
|
} |
||||
|
} |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("组织数据操作失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private Department mapDept(ResultSet rs) throws SQLException { |
||||
|
Department dept = new Department(); |
||||
|
dept.setId(rs.getInt("id")); |
||||
|
dept.setName(rs.getString("name")); |
||||
|
dept.setCode(rs.getString("code")); |
||||
|
return dept; |
||||
|
} |
||||
|
|
||||
|
private Major mapMajor(ResultSet rs) throws SQLException { |
||||
|
Major major = new Major(); |
||||
|
major.setId(rs.getInt("id")); |
||||
|
major.setDepartmentId(rs.getInt("department_id")); |
||||
|
major.setName(rs.getString("name")); |
||||
|
major.setCode(rs.getString("code")); |
||||
|
major.setDepartmentName(rs.getString("department_name")); |
||||
|
return major; |
||||
|
} |
||||
|
|
||||
|
private Clazz mapClazz(ResultSet rs) throws SQLException { |
||||
|
Clazz clazz = new Clazz(); |
||||
|
clazz.setId(rs.getInt("id")); |
||||
|
clazz.setMajorId(rs.getInt("major_id")); |
||||
|
clazz.setName(rs.getString("name")); |
||||
|
clazz.setGrade(rs.getString("grade")); |
||||
|
clazz.setMajorName(rs.getString("major_name")); |
||||
|
clazz.setDepartmentName(rs.getString("department_name")); |
||||
|
return clazz; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,97 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.RememberToken; |
||||
|
import com.student.dao.RememberTokenDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import java.sql.Connection; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.sql.Timestamp; |
||||
|
|
||||
|
public class RememberTokenDaoImpl implements RememberTokenDao { |
||||
|
|
||||
|
@Override |
||||
|
public boolean save(RememberToken token) { |
||||
|
String sql = "INSERT INTO remember_token (user_id, token, expire_time) VALUES (?, ?, ?)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, token.getUserId()); |
||||
|
ps.setString(2, token.getToken()); |
||||
|
ps.setTimestamp(3, new Timestamp(token.getExpireTime().getTime())); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("保存记住登录令牌失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public RememberToken findByToken(String token) { |
||||
|
String sql = "SELECT id, user_id, token, expire_time FROM remember_token WHERE token = ? AND expire_time > NOW()"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setString(1, token); |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
RememberToken rt = new RememberToken(); |
||||
|
rt.setId(rs.getInt("id")); |
||||
|
rt.setUserId(rs.getInt("user_id")); |
||||
|
rt.setToken(rs.getString("token")); |
||||
|
Timestamp expireTime = rs.getTimestamp("expire_time"); |
||||
|
if (expireTime != null) { |
||||
|
rt.setExpireTime(new java.util.Date(expireTime.getTime())); |
||||
|
} |
||||
|
return rt; |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询记住登录令牌失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean deleteByUser(int userId) { |
||||
|
String sql = "DELETE FROM remember_token WHERE user_id = ?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, userId); |
||||
|
ps.executeUpdate(); |
||||
|
return true; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("删除用户令牌失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int deleteExpired() { |
||||
|
String sql = "DELETE FROM remember_token WHERE expire_time <= NOW()"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
return ps.executeUpdate(); |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("清理过期令牌失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,161 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.CourseStats; |
||||
|
import com.student.bean.Score; |
||||
|
import com.student.dao.ScoreDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import java.math.BigDecimal; |
||||
|
import java.math.RoundingMode; |
||||
|
import java.sql.Connection; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class ScoreDaoImpl implements ScoreDao { |
||||
|
|
||||
|
private static final String BASE_SQL = |
||||
|
"SELECT s.id, s.student_id, s.course_id, s.score, s.remark, " |
||||
|
+ "u.real_name AS student_name, u.student_no, c.name AS course_name " |
||||
|
+ "FROM score s " |
||||
|
+ "JOIN users u ON s.student_id = u.id " |
||||
|
+ "JOIN course c ON s.course_id = c.id "; |
||||
|
|
||||
|
@Override |
||||
|
public boolean saveOrUpdate(Score score) { |
||||
|
String sql = "INSERT INTO score (student_id, course_id, score, remark) VALUES (?, ?, ?, ?) " |
||||
|
+ "ON DUPLICATE KEY UPDATE score=VALUES(score), remark=VALUES(remark)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, score.getStudentId()); |
||||
|
ps.setInt(2, score.getCourseId()); |
||||
|
ps.setBigDecimal(3, score.getScore()); |
||||
|
ps.setString(4, score.getRemark()); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("保存成绩失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean saveOrUpdateBatch(List<Score> scores) { |
||||
|
if (scores == null || scores.isEmpty()) { |
||||
|
return true; |
||||
|
} |
||||
|
String sql = "INSERT INTO score (student_id, course_id, score, remark) VALUES (?, ?, ?, ?) " |
||||
|
+ "ON DUPLICATE KEY UPDATE score=VALUES(score), remark=VALUES(remark)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
for (Score score : scores) { |
||||
|
ps.setInt(1, score.getStudentId()); |
||||
|
ps.setInt(2, score.getCourseId()); |
||||
|
ps.setBigDecimal(3, score.getScore()); |
||||
|
ps.setString(4, score.getRemark()); |
||||
|
ps.addBatch(); |
||||
|
} |
||||
|
ps.executeBatch(); |
||||
|
return true; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("批量保存成绩失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Score> findByStudent(int studentId) { |
||||
|
return queryList(BASE_SQL + " WHERE s.student_id = ? ORDER BY s.course_id", studentId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<Score> findByCourse(int courseId) { |
||||
|
return queryList(BASE_SQL + " WHERE s.course_id = ? ORDER BY u.student_no", courseId); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public CourseStats getCourseStats(int courseId) { |
||||
|
String sql = "SELECT COUNT(*) AS total_count, AVG(score) AS avg_score, " |
||||
|
+ "MAX(score) AS max_score, MIN(score) AS min_score, " |
||||
|
+ "SUM(CASE WHEN score >= 60 THEN 1 ELSE 0 END) AS pass_count " |
||||
|
+ "FROM score WHERE course_id = ? AND score IS NOT NULL"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, courseId); |
||||
|
rs = ps.executeQuery(); |
||||
|
CourseStats stats = new CourseStats(); |
||||
|
stats.setCourseId(courseId); |
||||
|
if (rs.next()) { |
||||
|
int total = rs.getInt("total_count"); |
||||
|
stats.setTotalCount(total); |
||||
|
stats.setAvg(round(rs.getBigDecimal("avg_score"))); |
||||
|
stats.setMax(round(rs.getBigDecimal("max_score"))); |
||||
|
stats.setMin(round(rs.getBigDecimal("min_score"))); |
||||
|
int passCount = rs.getInt("pass_count"); |
||||
|
if (total > 0) { |
||||
|
stats.setPassRate(new BigDecimal(passCount * 100.0 / total).setScale(1, RoundingMode.HALF_UP)); |
||||
|
} else { |
||||
|
stats.setPassRate(BigDecimal.ZERO); |
||||
|
} |
||||
|
} |
||||
|
return stats; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询课程成绩统计失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private BigDecimal round(BigDecimal value) { |
||||
|
if (value == null) { |
||||
|
return BigDecimal.ZERO; |
||||
|
} |
||||
|
return value.setScale(1, RoundingMode.HALF_UP); |
||||
|
} |
||||
|
|
||||
|
private List<Score> queryList(String sql, int id) { |
||||
|
java.util.List<Score> list = new java.util.ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, id); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapRow(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("查询成绩失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
private Score mapRow(ResultSet rs) throws SQLException { |
||||
|
Score score = new Score(); |
||||
|
score.setId(rs.getInt("id")); |
||||
|
score.setStudentId(rs.getInt("student_id")); |
||||
|
score.setCourseId(rs.getInt("course_id")); |
||||
|
score.setScore(rs.getBigDecimal("score")); |
||||
|
score.setRemark(rs.getString("remark")); |
||||
|
score.setStudentName(rs.getString("student_name")); |
||||
|
score.setStudentNo(rs.getString("student_no")); |
||||
|
score.setCourseName(rs.getString("course_name")); |
||||
|
return score; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,102 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.DashboardStats; |
||||
|
import com.student.bean.User; |
||||
|
import com.student.dao.StatDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import java.sql.Connection; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.util.HashMap; |
||||
|
import java.util.Map; |
||||
|
|
||||
|
public class StatDaoImpl implements StatDao { |
||||
|
|
||||
|
@Override |
||||
|
public DashboardStats getDashboardStats() { |
||||
|
DashboardStats stats = new DashboardStats(); |
||||
|
stats.setTotalUsers(queryInt("SELECT COUNT(*) FROM users WHERE role = 0")); |
||||
|
stats.setTodayRegister(queryInt("SELECT COUNT(*) FROM users WHERE role = 0 AND DATE(create_time) = CURDATE()")); |
||||
|
stats.setTotalCourses(queryInt("SELECT COUNT(*) FROM course")); |
||||
|
stats.setPendingLeave(queryInt("SELECT COUNT(*) FROM leave_request WHERE status = 0")); |
||||
|
stats.setPendingChange(queryInt("SELECT COUNT(*) FROM change_request WHERE status = 0")); |
||||
|
stats.setPendingRegister(queryInt("SELECT COUNT(*) FROM users WHERE role = 0 AND status = ?", User.STATUS_PENDING)); |
||||
|
stats.setGenderStats(genderDistribution()); |
||||
|
stats.setDeptStats(deptDistribution()); |
||||
|
return stats; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Map<String, Integer> genderDistribution() { |
||||
|
String sql = "SELECT IFNULL(gender, '未知') AS label, COUNT(*) AS cnt " |
||||
|
+ "FROM users WHERE role = 0 GROUP BY gender"; |
||||
|
return queryMap(sql); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Map<String, Integer> ageDistribution() { |
||||
|
String sql = "SELECT CASE " |
||||
|
+ "WHEN age IS NULL THEN '未知' " |
||||
|
+ "WHEN age < 18 THEN '18岁以下' " |
||||
|
+ "WHEN age BETWEEN 18 AND 22 THEN '18-22岁' " |
||||
|
+ "WHEN age BETWEEN 23 AND 25 THEN '23-25岁' " |
||||
|
+ "ELSE '25岁以上' END AS label, COUNT(*) AS cnt " |
||||
|
+ "FROM users WHERE role = 0 GROUP BY label"; |
||||
|
return queryMap(sql); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public Map<String, Integer> deptDistribution() { |
||||
|
String sql = "SELECT IFNULL(d.name, '未分配') AS label, COUNT(*) AS cnt " |
||||
|
+ "FROM users u " |
||||
|
+ "LEFT JOIN clazz c ON u.clazz_id = c.id " |
||||
|
+ "LEFT JOIN major m ON c.major_id = m.id " |
||||
|
+ "LEFT JOIN department d ON m.department_id = d.id " |
||||
|
+ "WHERE u.role = 0 GROUP BY d.name"; |
||||
|
return queryMap(sql); |
||||
|
} |
||||
|
|
||||
|
private int queryInt(String sql, Object... params) { |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
for (int i = 0; i < params.length; i++) { |
||||
|
ps.setObject(i + 1, params[i]); |
||||
|
} |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return rs.getInt(1); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("统计查询失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
private Map<String, Integer> queryMap(String sql) { |
||||
|
Map<String, Integer> map = new HashMap<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
map.put(rs.getString("label"), rs.getInt("cnt")); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("分布统计查询失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return map; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,475 @@ |
|||||
|
package com.student.dao.impl; |
||||
|
|
||||
|
import com.student.bean.PageBean; |
||||
|
import com.student.bean.User; |
||||
|
import com.student.bean.UserQuery; |
||||
|
import com.student.dao.UserDao; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import java.sql.Connection; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.sql.Timestamp; |
||||
|
import java.sql.Types; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class UserDaoImpl implements UserDao { |
||||
|
|
||||
|
private static final String BASE_COLUMNS = |
||||
|
"u.id, u.username, u.password, u.salt, u.student_no, u.real_name, u.gender, u.age, " |
||||
|
+ "u.email, u.phone, u.address, u.avatar, u.clazz_id, u.role, u.status, " |
||||
|
+ "u.fail_count, u.lock_until, u.create_time"; |
||||
|
|
||||
|
private static final String JOIN_CLAZZ = |
||||
|
" FROM users u LEFT JOIN clazz c ON u.clazz_id = c.id " |
||||
|
+ "LEFT JOIN major m ON c.major_id = m.id " |
||||
|
+ "LEFT JOIN department d ON m.department_id = d.id "; |
||||
|
|
||||
|
@Override |
||||
|
public User findByUsernameAndPassword(String username, String password) { |
||||
|
String sql = "SELECT " + BASE_COLUMNS + JOIN_CLAZZ + " WHERE u.username = ? AND u.password = ?"; |
||||
|
return queryOne(sql, ps -> { |
||||
|
ps.setString(1, username); |
||||
|
ps.setString(2, password); |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public User findByUsername(String username) { |
||||
|
String sql = "SELECT " + BASE_COLUMNS + ", c.name AS clazz_name, m.name AS major_name, d.name AS dept_name " |
||||
|
+ JOIN_CLAZZ + " WHERE u.username = ?"; |
||||
|
return queryOne(sql, ps -> ps.setString(1, username)); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public User findById(int id) { |
||||
|
String sql = "SELECT " + BASE_COLUMNS + ", c.name AS clazz_name, m.name AS major_name, d.name AS dept_name " |
||||
|
+ JOIN_CLAZZ + " WHERE u.id = ?"; |
||||
|
return queryOne(sql, ps -> ps.setInt(1, id)); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public User findByStudentNo(String studentNo) { |
||||
|
String sql = "SELECT " + BASE_COLUMNS + ", c.name AS clazz_name, m.name AS major_name, d.name AS dept_name " |
||||
|
+ JOIN_CLAZZ + " WHERE u.student_no = ?"; |
||||
|
return queryOne(sql, ps -> ps.setString(1, studentNo)); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean insert(User user) { |
||||
|
String sql = "INSERT INTO users (username, password, salt, student_no, real_name, gender, age, " |
||||
|
+ "email, phone, address, avatar, clazz_id, role, status) " |
||||
|
+ "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
fillInsertParams(ps, user); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("新增用户失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean update(User user) { |
||||
|
String sql = "UPDATE users SET username=?, student_no=?, real_name=?, gender=?, age=?, email=?, " |
||||
|
+ "phone=?, address=?, avatar=?, clazz_id=?, role=?, status=? WHERE id=?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setString(1, user.getUsername()); |
||||
|
setStringOrNull(ps, 2, user.getStudentNo()); |
||||
|
ps.setString(3, user.getRealName()); |
||||
|
ps.setString(4, user.getGender()); |
||||
|
setIntOrNull(ps, 5, user.getAge()); |
||||
|
ps.setString(6, user.getEmail()); |
||||
|
ps.setString(7, user.getPhone()); |
||||
|
ps.setString(8, user.getAddress()); |
||||
|
setStringOrNull(ps, 9, user.getAvatar()); |
||||
|
setIntOrNull(ps, 10, user.getClazzId()); |
||||
|
ps.setInt(11, user.getRole() != null ? user.getRole() : User.ROLE_STUDENT); |
||||
|
ps.setInt(12, user.getStatus() != null ? user.getStatus() : User.STATUS_ACTIVE); |
||||
|
ps.setInt(13, user.getId()); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("更新用户失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean updateProfile(User user) { |
||||
|
String sql = "UPDATE users SET real_name=?, gender=?, age=?, email=?, phone=?, address=? WHERE id=?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setString(1, user.getRealName()); |
||||
|
ps.setString(2, user.getGender()); |
||||
|
setIntOrNull(ps, 3, user.getAge()); |
||||
|
ps.setString(4, user.getEmail()); |
||||
|
ps.setString(5, user.getPhone()); |
||||
|
ps.setString(6, user.getAddress()); |
||||
|
ps.setInt(7, user.getId()); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("更新用户资料失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean updateAvatar(int userId, String avatar) { |
||||
|
String sql = "UPDATE users SET avatar=? WHERE id=?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setString(1, avatar); |
||||
|
ps.setInt(2, userId); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("更新头像失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean delete(int id) { |
||||
|
String sql = "DELETE FROM users WHERE id = ? AND role = 0"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, id); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("删除用户失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public int count(UserQuery query) { |
||||
|
StringBuilder sql = new StringBuilder("SELECT COUNT(*) FROM users u WHERE 1=1"); |
||||
|
List<Object> params = appendQueryConditions(sql, query); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql.toString()); |
||||
|
setParams(ps, params); |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return rs.getInt(1); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("统计用户数量失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<User> findList(UserQuery query, int startIndex, int pageSize) { |
||||
|
StringBuilder sql = new StringBuilder("SELECT " + BASE_COLUMNS |
||||
|
+ ", c.name AS clazz_name, m.name AS major_name, d.name AS dept_name " + JOIN_CLAZZ + " WHERE 1=1"); |
||||
|
List<Object> params = appendQueryConditions(sql, query); |
||||
|
sql.append(" ORDER BY u.id DESC LIMIT ?, ?"); |
||||
|
params.add(startIndex); |
||||
|
params.add(pageSize); |
||||
|
|
||||
|
List<User> list = new ArrayList<>(); |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql.toString()); |
||||
|
setParams(ps, params); |
||||
|
rs = ps.executeQuery(); |
||||
|
while (rs.next()) { |
||||
|
list.add(mapRow(rs)); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("分页查询用户失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return list; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public PageBean<User> findPage(UserQuery query) { |
||||
|
PageBean<User> page = new PageBean<>(query.getCurrentPage(), query.getPageSize()); |
||||
|
page.setTotalCount(count(query)); |
||||
|
page.setData(findList(query, page.getStartIndex(), page.getPageSize())); |
||||
|
return page; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public PageBean<User> findPendingRegister(int currentPage, int pageSize) { |
||||
|
UserQuery query = new UserQuery(); |
||||
|
query.setStatus(User.STATUS_PENDING); |
||||
|
query.setRole(User.ROLE_STUDENT); |
||||
|
query.setCurrentPage(currentPage); |
||||
|
query.setPageSize(pageSize); |
||||
|
return findPage(query); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean updatePassword(int userId, String password, String salt) { |
||||
|
String sql = "UPDATE users SET password=?, salt=?, fail_count=0, lock_until=NULL WHERE id=?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setString(1, password); |
||||
|
ps.setString(2, salt); |
||||
|
ps.setInt(3, userId); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("更新密码失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean updateFailCount(int userId, int failCount) { |
||||
|
String sql = "UPDATE users SET fail_count=? WHERE id=?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, failCount); |
||||
|
ps.setInt(2, userId); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("更新失败次数失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean lockUser(int userId, java.util.Date lockUntil) { |
||||
|
String sql = "UPDATE users SET lock_until=? WHERE id=?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
if (lockUntil != null) { |
||||
|
ps.setTimestamp(1, new Timestamp(lockUntil.getTime())); |
||||
|
} else { |
||||
|
ps.setNull(1, Types.TIMESTAMP); |
||||
|
} |
||||
|
ps.setInt(2, userId); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("锁定用户失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public boolean updateStatus(int userId, int status) { |
||||
|
String sql = "UPDATE users SET status=? WHERE id=?"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setInt(1, status); |
||||
|
ps.setInt(2, userId); |
||||
|
return ps.executeUpdate() > 0; |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("更新用户状态失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<User> findAllStudents() { |
||||
|
UserQuery query = new UserQuery(); |
||||
|
query.setRole(User.ROLE_STUDENT); |
||||
|
query.setCurrentPage(1); |
||||
|
query.setPageSize(Integer.MAX_VALUE); |
||||
|
return findList(query, 0, Integer.MAX_VALUE); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public List<User> findAllTeachers() { |
||||
|
UserQuery query = new UserQuery(); |
||||
|
query.setRole(User.ROLE_TEACHER); |
||||
|
query.setCurrentPage(1); |
||||
|
query.setPageSize(Integer.MAX_VALUE); |
||||
|
return findList(query, 0, Integer.MAX_VALUE); |
||||
|
} |
||||
|
|
||||
|
private List<Object> appendQueryConditions(StringBuilder sql, UserQuery query) { |
||||
|
List<Object> params = new ArrayList<>(); |
||||
|
if (query.getRole() != null) { |
||||
|
sql.append(" AND u.role = ?"); |
||||
|
params.add(query.getRole()); |
||||
|
} |
||||
|
if (query.getStatus() != null) { |
||||
|
sql.append(" AND u.status = ?"); |
||||
|
params.add(query.getStatus()); |
||||
|
} |
||||
|
if (query.getClazzId() != null) { |
||||
|
sql.append(" AND u.clazz_id = ?"); |
||||
|
params.add(query.getClazzId()); |
||||
|
} |
||||
|
if (query.getGender() != null && !query.getGender().isEmpty()) { |
||||
|
sql.append(" AND u.gender = ?"); |
||||
|
params.add(query.getGender()); |
||||
|
} |
||||
|
if (query.getAgeMin() != null) { |
||||
|
sql.append(" AND u.age >= ?"); |
||||
|
params.add(query.getAgeMin()); |
||||
|
} |
||||
|
if (query.getAgeMax() != null) { |
||||
|
sql.append(" AND u.age <= ?"); |
||||
|
params.add(query.getAgeMax()); |
||||
|
} |
||||
|
if (query.getKeyword() != null && !query.getKeyword().isEmpty()) { |
||||
|
sql.append(" AND (u.username LIKE ? OR u.real_name LIKE ? OR u.student_no LIKE ? " |
||||
|
+ "OR u.email LIKE ? OR u.phone LIKE ?)"); |
||||
|
String pattern = "%" + query.getKeyword() + "%"; |
||||
|
for (int i = 0; i < 5; i++) { |
||||
|
params.add(pattern); |
||||
|
} |
||||
|
} |
||||
|
return params; |
||||
|
} |
||||
|
|
||||
|
private void fillInsertParams(PreparedStatement ps, User user) throws SQLException { |
||||
|
ps.setString(1, user.getUsername()); |
||||
|
ps.setString(2, user.getPassword()); |
||||
|
ps.setString(3, user.getSalt()); |
||||
|
setStringOrNull(ps, 4, user.getStudentNo()); |
||||
|
ps.setString(5, user.getRealName()); |
||||
|
ps.setString(6, user.getGender()); |
||||
|
setIntOrNull(ps, 7, user.getAge()); |
||||
|
ps.setString(8, user.getEmail()); |
||||
|
ps.setString(9, user.getPhone()); |
||||
|
ps.setString(10, user.getAddress()); |
||||
|
setStringOrNull(ps, 11, user.getAvatar()); |
||||
|
setIntOrNull(ps, 12, user.getClazzId()); |
||||
|
ps.setInt(13, user.getRole() != null ? user.getRole() : User.ROLE_STUDENT); |
||||
|
ps.setInt(14, user.getStatus() != null ? user.getStatus() : User.STATUS_ACTIVE); |
||||
|
} |
||||
|
|
||||
|
private User mapRow(ResultSet rs) throws SQLException { |
||||
|
User user = new User(); |
||||
|
user.setId(rs.getInt("id")); |
||||
|
user.setUsername(rs.getString("username")); |
||||
|
user.setPassword(rs.getString("password")); |
||||
|
user.setSalt(rs.getString("salt")); |
||||
|
user.setStudentNo(rs.getString("student_no")); |
||||
|
user.setRealName(rs.getString("real_name")); |
||||
|
user.setGender(rs.getString("gender")); |
||||
|
int age = rs.getInt("age"); |
||||
|
user.setAge(rs.wasNull() ? null : age); |
||||
|
user.setEmail(rs.getString("email")); |
||||
|
user.setPhone(rs.getString("phone")); |
||||
|
user.setAddress(rs.getString("address")); |
||||
|
user.setAvatar(rs.getString("avatar")); |
||||
|
int clazzId = rs.getInt("clazz_id"); |
||||
|
user.setClazzId(rs.wasNull() ? null : clazzId); |
||||
|
user.setRole(rs.getInt("role")); |
||||
|
user.setStatus(rs.getInt("status")); |
||||
|
int failCount = rs.getInt("fail_count"); |
||||
|
user.setFailCount(rs.wasNull() ? 0 : failCount); |
||||
|
Timestamp lockUntil = rs.getTimestamp("lock_until"); |
||||
|
if (lockUntil != null) { |
||||
|
user.setLockUntil(new java.util.Date(lockUntil.getTime())); |
||||
|
} |
||||
|
Timestamp createTime = rs.getTimestamp("create_time"); |
||||
|
if (createTime != null) { |
||||
|
user.setCreateTime(new java.util.Date(createTime.getTime())); |
||||
|
} |
||||
|
try { |
||||
|
user.setClazzName(rs.getString("clazz_name")); |
||||
|
user.setMajorName(rs.getString("major_name")); |
||||
|
user.setDeptName(rs.getString("dept_name")); |
||||
|
} catch (SQLException ignored) { |
||||
|
} |
||||
|
return user; |
||||
|
} |
||||
|
|
||||
|
private void setIntOrNull(PreparedStatement ps, int index, Integer value) throws SQLException { |
||||
|
if (value != null) { |
||||
|
ps.setInt(index, value); |
||||
|
} else { |
||||
|
ps.setNull(index, Types.INTEGER); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void setStringOrNull(PreparedStatement ps, int index, String value) throws SQLException { |
||||
|
if (value != null) { |
||||
|
ps.setString(index, value); |
||||
|
} else { |
||||
|
ps.setNull(index, Types.VARCHAR); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private void setParams(PreparedStatement ps, List<Object> params) throws SQLException { |
||||
|
for (int i = 0; i < params.size(); i++) { |
||||
|
Object param = params.get(i); |
||||
|
if (param instanceof Integer) { |
||||
|
ps.setInt(i + 1, (Integer) param); |
||||
|
} else if (param instanceof String) { |
||||
|
ps.setString(i + 1, (String) param); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@FunctionalInterface |
||||
|
private interface ParamSetter { |
||||
|
void set(PreparedStatement ps) throws SQLException; |
||||
|
} |
||||
|
|
||||
|
private User queryOne(String sql, ParamSetter setter) { |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
setter.set(ps); |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return mapRow(rs); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("用户查询失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,81 @@ |
|||||
|
package com.student.filter; |
||||
|
|
||||
|
import com.student.bean.User; |
||||
|
|
||||
|
import javax.servlet.Filter; |
||||
|
import javax.servlet.FilterChain; |
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.ServletRequest; |
||||
|
import javax.servlet.ServletResponse; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import javax.servlet.http.HttpSession; |
||||
|
import java.io.IOException; |
||||
|
import java.net.URLEncoder; |
||||
|
|
||||
|
/** |
||||
|
* 登录认证与角色权限过滤器 |
||||
|
*/ |
||||
|
public class AuthFilter implements Filter { |
||||
|
|
||||
|
@Override |
||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
||||
|
throws IOException, ServletException { |
||||
|
HttpServletRequest req = (HttpServletRequest) request; |
||||
|
HttpServletResponse resp = (HttpServletResponse) response; |
||||
|
HttpSession session = req.getSession(false); |
||||
|
|
||||
|
User loginUser = null; |
||||
|
if (session != null) { |
||||
|
loginUser = (User) session.getAttribute("loginUser"); |
||||
|
} |
||||
|
|
||||
|
if (loginUser == null) { |
||||
|
resp.sendRedirect(req.getContextPath() + "/login.jsp?msg=" |
||||
|
+ URLEncoder.encode("请先登录", "UTF-8")); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
String uri = req.getRequestURI(); |
||||
|
String ctx = req.getContextPath(); |
||||
|
String path = uri.startsWith(ctx) ? uri.substring(ctx.length()) : uri; |
||||
|
|
||||
|
if (path.startsWith("/admin/")) { |
||||
|
if (!loginUser.isAdmin()) { |
||||
|
resp.sendRedirect(ctx + defaultHome(loginUser) + "?msg=" |
||||
|
+ URLEncoder.encode("无权访问管理员功能", "UTF-8")); |
||||
|
return; |
||||
|
} |
||||
|
} else if (path.startsWith("/teacher/")) { |
||||
|
if (!loginUser.isAdmin() && !loginUser.isTeacher()) { |
||||
|
resp.sendRedirect(ctx + defaultHome(loginUser) + "?msg=" |
||||
|
+ URLEncoder.encode("无权访问教师功能", "UTF-8")); |
||||
|
return; |
||||
|
} |
||||
|
} else if (path.startsWith("/user/")) { |
||||
|
// 所有已登录用户均可访问
|
||||
|
} else if (path.startsWith("/api/")) { |
||||
|
if (!loginUser.isAdmin()) { |
||||
|
resp.sendRedirect(ctx + defaultHome(loginUser) + "?msg=" |
||||
|
+ URLEncoder.encode("无权访问 API", "UTF-8")); |
||||
|
return; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
chain.doFilter(request, response); |
||||
|
} |
||||
|
|
||||
|
private String defaultHome(User user) { |
||||
|
if (user.isAdmin()) { |
||||
|
return "/admin/dashboard"; |
||||
|
} |
||||
|
if (user.isTeacher()) { |
||||
|
return "/teacher/home"; |
||||
|
} |
||||
|
return "/user/profile"; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void destroy() { |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
package com.student.filter; |
||||
|
|
||||
|
import javax.servlet.Filter; |
||||
|
import javax.servlet.FilterChain; |
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.ServletRequest; |
||||
|
import javax.servlet.ServletResponse; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 字符编码过滤器 |
||||
|
*/ |
||||
|
public class CharacterEncodingFilter implements Filter { |
||||
|
|
||||
|
private String encoding = "UTF-8"; |
||||
|
|
||||
|
@Override |
||||
|
public void init(javax.servlet.FilterConfig filterConfig) { |
||||
|
String configEncoding = filterConfig.getInitParameter("encoding"); |
||||
|
if (configEncoding != null && !configEncoding.isEmpty()) { |
||||
|
encoding = configEncoding; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
||||
|
throws IOException, ServletException { |
||||
|
request.setCharacterEncoding(encoding); |
||||
|
response.setCharacterEncoding(encoding); |
||||
|
// 不在这里设置 Content-Type,避免覆盖 CSS/JS/图片的 MIME 类型
|
||||
|
chain.doFilter(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void destroy() { |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,65 @@ |
|||||
|
package com.student.filter; |
||||
|
|
||||
|
import com.student.bean.OperationLog; |
||||
|
import com.student.bean.User; |
||||
|
import com.student.dao.LogDao; |
||||
|
import com.student.dao.impl.LogDaoImpl; |
||||
|
import com.student.util.IpUtil; |
||||
|
|
||||
|
import javax.servlet.Filter; |
||||
|
import javax.servlet.FilterChain; |
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.ServletRequest; |
||||
|
import javax.servlet.ServletResponse; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpSession; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 操作日志过滤器:记录已登录用户的 POST 请求 |
||||
|
*/ |
||||
|
public class OperationLogFilter implements Filter { |
||||
|
|
||||
|
private final LogDao logDao = new LogDaoImpl(); |
||||
|
|
||||
|
@Override |
||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
||||
|
throws IOException, ServletException { |
||||
|
HttpServletRequest req = (HttpServletRequest) request; |
||||
|
if ("POST".equalsIgnoreCase(req.getMethod())) { |
||||
|
HttpSession session = req.getSession(false); |
||||
|
if (session != null) { |
||||
|
Object obj = session.getAttribute("loginUser"); |
||||
|
if (obj instanceof User) { |
||||
|
User user = (User) obj; |
||||
|
String uri = req.getRequestURI(); |
||||
|
String ctx = req.getContextPath(); |
||||
|
String path = uri.startsWith(ctx) ? uri.substring(ctx.length()) : uri; |
||||
|
OperationLog log = new OperationLog(); |
||||
|
log.setUserId(user.getId()); |
||||
|
log.setUsername(user.getUsername()); |
||||
|
log.setModule(extractModule(path)); |
||||
|
log.setAction(path); |
||||
|
log.setIp(IpUtil.getClientIp(req)); |
||||
|
logDao.saveOperationLog(log); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
chain.doFilter(request, response); |
||||
|
} |
||||
|
|
||||
|
private String extractModule(String path) { |
||||
|
if (path == null || path.isEmpty()) { |
||||
|
return "unknown"; |
||||
|
} |
||||
|
String[] parts = path.split("/"); |
||||
|
if (parts.length >= 2 && !parts[1].isEmpty()) { |
||||
|
return parts[1]; |
||||
|
} |
||||
|
return "unknown"; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void destroy() { |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,117 @@ |
|||||
|
package com.student.filter; |
||||
|
|
||||
|
import com.student.bean.User; |
||||
|
import com.student.listener.SessionListener; |
||||
|
import com.student.util.CookieUtil; |
||||
|
import com.student.util.DBUtil; |
||||
|
|
||||
|
import javax.servlet.Filter; |
||||
|
import javax.servlet.FilterChain; |
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.ServletRequest; |
||||
|
import javax.servlet.ServletResponse; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import javax.servlet.http.HttpSession; |
||||
|
import java.io.IOException; |
||||
|
import java.sql.Connection; |
||||
|
import java.sql.PreparedStatement; |
||||
|
import java.sql.ResultSet; |
||||
|
import java.sql.SQLException; |
||||
|
import java.sql.Timestamp; |
||||
|
|
||||
|
/** |
||||
|
* 记住我过滤器:校验 remember_token Cookie 并自动登录 |
||||
|
*/ |
||||
|
public class RememberMeFilter implements Filter { |
||||
|
|
||||
|
public static final String REMEMBER_COOKIE_NAME = "remember_token"; |
||||
|
|
||||
|
private static final String USER_COLUMNS = |
||||
|
"u.id, u.username, u.password, u.salt, u.student_no, u.real_name, u.gender, u.age, " |
||||
|
+ "u.email, u.phone, u.address, u.avatar, u.clazz_id, u.role, u.status, " |
||||
|
+ "u.fail_count, u.lock_until, u.create_time"; |
||||
|
|
||||
|
@Override |
||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
||||
|
throws IOException, ServletException { |
||||
|
HttpServletRequest req = (HttpServletRequest) request; |
||||
|
HttpServletResponse resp = (HttpServletResponse) response; |
||||
|
|
||||
|
HttpSession session = req.getSession(false); |
||||
|
if (session == null || session.getAttribute("loginUser") == null) { |
||||
|
String token = CookieUtil.getCookie(req, REMEMBER_COOKIE_NAME); |
||||
|
if (token != null && !token.isEmpty()) { |
||||
|
User user = findUserByRememberToken(token); |
||||
|
if (user != null) { |
||||
|
HttpSession newSession = req.getSession(true); |
||||
|
newSession.setAttribute("loginUser", user); |
||||
|
SessionListener.registerSession(user, newSession); |
||||
|
} else { |
||||
|
CookieUtil.deleteCookie(resp, REMEMBER_COOKIE_NAME); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
chain.doFilter(request, response); |
||||
|
} |
||||
|
|
||||
|
private User findUserByRememberToken(String token) { |
||||
|
String sql = "SELECT " + USER_COLUMNS + " FROM remember_token rt " |
||||
|
+ "JOIN users u ON rt.user_id = u.id " |
||||
|
+ "WHERE rt.token = ? AND rt.expire_time > NOW() LIMIT 1"; |
||||
|
Connection conn = null; |
||||
|
PreparedStatement ps = null; |
||||
|
ResultSet rs = null; |
||||
|
try { |
||||
|
conn = DBUtil.getConnection(); |
||||
|
ps = conn.prepareStatement(sql); |
||||
|
ps.setString(1, token); |
||||
|
rs = ps.executeQuery(); |
||||
|
if (rs.next()) { |
||||
|
return mapUser(rs); |
||||
|
} |
||||
|
} catch (SQLException e) { |
||||
|
throw new RuntimeException("记住我自动登录查询失败", e); |
||||
|
} finally { |
||||
|
DBUtil.close(conn, ps, rs); |
||||
|
} |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
private User mapUser(ResultSet rs) throws SQLException { |
||||
|
User user = new User(); |
||||
|
user.setId(rs.getInt("id")); |
||||
|
user.setUsername(rs.getString("username")); |
||||
|
user.setPassword(rs.getString("password")); |
||||
|
user.setSalt(rs.getString("salt")); |
||||
|
user.setStudentNo(rs.getString("student_no")); |
||||
|
user.setRealName(rs.getString("real_name")); |
||||
|
user.setGender(rs.getString("gender")); |
||||
|
int age = rs.getInt("age"); |
||||
|
user.setAge(rs.wasNull() ? null : age); |
||||
|
user.setEmail(rs.getString("email")); |
||||
|
user.setPhone(rs.getString("phone")); |
||||
|
user.setAddress(rs.getString("address")); |
||||
|
user.setAvatar(rs.getString("avatar")); |
||||
|
int clazzId = rs.getInt("clazz_id"); |
||||
|
user.setClazzId(rs.wasNull() ? null : clazzId); |
||||
|
user.setRole(rs.getInt("role")); |
||||
|
user.setStatus(rs.getInt("status")); |
||||
|
int failCount = rs.getInt("fail_count"); |
||||
|
user.setFailCount(rs.wasNull() ? null : failCount); |
||||
|
Timestamp lockUntil = rs.getTimestamp("lock_until"); |
||||
|
if (lockUntil != null) { |
||||
|
user.setLockUntil(new java.util.Date(lockUntil.getTime())); |
||||
|
} |
||||
|
Timestamp createTime = rs.getTimestamp("create_time"); |
||||
|
if (createTime != null) { |
||||
|
user.setCreateTime(new java.util.Date(createTime.getTime())); |
||||
|
} |
||||
|
return user; |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void destroy() { |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,57 @@ |
|||||
|
package com.student.filter; |
||||
|
|
||||
|
import com.student.bean.DashboardStats; |
||||
|
import com.student.bean.User; |
||||
|
import com.student.service.MessageService; |
||||
|
import com.student.service.StatService; |
||||
|
|
||||
|
import javax.servlet.Filter; |
||||
|
import javax.servlet.FilterChain; |
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.ServletRequest; |
||||
|
import javax.servlet.ServletResponse; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpSession; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 为页面注入侧边栏所需的上下文数据(未读消息、待办数量等) |
||||
|
*/ |
||||
|
public class UserContextFilter implements Filter { |
||||
|
|
||||
|
private final MessageService messageService = new MessageService(); |
||||
|
private final StatService statService = new StatService(); |
||||
|
|
||||
|
@Override |
||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) |
||||
|
throws IOException, ServletException { |
||||
|
HttpServletRequest req = (HttpServletRequest) request; |
||||
|
HttpSession session = req.getSession(false); |
||||
|
User user = null; |
||||
|
if (session != null) { |
||||
|
Object obj = session.getAttribute("loginUser"); |
||||
|
if (obj instanceof User) { |
||||
|
user = (User) obj; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
String path = req.getRequestURI().substring(req.getContextPath().length()); |
||||
|
|
||||
|
if (user != null && path.startsWith("/user/")) { |
||||
|
request.setAttribute("unreadCount", messageService.countUnread(user.getId())); |
||||
|
} |
||||
|
|
||||
|
if (user != null && user.isAdmin() && path.startsWith("/admin/")) { |
||||
|
DashboardStats stats = statService.getDashboard(); |
||||
|
request.setAttribute("pendingRegister", stats.getPendingRegister()); |
||||
|
request.setAttribute("pendingChange", stats.getPendingChange()); |
||||
|
request.setAttribute("pendingLeave", stats.getPendingLeave()); |
||||
|
} |
||||
|
|
||||
|
chain.doFilter(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void destroy() { |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,79 @@ |
|||||
|
package com.student.listener; |
||||
|
|
||||
|
import com.student.bean.User; |
||||
|
|
||||
|
import javax.servlet.http.HttpSession; |
||||
|
import javax.servlet.http.HttpSessionEvent; |
||||
|
import javax.servlet.http.HttpSessionListener; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.List; |
||||
|
import java.util.Map; |
||||
|
import java.util.concurrent.ConcurrentHashMap; |
||||
|
|
||||
|
/** |
||||
|
* Session 监听器,维护在线用户会话 |
||||
|
*/ |
||||
|
public class SessionListener implements HttpSessionListener { |
||||
|
|
||||
|
private static final Map<String, HttpSession> ONLINE_SESSIONS = new ConcurrentHashMap<>(); |
||||
|
|
||||
|
@Override |
||||
|
public void sessionCreated(HttpSessionEvent se) { |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
public void sessionDestroyed(HttpSessionEvent se) { |
||||
|
HttpSession session = se.getSession(); |
||||
|
User user = getLoginUser(session); |
||||
|
if (user != null && user.getId() != null) { |
||||
|
ONLINE_SESSIONS.remove(String.valueOf(user.getId())); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public static void registerSession(User user, HttpSession session) { |
||||
|
if (user == null || user.getId() == null || session == null) { |
||||
|
return; |
||||
|
} |
||||
|
ONLINE_SESSIONS.put(String.valueOf(user.getId()), session); |
||||
|
} |
||||
|
|
||||
|
public static int getOnlineCount() { |
||||
|
return ONLINE_SESSIONS.size(); |
||||
|
} |
||||
|
|
||||
|
public static List<User> getOnlineUsers() { |
||||
|
List<User> users = new ArrayList<>(); |
||||
|
for (HttpSession session : ONLINE_SESSIONS.values()) { |
||||
|
User user = getLoginUser(session); |
||||
|
if (user != null) { |
||||
|
users.add(user); |
||||
|
} |
||||
|
} |
||||
|
return users; |
||||
|
} |
||||
|
|
||||
|
public static boolean invalidateSession(int userId) { |
||||
|
HttpSession session = ONLINE_SESSIONS.remove(String.valueOf(userId)); |
||||
|
if (session != null) { |
||||
|
try { |
||||
|
session.invalidate(); |
||||
|
return true; |
||||
|
} catch (IllegalStateException ignored) { |
||||
|
return true; |
||||
|
} |
||||
|
} |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
private static User getLoginUser(HttpSession session) { |
||||
|
if (session == null) { |
||||
|
return null; |
||||
|
} |
||||
|
try { |
||||
|
Object obj = session.getAttribute("loginUser"); |
||||
|
return obj instanceof User ? (User) obj : null; |
||||
|
} catch (IllegalStateException e) { |
||||
|
return null; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,44 @@ |
|||||
|
package com.student.service; |
||||
|
|
||||
|
import com.student.bean.Announcement; |
||||
|
import com.student.dao.AnnouncementDao; |
||||
|
import com.student.dao.impl.AnnouncementDaoImpl; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public class AnnouncementService { |
||||
|
|
||||
|
private final AnnouncementDao announcementDao; |
||||
|
|
||||
|
public AnnouncementService() { |
||||
|
this(new AnnouncementDaoImpl()); |
||||
|
} |
||||
|
|
||||
|
AnnouncementService(AnnouncementDao announcementDao) { |
||||
|
this.announcementDao = announcementDao; |
||||
|
} |
||||
|
|
||||
|
public Announcement findById(int id) { |
||||
|
return announcementDao.findById(id); |
||||
|
} |
||||
|
|
||||
|
public boolean add(Announcement announcement) { |
||||
|
return announcementDao.insert(announcement); |
||||
|
} |
||||
|
|
||||
|
public boolean update(Announcement announcement) { |
||||
|
return announcementDao.update(announcement); |
||||
|
} |
||||
|
|
||||
|
public boolean delete(int id) { |
||||
|
return announcementDao.delete(id); |
||||
|
} |
||||
|
|
||||
|
public List<Announcement> findAll() { |
||||
|
return announcementDao.findAll(); |
||||
|
} |
||||
|
|
||||
|
public List<Announcement> findActive() { |
||||
|
return announcementDao.findActive(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,49 @@ |
|||||
|
package com.student.service; |
||||
|
|
||||
|
import com.student.bean.Attendance; |
||||
|
import com.student.bean.AttendanceStats; |
||||
|
import com.student.dao.AttendanceDao; |
||||
|
import com.student.dao.impl.AttendanceDaoImpl; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public class AttendanceService { |
||||
|
|
||||
|
private final AttendanceDao attendanceDao; |
||||
|
|
||||
|
public AttendanceService() { |
||||
|
this(new AttendanceDaoImpl()); |
||||
|
} |
||||
|
|
||||
|
AttendanceService(AttendanceDao attendanceDao) { |
||||
|
this.attendanceDao = attendanceDao; |
||||
|
} |
||||
|
|
||||
|
public boolean recordBatch(List<Attendance> records) { |
||||
|
return attendanceDao.saveBatch(records); |
||||
|
} |
||||
|
|
||||
|
public List<Attendance> findByStudent(int studentId) { |
||||
|
return attendanceDao.findByStudent(studentId); |
||||
|
} |
||||
|
|
||||
|
public List<Attendance> findByCourse(int courseId) { |
||||
|
return attendanceDao.findByCourse(courseId); |
||||
|
} |
||||
|
|
||||
|
public List<Attendance> findRecent(int limit) { |
||||
|
return attendanceDao.findRecent(limit); |
||||
|
} |
||||
|
|
||||
|
public AttendanceStats getStatsByStudent(int studentId) { |
||||
|
return attendanceDao.getStatsByStudent(studentId); |
||||
|
} |
||||
|
|
||||
|
public AttendanceStats getStatsByClazz(int clazzId) { |
||||
|
return attendanceDao.getStatsByClazz(clazzId); |
||||
|
} |
||||
|
|
||||
|
public AttendanceStats getStatsByCourse(int courseId) { |
||||
|
return attendanceDao.getStatsByCourse(courseId); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,124 @@ |
|||||
|
package com.student.service; |
||||
|
|
||||
|
import com.student.bean.LoginLog; |
||||
|
import com.student.bean.RememberToken; |
||||
|
import com.student.bean.User; |
||||
|
import com.student.dao.LogDao; |
||||
|
import com.student.dao.RememberTokenDao; |
||||
|
import com.student.dao.UserDao; |
||||
|
import com.student.dao.impl.LogDaoImpl; |
||||
|
import com.student.dao.impl.RememberTokenDaoImpl; |
||||
|
import com.student.dao.impl.UserDaoImpl; |
||||
|
import com.student.util.PasswordUtil; |
||||
|
|
||||
|
import java.util.Calendar; |
||||
|
import java.util.Date; |
||||
|
|
||||
|
public class AuthService { |
||||
|
|
||||
|
private static final int MAX_FAIL_COUNT = 5; |
||||
|
private static final int LOCK_MINUTES = 30; |
||||
|
private static final int REMEMBER_DAYS = 7; |
||||
|
|
||||
|
private final UserDao userDao; |
||||
|
private final LogDao logDao; |
||||
|
private final RememberTokenDao tokenDao; |
||||
|
|
||||
|
public AuthService() { |
||||
|
this(new UserDaoImpl(), new LogDaoImpl(), new RememberTokenDaoImpl()); |
||||
|
} |
||||
|
|
||||
|
AuthService(UserDao userDao, LogDao logDao, RememberTokenDao tokenDao) { |
||||
|
this.userDao = userDao; |
||||
|
this.logDao = logDao; |
||||
|
this.tokenDao = tokenDao; |
||||
|
} |
||||
|
|
||||
|
public User login(String username, String password, String ip) { |
||||
|
User user = userDao.findByUsername(username); |
||||
|
if (user == null) { |
||||
|
saveLoginLog(null, username, ip, 0, "用户不存在"); |
||||
|
return null; |
||||
|
} |
||||
|
if (isLocked(user)) { |
||||
|
saveLoginLog(user.getId(), username, ip, 0, "账户已锁定"); |
||||
|
throw new RuntimeException("账户已锁定,请稍后再试"); |
||||
|
} |
||||
|
if (!PasswordUtil.verify(password, user.getSalt(), user.getPassword())) { |
||||
|
int failCount = (user.getFailCount() != null ? user.getFailCount() : 0) + 1; |
||||
|
userDao.updateFailCount(user.getId(), failCount); |
||||
|
if (failCount >= MAX_FAIL_COUNT) { |
||||
|
Calendar cal = Calendar.getInstance(); |
||||
|
cal.add(Calendar.MINUTE, LOCK_MINUTES); |
||||
|
userDao.lockUser(user.getId(), cal.getTime()); |
||||
|
saveLoginLog(user.getId(), username, ip, 0, "密码错误,账户已锁定"); |
||||
|
throw new RuntimeException("密码错误次数过多,账户已锁定30分钟"); |
||||
|
} |
||||
|
saveLoginLog(user.getId(), username, ip, 0, "密码错误"); |
||||
|
return null; |
||||
|
} |
||||
|
if (user.getStatus() != null && user.getStatus() == User.STATUS_PENDING) { |
||||
|
saveLoginLog(user.getId(), username, ip, 0, "账户待审核"); |
||||
|
throw new RuntimeException("账户待审核,请等待管理员审批"); |
||||
|
} |
||||
|
if (user.getStatus() != null && (user.getStatus() == User.STATUS_SUSPEND |
||||
|
|| user.getStatus() == User.STATUS_DROPPED)) { |
||||
|
saveLoginLog(user.getId(), username, ip, 0, "账户已停用"); |
||||
|
throw new RuntimeException("账户已停用"); |
||||
|
} |
||||
|
userDao.updateFailCount(user.getId(), 0); |
||||
|
userDao.lockUser(user.getId(), null); |
||||
|
saveLoginLog(user.getId(), username, ip, 1, "登录成功"); |
||||
|
user.setPassword(null); |
||||
|
return user; |
||||
|
} |
||||
|
|
||||
|
public String createRememberToken(int userId) { |
||||
|
tokenDao.deleteByUser(userId); |
||||
|
RememberToken token = new RememberToken(); |
||||
|
token.setUserId(userId); |
||||
|
token.setToken(PasswordUtil.generateToken()); |
||||
|
Calendar cal = Calendar.getInstance(); |
||||
|
cal.add(Calendar.DAY_OF_MONTH, REMEMBER_DAYS); |
||||
|
token.setExpireTime(cal.getTime()); |
||||
|
tokenDao.save(token); |
||||
|
return token.getToken(); |
||||
|
} |
||||
|
|
||||
|
public User loginByToken(String token) { |
||||
|
RememberToken rt = tokenDao.findByToken(token); |
||||
|
if (rt == null) { |
||||
|
return null; |
||||
|
} |
||||
|
User user = userDao.findById(rt.getUserId()); |
||||
|
if (user != null) { |
||||
|
user.setPassword(null); |
||||
|
} |
||||
|
return user; |
||||
|
} |
||||
|
|
||||
|
public void logoutRemember(int userId) { |
||||
|
tokenDao.deleteByUser(userId); |
||||
|
} |
||||
|
|
||||
|
public void cleanExpiredTokens() { |
||||
|
tokenDao.deleteExpired(); |
||||
|
} |
||||
|
|
||||
|
private boolean isLocked(User user) { |
||||
|
if (user.getLockUntil() == null) { |
||||
|
return false; |
||||
|
} |
||||
|
return user.getLockUntil().after(new Date()); |
||||
|
} |
||||
|
|
||||
|
private void saveLoginLog(Integer userId, String username, String ip, int result, String message) { |
||||
|
LoginLog log = new LoginLog(); |
||||
|
log.setUserId(userId); |
||||
|
log.setUsername(username); |
||||
|
log.setIp(ip); |
||||
|
log.setResult(result); |
||||
|
log.setMessage(message); |
||||
|
logDao.saveLoginLog(log); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,83 @@ |
|||||
|
package com.student.service; |
||||
|
|
||||
|
import com.student.bean.ChangeRequest; |
||||
|
import com.student.bean.User; |
||||
|
import com.student.dao.ChangeRequestDao; |
||||
|
import com.student.dao.UserDao; |
||||
|
import com.student.dao.impl.ChangeRequestDaoImpl; |
||||
|
import com.student.dao.impl.UserDaoImpl; |
||||
|
|
||||
|
import java.util.Arrays; |
||||
|
import java.util.HashSet; |
||||
|
import java.util.List; |
||||
|
import java.util.Set; |
||||
|
|
||||
|
public class ChangeRequestService { |
||||
|
|
||||
|
private static final Set<String> ALLOWED_FIELDS = new HashSet<>( |
||||
|
Arrays.asList("realName", "studentNo")); |
||||
|
|
||||
|
private final ChangeRequestDao changeRequestDao; |
||||
|
private final UserDao userDao; |
||||
|
|
||||
|
public ChangeRequestService() { |
||||
|
this(new ChangeRequestDaoImpl(), new UserDaoImpl()); |
||||
|
} |
||||
|
|
||||
|
ChangeRequestService(ChangeRequestDao changeRequestDao, UserDao userDao) { |
||||
|
this.changeRequestDao = changeRequestDao; |
||||
|
this.userDao = userDao; |
||||
|
} |
||||
|
|
||||
|
public boolean submit(ChangeRequest request) { |
||||
|
if (!ALLOWED_FIELDS.contains(request.getFieldName())) { |
||||
|
throw new RuntimeException("不允许修改该字段"); |
||||
|
} |
||||
|
User user = userDao.findById(request.getUserId()); |
||||
|
if (user == null) { |
||||
|
throw new RuntimeException("用户不存在"); |
||||
|
} |
||||
|
if ("realName".equals(request.getFieldName())) { |
||||
|
request.setOldValue(user.getRealName()); |
||||
|
} else if ("studentNo".equals(request.getFieldName())) { |
||||
|
request.setOldValue(user.getStudentNo()); |
||||
|
if (userDao.findByStudentNo(request.getNewValue()) != null) { |
||||
|
throw new RuntimeException("学号已存在"); |
||||
|
} |
||||
|
} |
||||
|
return changeRequestDao.submit(request); |
||||
|
} |
||||
|
|
||||
|
public boolean approve(int id, int approverId, String note) { |
||||
|
ChangeRequest cr = changeRequestDao.findById(id); |
||||
|
if (cr == null) { |
||||
|
throw new RuntimeException("申请不存在"); |
||||
|
} |
||||
|
if (cr.getStatus() != ChangeRequest.STATUS_PENDING) { |
||||
|
throw new RuntimeException("申请已处理"); |
||||
|
} |
||||
|
User user = userDao.findById(cr.getUserId()); |
||||
|
if (user == null) { |
||||
|
throw new RuntimeException("用户不存在"); |
||||
|
} |
||||
|
if ("realName".equals(cr.getFieldName())) { |
||||
|
user.setRealName(cr.getNewValue()); |
||||
|
} else if ("studentNo".equals(cr.getFieldName())) { |
||||
|
user.setStudentNo(cr.getNewValue()); |
||||
|
} |
||||
|
userDao.update(user); |
||||
|
return changeRequestDao.approve(id, approverId, note); |
||||
|
} |
||||
|
|
||||
|
public boolean reject(int id, int approverId, String note) { |
||||
|
return changeRequestDao.reject(id, approverId, note); |
||||
|
} |
||||
|
|
||||
|
public List<ChangeRequest> findPending() { |
||||
|
return changeRequestDao.findPending(); |
||||
|
} |
||||
|
|
||||
|
public List<ChangeRequest> findByUser(int userId) { |
||||
|
return changeRequestDao.findByUser(userId); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,56 @@ |
|||||
|
package com.student.service; |
||||
|
|
||||
|
import com.student.bean.Course; |
||||
|
import com.student.bean.PageBean; |
||||
|
import com.student.dao.CourseDao; |
||||
|
import com.student.dao.impl.CourseDaoImpl; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public class CourseService { |
||||
|
|
||||
|
private final CourseDao courseDao; |
||||
|
|
||||
|
public CourseService() { |
||||
|
this(new CourseDaoImpl()); |
||||
|
} |
||||
|
|
||||
|
CourseService(CourseDao courseDao) { |
||||
|
this.courseDao = courseDao; |
||||
|
} |
||||
|
|
||||
|
public Course findById(int id) { |
||||
|
return courseDao.findById(id); |
||||
|
} |
||||
|
|
||||
|
public boolean add(Course course) { |
||||
|
if (courseDao.findByCourseNo(course.getCourseNo()) != null) { |
||||
|
throw new RuntimeException("课程编号已存在"); |
||||
|
} |
||||
|
return courseDao.insert(course); |
||||
|
} |
||||
|
|
||||
|
public boolean update(Course course) { |
||||
|
Course existing = courseDao.findByCourseNo(course.getCourseNo()); |
||||
|
if (existing != null && !existing.getId().equals(course.getId())) { |
||||
|
throw new RuntimeException("课程编号已存在"); |
||||
|
} |
||||
|
return courseDao.update(course); |
||||
|
} |
||||
|
|
||||
|
public boolean delete(int id) { |
||||
|
return courseDao.delete(id); |
||||
|
} |
||||
|
|
||||
|
public PageBean<Course> findPage(String keyword, int currentPage, int pageSize) { |
||||
|
return courseDao.findPage(keyword, currentPage, pageSize); |
||||
|
} |
||||
|
|
||||
|
public List<Course> findByTeacher(int teacherId) { |
||||
|
return courseDao.findByTeacher(teacherId); |
||||
|
} |
||||
|
|
||||
|
public List<Course> findAll() { |
||||
|
return courseDao.findAll(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,56 @@ |
|||||
|
package com.student.service; |
||||
|
|
||||
|
import com.student.bean.Course; |
||||
|
import com.student.bean.Enrollment; |
||||
|
import com.student.dao.CourseDao; |
||||
|
import com.student.dao.EnrollmentDao; |
||||
|
import com.student.dao.impl.CourseDaoImpl; |
||||
|
import com.student.dao.impl.EnrollmentDaoImpl; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public class EnrollmentService { |
||||
|
|
||||
|
private final EnrollmentDao enrollmentDao; |
||||
|
private final CourseDao courseDao; |
||||
|
|
||||
|
public EnrollmentService() { |
||||
|
this(new EnrollmentDaoImpl(), new CourseDaoImpl()); |
||||
|
} |
||||
|
|
||||
|
EnrollmentService(EnrollmentDao enrollmentDao, CourseDao courseDao) { |
||||
|
this.enrollmentDao = enrollmentDao; |
||||
|
this.courseDao = courseDao; |
||||
|
} |
||||
|
|
||||
|
public boolean enroll(int studentId, int courseId) { |
||||
|
if (enrollmentDao.exists(studentId, courseId)) { |
||||
|
throw new RuntimeException("已选过该课程"); |
||||
|
} |
||||
|
Course course = courseDao.findById(courseId); |
||||
|
if (course == null) { |
||||
|
throw new RuntimeException("课程不存在"); |
||||
|
} |
||||
|
int count = enrollmentDao.countByCourse(courseId); |
||||
|
if (course.getMaxStudents() != null && count >= course.getMaxStudents()) { |
||||
|
throw new RuntimeException("课程已满"); |
||||
|
} |
||||
|
return enrollmentDao.enroll(studentId, courseId); |
||||
|
} |
||||
|
|
||||
|
public boolean cancel(int studentId, int courseId) { |
||||
|
return enrollmentDao.cancel(studentId, courseId); |
||||
|
} |
||||
|
|
||||
|
public List<Enrollment> findByStudent(int studentId) { |
||||
|
return enrollmentDao.findByStudent(studentId); |
||||
|
} |
||||
|
|
||||
|
public List<Enrollment> findByCourse(int courseId) { |
||||
|
return enrollmentDao.findByCourse(courseId); |
||||
|
} |
||||
|
|
||||
|
public int countByCourse(int courseId) { |
||||
|
return enrollmentDao.countByCourse(courseId); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
package com.student.service; |
||||
|
|
||||
|
import com.student.bean.UserImportTemp; |
||||
|
import com.student.dao.ImportTempDao; |
||||
|
import com.student.dao.impl.ImportTempDaoImpl; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public class ImportService { |
||||
|
|
||||
|
private final ImportTempDao importTempDao; |
||||
|
|
||||
|
public ImportService() { |
||||
|
this(new ImportTempDaoImpl()); |
||||
|
} |
||||
|
|
||||
|
ImportService(ImportTempDao importTempDao) { |
||||
|
this.importTempDao = importTempDao; |
||||
|
} |
||||
|
|
||||
|
public String uploadToTemp(List<UserImportTemp> records) { |
||||
|
if (records == null || records.isEmpty()) { |
||||
|
throw new RuntimeException("导入数据为空"); |
||||
|
} |
||||
|
String batchId = java.util.UUID.randomUUID().toString().replace("-", ""); |
||||
|
for (UserImportTemp temp : records) { |
||||
|
temp.setBatchId(batchId); |
||||
|
if (temp.getPassword() == null || temp.getPassword().isEmpty()) { |
||||
|
temp.setPassword("123456"); |
||||
|
} |
||||
|
} |
||||
|
importTempDao.batchInsert(records); |
||||
|
return batchId; |
||||
|
} |
||||
|
|
||||
|
public List<UserImportTemp> preview(String batchId) { |
||||
|
return importTempDao.findByBatch(batchId); |
||||
|
} |
||||
|
|
||||
|
public int confirm(String batchId) { |
||||
|
return importTempDao.confirmImport(batchId); |
||||
|
} |
||||
|
|
||||
|
public boolean rollback(String batchId) { |
||||
|
return importTempDao.deleteBatch(batchId); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,50 @@ |
|||||
|
package com.student.service; |
||||
|
|
||||
|
import com.student.bean.LeaveRequest; |
||||
|
import com.student.dao.LeaveDao; |
||||
|
import com.student.dao.impl.LeaveDaoImpl; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public class LeaveService { |
||||
|
|
||||
|
private final LeaveDao leaveDao; |
||||
|
|
||||
|
public LeaveService() { |
||||
|
this(new LeaveDaoImpl()); |
||||
|
} |
||||
|
|
||||
|
LeaveService(LeaveDao leaveDao) { |
||||
|
this.leaveDao = leaveDao; |
||||
|
} |
||||
|
|
||||
|
public boolean apply(LeaveRequest request) { |
||||
|
if (request.getStartDate() == null || request.getEndDate() == null) { |
||||
|
throw new RuntimeException("请假日期不能为空"); |
||||
|
} |
||||
|
if (request.getStartDate().after(request.getEndDate())) { |
||||
|
throw new RuntimeException("开始日期不能晚于结束日期"); |
||||
|
} |
||||
|
return leaveDao.submit(request); |
||||
|
} |
||||
|
|
||||
|
public boolean approve(int id, int approverId, String note) { |
||||
|
return leaveDao.approve(id, approverId, note); |
||||
|
} |
||||
|
|
||||
|
public boolean reject(int id, int approverId, String note) { |
||||
|
return leaveDao.reject(id, approverId, note); |
||||
|
} |
||||
|
|
||||
|
public List<LeaveRequest> findPending() { |
||||
|
return leaveDao.findPending(); |
||||
|
} |
||||
|
|
||||
|
public List<LeaveRequest> findByStudent(int studentId) { |
||||
|
return leaveDao.findByStudent(studentId); |
||||
|
} |
||||
|
|
||||
|
public LeaveRequest findById(int id) { |
||||
|
return leaveDao.findById(id); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,47 @@ |
|||||
|
package com.student.service; |
||||
|
|
||||
|
import com.student.bean.Message; |
||||
|
import com.student.dao.MessageDao; |
||||
|
import com.student.dao.impl.MessageDaoImpl; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public class MessageService { |
||||
|
|
||||
|
private final MessageDao messageDao; |
||||
|
|
||||
|
public MessageService() { |
||||
|
this(new MessageDaoImpl()); |
||||
|
} |
||||
|
|
||||
|
MessageService(MessageDao messageDao) { |
||||
|
this.messageDao = messageDao; |
||||
|
} |
||||
|
|
||||
|
public boolean send(Message message) { |
||||
|
if (message.getReceiverId() == null) { |
||||
|
throw new RuntimeException("接收者不能为空"); |
||||
|
} |
||||
|
return messageDao.send(message); |
||||
|
} |
||||
|
|
||||
|
public boolean sendAll(Message message) { |
||||
|
return messageDao.sendAll(message); |
||||
|
} |
||||
|
|
||||
|
public List<Message> findInbox(int receiverId) { |
||||
|
return messageDao.findInbox(receiverId); |
||||
|
} |
||||
|
|
||||
|
public int countUnread(int receiverId) { |
||||
|
return messageDao.countUnread(receiverId); |
||||
|
} |
||||
|
|
||||
|
public boolean markRead(int messageId) { |
||||
|
return messageDao.markRead(messageId); |
||||
|
} |
||||
|
|
||||
|
public boolean markAllRead(int receiverId) { |
||||
|
return messageDao.markAllRead(receiverId); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,90 @@ |
|||||
|
package com.student.service; |
||||
|
|
||||
|
import com.student.bean.Clazz; |
||||
|
import com.student.bean.Department; |
||||
|
import com.student.bean.Major; |
||||
|
import com.student.dao.OrgDao; |
||||
|
import com.student.dao.impl.OrgDaoImpl; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public class OrgService { |
||||
|
|
||||
|
private final OrgDao orgDao; |
||||
|
|
||||
|
public OrgService() { |
||||
|
this(new OrgDaoImpl()); |
||||
|
} |
||||
|
|
||||
|
OrgService(OrgDao orgDao) { |
||||
|
this.orgDao = orgDao; |
||||
|
} |
||||
|
|
||||
|
public List<Department> listDepts() { |
||||
|
return orgDao.findAllDepts(); |
||||
|
} |
||||
|
|
||||
|
public Department findDept(int id) { |
||||
|
return orgDao.findDeptById(id); |
||||
|
} |
||||
|
|
||||
|
public boolean addDept(Department dept) { |
||||
|
return orgDao.insertDept(dept); |
||||
|
} |
||||
|
|
||||
|
public boolean updateDept(Department dept) { |
||||
|
return orgDao.updateDept(dept); |
||||
|
} |
||||
|
|
||||
|
public boolean deleteDept(int id) { |
||||
|
return orgDao.deleteDept(id); |
||||
|
} |
||||
|
|
||||
|
public List<Major> listMajorsByDept(int deptId) { |
||||
|
return orgDao.findMajorsByDept(deptId); |
||||
|
} |
||||
|
|
||||
|
public List<Major> listAllMajors() { |
||||
|
return orgDao.findAllMajors(); |
||||
|
} |
||||
|
|
||||
|
public Major findMajor(int id) { |
||||
|
return orgDao.findMajorById(id); |
||||
|
} |
||||
|
|
||||
|
public boolean addMajor(Major major) { |
||||
|
return orgDao.insertMajor(major); |
||||
|
} |
||||
|
|
||||
|
public boolean updateMajor(Major major) { |
||||
|
return orgDao.updateMajor(major); |
||||
|
} |
||||
|
|
||||
|
public boolean deleteMajor(int id) { |
||||
|
return orgDao.deleteMajor(id); |
||||
|
} |
||||
|
|
||||
|
public List<Clazz> listClazzByMajor(int majorId) { |
||||
|
return orgDao.findClazzByMajor(majorId); |
||||
|
} |
||||
|
|
||||
|
public List<Clazz> listAllClazz() { |
||||
|
return orgDao.findAllClazz(); |
||||
|
} |
||||
|
|
||||
|
public Clazz findClazz(int id) { |
||||
|
return orgDao.findClazzById(id); |
||||
|
} |
||||
|
|
||||
|
public boolean addClazz(Clazz clazz) { |
||||
|
return orgDao.insertClazz(clazz); |
||||
|
} |
||||
|
|
||||
|
public boolean updateClazz(Clazz clazz) { |
||||
|
return orgDao.updateClazz(clazz); |
||||
|
} |
||||
|
|
||||
|
public boolean deleteClazz(int id) { |
||||
|
return orgDao.deleteClazz(id); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,41 @@ |
|||||
|
package com.student.service; |
||||
|
|
||||
|
import com.student.bean.CourseStats; |
||||
|
import com.student.bean.Score; |
||||
|
import com.student.dao.ScoreDao; |
||||
|
import com.student.dao.impl.ScoreDaoImpl; |
||||
|
|
||||
|
import java.util.List; |
||||
|
|
||||
|
public class ScoreService { |
||||
|
|
||||
|
private final ScoreDao scoreDao; |
||||
|
|
||||
|
public ScoreService() { |
||||
|
this(new ScoreDaoImpl()); |
||||
|
} |
||||
|
|
||||
|
ScoreService(ScoreDao scoreDao) { |
||||
|
this.scoreDao = scoreDao; |
||||
|
} |
||||
|
|
||||
|
public boolean save(Score score) { |
||||
|
return scoreDao.saveOrUpdate(score); |
||||
|
} |
||||
|
|
||||
|
public boolean saveBatch(List<Score> scores) { |
||||
|
return scoreDao.saveOrUpdateBatch(scores); |
||||
|
} |
||||
|
|
||||
|
public List<Score> findByStudent(int studentId) { |
||||
|
return scoreDao.findByStudent(studentId); |
||||
|
} |
||||
|
|
||||
|
public List<Score> findByCourse(int courseId) { |
||||
|
return scoreDao.findByCourse(courseId); |
||||
|
} |
||||
|
|
||||
|
public CourseStats getCourseStats(int courseId) { |
||||
|
return scoreDao.getCourseStats(courseId); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
package com.student.service; |
||||
|
|
||||
|
import com.student.bean.DashboardStats; |
||||
|
import com.student.dao.StatDao; |
||||
|
import com.student.dao.impl.StatDaoImpl; |
||||
|
|
||||
|
import java.util.Map; |
||||
|
|
||||
|
public class StatService { |
||||
|
|
||||
|
private final StatDao statDao; |
||||
|
|
||||
|
public StatService() { |
||||
|
this(new StatDaoImpl()); |
||||
|
} |
||||
|
|
||||
|
StatService(StatDao statDao) { |
||||
|
this.statDao = statDao; |
||||
|
} |
||||
|
|
||||
|
public DashboardStats getDashboard() { |
||||
|
return statDao.getDashboardStats(); |
||||
|
} |
||||
|
|
||||
|
public Map<String, Integer> genderDistribution() { |
||||
|
return statDao.genderDistribution(); |
||||
|
} |
||||
|
|
||||
|
public Map<String, Integer> ageDistribution() { |
||||
|
return statDao.ageDistribution(); |
||||
|
} |
||||
|
|
||||
|
public Map<String, Integer> deptDistribution() { |
||||
|
return statDao.deptDistribution(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,133 @@ |
|||||
|
package com.student.service; |
||||
|
|
||||
|
import com.student.bean.PageBean; |
||||
|
import com.student.bean.User; |
||||
|
import com.student.bean.UserQuery; |
||||
|
import com.student.dao.UserDao; |
||||
|
import com.student.dao.impl.UserDaoImpl; |
||||
|
import com.student.util.PasswordUtil; |
||||
|
|
||||
|
import java.text.SimpleDateFormat; |
||||
|
import java.util.Date; |
||||
|
import java.util.List; |
||||
|
|
||||
|
public class UserService { |
||||
|
|
||||
|
private final UserDao userDao; |
||||
|
|
||||
|
public UserService() { |
||||
|
this(new UserDaoImpl()); |
||||
|
} |
||||
|
|
||||
|
UserService(UserDao userDao) { |
||||
|
this.userDao = userDao; |
||||
|
} |
||||
|
|
||||
|
public boolean register(User user) { |
||||
|
if (userDao.findByUsername(user.getUsername()) != null) { |
||||
|
throw new RuntimeException("用户名已存在"); |
||||
|
} |
||||
|
String salt = PasswordUtil.generateSalt(); |
||||
|
user.setSalt(salt); |
||||
|
user.setPassword(PasswordUtil.hash(user.getPassword(), salt)); |
||||
|
user.setRole(User.ROLE_STUDENT); |
||||
|
user.setStatus(User.STATUS_PENDING); |
||||
|
user.setFailCount(0); |
||||
|
return userDao.insert(user); |
||||
|
} |
||||
|
|
||||
|
public boolean adminAdd(User user) { |
||||
|
if (userDao.findByUsername(user.getUsername()) != null) { |
||||
|
throw new RuntimeException("用户名已存在"); |
||||
|
} |
||||
|
String salt = PasswordUtil.generateSalt(); |
||||
|
user.setSalt(salt); |
||||
|
if (user.getPassword() != null && !user.getPassword().isEmpty()) { |
||||
|
user.setPassword(PasswordUtil.hash(user.getPassword(), salt)); |
||||
|
} else { |
||||
|
user.setPassword(PasswordUtil.hash("123456", salt)); |
||||
|
} |
||||
|
if (user.getRole() == null) { |
||||
|
user.setRole(User.ROLE_STUDENT); |
||||
|
} |
||||
|
if (user.getStatus() == null) { |
||||
|
user.setStatus(User.STATUS_ACTIVE); |
||||
|
} |
||||
|
if (user.getRole() == User.ROLE_STUDENT && user.getStudentNo() == null) { |
||||
|
user.setStudentNo(generateStudentNo(user.getClazzId())); |
||||
|
} |
||||
|
user.setFailCount(0); |
||||
|
return userDao.insert(user); |
||||
|
} |
||||
|
|
||||
|
public boolean update(User user) { |
||||
|
return userDao.update(user); |
||||
|
} |
||||
|
|
||||
|
public boolean updateAvatar(int userId, String avatar) { |
||||
|
return userDao.updateAvatar(userId, avatar); |
||||
|
} |
||||
|
|
||||
|
public User findById(int id) { |
||||
|
return userDao.findById(id); |
||||
|
} |
||||
|
|
||||
|
public User findByUsername(String username) { |
||||
|
return userDao.findByUsername(username); |
||||
|
} |
||||
|
|
||||
|
public PageBean<User> search(UserQuery query) { |
||||
|
if (query.getRole() == null) { |
||||
|
query.setRole(User.ROLE_STUDENT); |
||||
|
} |
||||
|
return userDao.findPage(query); |
||||
|
} |
||||
|
|
||||
|
public PageBean<User> findPendingRegister(int currentPage, int pageSize) { |
||||
|
return userDao.findPendingRegister(currentPage, pageSize); |
||||
|
} |
||||
|
|
||||
|
public boolean changeStatus(int userId, int status) { |
||||
|
return userDao.updateStatus(userId, status); |
||||
|
} |
||||
|
|
||||
|
public boolean delete(int id) { |
||||
|
return userDao.delete(id); |
||||
|
} |
||||
|
|
||||
|
public List<User> findAllStudents() { |
||||
|
return userDao.findAllStudents(); |
||||
|
} |
||||
|
|
||||
|
public List<User> findAllTeachers() { |
||||
|
return userDao.findAllTeachers(); |
||||
|
} |
||||
|
|
||||
|
public String generateStudentNo(Integer clazzId) { |
||||
|
String prefix = new SimpleDateFormat("yyyy").format(new Date()); |
||||
|
if (clazzId != null) { |
||||
|
prefix = prefix + String.format("%03d", clazzId); |
||||
|
} |
||||
|
int seq = 1; |
||||
|
String studentNo; |
||||
|
do { |
||||
|
studentNo = prefix + String.format("%03d", seq++); |
||||
|
} while (userDao.findByStudentNo(studentNo) != null && seq < 1000); |
||||
|
return studentNo; |
||||
|
} |
||||
|
|
||||
|
public boolean approveRegister(int userId, Integer clazzId) { |
||||
|
User user = userDao.findById(userId); |
||||
|
if (user == null) { |
||||
|
throw new RuntimeException("用户不存在"); |
||||
|
} |
||||
|
if (user.getStudentNo() == null) { |
||||
|
user.setStudentNo(generateStudentNo(clazzId)); |
||||
|
} |
||||
|
if (clazzId != null) { |
||||
|
user.setClazzId(clazzId); |
||||
|
} |
||||
|
user.setStatus(User.STATUS_ACTIVE); |
||||
|
return userDao.update(user); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,68 @@ |
|||||
|
package com.student.servlet; |
||||
|
|
||||
|
import com.student.bean.ApiResult; |
||||
|
import com.student.bean.OperationLog; |
||||
|
import com.student.bean.User; |
||||
|
import com.student.dao.LogDao; |
||||
|
import com.student.dao.impl.LogDaoImpl; |
||||
|
import com.student.util.JsonUtil; |
||||
|
|
||||
|
import javax.servlet.http.HttpServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import javax.servlet.http.HttpSession; |
||||
|
import java.io.IOException; |
||||
|
import java.net.URLEncoder; |
||||
|
|
||||
|
/** |
||||
|
* Servlet 基类,提供 JSON 输出、登录用户获取、操作日志等公共方法 |
||||
|
*/ |
||||
|
public abstract class BaseServlet extends HttpServlet { |
||||
|
|
||||
|
private final LogDao logDao = new LogDaoImpl(); |
||||
|
|
||||
|
protected void writeJson(HttpServletResponse response, ApiResult<?> result) throws IOException { |
||||
|
response.setContentType("application/json;charset=UTF-8"); |
||||
|
response.setCharacterEncoding("UTF-8"); |
||||
|
response.getWriter().write(JsonUtil.toJson(result)); |
||||
|
} |
||||
|
|
||||
|
protected User getLoginUser(HttpServletRequest request) { |
||||
|
HttpSession session = request.getSession(false); |
||||
|
if (session == null) { |
||||
|
return null; |
||||
|
} |
||||
|
Object obj = session.getAttribute("loginUser"); |
||||
|
return obj instanceof User ? (User) obj : null; |
||||
|
} |
||||
|
|
||||
|
protected void logOperation(User user, String module, String action, String ip) { |
||||
|
if (user == null) { |
||||
|
return; |
||||
|
} |
||||
|
OperationLog log = new OperationLog(); |
||||
|
log.setUserId(user.getId()); |
||||
|
log.setUsername(user.getUsername()); |
||||
|
log.setModule(module); |
||||
|
log.setAction(action); |
||||
|
log.setIp(ip); |
||||
|
logDao.saveOperationLog(log); |
||||
|
} |
||||
|
|
||||
|
protected void redirectWithMsg(HttpServletResponse response, HttpServletRequest request, |
||||
|
String path, String msg) throws IOException { |
||||
|
redirectWithMsg(response, request, path, msg, "info"); |
||||
|
} |
||||
|
|
||||
|
protected void redirectWithMsg(HttpServletResponse response, HttpServletRequest request, |
||||
|
String path, String msg, String type) throws IOException { |
||||
|
String url = request.getContextPath() + path; |
||||
|
if (msg != null && !msg.isEmpty()) { |
||||
|
url += (path.contains("?") ? "&" : "?") + "msg=" + URLEncoder.encode(msg, "UTF-8"); |
||||
|
if (type != null && !type.isEmpty()) { |
||||
|
url += "&type=" + type; |
||||
|
} |
||||
|
} |
||||
|
response.sendRedirect(url); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
package com.student.servlet; |
||||
|
|
||||
|
import com.student.util.CaptchaUtil; |
||||
|
|
||||
|
import javax.imageio.ImageIO; |
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import javax.servlet.http.HttpSession; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 图形验证码 Servlet |
||||
|
*/ |
||||
|
@WebServlet("/captcha") |
||||
|
public class CaptchaServlet extends HttpServlet { |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
String code = CaptchaUtil.generateCode(); |
||||
|
HttpSession session = request.getSession(); |
||||
|
session.setAttribute("captcha", code); |
||||
|
|
||||
|
response.setContentType("image/jpeg"); |
||||
|
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); |
||||
|
response.setHeader("Pragma", "no-cache"); |
||||
|
response.setDateHeader("Expires", 0); |
||||
|
|
||||
|
ImageIO.write(CaptchaUtil.generateImage(code), "JPEG", response.getOutputStream()); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
package com.student.servlet; |
||||
|
|
||||
|
import com.student.service.UserService; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* Ajax 校验用户名是否可用 |
||||
|
*/ |
||||
|
@WebServlet("/checkUsername") |
||||
|
public class CheckUsernameServlet extends BaseServlet { |
||||
|
|
||||
|
private final UserService userService = new UserService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
String username = ParamUtil.getString(request, "username"); |
||||
|
|
||||
|
if (username.isEmpty()) { |
||||
|
writeJson(response, com.student.bean.ApiResult.fail("用户名不能为空")); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
boolean available = userService.findByUsername(username) == null; |
||||
|
if (available) { |
||||
|
writeJson(response, com.student.bean.ApiResult.ok("用户名可用", true)); |
||||
|
} else { |
||||
|
writeJson(response, com.student.bean.ApiResult.fail("用户名已被占用")); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,92 @@ |
|||||
|
package com.student.servlet; |
||||
|
|
||||
|
import com.student.dao.UserDao; |
||||
|
import com.student.dao.impl.UserDaoImpl; |
||||
|
import com.student.service.UserService; |
||||
|
import com.student.util.ParamUtil; |
||||
|
import com.student.util.PasswordUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import javax.servlet.http.HttpSession; |
||||
|
import java.io.IOException; |
||||
|
import java.util.Random; |
||||
|
|
||||
|
/** |
||||
|
* 忘记密码(A-03 演示模式:验证码存入 Session) |
||||
|
*/ |
||||
|
@WebServlet("/forgotPassword") |
||||
|
public class ForgotPasswordServlet extends BaseServlet { |
||||
|
|
||||
|
private static final String SESSION_CODE_KEY = "resetCode"; |
||||
|
private static final String SESSION_USERNAME_KEY = "resetUsername"; |
||||
|
|
||||
|
private final UserService userService = new UserService(); |
||||
|
private final UserDao userDao = new UserDaoImpl(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
request.getRequestDispatcher("/forgot_password.jsp").forward(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
String step = ParamUtil.getString(request, "step"); |
||||
|
HttpSession session = request.getSession(); |
||||
|
|
||||
|
if ("sendCode".equals(step)) { |
||||
|
String username = ParamUtil.getString(request, "username"); |
||||
|
com.student.bean.User user = userService.findByUsername(username); |
||||
|
if (user == null) { |
||||
|
redirectWithMsg(response, request, "/forgotPassword", "用户不存在"); |
||||
|
return; |
||||
|
} |
||||
|
String code = String.format("%06d", new Random().nextInt(999999)); |
||||
|
session.setAttribute(SESSION_CODE_KEY, code); |
||||
|
session.setAttribute(SESSION_USERNAME_KEY, username); |
||||
|
redirectWithMsg(response, request, "/forgotPassword?step=reset", |
||||
|
"演示模式:验证码为 " + code + "(已存入Session)"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if ("reset".equals(step)) { |
||||
|
String username = ParamUtil.getString(request, "username"); |
||||
|
String code = ParamUtil.getString(request, "code"); |
||||
|
String newPassword = ParamUtil.getString(request, "newPassword"); |
||||
|
String confirmPassword = ParamUtil.getString(request, "confirmPassword"); |
||||
|
|
||||
|
String sessionCode = (String) session.getAttribute(SESSION_CODE_KEY); |
||||
|
String sessionUsername = (String) session.getAttribute(SESSION_USERNAME_KEY); |
||||
|
|
||||
|
if (sessionCode == null || !sessionCode.equals(code) |
||||
|
|| sessionUsername == null || !sessionUsername.equals(username)) { |
||||
|
redirectWithMsg(response, request, "/forgotPassword?step=reset", "验证码错误"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (newPassword.isEmpty() || !newPassword.equals(confirmPassword)) { |
||||
|
redirectWithMsg(response, request, "/forgotPassword?step=reset", "两次密码不一致"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
com.student.bean.User user = userService.findByUsername(username); |
||||
|
if (user == null) { |
||||
|
redirectWithMsg(response, request, "/forgotPassword", "用户不存在"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
String salt = PasswordUtil.generateSalt(); |
||||
|
if (userDao.updatePassword(user.getId(), PasswordUtil.hash(newPassword, salt), salt)) { |
||||
|
session.removeAttribute(SESSION_CODE_KEY); |
||||
|
session.removeAttribute(SESSION_USERNAME_KEY); |
||||
|
redirectWithMsg(response, request, "/login.jsp", "密码重置成功,请登录"); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/forgotPassword?step=reset", "重置失败"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,84 @@ |
|||||
|
package com.student.servlet; |
||||
|
|
||||
|
import com.student.bean.User; |
||||
|
import com.student.filter.RememberMeFilter; |
||||
|
import com.student.listener.SessionListener; |
||||
|
import com.student.service.AuthService; |
||||
|
import com.student.util.CookieUtil; |
||||
|
import com.student.util.IpUtil; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import javax.servlet.http.HttpSession; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 用户登录 Servlet |
||||
|
*/ |
||||
|
@WebServlet("/login") |
||||
|
public class LoginServlet extends BaseServlet { |
||||
|
|
||||
|
private static final int REMEMBER_MAX_AGE = 7 * 24 * 3600; |
||||
|
|
||||
|
private final AuthService authService = new AuthService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
response.sendRedirect(request.getContextPath() + "/login.jsp"); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
String username = ParamUtil.getString(request, "username"); |
||||
|
String password = ParamUtil.getString(request, "password"); |
||||
|
String captcha = ParamUtil.getString(request, "captcha"); |
||||
|
boolean rememberMe = "on".equals(request.getParameter("rememberMe")) |
||||
|
|| "true".equals(request.getParameter("rememberMe")); |
||||
|
|
||||
|
HttpSession session = request.getSession(); |
||||
|
String sessionCaptcha = (String) session.getAttribute("captcha"); |
||||
|
session.removeAttribute("captcha"); |
||||
|
|
||||
|
if (username.isEmpty() || password.isEmpty()) { |
||||
|
redirectWithMsg(response, request, "/login.jsp", "用户名和密码不能为空"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (sessionCaptcha == null || !sessionCaptcha.equalsIgnoreCase(captcha)) { |
||||
|
redirectWithMsg(response, request, "/login.jsp", "验证码错误"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
String ip = IpUtil.getClientIp(request); |
||||
|
try { |
||||
|
User user = authService.login(username, password, ip); |
||||
|
if (user == null) { |
||||
|
redirectWithMsg(response, request, "/login.jsp", "用户名或密码错误"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
session.setAttribute("loginUser", user); |
||||
|
SessionListener.registerSession(user, session); |
||||
|
|
||||
|
if (rememberMe) { |
||||
|
String token = authService.createRememberToken(user.getId()); |
||||
|
CookieUtil.setCookie(response, RememberMeFilter.REMEMBER_COOKIE_NAME, token, REMEMBER_MAX_AGE); |
||||
|
} |
||||
|
|
||||
|
if (user.isAdmin()) { |
||||
|
response.sendRedirect(request.getContextPath() + "/admin/dashboard"); |
||||
|
} else if (user.isTeacher()) { |
||||
|
response.sendRedirect(request.getContextPath() + "/teacher/home"); |
||||
|
} else { |
||||
|
response.sendRedirect(request.getContextPath() + "/user/profile"); |
||||
|
} |
||||
|
} catch (RuntimeException e) { |
||||
|
redirectWithMsg(response, request, "/login.jsp", e.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
package com.student.servlet; |
||||
|
|
||||
|
import com.student.bean.User; |
||||
|
import com.student.filter.RememberMeFilter; |
||||
|
import com.student.service.AuthService; |
||||
|
import com.student.util.CookieUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import javax.servlet.http.HttpSession; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 退出登录 Servlet |
||||
|
*/ |
||||
|
@WebServlet("/logout") |
||||
|
public class LogoutServlet extends BaseServlet { |
||||
|
|
||||
|
private final AuthService authService = new AuthService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
HttpSession session = request.getSession(false); |
||||
|
User loginUser = getLoginUser(request); |
||||
|
if (loginUser != null) { |
||||
|
authService.logoutRemember(loginUser.getId()); |
||||
|
} |
||||
|
CookieUtil.deleteCookie(response, RememberMeFilter.REMEMBER_COOKIE_NAME); |
||||
|
if (session != null) { |
||||
|
session.invalidate(); |
||||
|
} |
||||
|
response.sendRedirect(request.getContextPath() + "/login.jsp"); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
package com.student.servlet; |
||||
|
|
||||
|
import com.student.bean.ApiResult; |
||||
|
import com.student.service.OrgService; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 公开组织级联 API(注册页使用,无需登录) |
||||
|
*/ |
||||
|
@WebServlet(urlPatterns = {"/public/org/majors", "/public/org/clazz", "/public/org/depts"}) |
||||
|
public class PublicOrgServlet extends BaseServlet { |
||||
|
|
||||
|
private final OrgService orgService = new OrgService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { |
||||
|
String uri = request.getRequestURI(); |
||||
|
if (uri.endsWith("/depts")) { |
||||
|
writeJson(response, ApiResult.ok(orgService.listDepts())); |
||||
|
} else if (uri.endsWith("/majors")) { |
||||
|
writeJson(response, ApiResult.ok(orgService.listMajorsByDept(ParamUtil.getInt(request, "deptId", 0)))); |
||||
|
} else if (uri.endsWith("/clazz")) { |
||||
|
writeJson(response, ApiResult.ok(orgService.listClazzByMajor(ParamUtil.getInt(request, "majorId", 0)))); |
||||
|
} else { |
||||
|
writeJson(response, ApiResult.fail("无效路径")); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,81 @@ |
|||||
|
package com.student.servlet; |
||||
|
|
||||
|
import com.student.bean.User; |
||||
|
import com.student.service.OrgService; |
||||
|
import com.student.service.UserService; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 用户注册 Servlet(G-02 待审核) |
||||
|
*/ |
||||
|
@WebServlet("/register") |
||||
|
public class RegisterServlet extends BaseServlet { |
||||
|
|
||||
|
private final UserService userService = new UserService(); |
||||
|
private final OrgService orgService = new OrgService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
request.setAttribute("deptList", orgService.listDepts()); |
||||
|
request.getRequestDispatcher("/register.jsp").forward(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
String username = ParamUtil.getString(request, "username"); |
||||
|
String password = ParamUtil.getString(request, "password"); |
||||
|
String confirmPassword = ParamUtil.getString(request, "confirmPassword"); |
||||
|
String realName = ParamUtil.getString(request, "realName"); |
||||
|
String gender = ParamUtil.getString(request, "gender"); |
||||
|
Integer age = ParamUtil.getInteger(request, "age"); |
||||
|
String email = ParamUtil.getString(request, "email"); |
||||
|
String phone = ParamUtil.getString(request, "phone"); |
||||
|
String address = ParamUtil.getString(request, "address"); |
||||
|
Integer clazzId = ParamUtil.getInteger(request, "clazzId"); |
||||
|
|
||||
|
if (username.isEmpty() || password.isEmpty()) { |
||||
|
redirectWithMsg(response, request, "/register", "用户名和密码不能为空", "error"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (username.length() < 3 || username.length() > 20) { |
||||
|
redirectWithMsg(response, request, "/register", "用户名长度应在3-20个字符之间", "error"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (!password.equals(confirmPassword)) { |
||||
|
redirectWithMsg(response, request, "/register", "两次输入的密码不一致", "error"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
User user = new User(); |
||||
|
user.setUsername(username); |
||||
|
user.setPassword(password); |
||||
|
user.setRealName(realName); |
||||
|
user.setGender(gender); |
||||
|
user.setAge(age); |
||||
|
user.setEmail(email); |
||||
|
user.setPhone(phone); |
||||
|
user.setAddress(address); |
||||
|
user.setClazzId(clazzId); |
||||
|
user.setStatus(User.STATUS_PENDING); |
||||
|
|
||||
|
try { |
||||
|
if (userService.register(user)) { |
||||
|
redirectWithMsg(response, request, "/login.jsp", "注册成功,请等待管理员审核", "success"); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/register", "注册失败,请重试", "error"); |
||||
|
} |
||||
|
} catch (RuntimeException e) { |
||||
|
redirectWithMsg(response, request, "/register", e.getMessage(), "error"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,80 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.bean.Announcement; |
||||
|
import com.student.service.AnnouncementService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.IpUtil; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
import java.text.ParseException; |
||||
|
import java.text.SimpleDateFormat; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 公告 CRUD |
||||
|
*/ |
||||
|
@WebServlet("/admin/announcement") |
||||
|
public class AnnouncementServlet extends BaseServlet { |
||||
|
|
||||
|
private final AnnouncementService announcementService = new AnnouncementService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
int id = ParamUtil.getInt(request, "id", 0); |
||||
|
if (id > 0) { |
||||
|
request.setAttribute("announcement", announcementService.findById(id)); |
||||
|
} |
||||
|
request.setAttribute("annList", announcementService.findAll()); |
||||
|
request.getRequestDispatcher("/admin/announcement.jsp").forward(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
String action = ParamUtil.getString(request, "action"); |
||||
|
int id = ParamUtil.getInt(request, "id", 0); |
||||
|
|
||||
|
if ("delete".equals(action)) { |
||||
|
if (announcementService.delete(id)) { |
||||
|
logOperation(getLoginUser(request), "admin", "删除公告:" + id, IpUtil.getClientIp(request)); |
||||
|
redirectWithMsg(response, request, "/admin/announcement", "删除成功"); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/admin/announcement", "删除失败"); |
||||
|
} |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
Announcement ann = new Announcement(); |
||||
|
ann.setTitle(ParamUtil.getString(request, "title")); |
||||
|
ann.setContent(ParamUtil.getString(request, "content")); |
||||
|
ann.setIsTop(ParamUtil.getInt(request, "isTop", 0)); |
||||
|
String expireStr = ParamUtil.getString(request, "expireDate"); |
||||
|
if (!expireStr.isEmpty()) { |
||||
|
try { |
||||
|
ann.setExpireDate(new SimpleDateFormat("yyyy-MM-dd").parse(expireStr)); |
||||
|
} catch (ParseException ignored) { |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
boolean success; |
||||
|
if (id > 0) { |
||||
|
ann.setId(id); |
||||
|
success = announcementService.update(ann); |
||||
|
} else { |
||||
|
ann.setPublisherId(getLoginUser(request).getId()); |
||||
|
success = announcementService.add(ann); |
||||
|
} |
||||
|
|
||||
|
if (success) { |
||||
|
logOperation(getLoginUser(request), "admin", "保存公告", IpUtil.getClientIp(request)); |
||||
|
redirectWithMsg(response, request, "/admin/announcement", "保存成功"); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/admin/announcement", "保存失败"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,80 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.bean.Attendance; |
||||
|
import com.student.service.AttendanceService; |
||||
|
import com.student.service.CourseService; |
||||
|
import com.student.service.UserService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.IpUtil; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
import java.text.ParseException; |
||||
|
import java.text.SimpleDateFormat; |
||||
|
import java.util.ArrayList; |
||||
|
import java.util.Date; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 考勤记录 |
||||
|
*/ |
||||
|
@WebServlet("/admin/attendance") |
||||
|
public class AttendanceManageServlet extends BaseServlet { |
||||
|
|
||||
|
private final AttendanceService attendanceService = new AttendanceService(); |
||||
|
private final CourseService courseService = new CourseService(); |
||||
|
private final UserService userService = new UserService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
request.setAttribute("courseList", courseService.findAll()); |
||||
|
request.setAttribute("studentList", userService.findAllStudents()); |
||||
|
request.setAttribute("attList", attendanceService.findRecent(50)); |
||||
|
request.getRequestDispatcher("/admin/attendance.jsp").forward(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
int courseId = ParamUtil.getInt(request, "courseId", 0); |
||||
|
int studentId = ParamUtil.getInt(request, "studentId", 0); |
||||
|
String attDateStr = ParamUtil.getString(request, "attDate"); |
||||
|
int status = ParamUtil.getInt(request, "status", 1); |
||||
|
String remark = ParamUtil.getString(request, "remark"); |
||||
|
|
||||
|
if (courseId <= 0 || studentId <= 0 || attDateStr.isEmpty()) { |
||||
|
redirectWithMsg(response, request, "/admin/attendance", "参数无效"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
Date attDate; |
||||
|
try { |
||||
|
attDate = new SimpleDateFormat("yyyy-MM-dd").parse(attDateStr); |
||||
|
} catch (ParseException e) { |
||||
|
redirectWithMsg(response, request, "/admin/attendance", "日期格式错误"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
Attendance att = new Attendance(); |
||||
|
att.setStudentId(studentId); |
||||
|
att.setCourseId(courseId); |
||||
|
att.setAttDate(attDate); |
||||
|
att.setStatus(status); |
||||
|
att.setRemark(remark); |
||||
|
|
||||
|
List<Attendance> records = new ArrayList<>(); |
||||
|
records.add(att); |
||||
|
|
||||
|
if (attendanceService.recordBatch(records)) { |
||||
|
logOperation(getLoginUser(request), "admin", "记录考勤:course=" + courseId, IpUtil.getClientIp(request)); |
||||
|
redirectWithMsg(response, request, "/admin/attendance", "保存成功"); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/admin/attendance", "保存失败"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.bean.AttendanceStats; |
||||
|
import com.student.bean.Course; |
||||
|
import com.student.service.AttendanceService; |
||||
|
import com.student.service.CourseService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
import java.util.List; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 考勤统计 |
||||
|
*/ |
||||
|
@WebServlet("/admin/attendanceStats") |
||||
|
public class AttendanceStatsServlet extends BaseServlet { |
||||
|
|
||||
|
private final AttendanceService attendanceService = new AttendanceService(); |
||||
|
private final CourseService courseService = new CourseService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
int courseId = ParamUtil.getInt(request, "courseId", 0); |
||||
|
List<Course> courseList = courseService.findAll(); |
||||
|
request.setAttribute("courseList", courseList); |
||||
|
AttendanceStats stats = new AttendanceStats(); |
||||
|
if (courseId > 0) { |
||||
|
request.setAttribute("courseId", courseId); |
||||
|
stats = attendanceService.getStatsByCourse(courseId); |
||||
|
} |
||||
|
request.setAttribute("stats", stats); |
||||
|
request.getRequestDispatcher("/admin/attendance_stats.jsp").forward(request, response); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,26 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.service.StatService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 数据大屏 |
||||
|
*/ |
||||
|
@WebServlet("/admin/bigscreen") |
||||
|
public class BigScreenServlet extends BaseServlet { |
||||
|
|
||||
|
private final StatService statService = new StatService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
request.setAttribute("stats", statService.getDashboard()); |
||||
|
request.getRequestDispatcher("/admin/bigscreen.jsp").forward(request, response); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,58 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.service.ChangeRequestService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.IpUtil; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 变更申请审核(G-01) |
||||
|
*/ |
||||
|
@WebServlet("/admin/changeAudit") |
||||
|
public class ChangeAuditServlet extends BaseServlet { |
||||
|
|
||||
|
private final ChangeRequestService changeRequestService = new ChangeRequestService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
request.setAttribute("changeList", changeRequestService.findPending()); |
||||
|
request.getRequestDispatcher("/admin/change_audit.jsp").forward(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
int id = ParamUtil.getInt(request, "id", 0); |
||||
|
String action = ParamUtil.getString(request, "action"); |
||||
|
String note = ParamUtil.getString(request, "note"); |
||||
|
int approverId = getLoginUser(request).getId(); |
||||
|
|
||||
|
try { |
||||
|
boolean success; |
||||
|
if ("approve".equals(action)) { |
||||
|
success = changeRequestService.approve(id, approverId, note); |
||||
|
} else if ("reject".equals(action)) { |
||||
|
success = changeRequestService.reject(id, approverId, note); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/admin/changeAudit", "无效操作"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (success) { |
||||
|
logOperation(getLoginUser(request), "admin", "变更审核:" + action, IpUtil.getClientIp(request)); |
||||
|
redirectWithMsg(response, request, "/admin/changeAudit", "操作成功"); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/admin/changeAudit", "操作失败"); |
||||
|
} |
||||
|
} catch (RuntimeException e) { |
||||
|
redirectWithMsg(response, request, "/admin/changeAudit", e.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.service.CourseService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.IpUtil; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 删除课程 |
||||
|
*/ |
||||
|
@WebServlet("/admin/courseDelete") |
||||
|
public class CourseDeleteServlet extends BaseServlet { |
||||
|
|
||||
|
private final CourseService courseService = new CourseService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
int id = ParamUtil.getInt(request, "id", 0); |
||||
|
if (id > 0 && courseService.delete(id)) { |
||||
|
logOperation(getLoginUser(request), "admin", "删除课程:" + id, IpUtil.getClientIp(request)); |
||||
|
redirectWithMsg(response, request, "/admin/courseList", "删除成功"); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/admin/courseList", "删除失败"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,71 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.bean.Course; |
||||
|
import com.student.service.CourseService; |
||||
|
import com.student.service.UserService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.IpUtil; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
import java.math.BigDecimal; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 课程编辑 |
||||
|
*/ |
||||
|
@WebServlet("/admin/courseEdit") |
||||
|
public class CourseEditServlet extends BaseServlet { |
||||
|
|
||||
|
private final CourseService courseService = new CourseService(); |
||||
|
private final UserService userService = new UserService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
int id = ParamUtil.getInt(request, "id", 0); |
||||
|
if (id > 0) { |
||||
|
request.setAttribute("course", courseService.findById(id)); |
||||
|
} |
||||
|
request.setAttribute("teacherList", userService.findAllTeachers()); |
||||
|
request.getRequestDispatcher("/admin/course_edit.jsp").forward(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
int id = ParamUtil.getInt(request, "id", 0); |
||||
|
Course course = new Course(); |
||||
|
course.setId(id > 0 ? id : null); |
||||
|
course.setCourseNo(ParamUtil.getString(request, "courseNo")); |
||||
|
course.setName(ParamUtil.getString(request, "name")); |
||||
|
String creditStr = ParamUtil.getString(request, "credit"); |
||||
|
if (!creditStr.isEmpty()) { |
||||
|
course.setCredit(new BigDecimal(creditStr)); |
||||
|
} |
||||
|
course.setTeacherId(ParamUtil.getInteger(request, "teacherId")); |
||||
|
course.setMaxStudents(ParamUtil.getInteger(request, "maxStudents")); |
||||
|
course.setSchedule(ParamUtil.getString(request, "schedule")); |
||||
|
|
||||
|
try { |
||||
|
boolean success; |
||||
|
if (id > 0) { |
||||
|
course.setId(id); |
||||
|
success = courseService.update(course); |
||||
|
} else { |
||||
|
success = courseService.add(course); |
||||
|
} |
||||
|
if (success) { |
||||
|
logOperation(getLoginUser(request), "admin", "编辑课程:" + course.getCourseNo(), IpUtil.getClientIp(request)); |
||||
|
redirectWithMsg(response, request, "/admin/courseList", "保存成功"); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/admin/courseEdit" + (id > 0 ? "?id=" + id : ""), "保存失败"); |
||||
|
} |
||||
|
} catch (RuntimeException e) { |
||||
|
redirectWithMsg(response, request, "/admin/courseEdit" + (id > 0 ? "?id=" + id : ""), e.getMessage()); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,33 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.service.CourseService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 课程列表 |
||||
|
*/ |
||||
|
@WebServlet("/admin/courseList") |
||||
|
public class CourseListServlet extends BaseServlet { |
||||
|
|
||||
|
private final CourseService courseService = new CourseService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
String keyword = ParamUtil.getString(request, "keyword"); |
||||
|
int page = ParamUtil.getInt(request, "page", 1); |
||||
|
int pageSize = ParamUtil.getInt(request, "pageSize", 10); |
||||
|
com.student.bean.PageBean<com.student.bean.Course> pageBean = courseService.findPage(keyword, page, pageSize); |
||||
|
request.setAttribute("pageBean", pageBean); |
||||
|
request.setAttribute("courseList", pageBean.getData()); |
||||
|
request.setAttribute("keyword", keyword); |
||||
|
request.getRequestDispatcher("/admin/course_list.jsp").forward(request, response); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,29 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.service.AnnouncementService; |
||||
|
import com.student.service.StatService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 仪表盘 |
||||
|
*/ |
||||
|
@WebServlet("/admin/dashboard") |
||||
|
public class DashboardServlet extends BaseServlet { |
||||
|
|
||||
|
private final StatService statService = new StatService(); |
||||
|
private final AnnouncementService announcementService = new AnnouncementService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
request.setAttribute("stats", statService.getDashboard()); |
||||
|
request.setAttribute("announcements", announcementService.findActive()); |
||||
|
request.getRequestDispatcher("/admin/dashboard.jsp").forward(request, response); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,66 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.service.ImportService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.IpUtil; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 导入预览(G-03) |
||||
|
*/ |
||||
|
@WebServlet("/admin/importPreview") |
||||
|
public class ImportPreviewServlet extends BaseServlet { |
||||
|
|
||||
|
private final ImportService importService = new ImportService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
String batchId = ParamUtil.getString(request, "batchId"); |
||||
|
if (batchId.isEmpty()) { |
||||
|
Object lastBatch = request.getSession().getAttribute("lastImportBatchId"); |
||||
|
if (lastBatch instanceof String && !((String) lastBatch).isEmpty()) { |
||||
|
batchId = (String) lastBatch; |
||||
|
} |
||||
|
} |
||||
|
if (batchId.isEmpty()) { |
||||
|
request.setAttribute("msg", "请先上传 CSV 文件"); |
||||
|
request.getRequestDispatcher("/admin/user_upload.jsp").forward(request, response); |
||||
|
return; |
||||
|
} |
||||
|
request.setAttribute("batchId", batchId); |
||||
|
request.setAttribute("importList", importService.preview(batchId)); |
||||
|
request.getRequestDispatcher("/admin/import_preview.jsp").forward(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
String batchId = ParamUtil.getString(request, "batchId"); |
||||
|
String action = ParamUtil.getString(request, "action"); |
||||
|
|
||||
|
if (batchId.isEmpty()) { |
||||
|
redirectWithMsg(response, request, "/admin/importPreview", "批次ID无效"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if ("confirm".equals(action)) { |
||||
|
int count = importService.confirm(batchId); |
||||
|
request.getSession().removeAttribute("lastImportBatchId"); |
||||
|
logOperation(getLoginUser(request), "admin", "确认导入:" + count + "条", IpUtil.getClientIp(request)); |
||||
|
redirectWithMsg(response, request, "/admin/userList", "成功导入 " + count + " 条记录"); |
||||
|
} else if ("cancel".equals(action)) { |
||||
|
importService.rollback(batchId); |
||||
|
request.getSession().removeAttribute("lastImportBatchId"); |
||||
|
redirectWithMsg(response, request, "/admin/importPreview", "已取消导入"); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/admin/importPreview", "无效操作"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,54 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.service.LeaveService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.IpUtil; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 请假审批 |
||||
|
*/ |
||||
|
@WebServlet("/admin/leaveApprove") |
||||
|
public class LeaveApproveServlet extends BaseServlet { |
||||
|
|
||||
|
private final LeaveService leaveService = new LeaveService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
request.setAttribute("leaveList", leaveService.findPending()); |
||||
|
request.getRequestDispatcher("/admin/leave_approve.jsp").forward(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
int id = ParamUtil.getInt(request, "id", 0); |
||||
|
String action = ParamUtil.getString(request, "action"); |
||||
|
String note = ParamUtil.getString(request, "note"); |
||||
|
int approverId = getLoginUser(request).getId(); |
||||
|
|
||||
|
boolean success; |
||||
|
if ("approve".equals(action)) { |
||||
|
success = leaveService.approve(id, approverId, note); |
||||
|
} else if ("reject".equals(action)) { |
||||
|
success = leaveService.reject(id, approverId, note); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/admin/leaveApprove", "无效操作"); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (success) { |
||||
|
logOperation(getLoginUser(request), "admin", "请假审批:" + action + ",id=" + id, IpUtil.getClientIp(request)); |
||||
|
redirectWithMsg(response, request, "/admin/leaveApprove", "操作成功"); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/admin/leaveApprove", "操作失败"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.dao.LogDao; |
||||
|
import com.student.dao.impl.LogDaoImpl; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 登录/操作日志查看 |
||||
|
*/ |
||||
|
@WebServlet("/admin/logs") |
||||
|
public class LogViewServlet extends BaseServlet { |
||||
|
|
||||
|
private final LogDao logDao = new LogDaoImpl(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
String tab = ParamUtil.getString(request, "tab"); |
||||
|
if (tab.isEmpty()) { |
||||
|
tab = "login"; |
||||
|
} |
||||
|
int page = ParamUtil.getInt(request, "page", 1); |
||||
|
int pageSize = ParamUtil.getInt(request, "pageSize", 20); |
||||
|
|
||||
|
request.setAttribute("tab", tab); |
||||
|
if ("operation".equals(tab)) { |
||||
|
request.setAttribute("opLogs", logDao.findOperationLogs(page, pageSize).getData()); |
||||
|
} else { |
||||
|
request.setAttribute("loginLogs", logDao.findLoginLogs(page, pageSize).getData()); |
||||
|
} |
||||
|
request.getRequestDispatcher("/admin/logs.jsp").forward(request, response); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,60 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.bean.Message; |
||||
|
import com.student.service.MessageService; |
||||
|
import com.student.service.UserService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.IpUtil; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 发送消息 |
||||
|
*/ |
||||
|
@WebServlet("/admin/messageSend") |
||||
|
public class MessageSendServlet extends BaseServlet { |
||||
|
|
||||
|
private final MessageService messageService = new MessageService(); |
||||
|
private final UserService userService = new UserService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
request.setAttribute("userList", userService.findAllStudents()); |
||||
|
request.getRequestDispatcher("/admin/message_send.jsp").forward(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
String title = ParamUtil.getString(request, "title"); |
||||
|
String content = ParamUtil.getString(request, "content"); |
||||
|
String sendType = ParamUtil.getString(request, "sendType"); |
||||
|
Integer receiverId = ParamUtil.getInteger(request, "receiverId"); |
||||
|
|
||||
|
Message message = new Message(); |
||||
|
message.setSenderId(getLoginUser(request).getId()); |
||||
|
message.setTitle(title); |
||||
|
message.setContent(content); |
||||
|
|
||||
|
boolean success; |
||||
|
if ("all".equals(sendType)) { |
||||
|
success = messageService.sendAll(message); |
||||
|
} else { |
||||
|
message.setReceiverId(receiverId); |
||||
|
success = messageService.send(message); |
||||
|
} |
||||
|
|
||||
|
if (success) { |
||||
|
logOperation(getLoginUser(request), "admin", "发送消息:" + title, IpUtil.getClientIp(request)); |
||||
|
redirectWithMsg(response, request, "/admin/messageSend", "发送成功"); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/admin/messageSend", "发送失败"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.listener.SessionListener; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.IpUtil; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 在线用户管理 |
||||
|
*/ |
||||
|
@WebServlet("/admin/online") |
||||
|
public class OnlineUserServlet extends BaseServlet { |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
request.setAttribute("onlineList", SessionListener.getOnlineUsers()); |
||||
|
request.setAttribute("onlineCount", SessionListener.getOnlineCount()); |
||||
|
request.getRequestDispatcher("/admin/online.jsp").forward(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
int userId = ParamUtil.getInt(request, "userId", 0); |
||||
|
if (userId > 0 && SessionListener.invalidateSession(userId)) { |
||||
|
logOperation(getLoginUser(request), "admin", "踢出用户:" + userId, IpUtil.getClientIp(request)); |
||||
|
redirectWithMsg(response, request, "/admin/online", "已强制下线"); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/admin/online", "操作失败"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.bean.ApiResult; |
||||
|
import com.student.service.OrgService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 组织级联 API - 专业/班级 JSON |
||||
|
*/ |
||||
|
@WebServlet(urlPatterns = {"/api/org/majors", "/api/org/clazz"}) |
||||
|
public class OrgApiServlet extends BaseServlet { |
||||
|
|
||||
|
private final OrgService orgService = new OrgService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
String uri = request.getRequestURI(); |
||||
|
if (uri.endsWith("/majors")) { |
||||
|
int deptId = ParamUtil.getInt(request, "deptId", 0); |
||||
|
writeJson(response, ApiResult.ok(orgService.listMajorsByDept(deptId))); |
||||
|
} else if (uri.endsWith("/clazz")) { |
||||
|
int majorId = ParamUtil.getInt(request, "majorId", 0); |
||||
|
writeJson(response, ApiResult.ok(orgService.listClazzByMajor(majorId))); |
||||
|
} else { |
||||
|
writeJson(response, ApiResult.fail("无效路径")); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,73 @@ |
|||||
|
package com.student.servlet.admin; |
||||
|
|
||||
|
import com.student.bean.Clazz; |
||||
|
import com.student.bean.Department; |
||||
|
import com.student.bean.Major; |
||||
|
import com.student.service.OrgService; |
||||
|
import com.student.servlet.BaseServlet; |
||||
|
import com.student.util.IpUtil; |
||||
|
import com.student.util.ParamUtil; |
||||
|
|
||||
|
import javax.servlet.ServletException; |
||||
|
import javax.servlet.annotation.WebServlet; |
||||
|
import javax.servlet.http.HttpServletRequest; |
||||
|
import javax.servlet.http.HttpServletResponse; |
||||
|
import java.io.IOException; |
||||
|
|
||||
|
/** |
||||
|
* 管理员 - 组织架构管理 |
||||
|
*/ |
||||
|
@WebServlet("/admin/org") |
||||
|
public class OrgManageServlet extends BaseServlet { |
||||
|
|
||||
|
private final OrgService orgService = new OrgService(); |
||||
|
|
||||
|
@Override |
||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
request.setAttribute("deptList", orgService.listDepts()); |
||||
|
request.setAttribute("majorList", orgService.listAllMajors()); |
||||
|
request.setAttribute("clazzList", orgService.listAllClazz()); |
||||
|
request.getRequestDispatcher("/admin/org.jsp").forward(request, response); |
||||
|
} |
||||
|
|
||||
|
@Override |
||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) |
||||
|
throws ServletException, IOException { |
||||
|
String type = ParamUtil.getString(request, "type"); |
||||
|
String name = ParamUtil.getString(request, "name"); |
||||
|
String code = ParamUtil.getString(request, "code"); |
||||
|
boolean success = false; |
||||
|
|
||||
|
try { |
||||
|
if ("dept".equals(type)) { |
||||
|
Department dept = new Department(); |
||||
|
dept.setName(name); |
||||
|
dept.setCode(code); |
||||
|
success = orgService.addDept(dept); |
||||
|
} else if ("major".equals(type)) { |
||||
|
Major major = new Major(); |
||||
|
major.setName(name); |
||||
|
major.setCode(code); |
||||
|
major.setDepartmentId(ParamUtil.getInt(request, "deptId", 0)); |
||||
|
success = orgService.addMajor(major); |
||||
|
} else if ("clazz".equals(type)) { |
||||
|
Clazz clazz = new Clazz(); |
||||
|
clazz.setName(name); |
||||
|
clazz.setMajorId(ParamUtil.getInt(request, "majorId", 0)); |
||||
|
clazz.setGrade(ParamUtil.getString(request, "grade")); |
||||
|
success = orgService.addClazz(clazz); |
||||
|
} |
||||
|
} catch (RuntimeException e) { |
||||
|
redirectWithMsg(response, request, "/admin/org", e.getMessage()); |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
if (success) { |
||||
|
logOperation(getLoginUser(request), "admin", "添加组织:" + type, IpUtil.getClientIp(request)); |
||||
|
redirectWithMsg(response, request, "/admin/org", "添加成功"); |
||||
|
} else { |
||||
|
redirectWithMsg(response, request, "/admin/org", "添加失败"); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue