Compare commits

...

6 Commits

39 changed files with 3899 additions and 461 deletions

290
hs_err_pid36376.log Normal file
View File

@@ -0,0 +1,290 @@
#
# There is insufficient memory for the Java Runtime Environment to continue.
# Native memory allocation (mmap) failed to map 8323072 bytes. Error detail: G1 virtual space
# Possible reasons:
# The system is out of physical RAM or swap space
# This process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap
# Possible solutions:
# Reduce memory load on the system
# Increase physical memory or swap space
# Check if swap backing store is full
# Decrease Java heap size (-Xmx/-Xms)
# Decrease number of Java threads
# Decrease Java thread stack sizes (-Xss)
# Set larger code cache with -XX:ReservedCodeCacheSize=
# JVM is running with Zero Based Compressed Oops mode in which the Java heap is
# placed in the first 32GB address space. The Java Heap base address is the
# maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress
# to set the Java Heap base and to place the Java Heap above 32GB virtual address.
# This output file may be truncated or incomplete.
#
# Out of Memory Error (os_windows.cpp:3828), pid=36376, tid=60436
#
# JRE version: (21.0.5+8) (build )
# Java VM: OpenJDK 64-Bit Server VM (21.0.5+8-b631.30, mixed mode, sharing, tiered, compressed oops, compressed class ptrs, g1 gc, windows-amd64)
# No core dump will be written. Minidumps are not enabled by default on client versions of Windows
#
--------------- S U M M A R Y ------------
Command Line: git4idea.http.GitAskPassApp Username for 'https://gitea.kronecker.cc':
Host: 13th Gen Intel(R) Core(TM) i7-13620H, 16 cores, 31G, Windows 11 , 64 bit Build 26100 (10.0.26100.3912)
Time: Sun Dec 7 22:30:22 2025 Windows 11 , 64 bit Build 26100 (10.0.26100.3912) elapsed time: 1.502574 seconds (0d 0h 0m 1s)
--------------- T H R E A D ---------------
Current thread (0x00000297b3889a10): JavaThread "Unknown thread" [_thread_in_vm, id=60436, stack(0x000000d684000000,0x000000d684100000) (1024K)]
Stack: [0x000000d684000000,0x000000d684100000]
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V [jvm.dll+0x6e52b9]
V [jvm.dll+0x8c3633]
V [jvm.dll+0x8c5b8e]
V [jvm.dll+0x8c6273]
V [jvm.dll+0x288f46]
V [jvm.dll+0x6e1a35]
V [jvm.dll+0x6d5e3a]
V [jvm.dll+0x3634bb]
V [jvm.dll+0x36b086]
V [jvm.dll+0x3bd35b]
V [jvm.dll+0x3bd618]
V [jvm.dll+0x335c2c]
V [jvm.dll+0x33691b]
V [jvm.dll+0x88aa89]
V [jvm.dll+0x3ca518]
V [jvm.dll+0x873b98]
V [jvm.dll+0x45eede]
V [jvm.dll+0x460bc1]
C [jli.dll+0x52ab]
C [ucrtbase.dll+0x37b0]
C [KERNEL32.DLL+0x2e8d7]
C [ntdll.dll+0x9c5dc]
--------------- P R O C E S S ---------------
Threads class SMR info:
_java_thread_list=0x00007ffcc08aa148, length=0, elements={
}
Java Threads: ( => current thread )
Total: 0
Other Threads:
0x00000297b54e98c0 WorkerThread "GC Thread#0" [id=35860, stack(0x000000d684100000,0x000000d684200000) (1024K)]
0x00000297b54fb4e0 ConcurrentGCThread "G1 Main Marker" [id=58320, stack(0x000000d684200000,0x000000d684300000) (1024K)]
0x00000297b54fc780 WorkerThread "G1 Conc#0" [id=60424, stack(0x000000d684300000,0x000000d684400000) (1024K)]
[error occurred during error reporting (printing all threads), id 0xc0000005, EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x00007ffcbff98ce7]
VM state: not at safepoint (not fully initialized)
VM Mutex/Monitor currently owned by a thread: ([mutex/lock_event])
[0x00007ffcc091eb30] Heap_lock - owner thread: 0x00000297b3889a10
Heap address: 0x0000000604800000, size: 8120 MB, Compressed Oops mode: Zero based, Oop shift amount: 3
CDS archive(s) mapped at: [0x0000000000000000-0x0000000000000000-0x0000000000000000), size 0, SharedBaseAddress: 0x0000000800000000, ArchiveRelocationMode: 1.
Narrow klass base: 0x0000000000000000, Narrow klass shift: 0, Narrow klass range: 0x0
GC Precious Log:
CardTable entry size: 512
Card Set container configuration: InlinePtr #cards 4 size 8 Array Of Cards #cards 32 size 80 Howl #buckets 8 coarsen threshold 7372 Howl Bitmap #cards 1024 size 144 coarsen threshold 921 Card regions per heap region 1 cards per card region 8192
Heap:
garbage-first heap total 0K, used 0K [0x0000000604800000, 0x0000000800000000)
region size 4096K, 0 young (0K), 0 survivors (0K)
Metaspace used 0K, committed 0K, reserved 0K
class space used 0K, committed 0K, reserved 0K
Heap Regions: E=young(eden), S=young(survivor), O=old, HS=humongous(starts), HC=humongous(continues), CS=collection set, F=free, TAMS=top-at-mark-start, PB=parsable bottom
Card table byte_map: [0x00000297ca380000,0x00000297cb360000] _byte_map_base: 0x00000297c735c000
Marking Bits: (CMBitMap*) 0x00000297b54e9fc0
Bits: [0x00000297cb360000, 0x00000297d3240000)
GC Heap History (0 events):
No events
Dll operation events (1 events):
Event: 0.007 Loaded shared library D:\IDEAUI\IntelliJ IDEA 2024.3.2.1\jbr\bin\java.dll
Deoptimization events (0 events):
No events
Classes loaded (0 events):
No events
Classes unloaded (0 events):
No events
Classes redefined (0 events):
No events
Internal exceptions (0 events):
No events
ZGC Phase Switch (0 events):
No events
VM Operations (0 events):
No events
Memory protections (0 events):
No events
Nmethod flushes (0 events):
No events
Events (0 events):
No events
Dynamic libraries:
0x00007ff676710000 - 0x00007ff67671a000 D:\IDEAUI\IntelliJ IDEA 2024.3.2.1\jbr\bin\java.exe
0x00007ffe17fc0000 - 0x00007ffe18226000 C:\Windows\SYSTEM32\ntdll.dll
0x00007ffe16180000 - 0x00007ffe16249000 C:\Windows\System32\KERNEL32.DLL
0x00007ffe15220000 - 0x00007ffe155ec000 C:\Windows\System32\KERNELBASE.dll
0x00007ffe15a00000 - 0x00007ffe15b4b000 C:\Windows\System32\ucrtbase.dll
0x00007ffdf8950000 - 0x00007ffdf896b000 D:\IDEAUI\IntelliJ IDEA 2024.3.2.1\jbr\bin\VCRUNTIME140.dll
0x00007ffdf89c0000 - 0x00007ffdf89d8000 D:\IDEAUI\IntelliJ IDEA 2024.3.2.1\jbr\bin\jli.dll
0x00007ffe16340000 - 0x00007ffe1650a000 C:\Windows\System32\USER32.dll
0x00007ffe15150000 - 0x00007ffe15177000 C:\Windows\System32\win32u.dll
0x00007ffdf55a0000 - 0x00007ffdf583a000 C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.3912_none_3e07963ce335137e\COMCTL32.dll
0x00007ffe17c20000 - 0x00007ffe17c4b000 C:\Windows\System32\GDI32.dll
0x00007ffe15d80000 - 0x00007ffe15e29000 C:\Windows\System32\msvcrt.dll
0x00007ffe15830000 - 0x00007ffe15962000 C:\Windows\System32\gdi32full.dll
0x00007ffe15cd0000 - 0x00007ffe15d73000 C:\Windows\System32\msvcp_win.dll
0x00007ffe16250000 - 0x00007ffe16280000 C:\Windows\System32\IMM32.DLL
0x00007ffe0f570000 - 0x00007ffe0f57c000 D:\IDEAUI\IntelliJ IDEA 2024.3.2.1\jbr\bin\vcruntime140_1.dll
0x00007ffda1170000 - 0x00007ffda11fd000 D:\IDEAUI\IntelliJ IDEA 2024.3.2.1\jbr\bin\msvcp140.dll
0x00007ffcbfc50000 - 0x00007ffcc0a11000 D:\IDEAUI\IntelliJ IDEA 2024.3.2.1\jbr\bin\server\jvm.dll
0x00007ffe17630000 - 0x00007ffe176e2000 C:\Windows\System32\ADVAPI32.dll
0x00007ffe16290000 - 0x00007ffe16336000 C:\Windows\System32\sechost.dll
0x00007ffe15e30000 - 0x00007ffe15f46000 C:\Windows\System32\RPCRT4.dll
0x00007ffe17ba0000 - 0x00007ffe17c14000 C:\Windows\System32\WS2_32.dll
0x00007ffe140e0000 - 0x00007ffe1413e000 C:\Windows\SYSTEM32\POWRPROF.dll
0x00007ffe11b40000 - 0x00007ffe11b76000 C:\Windows\SYSTEM32\WINMM.dll
0x00007ffe0b240000 - 0x00007ffe0b24b000 C:\Windows\SYSTEM32\VERSION.dll
0x00007ffe140c0000 - 0x00007ffe140d4000 C:\Windows\SYSTEM32\UMPDC.dll
0x00007ffe13fa0000 - 0x00007ffe13fba000 C:\Windows\SYSTEM32\kernel.appcore.dll
0x00007ffe0f520000 - 0x00007ffe0f52a000 D:\IDEAUI\IntelliJ IDEA 2024.3.2.1\jbr\bin\jimage.dll
0x00007ffe12840000 - 0x00007ffe12a81000 C:\Windows\SYSTEM32\DBGHELP.DLL
0x00007ffe17750000 - 0x00007ffe17ad4000 C:\Windows\System32\combase.dll
0x00007ffe15f80000 - 0x00007ffe16060000 C:\Windows\System32\OLEAUT32.dll
0x00007ffde3870000 - 0x00007ffde38a9000 C:\Windows\SYSTEM32\dbgcore.DLL
0x00007ffe15180000 - 0x00007ffe15219000 C:\Windows\System32\bcryptPrimitives.dll
0x00007ffdf8930000 - 0x00007ffdf8950000 D:\IDEAUI\IntelliJ IDEA 2024.3.2.1\jbr\bin\java.dll
dbghelp: loaded successfully - version: 4.0.5 - missing functions: none
symbol engine: initialized successfully - sym options: 0x614 - pdb path: .;D:\IDEAUI\IntelliJ IDEA 2024.3.2.1\jbr\bin;C:\Windows\SYSTEM32;C:\Windows\WinSxS\amd64_microsoft.windows.common-controls_6595b64144ccf1df_6.0.26100.3912_none_3e07963ce335137e;D:\IDEAUI\IntelliJ IDEA 2024.3.2.1\jbr\bin\server
VM Arguments:
java_command: git4idea.http.GitAskPassApp Username for 'https://gitea.kronecker.cc':
java_class_path (initial): D:/IDEAUI/IntelliJ IDEA 2024.3.2.1/plugins/vcs-git/lib/git4idea-rt.jar;D:/IDEAUI/IntelliJ IDEA 2024.3.2.1/lib/externalProcess-rt.jar
Launcher Type: SUN_STANDARD
[Global flags]
intx CICompilerCount = 12 {product} {ergonomic}
uint ConcGCThreads = 3 {product} {ergonomic}
uint G1ConcRefinementThreads = 13 {product} {ergonomic}
size_t G1HeapRegionSize = 4194304 {product} {ergonomic}
uintx GCDrainStackTargetSize = 64 {product} {ergonomic}
size_t InitialHeapSize = 532676608 {product} {ergonomic}
size_t MarkStackSize = 4194304 {product} {ergonomic}
size_t MaxHeapSize = 8514437120 {product} {ergonomic}
size_t MinHeapDeltaBytes = 4194304 {product} {ergonomic}
size_t MinHeapSize = 8388608 {product} {ergonomic}
uintx NonNMethodCodeHeapSize = 7602480 {pd product} {ergonomic}
uintx NonProfiledCodeHeapSize = 122027880 {pd product} {ergonomic}
uintx ProfiledCodeHeapSize = 122027880 {pd product} {ergonomic}
uintx ReservedCodeCacheSize = 251658240 {pd product} {ergonomic}
bool SegmentedCodeCache = true {product} {ergonomic}
size_t SoftMaxHeapSize = 8514437120 {manageable} {ergonomic}
bool UseCompressedOops = true {product lp64_product} {ergonomic}
bool UseG1GC = true {product} {ergonomic}
bool UseLargePagesIndividualAllocation = false {pd product} {ergonomic}
Logging:
Log output configuration:
#0: stdout all=warning uptime,level,tags foldmultilines=false
#1: stderr all=off uptime,level,tags foldmultilines=false
Environment Variables:
JAVA_HOME=E:\java21
PATH=C:/Program Files/Git/mingw64/libexec/git-core;C:/Program Files/Git/mingw64/libexec/git-core;C:\Program Files\Git\mingw64\bin;C:\Program Files\Git\usr\bin;C:\Users\KiriAky\bin;C:\Program Files\Microsoft MPI\Bin\;E:\java21\bin;D:\mingw64\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.6\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.6\libnvvp;D:\VMware\bin\;C:\Python313\Scripts;C:\Python313;C:\Python312\Scripts\;C:\Python312\;C:\Program Files (x86)\Common Files\Intel\Shared Libraries\redist\intel64\compiler;C:\Program Files (x86)\Common Files\Oracle\Java\java8path;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps;C:\Recovery\OEM\Backup\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\dotnet\;C:\Users\<5C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\AppData\Roaming\nvm;C:\Program Files\nodejs;C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\DTS\Binn\;C:\Program Files\Microsoft SQL Server\150\Tools\Binn\;C:\ProgramData\chocolatey\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;C:\Windows\System32\OpenSSH\;C:\Program Files\NVIDIA Corporation\NVIDIA app\NvDLISR;H:\platform-tools;C:\Program Files (x86)\Bitvise SSH Client;C:\Program Files\NVIDIA Corporation\Nsight Compute 2024.3.2\;C:\mingw64\bin;C:\Program Files\GTK3-Runtime Win64\bin;C:\Program Files\Git\cmd;C:\Program Files\Pandoc\;C:\Program Files\nodejs\;C:\Program Files (x86)\Microsoft SQL Server\160\Tools\Binn\;C:\Program Files\Microsoft SQL Server\160\Tools\Binn\;C:\Program Files\Microsoft SQL Server\Client SDK\ODBC\170\Tools\Binn\;C:\Program Files\Microsoft SQL Server\160\DTS\Binn\;C:\Program Files\Microsoft SQL Server\170\Tools\Binn\;C:\Program Files (x86)\Windows Kits\10\Windows Performance Toolkit\;C:\Python313\Scripts\;C:\Python313\;C:\Users\KiriAky\AppData\Local\Programs\Python\Python313\Scripts\;C:\Users\KiriAky\AppData\Local\Programs\Python\Python313\;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.6\bin\\..\extras\CUPTI\lib64;E:\java21\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.6\bin;C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.6\libnvvp;D:\VMware\bin\;C:\Python312\Scripts\;C:\Python312\;C:\Program Files (x86)\Common Files\Intel\Shared Libraries\redist\intel64\compiler;C:\Program Files (x86)\Common Files\Oracle\Java\java8path;C:\Program Files (x86)\Common Files\Oracle\Java\javapath;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;C:\WINDOWS\System32\OpenSSH\;C:\Users\Administrator\AppData\Local\Microsoft\WindowsApps;C:\Recovery\OEM\Backup\;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files\dotnet\;C:\Users\<5C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>\AppData\Roaming\nvm;C:\Program Files\nodejs;C:\Program Files (x86)\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\Tools\Binn\;C:\Program Files\Microsoft SQL Server\100\DTS\Binn\;D:\Git\cmd;C:\Program Files\Microsof;D:\Microsoft VS Code\bin;C:\Users\KiriAky\AppData\Roaming\npm
USERNAME=KiriAky
DISPLAY=:0.0
LC_ALL=en_US.UTF-8
TERM=xterm-256color
TMPDIR=C:\Users\KiriAky\AppData\Local\Temp
OS=Windows_NT
PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 186 Stepping 2, GenuineIntel
TMP=C:\Users\KiriAky\AppData\Local\Temp
TEMP=C:\Users\KiriAky\AppData\Local\Temp
Periodic native trim disabled
JNI global refs:
JNI global refs: 0, weak refs: 0
JNI global refs memory usage: 0, weak refs: 0
Process memory usage:
Resident Set Size: 13356K (0% of 33251192K total physical memory with 1375080K free physical memory)
OOME stack traces (most recent first):
Classloader memory used:
--------------- S Y S T E M ---------------
OS:
Windows 11 , 64 bit Build 26100 (10.0.26100.3912)
OS uptime: 12 days 11:36 hours
CPU: total 16 (initial active 16) (8 cores per cpu, 2 threads per core) family 6 model 186 stepping 2 microcode 0x4114, cx8, cmov, fxsr, ht, mmx, 3dnowpref, sse, sse2, sse3, ssse3, sse4.1, sse4.2, popcnt, lzcnt, tsc, tscinvbit, avx, avx2, aes, erms, clmul, bmi1, bmi2, adx, sha, fma, vzeroupper, clflush, clflushopt, clwb, serialize, rdtscp, rdpid, fsrm, f16c, pku, cet_ibt, cet_ss
Processor Information for processor 0
Max Mhz: 2400, Current Mhz: 2400, Mhz Limit: 2400
Processor Information for processor 1
Max Mhz: 2400, Current Mhz: 2400, Mhz Limit: 2400
Processor Information for processor 2
Max Mhz: 2400, Current Mhz: 2400, Mhz Limit: 2400
Processor Information for processor 3
Max Mhz: 2400, Current Mhz: 2400, Mhz Limit: 2400
Processor Information for processor 4
Max Mhz: 2400, Current Mhz: 2400, Mhz Limit: 2400
Processor Information for processor 5
Max Mhz: 2400, Current Mhz: 2400, Mhz Limit: 2400
Processor Information for processor 6
Max Mhz: 2400, Current Mhz: 2400, Mhz Limit: 2400
Processor Information for processor 7
Max Mhz: 2400, Current Mhz: 2400, Mhz Limit: 2400
Processor Information for processor 8
Max Mhz: 2400, Current Mhz: 2400, Mhz Limit: 2400
Processor Information for processor 9
Max Mhz: 2400, Current Mhz: 2400, Mhz Limit: 2400
Processor Information for processor 10
Max Mhz: 2400, Current Mhz: 2400, Mhz Limit: 2400
Processor Information for processor 11
Max Mhz: 2400, Current Mhz: 2400, Mhz Limit: 2400
Processor Information for processor 12
Max Mhz: 2400, Current Mhz: 1800, Mhz Limit: 1800
Processor Information for processor 13
Max Mhz: 2400, Current Mhz: 1800, Mhz Limit: 1800
Processor Information for processor 14
Max Mhz: 2400, Current Mhz: 1800, Mhz Limit: 1800
Processor Information for processor 15
Max Mhz: 2400, Current Mhz: 1800, Mhz Limit: 1800
Memory: 4k page, system-wide physical 32471M (1342M free)
TotalPageFile size 68431M (AvailPageFile size 9M)
current process WorkingSet (physical memory assigned to process): 13M, peak: 13M
current process commit charge ("private bytes"): 580M, peak: 588M
vm_info: OpenJDK 64-Bit Server VM (21.0.5+8-b631.30) for windows-amd64 JRE (21.0.5+8-b631.30), built on 2024-12-06 by "builduser" with MS VC++ 16.10 / 16.11 (VS2019)
END.

2
src/Main.java Normal file
View File

@@ -0,0 +1,2 @@
public class Main {
}

View File

@@ -1,5 +1,12 @@
package backend; package backend;
import backend.model.enums.LoginStatus;
import view.LoginFrame;
import view.MainFrame;
public class Main { public class Main {
public static void main(String[] args) {
LoginFrame loginframe = new LoginFrame();
}
} }

View File

@@ -1,27 +0,0 @@
package backend.controller.interfaces;
import backend.service.interfaces.AuthService;
/**
* 登录控制器接口,用于处理用户登录和注册相关的业务逻辑
*/
public interface LoginController {
// AuthService authService;
//getter/setter
/**
* 处理用户登录请求
* @param username 用户名
* @param password 密码
*/
public void handleLogin(String username, String password);
/**
* 处理用户注册请求
* @param username 用户名
* @param password 密码
* @param email 邮箱地址
*/
public void handleRegister(String username, String password, String email);
}

View File

@@ -1,33 +0,0 @@
package backend.controller.interfaces;
import backend.service.interfaces.DataQueryService;
/**
* 查询控制器接口
* 定义了数据查询和管理的相关操作接口
*/
public interface QueryController {
// DataQueryService dataService;
//getter/setter
/**
* 显示所有数据项
* 该方法用于获取并展示系统中的全部数据记录
*/
void displayAll();
/**
* 根据关键字搜索数据
* @param keyword 搜索关键字,用于匹配数据项的标题、描述等字段
*/
void searchData(String keyword);
/**
* 添加新的数据项
* @param title 数据项标题
* @param desc 数据项描述
* @param category 数据项分类
* @param userId 用户ID标识数据项的创建者
*/
void addDataItem(String title, String desc, String category, int userId);
}

View File

@@ -1,33 +0,0 @@
package backend.controller.interfaces;
import backend.service.interfaces.UserService;
/**
* 用户控制器接口
* 定义了用户管理相关的核心操作方法
*/
public interface UserController {
// UserService userService;
//getter/setter
/**
* 显示指定用户的详细信息
* @param id 用户ID
*/
void showUserInfo(int id);
/**
* 列出所有用户信息
* @param adminId 管理员ID用于权限验证
*/
void listAllUsers(int adminId);
/**
* 更新用户角色
* @param targetId 目标用户ID
* @param newRole 新的角色名称
* @param adminId 执行操作的管理员ID
*/
void updateRole(int targetId, String newRole, int adminId);
}

View File

@@ -0,0 +1,160 @@
package backend.dao;
import backend.model.Charts;
import backend.utils.DBConnectionPool;
import backend.utils.DBHelper;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class ChartsDao {
List<Charts> commonResultSet(ResultSet rs) throws SQLException {
List<Charts> chartsPoList = new ArrayList<>();
while(rs.next()){
Charts charts = new Charts();
charts.setUserid(rs.getInt("userid"));
charts.setCount(rs.getInt("count"));
charts.setScore(rs.getInt("score"));
chartsPoList.add(charts);
}
return chartsPoList;
}
public List<Charts> findAll() {
List<Charts> chartsPoList = new ArrayList<>();
Connection conn = DBHelper.getInstance().getConnection();
String sql = "select userid,count,score from charts";
try {
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
Charts charts = new Charts();
charts.setUserid(rs.getInt("userid"));
charts.setCount(rs.getInt("count"));
charts.setScore(rs.getInt("score"));
chartsPoList.add(charts);
}
rs.close();
stmt.close();
} catch (SQLException e) {
System.out.println("查询所有用户失败: " + e.getMessage());
}
return chartsPoList;
}
public Charts findById(int userid) {
Connection conn = DBHelper.getInstance().getConnection();
Charts chartsPo = null;
if(conn==null)
return null;
String sql = "select userid,count,score from charts where userid = ?";
try {
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1,userid);
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
chartsPo = new Charts();
chartsPo.setUserid(rs.getInt("userid"));
chartsPo.setCount(rs.getInt("count"));
chartsPo.setScore(rs.getInt("score"));
}
rs.close();
stmt.close();
} catch (SQLException e) {
System.out.println("查询用户失败: " + e.getMessage());
}
return chartsPo;
}
public boolean insertCharts(Charts charts) {
Connection conn = DBHelper.getInstance().getConnection();
int row = 0;
if(conn==null)
return false;
//查找是否已存在
String findSql = "select * from charts where userid = ?";
try{
PreparedStatement stmt = conn.prepareStatement(findSql);
stmt.setInt(1,charts.getUserid());
ResultSet rs = stmt.executeQuery();
if(rs.next()){
return false;
}
rs.close();
} catch (SQLException e) {
System.out.println("查找用户失败: " + e.getMessage());
}
String sql = "insert into charts (userid,count,score) values (?,?,?)";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1,charts.getUserid());
stmt.setInt(2,charts.getCount());
stmt.setInt(3,charts.getScore());
row = stmt.executeUpdate();
stmt.close();
DBConnectionPool.releaseConnection(conn);
} catch (SQLException e) {
System.out.println("添加用户失败: " + e.getMessage());
}
return row > 0;
}
public boolean updateCharts(Charts charts) {
Connection conn = DBHelper.getInstance().getConnection();
Charts oldCharts = findById(charts.getUserid());
int row = 0;
if(conn==null)
return false;
String sql = "update charts set count = ?,score = ? where userid = ?";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1,oldCharts.getCount()+1);
stmt.setInt(2,oldCharts.getScore()+charts.getScore());
stmt.setInt(3,charts.getUserid());
row = stmt.executeUpdate();
stmt.close();
} catch (SQLException e) {
System.out.println("更新用户失败: " + e.getMessage());
}
return row > 0;
}
public boolean deleteCharts(int userid) {
Connection conn = DBHelper.getInstance().getConnection();
String sql = "delete from charts where userid = ?";
int row = 0;
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1,userid);
row = stmt.executeUpdate() ;
} catch (SQLException e) {
System.out.println("删除用户失败: " + e.getMessage());
}
return row>0;
}
public List<Charts> sortByScoreUp() {
List<Charts> chartsPoList = new ArrayList<>();
List<Charts> list = findAll();
for(int i = 0; i < list.size() - 1; i++) {
for(int j = i + 1; j < list.size(); j++) {
if(list.get(i).getScore() < list.get(j).getScore()) {
Charts temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
}
return list;
}
public List<Charts> sortByScoreDown() {
List<Charts> chartsPoList = new ArrayList<>();
List<Charts> list = findAll();
for(int i = 0; i < list.size() - 1; i++) {
for(int j = i + 1; j < list.size(); j++) {
if(list.get(i).getScore() > list.get(j).getScore()) {
Charts temp = list.get(i);
list.set(i, list.get(j));
list.set(j, temp);
}
}
}
return list;
}
}

View File

@@ -0,0 +1,233 @@
package backend.dao;
import backend.model.Questions;
import backend.model.TestRecord;
import backend.utils.DBConnectionPool;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class QuestionsDao {
List<Questions> commonResultSet(ResultSet rs) throws SQLException{
List<Questions> questionPoList = new ArrayList<>();
while(rs.next()){
Questions questions = new Questions();
questions.setId(rs.getInt("id"));
questions.setName(rs.getString("name"));
questions.setDescription(rs.getString("description"));
questions.setAnswer(rs.getString("answer"));
questions.setFrequency(rs.getInt("frequency"));
questionPoList.add(questions);
}
return questionPoList;
}
public List<Questions> getAll() {
List<Questions> questionPoList = new ArrayList<>();
//1. 从连接池中拿到连接
Connection conn = DBConnectionPool.getConnection();
if(conn==null)
return null;
//2. 创建Statement对象
String sql = "select id,name,description,answer,frequency from questions";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
questionPoList=commonResultSet(rs);
rs.close();
stmt.close();
}catch(SQLException e){
System.out.println("数据库异常:"+ e.getMessage());
}finally {
DBConnectionPool.releaseConnection(conn);
}
return questionPoList;
}
public Questions getById(Integer id) {
Connection conn = DBConnectionPool.getConnection();
if (conn == null)
return null;
Questions questionPo = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
stmt = conn.prepareStatement("select id,name,description,answer,frequency from questions where id = ?");
stmt.setInt(1, id);
rs = stmt.executeQuery();
if (rs.next()) { // 检查是否有数据
questionPo = new Questions();
questionPo.setId(rs.getInt("id"));
questionPo.setName(rs.getString("name"));
questionPo.setDescription(rs.getString("description"));
questionPo.setAnswer(rs.getString("answer"));
questionPo.setFrequency(rs.getInt("frequency"));
}
} catch (SQLException e) {
System.out.println("数据库异常:" + e.getMessage());
} finally {
// 释放资源
try {
if (rs != null) rs.close();
if (stmt != null) stmt.close();
} catch (SQLException e) {
System.out.println("资源释放异常:" + e.getMessage());
}
DBConnectionPool.releaseConnection(conn);
}
return questionPo;
}
public List<Questions> getByCondition(Integer frequency,String key) {
List<Questions> questionPoList = null;
//1. 从连接池中拿到连接
Connection conn = DBConnectionPool.getConnection();
if(conn==null)
return null;
//2. 创建Statement对象
String sql = "select id,name,description,answer,frequency from questions where name like ?";
if(frequency != null)
sql += " and frequency = ?";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, "%"+key+"%");
if(frequency != null)
stmt.setInt(2, frequency);
ResultSet rs = stmt.executeQuery();
questionPoList =commonResultSet(rs);
rs.close();
stmt.close();
}catch(SQLException e){
System.out.println("数据库异常:"+ e.getMessage());
}finally {
DBConnectionPool.releaseConnection(conn);
}
return questionPoList;
}
public boolean insert(Questions question){
int row = 0;
//1. 从连接池中拿到连接
Connection conn = DBConnectionPool.getConnection();
if(conn==null)
return false;
//2. 创建Statement对象
String sql = "insert into questions(name,description,answer,frequency) values(?,?,?,?)";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, question.getName());
stmt.setString(2, question.getDescription());
stmt.setString(3, question.getAnswer());
if(question.getFrequency()==null)
stmt.setInt(4, 0);
else
stmt.setInt(4, question.getFrequency());
row = stmt.executeUpdate();
stmt.close();
}catch(SQLException e){
System.out.println("数据库异常:"+ e.getMessage());
}finally {
DBConnectionPool.releaseConnection(conn);
}
return row > 0;
}
public boolean delete(Integer id){
int row = 0;
//1. 从连接池中拿到连接
Connection conn = DBConnectionPool.getConnection();
if(conn==null)
return false;
//2. 创建Statement对象
String sql = "delete from questions where id = ?";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, id);
row = stmt.executeUpdate();
stmt.close();
}catch(SQLException e){
System.out.println("数据库异常:"+ e.getMessage());
}finally {
DBConnectionPool.releaseConnection(conn);
}
return row > 0;
}
public boolean update(Questions question){
int row = 0;
//1. 从连接池中拿到连接
Connection conn = DBConnectionPool.getConnection();
if(conn==null)
return false;
//2. 创建Statement对象
String sql = "update questions set name = ?,description = ?,answer = ?,frequency=? where id = ?";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, question.getName());
stmt.setString(2, question.getDescription());
stmt.setString(3, question.getAnswer());
if(question.getFrequency()==null)
stmt.setInt(4, 0);
else
stmt.setInt(4, question.getFrequency());
stmt.setInt(5, question.getId());
row = stmt.executeUpdate();
stmt.close();
}catch(SQLException e){
System.out.println("数据库异常:"+ e.getMessage());
}finally {
DBConnectionPool.releaseConnection(conn);
}
return row > 0;
}
public Questions getRandomQuestion() {
List<Questions> questionPoList = getAll();
Random random = new Random();
//生成随机索引
int index = random.nextInt(questionPoList.size());
return questionPoList.get(index);
}
public Questions getByName(String name) {
Questions questionPo = null;
//1. 从连接池中拿到连接
Connection conn = DBConnectionPool.getConnection();
if(conn==null)
return null;
//2. 创建Statement对象
String sql = "select id,name,description,answer,frequency from questions where name = ?";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, name);
ResultSet rs = stmt.executeQuery();
questionPo = commonResultSet(rs).get(0);
rs.close();
stmt.close();
} catch(SQLException e){
System.out.println("数据库异常:"+ e.getMessage());
} finally {
DBConnectionPool.releaseConnection(conn);
}
return questionPo;
}
// public static void main(String[] args) {
// WordDao wordDao = new WordDao();
// //查询
// List<WordPo> wordPoList = wordDao.getByCondition(3,"v");
// if(wordPoList != null)
// for(WordPo wordPo:wordPoList)
// System.out.println(wordPo.getWord());
// //增加
// wordDao.insert(new WordPo("test", "test", "test", 1));
// //更新
// wordDao.updata(new WordPo(1, 1, "test", "test", "test"));
// }
}

View File

@@ -0,0 +1,163 @@
package backend.dao;
import backend.model.TestRecord;
import backend.utils.DBConnectionPool;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;
public class TestRecordDao {
List<TestRecord> commonResultSet(ResultSet rs) throws SQLException{
List<TestRecord> testRecordPoList = new ArrayList<>();
while(rs.next()){
TestRecord testRecord = new TestRecord();
testRecord.setId(rs.getInt("id"));
testRecord.setUserId(rs.getInt("userId"));
testRecord.setQuestionId(rs.getInt("questionId"));
testRecord.setScore(rs.getInt("score"));
testRecord.setAnswer(rs.getString("answer"));
testRecord.setTime(rs.getDate("time"));
testRecordPoList.add(testRecord);
}
return testRecordPoList;
}
public List<TestRecord> getAll() {
List<TestRecord> testRecordPoList = new ArrayList<>();
//1. 从连接池中拿到连接
Connection conn = DBConnectionPool.getConnection();
if(conn==null)
return null;
//2. 创建Statement对象
String sql = "select id,userId,questionId,score,answer,time from testRecord";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
testRecordPoList=commonResultSet(rs);
rs.close();
stmt.close();
} catch(SQLException e){
System.out.println("数据库异常:"+ e.getMessage());
}
finally {
DBConnectionPool.releaseConnection(conn);
}
return testRecordPoList;
}
public List<TestRecord> getByUserId(Integer userId) {
List<TestRecord> testRecordPoList = new ArrayList<>();
//1. 从连接池中拿到连接
Connection conn = DBConnectionPool.getConnection();
if(conn==null)
return null;
//2. 创建Statement对象
String sql = "select id,userId,questionId,score,answer,time from testRecord where userId = ?";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, userId);
ResultSet rs = stmt.executeQuery();
testRecordPoList=commonResultSet(rs);
rs.close();
stmt.close();
} catch(SQLException e){
System.out.println("数据库异常:"+ e.getMessage());
} finally {
DBConnectionPool.releaseConnection(conn);
}
return testRecordPoList;
}
public List<TestRecord> getByQuestionId(Integer questionId) {
List<TestRecord> testRecordPoList = new ArrayList<>();
//1. 从连接池中拿到连接
Connection conn = DBConnectionPool.getConnection();
if(conn==null)
return null;
//2. 创建Statement对象
String sql = "select id,userId,questionId,score,answer,time from testRecord where questionId = ?";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, questionId);
ResultSet rs = stmt.executeQuery();
testRecordPoList=commonResultSet(rs);
rs.close();
stmt.close();
}
catch(SQLException e){
System.out.println("数据库异常:"+ e.getMessage());
} finally {
DBConnectionPool.releaseConnection(conn);
}
return testRecordPoList;
}
public List<TestRecord> getByUserIdAndQuestionId(Integer userId, Integer questionId) {
List<TestRecord> testRecordPoList = new ArrayList<>();
//1. 从连接池中拿到连接
Connection conn = DBConnectionPool.getConnection();
if(conn==null)
return null;
//2. 创建Statement对象
String sql = "select id,userId,questionId,score,answer,time from testRecord where userId = ? and questionId = ?";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, userId);
stmt.setInt(2, questionId);
ResultSet rs = stmt.executeQuery();
testRecordPoList = commonResultSet(rs);
rs.close();
stmt.close();
} catch(SQLException e){
System.out.println("数据库异常:"+ e.getMessage());
} finally {
DBConnectionPool.releaseConnection(conn);
}
return testRecordPoList;
}
public boolean insert(TestRecord testRecord){
int row = 0;
//1. 从连接池中拿到连接
Connection conn = DBConnectionPool.getConnection();
if(conn==null)
return false;
//2. 创建Statement对象
String sql = "insert into testRecord(userId,questionId,score,answer,time) values(?,?,?,?,?)";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, testRecord.getUserId());
stmt.setInt(2, testRecord.getQuestionId());
stmt.setInt(3, testRecord.getScore());
stmt.setString(4, testRecord.getAnswer());
stmt.setDate(5, testRecord.getTime());
row = stmt.executeUpdate();
stmt.close();
} catch(SQLException e){
System.out.println("数据库异常:"+ e.getMessage());
} finally {
DBConnectionPool.releaseConnection(conn);
}
return row > 0;
}
public boolean delete(Integer id){
int row = 0;
//1. 从连接池中拿到连接
Connection conn = DBConnectionPool.getConnection();
if(conn==null)
return false;
//2. 创建Statement对象
String sql = "delete from testRecord where id = ?";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, id);
row = stmt.executeUpdate();
stmt.close();
} catch(SQLException e){
System.out.println("数据库异常:"+ e.getMessage());
} finally {
DBConnectionPool.releaseConnection(conn);
}
return row > 0;
}
}

View File

@@ -1,59 +1,74 @@
package backend.dao.impl; package backend.dao;
import backend.dao.interfaces.UserDaoIF;
import backend.model.User; import backend.model.User;
import backend.service.AuthService;
import backend.utils.DBConnectionPool;
import backend.utils.DBHelper; import backend.utils.DBHelper;
import java.sql.Connection; import java.sql.*;
import java.sql.PreparedStatement; import java.util.ArrayList;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List; import java.util.List;
public class UserDao implements UserDaoIF { public class UserDao {
List<User> commonResultSet(ResultSet rs) throws SQLException{
List<User> userPoList = new ArrayList<>();
while(rs.next()){
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password"));
user.setRole(rs.getString("role"));
user.setEmail(rs.getString("email"));
user.setCreatedAt(rs.getDate("createdAt"));
userPoList.add(user);
}
return userPoList;
}
@Override
public User findByUsername(String username) { public User findByUsername(String username) {
User user = null; User user = null;
//1. 从连接池中创建数据库连接 //1. 从连接池中创建数据库连接
Connection conn = DBHelper.getInstance().getConnection(); Connection conn = DBHelper.getInstance().getConnection();
//2. 创建Statement对象 //2. 创建Statement对象
String sql = "select username,password,role,email,createdAt from USER where username = ?"; String sql = "select id,username,password,role,email,createdAt from USER where username = ?";
try { try {
PreparedStatement stmt = conn.prepareStatement(sql); PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, username); stmt.setString(1, username);
ResultSet rs = stmt.executeQuery(); ResultSet rs = stmt.executeQuery();
while (rs.next()) { while (rs.next()) {
user = new User(); user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username")); user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password")); user.setPassword(rs.getString("password"));
user.setRole(rs.getString("role")); user.setRole(rs.getString("role"));
user.setEmail(rs.getString("email")); user.setEmail(rs.getString("email"));
user.setCreatedAt(rs.getTimestamp("createdAt")); user.setCreatedAt(rs.getDate("createdAt"));
} }
} catch (SQLException e) { } catch (SQLException e) {
System.out.println("查询用户失败: " + e.getMessage()); System.out.println("查询用户失败: " + e.getMessage());
} }
return user; return user;
} }
@Override
public User findById(int id) { public User findById(int id) {
User user = null; User user = null;
//1. 从连接池中创建数据库连接 //1. 从连接池中创建数据库连接
Connection conn = DBHelper.getInstance().getConnection(); Connection conn = DBHelper.getInstance().getConnection();
//2. 创建Statement对象 //2. 创建Statement对象
String sql = "select username,password,role,email,createdAt from USER where id = ?"; String sql = "select id,username,password,role,email,createdAt from USER where id = ?";
try{ try{
PreparedStatement stmt = conn.prepareStatement(sql); PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1,id); stmt.setInt(1,id);
ResultSet rs = stmt.executeQuery(); ResultSet rs = stmt.executeQuery();
while(rs.next()) { while(rs.next()) {
user = new User(); user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username")); user.setUsername(rs.getString("username"));
user.setPassword(rs.getString("password")); user.setPassword(rs.getString("password"));
user.setRole(rs.getString("role")); user.setRole(rs.getString("role"));
user.setEmail(rs.getString("email")); user.setEmail(rs.getString("email"));
user.setCreatedAt(rs.getTimestamp("createdAt")); user.setCreatedAt(rs.getDate("createdAt"));
} }
}catch (SQLException e) { }catch (SQLException e) {
System.out.println("查询用户失败: " + e.getMessage()); System.out.println("查询用户失败: " + e.getMessage());
@@ -61,9 +76,11 @@ public class UserDao implements UserDaoIF {
return user; return user;
} }
@Override
public boolean addUser(User user) { public boolean addUser(User user) {
Connection conn = DBHelper.getInstance().getConnection(); Connection conn = DBHelper.getInstance().getConnection();
int row=0;
if(conn==null)
return false;
String sql = "insert into USER (username,password,role,email,createdAt) values (?,?,?,?,?)"; String sql = "insert into USER (username,password,role,email,createdAt) values (?,?,?,?,?)";
try{ try{
PreparedStatement stmt = conn.prepareStatement(sql); PreparedStatement stmt = conn.prepareStatement(sql);
@@ -71,17 +88,22 @@ public class UserDao implements UserDaoIF {
stmt.setString(2,user.getPassword()); stmt.setString(2,user.getPassword());
stmt.setString(3,user.getRole()); stmt.setString(3,user.getRole());
stmt.setString(4,user.getEmail()); stmt.setString(4,user.getEmail());
stmt.setTimestamp(5,user.getCreatedAt()); stmt.setDate(5,user.getCreatedAt());
return stmt.executeUpdate() > 0; row = stmt.executeUpdate();
stmt.close();
DBConnectionPool.releaseConnection(conn);
} catch (SQLException e) { } catch (SQLException e) {
System.out.println("添加用户失败: " + e.getMessage()); System.out.println("添加用户失败: " + e.getMessage());
} }
return false; return row>0;
} }
@Override
public boolean updateUser(User user) { public boolean updateUser(User user) {
Connection conn = DBHelper.getInstance().getConnection(); Connection conn = DBHelper.getInstance().getConnection();
int row = 0;
if(conn==null)
return false;
String sql = "update USER set username = ?,password = ?,role = ?,email = ?,createdAt = ? where id = ?"; String sql = "update USER set username = ?,password = ?,role = ?,email = ?,createdAt = ? where id = ?";
try{ try{
PreparedStatement stmt = conn.prepareStatement(sql); PreparedStatement stmt = conn.prepareStatement(sql);
@@ -89,31 +111,34 @@ public class UserDao implements UserDaoIF {
stmt.setString(2,user.getPassword()); stmt.setString(2,user.getPassword());
stmt.setString(3,user.getRole()); stmt.setString(3,user.getRole());
stmt.setString(4,user.getEmail()); stmt.setString(4,user.getEmail());
stmt.setTimestamp(5,user.getCreatedAt()); stmt.setDate(5,user.getCreatedAt());
stmt.setInt(6,user.getId()); stmt.setInt(6,user.getId());
return stmt.executeUpdate() > 0; row = stmt.executeUpdate();
stmt.close();
} catch (SQLException e) { } catch (SQLException e) {
System.out.println("更新用户失败: " + e.getMessage()); System.out.println("更新用户失败: " + e.getMessage());
}finally {
DBConnectionPool.releaseConnection(conn);
} }
return false; return row>0;
} }
@Override
public boolean deleteUser(int id) { public boolean deleteUser(int id) {
Connection conn = DBHelper.getInstance().getConnection(); Connection conn = DBHelper.getInstance().getConnection();
String sql = "delete from USER where id = ?"; String sql = "delete from USER where id = ?";
int row = 0;
try{ try{
PreparedStatement stmt = conn.prepareStatement(sql); PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1,id); stmt.setInt(1,id);
return stmt.executeUpdate() > 0; row = stmt.executeUpdate() ;
} catch (SQLException e) { } catch (SQLException e) {
System.out.println("删除用户失败: " + e.getMessage()); System.out.println("删除用户失败: " + e.getMessage());
} }
return false; return row>0;
} }
@Override
public List<User> findAll() { public List<User> findAll() {
List<User> userPoList = new ArrayList<>();
Connection conn = DBHelper.getInstance().getConnection(); Connection conn = DBHelper.getInstance().getConnection();
String sql = "select id,username,password,role,email,createdAt from USER"; String sql = "select id,username,password,role,email,createdAt from USER";
try { try {
@@ -126,12 +151,53 @@ public class UserDao implements UserDaoIF {
user.setPassword(rs.getString("password")); user.setPassword(rs.getString("password"));
user.setRole(rs.getString("role")); user.setRole(rs.getString("role"));
user.setEmail(rs.getString("email")); user.setEmail(rs.getString("email"));
user.setCreatedAt(rs.getTimestamp("createdAt")); user.setCreatedAt(rs.getDate("createdAt"));
return List.of(user); userPoList.add(user);
} }
}catch (SQLException e) { }catch (SQLException e) {
System.out.println("查询所有用户失败: " + e.getMessage()); System.out.println("查询所有用户失败: " + e.getMessage());
} }
return List.of(); return userPoList;
} }
public List<User> findByCondition(String role, String key) {
List<User> userPoList = null;
//1. 从连接池中拿到连接
Connection conn = DBConnectionPool.getConnection();
if(conn==null)
return null;
//2. 创建Statement对象
String sql = "select id,username,password,role,email,createdAt from USER where username like ?";
if(role != null)
sql += " and role = ?";
try{
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setString(1, "%"+key+"%");
if(role != null)
stmt.setString(2, role);
ResultSet rs = stmt.executeQuery();
userPoList =commonResultSet(rs);
rs.close();
stmt.close();
}catch(SQLException e){
System.out.println("数据库异常:"+ e.getMessage());
}finally {
DBConnectionPool.releaseConnection(conn);
}
return userPoList;
}
public static void main(String[] args) {
UserDao userDao = new UserDao();
AuthService authService = new AuthService();
User user= userDao.findById(2);
System.out.println(user.getRole());
user.setRole("admin");
System.out.println(user.getRole());
userDao.updateUser(user);
System.out.println(userDao.findById(2).getRole());
}
} }

View File

@@ -1,51 +0,0 @@
package backend.dao.interfaces;
import backend.model.DataItem;
import java.util.*;
import java.sql.*;
/**
* 数据项DAO接口提供数据项的增删改查操作
*/
public interface DataItemDao {
/**
* 根据ID查找数据项
* @param id 数据项ID
* @return 找到的数据项对象如果未找到则返回null
*/
DataItem findById(int id);
/**
* 查找所有数据项
* @return 包含所有数据项的列表
*/
List<DataItem> findAll();
/**
* 根据关键字搜索数据项
* @param keyword 搜索关键字
* @return 匹配关键字的数据项列表
*/
List<DataItem> searchByKeyword(String keyword);
/**
* 添加数据项
* @param item 要添加的数据项对象
* @return 添加成功返回true失败返回false
*/
boolean addItem(DataItem item);
/**
* 更新数据项
* @param item 包含更新信息的数据项对象
* @return 更新成功返回true失败返回false
*/
boolean updateItem(DataItem item);
/**
* 删除数据项
* @param id 要删除的数据项ID
* @return 删除成功返回true失败返回false
*/
boolean deleteItem(int id);
}

View File

@@ -1,28 +0,0 @@
package backend.dao.interfaces;
import backend.model.QueryRecord;
import java.util.*;
/**
* 查询记录数据访问接口
* 定义了对查询记录进行持久化操作的方法
*/
public interface QueryRecordDao {
/**
* 添加查询记录
* 将指定的查询记录保存到数据存储中
*
* @param record 要添加的查询记录对象不能为null
* @return 添加成功返回true否则返回false
*/
boolean addRecord(QueryRecord record);
/**
* 根据用户ID查找查询记录
* 返回指定用户的所有查询记录列表
*
* @param userId 用户唯一标识符
* @return 查询记录列表,如果未找到则返回空列表
*/
List<QueryRecord> findByUserId(int userId);
}

View File

@@ -1,52 +0,0 @@
package backend.dao.interfaces;
import backend.model.User;
import java.util.*;
/**
* 用户数据访问接口
* 定义了用户相关的数据库操作方法
*/
public interface UserDaoIF {
/**
* 根据用户名查找用户
* @param username 用户名
* @return 查找到的用户对象如果未找到则返回null
*/
User findByUsername(String username);
/**
* 根据用户ID查找用户
* @param id 用户ID
* @return 查找到的用户对象如果未找到则返回null
*/
User findById(int id);
/**
* 添加新用户
* @param user 要添加的用户对象
* @return 添加成功返回true失败返回false
*/
boolean addUser(User user);
/**
* 更新用户信息
* @param user 包含更新信息的用户对象
* @return 更新成功返回true失败返回false
*/
boolean updateUser(User user);
/**
* 删除用户
* @param id 要删除的用户ID
* @return 删除成功返回true失败返回false
*/
boolean deleteUser(int id);
/**
* 查找所有用户
* @return 包含所有用户对象的列表
*/
List<User> findAll();
}

View File

@@ -0,0 +1,40 @@
package backend.model;
public class Charts {
private int userid;
private int count;
private int score;
public Charts() {
}
public Charts(int userid, int count, int score) {
this.userid = userid;
this.count = count;
this.score = score;
}
public int getUserid() {
return userid;
}
public void setUserid(int userid) {
this.userid = userid;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
}

View File

@@ -0,0 +1,49 @@
package backend.model;
public class Questions {
private int id;
private String name;
private String description;
private String answer;
private Integer frequency;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getAnswer() {
return answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
public Integer getFrequency() {
return frequency;
}
public void setFrequency(Integer frequency) {
this.frequency = frequency;
}
}

View File

@@ -0,0 +1,71 @@
package backend.model;
import java.sql.*;
public class TestRecord {
private int id;
private int userId;
private int questionId;
private int score;
private String answer;
private Date time;
public TestRecord() {
}
public TestRecord(int id, int userId, int questionId, int score, String answer, Date time) {
this.id = id;
this.userId = userId;
this.questionId = questionId;
this.score = score;
this.answer = answer;
this.time = time;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public int getQuestionId() {
return questionId;
}
public void setQuestionId(int questionId) {
this.questionId = questionId;
}
public int getScore() {
return score;
}
public void setScore(int score) {
this.score = score;
}
public String getAnswer() {
return answer;
}
public void setAnswer(String answer) {
this.answer = answer;
}
public Date getTime() {
return time;
}
public void setTime(Date time) {
this.time = time;
}
}

View File

@@ -1,4 +1,6 @@
package backend.model; package backend.model;
import backend.utils.DBHelper;
import java.sql.*; import java.sql.*;
/** /**
@@ -50,6 +52,24 @@ public class User {
this.id = id; this.id = id;
} }
public void setId() {
Connection conn = DBHelper.getInstance().getConnection();
//根据目前最大ID值
String sql = "select max(id) from USER";
try {
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery();
if(rs.next()) {
id = rs.getInt(1) + 1;
this.id = id;
}
} catch (SQLException e) {
e.printStackTrace();
}
}
/** /**
* 设置用户名 * 设置用户名
* *
@@ -65,7 +85,7 @@ public class User {
* @param role 用户角色,可选值为"admin"或"user" * @param role 用户角色,可选值为"admin"或"user"
*/ */
public void setRole(String role) { public void setRole(String role) {
this.role = role; this.role = role;
} }
/** /**
@@ -91,9 +111,13 @@ public class User {
* *
* @param createdAt 用户创建时间 * @param createdAt 用户创建时间
*/ */
public void setCreatedAt(Timestamp createdAt) { public void setCreatedAt(Date createdAt) {
this.createdAt = createdAt; this.createdAt = createdAt;
} }
public void setCreatedAt() {
this.createdAt = new Date(System.currentTimeMillis());
}
/** /**
* 获取用户ID * 获取用户ID
@@ -145,8 +169,9 @@ public class User {
* *
* @return 用户创建时间 * @return 用户创建时间
*/ */
public Timestamp getCreatedAt() { public Date getCreatedAt() {
return createdAt; return createdAt;
} }
} }

View File

@@ -0,0 +1,19 @@
package backend.model.enums;
import java.util.*;
public class GlobalData {
public static final Map<Integer,String> FREQUENCY_MAP = new HashMap<>();
static{
FREQUENCY_MAP.put(0,"未指定");
FREQUENCY_MAP.put(1,"低频");
FREQUENCY_MAP.put(2,"中频");
FREQUENCY_MAP.put(3,"高频");
}
public static Integer getFrequencyByValue(String value){
for(Map.Entry<Integer,String> entry:FREQUENCY_MAP.entrySet()) {
if (entry.getValue().equals(value))
return entry.getKey();
}
return 0;
}
}

View File

@@ -2,27 +2,35 @@ package backend.model.enums;
/** /**
* 登录状态枚举类 * 登录状态枚举类
* 定义了系统中所有可能的登录相关状态码和对应的消息描述 * 用final保证状态信息不可变用static提供工具方法
*/ */
public enum LoginStatus { public enum LoginStatus {
SUCCESS(490,"登录成功"), // 【任务3】枚举实例状态码和描述
USER_NOT_FOUND(491,"用户不存在"), // 成功登录
PASSWORD_ERROR(492,"密码错误"), SUCCESS(200,"登录成功"),
ALREADY_LOGGED_IN(493,"重复登录"), // 密码错误
CAPTCHA_ERROR(494,"验证码错误"), PASSWORD_ERROR(901,"码错误"),
ACCOUNT_LOCKED(495,"账户被封禁"), // 验证码错误
PERMISSION_DENIED(496,"权限不足"), CAPTCHA_ERROR(902,"验证码错误"),
LOGOUT_SUCCESS(497,"登出成功"), // 用户不存在
NOT_LOGGED_IN(498,"未登录"), USER_NOT_FOUND(903,"用户不存在"),
UNKNOWN_ERROR(499,"未知错误"), //注册失败
REGISTER_FAILD(500,"注册失败"); REGISTER_FAILED(904, "注册失败,用户名已存在"),
//注册成功
REGISTER_SUCCESS(905, "注册成功"),
//两次输入密码不一致
PASSWORD_NOT_MATCH(906, "两次输入的密码不一致");
// 【任务1】定义 final修饰的属性确保状态信息不可修改
private final int code; private final int code;
private final String msg; private final String msg;
/** /**
* 构造函数,初始化状态码和消息 * 【任务2】
* 构造函数用于创建LoginStatus实例
* @param code 状态码 * @param code 状态码
* @param msg 状态消息 * @param msg 状态消息
*/ */
@@ -31,13 +39,14 @@ public enum LoginStatus {
this.msg = msg; this.msg = msg;
} }
// 静态方法根据状态码获取枚举实例static工具方法
/** /**
* 根据状态码获取对应的登录状态枚举值 * 【任务4】
* 静态方法: getByCode 根据状态码获取对应的登录状态枚举值
* @param code 状态码 * @param code 状态码
* @return 对应的LoginStatus枚举值如果未找到则返回null * @return LoginStatus 对应的LoginStatus枚举值如果找不到匹配的状态码则返回null
*/ */
public static LoginStatus getByCode(int code){ public static LoginStatus getByCode(int code){
// 遍历所有枚举值查找匹配的状态码
for(LoginStatus status:values()){ for(LoginStatus status:values()){
if(status.code==code){ if(status.code==code){
return status; return status;
@@ -46,21 +55,25 @@ public enum LoginStatus {
return null; return null;
} }
// getter方法final属性无需setter
/** /**
* 获取状态码 * 【任务5】
* @return 状态码 * 方法: getCode 获取code值
*
* @return int code值
*/ */
public int getCode() { public int getCode() {
return code; return code;
} }
/** /**
* 获取状态消息 * 任务【6】
* @return 状态消息 * 方法: getMsg 获取消息内容
*
* @return String 返回当前对象的消息字符串
*/ */
public String getMsg() { public String getMsg() {
return msg; return msg;
} }
} }

View File

@@ -0,0 +1,20 @@
package backend.model.enums;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class ScoreKey {
public static final Map<Integer,Integer> SCORE_MAP = new HashMap<>();
static{
SCORE_MAP.put(0,5);
SCORE_MAP.put(1,10);
SCORE_MAP.put(2,20);
SCORE_MAP.put(3,50);
}
public static Integer getScoreByKey(Integer key) {
return SCORE_MAP.getOrDefault(key, 0);
}
}

View File

@@ -0,0 +1,85 @@
package backend.service;
import backend.dao.UserDao;
import backend.model.enums.LoginStatus;
import backend.model.User;
import java.util.List;
import java.util.Vector;
public class AuthService {
private UserDao userDao = new UserDao();
public boolean addUser(User user) {
return userDao.addUser(user);
}
public boolean deleteUser(int id) {
return userDao.deleteUser(id);
}
public LoginStatus login(User user) {
User dbUser = userDao.findByUsername(user.getUsername());
if(dbUser==null)
return LoginStatus.USER_NOT_FOUND;
if(dbUser.getUsername().equals(user.getUsername())&&dbUser.getPassword().equals(user.getPassword()))
return LoginStatus.SUCCESS;
else if (!dbUser.getUsername().equals(user.getUsername())) {
return LoginStatus.USER_NOT_FOUND;
}
return LoginStatus.PASSWORD_ERROR;
}
public LoginStatus register(User user) {
User dbAccount = userDao.findByUsername(user.getUsername());
if(dbAccount!=null)
return LoginStatus.REGISTER_FAILED;
//点击注册按钮后的事件
if(userDao.addUser(user))
return LoginStatus.REGISTER_SUCCESS;
else
return LoginStatus.REGISTER_FAILED;
}
public boolean updateUser(User user) {
return userDao.updateUser(user);
}
private Vector<Vector<String>> commonHandler(List<User> usersList){
//加工数据 把数据库查到的List转成Vector<Vector<>>
Vector<Vector<String>> usersData = new Vector<>();
if(usersList != null) {
for (User usersPo : usersList) {
Vector<String> row = new Vector<>();
row.add(String.valueOf(usersPo.getId()));
row.add(usersPo.getUsername());
row.add(usersPo.getRole());
row.add(usersPo.getEmail());
row.add(String.valueOf(usersPo.getCreatedAt()));
usersData.add(row);
}
}
return usersData;
}
public Vector<Vector<String>> getAll(){
//从数据库中获取所有用户
List<User> usersList = userDao.findAll();
//把List转成表格所需的格式
return commonHandler(usersList);
//返回给前端
}
public Vector<Vector<String>> getByCondition(String role, String key){
//从数据库中获取所有用户
List<User> usersList = userDao.findByCondition(role,key);
//把List转成表格所需的格式
return commonHandler(usersList);
//返回给前端
}
public static void main(String[] args) {
UserDao userDao = new UserDao();
AuthService authService = new AuthService();
Vector<Vector<String>> users= authService.commonHandler(userDao.findAll());
System.out.println(users);
}
}

View File

@@ -0,0 +1,52 @@
package backend.service;
import backend.dao.ChartsDao;
import backend.dao.QuestionsDao;
import backend.dao.UserDao;
import backend.model.Charts;
import java.util.*;
public class ChartsService {
private ChartsDao chartsDao = new ChartsDao();
private UserDao userDao = new UserDao();
public Vector<Vector<String>> commonHandler(List<Charts> chartsList){
Vector<Vector<String>> chartsData = new Vector<>();
if(chartsList != null) {
int i = 1;
for (Charts chartsPo : chartsList) {
Vector<String> row = new Vector<>();
row.add(String.valueOf(i++));
row.add(String.valueOf(userDao.findById(chartsPo.getUserid()).getUsername()));
row.add(String.valueOf(chartsPo.getCount()));
row.add(String.valueOf(chartsPo.getScore()));
chartsData.add(row);
}
}
return chartsData;
}
public Vector<Vector<String>> getAll(){
List<Charts> chartsList = chartsDao.findAll();
return commonHandler(chartsList);
}
public Vector<Vector<String>> sortByScoreUp(){
List<Charts> chartsList = chartsDao.sortByScoreUp();
return commonHandler(chartsList);
}
public Vector<Vector<String>> sortByScoreDown(){
List<Charts> chartsList = chartsDao.sortByScoreDown();
return commonHandler(chartsList);
}
public boolean updateCharts(Charts charts){
return chartsDao.updateCharts(charts);
}
public boolean deleteCharts(int userid){
return chartsDao.deleteCharts(userid);
}
public boolean insertCharts(Charts charts){
return chartsDao.insertCharts(charts);
}
}

View File

@@ -0,0 +1,69 @@
package backend.service;
import backend.dao.QuestionsDao;
import backend.model.Questions;
import backend.model.enums.GlobalData;
import java.util.HashSet;
import java.util.List;
import java.util.Vector;
public class QuestionsService {
private QuestionsDao questionsDao = new QuestionsDao();
private static HashSet<Questions> questionsSet = new HashSet<>();
private Vector<Vector<String>> commonHandler(List<Questions> questionsList){
//加工数据 把数据库查到的List转成Vector<Vector<>>
Vector<Vector<String>> questionsData = new Vector<>();
if(questionsList != null) {
for (Questions questionsPo : questionsList) {
Vector<String> row = new Vector<>();
row.add(String.valueOf(questionsPo.getId()));
row.add(questionsPo.getName());
row.add(questionsPo.getDescription());
row.add(questionsPo.getAnswer());
row.add(GlobalData.FREQUENCY_MAP.get(questionsPo.getFrequency()));
questionsData.add(row);
}
}
return questionsData;
}
public Vector<Vector<String>> getAll(){
//从数据库中获取所有题目
List<Questions> questionsList = questionsDao.getAll();
//把List转成表格所需的格式
return commonHandler(questionsList);
//返回给前端
}
public Vector<Vector<String>> getByCondition(Integer frequency,String key){
//从数据库中获取所有题目
List<Questions> wordPoList = questionsDao.getByCondition(frequency,key);
//把List转成表格所需的格式
return commonHandler(wordPoList);
}
public boolean insert(Questions question){
return questionsDao.insert(question);
}
public void delete(Integer id){
questionsDao.delete(id);
}
public boolean update(Questions question){
return questionsDao.update(question);
}
public Questions getRandomQuestion() {
//使用红黑树实现的集合防止重复刷同一个题
if(questionsSet.isEmpty()) {
Questions question = questionsDao.getRandomQuestion();
questionsSet.add(question);
return question;
}
while(true) {
Questions question = questionsDao.getRandomQuestion();
if(!questionsSet.contains(question)) {
questionsSet.add(question);
return question;
}
}
}
}

View File

@@ -0,0 +1,78 @@
package backend.service;
import backend.dao.QuestionsDao;
import backend.dao.TestRecordDao;
import backend.dao.UserDao;
import backend.model.Charts;
import backend.model.TestRecord;
import java.util.*;
public class TestRecordService {
private TestRecordDao testRecordDao = new TestRecordDao();
private UserDao userDao = new UserDao();
private QuestionsDao questionsDao = new QuestionsDao();
private Vector<Vector<String>> commonHandler(List<TestRecord> testRecordList){
//加工数据 把数据库查到的List转成Vector<Vector<>>
Vector<Vector<String>> testRecordData = new Vector<>();
if(testRecordList != null) {
for (TestRecord testRecordPo : testRecordList) {
Vector<String> row = new Vector<>();
row.add(String.valueOf(testRecordPo.getId()));
row.add(String.valueOf(userDao.findById(testRecordPo.getUserId()).getUsername()));
row.add(String.valueOf(questionsDao.getById(testRecordPo.getQuestionId()).getName()));
row.add(String.valueOf(testRecordPo.getScore()));
row.add(testRecordPo.getAnswer());
row.add(String.valueOf(testRecordPo.getTime()));
testRecordData.add(row);
}
}
return testRecordData;
}
//获取所有记录 用于管理员
public Vector<Vector<String>> getAll(){
//从数据库中获取所有记录
List<TestRecord> testRecordList = testRecordDao.getAll();
//把List转成表格所需的格式
return commonHandler(testRecordList);
//返回给前端
}
//获取指定用户的所有记录 用于用户和管理员
public Vector<Vector<String>> getByUserId(Integer userId){
//从数据库中获取所有记录
List<TestRecord> testRecordList = testRecordDao.getByUserId(userId);
//把List转成表格所需的格式
return commonHandler(testRecordList);
//返回给前端
}
//获取指定题目的所有记录 用于管理员和 用户
public Vector<Vector<String>> getByQuestionId(Integer questionId){
//从数据库中获取所有记录
List<TestRecord> testRecordList = testRecordDao.getByQuestionId(questionId);
//把List转成表格所需的格式
return commonHandler(testRecordList);
//返回给前端
}
//获取指定用户指定题目的所有记录 用于用户和管理员
public Vector<Vector<String>> getByUserIdAndQuestionId(Integer userId, Integer questionId){
//从数据库中获取所有记录
List<TestRecord> testRecordList = testRecordDao.getByUserIdAndQuestionId(userId, questionId);
//把List转成表格所需的格式
return commonHandler(testRecordList);
//返回给前端
}
public boolean insert(TestRecord testRecord){
//插入新的记录的同时,更新排行榜
ChartsService chartsService = new ChartsService();
Charts charts = new Charts();
charts.setUserid(testRecord.getUserId());
charts.setScore(testRecord.getScore());
chartsService.updateCharts(charts);
return testRecordDao.insert(testRecord);
}
public boolean delete(Integer id){
return testRecordDao.delete(id);
}
}

View File

@@ -1,48 +0,0 @@
package backend.service.interfaces;
/**
* 认证服务接口
* 提供用户认证和权限管理相关功能
*/
public interface AuthService {
/**
* 用户登录验证
* 验证用户名和密码是否匹配,如果匹配则允许用户登录系统
*
* @param username 用户名
* @param password 密码
* @return 登录成功返回true失败返回false
*/
boolean login(String username, String password);
/**
* 用户注册
* 创建新的用户账户,将用户信息存储到系统中
*
* @param username 用户名
* @param password 密码
* @param email 邮箱地址
* @return 注册成功返回true失败返回false
*/
boolean register(String username, String password, String email);
/**
* 用户登出
* 使指定用户的会话失效,结束用户的登录状态
*
* @param userId 用户唯一标识符
* @return 登出成功返回true失败返回false
*/
boolean logout(int userId);
/**
* 权限检查
* 检查指定用户是否具有所需的权限角色
*
* @param userId 用户唯一标识符
* @param requiredRole 所需的角色权限
* @return 具有权限返回true无权限返回false
*/
boolean hasPermission(int userId, String requiredRole);
}

View File

@@ -1,49 +0,0 @@
package backend.service.interfaces;
import backend.model.DataItem;
import backend.model.QueryRecord;
import backend.model.User;
import java.util.*;
/**
* 数据查询服务接口
* 提供数据项的增删改查功能
*/
public interface DataQueryService {
/**
* 查询所有数据项
* @return 包含所有数据项的列表
*/
List<DataItem> queryAll();
/**
* 根据关键字搜索数据项
* @param keyword 搜索关键字
* @return 匹配关键字的数据项列表
*/
List<DataItem> search(String keyword);
/**
* 添加数据项
* @param item 要添加的数据项对象
* @param userId 执行操作的用户ID
* @return 添加成功返回true失败返回false
*/
boolean addDataItem(DataItem item, int userId);
/**
* 更新数据项
* @param item 要更新的数据项对象
* @param userId 执行操作的用户ID
* @return 更新成功返回true失败返回false
*/
boolean updateDataItem(DataItem item, int userId);
/**
* 删除数据项
* @param id 要删除的数据项ID
* @param userId 执行操作的用户ID
* @return 删除成功返回true失败返回false
*/
boolean deleteDataItem(int id, int userId);
}

View File

@@ -1,33 +0,0 @@
package backend.service.interfaces;
import backend.model.User;
import java.util.*;
/**
* 用户服务接口
* 定义了用户相关的业务操作方法
*/
public interface UserService {
/**
* 根据用户ID获取用户信息
* @param id 用户ID
* @return 用户对象如果未找到则返回null
*/
User getUserInfo(int id);
/**
* 列出所有用户信息
* @param requesterId 请求者用户ID用于权限验证
* @return 用户列表
*/
List<User> listAllUsers(int requesterId);
/**
* 更新用户角色权限
* @param targetId 目标用户ID
* @param newRole 新的角色权限
* @param adminId 管理员用户ID
* @return 操作是否成功
*/
boolean updateUserRole(int targetId, String newRole, int adminId);//用户权限
}

View File

@@ -1,12 +1,8 @@
package backend.utils.interfaces; package backend.utils;
import java.util.Random; import java.util.Random;
/** public class CaptchaUtils{
* 验证码工具类接口
* 提供验证码的生成和验证功能
*/
public interface CaptchaUtils {
/** /**
* 字符集常量包含大小写字母和数字 * 字符集常量包含大小写字母和数字
*/ */
@@ -20,14 +16,25 @@ public interface CaptchaUtils {
/** /**
* 私有构造函数防止实例化 * 私有构造函数防止实例化
*/ */
//private CaptchaUtils(); private CaptchaUtils(){};
/** /**
* 生成随机验证码 * 生成随机验证码
* *
* @return 生成的验证码字符串 * @return 生成的验证码字符串
*/ */
//static String generateCaptcha(); public static String generateCaptcha(){
Random random = new Random();
//生成随机验证码
StringBuilder sb = new StringBuilder();
for(int i=0;i<CAPTCHA_LENGTH;i++){
//生成随机数索引
int index = random.nextInt(CHAR_SET.length());
//根据索引获取随机字符
sb.append(CHAR_SET.charAt(index));
}
return sb.toString();
}
/** /**
* 验证用户输入的验证码是否正确 * 验证用户输入的验证码是否正确
@@ -36,6 +43,7 @@ public interface CaptchaUtils {
* @param systemCaptcha 系统生成的验证码 * @param systemCaptcha 系统生成的验证码
* @return 验证结果正确返回true错误返回false * @return 验证结果正确返回true错误返回false
*/ */
//static boolean verifyCaptcha(String inputCaptcha,String systemCaptcha); public static boolean verifyCaptcha(String inputCaptcha,String systemCaptcha){
return inputCaptcha.equals(systemCaptcha);
}
} }

View File

@@ -0,0 +1,89 @@
package backend.utils;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class PasswordUtils {
private static final String PREFIX = "encrypted_";
private static final SecureRandom random = new SecureRandom();
/**
* 对明文密码进行加密处理
*
* @param plainText 需要加密的明文密码字符串
* @return 加密后的密码字符串
*/
public static String encrypt(String plainText){
if (plainText == null) {
throw new IllegalArgumentException("密码不能为空");
}
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
byte[] salt = new byte[16];
random.nextBytes(salt);
md.update(salt);
byte[] hashedPassword = md.digest(plainText.getBytes());
StringBuilder sb = new StringBuilder();
sb.append(PREFIX);
for (byte b : salt) {
sb.append(String.format("%02x", b));
}
for (byte b : hashedPassword) {
sb.append(String.format("%02x", b));
}
return sb.toString();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("SHA-256 algorithm not available", e);
}
}
/**
* 验证明文密码与已加密密码是否匹配
*
* @param plainText 明文密码字符串
* @param hashed 已加密的密码字符串
* @return 如果匹配返回true否则返回false
*/
public static boolean verify(String plainText, String hashed){
if (plainText == null || hashed == null) {
return false;
}
if (!hashed.startsWith(PREFIX)) {
return false;
}
try {
MessageDigest md = MessageDigest.getInstance("SHA-256");
String hashWithoutPrefix = hashed.substring(PREFIX.length());
if (hashWithoutPrefix.length() < 32) {
return false;
}
String saltHex = hashWithoutPrefix.substring(0, 32);
String storedHashHex = hashWithoutPrefix.substring(32);
byte[] salt = new byte[16];
for (int i = 0; i < 16; i++) {
salt[i] = (byte) Integer.parseInt(saltHex.substring(i * 2, i * 2 + 2), 16);
}
md.update(salt);
byte[] hashedPassword = md.digest(plainText.getBytes());
StringBuilder sb = new StringBuilder();
for (byte b : hashedPassword) {
sb.append(String.format("%02x", b));
}
return sb.toString().equals(storedHashHex);
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException("SHA-256 algorithm not available", e);
} catch (NumberFormatException e) {
return false;
}
}
}

View File

@@ -1,24 +0,0 @@
package backend.utils.interfaces;
/**
* 密码工具接口,提供密码加密和验证功能
*/
public interface PasswordUtil {
/**
* 对明文密码进行加密处理
*
* @param plainText 需要加密的明文密码字符串
* @return 加密后的密码字符串
*/
//static String encrypt(String plainText);
/**
* 验证明文密码与已加密密码是否匹配
*
* @param plainText 明文密码字符串
* @param hashed 已加密的密码字符串
* @return 如果匹配返回true否则返回false
*/
//static boolean verify(String plainText, String hashed);
}

View File

@@ -1,21 +0,0 @@
package backend.utils.interfaces;
/**
* 角色工具类接口,提供角色判断功能
*/
public interface RoleUtil {
/**
* 判断给定的角色是否为管理员角色
* @param role 待判断的角色字符串
* @return 如果是管理员角色返回true否则返回false
*/
//static boolean isAdmin(String role);
/**
* 判断给定的角色是否为普通用户角色
* @param role 待判断的角色字符串
* @return 如果是普通用户角色返回true否则返回false
*/
//static boolean isUser(String role);
}

View File

@@ -0,0 +1,200 @@
package view;
import backend.model.Questions;
import backend.service.QuestionsService;
import javax.swing.*;
import java.awt.*;
public class EditQuestionDialog extends JDialog{
private JTextField nameTextField;
private JTextField descriptionTextField;
private JTextField answerTextField;
private JComboBox frequencyCombobox;
private JButton saveButton;
private JButton cancelButton;
private int type;
private Questions question;
private QuestionsService questionsService = new QuestionsService();
// 颜色常量定义
private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色
private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景
private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色
private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景
public EditQuestionDialog(int type, Questions question) {
this.type = type;
this.question = question;
initView();
}
public void initListener(){
saveButton.addActionListener(e->{
String name = nameTextField.getText().trim();
String description = descriptionTextField.getText().trim();
String answer = answerTextField.getText().trim();
if(name.equals("")|| description.equals("")|| answer.equals("")) {
JOptionPane.showMessageDialog(this, "请填写完整!");
return;
}
Questions questionsPo = new Questions();
questionsPo.setName(name);
questionsPo.setDescription(description);
questionsPo.setAnswer(answer);
Integer index=frequencyCombobox.getSelectedIndex();
questionsPo.setFrequency(index==0 ? null:index);
String message;
boolean res;
if(type==0) {
res = questionsService.insert(questionsPo);
message = "添加";
}
else{
questionsPo.setId(question.getId());
res = questionsService.update(questionsPo);
message = "修改";
}
if(res)
dispose();
else
JOptionPane.showMessageDialog(this, message+"失败");
});
cancelButton.addActionListener(e->{
dispose();
});
}
private void initView(){
setSize(400, 350);
setLocationRelativeTo(null);//居中
setLayout(new BorderLayout());
// 创建顶部标题面板
JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
titlePanel.setBackground(PRIMARY_COLOR);
JLabel titleLabel = new JLabel(type == 0 ? "添加题目" : "编辑题目");
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
titleLabel.setForeground(Color.WHITE);
titlePanel.add(titleLabel);
add(titlePanel, BorderLayout.NORTH);
// 添加主内容面板
add(initPanel(), BorderLayout.CENTER);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setModal(true);//设置模态
if(type==0)
setTitle("添加题目");
else{
setTitle("编辑题目");
nameTextField.setText(question.getName());
descriptionTextField.setText(question.getDescription());
answerTextField.setText(question.getAnswer());
frequencyCombobox.setSelectedIndex(question.getFrequency() == null? 0:question.getFrequency());
}
//细节:要先初始化监听器,再初始化界面
//初始化监听器
initListener();
//显示界面
setVisible(true);
}
private JPanel initPanel(){
JPanel mainPanel = new JPanel(new GridBagLayout());
mainPanel.setBackground(BACKGROUND_COLOR);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
// 第一行 - 问题
gbc.gridx = 0; gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
mainPanel.add(new JLabel("问题:"), gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
nameTextField = new JTextField();
nameTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12));
nameTextField.setPreferredSize(new Dimension(200, 25));
mainPanel.add(nameTextField, gbc);
// 第二行 - 描述
gbc.gridx = 0; gbc.gridy = 1;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
mainPanel.add(new JLabel("描述:"), gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
descriptionTextField = new JTextField();
descriptionTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12));
descriptionTextField.setPreferredSize(new Dimension(200, 25));
mainPanel.add(descriptionTextField, gbc);
// 第三行 - 答案
gbc.gridx = 0; gbc.gridy = 2;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
mainPanel.add(new JLabel("答案:"), gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
answerTextField = new JTextField();
answerTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12));
answerTextField.setPreferredSize(new Dimension(200, 25));
mainPanel.add(answerTextField, gbc);
// 第四行 - 频率
gbc.gridx = 0; gbc.gridy = 3;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
mainPanel.add(new JLabel("频率:"), gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
frequencyCombobox = new JComboBox<>(new String[]{"未指定","低频","中频","高频"});
frequencyCombobox.setFont(new Font("微软雅黑", Font.PLAIN, 12));
frequencyCombobox.setPreferredSize(new Dimension(200, 25));
mainPanel.add(frequencyCombobox, gbc);
// 第五行 - 按钮
gbc.gridx = 0; gbc.gridy = 4;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
gbc.anchor = GridBagConstraints.CENTER;
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 0));
buttonPanel.setBackground(BACKGROUND_COLOR);
saveButton = new JButton("保存");
cancelButton = new JButton("取消");
// 设置按钮样式
setButtonStyle(saveButton);
setButtonStyle(cancelButton);
buttonPanel.add(saveButton);
buttonPanel.add(cancelButton);
mainPanel.add(buttonPanel, gbc);
// 添加边距
mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
return mainPanel;
}
// 设置按钮样式
private void setButtonStyle(JButton button) {
button.setFont(new Font("微软雅黑", Font.BOLD, 14));
button.setPreferredSize(new Dimension(80, 30));
button.setBackground(PRIMARY_COLOR);
button.setForeground(Color.WHITE);
button.setFocusPainted(false);
button.setBorder(BorderFactory.createRaisedBevelBorder());
}
}

View File

@@ -0,0 +1,192 @@
package view;
import javax.swing.*;
import backend.model.User;
import backend.service.AuthService;
import java.awt.*;
public class EditUserDialog extends JDialog {
private JTextField nameTextField;
private JTextField emailTextField;
private JComboBox roleCombobox;
private JButton saveButton;
private JButton cancelButton;
private int type;
private User user;
private AuthService userService = new AuthService();
// 颜色常量定义
private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色
private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景
private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色
private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景
public EditUserDialog(int type, User user) {
this.type = type;
this.user = user;
initView();
}
public void initListener(){
saveButton.addActionListener(e->{
String name = nameTextField.getText().trim();
String email = emailTextField.getText().trim();
if(name.equals("")|| email.equals("")) {
JOptionPane.showMessageDialog(this, "请填写完整!");
return;
}
User userPo = new User();
userPo.setUsername(name);
userPo.setEmail(email);
Integer index= roleCombobox.getSelectedIndex();
userPo.setRole(index==0 ? "user":"admin");
String message;
boolean res;
if(type==0) {
userPo.setPassword("123456");
userPo.setCreatedAt();
res = userService.addUser(userPo);
message = "添加";
}
else{
userPo.setCreatedAt(user.getCreatedAt());
userPo.setPassword(user.getPassword());
userPo.setId(user.getId());
res = userService.updateUser(userPo);
message = "修改";
}
if(res)
dispose();
else
JOptionPane.showMessageDialog(this, message+"失败");
});
cancelButton.addActionListener(e->{
dispose();
});
}
private void initView(){
setSize(400, 300);
setLocationRelativeTo(null);//居中
setLayout(new BorderLayout());
// 创建顶部标题面板
JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
titlePanel.setBackground(PRIMARY_COLOR);
JLabel titleLabel = new JLabel(type == 0 ? "添加用户" : "编辑用户");
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
titleLabel.setForeground(Color.WHITE);
titlePanel.add(titleLabel);
add(titlePanel, BorderLayout.NORTH);
// 添加主内容面板
add(initPanel(), BorderLayout.CENTER);
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
setModal(true);//设置模态
if(type==0)
setTitle("添加用户");
else{
setTitle("编辑用户");
nameTextField.setText(user.getUsername());
emailTextField.setText(user.getEmail());
roleCombobox.setSelectedIndex(user.getRole().equals("admin")? 1:0);
}
//细节:要先初始化监听器,再初始化界面
//初始化监听器
initListener();
//显示界面
setVisible(true);
}
private JPanel initPanel(){
JPanel mainPanel = new JPanel(new GridBagLayout());
mainPanel.setBackground(BACKGROUND_COLOR);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
// 第一行 - 用户名
gbc.gridx = 0; gbc.gridy = 0;
gbc.anchor = GridBagConstraints.WEST;
mainPanel.add(new JLabel("用户名:"), gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
nameTextField = new JTextField();
nameTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12));
nameTextField.setPreferredSize(new Dimension(200, 25));
mainPanel.add(nameTextField, gbc);
// 第二行 - 邮箱
gbc.gridx = 0; gbc.gridy = 1;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
mainPanel.add(new JLabel("邮箱:"), gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
emailTextField = new JTextField();
emailTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12));
emailTextField.setPreferredSize(new Dimension(200, 25));
mainPanel.add(emailTextField, gbc);
// 第三行 - 权限
gbc.gridx = 0; gbc.gridy = 2;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
mainPanel.add(new JLabel("权限:"), gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
roleCombobox = new JComboBox<>(new String[]{"user","admin"});
roleCombobox.setFont(new Font("微软雅黑", Font.PLAIN, 12));
roleCombobox.setPreferredSize(new Dimension(200, 25));
mainPanel.add(roleCombobox, gbc);
// 第四行 - 按钮
gbc.gridx = 0; gbc.gridy = 3;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
gbc.anchor = GridBagConstraints.CENTER;
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 0));
buttonPanel.setBackground(BACKGROUND_COLOR);
saveButton = new JButton("保存");
cancelButton = new JButton("取消");
// 设置按钮样式
setButtonStyle(saveButton);
setButtonStyle(cancelButton);
buttonPanel.add(saveButton);
buttonPanel.add(cancelButton);
mainPanel.add(buttonPanel, gbc);
// 添加边距
mainPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
return mainPanel;
}
// 设置按钮样式
private void setButtonStyle(JButton button) {
button.setFont(new Font("微软雅黑", Font.BOLD, 14));
button.setPreferredSize(new Dimension(80, 30));
button.setBackground(PRIMARY_COLOR);
button.setForeground(Color.WHITE);
button.setFocusPainted(false);
button.setBorder(BorderFactory.createRaisedBevelBorder());
}
// public static void main(String[] args) {
// new EditUserDialog(0,null);
// }
}

639
src/view/ExamPanel.java Normal file
View File

@@ -0,0 +1,639 @@
package view;
import backend.dao.QuestionsDao;
import backend.dao.UserDao;
import backend.model.Charts;
import backend.model.Questions;
import backend.model.TestRecord;
import backend.model.enums.ScoreKey;
import backend.service.ChartsService;
import backend.service.QuestionsService;
import backend.service.TestRecordService;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.sql.Date;
import java.util.Vector;
public class ExamPanel extends JPanel {
private QuestionsService questionsService = new QuestionsService();
private Questions currentQuestion;
private JButton startButton;
private JButton submitButton;
private JButton nextButton;
private JButton exitButton;
private JLabel questionLabel;
private JLabel descriptionLabel;
private JLabel progressLabel;
private JTextField answerTextField;
private JMenuBar menuBar;
private String role = MainFrame.role;
private int userId = MainFrame.userId;
// 颜色常量定义
private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色
private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景
private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色
private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景
public ExamPanel() {
initializeComponents();
initView();
initListener();
}
// 初始化所有UI组件
private void initializeComponents() {
// 题目标题标签
questionLabel = new JLabel("点击开始测试获取题目");
questionLabel.setFont(new Font("微软雅黑", Font.BOLD, 18));
questionLabel.setForeground(new Color(50, 50, 50));
questionLabel.setHorizontalAlignment(JLabel.CENTER);
questionLabel.setVerticalAlignment(JLabel.TOP);
// 题目描述标签
descriptionLabel = new JLabel("描述将在这里显示");
descriptionLabel.setFont(new Font("微软雅黑", Font.PLAIN, 14));
descriptionLabel.setForeground(new Color(100, 100, 100));
descriptionLabel.setHorizontalAlignment(JLabel.CENTER);
descriptionLabel.setVerticalAlignment(JLabel.TOP);
// 进度标签
progressLabel = new JLabel("题目进度: 0/0");
progressLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
progressLabel.setForeground(new Color(120, 120, 120));
progressLabel.setHorizontalAlignment(JLabel.RIGHT);
// 答案输入框
answerTextField = new JTextField(20);
answerTextField.setFont(new Font("微软雅黑", Font.PLAIN, 14));
answerTextField.setHorizontalAlignment(JLabel.CENTER);
answerTextField.setPreferredSize(new Dimension(250, 35));
// 初始化按钮
startButton = new JButton("开始测试");
submitButton = new JButton("提交");
nextButton = new JButton("下一题");
exitButton = new JButton("退出");
// 设置按钮样式
setButtonStyle(startButton);
setButtonStyle(submitButton);
setButtonStyle(nextButton);
setButtonStyle(exitButton);
// 隐藏非初始按钮
submitButton.setVisible(false);
nextButton.setVisible(false);
exitButton.setVisible(false);
}
// 设置按钮样式
private void setButtonStyle(JButton button) {
button.setFont(new Font("微软雅黑", Font.BOLD, 14));
button.setPreferredSize(new Dimension(100, 35));
button.setBackground(PRIMARY_COLOR);
button.setForeground(Color.WHITE);
button.setFocusPainted(false);
button.setBorder(BorderFactory.createRaisedBevelBorder());
}
private void initView() {
setLayout(new BorderLayout());
setBackground(BACKGROUND_COLOR);
// 创建顶部工具栏
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.setBackground(PRIMARY_COLOR);
topPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
JLabel titleLabel = new JLabel("测试管理");
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
titleLabel.setForeground(Color.WHITE);
topPanel.add(titleLabel, BorderLayout.WEST);
topPanel.add(progressLabel, BorderLayout.EAST);
topPanel.add(initMenuBar(), BorderLayout.CENTER);
add(topPanel, BorderLayout.NORTH);
// 创建中央内容面板
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS));
centerPanel.setBackground(BACKGROUND_COLOR);
centerPanel.setBorder(BorderFactory.createEmptyBorder(30, 30, 30, 30));
// 添加初始显示内容
centerPanel.add(Box.createVerticalGlue());
// 题目展示区域
JPanel questionPanel = new JPanel(new BorderLayout());
questionPanel.setBackground(Color.WHITE);
questionPanel.setBorder(BorderFactory.createCompoundBorder(
BorderFactory.createLineBorder(BORDER_COLOR, 1),
BorderFactory.createEmptyBorder(20, 20, 20, 20)
));
questionPanel.setMaximumSize(new Dimension(600, 300));
questionPanel.setAlignmentX(Component.CENTER_ALIGNMENT);
questionPanel.add(questionLabel, BorderLayout.CENTER);
questionPanel.add(descriptionLabel, BorderLayout.SOUTH);
centerPanel.add(questionPanel);
centerPanel.add(Box.createVerticalStrut(20));
// 答案输入区域
JPanel inputPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5));
inputPanel.setBackground(BACKGROUND_COLOR);
inputPanel.add(new JLabel("请输入答案: "));
inputPanel.add(answerTextField);
centerPanel.add(inputPanel);
centerPanel.add(Box.createVerticalStrut(15));
// 按钮区域
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 15, 5));
buttonPanel.setBackground(BACKGROUND_COLOR);
buttonPanel.add(startButton);
buttonPanel.add(submitButton);
buttonPanel.add(nextButton);
buttonPanel.add(exitButton);
centerPanel.add(buttonPanel);
centerPanel.add(Box.createVerticalGlue());
add(centerPanel, BorderLayout.CENTER);
// 更新按钮可见性
updateButtonVisibility();
}
private void updateButtonVisibility() {
startButton.setVisible(true);
submitButton.setVisible(false);
nextButton.setVisible(false);
exitButton.setVisible(false);
}
private void showQuestion() {
// 更新按钮可见性
startButton.setVisible(false);
submitButton.setVisible(true);
nextButton.setVisible(false);
exitButton.setVisible(false);
// 更新进度显示
progressLabel.setText("题目进度: 1/1");
// 重新验证和重绘界面
revalidate();
repaint();
}
private void showNextQuestionOption() {
// 更新按钮可见性
startButton.setVisible(false);
submitButton.setVisible(false);
nextButton.setVisible(true);
exitButton.setVisible(true);
// 重新验证和重绘界面
revalidate();
repaint();
}
private void initListener() {
startButton.addActionListener(e -> {
// 获取随机题目并显示
currentQuestion = questionsService.getRandomQuestion();
if (currentQuestion != null) {
//在排行榜中创建角色(若没有)
ChartsService chartsService = new ChartsService();
Charts charts = new Charts();
charts.setUserid(userId);
chartsService.insertCharts(charts);
updateQuestionDisplay();
showQuestion();
} else {
JOptionPane.showMessageDialog(this,
"没有可用的题目", "错误", JOptionPane.ERROR_MESSAGE);
}
});
submitButton.addActionListener(e -> handleAnswerSubmission());
// 为 nextButton 和 exitButton 添加监听器
if (nextButton != null) {
nextButton.addActionListener(e -> {
currentQuestion = questionsService.getRandomQuestion();
if (currentQuestion != null) {
updateQuestionDisplay();
showQuestion();
} else {
JOptionPane.showMessageDialog(this,
"没有更多题目", "提示", JOptionPane.INFORMATION_MESSAGE);
}
});
}
if (exitButton != null) {
exitButton.addActionListener(e -> {
int choice = JOptionPane.showConfirmDialog(
this,
"确定要退出测试吗?",
"确认退出",
JOptionPane.YES_NO_OPTION
);
if (choice == JOptionPane.YES_OPTION) {
resetToInitialState();
}
});
}
// 为菜单项添加监听器
JMenu testMenu = (JMenu) menuBar.getMenu(0);
JMenuItem testContentItem = testMenu.getItem(0);
testContentItem.addActionListener(e -> {
resetToInitialState();
});
JMenu recordMenu = (JMenu) menuBar.getMenu(1);
JMenuItem recordItem = recordMenu.getItem(0);
recordItem.addActionListener(e -> {
initRecordView();
});
JMenu chartMenu = (JMenu) menuBar.getMenu(2);
JMenuItem chartItem = chartMenu.getItem(0);
chartItem.addActionListener(e -> {
// 这里可以添加排行榜页面的切换逻辑
initRankView();
});
}
private void updateQuestionDisplay() {
if (currentQuestion != null) {
questionLabel.setText(currentQuestion.getName());
descriptionLabel.setText(currentQuestion.getDescription());
answerTextField.setText("");
}
}
private void handleAnswerSubmission() {
int user=userId, questionId= currentQuestion.getId(), score=0;
if (currentQuestion == null) {
JOptionPane.showMessageDialog(this,
"请先开始测试", "提示", JOptionPane.WARNING_MESSAGE);
return;
}
String userAnswer = answerTextField.getText().trim();
if (userAnswer.isEmpty()) {
JOptionPane.showMessageDialog(this,
"请输入答案", "提示", JOptionPane.WARNING_MESSAGE);
return;
}
if (userAnswer.equalsIgnoreCase(currentQuestion.getAnswer())) {
// 答案正确时高亮输入框
answerTextField.setBackground(HIGHLIGHT_COLOR);
JOptionPane.showMessageDialog(this,
"答案正确!", "正确", JOptionPane.INFORMATION_MESSAGE);
answerTextField.setBackground(Color.WHITE);
score= ScoreKey.getScoreByKey(currentQuestion.getFrequency());
showNextQuestionOption();
} else {
// 答案错误时改变输入框颜色
answerTextField.setBackground(new Color(255, 220, 220)); // 淡红色
int choice = JOptionPane.showConfirmDialog(
this,
"答案错误,正确答案是:" + currentQuestion.getAnswer() + "\n是否重新尝试",
"错误",
JOptionPane.YES_NO_OPTION
);
if (choice == JOptionPane.NO_OPTION) {
answerTextField.setBackground(Color.WHITE);
showNextQuestionOption();
} else {
// 清空输入框,允许重新尝试
answerTextField.setText("");
answerTextField.setBackground(Color.WHITE);
}
}
// 保存测试记录
TestRecord testRecord = new TestRecord();
testRecord.setUserId(user);
testRecord.setQuestionId(questionId);
testRecord.setScore(score);
testRecord.setAnswer(userAnswer);
testRecord.setTime(new Date(System.currentTimeMillis()));
TestRecordService testRecordService = new TestRecordService();
testRecordService.insert(testRecord);
}
private void resetToInitialState() {
// 重置所有组件状态
questionLabel.setText("点击开始测试获取题目");
descriptionLabel.setText("描述将在这里显示");
answerTextField.setText("");
answerTextField.setBackground(Color.WHITE);
// 重置按钮状态
updateButtonVisibility();
// 重置进度
progressLabel.setText("题目进度: 0/0");
revalidate();
repaint();
}
private JMenuBar initMenuBar() {
menuBar = new JMenuBar();
menuBar.setBackground(PRIMARY_COLOR);
JMenu testMenu = new JMenu("测试内容");
testMenu.setForeground(Color.WHITE);
testMenu.add(new JMenuItem("开始测试"));
menuBar.add(testMenu);
JMenu recordMenu = new JMenu("测试记录");
recordMenu.setForeground(Color.WHITE);
if(role.equals("user"))
recordMenu.add(new JMenuItem("我的记录"));
else
recordMenu.add(new JMenuItem("查看所有记录"));
menuBar.add(recordMenu);
JMenu chartMenu = new JMenu("排行榜");
chartMenu.setForeground(Color.WHITE);
chartMenu.add(new JMenuItem("查看排行榜"));
menuBar.add(chartMenu);
return menuBar;
}
private void initRecordView() {
// 清空当前面板
removeAll();
setLayout(new BorderLayout());
// 创建顶部查询面板
JPanel queryPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
queryPanel.setBackground(PRIMARY_COLOR);
queryPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
// 添加查询输入框和按钮
JLabel userLabel = new JLabel("用户:");
userLabel.setForeground(Color.WHITE);
JTextField userIdField = new JTextField(8);
userIdField.setPreferredSize(new Dimension(80, 25));
JLabel questionLabel = new JLabel("题目:");
questionLabel.setForeground(Color.WHITE);
JTextField questionIdField = new JTextField(8);
questionIdField.setPreferredSize(new Dimension(80, 25));
JButton searchButton = new JButton("查询");
setButtonStyle(searchButton);
JButton resetButton = new JButton("重置");
setButtonStyle(resetButton);
queryPanel.add(userLabel);
queryPanel.add(userIdField);
queryPanel.add(questionLabel);
queryPanel.add(questionIdField);
queryPanel.add(searchButton);
queryPanel.add(resetButton);
// 创建表格展示面板
JPanel tablePanel = new JPanel(new BorderLayout());
tablePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// 初始化表格
String[] columnNames = {"记录ID", "用户名", "题目", "得分", "答案", "时间"};
DefaultTableModel tableModel = new DefaultTableModel(columnNames, 0) {
@Override
public boolean isCellEditable(int row, int column) {
return false; // 表格不可编辑
}
};
JTable recordTable = new JTable(tableModel);
recordTable.setFont(new Font("微软雅黑", Font.PLAIN, 12));
recordTable.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 13));
recordTable.getTableHeader().setBackground(PRIMARY_COLOR);
recordTable.getTableHeader().setForeground(Color.WHITE);
recordTable.setSelectionBackground(new Color(176, 224, 230));
recordTable.setRowHeight(25);
// 设置列宽
recordTable.getColumnModel().getColumn(0).setPreferredWidth(60); // 记录ID
recordTable.getColumnModel().getColumn(1).setPreferredWidth(100); // 用户名
recordTable.getColumnModel().getColumn(2).setPreferredWidth(200); // 题目
recordTable.getColumnModel().getColumn(3).setPreferredWidth(60); // 得分
recordTable.getColumnModel().getColumn(4).setPreferredWidth(150); // 答案
recordTable.getColumnModel().getColumn(5).setPreferredWidth(120); // 时间
JScrollPane scrollPane = new JScrollPane(recordTable);
scrollPane.setPreferredSize(new Dimension(700, 400));
tablePanel.add(scrollPane, BorderLayout.CENTER);
// 添加到主面板
add(queryPanel, BorderLayout.NORTH);
add(tablePanel, BorderLayout.CENTER);
// 查询按钮事件处理
searchButton.addActionListener(e -> {
UserDao userDao = new UserDao();
QuestionsDao questionsDao = new QuestionsDao();
String userIdText = userIdField.getText().trim();
String questionIdText = questionIdField.getText().trim();
TestRecordService testRecordService = new TestRecordService();
Vector<Vector<String>> records;
try {
if (!userIdText.isEmpty() && !questionIdText.isEmpty()) {
userIdText = String.valueOf(userDao.findByUsername(userIdField.getText().trim()).getId());
questionIdText = String.valueOf(questionsDao.getByName(questionIdField.getText().trim()).getId());
// 同时查询用户ID和题目ID
Integer userId = Integer.parseInt(userIdText);
Integer questionId = Integer.parseInt(questionIdText);
records = testRecordService.getByUserIdAndQuestionId(userId, questionId);
} else if (!userIdText.isEmpty()) {
// 只查询用户ID
userIdText = String.valueOf(userDao.findByUsername(userIdField.getText().trim()).getId());
Integer userId = Integer.parseInt(userIdText);
records = testRecordService.getByUserId(userId);
} else if (!questionIdText.isEmpty()) {
// 只查询题目ID
questionIdText = String.valueOf(questionsDao.getByName(questionIdField.getText().trim()).getId());
Integer questionId = Integer.parseInt(questionIdText);
records = testRecordService.getByQuestionId(questionId);
} else {
// 查询所有记录(根据角色权限)
if (role.equals("user")) {
records = testRecordService.getByUserId(this.userId);
} else {
records = testRecordService.getAll();
}
}
// 清空表格
tableModel.setRowCount(0);
// 添加数据到表格
for (Vector<String> record : records) {
tableModel.addRow(record);
}
// 如果没有找到记录,显示提示
if (records.isEmpty()) {
JOptionPane.showMessageDialog(this, "没有找到匹配的记录", "提示", JOptionPane.INFORMATION_MESSAGE);
}
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(this, "请输入有效的数字ID", "错误", JOptionPane.ERROR_MESSAGE);
}
});
// 重置按钮事件处理
resetButton.addActionListener(e -> {
userIdField.setText("");
questionIdField.setText("");
// 根据角色加载默认数据
TestRecordService testRecordService = new TestRecordService();
Vector<Vector<String>> records;
if (role.equals("user")) {
records = testRecordService.getByUserId(this.userId);
} else {
records = testRecordService.getAll();
}
// 清空表格
tableModel.setRowCount(0);
// 添加数据到表格
for (Vector<String> record : records) {
tableModel.addRow(record);
}
});
// 初始加载数据
SwingUtilities.invokeLater(() -> {
TestRecordService testRecordService = new TestRecordService();
Vector<Vector<String>> records;
if (role.equals("user")) {
records = testRecordService.getByUserId(this.userId);
} else {
records = testRecordService.getAll();
}
// 添加数据到表格
for (Vector<String> record : records) {
tableModel.addRow(record);
}
});
revalidate();
repaint();
}
private void initRankView() {
// 清空当前面板
removeAll();
setLayout(new BorderLayout());
// 创建顶部控制面板
JPanel controlPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
controlPanel.setBackground(PRIMARY_COLOR);
controlPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
JButton sortByScoreUpButton = new JButton("按分数升序");
JButton sortByScoreDownButton = new JButton("按分数降序");
setButtonStyle(sortByScoreUpButton);
setButtonStyle(sortByScoreDownButton);
controlPanel.add(sortByScoreUpButton);
controlPanel.add(sortByScoreDownButton);
// 创建表格展示面板
JPanel tablePanel = new JPanel(new BorderLayout());
tablePanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// 初始化表格
String[] columnNames = {"排名", "用户名", "答题次数", "总得分"};
DefaultTableModel tableModel = new DefaultTableModel(columnNames, 0) {
@Override
public boolean isCellEditable(int row, int column) {
return false; // 表格不可编辑
}
};
JTable rankTable = new JTable(tableModel);
rankTable.setFont(new Font("微软雅黑", Font.PLAIN, 12));
rankTable.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 13));
rankTable.getTableHeader().setBackground(PRIMARY_COLOR);
rankTable.getTableHeader().setForeground(Color.WHITE);
rankTable.setSelectionBackground(new Color(176, 224, 230));
rankTable.setRowHeight(25);
// 设置列宽
rankTable.getColumnModel().getColumn(0).setPreferredWidth(60); // 排名
rankTable.getColumnModel().getColumn(1).setPreferredWidth(120); // 用户名
rankTable.getColumnModel().getColumn(2).setPreferredWidth(100); // 答题次数
rankTable.getColumnModel().getColumn(3).setPreferredWidth(100); // 总得分
JScrollPane scrollPane = new JScrollPane(rankTable);
scrollPane.setPreferredSize(new Dimension(600, 400));
tablePanel.add(scrollPane, BorderLayout.CENTER);
// 添加到主面板
add(controlPanel, BorderLayout.NORTH);
add(tablePanel, BorderLayout.CENTER);
// 加载默认数据(升序)
loadRankData(tableModel, true);
// 按分数升序按钮事件
sortByScoreUpButton.addActionListener(e -> {
loadRankData(tableModel, true);
});
// 按分数降序按钮事件
sortByScoreDownButton.addActionListener(e -> {
loadRankData(tableModel, false);
});
revalidate();
repaint();
}
private void loadRankData(DefaultTableModel tableModel, boolean isAscending) {
ChartsService chartsService = new ChartsService();
Vector<Vector<String>> rankData;
if (isAscending) {
rankData = chartsService.sortByScoreUp();
} else {
rankData = chartsService.sortByScoreDown();
}
// 清空表格
tableModel.setRowCount(0);
// 添加数据到表格
for (Vector<String> rankItem : rankData) {
tableModel.addRow(rankItem);
}
}
}

324
src/view/LoginFrame.java Normal file
View File

@@ -0,0 +1,324 @@
package view;
import backend.dao.UserDao;
import backend.model.enums.LoginStatus;
import backend.model.User;
import backend.service.AuthService;
import backend.utils.CaptchaUtils;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class LoginFrame extends JFrame{
private JPanel mainPanel;//中间层面板
private JTextField usernameTextField;//用户名输入框
private JPasswordField passwordField;//密码输入框
private JTextField captchaTextField;//验证码输入框
private JLabel captchaLabel;//验证码标签
private JButton loginButton;//登录按钮
private JButton registerButton;//注册按钮
private AuthService authService = new AuthService();
private UserDao userDao = new UserDao();
protected static String loginRole;
protected static int userId;
// 颜色常量定义
private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色
private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景
private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色
private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景
public LoginFrame() {
//初始化界面
initView();
//注册监听器
initListener();
usernameTextField.setText("admin");
passwordField.setText("123456");
captchaTextField.setText(captchaLabel.getText());
}
private void initView(){
//1.设置标题
setTitle("中医药知识测试系统 - 登录");
//2.设置点击关闭时的动作
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//3.设置窗口背景色
getContentPane().setBackground(BACKGROUND_COLOR);
//4.中间层容器
add(initPanel());
//5.不允许窗口改变大小
setResizable(false);
//6.设置窗口大小 居中显示
setSize(400, 350);
setLocationRelativeTo(null);
//7.显示窗口
setVisible(true);
}
private void initListener(){
captchaLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
captchaLabel.setText(CaptchaUtils.generateCaptcha());
}
});
loginButton.addActionListener(e -> {
//点击登录按钮后的事件
String username = usernameTextField.getText();
String password = passwordField.getText();
String captcha = captchaTextField.getText();
//System.out.println("用户名" + username + " 密码" + password + " 验证码" + captcha);
if(username.equals("")||password.equals("")||captcha.equals("")) {
JOptionPane.showMessageDialog(this, "请填写完整信息!", "提示", JOptionPane.INFORMATION_MESSAGE);
return;
}
if(!CaptchaUtils.verifyCaptcha(captcha,captchaLabel.getText())){
JOptionPane.showMessageDialog(this, LoginStatus.CAPTCHA_ERROR.getMsg(), "提示", JOptionPane.INFORMATION_MESSAGE);
return;
}
User account = new User();
account.setUsername(username);
account.setPassword(password);
LoginStatus loginStatus = authService.login(account);
if(loginStatus == LoginStatus.SUCCESS) {
//记录登陆角色的权限
account=userDao.findByUsername(username);
loginRole = account.getRole();
userId = account.getId();
//进入主界面
new MainFrame();
this.dispose();
}
else if(loginStatus == LoginStatus.USER_NOT_FOUND) {
JOptionPane.showMessageDialog(this, LoginStatus.USER_NOT_FOUND.getMsg(), "提示", JOptionPane.INFORMATION_MESSAGE);
return;
}
else if(loginStatus == LoginStatus.PASSWORD_ERROR) {
JOptionPane.showMessageDialog(this, LoginStatus.PASSWORD_ERROR.getMsg(), "提示", JOptionPane.INFORMATION_MESSAGE);
return;
}
else{
JOptionPane.showMessageDialog(this, loginStatus.getMsg(), "提示", JOptionPane.INFORMATION_MESSAGE);
}
});
registerButton.addActionListener(e -> {
//点击注册按钮后的事件
RegisterFrame registerFrame = new RegisterFrame();
registerFrame.setVisible(true);
registerFrame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
});
}
private JPanel initPanel(){
mainPanel = new JPanel(new BorderLayout());
mainPanel.setBackground(BACKGROUND_COLOR);
// 创建顶部标题面板
JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
titlePanel.setBackground(PRIMARY_COLOR);
JLabel titleLabel = new JLabel("中医药知识测试系统");
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 18));
titleLabel.setForeground(Color.WHITE);
titlePanel.add(titleLabel);
mainPanel.add(titlePanel, BorderLayout.NORTH);
// 创建中央登录表单面板
JPanel formPanel = new JPanel(new GridBagLayout());
formPanel.setBackground(BACKGROUND_COLOR);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
// 第1行 - 标题
gbc.gridx = 0; gbc.gridy = 0;
gbc.gridwidth = 2;
gbc.anchor = GridBagConstraints.CENTER;
JLabel formTitleLabel = new JLabel("用户登录");
formTitleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
formTitleLabel.setForeground(PRIMARY_COLOR);
formPanel.add(formTitleLabel, gbc);
// 第2行 - 用户名
gbc.gridx = 0; gbc.gridy = 1;
gbc.gridwidth = 1;
gbc.anchor = GridBagConstraints.WEST;
JLabel usernameLabel = new JLabel("用户名:");
usernameLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
formPanel.add(usernameLabel, gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
usernameTextField = new JTextField(15);
usernameTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12));
usernameTextField.setPreferredSize(new Dimension(200, 25));
formPanel.add(usernameTextField, gbc);
// 第3行 - 密码
gbc.gridx = 0; gbc.gridy = 2;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
gbc.anchor = GridBagConstraints.WEST;
JLabel passwordLabel = new JLabel("密 码:");
passwordLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
formPanel.add(passwordLabel, gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
passwordField = new JPasswordField(15);
passwordField.setFont(new Font("微软雅黑", Font.PLAIN, 12));
passwordField.setPreferredSize(new Dimension(200, 25));
formPanel.add(passwordField, gbc);
// 第4行 - 验证码
gbc.gridx = 0; gbc.gridy = 3;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
gbc.anchor = GridBagConstraints.WEST;
JLabel captchaLabel = new JLabel("验证码:");
captchaLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
formPanel.add(captchaLabel, gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
JPanel captchaPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
captchaPanel.setBackground(BACKGROUND_COLOR);
captchaTextField = new JTextField(8);
captchaTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12));
captchaTextField.setPreferredSize(new Dimension(80, 25));
captchaPanel.add(captchaTextField);
this.captchaLabel = new JLabel(CaptchaUtils.generateCaptcha());
this.captchaLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
this.captchaLabel.setBackground(Color.WHITE);
this.captchaLabel.setOpaque(true);
this.captchaLabel.setBorder(BorderFactory.createLineBorder(BORDER_COLOR));
this.captchaLabel.setPreferredSize(new Dimension(80, 25));
this.captchaLabel.setHorizontalAlignment(JLabel.CENTER);
captchaPanel.add(this.captchaLabel);
formPanel.add(captchaPanel, gbc);
// 第5行 - 按钮
gbc.gridx = 0; gbc.gridy = 4;
gbc.gridwidth = 2;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
gbc.anchor = GridBagConstraints.CENTER;
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 0));
buttonPanel.setBackground(BACKGROUND_COLOR);
loginButton = new JButton("登录");
registerButton = new JButton("注册");
// 设置按钮样式
setButtonStyle(loginButton);
setButtonStyle(registerButton);
buttonPanel.add(loginButton);
buttonPanel.add(registerButton);
formPanel.add(buttonPanel, gbc);
// 添加边距
formPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
mainPanel.add(formPanel, BorderLayout.CENTER);
return mainPanel;
}
// 设置按钮样式
private void setButtonStyle(JButton button) {
button.setFont(new Font("微软雅黑", Font.BOLD, 14));
button.setPreferredSize(new Dimension(80, 30));
button.setBackground(PRIMARY_COLOR);
button.setForeground(Color.WHITE);
button.setFocusPainted(false);
button.setBorder(BorderFactory.createRaisedBevelBorder());
}
private JPanel initAcountPanel(){
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1,4,10,0));
JLabel label = new JLabel("用户名:");
//让label居右
label.setHorizontalAlignment(SwingConstants.RIGHT);
usernameTextField = new JTextField(15);
panel.add(label);
panel.add(usernameTextField);
panel.add(new JPanel());
return panel;
}
private JPanel initPasswordPanel(){
JPanel panel = new JPanel();
// 设置网格布局1行4列水平间距10像素
panel.setLayout(new GridLayout(1,4,10,0));
JLabel label = new JLabel("密 码:");
// 设置标签文本右对齐
label.setHorizontalAlignment(SwingConstants.RIGHT);
passwordField = new JPasswordField(15);
panel.add(label);
panel.add(passwordField);
// 添加空白面板占位
panel.add(new JPanel());
return panel;
}
private JPanel initCaptchaPanel(){
// 创建面板并设置网格布局
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1,4,10,0));
// 创建验证码标签
JLabel label = new JLabel("验证码:");
label.setHorizontalAlignment(SwingConstants.RIGHT);
// 创建验证码输入框和验证码显示标签
captchaTextField = new JTextField(4);
captchaLabel = new JLabel(CaptchaUtils.generateCaptcha());
// 将组件添加到面板中
panel.add(label);
panel.add(captchaTextField);
panel.add(captchaLabel);
return panel;
}
private JPanel initEmailPanel(){
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1,4,10,0));
JLabel label = new JLabel("邮 箱:");
label.setHorizontalAlignment(SwingConstants.RIGHT);
JTextField emailTextField = new JTextField(15);
panel.add(label);
panel.add(emailTextField);
panel.add(new JPanel());
return panel;
}
private JPanel initButtonPanel(){
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1,4,10,0));
loginButton = new JButton("登录");
registerButton = new JButton("注册");
panel.add(new JPanel());
panel.add(loginButton);
panel.add(registerButton);
panel.add(new JPanel());
return panel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
LoginFrame loginFrame = new LoginFrame();
loginFrame.setVisible(true);
});
}
}

122
src/view/MainFrame.java Normal file
View File

@@ -0,0 +1,122 @@
package view;
import backend.model.Questions;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class MainFrame extends JFrame{
private JPanel mainPanel;
private JMenuBar menuBar;
private JMenu questionsMenu;
private JMenu examMenu;
private JMenu userMenu;
protected static String role = LoginFrame.loginRole;
protected static int userId = LoginFrame.userId;
// 颜色常量定义
private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色
private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景
private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色
private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景
public MainFrame(){
initView();
initListener();
}
private void initView(){
//1.设置标题
setTitle("中医药知识测试系统");
//2.设置点击关闭时的动作
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//3.设置窗口背景色
getContentPane().setBackground(BACKGROUND_COLOR);
//4.中间层容器
add(initPanel());
//5.不允许窗口改变大小
setResizable(false);
//6.设置窗口大小 居中显示
setSize(800, 600);
setLocationRelativeTo(null);
//7.显示窗口
setVisible(true);
}
private void initListener(){
if(role.equals("admin")) {
questionsMenu.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
mainPanel.removeAll();
mainPanel.add(new QuestionsPanel());
mainPanel.revalidate();
mainPanel.repaint();
}
});
userMenu.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
mainPanel.removeAll();
mainPanel.add(new UserPanel());
mainPanel.revalidate();
mainPanel.repaint();
}
});
}
examMenu.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
mainPanel.removeAll();
mainPanel.add(new ExamPanel());
mainPanel.revalidate();
mainPanel.repaint();
}
});
}
private JPanel initPanel(){
mainPanel = new JPanel(new BorderLayout());
mainPanel.setBackground(BACKGROUND_COLOR);
setJMenuBar(initMenuBar());
if(MainFrame.role.equals("admin")) {
//默认为问题库界面
mainPanel.add(new QuestionsPanel(), BorderLayout.CENTER);
}
else{
//默认为考试界面
mainPanel.add(new ExamPanel(), BorderLayout.CENTER);
}
return mainPanel;
}
private JMenuBar initMenuBar(){
menuBar = new JMenuBar();
menuBar.setBackground(PRIMARY_COLOR);
if(role.equals("admin")) {
questionsMenu = new JMenu("问题库管理");
questionsMenu.setForeground(Color.WHITE);
questionsMenu.setFont(new Font("微软雅黑", Font.BOLD, 14));
menuBar.add(questionsMenu);
userMenu = new JMenu("用户管理");
userMenu.setForeground(Color.WHITE);
userMenu.setFont(new Font("微软雅黑", Font.BOLD, 14));
menuBar.add(userMenu);
}
examMenu = new JMenu("测试管理");
examMenu.setForeground(Color.WHITE);
examMenu.setFont(new Font("微软雅黑", Font.BOLD, 14));
menuBar.add(examMenu);
return menuBar;
}
public static void main(String[] args) {
new MainFrame().initView();
}
}

View File

@@ -0,0 +1,222 @@
package view;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Vector;
import backend.model.Questions;
import backend.service.QuestionsService;
import backend.model.enums.GlobalData;
public class QuestionsPanel extends JPanel{
private QuestionsService questionsService = new QuestionsService();
private static Vector<String> columNames = new Vector<>();
private DefaultTableModel model;
private JTable table;
private JScrollPane scrollPane;
private Vector<Vector<String>> tableData;
//按钮界面
private JButton addButton;
private JButton deleteButton;
private JButton editButton;
//搜索界面
private JComboBox frequencyComboBox;
private JTextField keyTextField;
private JButton queryButton;
// 颜色常量定义
private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色
private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景
private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色
private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景
static {
columNames.add("ID");
columNames.add("题目");
columNames.add("描述");
columNames.add("答案");
columNames.add("频率");
}
public void initListener(){
queryButton.addActionListener(e->{
Integer frequency = frequencyComboBox.getSelectedIndex()==0?null:frequencyComboBox.getSelectedIndex();
String key = keyTextField.getText();
//清楚已有数据
model.setRowCount(0);
//条件查询
tableData = questionsService.getByCondition(frequency,key);
//刷新表格
refreshData();
});
deleteButton.addActionListener(e->{
if(MainFrame.role.equals("user"))
return;
int row = table.getSelectedRow();
if(row!=-1){
int id = Integer.valueOf(tableData.get(row).get(0));
String word = tableData.get(row).get(1);
int option = JOptionPane.showConfirmDialog(this,"确认删除"+word+"吗?","提示",JOptionPane.YES_NO_CANCEL_OPTION);
if(option == JOptionPane.YES_OPTION){
questionsService.delete(id);
model.removeRow(row);
}
}
});
//添加事件:打开对话框
addButton.addActionListener(e->{
if(MainFrame.role.equals("user"))
return;
new EditQuestionDialog(0,null);
});
editButton.addActionListener(e->{
if(MainFrame.role.equals("user"))
return;
int row = table.getSelectedRow();
if(row>=0)
openEditDialog(row);
});
//双击某行弹出修改对话框
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if(MainFrame.role.equals("user"))
return;
if(e.getClickCount()==2){
int row = table.getSelectedRow();
openEditDialog(row);
}
}
});
}
private void openEditDialog(int row){
Vector<String> data = tableData.get(row);
Questions questions = new Questions();
questions.setId(Integer.parseInt(data.get(0)));
questions.setName(data.get(1));
questions.setDescription(data.get(2));
questions.setAnswer(data.get(3));
questions.setFrequency(GlobalData.getFrequencyByValue(data.get(4)));
new EditQuestionDialog(1, questions);
//修改成功后刷新并定位修改位置
tableData = questionsService.getAll();
refreshData();
table.setRowSelectionInterval(row,row);
scrollPane.getVerticalScrollBar().setValue(row*table.getRowHeight());
scrollPane.getHorizontalScrollBar().setValue(0);
scrollPane.revalidate();
}
public QuestionsPanel(){
initView();
initListener();
}
private void initView(){
setLayout(new BorderLayout());
setBackground(BACKGROUND_COLOR);
// 创建顶部工具栏
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.setBackground(PRIMARY_COLOR);
topPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
JLabel titleLabel = new JLabel("题目管理");
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
titleLabel.setForeground(Color.WHITE);
topPanel.add(titleLabel, BorderLayout.WEST);
add(topPanel, BorderLayout.NORTH);
// 创建中央内容面板
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS));
centerPanel.setBackground(BACKGROUND_COLOR);
centerPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// 1.按钮界面
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
buttonPanel.setBackground(BACKGROUND_COLOR);
addButton = new JButton("添加");
deleteButton = new JButton("删除");
editButton = new JButton("修改");
// 设置按钮样式
setButtonStyle(addButton);
setButtonStyle(deleteButton);
setButtonStyle(editButton);
buttonPanel.add(addButton);
buttonPanel.add(deleteButton);
buttonPanel.add(editButton);
centerPanel.add(buttonPanel);
centerPanel.add(Box.createVerticalStrut(10));
// 2.搜索界面
JPanel queryPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
queryPanel.setBackground(BACKGROUND_COLOR);
frequencyComboBox = new JComboBox<String>(new String[]{"全部","低频","中频","高频"});
keyTextField = new JTextField(15);
queryButton = new JButton("查询");
// 设置查询按钮样式
setButtonStyle(queryButton);
queryPanel.add(new JLabel("频率:"));
queryPanel.add(frequencyComboBox);
queryPanel.add(new JLabel("关键词:"));
queryPanel.add(keyTextField);
queryPanel.add(queryButton);
centerPanel.add(queryPanel);
centerPanel.add(Box.createVerticalStrut(10));
// 3.表格界面
model = new DefaultTableModel(){
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
table = new JTable(model);
table.setFont(new Font("微软雅黑", Font.PLAIN, 12));
table.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 13));
table.getTableHeader().setBackground(PRIMARY_COLOR);
table.getTableHeader().setForeground(Color.WHITE);
table.setSelectionBackground(new Color(176, 224, 230));
table.setRowHeight(25);
scrollPane = new JScrollPane(table);
scrollPane.setPreferredSize(new Dimension(700, 400));
scrollPane.setBorder(BorderFactory.createLineBorder(BORDER_COLOR, 1));
centerPanel.add(scrollPane);
add(centerPanel, BorderLayout.CENTER);
tableData = questionsService.getAll();
//刷新数据
refreshData();
}
// 设置按钮样式
private void setButtonStyle(JButton button) {
button.setFont(new Font("微软雅黑", Font.BOLD, 14));
button.setPreferredSize(new Dimension(80, 30));
button.setBackground(PRIMARY_COLOR);
button.setForeground(Color.WHITE);
button.setFocusPainted(false);
button.setBorder(BorderFactory.createRaisedBevelBorder());
}
private void refreshData(){
model.setDataVector(tableData,columNames);
model.fireTableDataChanged();
}
}

374
src/view/RegisterFrame.java Normal file
View File

@@ -0,0 +1,374 @@
package view;
import backend.model.User;
import backend.model.enums.LoginStatus;
import backend.service.AuthService;
import backend.utils.CaptchaUtils;
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
public class RegisterFrame extends JFrame{
private JPanel mainPanel;//中间层面板
private JTextField usernameTextField;//用户名输入框
private JPasswordField passwordField;//密码输入框
private JPasswordField confirmPasswordField;//确认密码输入框
private JTextField captchaTextField;//验证码输入框
private JTextField emailTextField;//邮箱输入框
private JLabel captchaLabel;//验证码标签
private JButton registerButton;//注册按钮
private JButton backButton;//返回按钮
private AuthService authService = new AuthService();
// 颜色常量定义
private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色
private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景
private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色
private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景
public RegisterFrame() {
//初始化界面
initView();
//注册监听器
initListener();
usernameTextField.setText("admin");
passwordField.setText("123456");
captchaTextField.setText(captchaLabel.getText());
emailTextField.setText("123456@qq.com");
confirmPasswordField.setText(passwordField.getText());
}
private void initView(){
//1.设置标题
setTitle("中医药知识测试系统 - 注册");
//2.设置点击关闭时的动作
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//3.设置窗口背景色
getContentPane().setBackground(BACKGROUND_COLOR);
//4.中间层容器
add(initPanel());
//5.不允许窗口改变大小
setResizable(false);
//6.设置窗口大小 居中显示
setSize(400, 400);
setLocationRelativeTo(null);
//7.显示窗口
setVisible(true);
}
private void initListener(){
captchaLabel.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
captchaLabel.setText(CaptchaUtils.generateCaptcha());
}
});
registerButton.addActionListener(e -> {
//点击注册按钮后的事件
String username = usernameTextField.getText();
String password = passwordField.getText();
String captcha = captchaTextField.getText();
//System.out.println("用户名" + username + " 密码" + password + " 验证码" + captcha);
if(username.equals("")||password.equals("")||captcha.equals("")) {
JOptionPane.showMessageDialog(this, "请填写完整信息!", "提示", JOptionPane.INFORMATION_MESSAGE);
return;
}
if(!CaptchaUtils.verifyCaptcha(captcha,captchaLabel.getText())){
JOptionPane.showMessageDialog(this, LoginStatus.CAPTCHA_ERROR.getMsg(), "提示", JOptionPane.INFORMATION_MESSAGE);
return;
}
if(!confirmPasswordField.getText().equals(password))
JOptionPane.showMessageDialog(this, LoginStatus.PASSWORD_NOT_MATCH.getMsg(), "提示", JOptionPane.INFORMATION_MESSAGE);
User account = new User();
account.setId();
account.setUsername(username);
account.setPassword(password);
account.setEmail(emailTextField.getText());
account.setRole("user");
account.setCreatedAt();
LoginStatus loginStatus = authService.register(account);
if(loginStatus==LoginStatus.REGISTER_SUCCESS) {
this.dispose();
}
if(loginStatus == LoginStatus.SUCCESS) {
//返回注册界面
mainPanel.removeAll();
//关闭注册界面
this.dispose();
}
else if(loginStatus == LoginStatus.USER_NOT_FOUND) {
JOptionPane.showMessageDialog(this, LoginStatus.USER_NOT_FOUND.getMsg(), "提示", JOptionPane.INFORMATION_MESSAGE);
return;
}
else if(loginStatus == LoginStatus.PASSWORD_ERROR) {
JOptionPane.showMessageDialog(this, LoginStatus.PASSWORD_ERROR.getMsg(), "提示", JOptionPane.INFORMATION_MESSAGE);
return;
}
else{
JOptionPane.showMessageDialog(this, loginStatus.getMsg(), "提示", JOptionPane.INFORMATION_MESSAGE);
}
});
backButton.addActionListener(e -> {
//返回登录界面
mainPanel.removeAll();
dispose();
});
}
private JPanel initPanel(){
mainPanel = new JPanel(new BorderLayout());
mainPanel.setBackground(BACKGROUND_COLOR);
// 创建顶部标题面板
JPanel titlePanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
titlePanel.setBackground(PRIMARY_COLOR);
JLabel titleLabel = new JLabel("用户注册");
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 18));
titleLabel.setForeground(Color.WHITE);
titlePanel.add(titleLabel);
mainPanel.add(titlePanel, BorderLayout.NORTH);
// 创建中央注册表单面板
JPanel formPanel = new JPanel(new GridBagLayout());
formPanel.setBackground(BACKGROUND_COLOR);
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(10, 10, 10, 10);
// 第1行 - 标题
gbc.gridx = 0; gbc.gridy = 0;
gbc.gridwidth = 2;
gbc.anchor = GridBagConstraints.CENTER;
JLabel formTitleLabel = new JLabel("创建新账户");
formTitleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
formTitleLabel.setForeground(PRIMARY_COLOR);
formPanel.add(formTitleLabel, gbc);
// 第2行 - 用户名
gbc.gridx = 0; gbc.gridy = 1;
gbc.gridwidth = 1;
gbc.anchor = GridBagConstraints.WEST;
JLabel usernameLabel = new JLabel("用户名:");
usernameLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
formPanel.add(usernameLabel, gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
usernameTextField = new JTextField(15);
usernameTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12));
usernameTextField.setPreferredSize(new Dimension(200, 25));
formPanel.add(usernameTextField, gbc);
// 第3行 - 密码
gbc.gridx = 0; gbc.gridy = 2;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
gbc.anchor = GridBagConstraints.WEST;
JLabel passwordLabel = new JLabel("密 码:");
passwordLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
formPanel.add(passwordLabel, gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
passwordField = new JPasswordField(15);
passwordField.setFont(new Font("微软雅黑", Font.PLAIN, 12));
passwordField.setPreferredSize(new Dimension(200, 25));
formPanel.add(passwordField, gbc);
// 第4行 - 确认密码
gbc.gridx = 0; gbc.gridy = 3;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
gbc.anchor = GridBagConstraints.WEST;
JLabel confirmPasswordLabel = new JLabel("确认密码:");
confirmPasswordLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
formPanel.add(confirmPasswordLabel, gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
confirmPasswordField = new JPasswordField(15);
confirmPasswordField.setFont(new Font("微软雅黑", Font.PLAIN, 12));
confirmPasswordField.setPreferredSize(new Dimension(200, 25));
formPanel.add(confirmPasswordField, gbc);
// 第5行 - 邮箱
gbc.gridx = 0; gbc.gridy = 4;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
gbc.anchor = GridBagConstraints.WEST;
JLabel emailLabel = new JLabel("邮 箱:");
emailLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
formPanel.add(emailLabel, gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
emailTextField = new JTextField(15);
emailTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12));
emailTextField.setPreferredSize(new Dimension(200, 25));
formPanel.add(emailTextField, gbc);
// 第6行 - 验证码
gbc.gridx = 0; gbc.gridy = 5;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
gbc.anchor = GridBagConstraints.WEST;
JLabel captchaLabel = new JLabel("验证码:");
captchaLabel.setFont(new Font("微软雅黑", Font.PLAIN, 12));
formPanel.add(captchaLabel, gbc);
gbc.gridx = 1;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.weightx = 1.0;
JPanel captchaPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 0));
captchaPanel.setBackground(BACKGROUND_COLOR);
captchaTextField = new JTextField(8);
captchaTextField.setFont(new Font("微软雅黑", Font.PLAIN, 12));
captchaTextField.setPreferredSize(new Dimension(80, 25));
captchaPanel.add(captchaTextField);
this.captchaLabel = new JLabel(CaptchaUtils.generateCaptcha());
this.captchaLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
this.captchaLabel.setBackground(Color.WHITE);
this.captchaLabel.setOpaque(true);
this.captchaLabel.setBorder(BorderFactory.createLineBorder(BORDER_COLOR));
this.captchaLabel.setPreferredSize(new Dimension(80, 25));
this.captchaLabel.setHorizontalAlignment(JLabel.CENTER);
captchaPanel.add(this.captchaLabel);
formPanel.add(captchaPanel, gbc);
// 第7行 - 按钮
gbc.gridx = 0; gbc.gridy = 6;
gbc.gridwidth = 2;
gbc.fill = GridBagConstraints.NONE;
gbc.weightx = 0.0;
gbc.anchor = GridBagConstraints.CENTER;
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 20, 0));
buttonPanel.setBackground(BACKGROUND_COLOR);
registerButton = new JButton("注册");
backButton = new JButton("返回");
// 设置按钮样式
setButtonStyle(registerButton);
setButtonStyle(backButton);
buttonPanel.add(registerButton);
buttonPanel.add(backButton);
formPanel.add(buttonPanel, gbc);
// 添加边距
formPanel.setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
mainPanel.add(formPanel, BorderLayout.CENTER);
return mainPanel;
}
// 设置按钮样式
private void setButtonStyle(JButton button) {
button.setFont(new Font("微软雅黑", Font.BOLD, 14));
button.setPreferredSize(new Dimension(80, 30));
button.setBackground(PRIMARY_COLOR);
button.setForeground(Color.WHITE);
button.setFocusPainted(false);
button.setBorder(BorderFactory.createRaisedBevelBorder());
}
private JPanel initAcountPanel(){
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1,4,10,0));
JLabel label = new JLabel("用户名:");
//让label居右
label.setHorizontalAlignment(SwingConstants.RIGHT);
usernameTextField = new JTextField(15);
panel.add(label);
panel.add(usernameTextField);
panel.add(new JPanel());
return panel;
}
private JPanel initPasswordPanel(){
JPanel panel = new JPanel();
// 设置网格布局1行4列水平间距10像素
panel.setLayout(new GridLayout(1,4,10,0));
JLabel label = new JLabel("密 码:");
// 设置标签文本右对齐
label.setHorizontalAlignment(SwingConstants.RIGHT);
passwordField = new JPasswordField(15);
panel.add(label);
panel.add(passwordField);
// 添加空白面板占位
panel.add(new JPanel());
return panel;
}
private JPanel initConfirmPasswordPanel(){
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1,4,10,0));
JLabel label = new JLabel("确认密码:");
label.setHorizontalAlignment(SwingConstants.RIGHT);
confirmPasswordField = new JPasswordField(15);
panel.add(label);
panel.add(confirmPasswordField);
panel.add(new JPanel());
return panel;
}
private JPanel initCaptchaPanel(){
// 创建面板并设置网格布局
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1,4,10,0));
// 创建验证码标签
JLabel label = new JLabel("验证码:");
label.setHorizontalAlignment(SwingConstants.RIGHT);
// 创建验证码输入框和验证码显示标签
captchaTextField = new JTextField(4);
captchaLabel = new JLabel(CaptchaUtils.generateCaptcha());
// 将组件添加到面板中
panel.add(label);
panel.add(captchaTextField);
panel.add(captchaLabel);
return panel;
}
private JPanel initEmailPanel(){
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1,4,10,0));
JLabel label = new JLabel("邮 箱:");
label.setHorizontalAlignment(SwingConstants.RIGHT);
emailTextField = new JTextField(15);
panel.add(label);
panel.add(emailTextField);
panel.add(new JPanel());
return panel;
}
private JPanel initButtonPanel(){
JPanel panel = new JPanel();
panel.setLayout(new GridLayout(1,4,10,0));
registerButton = new JButton("注册");
backButton = new JButton("返回");
panel.add(new JPanel());
panel.add(registerButton);
panel.add(backButton);
panel.add(new JPanel());
return panel;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
view.RegisterFrame registerFrame = new view.RegisterFrame();
registerFrame.setVisible(true);
});
}
}

225
src/view/UserPanel.java Normal file
View File

@@ -0,0 +1,225 @@
package view;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Vector;
import backend.dao.UserDao;
import backend.model.User;
import backend.service.AuthService;
public class UserPanel extends JPanel {
private AuthService authService = new AuthService();
private static Vector<String> columNames = new Vector<>();
private DefaultTableModel model;
private JTable table;
private JScrollPane scrollPane;
private Vector<Vector<String>> tableData;
//按钮界面
private JButton addButton;
private JButton deleteButton;
private JButton editButton;
//搜索界面
private JComboBox roleComboBox;
private JTextField keyTextField;
private JButton queryButton;
// 颜色常量定义
private static final Color PRIMARY_COLOR = new Color(70, 130, 180); // 钢蓝色
private static final Color BACKGROUND_COLOR = new Color(248, 249, 250); // 浅灰色背景
private static final Color BORDER_COLOR = new Color(220, 220, 220); // 边框颜色
private static final Color HIGHLIGHT_COLOR = new Color(255, 255, 204); // 高亮背景
static {
columNames.add("ID");
columNames.add("昵称");
columNames.add("权限");
columNames.add("邮箱");
columNames.add("创建时间");
}
public void initListener(){
queryButton.addActionListener(e->{
Integer r = roleComboBox.getSelectedIndex()==0? null:roleComboBox.getSelectedIndex();
String role;
if(r==null)
role=null;
else if(r==1)
role="user";
else role="admin";
String key = keyTextField.getText();
//清楚已有数据
model.setRowCount(0);
//条件查询
tableData = authService.getByCondition(role,key);
//刷新表格
refreshData();
});
deleteButton.addActionListener(e->{
if(MainFrame.role.equals("user"))
return;
int row = table.getSelectedRow();
if(row!=-1){
int id = Integer.valueOf(tableData.get(row).get(0));
String word = tableData.get(row).get(1);
int option = JOptionPane.showConfirmDialog(this,"确认删除"+word+"吗?","提示",JOptionPane.YES_NO_CANCEL_OPTION);
if(option == JOptionPane.YES_OPTION){
authService.deleteUser(id);
model.removeRow(row);
}
}
});
//添加事件:打开对话框
addButton.addActionListener(e->{
if(MainFrame.role.equals("user"))
return;
new EditUserDialog(0,null);
});
editButton.addActionListener(e->{
if(MainFrame.role.equals("user"))
return;
int row = table.getSelectedRow();
if(row>=0)
openEditDialog(row);
});
//双击某行弹出修改对话框
table.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if(MainFrame.role.equals("user"))
return;
if(e.getClickCount()==2){
int row = table.getSelectedRow();
openEditDialog(row);
}
}
});
}
private void initView(){
setLayout(new BorderLayout());
setBackground(BACKGROUND_COLOR);
// 创建顶部工具栏
JPanel topPanel = new JPanel(new BorderLayout());
topPanel.setBackground(PRIMARY_COLOR);
topPanel.setBorder(BorderFactory.createEmptyBorder(5, 10, 5, 10));
JLabel titleLabel = new JLabel("用户管理");
titleLabel.setFont(new Font("微软雅黑", Font.BOLD, 16));
titleLabel.setForeground(Color.WHITE);
topPanel.add(titleLabel, BorderLayout.WEST);
add(topPanel, BorderLayout.NORTH);
// 创建中央内容面板
JPanel centerPanel = new JPanel();
centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS));
centerPanel.setBackground(BACKGROUND_COLOR);
centerPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
// 1.按钮界面
JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
buttonPanel.setBackground(BACKGROUND_COLOR);
addButton = new JButton("添加");
deleteButton = new JButton("删除");
editButton = new JButton("修改");
// 设置按钮样式
setButtonStyle(addButton);
setButtonStyle(deleteButton);
setButtonStyle(editButton);
buttonPanel.add(addButton);
buttonPanel.add(deleteButton);
buttonPanel.add(editButton);
centerPanel.add(buttonPanel);
centerPanel.add(Box.createVerticalStrut(10));
// 2.搜索界面
JPanel queryPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 10, 5));
queryPanel.setBackground(BACKGROUND_COLOR);
roleComboBox = new JComboBox<String>(new String[]{"全部","user","admin"});
keyTextField = new JTextField(15);
queryButton = new JButton("查询");
// 设置查询按钮样式
setButtonStyle(queryButton);
queryPanel.add(new JLabel("角色:"));
queryPanel.add(roleComboBox);
queryPanel.add(new JLabel("关键词:"));
queryPanel.add(keyTextField);
queryPanel.add(queryButton);
centerPanel.add(queryPanel);
centerPanel.add(Box.createVerticalStrut(10));
// 3.表格界面
model = new DefaultTableModel(){
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
table = new JTable(model);
table.setFont(new Font("微软雅黑", Font.PLAIN, 12));
table.getTableHeader().setFont(new Font("微软雅黑", Font.BOLD, 13));
table.getTableHeader().setBackground(PRIMARY_COLOR);
table.getTableHeader().setForeground(Color.WHITE);
table.setSelectionBackground(new Color(176, 224, 230));
table.setRowHeight(25);
scrollPane = new JScrollPane(table);
scrollPane.setPreferredSize(new Dimension(700, 400));
scrollPane.setBorder(BorderFactory.createLineBorder(BORDER_COLOR, 1));
centerPanel.add(scrollPane);
add(centerPanel, BorderLayout.CENTER);
tableData = authService.getAll();
//刷新数据
refreshData();
}
// 设置按钮样式
private void setButtonStyle(JButton button) {
button.setFont(new Font("微软雅黑", Font.BOLD, 14));
button.setPreferredSize(new Dimension(80, 30));
button.setBackground(PRIMARY_COLOR);
button.setForeground(Color.WHITE);
button.setFocusPainted(false);
button.setBorder(BorderFactory.createRaisedBevelBorder());
}
private void openEditDialog(int row){
Vector<String> data = tableData.get(row);
UserDao userDao = new UserDao();
User userPo = userDao.findById(Integer.parseInt(data.get(0)));
new EditUserDialog(1, userPo);
//修改成功后刷新并定位修改位置
tableData = authService.getAll();
refreshData();
table.setRowSelectionInterval(row,row);
scrollPane.getVerticalScrollBar().setValue(row*table.getRowHeight());
scrollPane.getHorizontalScrollBar().setValue(0);
scrollPane.revalidate();
}
public UserPanel(){
initView();
initListener();
}
private void refreshData(){
model.setDataVector(tableData,columNames);
model.fireTableDataChanged();
}
}