diff --git a/HRS/.classpath b/HRS/.classpath
new file mode 100644
index 0000000..cd67f69
--- /dev/null
+++ b/HRS/.classpath
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HRS/.project b/HRS/.project
new file mode 100644
index 0000000..91242a4
--- /dev/null
+++ b/HRS/.project
@@ -0,0 +1,31 @@
+
+
+ HRS
+
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.wst.common.project.facet.core.builder
+
+
+
+
+ org.eclipse.wst.validation.validationbuilder
+
+
+
+
+
+ org.eclipse.jem.workbench.JavaEMFNature
+ org.eclipse.wst.common.modulecore.ModuleCoreNature
+ org.eclipse.wst.common.project.facet.core.nature
+ org.eclipse.jdt.core.javanature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/HRS/.settings/.jsdtscope b/HRS/.settings/.jsdtscope
new file mode 100644
index 0000000..92e666d
--- /dev/null
+++ b/HRS/.settings/.jsdtscope
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HRS/.settings/org.eclipse.jdt.core.prefs b/HRS/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..0c68a61
--- /dev/null
+++ b/HRS/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
+org.eclipse.jdt.core.compiler.compliance=1.8
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.8
diff --git a/HRS/.settings/org.eclipse.wst.common.component b/HRS/.settings/org.eclipse.wst.common.component
new file mode 100644
index 0000000..b729e7b
--- /dev/null
+++ b/HRS/.settings/org.eclipse.wst.common.component
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/HRS/.settings/org.eclipse.wst.common.project.facet.core.xml b/HRS/.settings/org.eclipse.wst.common.project.facet.core.xml
new file mode 100644
index 0000000..95377b2
--- /dev/null
+++ b/HRS/.settings/org.eclipse.wst.common.project.facet.core.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/HRS/.settings/org.eclipse.wst.jsdt.ui.superType.container b/HRS/.settings/org.eclipse.wst.jsdt.ui.superType.container
new file mode 100644
index 0000000..3bd5d0a
--- /dev/null
+++ b/HRS/.settings/org.eclipse.wst.jsdt.ui.superType.container
@@ -0,0 +1 @@
+org.eclipse.wst.jsdt.launching.baseBrowserLibrary
\ No newline at end of file
diff --git a/HRS/.settings/org.eclipse.wst.jsdt.ui.superType.name b/HRS/.settings/org.eclipse.wst.jsdt.ui.superType.name
new file mode 100644
index 0000000..05bd71b
--- /dev/null
+++ b/HRS/.settings/org.eclipse.wst.jsdt.ui.superType.name
@@ -0,0 +1 @@
+Window
\ No newline at end of file
diff --git a/HRS/build/classes/com/hrs/controller/admin/AdminHouseAuditController.class b/HRS/build/classes/com/hrs/controller/admin/AdminHouseAuditController.class
new file mode 100644
index 0000000..36e7701
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/admin/AdminHouseAuditController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/admin/AdminHouseController.class b/HRS/build/classes/com/hrs/controller/admin/AdminHouseController.class
new file mode 100644
index 0000000..a20f694
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/admin/AdminHouseController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/admin/AdminHouseOfflineController.class b/HRS/build/classes/com/hrs/controller/admin/AdminHouseOfflineController.class
new file mode 100644
index 0000000..ec952bd
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/admin/AdminHouseOfflineController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/admin/AdminHouseOnlineController.class b/HRS/build/classes/com/hrs/controller/admin/AdminHouseOnlineController.class
new file mode 100644
index 0000000..7e79d26
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/admin/AdminHouseOnlineController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/admin/AdminOrderController.class b/HRS/build/classes/com/hrs/controller/admin/AdminOrderController.class
new file mode 100644
index 0000000..3196fd8
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/admin/AdminOrderController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/admin/AdminStatisticsController.class b/HRS/build/classes/com/hrs/controller/admin/AdminStatisticsController.class
new file mode 100644
index 0000000..caeaae8
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/admin/AdminStatisticsController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/admin/AdminUserController.class b/HRS/build/classes/com/hrs/controller/admin/AdminUserController.class
new file mode 100644
index 0000000..ab09e95
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/admin/AdminUserController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/admin/AdminUserDeleteController.class b/HRS/build/classes/com/hrs/controller/admin/AdminUserDeleteController.class
new file mode 100644
index 0000000..cb491db
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/admin/AdminUserDeleteController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/admin/AdminUserStatusController.class b/HRS/build/classes/com/hrs/controller/admin/AdminUserStatusController.class
new file mode 100644
index 0000000..787f01e
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/admin/AdminUserStatusController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/landlord/HouseAddController.class b/HRS/build/classes/com/hrs/controller/landlord/HouseAddController.class
new file mode 100644
index 0000000..a26c87e
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/landlord/HouseAddController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/landlord/HouseDeleteController.class b/HRS/build/classes/com/hrs/controller/landlord/HouseDeleteController.class
new file mode 100644
index 0000000..3904fde
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/landlord/HouseDeleteController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/landlord/HouseEditController.class b/HRS/build/classes/com/hrs/controller/landlord/HouseEditController.class
new file mode 100644
index 0000000..58e9354
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/landlord/HouseEditController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/landlord/HouseListController.class b/HRS/build/classes/com/hrs/controller/landlord/HouseListController.class
new file mode 100644
index 0000000..bf27aaf
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/landlord/HouseListController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/landlord/OrderConfirmController.class b/HRS/build/classes/com/hrs/controller/landlord/OrderConfirmController.class
new file mode 100644
index 0000000..7ef7bbd
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/landlord/OrderConfirmController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/landlord/OrderManageController.class b/HRS/build/classes/com/hrs/controller/landlord/OrderManageController.class
new file mode 100644
index 0000000..5f9c775
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/landlord/OrderManageController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/landlord/ReservationHandleController.class b/HRS/build/classes/com/hrs/controller/landlord/ReservationHandleController.class
new file mode 100644
index 0000000..aa2f8a7
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/landlord/ReservationHandleController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/landlord/ReservationManageController.class b/HRS/build/classes/com/hrs/controller/landlord/ReservationManageController.class
new file mode 100644
index 0000000..547d6a5
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/landlord/ReservationManageController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/CollectionAddController.class b/HRS/build/classes/com/hrs/controller/user/CollectionAddController.class
new file mode 100644
index 0000000..a28e53c
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/CollectionAddController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/CollectionDeleteController.class b/HRS/build/classes/com/hrs/controller/user/CollectionDeleteController.class
new file mode 100644
index 0000000..8bea522
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/CollectionDeleteController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/CollectionListController.class b/HRS/build/classes/com/hrs/controller/user/CollectionListController.class
new file mode 100644
index 0000000..e9223b7
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/CollectionListController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/HouseDetailController.class b/HRS/build/classes/com/hrs/controller/user/HouseDetailController.class
new file mode 100644
index 0000000..ea2e9ba
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/HouseDetailController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/HouseListController.class b/HRS/build/classes/com/hrs/controller/user/HouseListController.class
new file mode 100644
index 0000000..cdfffdf
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/HouseListController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/LoginController.class b/HRS/build/classes/com/hrs/controller/user/LoginController.class
new file mode 100644
index 0000000..adcc2eb
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/LoginController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/LogoutController.class b/HRS/build/classes/com/hrs/controller/user/LogoutController.class
new file mode 100644
index 0000000..8db8c65
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/LogoutController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/OrderCancelController.class b/HRS/build/classes/com/hrs/controller/user/OrderCancelController.class
new file mode 100644
index 0000000..6137ee3
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/OrderCancelController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/OrderCreateController.class b/HRS/build/classes/com/hrs/controller/user/OrderCreateController.class
new file mode 100644
index 0000000..ac69603
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/OrderCreateController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/OrderListController.class b/HRS/build/classes/com/hrs/controller/user/OrderListController.class
new file mode 100644
index 0000000..2627a2f
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/OrderListController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/OrderPayController.class b/HRS/build/classes/com/hrs/controller/user/OrderPayController.class
new file mode 100644
index 0000000..7eb4206
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/OrderPayController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/RegisterController.class b/HRS/build/classes/com/hrs/controller/user/RegisterController.class
new file mode 100644
index 0000000..cb634f2
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/RegisterController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/ReservationAddController.class b/HRS/build/classes/com/hrs/controller/user/ReservationAddController.class
new file mode 100644
index 0000000..2e4f66d
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/ReservationAddController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/ReservationCancelController.class b/HRS/build/classes/com/hrs/controller/user/ReservationCancelController.class
new file mode 100644
index 0000000..b1ac4c5
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/ReservationCancelController.class differ
diff --git a/HRS/build/classes/com/hrs/controller/user/ReservationListController.class b/HRS/build/classes/com/hrs/controller/user/ReservationListController.class
new file mode 100644
index 0000000..a8c9e3e
Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/ReservationListController.class differ
diff --git a/HRS/build/classes/com/hrs/dao/CollectionDao.class b/HRS/build/classes/com/hrs/dao/CollectionDao.class
new file mode 100644
index 0000000..c9893d1
Binary files /dev/null and b/HRS/build/classes/com/hrs/dao/CollectionDao.class differ
diff --git a/HRS/build/classes/com/hrs/dao/HouseDao.class b/HRS/build/classes/com/hrs/dao/HouseDao.class
new file mode 100644
index 0000000..095f411
Binary files /dev/null and b/HRS/build/classes/com/hrs/dao/HouseDao.class differ
diff --git a/HRS/build/classes/com/hrs/dao/OrderDao.class b/HRS/build/classes/com/hrs/dao/OrderDao.class
new file mode 100644
index 0000000..7844e4c
Binary files /dev/null and b/HRS/build/classes/com/hrs/dao/OrderDao.class differ
diff --git a/HRS/build/classes/com/hrs/dao/ReservationDao.class b/HRS/build/classes/com/hrs/dao/ReservationDao.class
new file mode 100644
index 0000000..956aabc
Binary files /dev/null and b/HRS/build/classes/com/hrs/dao/ReservationDao.class differ
diff --git a/HRS/build/classes/com/hrs/dao/UserDao.class b/HRS/build/classes/com/hrs/dao/UserDao.class
new file mode 100644
index 0000000..8f0a25e
Binary files /dev/null and b/HRS/build/classes/com/hrs/dao/UserDao.class differ
diff --git a/HRS/build/classes/com/hrs/dao/impl/CollectionDaoImpl.class b/HRS/build/classes/com/hrs/dao/impl/CollectionDaoImpl.class
new file mode 100644
index 0000000..a3a3eda
Binary files /dev/null and b/HRS/build/classes/com/hrs/dao/impl/CollectionDaoImpl.class differ
diff --git a/HRS/build/classes/com/hrs/dao/impl/HouseDaoImpl.class b/HRS/build/classes/com/hrs/dao/impl/HouseDaoImpl.class
new file mode 100644
index 0000000..8edb1a5
Binary files /dev/null and b/HRS/build/classes/com/hrs/dao/impl/HouseDaoImpl.class differ
diff --git a/HRS/build/classes/com/hrs/dao/impl/OrderDaoImpl.class b/HRS/build/classes/com/hrs/dao/impl/OrderDaoImpl.class
new file mode 100644
index 0000000..5826718
Binary files /dev/null and b/HRS/build/classes/com/hrs/dao/impl/OrderDaoImpl.class differ
diff --git a/HRS/build/classes/com/hrs/dao/impl/ReservationDaoImpl.class b/HRS/build/classes/com/hrs/dao/impl/ReservationDaoImpl.class
new file mode 100644
index 0000000..b907333
Binary files /dev/null and b/HRS/build/classes/com/hrs/dao/impl/ReservationDaoImpl.class differ
diff --git a/HRS/build/classes/com/hrs/dao/impl/UserDaoImpl.class b/HRS/build/classes/com/hrs/dao/impl/UserDaoImpl.class
new file mode 100644
index 0000000..f2f80fd
Binary files /dev/null and b/HRS/build/classes/com/hrs/dao/impl/UserDaoImpl.class differ
diff --git a/HRS/build/classes/com/hrs/filter/EncodingFilter.class b/HRS/build/classes/com/hrs/filter/EncodingFilter.class
new file mode 100644
index 0000000..ab2fd90
Binary files /dev/null and b/HRS/build/classes/com/hrs/filter/EncodingFilter.class differ
diff --git a/HRS/build/classes/com/hrs/filter/LoginFilter.class b/HRS/build/classes/com/hrs/filter/LoginFilter.class
new file mode 100644
index 0000000..e2b10e2
Binary files /dev/null and b/HRS/build/classes/com/hrs/filter/LoginFilter.class differ
diff --git a/HRS/build/classes/com/hrs/model/entity/Collection.class b/HRS/build/classes/com/hrs/model/entity/Collection.class
new file mode 100644
index 0000000..5b47bdc
Binary files /dev/null and b/HRS/build/classes/com/hrs/model/entity/Collection.class differ
diff --git a/HRS/build/classes/com/hrs/model/entity/House.class b/HRS/build/classes/com/hrs/model/entity/House.class
new file mode 100644
index 0000000..1b65370
Binary files /dev/null and b/HRS/build/classes/com/hrs/model/entity/House.class differ
diff --git a/HRS/build/classes/com/hrs/model/entity/Order.class b/HRS/build/classes/com/hrs/model/entity/Order.class
new file mode 100644
index 0000000..56e71e9
Binary files /dev/null and b/HRS/build/classes/com/hrs/model/entity/Order.class differ
diff --git a/HRS/build/classes/com/hrs/model/entity/Reservation.class b/HRS/build/classes/com/hrs/model/entity/Reservation.class
new file mode 100644
index 0000000..7332aa9
Binary files /dev/null and b/HRS/build/classes/com/hrs/model/entity/Reservation.class differ
diff --git a/HRS/build/classes/com/hrs/model/entity/User.class b/HRS/build/classes/com/hrs/model/entity/User.class
new file mode 100644
index 0000000..f5abe5e
Binary files /dev/null and b/HRS/build/classes/com/hrs/model/entity/User.class differ
diff --git a/HRS/build/classes/com/hrs/service/CollectionService$CollectionResult.class b/HRS/build/classes/com/hrs/service/CollectionService$CollectionResult.class
new file mode 100644
index 0000000..4612db1
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/CollectionService$CollectionResult.class differ
diff --git a/HRS/build/classes/com/hrs/service/CollectionService.class b/HRS/build/classes/com/hrs/service/CollectionService.class
new file mode 100644
index 0000000..5ac1458
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/CollectionService.class differ
diff --git a/HRS/build/classes/com/hrs/service/HouseService$AddHouseResult.class b/HRS/build/classes/com/hrs/service/HouseService$AddHouseResult.class
new file mode 100644
index 0000000..ef55154
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/HouseService$AddHouseResult.class differ
diff --git a/HRS/build/classes/com/hrs/service/HouseService$UpdateHouseResult.class b/HRS/build/classes/com/hrs/service/HouseService$UpdateHouseResult.class
new file mode 100644
index 0000000..d6ecf86
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/HouseService$UpdateHouseResult.class differ
diff --git a/HRS/build/classes/com/hrs/service/HouseService.class b/HRS/build/classes/com/hrs/service/HouseService.class
new file mode 100644
index 0000000..48ea8f5
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/HouseService.class differ
diff --git a/HRS/build/classes/com/hrs/service/OrderService$CreateOrderResult.class b/HRS/build/classes/com/hrs/service/OrderService$CreateOrderResult.class
new file mode 100644
index 0000000..da78cc0
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/OrderService$CreateOrderResult.class differ
diff --git a/HRS/build/classes/com/hrs/service/OrderService.class b/HRS/build/classes/com/hrs/service/OrderService.class
new file mode 100644
index 0000000..cf454b6
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/OrderService.class differ
diff --git a/HRS/build/classes/com/hrs/service/ReservationService$ReservationResult.class b/HRS/build/classes/com/hrs/service/ReservationService$ReservationResult.class
new file mode 100644
index 0000000..cda3778
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/ReservationService$ReservationResult.class differ
diff --git a/HRS/build/classes/com/hrs/service/ReservationService.class b/HRS/build/classes/com/hrs/service/ReservationService.class
new file mode 100644
index 0000000..85f3dca
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/ReservationService.class differ
diff --git a/HRS/build/classes/com/hrs/service/UserService$RegisterResult.class b/HRS/build/classes/com/hrs/service/UserService$RegisterResult.class
new file mode 100644
index 0000000..5ca8793
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/UserService$RegisterResult.class differ
diff --git a/HRS/build/classes/com/hrs/service/UserService.class b/HRS/build/classes/com/hrs/service/UserService.class
new file mode 100644
index 0000000..68cf1c3
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/UserService.class differ
diff --git a/HRS/build/classes/com/hrs/service/impl/CollectionServiceImpl.class b/HRS/build/classes/com/hrs/service/impl/CollectionServiceImpl.class
new file mode 100644
index 0000000..246d671
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/impl/CollectionServiceImpl.class differ
diff --git a/HRS/build/classes/com/hrs/service/impl/HouseServiceImpl.class b/HRS/build/classes/com/hrs/service/impl/HouseServiceImpl.class
new file mode 100644
index 0000000..a1cd4ae
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/impl/HouseServiceImpl.class differ
diff --git a/HRS/build/classes/com/hrs/service/impl/OrderServiceImpl.class b/HRS/build/classes/com/hrs/service/impl/OrderServiceImpl.class
new file mode 100644
index 0000000..7cfbf65
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/impl/OrderServiceImpl.class differ
diff --git a/HRS/build/classes/com/hrs/service/impl/ReservationServiceImpl.class b/HRS/build/classes/com/hrs/service/impl/ReservationServiceImpl.class
new file mode 100644
index 0000000..41fe4dc
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/impl/ReservationServiceImpl.class differ
diff --git a/HRS/build/classes/com/hrs/service/impl/UserServiceImpl.class b/HRS/build/classes/com/hrs/service/impl/UserServiceImpl.class
new file mode 100644
index 0000000..a0512e1
Binary files /dev/null and b/HRS/build/classes/com/hrs/service/impl/UserServiceImpl.class differ
diff --git a/HRS/build/classes/com/hrs/util/DBUtil.class b/HRS/build/classes/com/hrs/util/DBUtil.class
new file mode 100644
index 0000000..20ddba1
Binary files /dev/null and b/HRS/build/classes/com/hrs/util/DBUtil.class differ
diff --git a/HRS/build/classes/com/hrs/util/ImageUploadUtil.class b/HRS/build/classes/com/hrs/util/ImageUploadUtil.class
new file mode 100644
index 0000000..8ef142b
Binary files /dev/null and b/HRS/build/classes/com/hrs/util/ImageUploadUtil.class differ
diff --git a/HRS/build/classes/com/hrs/util/MD5Util.class b/HRS/build/classes/com/hrs/util/MD5Util.class
new file mode 100644
index 0000000..b6d559b
Binary files /dev/null and b/HRS/build/classes/com/hrs/util/MD5Util.class differ
diff --git a/HRS/sql/hrs_init.sql b/HRS/sql/hrs_init.sql
new file mode 100644
index 0000000..0d6f4c6
--- /dev/null
+++ b/HRS/sql/hrs_init.sql
@@ -0,0 +1,170 @@
+/*
+ Navicat Premium Dump SQL
+
+ Source Server : 本机
+ Source Server Type : MySQL
+ Source Server Version : 90500 (9.5.0)
+ Source Host : localhost:3306
+ Source Schema : hrs
+
+ Target Server Type : MySQL
+ Target Server Version : 90500 (9.5.0)
+ File Encoding : 65001
+
+ Date: 10/03/2026 22:26:27
+*/
+
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- Table structure for hrs_collection
+-- ----------------------------
+DROP TABLE IF EXISTS `hrs_collection`;
+CREATE TABLE `hrs_collection` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `tenant_id` bigint NOT NULL COMMENT '租客ID(关联hrs_user.id)',
+ `house_id` bigint NOT NULL COMMENT '房源ID(关联hrs_house.id)',
+ `collect_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '收藏时间',
+ `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_tenant_house`(`tenant_id` ASC, `house_id` ASC) USING BTREE COMMENT '避免重复收藏',
+ INDEX `idx_collect_tenant_id`(`tenant_id` ASC) USING BTREE COMMENT '租客ID索引',
+ INDEX `idx_collect_house_id`(`house_id` ASC) USING BTREE COMMENT '房源ID索引',
+ CONSTRAINT `fk_collect_house` FOREIGN KEY (`house_id`) REFERENCES `hrs_house` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
+ CONSTRAINT `fk_collect_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `hrs_user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '房源收藏表(外键:fk_collect_tenant关联租客、fk_collect_house关联房源)' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of hrs_collection
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for hrs_house
+-- ----------------------------
+DROP TABLE IF EXISTS `hrs_house`;
+CREATE TABLE `hrs_house` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `landlord_id` bigint NOT NULL COMMENT '房东ID(关联hrs_user.id)',
+ `house_no` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '房源编号',
+ `title` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '房源标题',
+ `area` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '房源区域(如朝阳区)',
+ `address` varchar(200) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '详细地址',
+ `house_type` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '户型(如一室一厅)',
+ `rent_price` decimal(10, 2) NOT NULL COMMENT '月租金(元)',
+ `rent_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '0' COMMENT '租赁类型:0-整租;1-合租',
+ `facility` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '配套设施(如空调、洗衣机)',
+ `description` text CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL COMMENT '房源描述',
+ `img_url` varchar(1000) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '房源图片路径(多图逗号分隔)',
+ `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '房源状态:0-待审核;1-已上架;2-已下架;3-违规',
+ `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人',
+ `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_house_no`(`house_no` ASC) USING BTREE COMMENT '房源编号唯一',
+ INDEX `idx_landlord_id`(`landlord_id` ASC) USING BTREE COMMENT '房东ID索引',
+ INDEX `idx_area`(`area` ASC) USING BTREE COMMENT '区域索引',
+ INDEX `idx_house_status`(`status` ASC) USING BTREE COMMENT '房源状态索引',
+ CONSTRAINT `fk_house_landlord` FOREIGN KEY (`landlord_id`) REFERENCES `hrs_user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '房源信息表(外键fk_house_landlord关联房东用户表hrs_user.id)' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of hrs_house
+-- ----------------------------
+INSERT INTO `hrs_house` VALUES (1, 2, 'H20260309001', '朝阳小区一室一厅', '朝阳区', '朝阳小区1号楼1单元101', '一室一厅', 2500.00, '0', NULL, NULL, NULL, '1', NULL, '2026-03-10 15:32:31', NULL, '2026-03-10 15:32:31');
+
+-- ----------------------------
+-- Table structure for hrs_order
+-- ----------------------------
+DROP TABLE IF EXISTS `hrs_order`;
+CREATE TABLE `hrs_order` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `tenant_id` bigint NOT NULL COMMENT '租客ID(关联hrs_user.id)',
+ `house_id` bigint NOT NULL COMMENT '房源ID(关联hrs_house.id)',
+ `order_no` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '订单编号',
+ `rent_start_time` datetime NOT NULL COMMENT '租赁开始时间',
+ `rent_end_time` datetime NOT NULL COMMENT '租赁结束时间',
+ `total_rent` decimal(10, 2) NOT NULL COMMENT '总租金(元)',
+ `pay_status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '支付状态:0-待支付;1-已支付;2-已退款',
+ `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '订单状态:0-待签约;1-已签约;2-已结束;3-已取消',
+ `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人',
+ `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_order_no`(`order_no` ASC) USING BTREE COMMENT '订单编号唯一',
+ INDEX `idx_order_tenant_id`(`tenant_id` ASC) USING BTREE COMMENT '租客ID索引',
+ INDEX `idx_order_house_id`(`house_id` ASC) USING BTREE COMMENT '房源ID索引',
+ INDEX `idx_pay_status`(`pay_status` ASC) USING BTREE COMMENT '支付状态索引',
+ INDEX `idx_order_status`(`status` ASC) USING BTREE COMMENT '订单状态索引',
+ CONSTRAINT `fk_order_house` FOREIGN KEY (`house_id`) REFERENCES `hrs_house` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
+ CONSTRAINT `fk_order_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `hrs_user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '租房订单表(外键:fk_order_tenant关联租客、fk_order_house关联房源)' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of hrs_order
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for hrs_reservation
+-- ----------------------------
+DROP TABLE IF EXISTS `hrs_reservation`;
+CREATE TABLE `hrs_reservation` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `tenant_id` bigint NOT NULL COMMENT '租客ID(关联hrs_user.id)',
+ `house_id` bigint NOT NULL COMMENT '房源ID(关联hrs_house.id)',
+ `landlord_id` bigint NOT NULL COMMENT '房东ID(关联hrs_user.id)',
+ `reserve_time` datetime NOT NULL COMMENT '预约看房时间',
+ `remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '租客备注',
+ `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '预约状态:0-待确认;1-已确认;2-已取消;3-已完成',
+ `handle_time` datetime NULL DEFAULT NULL COMMENT '房东处理时间',
+ `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人',
+ `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ INDEX `idx_tenant_id`(`tenant_id` ASC) USING BTREE COMMENT '租客ID索引',
+ INDEX `idx_house_id`(`house_id` ASC) USING BTREE COMMENT '房源ID索引',
+ INDEX `idx_reserve_landlord_id`(`landlord_id` ASC) USING BTREE COMMENT '房东ID索引',
+ INDEX `idx_reserve_status`(`status` ASC) USING BTREE COMMENT '预约状态索引',
+ CONSTRAINT `fk_reserve_house` FOREIGN KEY (`house_id`) REFERENCES `hrs_house` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
+ CONSTRAINT `fk_reserve_landlord` FOREIGN KEY (`landlord_id`) REFERENCES `hrs_user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT,
+ CONSTRAINT `fk_reserve_tenant` FOREIGN KEY (`tenant_id`) REFERENCES `hrs_user` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '预约看房记录表(外键:fk_reserve_tenant关联租客、fk_reserve_house关联房源、fk_reserve_landlord关联房东)' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of hrs_reservation
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for hrs_user
+-- ----------------------------
+DROP TABLE IF EXISTS `hrs_user`;
+CREATE TABLE `hrs_user` (
+ `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键ID',
+ `user_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '用户名(登录账号)',
+ `password` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '密码(加密存储)',
+ `real_name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '真实姓名',
+ `phone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '手机号',
+ `id_card` varchar(18) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '身份证号',
+ `role_type` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '角色类型:0-租客;1-房东;2-管理员',
+ `status` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '0' COMMENT '账号状态:0-未认证;1-已认证;2-禁用',
+ `create_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '创建人',
+ `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+ `update_by` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '更新人',
+ `update_time` datetime NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE,
+ UNIQUE INDEX `uk_user_name`(`user_name` ASC) USING BTREE COMMENT '用户名唯一',
+ UNIQUE INDEX `uk_phone`(`phone` ASC) USING BTREE COMMENT '手机号唯一',
+ INDEX `idx_role_type`(`role_type` ASC) USING BTREE COMMENT '角色类型索引'
+) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '基础用户信息表' ROW_FORMAT = Dynamic;
+
+-- ----------------------------
+-- Records of hrs_user
+-- ----------------------------
+INSERT INTO `hrs_user` VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', '系统管理员', '13800138000', NULL, '2', '1', NULL, '2026-03-10 15:32:31', NULL, '2026-03-10 15:32:31');
+INSERT INTO `hrs_user` VALUES (2, 'landlord01', 'e10adc3949ba59abbe56e057f20f883e', '张三', '13800138001', NULL, '1', '1', NULL, '2026-03-10 15:32:31', NULL, '2026-03-10 15:32:31');
+
+SET FOREIGN_KEY_CHECKS = 1;
diff --git a/HRS/src/com/hrs/controller/admin/AdminHouseAuditController.java b/HRS/src/com/hrs/controller/admin/AdminHouseAuditController.java
new file mode 100644
index 0000000..b67eb4a
--- /dev/null
+++ b/HRS/src/com/hrs/controller/admin/AdminHouseAuditController.java
@@ -0,0 +1,76 @@
+package com.hrs.controller.admin;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: AdminHouseAuditController.java
+* @Description: 管理员房源审核操作控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:48:49
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+
+@WebServlet("/admin/house/audit")
+public class AdminHouseAuditController extends HttpServlet {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"2".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ String houseIdStr = request.getParameter("id");
+ String action = request.getParameter("action");
+
+ if (houseIdStr == null || action == null) {
+ response.sendRedirect(request.getContextPath() + "/admin/house/list");
+ return;
+ }
+ Long houseId = Long.parseLong(houseIdStr);
+ String status = "approve".equals(action) ? "1" : "3"; // 1-已上架,3-违规/拒绝
+
+ boolean success = houseDao.updateStatus(houseId, status);
+
+ if (success) {
+ String msg = "approve".equals(action) ? "房源审核通过,已上架" : "房源审核拒绝";
+ String encodedMsg = URLEncoder.encode(msg, "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/admin/house/list?msg=" + encodedMsg);
+ } else {
+ String encodedError = URLEncoder.encode("操作失败", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/admin/house/list?error=" + encodedError);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/admin/AdminHouseController.java b/HRS/src/com/hrs/controller/admin/AdminHouseController.java
new file mode 100644
index 0000000..bdd3960
--- /dev/null
+++ b/HRS/src/com/hrs/controller/admin/AdminHouseController.java
@@ -0,0 +1,68 @@
+package com.hrs.controller.admin;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.model.entity.House;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: AdminHouseController.java
+* @Description: 管理员房源审核控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:51:26
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/admin/house/list")
+public class AdminHouseController extends HttpServlet {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"2".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ // 获取不同状态的房源
+ List pendingList = houseDao.findPendingHouses();
+ List publishedList = houseDao.findPublishedHousesForAdmin();
+ List offlineList = houseDao.findOfflineHouses();
+
+ request.setAttribute("pendingList", pendingList);
+ request.setAttribute("publishedList", publishedList);
+ request.setAttribute("offlineList", offlineList);
+ request.setAttribute("pendingCount", pendingList.size());
+ request.setAttribute("publishedCount", publishedList.size());
+ request.setAttribute("offlineCount", offlineList.size());
+ request.setAttribute("loginUser", loginUser);
+
+ request.getRequestDispatcher("/jsp/admin/house_list.jsp").forward(request, response);
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/admin/AdminHouseOfflineController.java b/HRS/src/com/hrs/controller/admin/AdminHouseOfflineController.java
new file mode 100644
index 0000000..9d6ec9b
--- /dev/null
+++ b/HRS/src/com/hrs/controller/admin/AdminHouseOfflineController.java
@@ -0,0 +1,69 @@
+package com.hrs.controller.admin;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: AdminHouseOfflineController.java
+* @Description: 管理员下架房源控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:52:08
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/admin/house/offline")
+public class AdminHouseOfflineController extends HttpServlet {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"2".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ String houseIdStr = request.getParameter("id");
+ if (houseIdStr == null) {
+ response.sendRedirect(request.getContextPath() + "/admin/house/list");
+ return;
+ }
+
+ Long houseId = Long.parseLong(houseIdStr);
+ boolean success = houseDao.updateStatus(houseId, "2"); // 2-已下架
+
+ if (success) {
+ String encodedMsg = URLEncoder.encode("房源已下架", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/admin/house/list?msg=" + encodedMsg);
+ } else {
+ String encodedError = URLEncoder.encode("操作失败", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/admin/house/list?error=" + encodedError);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/admin/AdminHouseOnlineController.java b/HRS/src/com/hrs/controller/admin/AdminHouseOnlineController.java
new file mode 100644
index 0000000..bd1278b
--- /dev/null
+++ b/HRS/src/com/hrs/controller/admin/AdminHouseOnlineController.java
@@ -0,0 +1,69 @@
+package com.hrs.controller.admin;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: AdminHouseOnlineController.java
+* @Description: 管理员重新上架房源控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:53:08
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/admin/house/online")
+public class AdminHouseOnlineController extends HttpServlet {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"2".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ String houseIdStr = request.getParameter("id");
+ if (houseIdStr == null) {
+ response.sendRedirect(request.getContextPath() + "/admin/house/list");
+ return;
+ }
+
+ Long houseId = Long.parseLong(houseIdStr);
+ boolean success = houseDao.updateStatus(houseId, "1"); // 1-已上架
+
+ if (success) {
+ String encodedMsg = URLEncoder.encode("房源已重新上架", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/admin/house/list?msg=" + encodedMsg);
+ } else {
+ String encodedError = URLEncoder.encode("操作失败", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/admin/house/list?error=" + encodedError);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/admin/AdminOrderController.java b/HRS/src/com/hrs/controller/admin/AdminOrderController.java
new file mode 100644
index 0000000..a4ed878
--- /dev/null
+++ b/HRS/src/com/hrs/controller/admin/AdminOrderController.java
@@ -0,0 +1,61 @@
+package com.hrs.controller.admin;
+
+import com.hrs.dao.OrderDao;
+import com.hrs.dao.impl.OrderDaoImpl;
+import com.hrs.model.entity.Order;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: AdminOrderController.java
+* @Description: 管理员订单管理控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:53:35
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/admin/order/list")
+public class AdminOrderController extends HttpServlet {
+
+ private OrderDao orderDao = new OrderDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"2".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ List orderList = orderDao.findAll();
+
+ request.setAttribute("orderList", orderList);
+ request.setAttribute("totalCount", orderList.size());
+ request.setAttribute("loginUser", loginUser);
+
+ request.getRequestDispatcher("/jsp/admin/order_list.jsp").forward(request, response);
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/admin/AdminStatisticsController.java b/HRS/src/com/hrs/controller/admin/AdminStatisticsController.java
new file mode 100644
index 0000000..1a376ab
--- /dev/null
+++ b/HRS/src/com/hrs/controller/admin/AdminStatisticsController.java
@@ -0,0 +1,74 @@
+package com.hrs.controller.admin;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.dao.OrderDao;
+import com.hrs.dao.impl.OrderDaoImpl;
+import com.hrs.dao.UserDao;
+import com.hrs.dao.impl.UserDaoImpl;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: AdminStatisticsController.java
+* @Description: 管理员统计数据AP
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:53:55
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/admin/statistics")
+public class AdminStatisticsController extends HttpServlet {
+
+ private UserDao userDao = new UserDaoImpl();
+ private HouseDao houseDao = new HouseDaoImpl();
+ private OrderDao orderDao = new OrderDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.setStatus(401);
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"2".equals(loginUser.getRoleType())) {
+ response.setStatus(403);
+ return;
+ }
+
+ // 获取统计数据
+ int userCount = userDao.count();
+ int houseCount = houseDao.countAll();
+ int orderCount = orderDao.countAll();
+ int pendingCount = houseDao.findPendingHouses().size();
+
+ // 返回JSON
+ response.setContentType("application/json;charset=UTF-8");
+ PrintWriter out = response.getWriter();
+ out.print("{");
+ out.print("\"userCount\":" + userCount + ",");
+ out.print("\"houseCount\":" + houseCount + ",");
+ out.print("\"orderCount\":" + orderCount + ",");
+ out.print("\"pendingCount\":" + pendingCount);
+ out.print("}");
+ }
+}
diff --git a/HRS/src/com/hrs/controller/admin/AdminUserController.java b/HRS/src/com/hrs/controller/admin/AdminUserController.java
new file mode 100644
index 0000000..dd05655
--- /dev/null
+++ b/HRS/src/com/hrs/controller/admin/AdminUserController.java
@@ -0,0 +1,94 @@
+package com.hrs.controller.admin;
+
+import com.hrs.dao.UserDao;
+import com.hrs.dao.impl.UserDaoImpl;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: AdminUserController.java
+* @Description: 管理员用户管理控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:54:18
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/admin/user/list")
+public class AdminUserController extends HttpServlet {
+
+ private UserDao userDao = new UserDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 检查登录状态和管理员权限
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"2".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ // 获取所有用户
+ List allUsers = getAllUsers();
+
+ // 分离不同角色
+ List tenants = new java.util.ArrayList<>();
+ List landlords = new java.util.ArrayList<>();
+ List admins = new java.util.ArrayList<>();
+
+ for (User user : allUsers) {
+ if ("0".equals(user.getRoleType())) {
+ tenants.add(user);
+ } else if ("1".equals(user.getRoleType())) {
+ landlords.add(user);
+ } else if ("2".equals(user.getRoleType())) {
+ admins.add(user);
+ }
+ }
+
+ request.setAttribute("tenants", tenants);
+ request.setAttribute("landlords", landlords);
+ request.setAttribute("admins", admins);
+ request.setAttribute("totalCount", allUsers.size());
+ request.setAttribute("loginUser", loginUser);
+
+ request.getRequestDispatcher("/jsp/admin/user_list.jsp").forward(request, response);
+ }
+
+ private List getAllUsers() {
+ // 通过DAO获取所有用户
+ // 注意:UserDAO中没有findAll方法,需要添加
+ // 这里先用查询所有租客和房东的方式
+ List allUsers = new java.util.ArrayList<>();
+ allUsers.addAll(userDao.findAllTenants());
+ allUsers.addAll(userDao.findAllLandlords());
+ // 手动添加管理员(管理员数量少,可以从数据库查)
+ User admin = userDao.findByUsername("admin");
+ if (admin != null) {
+ allUsers.add(admin);
+ }
+ return allUsers;
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/admin/AdminUserDeleteController.java b/HRS/src/com/hrs/controller/admin/AdminUserDeleteController.java
new file mode 100644
index 0000000..a7ed1ce
--- /dev/null
+++ b/HRS/src/com/hrs/controller/admin/AdminUserDeleteController.java
@@ -0,0 +1,77 @@
+package com.hrs.controller.admin;
+
+import com.hrs.dao.UserDao;
+import com.hrs.dao.impl.UserDaoImpl;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: AdminUserDeleteController.java
+* @Description: 管理员删除用户控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:54:34
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/admin/user/delete")
+public class AdminUserDeleteController extends HttpServlet {
+
+ private UserDao userDao = new UserDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"2".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ String userIdStr = request.getParameter("id");
+ if (userIdStr == null) {
+ response.sendRedirect(request.getContextPath() + "/admin/user/list");
+ return;
+ }
+
+ Long userId = Long.parseLong(userIdStr);
+
+ // 不能删除自己
+ if (userId.equals(loginUser.getId())) {
+ String encodedError = URLEncoder.encode("不能删除自己", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/admin/user/list?error=" + encodedError);
+ return;
+ }
+
+ boolean success = userDao.delete(userId);
+
+ if (success) {
+ String encodedMsg = URLEncoder.encode("删除成功", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/admin/user/list?msg=" + encodedMsg);
+ } else {
+ String encodedError = URLEncoder.encode("删除失败", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/admin/user/list?error=" + encodedError);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/admin/AdminUserStatusController.java b/HRS/src/com/hrs/controller/admin/AdminUserStatusController.java
new file mode 100644
index 0000000..0ef6e64
--- /dev/null
+++ b/HRS/src/com/hrs/controller/admin/AdminUserStatusController.java
@@ -0,0 +1,74 @@
+package com.hrs.controller.admin;
+
+import com.hrs.dao.UserDao;
+import com.hrs.dao.impl.UserDaoImpl;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: AdminUserStatusController.java
+* @Description: 管理员操作用户状态控制器(启用/禁用)
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:54:49
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/admin/user/status")
+public class AdminUserStatusController extends HttpServlet {
+
+ private UserDao userDao = new UserDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"2".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ String userIdStr = request.getParameter("id");
+ String action = request.getParameter("action"); // enable 或 disable
+
+ if (userIdStr == null || action == null) {
+ response.sendRedirect(request.getContextPath() + "/admin/user/list");
+ return;
+ }
+
+ Long userId = Long.parseLong(userIdStr);
+ String status = "enable".equals(action) ? "1" : "2";
+
+ boolean success = userDao.updateStatus(userId, status);
+
+ if (success) {
+ String msg = "enable".equals(action) ? "用户已启用" : "用户已禁用";
+ String encodedMsg = URLEncoder.encode(msg, "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/admin/user/list?msg=" + encodedMsg);
+ } else {
+ String encodedError = URLEncoder.encode("操作失败", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/admin/user/list?error=" + encodedError);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/landlord/HouseAddController.java b/HRS/src/com/hrs/controller/landlord/HouseAddController.java
new file mode 100644
index 0000000..c5c3ece
--- /dev/null
+++ b/HRS/src/com/hrs/controller/landlord/HouseAddController.java
@@ -0,0 +1,152 @@
+package com.hrs.controller.landlord;
+
+import com.hrs.model.entity.House;
+import com.hrs.model.entity.User;
+import com.hrs.service.HouseService;
+import com.hrs.service.impl.HouseServiceImpl;
+import com.hrs.util.ImageUploadUtil;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.MultipartConfig;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.Part;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Date;
+
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: HouseAddController.java
+* @Description: 添加房源控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:55:45
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/landlord/house/add")
+@MultipartConfig(
+ maxFileSize = 5 * 1024 * 1024,
+ maxRequestSize = 25 * 1024 * 1024
+)
+public class HouseAddController extends HttpServlet {
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 获取登录用户
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"1".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ request.setAttribute("loginUser", loginUser);
+ request.getRequestDispatcher("/jsp/landlord/house_add.jsp").forward(request, response);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ request.setCharacterEncoding("UTF-8");
+
+ // 获取登录用户
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"1".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ // 获取表单参数
+ String title = request.getParameter("title");
+ String area = request.getParameter("area");
+ String address = request.getParameter("address");
+ String houseType = request.getParameter("houseType");
+ String rentPriceStr = request.getParameter("rentPrice");
+ String rentType = request.getParameter("rentType");
+ String facility = request.getParameter("facility");
+ String description = request.getParameter("description");
+
+ // 验证必填项
+ if (title == null || title.trim().isEmpty()) {
+ request.setAttribute("error", "房源标题不能为空");
+ doGet(request, response);
+ return;
+ }
+
+ if (rentPriceStr == null || rentPriceStr.trim().isEmpty()) {
+ request.setAttribute("error", "租金不能为空");
+ doGet(request, response);
+ return;
+ }
+
+ // 处理图片上传
+ Collection parts = request.getParts();
+ String imgUrl = ImageUploadUtil.saveMultipleImages(parts, request);
+
+ // 生成房源编号
+ String houseNo = generateHouseNo();
+
+ // 创建房源对象
+ House house = new House();
+ house.setLandlordId(loginUser.getId());
+ house.setHouseNo(houseNo);
+ house.setTitle(title);
+ house.setArea(area);
+ house.setAddress(address);
+ house.setHouseType(houseType);
+ house.setRentPrice(new BigDecimal(rentPriceStr));
+ house.setRentType(rentType);
+ house.setFacility(facility);
+ house.setDescription(description);
+ house.setImgUrl(imgUrl);
+ house.setStatus("0"); // 默认待审核状态
+
+ // 使用Service层添加房源
+ HouseService houseService = new HouseServiceImpl();
+ HouseService.AddHouseResult result = houseService.addHouse(house);
+
+ if (result.isSuccess()) {
+ String encodedMsg = URLEncoder.encode(result.getMessage(), "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/landlord/house/list?msg=" + encodedMsg);
+ } else {
+ request.setAttribute("error", result.getMessage());
+ doGet(request, response);
+ }
+ }
+
+ /**
+ * 生成房源编号
+ */
+ private String generateHouseNo() {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+ return "H" + sdf.format(new Date());
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/landlord/HouseDeleteController.java b/HRS/src/com/hrs/controller/landlord/HouseDeleteController.java
new file mode 100644
index 0000000..c736592
--- /dev/null
+++ b/HRS/src/com/hrs/controller/landlord/HouseDeleteController.java
@@ -0,0 +1,111 @@
+package com.hrs.controller.landlord;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.dao.OrderDao;
+import com.hrs.dao.impl.OrderDaoImpl;
+import com.hrs.dao.ReservationDao;
+import com.hrs.dao.impl.ReservationDaoImpl;
+import com.hrs.model.entity.House;
+import com.hrs.model.entity.User;
+import com.hrs.util.ImageUploadUtil;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: HouseDeleteController.java
+* @Description: 删除房源控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:56:09
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/landlord/house/delete")
+public class HouseDeleteController extends HttpServlet {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+ private OrderDao orderDao = new OrderDaoImpl();
+ private ReservationDao reservationDao = new ReservationDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 获取登录用户
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"1".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ // 获取房源ID
+ String idStr = request.getParameter("id");
+ if (idStr == null || idStr.trim().isEmpty()) {
+ response.sendRedirect(request.getContextPath() + "/landlord/house/list");
+ return;
+ }
+
+ Long houseId = Long.parseLong(idStr);
+
+ // 先获取房源信息(为了删除图片)
+ House house = houseDao.findById(houseId);
+
+ if (house == null) {
+ String encodedError = URLEncoder.encode("房源不存在", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/landlord/house/list?error=" + encodedError);
+ return;
+ }
+
+ // 检查是否有关联的订单
+ boolean hasOrders = orderDao.existsByHouseId(houseId);
+ if (hasOrders) {
+ String encodedError = URLEncoder.encode("该房源存在关联订单,无法删除", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/landlord/house/list?error=" + encodedError);
+ return;
+ }
+
+ // 检查是否有关联的预约
+ boolean hasReservations = reservationDao.existsByHouseId(houseId);
+ if (hasReservations) {
+ String encodedError = URLEncoder.encode("该房源存在关联预约,无法删除", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/landlord/house/list?error=" + encodedError);
+ return;
+ }
+
+ // 删除数据库记录
+ boolean success = houseDao.delete(houseId);
+
+ if (success && house != null && house.getImgUrl() != null) {
+ // 删除图片文件
+ ImageUploadUtil.deleteImages(house.getImgUrl(), request);
+ String encodedMsg = URLEncoder.encode("删除成功", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/landlord/house/list?msg=" + encodedMsg);
+ } else if (success) {
+ String encodedMsg = URLEncoder.encode("删除成功", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/landlord/house/list?msg=" + encodedMsg);
+ } else {
+ String encodedError = URLEncoder.encode("删除失败", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/landlord/house/list?error=" + encodedError);
+ }
+ }
+}
diff --git a/HRS/src/com/hrs/controller/landlord/HouseEditController.java b/HRS/src/com/hrs/controller/landlord/HouseEditController.java
new file mode 100644
index 0000000..ae37bea
--- /dev/null
+++ b/HRS/src/com/hrs/controller/landlord/HouseEditController.java
@@ -0,0 +1,138 @@
+package com.hrs.controller.landlord;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.model.entity.House;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.net.URLEncoder;
+
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: HouseEditController.java
+* @Description: 编辑房源控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:56:25
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/landlord/house/edit")
+public class HouseEditController extends HttpServlet {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 获取登录用户
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"1".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ // 获取房源ID
+ String idStr = request.getParameter("id");
+ if (idStr == null || idStr.trim().isEmpty()) {
+ response.sendRedirect(request.getContextPath() + "/landlord/house/list");
+ return;
+ }
+
+ Long houseId = Long.parseLong(idStr);
+ House house = houseDao.findById(houseId);
+
+ // 验证是否是自己的房源
+ if (house == null || !house.getLandlordId().equals(loginUser.getId())) {
+ response.sendRedirect(request.getContextPath() + "/landlord/house/list");
+ return;
+ }
+
+ request.setAttribute("house", house);
+ request.setAttribute("loginUser", loginUser);
+ request.getRequestDispatcher("/jsp/landlord/house_edit.jsp").forward(request, response);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ request.setCharacterEncoding("UTF-8");
+
+ // 获取登录用户
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"1".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ // 获取表单参数
+ String idStr = request.getParameter("id");
+ String title = request.getParameter("title");
+ String area = request.getParameter("area");
+ String address = request.getParameter("address");
+ String houseType = request.getParameter("houseType");
+ String rentPriceStr = request.getParameter("rentPrice");
+ String rentType = request.getParameter("rentType");
+ String facility = request.getParameter("facility");
+ String description = request.getParameter("description");
+ String imgUrl = request.getParameter("imgUrl");
+
+ if (idStr == null || title == null || rentPriceStr == null) {
+ response.sendRedirect(request.getContextPath() + "/landlord/house/list");
+ return;
+ }
+
+ Long houseId = Long.parseLong(idStr);
+
+ // 创建房源对象
+ House house = new House();
+ house.setId(houseId);
+ house.setTitle(title);
+ house.setArea(area);
+ house.setAddress(address);
+ house.setHouseType(houseType);
+ house.setRentPrice(new BigDecimal(rentPriceStr));
+ house.setRentType(rentType);
+ house.setFacility(facility);
+ house.setDescription(description);
+ house.setImgUrl(imgUrl);
+
+ boolean success = houseDao.update(house);
+
+ if (success) {
+ String encodedMsg = URLEncoder.encode("房源修改成功", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/landlord/house/list?msg=" + encodedMsg);
+ } else {
+ request.setAttribute("error", "修改失败,请稍后重试");
+ doGet(request, response);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/landlord/HouseListController.java b/HRS/src/com/hrs/controller/landlord/HouseListController.java
new file mode 100644
index 0000000..43dba57
--- /dev/null
+++ b/HRS/src/com/hrs/controller/landlord/HouseListController.java
@@ -0,0 +1,63 @@
+package com.hrs.controller.landlord;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.model.entity.House;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: HouseListController.java
+* @Description: 房东房源列表控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:56:39
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/landlord/house/list")
+public class HouseListController extends HttpServlet {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 获取登录用户
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"1".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ // 查询房东自己的房源
+ List houseList = houseDao.findByLandlordId(loginUser.getId());
+
+ request.setAttribute("houseList", houseList);
+ request.setAttribute("totalCount", houseList.size());
+ request.setAttribute("loginUser", loginUser);
+
+ request.getRequestDispatcher("/jsp/landlord/house_list.jsp").forward(request, response);
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/landlord/OrderConfirmController.java b/HRS/src/com/hrs/controller/landlord/OrderConfirmController.java
new file mode 100644
index 0000000..af6babf
--- /dev/null
+++ b/HRS/src/com/hrs/controller/landlord/OrderConfirmController.java
@@ -0,0 +1,79 @@
+package com.hrs.controller.landlord;
+
+import com.hrs.dao.OrderDao;
+import com.hrs.dao.impl.OrderDaoImpl;
+import com.hrs.model.entity.Order;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: OrderConfirmController.java
+* @Description: 房东确认签约控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午8:56:51
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/landlord/order/confirm")
+public class OrderConfirmController extends HttpServlet {
+
+ private OrderDao orderDao = new OrderDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"1".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ String orderIdStr = request.getParameter("id");
+ if (orderIdStr == null) {
+ response.sendRedirect(request.getContextPath() + "/landlord/order/list");
+ return;
+ }
+
+ Long orderId = Long.parseLong(orderIdStr);
+ Order order = orderDao.findById(orderId);
+
+ // 验证订单是否属于该房东的房源
+ if (order == null) {
+ String encodedError = URLEncoder.encode("订单不存在", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/landlord/order/list?error=" + encodedError);
+ return;
+ }
+
+ boolean success = orderDao.updateStatus(orderId, "1"); // 1-已签约
+
+ if (success) {
+ String encodedMsg = URLEncoder.encode("已确认签约", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/landlord/order/list?msg=" + encodedMsg);
+ } else {
+ String encodedError = URLEncoder.encode("操作失败", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/landlord/order/list?error=" + encodedError);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/landlord/OrderManageController.java b/HRS/src/com/hrs/controller/landlord/OrderManageController.java
new file mode 100644
index 0000000..6a1f919
--- /dev/null
+++ b/HRS/src/com/hrs/controller/landlord/OrderManageController.java
@@ -0,0 +1,61 @@
+package com.hrs.controller.landlord;
+
+import com.hrs.dao.OrderDao;
+import com.hrs.dao.impl.OrderDaoImpl;
+import com.hrs.model.entity.Order;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: OrderManageController.java
+* @Description: 房东订单管理控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:01:28
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/landlord/order/list")
+public class OrderManageController extends HttpServlet {
+
+ private OrderDao orderDao = new OrderDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"1".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ List orderList = orderDao.findByLandlordId(loginUser.getId());
+
+ request.setAttribute("orderList", orderList);
+ request.setAttribute("totalCount", orderList.size());
+ request.setAttribute("loginUser", loginUser);
+
+ request.getRequestDispatcher("/jsp/landlord/order_list.jsp").forward(request, response);
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/landlord/ReservationHandleController.java b/HRS/src/com/hrs/controller/landlord/ReservationHandleController.java
new file mode 100644
index 0000000..bcec474
--- /dev/null
+++ b/HRS/src/com/hrs/controller/landlord/ReservationHandleController.java
@@ -0,0 +1,76 @@
+package com.hrs.controller.landlord;
+
+import com.hrs.dao.ReservationDao;
+import com.hrs.dao.impl.ReservationDaoImpl;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: ReservationHandleController.java
+* @Description: 房东处理预约控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:01:42
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/landlord/reservation/handle")
+public class ReservationHandleController extends HttpServlet {
+
+ private ReservationDao reservationDao = new ReservationDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 获取登录用户
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"1".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ // 获取参数
+ String idStr = request.getParameter("id");
+ String action = request.getParameter("action"); // confirm 或 reject
+
+ if (idStr == null || action == null) {
+ response.sendRedirect(request.getContextPath() + "/landlord/reservation/list");
+ return;
+ }
+
+ Long id = Long.parseLong(idStr);
+ String status = "confirm".equals(action) ? "1" : "2";
+
+ boolean success = reservationDao.updateStatus(id, status);
+
+ if (success) {
+ String msg = "confirm".equals(action) ? "已确认预约" : "已拒绝预约";
+ String encodedMsg = URLEncoder.encode(msg, "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/landlord/reservation/list?msg=" + encodedMsg);
+ } else {
+ String encodedError = URLEncoder.encode("操作失败", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/landlord/reservation/list?error=" + encodedError);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/landlord/ReservationManageController.java b/HRS/src/com/hrs/controller/landlord/ReservationManageController.java
new file mode 100644
index 0000000..5435470
--- /dev/null
+++ b/HRS/src/com/hrs/controller/landlord/ReservationManageController.java
@@ -0,0 +1,63 @@
+package com.hrs.controller.landlord;
+
+import com.hrs.dao.ReservationDao;
+import com.hrs.dao.impl.ReservationDaoImpl;
+import com.hrs.model.entity.Reservation;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: ReservationManageController.java
+* @Description: 房东预约管理控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:02:01
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/landlord/reservation/list")
+public class ReservationManageController extends HttpServlet {
+
+ private ReservationDao reservationDao = new ReservationDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 获取登录用户
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"1".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ // 查询收到的预约
+ List reservationList = reservationDao.findByLandlordId(loginUser.getId());
+
+ request.setAttribute("reservationList", reservationList);
+ request.setAttribute("totalCount", reservationList.size());
+ request.setAttribute("loginUser", loginUser);
+
+ request.getRequestDispatcher("/jsp/landlord/reservation_list.jsp").forward(request, response);
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/CollectionAddController.java b/HRS/src/com/hrs/controller/user/CollectionAddController.java
new file mode 100644
index 0000000..d72dd5f
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/CollectionAddController.java
@@ -0,0 +1,89 @@
+package com.hrs.controller.user;
+
+import com.hrs.model.entity.User;
+import com.hrs.service.CollectionService;
+import com.hrs.service.impl.CollectionServiceImpl;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: CollectionAddController.java
+* @Description: 添加收藏控制器/AJAX请求,返回文本结果
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:02:40
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/collection/add")
+public class CollectionAddController extends HttpServlet {
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ response.setContentType("text/plain;charset=UTF-8");
+ PrintWriter out = response.getWriter();
+
+ // 1. 检查登录状态
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ out.print("not_login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"0".equals(loginUser.getRoleType())) {
+ out.print("not_login");
+ return;
+ }
+
+ // 2. 获取房源ID
+ String houseIdStr = request.getParameter("houseId");
+ if (houseIdStr == null || houseIdStr.trim().isEmpty()) {
+ out.print("error");
+ return;
+ }
+
+ Long houseId = null;
+ try {
+ houseId = Long.parseLong(houseIdStr);
+ } catch (NumberFormatException e) {
+ out.print("error");
+ return;
+ }
+
+ // 原来的代码
+ // boolean exists = collectionDao.isCollected(loginUser.getId(), houseId);
+ // if (exists) {
+ // out.print("exists");
+ // return;
+ // }
+ // boolean success = collectionDao.add(collection);
+
+ // 修改为
+ CollectionService collectionService = new CollectionServiceImpl();
+ CollectionService.CollectionResult result = collectionService.addCollection(loginUser.getId(), houseId);
+
+ if (result.isExists()) {
+ out.print("exists");
+ } else if (result.isSuccess()) {
+ out.print("success");
+ } else {
+ out.print("error");
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/CollectionDeleteController.java b/HRS/src/com/hrs/controller/user/CollectionDeleteController.java
new file mode 100644
index 0000000..19edde5
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/CollectionDeleteController.java
@@ -0,0 +1,127 @@
+package com.hrs.controller.user;
+
+import com.hrs.dao.CollectionDao;
+import com.hrs.dao.impl.CollectionDaoImpl;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URLEncoder;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: CollectionDeleteController.java
+* @Description: 取消收藏控制器/支持两种删除方式:
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:03:05
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/collection/delete")
+public class CollectionDeleteController extends HttpServlet {
+
+ private CollectionDao collectionDao = new CollectionDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 获取来源参数
+ String from = request.getParameter("from");
+ String idStr = request.getParameter("id");
+ String houseIdStr = request.getParameter("houseId");
+
+ // 判断是否是AJAX请求
+ String ajax = request.getParameter("ajax");
+
+ // 1. 获取登录用户
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ if ("true".equals(ajax)) {
+ response.setContentType("application/json;charset=UTF-8");
+ PrintWriter out = response.getWriter();
+ out.print("{\"success\":false,\"msg\":\"未登录\"}");
+ return;
+ } else {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"0".equals(loginUser.getRoleType())) {
+ if ("true".equals(ajax)) {
+ response.setContentType("application/json;charset=UTF-8");
+ PrintWriter out = response.getWriter();
+ out.print("{\"success\":false,\"msg\":\"未登录\"}");
+ return;
+ } else {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+ }
+
+ boolean success = false;
+
+ // 2. 根据ID删除(从收藏列表删除)
+ if (idStr != null && !idStr.trim().isEmpty()) {
+ Long id = Long.parseLong(idStr);
+ success = collectionDao.deleteById(id);
+ }
+ // 3. 根据房源ID删除(从详情页删除)
+ else if (houseIdStr != null && !houseIdStr.trim().isEmpty()) {
+ Long houseId = Long.parseLong(houseIdStr);
+ success = collectionDao.delete(loginUser.getId(), houseId);
+ }
+
+ // 4. 处理返回结果
+ if ("true".equals(ajax)) {
+ // AJAX请求:返回JSON
+ response.setContentType("application/json;charset=UTF-8");
+ PrintWriter out = response.getWriter();
+ if (success) {
+ out.print("{\"success\":true,\"msg\":\"取消收藏成功\"}");
+ } else {
+ out.print("{\"success\":false,\"msg\":\"取消收藏失败\"}");
+ }
+ } else {
+ // 普通请求:页面跳转
+ if (success) {
+ // 根据来源参数决定跳转位置
+ if ("detail".equals(from) && houseIdStr != null) {
+ // 从详情页删除,跳回详情页
+ String encodedMsg = URLEncoder.encode("取消收藏成功", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/house/detail?id=" + houseIdStr + "&msg=" + encodedMsg);
+ } else if ("list".equals(from)) {
+ // 从收藏列表删除,跳回收藏列表
+ String encodedMsg = URLEncoder.encode("取消收藏成功", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/collection/list?msg=" + encodedMsg);
+ } else {
+ // 默认跳回收藏列表
+ String encodedMsg = URLEncoder.encode("取消收藏成功", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/collection/list?msg=" + encodedMsg);
+ }
+ } else {
+ if ("detail".equals(from) && houseIdStr != null) {
+ String encodedError = URLEncoder.encode("取消收藏失败", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/house/detail?id=" + houseIdStr + "&error=" + encodedError);
+ } else {
+ String encodedError = URLEncoder.encode("取消收藏失败", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/collection/list?error=" + encodedError);
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/CollectionListController.java b/HRS/src/com/hrs/controller/user/CollectionListController.java
new file mode 100644
index 0000000..ad0390f
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/CollectionListController.java
@@ -0,0 +1,65 @@
+package com.hrs.controller.user;
+
+import com.hrs.dao.CollectionDao;
+import com.hrs.dao.impl.CollectionDaoImpl;
+import com.hrs.model.entity.Collection;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: CollectionListController.java
+* @Description: 我的收藏列表控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:03:32
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/collection/list")
+public class CollectionListController extends HttpServlet {
+
+ private CollectionDao collectionDao = new CollectionDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 1. 获取登录用户
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"0".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ // 2. 查询收藏列表
+ List collectionList = collectionDao.findByTenantId(loginUser.getId());
+
+ // 3. 存入request
+ request.setAttribute("collectionList", collectionList);
+ request.setAttribute("totalCount", collectionList.size());
+ request.setAttribute("loginUser", loginUser);
+
+ // 4. 转发到JSP
+ request.getRequestDispatcher("/jsp/user/collection_list.jsp").forward(request, response);
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/HouseDetailController.java b/HRS/src/com/hrs/controller/user/HouseDetailController.java
new file mode 100644
index 0000000..727f755
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/HouseDetailController.java
@@ -0,0 +1,73 @@
+package com.hrs.controller.user;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.model.entity.House;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: HouseDetailController.java
+* @Description: 房源详情控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:04:08
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/house/detail")
+public class HouseDetailController extends HttpServlet {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 1. 获取房源ID
+ String idStr = request.getParameter("id");
+ if (idStr == null || idStr.trim().isEmpty()) {
+ response.sendRedirect(request.getContextPath() + "/user/house/list");
+ return;
+ }
+
+ Long houseId = null;
+ try {
+ houseId = Long.parseLong(idStr);
+ } catch (NumberFormatException e) {
+ response.sendRedirect(request.getContextPath() + "/user/house/list");
+ return;
+ }
+
+ // 2. 查询房源详情
+ House house = houseDao.findById(houseId);
+ if (house == null) {
+ response.sendRedirect(request.getContextPath() + "/user/house/list");
+ return;
+ }
+
+ // 3. 获取当前登录用户
+ HttpSession session = request.getSession(false);
+ User loginUser = (User) session.getAttribute("loginUser");
+
+ // 4. 将数据存入request
+ request.setAttribute("house", house);
+ request.setAttribute("loginUser", loginUser);
+
+ // 5. 转发到详情页面
+ request.getRequestDispatcher("/jsp/user/house_detail.jsp").forward(request, response);
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/HouseListController.java b/HRS/src/com/hrs/controller/user/HouseListController.java
new file mode 100644
index 0000000..110776f
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/HouseListController.java
@@ -0,0 +1,74 @@
+package com.hrs.controller.user;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.model.entity.House;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: HouseListController.java
+* @Description: 房源列表控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:04:41
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/house/list")
+public class HouseListController extends HttpServlet {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 获取请求参数
+ String area = request.getParameter("area");
+ String minPriceStr = request.getParameter("minPrice");
+ String maxPriceStr = request.getParameter("maxPrice");
+
+ List houseList;
+
+ // 根据条件查询
+ if (area != null && !area.trim().isEmpty()) {
+ houseList = houseDao.findHousesByArea(area);
+ request.setAttribute("searchArea", area);
+ } else if (minPriceStr != null && maxPriceStr != null && !minPriceStr.isEmpty() && !maxPriceStr.isEmpty()) {
+ int minPrice = Integer.parseInt(minPriceStr);
+ int maxPrice = Integer.parseInt(maxPriceStr);
+ houseList = houseDao.findHousesByPrice(minPrice, maxPrice);
+ request.setAttribute("minPrice", minPrice);
+ request.setAttribute("maxPrice", maxPrice);
+ } else {
+ houseList = houseDao.findPublishedHouses();
+ }
+
+ // 获取当前登录用户(用于判断是否已收藏)
+ HttpSession session = request.getSession(false);
+ User loginUser = (User) session.getAttribute("loginUser");
+
+ // 将数据存入request
+ request.setAttribute("houseList", houseList);
+ request.setAttribute("totalCount", houseList.size());
+ request.setAttribute("loginUser", loginUser);
+
+ // 转发到JSP页面
+ request.getRequestDispatcher("/jsp/user/house_list.jsp").forward(request, response);
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/LoginController.java b/HRS/src/com/hrs/controller/user/LoginController.java
new file mode 100644
index 0000000..01b0c47
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/LoginController.java
@@ -0,0 +1,120 @@
+package com.hrs.controller.user;
+
+import com.hrs.dao.UserDao;
+import com.hrs.dao.impl.UserDaoImpl;
+import com.hrs.service.UserService;
+import com.hrs.service.impl.UserServiceImpl;
+import com.hrs.model.entity.User;
+import com.hrs.util.MD5Util;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: LoginController.java
+* @Description: 登录控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:05:32
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/login")
+public class LoginController extends HttpServlet {
+
+ private UserDao userDao = new UserDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ // GET请求:显示登录页面
+ // 如果有消息(如注册成功),传递给页面
+ String message = request.getParameter("message");
+ if (message != null) {
+ request.setAttribute("message", message);
+ }
+ request.getRequestDispatcher("/jsp/user/login.jsp").forward(request, response);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ // POST请求:处理登录表单提交
+ request.setCharacterEncoding("UTF-8");
+
+ // 1. 获取表单参数
+ String username = request.getParameter("username");
+ String password = request.getParameter("password");
+ String roleType = request.getParameter("roleType"); // 前端传:0-租客 1-房东 2-管理员
+
+ // 2. 基础验证
+ if (username == null || username.trim().isEmpty() ||
+ password == null || password.trim().isEmpty()) {
+ request.setAttribute("error", "用户名和密码不能为空");
+ request.getRequestDispatcher("/jsp/user/login.jsp").forward(request, response);
+ return;
+ }
+
+ // 3. 密码MD5加密(因为数据库里存的是MD5)
+ String encryptedPassword = MD5Util.md5(password);
+
+ // 4. 调用Service查询用户
+ UserService userService = new UserServiceImpl();
+ User user = userService.login(username, password, roleType);
+
+ // 5. 验证结果
+ if (user == null) {
+ // 登录失败
+ request.setAttribute("error", "用户名或密码错误");
+ request.getRequestDispatcher("/jsp/user/login.jsp").forward(request, response);
+ return;
+ }
+
+ // 6. 验证角色是否匹配
+ if (!user.getRoleType().equals(roleType)) {
+ request.setAttribute("error", "角色类型不匹配");
+ request.getRequestDispatcher("/jsp/user/login.jsp").forward(request, response);
+ return;
+ }
+
+ // 7. 验证账号状态
+ if ("2".equals(user.getStatus())) {
+ request.setAttribute("error", "账号已被禁用,请联系管理员");
+ request.getRequestDispatcher("/jsp/user/login.jsp").forward(request, response);
+ return;
+ }
+
+ // 8. 登录成功,保存用户信息到Session
+ HttpSession session = request.getSession();
+ session.setAttribute("loginUser", user);
+ session.setAttribute("userRole", user.getRoleType());
+ session.setMaxInactiveInterval(30 * 60); // 30分钟超时
+
+ // 9. 根据角色跳转到不同首页
+ String redirectUrl = "/HRS/";
+ switch (user.getRoleType()) {
+ case "0": // 租客
+ redirectUrl = "/HRS/jsp/user/index.jsp";
+ break;
+ case "1": // 房东
+ redirectUrl = "/HRS/jsp/landlord/index.jsp";
+ break;
+ case "2": // 管理员
+ redirectUrl = "/HRS/jsp/admin/index.jsp";
+ break;
+ }
+
+ response.sendRedirect(redirectUrl);
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/LogoutController.java b/HRS/src/com/hrs/controller/user/LogoutController.java
new file mode 100644
index 0000000..431f93d
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/LogoutController.java
@@ -0,0 +1,50 @@
+package com.hrs.controller.user;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: LogoutController.java
+* @Description: 退出登录控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:06:00
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/logout")
+public class LogoutController extends HttpServlet {
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 1. 获取Session
+ HttpSession session = request.getSession(false);
+
+ // 2. 如果Session存在,销毁它
+ if (session != null) {
+ session.invalidate();
+ }
+
+ // 3. 跳转到登录页面
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ doGet(request, response);
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/OrderCancelController.java b/HRS/src/com/hrs/controller/user/OrderCancelController.java
new file mode 100644
index 0000000..b1b8ecd
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/OrderCancelController.java
@@ -0,0 +1,84 @@
+package com.hrs.controller.user;
+
+import com.hrs.dao.OrderDao;
+import com.hrs.dao.impl.OrderDaoImpl;
+import com.hrs.model.entity.Order;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: OrderCancelController.java
+* @Description: 取消订单控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:06:23
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/order/cancel")
+public class OrderCancelController extends HttpServlet {
+
+ private OrderDao orderDao = new OrderDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"0".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ String orderIdStr = request.getParameter("id");
+ if (orderIdStr == null) {
+ response.sendRedirect(request.getContextPath() + "/user/order/list");
+ return;
+ }
+
+ Long orderId = Long.parseLong(orderIdStr);
+ Order order = orderDao.findById(orderId);
+
+ if (order == null || !order.getTenantId().equals(loginUser.getId())) {
+ response.sendRedirect(request.getContextPath() + "/user/order/list");
+ return;
+ }
+
+ // 只有待支付的订单可以取消
+ if (!"0".equals(order.getPayStatus())) {
+ String encodedError = URLEncoder.encode("该订单无法取消", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/order/list?error=" + encodedError);
+ return;
+ }
+
+ boolean success = orderDao.updateStatus(orderId, "3"); // 3-已取消
+
+ if (success) {
+ String encodedMsg = URLEncoder.encode("订单已取消", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/order/list?msg=" + encodedMsg);
+ } else {
+ String encodedError = URLEncoder.encode("取消失败", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/order/list?error=" + encodedError);
+ }
+ }
+}
diff --git a/HRS/src/com/hrs/controller/user/OrderCreateController.java b/HRS/src/com/hrs/controller/user/OrderCreateController.java
new file mode 100644
index 0000000..01822cb
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/OrderCreateController.java
@@ -0,0 +1,166 @@
+package com.hrs.controller.user;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.model.entity.House;
+import com.hrs.model.entity.User;
+import com.hrs.service.OrderService;
+import com.hrs.service.impl.OrderServiceImpl;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: OrderCreateController.java
+* @Description: 创建订单控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:06:38
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/order/create")
+public class OrderCreateController extends HttpServlet {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 获取房源ID
+ String houseIdStr = request.getParameter("houseId");
+ if (houseIdStr == null || houseIdStr.trim().isEmpty()) {
+ response.sendRedirect(request.getContextPath() + "/user/house/list");
+ return;
+ }
+
+ Long houseId = Long.parseLong(houseIdStr);
+ House house = houseDao.findById(houseId);
+
+ if (house == null || !"1".equals(house.getStatus())) {
+ response.sendRedirect(request.getContextPath() + "/user/house/list");
+ return;
+ }
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"0".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ request.setAttribute("house", house);
+ request.setAttribute("loginUser", loginUser);
+ request.getRequestDispatcher("/jsp/user/order_create.jsp").forward(request, response);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ request.setCharacterEncoding("UTF-8");
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"0".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ String houseIdStr = request.getParameter("houseId");
+ String startDateStr = request.getParameter("startDate");
+ String endDateStr = request.getParameter("endDate");
+
+ if (houseIdStr == null || startDateStr == null || endDateStr == null) {
+ response.sendRedirect(request.getContextPath() + "/user/house/list");
+ return;
+ }
+
+ Long houseId = Long.parseLong(houseIdStr);
+ House house = houseDao.findById(houseId);
+
+ if (house == null || !"1".equals(house.getStatus())) {
+ response.sendRedirect(request.getContextPath() + "/user/house/list");
+ return;
+ }
+
+ // 解析日期
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+ Date startDate, endDate;
+ try {
+ startDate = sdf.parse(startDateStr);
+ endDate = sdf.parse(endDateStr);
+ } catch (ParseException e) {
+ request.setAttribute("error", "日期格式错误");
+ request.setAttribute("house", house);
+ request.getRequestDispatcher("/jsp/user/order_create.jsp").forward(request, response);
+ return;
+ }
+
+ // 验证日期
+ if (startDate.before(new Date())) {
+ request.setAttribute("error", "租赁开始日期不能早于今天");
+ request.setAttribute("house", house);
+ request.getRequestDispatcher("/jsp/user/order_create.jsp").forward(request, response);
+ return;
+ }
+
+ if (endDate.before(startDate)) {
+ request.setAttribute("error", "结束日期不能早于开始日期");
+ request.setAttribute("house", house);
+ request.getRequestDispatcher("/jsp/user/order_create.jsp").forward(request, response);
+ return;
+ }
+
+ // 修改为
+ OrderService orderService = new OrderServiceImpl();
+ OrderService.CreateOrderResult result = orderService.createOrder(
+ loginUser.getId(), houseId, startDate, endDate
+ );
+
+ if (result.isSuccess()) {
+ // 对中文消息进行 URL 编码
+ String encodedMsg = URLEncoder.encode(result.getMessage(), "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/order/list?msg=" + encodedMsg);
+ } else {
+ request.setAttribute("error", result.getMessage());
+ request.setAttribute("house", house);
+ request.getRequestDispatcher("/jsp/user/order_create.jsp").forward(request, response);
+ }
+ }
+
+ /**
+ * 生成订单编号
+ */
+ private String generateOrderNo() {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+ return "ORD" + sdf.format(new Date());
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/OrderListController.java b/HRS/src/com/hrs/controller/user/OrderListController.java
new file mode 100644
index 0000000..90c2f47
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/OrderListController.java
@@ -0,0 +1,61 @@
+package com.hrs.controller.user;
+
+import com.hrs.dao.OrderDao;
+import com.hrs.dao.impl.OrderDaoImpl;
+import com.hrs.model.entity.Order;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: OrderListController.java
+* @Description: 我的订单列表控制器(租客端)
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:07:07
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/order/list")
+public class OrderListController extends HttpServlet {
+
+ private OrderDao orderDao = new OrderDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"0".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ List orderList = orderDao.findByTenantId(loginUser.getId());
+
+ request.setAttribute("orderList", orderList);
+ request.setAttribute("totalCount", orderList.size());
+ request.setAttribute("loginUser", loginUser);
+
+ request.getRequestDispatcher("/jsp/user/order_list.jsp").forward(request, response);
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/OrderPayController.java b/HRS/src/com/hrs/controller/user/OrderPayController.java
new file mode 100644
index 0000000..a06cf7f
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/OrderPayController.java
@@ -0,0 +1,78 @@
+package com.hrs.controller.user;
+
+import com.hrs.dao.OrderDao;
+import com.hrs.dao.impl.OrderDaoImpl;
+import com.hrs.model.entity.Order;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: OrderPayController.java
+* @Description: 订单支付控制器(模拟支付)
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:07:43
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/order/pay")
+public class OrderPayController extends HttpServlet {
+
+ private OrderDao orderDao = new OrderDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"0".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ String orderIdStr = request.getParameter("id");
+ if (orderIdStr == null) {
+ response.sendRedirect(request.getContextPath() + "/user/order/list");
+ return;
+ }
+
+ Long orderId = Long.parseLong(orderIdStr);
+ Order order = orderDao.findById(orderId);
+
+ if (order == null || !order.getTenantId().equals(loginUser.getId())) {
+ response.sendRedirect(request.getContextPath() + "/user/order/list");
+ return;
+ }
+
+ // 模拟支付:更新支付状态为已支付
+ boolean success = orderDao.updatePayStatus(orderId, "1");
+
+ if (success) {
+ String encodedMsg = URLEncoder.encode("支付成功", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/order/list?msg=" + encodedMsg);
+ } else {
+ String encodedError = URLEncoder.encode("支付失败", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/order/list?error=" + encodedError);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/RegisterController.java b/HRS/src/com/hrs/controller/user/RegisterController.java
new file mode 100644
index 0000000..0628f2d
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/RegisterController.java
@@ -0,0 +1,84 @@
+package com.hrs.controller.user;
+
+import com.hrs.dao.UserDao;
+import com.hrs.dao.impl.UserDaoImpl;
+import com.hrs.model.entity.User;
+import com.hrs.service.UserService;
+import com.hrs.service.impl.UserServiceImpl;
+import com.hrs.util.MD5Util;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URLEncoder;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: RegisterController.java
+* @Description: 注册控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:08:06
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/register")
+public class RegisterController extends HttpServlet {
+
+ private UserDao userDao = new UserDaoImpl();
+ private UserService userService = new UserServiceImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ // GET请求:显示注册页面
+ request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response);
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ // POST请求:处理注册表单提交
+ request.setCharacterEncoding("UTF-8");
+
+ // 1. 获取表单参数
+ String username = request.getParameter("username");
+ String password = request.getParameter("password");
+ String confirmPassword = request.getParameter("confirmPassword");
+ String realName = request.getParameter("realName");
+ String phone = request.getParameter("phone");
+ String idCard = request.getParameter("idCard");
+ String roleType = request.getParameter("roleType");
+
+ // 2. 创建用户对象
+ User user = new User();
+ user.setUserName(username);
+ user.setPassword(password); // 密码将在Service层加密
+ user.setRealName(realName);
+ user.setPhone(phone);
+ user.setIdCard(idCard);
+ user.setRoleType(roleType); // 0-租客 1-房东
+ user.setStatus("0"); // 默认未认证状态
+
+ // 3. 调用UserService进行注册验证和保存
+ UserService.RegisterResult result = userService.register(user, confirmPassword);
+
+ if (result.isSuccess()) {
+ // 注册成功,跳转到登录页面(使用重定向避免表单重复提交)
+ String encodedMsg = URLEncoder.encode(result.getMessage(), "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/login?message=" + encodedMsg);
+ } else {
+ // 注册失败,留在注册页面显示错误
+ request.setAttribute("error", result.getMessage());
+ request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/ReservationAddController.java b/HRS/src/com/hrs/controller/user/ReservationAddController.java
new file mode 100644
index 0000000..018cd90
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/ReservationAddController.java
@@ -0,0 +1,150 @@
+package com.hrs.controller.user;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.model.entity.House;
+import com.hrs.model.entity.User;
+import com.hrs.service.ReservationService;
+import com.hrs.service.impl.ReservationServiceImpl;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: ReservationAddController.java
+* @Description: 添加预约控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:11:10
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/reservation/add")
+public class ReservationAddController extends HttpServlet {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ String houseIdStr = request.getParameter("houseId");
+ if (houseIdStr == null || houseIdStr.trim().isEmpty()) {
+ response.sendRedirect(request.getContextPath() + "/user/house/list");
+ return; // ← 必须加return
+ }
+
+ Long houseId = Long.parseLong(houseIdStr);
+ House house = houseDao.findById(houseId);
+
+ if (house == null) {
+ response.sendRedirect(request.getContextPath() + "/user/house/list");
+ return; // ← 必须加return
+ }
+
+ HttpSession session = request.getSession(false);
+ User loginUser = (User) session.getAttribute("loginUser");
+
+ request.setAttribute("house", house);
+ request.setAttribute("loginUser", loginUser);
+ request.getRequestDispatcher("/jsp/user/reservation_add.jsp").forward(request, response);
+ // forward后不需要return,因为这是最后一行
+ }
+
+ @Override
+ protected void doPost(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ request.setCharacterEncoding("UTF-8");
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return; // ← 必须加return
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"0".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return; // ← 必须加return
+ }
+
+ String houseIdStr = request.getParameter("houseId");
+ String reserveDate = request.getParameter("reserveDate");
+ String reserveTime = request.getParameter("reserveTime");
+ String remark = request.getParameter("remark");
+
+ // 验证参数
+ if (houseIdStr == null || reserveDate == null || reserveTime == null) {
+ // 错误时回到预约表单页
+ request.setAttribute("error", "请填写完整信息");
+ doGet(request, response);
+ return; // ← 必须加return
+ }
+
+ Long houseId = Long.parseLong(houseIdStr);
+ House house = houseDao.findById(houseId);
+
+ if (house == null) {
+ request.setAttribute("error", "房源不存在");
+ doGet(request, response);
+ return; // ← 必须加return
+ }
+
+ // 组合时间
+ String datetimeStr = reserveDate + " " + reserveTime + ":00";
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ Date reserveDateTime;
+ try {
+ reserveDateTime = sdf.parse(datetimeStr);
+ } catch (Exception e) {
+ request.setAttribute("error", "时间格式错误");
+ doGet(request, response);
+ return; // ← 必须加return
+ }
+
+ if (reserveDateTime.before(new Date())) {
+ request.setAttribute("error", "预约时间不能早于当前时间");
+ doGet(request, response);
+ return; // ← 必须加return
+ }
+
+ // 原来的代码
+ // Reservation reservation = new Reservation();
+ // reservation.setTenantId(loginUser.getId());
+ // reservation.setHouseId(houseId);
+ // reservation.setLandlordId(house.getLandlordId());
+ // reservation.setReserveTime(reserveDateTime);
+ // reservation.setRemark(remark);
+ // boolean success = reservationDao.add(reservation);
+
+ // 修改为
+ ReservationService reservationService = new ReservationServiceImpl();
+ ReservationService.ReservationResult result = reservationService.createReservation(
+ loginUser.getId(), houseId, reserveDateTime, remark
+ );
+
+ if (result.isSuccess()) {
+ // 对中文消息进行 URL 编码
+ String encodedMsg = URLEncoder.encode(result.getMessage(), "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/reservation/list?msg=" + encodedMsg);
+ } else {
+ request.setAttribute("error", result.getMessage());
+ doGet(request, response);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/ReservationCancelController.java b/HRS/src/com/hrs/controller/user/ReservationCancelController.java
new file mode 100644
index 0000000..dda6ce6
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/ReservationCancelController.java
@@ -0,0 +1,70 @@
+package com.hrs.controller.user;
+
+import com.hrs.dao.ReservationDao;
+import com.hrs.dao.impl.ReservationDaoImpl;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.net.URLEncoder;
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: ReservationCancelController.java
+* @Description: 取消预约控制器
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:12:10
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/reservation/cancel")
+public class ReservationCancelController extends HttpServlet {
+
+ private ReservationDao reservationDao = new ReservationDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return; // ← 必须加return
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"0".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return; // ← 必须加return
+ }
+
+ String idStr = request.getParameter("id");
+ if (idStr == null || idStr.trim().isEmpty()) {
+ response.sendRedirect(request.getContextPath() + "/user/reservation/list");
+ return; // ← 必须加return
+ }
+
+ Long id = Long.parseLong(idStr);
+ boolean success = reservationDao.cancel(id, loginUser.getId());
+
+ if (success) {
+ // ✅ 成功:重定向到预约列表,带成功消息
+ String encodedMsg = URLEncoder.encode("取消预约成功", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/reservation/list?msg=" + encodedMsg);
+ } else {
+ // ❌ 失败:重定向到预约列表,带错误消息
+ String encodedError = URLEncoder.encode("取消预约失败", "UTF-8");
+ response.sendRedirect(request.getContextPath() + "/user/reservation/list?error=" + encodedError);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/controller/user/ReservationListController.java b/HRS/src/com/hrs/controller/user/ReservationListController.java
new file mode 100644
index 0000000..58739d8
--- /dev/null
+++ b/HRS/src/com/hrs/controller/user/ReservationListController.java
@@ -0,0 +1,63 @@
+package com.hrs.controller.user;
+
+import com.hrs.dao.ReservationDao;
+import com.hrs.dao.impl.ReservationDaoImpl;
+import com.hrs.model.entity.Reservation;
+import com.hrs.model.entity.User;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: ReservationListController.java
+* @Description: 我的预约列表控制器(租客端)
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午9:12:43
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+@WebServlet("/user/reservation/list")
+public class ReservationListController extends HttpServlet {
+
+ private ReservationDao reservationDao = new ReservationDaoImpl();
+
+ @Override
+ protected void doGet(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+
+ // 获取登录用户
+ HttpSession session = request.getSession(false);
+ if (session == null) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ User loginUser = (User) session.getAttribute("loginUser");
+ if (loginUser == null || !"0".equals(loginUser.getRoleType())) {
+ response.sendRedirect(request.getContextPath() + "/user/login");
+ return;
+ }
+
+ // 查询预约列表
+ List reservationList = reservationDao.findByTenantId(loginUser.getId());
+
+ request.setAttribute("reservationList", reservationList);
+ request.setAttribute("totalCount", reservationList.size());
+ request.setAttribute("loginUser", loginUser);
+
+ request.getRequestDispatcher("/jsp/user/reservation_list.jsp").forward(request, response);
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/dao/CollectionDao.java b/HRS/src/com/hrs/dao/CollectionDao.java
new file mode 100644
index 0000000..4a4817e
--- /dev/null
+++ b/HRS/src/com/hrs/dao/CollectionDao.java
@@ -0,0 +1,136 @@
+package com.hrs.dao;
+
+import com.hrs.model.entity.Collection;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: CollectionDao.java
+* @Description: 收藏数据层
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:30:25
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public interface CollectionDao {
+ /**
+ *
+ * @Function: add
+ * @Description: 添加收藏
+ *
+ * @param: collection 收藏对象
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:37:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean add(Collection collection);
+ /**
+ *
+ * @Function: isCollected
+ * @Description: 判断是否已收藏
+ *
+ * @param: tenantId 租客ID, houseId 房源ID
+ * @return:boolean 是否已收藏
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:37:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean isCollected(Long tenantId, Long houseId);
+ /**
+ *
+ * @Function: delete
+ * @Description: 删除收藏(根据租客和房源)
+ *
+ * @param: tenantId 租客ID, houseId 房源ID
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:38:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean delete(Long tenantId, Long houseId);
+ /**
+ *
+ * @Function: deleteById
+ * @Description: 删除收藏(根据ID)
+ *
+ * @param: id 收藏ID
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:38:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean deleteById(Long id);
+ /**
+ *
+ * @Function: findByTenantId
+ * @Description: 根据租客ID查询收藏列表
+ *
+ * @param: tenantId 租客ID
+ * @return:List 收藏列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:38:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findByTenantId(Long tenantId);
+ /**
+ *
+ * @Function: countByTenantId
+ * @Description: 统计租客的收藏数量
+ *
+ * @param: tenantId 租客ID
+ * @return:int 收藏数量
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:38:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ int countByTenantId(Long tenantId);
+}
diff --git a/HRS/src/com/hrs/dao/HouseDao.java b/HRS/src/com/hrs/dao/HouseDao.java
new file mode 100644
index 0000000..f0ee771
--- /dev/null
+++ b/HRS/src/com/hrs/dao/HouseDao.java
@@ -0,0 +1,307 @@
+package com.hrs.dao;
+
+import com.hrs.model.entity.House;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: HouseDao.java
+* @Description: 房源数据层
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:31:08
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public interface HouseDao {
+ /**
+ *
+ * @Function: findPublishedHouses
+ * @Description: 查询已上架的房源
+ *
+ * @param: 无
+ * @return:List 房源列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:28:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findPublishedHouses();
+ /**
+ *
+ * @Function: findHousesByArea
+ * @Description: 根据区域查询房源
+ *
+ * @param: area 区域名称
+ * @return:List 房源列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:28:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findHousesByArea(String area);
+ /**
+ *
+ * @Function: findHousesByPrice
+ * @Description: 根据价格范围查询房源
+ *
+ * @param: minPrice 最低价格, maxPrice 最高价格
+ * @return:List 房源列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:28:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findHousesByPrice(int minPrice, int maxPrice);
+ /**
+ *
+ * @Function: findById
+ * @Description: 根据ID查询房源
+ *
+ * @param: id 房源ID
+ * @return:House 房源对象,未找到返回null
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:28:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ House findById(Long id);
+ /**
+ *
+ * @Function: findByLandlordId
+ * @Description: 根据房东ID查询房源
+ *
+ * @param: landlordId 房东ID
+ * @return:List 房源列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:29:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findByLandlordId(Long landlordId);
+ /**
+ *
+ * @Function: findAll
+ * @Description: 查询所有房源
+ *
+ * @param: 无
+ * @return:List 房源列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:29:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findAll();
+ /**
+ *
+ * @Function: findPendingHouses
+ * @Description: 查询待审核的房源
+ *
+ * @param: 无
+ * @return:List 房源列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:29:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findPendingHouses();
+ /**
+ *
+ * @Function: findPublishedHousesForAdmin
+ * @Description: 管理员查询已上架的房源
+ *
+ * @param: 无
+ * @return:List 房源列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:29:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findPublishedHousesForAdmin();
+ /**
+ *
+ * @Function: findOfflineHouses
+ * @Description: 查询已下架的房源
+ *
+ * @param: 无
+ * @return:List 房源列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:30:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findOfflineHouses();
+ /**
+ *
+ * @Function: add
+ * @Description: 添加房源
+ *
+ * @param: house 房源对象
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:30:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean add(House house);
+ /**
+ *
+ * @Function: update
+ * @Description: 更新房源信息
+ *
+ * @param: house 房源对象
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:30:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean update(House house);
+ /**
+ *
+ * @Function: updateStatus
+ * @Description: 更新房源状态
+ *
+ * @param: houseId 房源ID, status 状态
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:30:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean updateStatus(Long houseId, String status);
+ /**
+ *
+ * @Function: delete
+ * @Description: 删除房源
+ *
+ * @param: id 房源ID
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:31:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean delete(Long id);
+ /**
+ *
+ * @Function: countPublished
+ * @Description: 统计已上架房源数量
+ *
+ * @param: 无
+ * @return:int 已上架房源数量
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:31:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ int countPublished();
+ /**
+ *
+ * @Function: countAll
+ * @Description: 统计所有房源数量
+ *
+ * @param: 无
+ * @return:int 房源总数
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:31:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ int countAll();
+}
diff --git a/HRS/src/com/hrs/dao/OrderDao.java b/HRS/src/com/hrs/dao/OrderDao.java
new file mode 100644
index 0000000..fc26846
--- /dev/null
+++ b/HRS/src/com/hrs/dao/OrderDao.java
@@ -0,0 +1,250 @@
+package com.hrs.dao;
+
+import com.hrs.model.entity.Order;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: OrderDao.java
+* @Description: 订单数据层
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:31:25
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public interface OrderDao {
+ /**
+ *
+ * @Function: add
+ * @Description: 添加订单
+ *
+ * @param: order 订单对象
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:32:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean add(Order order);
+ /**
+ *
+ * @Function: findByTenantId
+ * @Description: 根据租客ID查询订单
+ *
+ * @param: tenantId 租客ID
+ * @return:List 订单列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:32:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findByTenantId(Long tenantId);
+ /**
+ *
+ * @Function: findByLandlordId
+ * @Description: 根据房东ID查询订单
+ *
+ * @param: landlordId 房东ID
+ * @return:List 订单列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:32:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findByLandlordId(Long landlordId);
+ /**
+ *
+ * @Function: findById
+ * @Description: 根据ID查询订单
+ *
+ * @param: id 订单ID
+ * @return:Order 订单对象,未找到返回null
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:32:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ Order findById(Long id);
+ /**
+ *
+ * @Function: findByOrderNo
+ * @Description: 根据订单编号查询订单
+ *
+ * @param: orderNo 订单编号
+ * @return:Order 订单对象,未找到返回null
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:33:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ Order findByOrderNo(String orderNo);
+ /**
+ *
+ * @Function: updateStatus
+ * @Description: 更新订单状态
+ *
+ * @param: orderId 订单ID, status 状态
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:33:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean updateStatus(Long orderId, String status);
+ /**
+ *
+ * @Function: updatePayStatus
+ * @Description: 更新支付状态
+ *
+ * @param: orderId 订单ID, payStatus 支付状态
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:33:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean updatePayStatus(Long orderId, String payStatus);
+ /**
+ *
+ * @Function: countByTenantId
+ * @Description: 统计租客的订单数量
+ *
+ * @param: tenantId 租客ID
+ * @return:int 订单数量
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:33:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ int countByTenantId(Long tenantId);
+ /**
+ *
+ * @Function: countByLandlordId
+ * @Description: 统计房东的订单数量
+ *
+ * @param: landlordId 房东ID
+ * @return:int 订单数量
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:34:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ int countByLandlordId(Long landlordId);
+ /**
+ *
+ * @Function: existsByHouseId
+ * @Description: 判断房源是否存在订单
+ *
+ * @param: houseId 房源ID
+ * @return:boolean 是否存在订单
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:34:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean existsByHouseId(Long houseId);
+ /**
+ *
+ * @Function: findAll
+ * @Description: 查询所有订单
+ *
+ * @param: 无
+ * @return:List 订单列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:34:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findAll();
+ /**
+ *
+ * @Function: countAll
+ * @Description: 统计所有订单数量
+ *
+ * @param: 无
+ * @return:int 订单总数
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:34:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ int countAll();
+}
diff --git a/HRS/src/com/hrs/dao/ReservationDao.java b/HRS/src/com/hrs/dao/ReservationDao.java
new file mode 100644
index 0000000..d9863b3
--- /dev/null
+++ b/HRS/src/com/hrs/dao/ReservationDao.java
@@ -0,0 +1,193 @@
+package com.hrs.dao;
+
+import com.hrs.model.entity.Reservation;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: ReservationDao.java
+* @Description: 预约控制层
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:32:15
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public interface ReservationDao {
+ /**
+ *
+ * @Function: add
+ * @Description: 添加预约
+ *
+ * @param: reservation 预约对象
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:35:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean add(Reservation reservation);
+ /**
+ *
+ * @Function: findByTenantId
+ * @Description: 根据租客ID查询预约
+ *
+ * @param: tenantId 租客ID
+ * @return:List 预约列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:35:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findByTenantId(Long tenantId);
+ /**
+ *
+ * @Function: findByLandlordId
+ * @Description: 根据房东ID查询预约
+ *
+ * @param: landlordId 房东ID
+ * @return:List 预约列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:35:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findByLandlordId(Long landlordId);
+ /**
+ *
+ * @Function: findById
+ * @Description: 根据ID查询预约
+ *
+ * @param: id 预约ID
+ * @return:Reservation 预约对象,未找到返回null
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:35:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ Reservation findById(Long id);
+ /**
+ *
+ * @Function: updateStatus
+ * @Description: 更新预约状态
+ *
+ * @param: id 预约ID, status 状态
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:36:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean updateStatus(Long id, String status);
+ /**
+ *
+ * @Function: cancel
+ * @Description: 取消预约
+ *
+ * @param: id 预约ID, tenantId 租客ID
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:36:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean cancel(Long id, Long tenantId);
+ /**
+ *
+ * @Function: countByTenantId
+ * @Description: 统计租客的预约数量
+ *
+ * @param: tenantId 租客ID
+ * @return:int 预约数量
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:36:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ int countByTenantId(Long tenantId);
+ /**
+ *
+ * @Function: countByLandlordId
+ * @Description: 统计房东的预约数量
+ *
+ * @param: landlordId 房东ID
+ * @return:int 预约数量
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:36:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ int countByLandlordId(Long landlordId);
+ /**
+ *
+ * @Function: existsByHouseId
+ * @Description: 判断房源是否存在预约
+ *
+ * @param: houseId 房源ID
+ * @return:boolean 是否存在预约
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:37:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean existsByHouseId(Long houseId);
+}
diff --git a/HRS/src/com/hrs/dao/UserDao.java b/HRS/src/com/hrs/dao/UserDao.java
new file mode 100644
index 0000000..a81da7a
--- /dev/null
+++ b/HRS/src/com/hrs/dao/UserDao.java
@@ -0,0 +1,250 @@
+package com.hrs.dao;
+
+import com.hrs.model.entity.User;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: UserDao.java
+* @Description: 用户数据层
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:32:28
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public interface UserDao {
+ /**
+ *
+ * @Function: findByUsernameAndPassword
+ * @Description: 根据用户名和密码查询用户
+ *
+ * @param: username 用户名, password 密码
+ * @return:User 用户对象,未找到返回null
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:25:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ User findByUsernameAndPassword(String username, String password);
+ /**
+ *
+ * @Function: findByUsername
+ * @Description: 根据用户名查询用户
+ *
+ * @param: username 用户名
+ * @return:User 用户对象,未找到返回null
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:25:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ User findByUsername(String username);
+ /**
+ *
+ * @Function: findByPhone
+ * @Description: 根据手机号查询用户
+ *
+ * @param: phone 手机号
+ * @return:User 用户对象,未找到返回null
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:25:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ User findByPhone(String phone);
+ /**
+ *
+ * @Function: findById
+ * @Description: 根据ID查询用户
+ *
+ * @param: id 用户ID
+ * @return:User 用户对象,未找到返回null
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:25:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ User findById(Long id);
+ /**
+ *
+ * @Function: findAll
+ * @Description: 查询所有用户
+ *
+ * @param: 无
+ * @return:List 用户列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:26:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findAll();
+ /**
+ *
+ * @Function: findAllTenants
+ * @Description: 查询所有租客
+ *
+ * @param: 无
+ * @return:List 租客列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:26:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findAllTenants();
+ /**
+ *
+ * @Function: findAllLandlords
+ * @Description: 查询所有房东
+ *
+ * @param: 无
+ * @return:List 房东列表
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:26:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ List findAllLandlords();
+ /**
+ *
+ * @Function: add
+ * @Description: 添加用户
+ *
+ * @param: user 用户对象
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:26:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean add(User user);
+ /**
+ *
+ * @Function: update
+ * @Description: 更新用户信息
+ *
+ * @param: user 用户对象
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:27:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean update(User user);
+ /**
+ *
+ * @Function: updateStatus
+ * @Description: 更新用户状态
+ *
+ * @param: userId 用户ID, status 状态
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:27:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean updateStatus(Long userId, String status);
+ /**
+ *
+ * @Function: delete
+ * @Description: 删除用户
+ *
+ * @param: id 用户ID
+ * @return:boolean 是否成功
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:27:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ boolean delete(Long id);
+ /**
+ *
+ * @Function: count
+ * @Description: 统计用户总数
+ *
+ * @param: 无
+ * @return:int 用户总数
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:27:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ int count();
+}
diff --git a/HRS/src/com/hrs/dao/impl/CollectionDaoImpl.java b/HRS/src/com/hrs/dao/impl/CollectionDaoImpl.java
new file mode 100644
index 0000000..b83b394
--- /dev/null
+++ b/HRS/src/com/hrs/dao/impl/CollectionDaoImpl.java
@@ -0,0 +1,224 @@
+package com.hrs.dao.impl;
+
+import com.hrs.dao.CollectionDao;
+import com.hrs.dao.HouseDao;
+import com.hrs.model.entity.Collection;
+import com.hrs.model.entity.House;
+import com.hrs.util.DBUtil;
+
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: CollectionDaoImpl.java
+* @Description: 收藏数据访问实现类
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:33:33
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public class CollectionDaoImpl implements CollectionDao {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ /**
+ * 添加收藏
+ */
+ @Override
+ public boolean add(Collection collection) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "INSERT INTO hrs_collection (tenant_id, house_id, collect_time, create_time) " +
+ "VALUES (?, ?, NOW(), NOW())";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, collection.getTenantId());
+ pstmt.setLong(2, collection.getHouseId());
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ * 检查是否已收藏
+ */
+ @Override
+ public boolean isCollected(Long tenantId, Long houseId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ boolean exists = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT COUNT(*) FROM hrs_collection WHERE tenant_id = ? AND house_id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, tenantId);
+ pstmt.setLong(2, houseId);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ exists = rs.getInt(1) > 0;
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return exists;
+ }
+
+ /**
+ * 取消收藏
+ */
+ @Override
+ public boolean delete(Long tenantId, Long houseId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "DELETE FROM hrs_collection WHERE tenant_id = ? AND house_id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, tenantId);
+ pstmt.setLong(2, houseId);
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ * 根据收藏ID删除
+ */
+ @Override
+ public boolean deleteById(Long id) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "DELETE FROM hrs_collection WHERE id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, id);
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ * 查询租客的所有收藏
+ */
+ @Override
+ public List findByTenantId(Long tenantId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List collectionList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_collection WHERE tenant_id = ? ORDER BY collect_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, tenantId);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ Collection collection = resultSetToCollection(rs);
+ // 查询关联的房源详情
+ House house = houseDao.findById(collection.getHouseId());
+ collection.setHouse(house);
+ collectionList.add(collection);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return collectionList;
+ }
+
+ /**
+ * 查询租客的收藏数量
+ */
+ @Override
+ public int countByTenantId(Long tenantId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ int count = 0;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT COUNT(*) FROM hrs_collection WHERE tenant_id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, tenantId);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ count = rs.getInt(1);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return count;
+ }
+
+ /**
+ * 将ResultSet转换为Collection对象
+ */
+ private Collection resultSetToCollection(ResultSet rs) throws SQLException {
+ Collection collection = new Collection();
+ collection.setId(rs.getLong("id"));
+ collection.setTenantId(rs.getLong("tenant_id"));
+ collection.setHouseId(rs.getLong("house_id"));
+ collection.setCollectTime(rs.getTimestamp("collect_time"));
+ collection.setCreateBy(rs.getString("create_by"));
+ collection.setCreateTime(rs.getTimestamp("create_time"));
+ return collection;
+ }
+}
diff --git a/HRS/src/com/hrs/dao/impl/HouseDaoImpl.java b/HRS/src/com/hrs/dao/impl/HouseDaoImpl.java
new file mode 100644
index 0000000..6b44c8c
--- /dev/null
+++ b/HRS/src/com/hrs/dao/impl/HouseDaoImpl.java
@@ -0,0 +1,548 @@
+package com.hrs.dao.impl;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.model.entity.House;
+import com.hrs.util.DBUtil;
+
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: HouseDaoImpl.java
+* @Description: 房源数据访问实现类/负责房源表的增删改查操作
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:34:28
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public class HouseDaoImpl implements HouseDao {
+
+ /**
+ * 查询已上架的房源(供租客查看)
+ */
+ @Override
+ public List findPublishedHouses() {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List houseList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT h.*, u.real_name as landlord_name, u.phone as landlord_phone " +
+ "FROM hrs_house h " +
+ "LEFT JOIN hrs_user u ON h.landlord_id = u.id " +
+ "WHERE h.status = '1' " +
+ "ORDER BY h.create_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ houseList.add(resultSetToHouse(rs));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return houseList;
+ }
+
+ /**
+ * 根据区域筛选房源
+ */
+ @Override
+ public List findHousesByArea(String area) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List houseList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT h.*, u.real_name as landlord_name, u.phone as landlord_phone " +
+ "FROM hrs_house h " +
+ "LEFT JOIN hrs_user u ON h.landlord_id = u.id " +
+ "WHERE h.status = '1' AND h.area LIKE ? " +
+ "ORDER BY h.create_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, "%" + area + "%");
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ houseList.add(resultSetToHouse(rs));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return houseList;
+ }
+
+ /**
+ * 根据价格区间筛选房源
+ */
+ @Override
+ public List findHousesByPrice(int minPrice, int maxPrice) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List houseList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT h.*, u.real_name as landlord_name, u.phone as landlord_phone " +
+ "FROM hrs_house h " +
+ "LEFT JOIN hrs_user u ON h.landlord_id = u.id " +
+ "WHERE h.status = '1' AND h.rent_price BETWEEN ? AND ? " +
+ "ORDER BY h.rent_price ASC";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setInt(1, minPrice);
+ pstmt.setInt(2, maxPrice);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ houseList.add(resultSetToHouse(rs));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return houseList;
+ }
+
+ /**
+ * 根据房源ID查询详情
+ */
+ @Override
+ public House findById(Long id) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ House house = null;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT h.*, u.real_name as landlord_name, u.phone as landlord_phone " +
+ "FROM hrs_house h " +
+ "LEFT JOIN hrs_user u ON h.landlord_id = u.id " +
+ "WHERE h.id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, id);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ house = resultSetToHouse(rs);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return house;
+ }
+
+ /**
+ * 查询房东自己的房源
+ */
+ @Override
+ public List findByLandlordId(Long landlordId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List houseList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_house WHERE landlord_id = ? ORDER BY create_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, landlordId);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ houseList.add(resultSetToHouse(rs));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return houseList;
+ }
+
+ /**
+ * 查询所有房源(管理员用)
+ */
+ @Override
+ public List findAll() {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List houseList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT h.*, u.real_name as landlord_name " +
+ "FROM hrs_house h " +
+ "LEFT JOIN hrs_user u ON h.landlord_id = u.id " +
+ "ORDER BY h.create_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ houseList.add(resultSetToHouse(rs));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return houseList;
+ }
+
+ /**
+ * 查询待审核房源(管理员用)
+ */
+ @Override
+ public List findPendingHouses() {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List houseList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT h.*, u.real_name as landlord_name, u.phone as landlord_phone " +
+ "FROM hrs_house h " +
+ "LEFT JOIN hrs_user u ON h.landlord_id = u.id " +
+ "WHERE h.status = '0' " +
+ "ORDER BY h.create_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ houseList.add(resultSetToHouse(rs));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return houseList;
+ }
+
+ /**
+ * 查询已上架房源(管理员用)
+ */
+ @Override
+ public List findPublishedHousesForAdmin() {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List houseList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT h.*, u.real_name as landlord_name, u.phone as landlord_phone " +
+ "FROM hrs_house h " +
+ "LEFT JOIN hrs_user u ON h.landlord_id = u.id " +
+ "WHERE h.status = '1' " +
+ "ORDER BY h.create_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ houseList.add(resultSetToHouse(rs));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return houseList;
+ }
+
+ /**
+ * 查询已下架房源(管理员用)
+ */
+ @Override
+ public List findOfflineHouses() {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List houseList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT h.*, u.real_name as landlord_name, u.phone as landlord_phone " +
+ "FROM hrs_house h " +
+ "LEFT JOIN hrs_user u ON h.landlord_id = u.id " +
+ "WHERE h.status IN ('2', '3') " +
+ "ORDER BY h.create_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ houseList.add(resultSetToHouse(rs));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return houseList;
+ }
+
+ /**
+ * 添加房源
+ */
+ @Override
+ public boolean add(House house) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "INSERT INTO hrs_house (landlord_id, house_no, title, area, address, " +
+ "house_type, rent_price, rent_type, facility, description, img_url, " +
+ "status, create_time) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW())";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, house.getLandlordId());
+ pstmt.setString(2, house.getHouseNo());
+ pstmt.setString(3, house.getTitle());
+ pstmt.setString(4, house.getArea());
+ pstmt.setString(5, house.getAddress());
+ pstmt.setString(6, house.getHouseType());
+ pstmt.setBigDecimal(7, house.getRentPrice());
+ pstmt.setString(8, house.getRentType());
+ pstmt.setString(9, house.getFacility());
+ pstmt.setString(10, house.getDescription());
+ pstmt.setString(11, house.getImgUrl());
+ pstmt.setString(12, house.getStatus() != null ? house.getStatus() : "0");
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ * 更新房源
+ */
+ @Override
+ public boolean update(House house) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "UPDATE hrs_house SET title=?, area=?, address=?, house_type=?, " +
+ "rent_price=?, rent_type=?, facility=?, description=?, img_url=?, " +
+ "update_time=NOW() WHERE id=?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, house.getTitle());
+ pstmt.setString(2, house.getArea());
+ pstmt.setString(3, house.getAddress());
+ pstmt.setString(4, house.getHouseType());
+ pstmt.setBigDecimal(5, house.getRentPrice());
+ pstmt.setString(6, house.getRentType());
+ pstmt.setString(7, house.getFacility());
+ pstmt.setString(8, house.getDescription());
+ pstmt.setString(9, house.getImgUrl());
+ pstmt.setLong(10, house.getId());
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ * 更新房源状态(审核/上架/下架)
+ */
+ @Override
+ public boolean updateStatus(Long houseId, String status) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "UPDATE hrs_house SET status=?, update_time=NOW() WHERE id=?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, status);
+ pstmt.setLong(2, houseId);
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ * 删除房源
+ */
+ @Override
+ public boolean delete(Long id) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "DELETE FROM hrs_house WHERE id=?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, id);
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ * 统计已上架房源数量
+ */
+ @Override
+ public int countPublished() {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ int count = 0;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT COUNT(*) FROM hrs_house WHERE status = '1'";
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ count = rs.getInt(1);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return count;
+ }
+
+ /**
+ * 统计房源总数(管理员用)
+ */
+ @Override
+ public int countAll() {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ int count = 0;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT COUNT(*) FROM hrs_house";
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ count = rs.getInt(1);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return count;
+ }
+
+ /**
+ * 将ResultSet转换为House对象
+ */
+ private House resultSetToHouse(ResultSet rs) throws SQLException {
+ House house = new House();
+ house.setId(rs.getLong("id"));
+ house.setLandlordId(rs.getLong("landlord_id"));
+ house.setHouseNo(rs.getString("house_no"));
+ house.setTitle(rs.getString("title"));
+ house.setArea(rs.getString("area"));
+ house.setAddress(rs.getString("address"));
+ house.setHouseType(rs.getString("house_type"));
+ house.setRentPrice(rs.getBigDecimal("rent_price"));
+ house.setRentType(rs.getString("rent_type"));
+ house.setFacility(rs.getString("facility"));
+ house.setDescription(rs.getString("description"));
+ house.setImgUrl(rs.getString("img_url"));
+ house.setStatus(rs.getString("status"));
+ house.setCreateBy(rs.getString("create_by"));
+ house.setCreateTime(rs.getTimestamp("create_time"));
+ house.setUpdateBy(rs.getString("update_by"));
+ house.setUpdateTime(rs.getTimestamp("update_time"));
+
+ // 关联字段
+ try {
+ house.setLandlordName(rs.getString("landlord_name"));
+ house.setLandlordPhone(rs.getString("landlord_phone"));
+ } catch (SQLException e) {
+ // 可能没有这些字段
+ }
+
+ return house;
+ }
+}
diff --git a/HRS/src/com/hrs/dao/impl/OrderDaoImpl.java b/HRS/src/com/hrs/dao/impl/OrderDaoImpl.java
new file mode 100644
index 0000000..1d0db18
--- /dev/null
+++ b/HRS/src/com/hrs/dao/impl/OrderDaoImpl.java
@@ -0,0 +1,435 @@
+package com.hrs.dao.impl;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.OrderDao;
+import com.hrs.model.entity.House;
+import com.hrs.model.entity.Order;
+import com.hrs.model.entity.User;
+import com.hrs.util.DBUtil;
+
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: OrderDaoImpl.java
+* @Description: 订单数据访问实现类
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:34:55
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public class OrderDaoImpl implements OrderDao {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+ private UserDaoImpl userDao = new UserDaoImpl();
+
+ /**
+ * 添加订单
+ */
+ @Override
+ public boolean add(Order order) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "INSERT INTO hrs_order (tenant_id, house_id, order_no, rent_start_time, " +
+ "rent_end_time, total_rent, pay_status, status, create_time) " +
+ "VALUES (?, ?, ?, ?, ?, ?, '0', '0', NOW())";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, order.getTenantId());
+ pstmt.setLong(2, order.getHouseId());
+ pstmt.setString(3, order.getOrderNo());
+ pstmt.setTimestamp(4, new Timestamp(order.getRentStartTime().getTime()));
+ pstmt.setTimestamp(5, new Timestamp(order.getRentEndTime().getTime()));
+ pstmt.setBigDecimal(6, order.getTotalRent());
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ * 根据租客ID查询订单列表
+ */
+ @Override
+ public List findByTenantId(Long tenantId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List orderList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_order WHERE tenant_id = ? ORDER BY create_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, tenantId);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ Order order = resultSetToOrder(rs);
+ orderList.add(order);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return orderList;
+ }
+
+ /**
+ * 根据房东ID查询订单列表
+ */
+ @Override
+ public List findByLandlordId(Long landlordId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List orderList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT o.* FROM hrs_order o " +
+ "INNER JOIN hrs_house h ON o.house_id = h.id " +
+ "WHERE h.landlord_id = ? " +
+ "ORDER BY o.create_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, landlordId);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ Order order = resultSetToOrder(rs);
+ orderList.add(order);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return orderList;
+ }
+
+ /**
+ * 根据订单ID查询
+ */
+ @Override
+ public Order findById(Long id) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ Order order = null;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_order WHERE id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, id);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ order = resultSetToOrder(rs);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return order;
+ }
+
+ /**
+ * 根据订单编号查询
+ */
+ @Override
+ public Order findByOrderNo(String orderNo) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ Order order = null;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_order WHERE order_no = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, orderNo);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ order = resultSetToOrder(rs);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return order;
+ }
+
+ /**
+ * 更新订单状态
+ */
+ @Override
+ public boolean updateStatus(Long orderId, String status) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "UPDATE hrs_order SET status=?, update_time=NOW() WHERE id=?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, status);
+ pstmt.setLong(2, orderId);
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ * 更新支付状态
+ */
+ @Override
+ public boolean updatePayStatus(Long orderId, String payStatus) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "UPDATE hrs_order SET pay_status=?, update_time=NOW() WHERE id=?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, payStatus);
+ pstmt.setLong(2, orderId);
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ * 统计租客订单数量
+ */
+ @Override
+ public int countByTenantId(Long tenantId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ int count = 0;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT COUNT(*) FROM hrs_order WHERE tenant_id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, tenantId);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ count = rs.getInt(1);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return count;
+ }
+
+ /**
+ * 统计房东订单数量
+ */
+ @Override
+ public int countByLandlordId(Long landlordId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ int count = 0;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT COUNT(*) FROM hrs_order o " +
+ "INNER JOIN hrs_house h ON o.house_id = h.id " +
+ "WHERE h.landlord_id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, landlordId);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ count = rs.getInt(1);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return count;
+ }
+
+ /**
+ * 检查房源是否存在关联订单
+ */
+ @Override
+ public boolean existsByHouseId(Long houseId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT COUNT(*) FROM hrs_order WHERE house_id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, houseId);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ return rs.getInt(1) > 0;
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return false;
+ }
+
+ /**
+ * 查询所有订单(管理员用)
+ */
+ @Override
+ public List findAll() {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List orderList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT o.* FROM hrs_order o " +
+ "ORDER BY o.create_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ Order order = resultSetToOrder(rs);
+ orderList.add(order);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return orderList;
+ }
+
+ /**
+ * 统计所有订单数量(管理员用)
+ */
+ @Override
+ public int countAll() {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ int count = 0;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT COUNT(*) FROM hrs_order";
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ count = rs.getInt(1);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return count;
+ }
+
+ /**
+ * 将ResultSet转换为Order对象
+ */
+ private Order resultSetToOrder(ResultSet rs) throws SQLException {
+ Order order = new Order();
+ order.setId(rs.getLong("id"));
+ order.setTenantId(rs.getLong("tenant_id"));
+ order.setHouseId(rs.getLong("house_id"));
+ order.setOrderNo(rs.getString("order_no"));
+ order.setRentStartTime(rs.getTimestamp("rent_start_time"));
+ order.setRentEndTime(rs.getTimestamp("rent_end_time"));
+ order.setTotalRent(rs.getBigDecimal("total_rent"));
+ order.setPayStatus(rs.getString("pay_status"));
+ order.setStatus(rs.getString("status"));
+ order.setCreateBy(rs.getString("create_by"));
+ order.setCreateTime(rs.getTimestamp("create_time"));
+ order.setUpdateBy(rs.getString("update_by"));
+ order.setUpdateTime(rs.getTimestamp("update_time"));
+
+ try {
+ House house = houseDao.findById(order.getHouseId());
+ order.setHouse(house);
+ } catch (Exception e) {
+ // 忽略
+ }
+
+ try {
+ User tenant = userDao.findById(order.getTenantId());
+ order.setTenant(tenant);
+ } catch (Exception e) {
+ // 忽略
+ }
+
+ return order;
+ }
+}
diff --git a/HRS/src/com/hrs/dao/impl/ReservationDaoImpl.java b/HRS/src/com/hrs/dao/impl/ReservationDaoImpl.java
new file mode 100644
index 0000000..bf74530
--- /dev/null
+++ b/HRS/src/com/hrs/dao/impl/ReservationDaoImpl.java
@@ -0,0 +1,338 @@
+package com.hrs.dao.impl;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.ReservationDao;
+import com.hrs.dao.UserDao;
+import com.hrs.model.entity.Reservation;
+import com.hrs.model.entity.House;
+import com.hrs.model.entity.User;
+import com.hrs.util.DBUtil;
+
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: ReservationDaoImpl.java
+* @Description: 预约看房数据访问实现类
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:35:10
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public class ReservationDaoImpl implements ReservationDao {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+ private UserDao userDao = new UserDaoImpl();
+
+ /**
+ * 添加预约
+ */
+ @Override
+ public boolean add(Reservation reservation) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "INSERT INTO hrs_reservation (tenant_id, house_id, landlord_id, reserve_time, remark, status, create_time) " +
+ "VALUES (?, ?, ?, ?, ?, '0', NOW())";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, reservation.getTenantId());
+ pstmt.setLong(2, reservation.getHouseId());
+ pstmt.setLong(3, reservation.getLandlordId());
+ pstmt.setTimestamp(4, new Timestamp(reservation.getReserveTime().getTime()));
+ pstmt.setString(5, reservation.getRemark());
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ * 查询租客的所有预约
+ */
+ @Override
+ public List findByTenantId(Long tenantId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List reservationList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_reservation WHERE tenant_id = ? ORDER BY reserve_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, tenantId);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ Reservation reservation = resultSetToReservation(rs);
+ // 关联房源详情
+ House house = houseDao.findById(reservation.getHouseId());
+ reservation.setHouse(house);
+ reservationList.add(reservation);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return reservationList;
+ }
+
+ /**
+ * 查询房东收到的预约
+ */
+ @Override
+ public List findByLandlordId(Long landlordId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List reservationList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_reservation WHERE landlord_id = ? ORDER BY reserve_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, landlordId);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ Reservation reservation = resultSetToReservation(rs);
+ // 关联房源详情
+ House house = houseDao.findById(reservation.getHouseId());
+ reservation.setHouse(house);
+ // 关联租客信息
+ User tenant = userDao.findById(reservation.getTenantId());
+ reservation.setTenant(tenant);
+ reservationList.add(reservation);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return reservationList;
+ }
+
+ /**
+ * 根据ID查询预约
+ */
+ @Override
+ public Reservation findById(Long id) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ Reservation reservation = null;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_reservation WHERE id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, id);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ reservation = resultSetToReservation(rs);
+ House house = houseDao.findById(reservation.getHouseId());
+ reservation.setHouse(house);
+ User tenant = userDao.findById(reservation.getTenantId());
+ reservation.setTenant(tenant);
+ User landlord = userDao.findById(reservation.getLandlordId());
+ reservation.setLandlord(landlord);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return reservation;
+ }
+
+ /**
+ * 更新预约状态(房东确认/取消)
+ */
+ @Override
+ public boolean updateStatus(Long id, String status) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "UPDATE hrs_reservation SET status=?, handle_time=NOW(), update_time=NOW() WHERE id=?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, status);
+ pstmt.setLong(2, id);
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ * 取消预约(租客取消)
+ */
+ @Override
+ public boolean cancel(Long id, Long tenantId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "UPDATE hrs_reservation SET status='2', update_time=NOW() WHERE id=? AND tenant_id=?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, id);
+ pstmt.setLong(2, tenantId);
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ * 统计租客的预约数量
+ */
+ @Override
+ public int countByTenantId(Long tenantId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ int count = 0;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT COUNT(*) FROM hrs_reservation WHERE tenant_id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, tenantId);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ count = rs.getInt(1);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return count;
+ }
+
+ /**
+ * 统计房东的预约数量
+ */
+ @Override
+ public int countByLandlordId(Long landlordId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ int count = 0;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT COUNT(*) FROM hrs_reservation WHERE landlord_id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, landlordId);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ count = rs.getInt(1);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return count;
+ }
+
+ /**
+ * 检查房源是否存在关联预约
+ */
+ @Override
+ public boolean existsByHouseId(Long houseId) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT COUNT(*) FROM hrs_reservation WHERE house_id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, houseId);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ return rs.getInt(1) > 0;
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return false;
+ }
+
+ /**
+ * 将ResultSet转换为Reservation对象
+ */
+ private Reservation resultSetToReservation(ResultSet rs) throws SQLException {
+ Reservation reservation = new Reservation();
+ reservation.setId(rs.getLong("id"));
+ reservation.setTenantId(rs.getLong("tenant_id"));
+ reservation.setHouseId(rs.getLong("house_id"));
+ reservation.setLandlordId(rs.getLong("landlord_id"));
+ reservation.setReserveTime(rs.getTimestamp("reserve_time"));
+ reservation.setRemark(rs.getString("remark"));
+ reservation.setStatus(rs.getString("status"));
+ reservation.setHandleTime(rs.getTimestamp("handle_time"));
+ reservation.setCreateBy(rs.getString("create_by"));
+ reservation.setCreateTime(rs.getTimestamp("create_time"));
+ reservation.setUpdateBy(rs.getString("update_by"));
+ reservation.setUpdateTime(rs.getTimestamp("update_time"));
+ return reservation;
+ }
+}
diff --git a/HRS/src/com/hrs/dao/impl/UserDaoImpl.java b/HRS/src/com/hrs/dao/impl/UserDaoImpl.java
new file mode 100644
index 0000000..3a47c55
--- /dev/null
+++ b/HRS/src/com/hrs/dao/impl/UserDaoImpl.java
@@ -0,0 +1,602 @@
+package com.hrs.dao.impl;
+
+import com.hrs.dao.UserDao;
+import com.hrs.model.entity.User;
+import com.hrs.util.DBUtil;
+import java.sql.*;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: UserDaoImpl.java
+* @Description: 用户数据访问实现类/负责用户表的增删改查操作
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:35:47
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public class UserDaoImpl implements UserDao {
+ /**
+ *
+ * @Function: findByUsernameAndPassword
+ * @Description: 根据用户名和密码查询用户(登录用)
+ *
+ * @param: username 用户名, password 密码
+ * @return:User 用户对象,未找到返回null
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:40:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public User findByUsernameAndPassword(String username, String password) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ User user = null;
+
+ try {
+ // 1. 获取连接
+ conn = DBUtil.getConnection();
+
+ // 2. 编写SQL(注意:实际项目密码应该是加密后比较,这里简化)
+ String sql = "SELECT * FROM hrs_user WHERE user_name = ? AND password = ?";
+
+ // 3. 创建预编译语句
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, username);
+ pstmt.setString(2, password); // 实际应该是MD5加密后比较
+
+ // 4. 执行查询
+ rs = pstmt.executeQuery();
+
+ // 5. 处理结果集
+ if (rs.next()) {
+ user = resultSetToUser(rs);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ // 6. 释放资源
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return user;
+ }
+
+ /**
+ *
+ * @Function: findByUsername
+ * @Description: 根据用户名查询用户(检查用户名是否已存在)
+ *
+ * @param: username 用户名
+ * @return:User 用户对象,未找到返回null
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:40:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public User findByUsername(String username) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ User user = null;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_user WHERE user_name = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, username);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ user = resultSetToUser(rs);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return user;
+ }
+ /**
+ *
+ * @Function: findByPhone
+ * @Description: 根据手机号查询用户(检查手机号是否已注册)
+ *
+ * @param: phone 手机号
+ * @return:User 用户对象,未找到返回null
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:41:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public User findByPhone(String phone) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ User user = null;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_user WHERE phone = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, phone);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ user = resultSetToUser(rs);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return user;
+ }
+ /**
+ *
+ * @Function: findById
+ * @Description: 根据ID查询用户
+ *
+ * @param: id 用户ID
+ * @return:User 用户对象,未找到返回null
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:41:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public User findById(Long id) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ User user = null;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_user WHERE id = ?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, id);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ user = resultSetToUser(rs);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return user;
+ }
+ /**
+ *
+ * @Function: findAll
+ * @Description: 查询所有用户(管理员用)
+ *
+ * @param: 无
+ * @return:List 用户列表
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:42:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public List findAll() {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List userList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_user ORDER BY create_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ userList.add(resultSetToUser(rs));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return userList;
+ }
+
+ /**
+ *
+ * @Function: findAllTenants
+ * @Description: 查询所有租客
+ *
+ * @param: 无
+ * @return:List 租客列表
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:42:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public List findAllTenants() {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List userList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_user WHERE role_type = '0' ORDER BY create_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ userList.add(resultSetToUser(rs));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return userList;
+ }
+ /**
+ *
+ * @Function: findAllLandlords
+ * @Description: 查询所有房东
+ *
+ * @param: 无
+ * @return:List 房东列表
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:43:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public List findAllLandlords() {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ List userList = new ArrayList<>();
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT * FROM hrs_user WHERE role_type = '1' ORDER BY create_time DESC";
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+
+ while (rs.next()) {
+ userList.add(resultSetToUser(rs));
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return userList;
+ }
+
+ /**
+ *
+ * @Function: add
+ * @Description: 添加用户(注册用)
+ *
+ * @param: user 用户对象
+ * @return:boolean 是否成功
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:43:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public boolean add(User user) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "INSERT INTO hrs_user (user_name, password, real_name, phone, id_card, role_type, status, create_time) " +
+ "VALUES (?, ?, ?, ?, ?, ?, ?, NOW())";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, user.getUserName());
+ pstmt.setString(2, user.getPassword());
+ pstmt.setString(3, user.getRealName());
+ pstmt.setString(4, user.getPhone());
+ pstmt.setString(5, user.getIdCard());
+ pstmt.setString(6, user.getRoleType());
+ pstmt.setString(7, user.getStatus() != null ? user.getStatus() : "0"); // 默认未认证
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ *
+ * @Function: update
+ * @Description: 更新用户信息
+ *
+ * @param: user 用户对象
+ * @return:boolean 是否成功
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:44:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public boolean update(User user) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "UPDATE hrs_user SET real_name=?, phone=?, id_card=?, status=?, update_time=NOW() WHERE id=?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, user.getRealName());
+ pstmt.setString(2, user.getPhone());
+ pstmt.setString(3, user.getIdCard());
+ pstmt.setString(4, user.getStatus());
+ pstmt.setLong(5, user.getId());
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+ /**
+ *
+ * @Function: updateStatus
+ * @Description: 更新用户状态(启用/禁用)
+ *
+ * @param: userId 用户ID, status 状态
+ * @return:boolean 是否成功
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:44:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public boolean updateStatus(Long userId, String status) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "UPDATE hrs_user SET status=?, update_time=NOW() WHERE id=?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setString(1, status);
+ pstmt.setLong(2, userId);
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ *
+ * @Function: delete
+ * @Description: 删除用户(物理删除,一般不建议)
+ *
+ * @param: id 用户ID
+ * @return:boolean 是否成功
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:45:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public boolean delete(Long id) {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ boolean success = false;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "DELETE FROM hrs_user WHERE id=?";
+ pstmt = conn.prepareStatement(sql);
+ pstmt.setLong(1, id);
+
+ int rows = pstmt.executeUpdate();
+ success = rows > 0;
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(pstmt, conn);
+ }
+
+ return success;
+ }
+
+ /**
+ *
+ * @Function: count
+ * @Description: 统计用户总数
+ *
+ * @param: 无
+ * @return:int 用户总数
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:45:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public int count() {
+ Connection conn = null;
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ int count = 0;
+
+ try {
+ conn = DBUtil.getConnection();
+ String sql = "SELECT COUNT(*) FROM hrs_user";
+ pstmt = conn.prepareStatement(sql);
+ rs = pstmt.executeQuery();
+
+ if (rs.next()) {
+ count = rs.getInt(1);
+ }
+
+ } catch (SQLException e) {
+ e.printStackTrace();
+ } finally {
+ DBUtil.close(rs, pstmt, conn);
+ }
+
+ return count;
+ }
+
+
+ /**
+ *
+ * @Function: resultSetToUser
+ * @Description: 将ResultSet转换为User对象
+ *
+ * @param: rs 结果集
+ * @return:User 用户对象
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:46:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ private User resultSetToUser(ResultSet rs) throws SQLException {
+ User user = new User();
+ user.setId(rs.getLong("id"));
+ user.setUserName(rs.getString("user_name"));
+ user.setPassword(rs.getString("password"));
+ user.setRealName(rs.getString("real_name"));
+ user.setPhone(rs.getString("phone"));
+ user.setIdCard(rs.getString("id_card"));
+ user.setRoleType(rs.getString("role_type"));
+ user.setStatus(rs.getString("status"));
+ user.setCreateBy(rs.getString("create_by"));
+ user.setCreateTime(rs.getTimestamp("create_time"));
+ user.setUpdateBy(rs.getString("update_by"));
+ user.setUpdateTime(rs.getTimestamp("update_time"));
+ return user;
+ }
+}
diff --git a/HRS/src/com/hrs/filter/EncodingFilter.java b/HRS/src/com/hrs/filter/EncodingFilter.java
new file mode 100644
index 0000000..9a96f72
--- /dev/null
+++ b/HRS/src/com/hrs/filter/EncodingFilter.java
@@ -0,0 +1,49 @@
+package com.hrs.filter;
+
+import javax.servlet.*;
+import javax.servlet.annotation.WebFilter;
+import java.io.IOException;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: EncodingFilter.java
+* @Description: 字符编码过滤器
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:36:34
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+@WebFilter("/*")
+public class EncodingFilter implements Filter {
+
+ private String encoding = "UTF-8";
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ String param = filterConfig.getInitParameter("encoding");
+ if (param != null && !param.isEmpty()) {
+ encoding = param;
+ }
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ // 设置请求编码
+ request.setCharacterEncoding(encoding);
+ // 设置响应编码
+ response.setCharacterEncoding(encoding);
+ // 继续执行
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ public void destroy() {
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/filter/LoginFilter.java b/HRS/src/com/hrs/filter/LoginFilter.java
new file mode 100644
index 0000000..536903a
--- /dev/null
+++ b/HRS/src/com/hrs/filter/LoginFilter.java
@@ -0,0 +1,104 @@
+package com.hrs.filter;
+
+import com.hrs.model.entity.User;
+
+import javax.servlet.*;
+import javax.servlet.annotation.WebFilter;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: LoginFilter.java
+* @Description: 登录过滤器/拦截未登录的请求
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:36:48
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+@WebFilter("/*") // 拦截所有请求
+public class LoginFilter implements Filter {
+
+ // 不需要登录就能访问的路径
+ private static final String[] PUBLIC_PATHS = {
+ "/user/login", // 登录页面
+ "/user/register", // 注册页面 ✅ 新增
+ "/css/", // 静态资源
+ "/js/",
+ "/images/",
+ "/jsp/common/", // 公共页面
+ "/index.jsp" // 首页
+ };
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ System.out.println("登录过滤器初始化");
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+
+ HttpServletRequest req = (HttpServletRequest) request;
+ HttpServletResponse resp = (HttpServletResponse) response;
+
+ // 1. 获取请求路径
+ String path = req.getRequestURI().substring(req.getContextPath().length());
+ System.out.println("过滤器拦截路径:" + path);
+
+ // 2. 判断是否是公开路径
+ if (isPublicPath(path)) {
+ chain.doFilter(request, response);
+ return;
+ }
+
+ // 3. 检查Session中是否有登录用户
+ HttpSession session = req.getSession(false);
+ User loginUser = null;
+ if (session != null) {
+ loginUser = (User) session.getAttribute("loginUser");
+ }
+
+ // 4. 如果没登录,跳转到登录页
+ if (loginUser == null) {
+ System.out.println("未登录,拦截请求:" + path);
+ resp.sendRedirect(req.getContextPath() + "/user/login");
+ return;
+ }
+
+ // 5. 已登录,继续请求
+ chain.doFilter(request, response);
+ }
+
+ /**
+ * 判断是否是公开路径
+ */
+ private boolean isPublicPath(String path) {
+ // 如果是根路径,放行(通常重定向到首页)
+ if (path == null || path.equals("/") || path.isEmpty()) {
+ return true;
+ }
+
+ // 检查是否在公开路径列表中
+ for (String publicPath : PUBLIC_PATHS) {
+ if (path.startsWith(publicPath)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void destroy() {
+ System.out.println("登录过滤器销毁");
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/model/entity/Collection.java b/HRS/src/com/hrs/model/entity/Collection.java
new file mode 100644
index 0000000..73e6890
--- /dev/null
+++ b/HRS/src/com/hrs/model/entity/Collection.java
@@ -0,0 +1,369 @@
+package com.hrs.model.entity;
+
+import java.util.Date;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: Collection.java
+* @Description: 收藏实体类
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:58:59
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public class Collection {
+
+ private Long id; // 主键ID
+ private Long tenantId; // 租客ID
+ private Long houseId; // 房源ID
+ private Date collectTime; // 收藏时间
+ private String createBy; // 创建人
+ private Date createTime; // 创建时间
+
+ // 关联字段(不存数据库,用于显示)
+ private House house; // 房源详情
+
+ /**
+ *
+ * @Function: Collection
+ * @Description: 无参构造方法
+ *
+ * @param: 无
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:20:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Collection() {
+ }
+ /**
+ *
+ * @Function: Collection
+ * @Description: 带参构造方法
+ *
+ * @param: tenantId 租客ID, houseId 房源ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:20:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Collection(Long tenantId, Long houseId) {
+ this.tenantId = tenantId;
+ this.houseId = houseId;
+ }
+
+ /**
+ *
+ * @Function: getId
+ * @Description: 获取主键ID
+ *
+ * @param: 无
+ * @return:Long 主键ID
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:21:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Long getId() {
+ return id;
+ }
+ /**
+ *
+ * @Function: setId
+ * @Description: 设置主键ID
+ *
+ * @param: id 主键ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:21:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+ /**
+ *
+ * @Function: getTenantId
+ * @Description: 获取租客ID
+ *
+ * @param: 无
+ * @return:Long 租客ID
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:21:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Long getTenantId() {
+ return tenantId;
+ }
+ /**
+ *
+ * @Function: setTenantId
+ * @Description: 设置租客ID
+ *
+ * @param: tenantId 租客ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:21:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setTenantId(Long tenantId) {
+ this.tenantId = tenantId;
+ }
+ /**
+ *
+ * @Function: getHouseId
+ * @Description: 获取房源ID
+ *
+ * @param: 无
+ * @return:Long 房源ID
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:22:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Long getHouseId() {
+ return houseId;
+ }
+ /**
+ *
+ * @Function: setHouseId
+ * @Description: 设置房源ID
+ *
+ * @param: houseId 房源ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:22:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setHouseId(Long houseId) {
+ this.houseId = houseId;
+ }
+ /**
+ *
+ * @Function: getCollectTime
+ * @Description: 获取收藏时间
+ *
+ * @param: 无
+ * @return:Date 收藏时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:22:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Date getCollectTime() {
+ return collectTime;
+ }
+ /**
+ *
+ * @Function: setCollectTime
+ * @Description: 设置收藏时间
+ *
+ * @param: collectTime 收藏时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:22:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setCollectTime(Date collectTime) {
+ this.collectTime = collectTime;
+ }
+ /**
+ *
+ * @Function: getCreateBy
+ * @Description: 获取创建人
+ *
+ * @param: 无
+ * @return:String 创建人
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:23:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getCreateBy() {
+ return createBy;
+ }
+ /**
+ *
+ * @Function: setCreateBy
+ * @Description: 设置创建人
+ *
+ * @param: createBy 创建人
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:23:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setCreateBy(String createBy) {
+ this.createBy = createBy;
+ }
+ /**
+ *
+ * @Function: getCreateTime
+ * @Description: 获取创建时间
+ *
+ * @param: 无
+ * @return:Date 创建时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:23:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Date getCreateTime() {
+ return createTime;
+ }
+ /**
+ *
+ * @Function: setCreateTime
+ * @Description: 设置创建时间
+ *
+ * @param: createTime 创建时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:23:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+ /**
+ *
+ * @Function: getHouse
+ * @Description: 获取房源详情
+ *
+ * @param: 无
+ * @return:House 房源对象
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:24:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public House getHouse() {
+ return house;
+ }
+ /**
+ *
+ * @Function: setHouse
+ * @Description: 设置房源详情
+ *
+ * @param: house 房源对象
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:24:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setHouse(House house) {
+ this.house = house;
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/model/entity/House.java b/HRS/src/com/hrs/model/entity/House.java
new file mode 100644
index 0000000..1032865
--- /dev/null
+++ b/HRS/src/com/hrs/model/entity/House.java
@@ -0,0 +1,964 @@
+package com.hrs.model.entity;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: House.java
+* @Description: 房源实体类
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:59:13
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public class House {
+
+ private Long id; // 主键ID
+ private Long landlordId; // 房东ID
+ private String houseNo; // 房源编号
+ private String title; // 房源标题
+ private String area; // 房源区域
+ private String address; // 详细地址
+ private String houseType; // 户型
+ private BigDecimal rentPrice; // 月租金
+ private String rentType; // 租赁类型:0-整租;1-合租
+ private String facility; // 配套设施
+ private String description; // 房源描述
+ private String imgUrl; // 房源图片路径
+ private String status; // 房源状态:0-待审核;1-已上架;2-已下架;3-违规
+ private String createBy; // 创建人
+ private Date createTime; // 创建时间
+ private String updateBy; // 更新人
+ private Date updateTime; // 更新时间
+
+ // 关联字段(不存数据库,用于显示房东信息)
+ private String landlordName; // 房东姓名
+ private String landlordPhone; // 房东电话
+ /**
+ *
+ * @Function: House
+ * @Description: 无参构造方法
+ *
+ * @param: 无
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:56:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public House() {
+ }
+ /**
+ *
+ * @Function: getId
+ * @Description: 获取主键ID
+ *
+ * @param: 无
+ * @return:Long 主键ID
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:56:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ // Getter 和 Setter
+ public Long getId() {
+ return id;
+ }
+ /**
+ *
+ * @Function: setId
+ * @Description: 设置主键ID
+ *
+ * @param: id 主键ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:57:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+ /**
+ *
+ * @Function: getLandlordId
+ * @Description: 获取房东ID
+ *
+ * @param: 无
+ * @return:Long 房东ID
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:57:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Long getLandlordId() {
+ return landlordId;
+ }
+ /**
+ *
+ * @Function: setLandlordId
+ * @Description: 设置房东ID
+ *
+ * @param: landlordId 房东ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:57:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setLandlordId(Long landlordId) {
+ this.landlordId = landlordId;
+ }
+ /**
+ *
+ * @Function: getHouseNo
+ * @Description: 获取房源编号
+ *
+ * @param: 无
+ * @return:String 房源编号
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:57:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getHouseNo() {
+ return houseNo;
+ }
+ /**
+ *
+ * @Function: setHouseNo
+ * @Description: 设置房源编号
+ *
+ * @param: houseNo 房源编号
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:58:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setHouseNo(String houseNo) {
+ this.houseNo = houseNo;
+ }
+ /**
+ *
+ * @Function: getTitle
+ * @Description: 获取房源标题
+ *
+ * @param: 无
+ * @return:String 房源标题
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:58:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getTitle() {
+ return title;
+ }
+ /**
+ *
+ * @Function: setTitle
+ * @Description: 设置房源标题
+ *
+ * @param: title 房源标题
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:58:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setTitle(String title) {
+ this.title = title;
+ }
+ /**
+ *
+ * @Function: getArea
+ * @Description: 获取房源区域
+ *
+ * @param: 无
+ * @return:String 房源区域
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:58:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getArea() {
+ return area;
+ }
+ /**
+ *
+ * @Function: setArea
+ * @Description: 设置房源区域
+ *
+ * @param: area 房源区域
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:59:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setArea(String area) {
+ this.area = area;
+ }
+ /**
+ *
+ * @Function: getAddress
+ * @Description: 获取详细地址
+ *
+ * @param: 无
+ * @return:String 详细地址
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:59:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getAddress() {
+ return address;
+ }
+ /**
+ *
+ * @Function: setAddress
+ * @Description: 设置详细地址
+ *
+ * @param: address 详细地址
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:59:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setAddress(String address) {
+ this.address = address;
+ }
+ /**
+ *
+ * @Function: getHouseType
+ * @Description: 获取户型
+ *
+ * @param: 无
+ * @return:String 户型
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:59:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getHouseType() {
+ return houseType;
+ }
+ /**
+ *
+ * @Function: setHouseType
+ * @Description: 设置户型
+ *
+ * @param: houseType 户型
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:00:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setHouseType(String houseType) {
+ this.houseType = houseType;
+ }
+ /**
+ *
+ * @Function: getRentPrice
+ * @Description: 获取月租金
+ *
+ * @param: 无
+ * @return:BigDecimal 月租金
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:00:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public BigDecimal getRentPrice() {
+ return rentPrice;
+ }
+ /**
+ *
+ * @Function: setRentPrice
+ * @Description: 设置月租金
+ *
+ * @param: rentPrice 月租金
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:00:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setRentPrice(BigDecimal rentPrice) {
+ this.rentPrice = rentPrice;
+ }
+ /**
+ *
+ * @Function: getRentType
+ * @Description: 获取租赁类型
+ *
+ * @param: 无
+ * @return:String 租赁类型(0-整租;1-合租)
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:00:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getRentType() {
+ return rentType;
+ }
+ /**
+ *
+ * @Function: setRentType
+ * @Description: 设置租赁类型
+ *
+ * @param: rentType 租赁类型(0-整租;1-合租)
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:01:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setRentType(String rentType) {
+ this.rentType = rentType;
+ }
+ /**
+ *
+ * @Function: getRentTypeText
+ * @Description: 获取租赁类型文本
+ *
+ * @param: 无
+ * @return:String 租赁类型文本(整租/合租)
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:01:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getRentTypeText() {
+ return "0".equals(rentType) ? "整租" : "合租";
+ }
+ /**
+ *
+ * @Function: getFacility
+ * @Description: 获取配套设施
+ *
+ * @param: 无
+ * @return:String 配套设施
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:01:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getFacility() {
+ return facility;
+ }
+ /**
+ *
+ * @Function: setFacility
+ * @Description: 设置配套设施
+ *
+ * @param: facility 配套设施
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:01:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setFacility(String facility) {
+ this.facility = facility;
+ }
+ /**
+ *
+ * @Function: getDescription
+ * @Description: 获取房源描述
+ *
+ * @param: 无
+ * @return:String 房源描述
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:02:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getDescription() {
+ return description;
+ }
+ /**
+ *
+ * @Function: setDescription
+ * @Description: 设置房源描述
+ *
+ * @param: description 房源描述
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:02:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setDescription(String description) {
+ this.description = description;
+ }
+ /**
+ *
+ * @Function: getImgUrl
+ * @Description: 获取房源图片路径
+ *
+ * @param: 无
+ * @return:String 房源图片路径
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:02:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getImgUrl() {
+ return imgUrl;
+ }
+ /**
+ *
+ * @Function: getImgUrl
+ * @Description: 获取房源图片路径
+ *
+ * @param: 无
+ * @return:String 房源图片路径
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:02:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setImgUrl(String imgUrl) {
+ this.imgUrl = imgUrl;
+ }
+ /**
+ *
+ * @Function: getStatus
+ * @Description: 获取房源状态
+ *
+ * @param: 无
+ * @return:String 房源状态(0-待审核;1-已上架;2-已下架;3-违规)
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:03:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getStatus() {
+ return status;
+ }
+ /**
+ *
+ * @Function: getStatus
+ * @Description: 获取房源状态
+ *
+ * @param: 无
+ * @return:String 房源状态(0-待审核;1-已上架;2-已下架;3-违规)
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:03:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setStatus(String status) {
+ this.status = status;
+ }
+ /**
+ *
+ * @Function: getStatusText
+ * @Description: 获取房源状态文本
+ *
+ * @param: 无
+ * @return:String 房源状态文本
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:03:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getStatusText() {
+ switch (status) {
+ case "0": return "待审核";
+ case "1": return "已上架";
+ case "2": return "已下架";
+ case "3": return "违规";
+ default: return "未知";
+ }
+ }
+ /**
+ *
+ * @Function: getCreateBy
+ * @Description: 获取创建人
+ *
+ * @param: 无
+ * @return:String 创建人
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:03:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getCreateBy() {
+ return createBy;
+ }
+ /**
+ *
+ * @Function: setCreateBy
+ * @Description: 设置创建人
+ *
+ * @param: createBy 创建人
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:04:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setCreateBy(String createBy) {
+ this.createBy = createBy;
+ }
+ /**
+ *
+ * @Function: getCreateTime
+ * @Description: 获取创建时间
+ *
+ * @param: 无
+ * @return:Date 创建时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:04:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Date getCreateTime() {
+ return createTime;
+ }
+ /**
+ *
+ * @Function: setCreateTime
+ * @Description: 设置创建时间
+ *
+ * @param: createTime 创建时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:04:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+ /**
+ *
+ * @Function: getUpdateBy
+ * @Description: 获取更新人
+ *
+ * @param: 无
+ * @return:String 更新人
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:04:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getUpdateBy() {
+ return updateBy;
+ }
+ /**
+ *
+ * @Function: setUpdateBy
+ * @Description: 设置更新人
+ *
+ * @param: updateBy 更新人
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:05:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setUpdateBy(String updateBy) {
+ this.updateBy = updateBy;
+ }
+ /**
+ *
+ * @Function: getUpdateTime
+ * @Description: 获取更新时间
+ *
+ * @param: 无
+ * @return:Date 更新时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:05:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+ /**
+ *
+ * @Function: setUpdateTime
+ * @Description: 设置更新时间
+ *
+ * @param: updateTime 更新时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:05:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+ /**
+ *
+ * @Function: getLandlordName
+ * @Description: 获取房东姓名
+ *
+ * @param: 无
+ * @return:String 房东姓名
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:05:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getLandlordName() {
+ return landlordName;
+ }
+ /**
+ *
+ * @Function: setLandlordName
+ * @Description: 设置房东姓名
+ *
+ * @param: landlordName 房东姓名
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:06:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setLandlordName(String landlordName) {
+ this.landlordName = landlordName;
+ }
+ /**
+ *
+ * @Function: getLandlordPhone
+ * @Description: 获取房东电话
+ *
+ * @param: 无
+ * @return:String 房东电话
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:06:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getLandlordPhone() {
+ return landlordPhone;
+ }
+ /**
+ *
+ * @Function: setLandlordPhone
+ * @Description: 设置房东电话
+ *
+ * @param: landlordPhone 房东电话
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:06:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setLandlordPhone(String landlordPhone) {
+ this.landlordPhone = landlordPhone;
+ }
+ /**
+ *
+ * @Function: getFirstImage
+ * @Description: 获取第一张图片(用于列表展示)
+ *
+ * @param: 无
+ * @return:String 第一张图片路径
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:06:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getFirstImage() {
+ if (imgUrl != null && !imgUrl.isEmpty()) {
+ String[] images = imgUrl.split(",");
+ return images[0];
+ }
+ return null;
+ }
+ /**
+ *
+ * @Function: toString
+ * @Description: 重写toString方法
+ *
+ * @param: 无
+ * @return:String 对象字符串表示
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:07:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public String toString() {
+ return "House{" +
+ "id=" + id +
+ ", title='" + title + '\'' +
+ ", area='" + area + '\'' +
+ ", rentPrice=" + rentPrice +
+ ", status='" + status + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/model/entity/Order.java b/HRS/src/com/hrs/model/entity/Order.java
new file mode 100644
index 0000000..8078b92
--- /dev/null
+++ b/HRS/src/com/hrs/model/entity/Order.java
@@ -0,0 +1,839 @@
+package com.hrs.model.entity;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: Order.java
+* @Description: 订单实体类
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:59:27
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public class Order {
+
+ private Long id; // 主键ID
+ private Long tenantId; // 租客ID
+ private Long houseId; // 房源ID
+ private String orderNo; // 订单编号
+ private Date rentStartTime; // 租赁开始时间
+ private Date rentEndTime; // 租赁结束时间
+ private BigDecimal totalRent; // 总租金
+ private String payStatus; // 支付状态:0-待支付;1-已支付;2-已退款
+ private String status; // 订单状态:0-待签约;1-已签约;2-已结束;3-已取消
+ private String createBy; // 创建人
+ private Date createTime; // 创建时间
+ private String updateBy; // 更新人
+ private Date updateTime; // 更新时间
+
+ // 关联字段(不存数据库)
+ private House house; // 房源详情
+ private User tenant; // 租客信息
+ private User landlord; // 房东信息
+ /**
+ *
+ * @Function: Order
+ * @Description: 无参构造方法
+ *
+ * @param: 无
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:08:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Order() {
+ }
+ /**
+ *
+ * @Function: getId
+ * @Description: 获取主键ID
+ *
+ * @param: 无
+ * @return:Long 主键ID
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:08:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Long getId() {
+ return id;
+ }
+ /**
+ *
+ * @Function: setId
+ * @Description: 设置主键ID
+ *
+ * @param: id 主键ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:08:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+ /**
+ *
+ * @Function: getTenantId
+ * @Description: 获取租客ID
+ *
+ * @param: 无
+ * @return:Long 租客ID
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:09:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public Long getTenantId() {
+ return tenantId;
+ }
+ /**
+ *
+ * @Function: setTenantId
+ * @Description: 设置租客ID
+ *
+ * @param: tenantId 租客ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:09:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setTenantId(Long tenantId) {
+ this.tenantId = tenantId;
+ }
+ /**
+ *
+ * @Function: getHouseId
+ * @Description: 获取房源ID
+ *
+ * @param: 无
+ * @return:Long 房源ID
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:09:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public Long getHouseId() {
+ return houseId;
+ }
+ /**
+ *
+ * @Function: setHouseId
+ * @Description: 设置房源ID
+ *
+ * @param: houseId 房源ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:09:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setHouseId(Long houseId) {
+ this.houseId = houseId;
+ }
+ /**
+ *
+ * @Function: getOrderNo
+ * @Description: 获取订单编号
+ *
+ * @param: 无
+ * @return:String 订单编号
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:10:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public String getOrderNo() {
+ return orderNo;
+ }
+ /**
+ *
+ * @Function: setOrderNo
+ * @Description: 设置订单编号
+ *
+ * @param: orderNo 订单编号
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:10:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setOrderNo(String orderNo) {
+ this.orderNo = orderNo;
+ }
+ /**
+ *
+ * @Function: getRentStartTime
+ * @Description: 获取租赁开始时间
+ *
+ * @param: 无
+ * @return:Date 租赁开始时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:10:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public Date getRentStartTime() {
+ return rentStartTime;
+ }
+ /**
+ *
+ * @Function: setRentStartTime
+ * @Description: 设置租赁开始时间
+ *
+ * @param: rentStartTime 租赁开始时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:10:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setRentStartTime(Date rentStartTime) {
+ this.rentStartTime = rentStartTime;
+ }
+ /**
+ *
+ * @Function: getRentEndTime
+ * @Description: 获取租赁结束时间
+ *
+ * @param: 无
+ * @return:Date 租赁结束时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:11:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public Date getRentEndTime() {
+ return rentEndTime;
+ }
+ /**
+ *
+ * @Function: setRentEndTime
+ * @Description: 设置租赁结束时间
+ *
+ * @param: rentEndTime 租赁结束时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:11:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setRentEndTime(Date rentEndTime) {
+ this.rentEndTime = rentEndTime;
+ }
+ /**
+ *
+ * @Function: getTotalRent
+ * @Description: 获取总租金
+ *
+ * @param: 无
+ * @return:BigDecimal 总租金
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:11:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public BigDecimal getTotalRent() {
+ return totalRent;
+ }
+ /**
+ *
+ * @Function: setTotalRent
+ * @Description: 设置总租金
+ *
+ * @param: totalRent 总租金
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:11:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setTotalRent(BigDecimal totalRent) {
+ this.totalRent = totalRent;
+ }
+ /**
+ *
+ * @Function: getPayStatus
+ * @Description: 获取支付状态
+ *
+ * @param: 无
+ * @return:String 支付状态(0-待支付;1-已支付;2-已退款)
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:12:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public String getPayStatus() {
+ return payStatus;
+ }
+ /**
+ *
+ * @Function: setPayStatus
+ * @Description: 设置支付状态
+ *
+ * @param: payStatus 支付状态(0-待支付;1-已支付;2-已退款)
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:12:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setPayStatus(String payStatus) {
+ this.payStatus = payStatus;
+ }
+ /**
+ *
+ * @Function: getPayStatusText
+ * @Description: 获取支付状态文本
+ *
+ * @param: 无
+ * @return:String 支付状态文本
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:09:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getPayStatusText() {
+ switch (payStatus) {
+ case "0": return "待支付";
+ case "1": return "已支付";
+ case "2": return "已退款";
+ default: return "未知";
+ }
+ }
+ /**
+ *
+ * @Function: getStatus
+ * @Description: 获取订单状态
+ *
+ * @param: 无
+ * @return:String 订单状态(0-待签约;1-已签约;2-已结束;3-已取消)
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:12:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public String getStatus() {
+ return status;
+ }
+ /**
+ *
+ * @Function: setStatus
+ * @Description: 设置订单状态
+ *
+ * @param: status 订单状态(0-待签约;1-已签约;2-已结束;3-已取消)
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:13:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setStatus(String status) {
+ this.status = status;
+ }
+ /**
+ *
+ * @Function: getStatusText
+ * @Description: 获取订单状态文本
+ *
+ * @param: 无
+ * @return:String 订单状态文本
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:09:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getStatusText() {
+ switch (status) {
+ case "0": return "待签约";
+ case "1": return "已签约";
+ case "2": return "已结束";
+ case "3": return "已取消";
+ default: return "未知";
+ }
+ }
+ /**
+ *
+ * @Function: getCreateBy
+ * @Description: 获取创建人
+ *
+ * @param: 无
+ * @return:String 创建人
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:13:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public String getCreateBy() {
+ return createBy;
+ }
+ /**
+ *
+ * @Function: setCreateBy
+ * @Description: 设置创建人
+ *
+ * @param: createBy 创建人
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:13:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setCreateBy(String createBy) {
+ this.createBy = createBy;
+ }
+ /**
+ *
+ * @Function: getCreateTime
+ * @Description: 获取创建时间
+ *
+ * @param: 无
+ * @return:Date 创建时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:14:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public Date getCreateTime() {
+ return createTime;
+ }
+ /**
+ *
+ * @Function: setCreateTime
+ * @Description: 设置创建时间
+ *
+ * @param: createTime 创建时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:14:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+ /**
+ *
+ * @Function: getUpdateBy
+ * @Description: 获取更新人
+ *
+ * @param: 无
+ * @return:String 更新人
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:14:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public String getUpdateBy() {
+ return updateBy;
+ }
+ /**
+ *
+ * @Function: setUpdateBy
+ * @Description: 设置更新人
+ *
+ * @param: updateBy 更新人
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:14:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setUpdateBy(String updateBy) {
+ this.updateBy = updateBy;
+ }
+ /**
+ *
+ * @Function: getUpdateTime
+ * @Description: 获取更新时间
+ *
+ * @param: 无
+ * @return:Date 更新时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:15:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+ /**
+ *
+ * @Function: setUpdateTime
+ * @Description: 设置更新时间
+ *
+ * @param: updateTime 更新时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:15:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+ /**
+ *
+ * @Function: getHouse
+ * @Description: 获取房源详情
+ *
+ * @param: 无
+ * @return:House 房源对象
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:15:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public House getHouse() {
+ return house;
+ }
+ /**
+ *
+ * @Function: setHouse
+ * @Description: 设置房源详情
+ *
+ * @param: house 房源对象
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:15:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setHouse(House house) {
+ this.house = house;
+ }
+ /**
+ *
+ * @Function: getTenant
+ * @Description: 获取租客信息
+ *
+ * @param: 无
+ * @return:User 租客对象
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:16:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public User getTenant() {
+ return tenant;
+ }
+ /**
+ *
+ * @Function: setTenant
+ * @Description: 设置租客信息
+ *
+ * @param: tenant 租客对象
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:16:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setTenant(User tenant) {
+ this.tenant = tenant;
+ }
+ /**
+ *
+ * @Function: getLandlord
+ * @Description: 获取房东信息
+ *
+ * @param: 无
+ * @return:User 房东对象
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:16:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public User getLandlord() {
+ return landlord;
+ }
+ /**
+ *
+ * @Function: setLandlord
+ * @Description: 设置房东信息
+ *
+ * @param: landlord 房东对象
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李洪涛
+ * @date: 2025年4月13日 下午3:16:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 李洪涛 v1.0.0 新建方法
+ */
+ public void setLandlord(User landlord) {
+ this.landlord = landlord;
+ }
+
+ /**
+ *
+ * @Function: getRentDays
+ * @Description: 计算租赁天数
+ *
+ * @param: 无
+ * @return:int 租赁天数
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:10:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public int getRentDays() {
+ if (rentStartTime == null || rentEndTime == null) {
+ return 0;
+ }
+ long diff = rentEndTime.getTime() - rentStartTime.getTime();
+ return (int) (diff / (1000 * 60 * 60 * 24));
+ }
+ /**
+ *
+ * @Function: toString
+ * @Description: 重写toString方法
+ *
+ * @param: 无
+ * @return:String 对象字符串表示
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:10:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public String toString() {
+ return "Order{" +
+ "id=" + id +
+ ", orderNo='" + orderNo + '\'' +
+ ", totalRent=" + totalRent +
+ ", status='" + status + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/model/entity/Reservation.java b/HRS/src/com/hrs/model/entity/Reservation.java
new file mode 100644
index 0000000..4085d7a
--- /dev/null
+++ b/HRS/src/com/hrs/model/entity/Reservation.java
@@ -0,0 +1,743 @@
+package com.hrs.model.entity;
+
+import java.util.Date;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: Reservation.java
+* @Description: 预约看房实体类
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午9:59:56
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public class Reservation {
+
+ private Long id; // 主键ID
+ private Long tenantId; // 租客ID
+ private Long houseId; // 房源ID
+ private Long landlordId; // 房东ID
+ private Date reserveTime; // 预约看房时间
+ private String remark; // 租客备注
+ private String status; // 预约状态:0-待确认;1-已确认;2-已取消;3-已完成
+ private Date handleTime; // 房东处理时间
+ private String createBy; // 创建人
+ private Date createTime; // 创建时间
+ private String updateBy; // 更新人
+ private Date updateTime; // 更新时间
+
+ // 关联字段(不存数据库)
+ private House house; // 房源详情
+ private User tenant; // 租客信息
+ private User landlord; // 房东信息
+ /**
+ *
+ * @Function: Reservation
+ * @Description: 无参构造方法
+ *
+ * @param: 无
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:11:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Reservation() {
+ }
+ /**
+ *
+ * @Function: getId
+ * @Description: 获取主键ID
+ *
+ * @param: 无
+ * @return:Long 主键ID
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:11:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Long getId() {
+ return id;
+ }
+ /**
+ *
+ * @Function: setId
+ * @Description: 设置主键ID
+ *
+ * @param: id 主键ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:12:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+ /**
+ *
+ * @Function: getTenantId
+ * @Description: 获取租客ID
+ *
+ * @param: 无
+ * @return:Long 租客ID
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:12:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Long getTenantId() {
+ return tenantId;
+ }
+ /**
+ *
+ * @Function: setTenantId
+ * @Description: 设置租客ID
+ *
+ * @param: tenantId 租客ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:12:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setTenantId(Long tenantId) {
+ this.tenantId = tenantId;
+ }
+ /**
+ *
+ * @Function: getHouseId
+ * @Description: 获取房源ID
+ *
+ * @param: 无
+ * @return:Long 房源ID
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:12:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Long getHouseId() {
+ return houseId;
+ }
+ /**
+ *
+ * @Function: setHouseId
+ * @Description: 设置房源ID
+ *
+ * @param: houseId 房源ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:13:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setHouseId(Long houseId) {
+ this.houseId = houseId;
+ }
+ /**
+ *
+ * @Function: getLandlordId
+ * @Description: 获取房东ID
+ *
+ * @param: 无
+ * @return:Long 房东ID
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:13:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Long getLandlordId() {
+ return landlordId;
+ }
+ /**
+ *
+ * @Function: setLandlordId
+ * @Description: 设置房东ID
+ *
+ * @param: landlordId 房东ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:13:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setLandlordId(Long landlordId) {
+ this.landlordId = landlordId;
+ }
+ /**
+ *
+ * @Function: getReserveTime
+ * @Description: 获取预约看房时间
+ *
+ * @param: 无
+ * @return:Date 预约看房时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:13:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Date getReserveTime() {
+ return reserveTime;
+ }
+ /**
+ *
+ * @Function: setReserveTime
+ * @Description: 设置预约看房时间
+ *
+ * @param: reserveTime 预约看房时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:14:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setReserveTime(Date reserveTime) {
+ this.reserveTime = reserveTime;
+ }
+ /**
+ *
+ * @Function: getRemark
+ * @Description: 获取租客备注
+ *
+ * @param: 无
+ * @return:String 租客备注
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:14:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getRemark() {
+ return remark;
+ }
+ /**
+ *
+ * @Function: setRemark
+ * @Description: 设置租客备注
+ *
+ * @param: remark 租客备注
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:14:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setRemark(String remark) {
+ this.remark = remark;
+ }
+ /**
+ *
+ * @Function: getStatus
+ * @Description: 获取预约状态
+ *
+ * @param: 无
+ * @return:String 预约状态(0-待确认;1-已确认;2-已取消;3-已完成)
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:14:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getStatus() {
+ return status;
+ }
+ /**
+ *
+ * @Function: setStatus
+ * @Description: 设置预约状态
+ *
+ * @param: status 预约状态(0-待确认;1-已确认;2-已取消;3-已完成)
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:15:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setStatus(String status) {
+ this.status = status;
+ }
+ /**
+ *
+ * @Function: getStatusText
+ * @Description: 获取预约状态文本
+ *
+ * @param: 无
+ * @return:String 预约状态文本
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:15:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getStatusText() {
+ switch (status) {
+ case "0": return "待确认";
+ case "1": return "已确认";
+ case "2": return "已取消";
+ case "3": return "已完成";
+ default: return "未知";
+ }
+ }
+ /**
+ *
+ * @Function: getHandleTime
+ * @Description: 获取房东处理时间
+ *
+ * @param: 无
+ * @return:Date 房东处理时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:15:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Date getHandleTime() {
+ return handleTime;
+ }
+ /**
+ *
+ * @Function: setHandleTime
+ * @Description: 设置房东处理时间
+ *
+ * @param: handleTime 房东处理时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:15:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setHandleTime(Date handleTime) {
+ this.handleTime = handleTime;
+ }
+ /**
+ *
+ * @Function: getCreateBy
+ * @Description: 获取创建人
+ *
+ * @param: 无
+ * @return:String 创建人
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:16:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getCreateBy() {
+ return createBy;
+ }
+ /**
+ *
+ * @Function: setCreateBy
+ * @Description: 设置创建人
+ *
+ * @param: createBy 创建人
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:16:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setCreateBy(String createBy) {
+ this.createBy = createBy;
+ }
+ /**
+ *
+ * @Function: getCreateTime
+ * @Description: 获取创建时间
+ *
+ * @param: 无
+ * @return:Date 创建时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:16:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Date getCreateTime() {
+ return createTime;
+ }
+ /**
+ *
+ * @Function: setCreateTime
+ * @Description: 设置创建时间
+ *
+ * @param: createTime 创建时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:16:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+ /**
+ *
+ * @Function: getUpdateBy
+ * @Description: 获取更新人
+ *
+ * @param: 无
+ * @return:String 更新人
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:17:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getUpdateBy() {
+ return updateBy;
+ }
+ /**
+ *
+ * @Function: setUpdateBy
+ * @Description: 设置更新人
+ *
+ * @param: updateBy 更新人
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:17:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setUpdateBy(String updateBy) {
+ this.updateBy = updateBy;
+ }
+ /**
+ *
+ * @Function: getUpdateTime
+ * @Description: 获取更新时间
+ *
+ * @param: 无
+ * @return:Date 更新时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:17:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+ /**
+ *
+ * @Function: setUpdateTime
+ * @Description: 设置更新时间
+ *
+ * @param: updateTime 更新时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:17:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+ /**
+ *
+ * @Function: getHouse
+ * @Description: 获取房源详情
+ *
+ * @param: 无
+ * @return:House 房源对象
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:18:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public House getHouse() {
+ return house;
+ }
+ /**
+ *
+ * @Function: setHouse
+ * @Description: 设置房源详情
+ *
+ * @param: house 房源对象
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:18:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setHouse(House house) {
+ this.house = house;
+ }
+ /**
+ *
+ * @Function: getTenant
+ * @Description: 获取租客信息
+ *
+ * @param: 无
+ * @return:User 租客对象
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:18:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public User getTenant() {
+ return tenant;
+ }
+ /**
+ *
+ * @Function: setTenant
+ * @Description: 设置租客信息
+ *
+ * @param: tenant 租客对象
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:18:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setTenant(User tenant) {
+ this.tenant = tenant;
+ }
+ /**
+ *
+ * @Function: getLandlord
+ * @Description: 获取房东信息
+ *
+ * @param: 无
+ * @return:User 房东对象
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:19:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public User getLandlord() {
+ return landlord;
+ }
+ /**
+ *
+ * @Function: setLandlord
+ * @Description: 设置房东信息
+ *
+ * @param: landlord 房东对象
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:19:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setLandlord(User landlord) {
+ this.landlord = landlord;
+ }
+ /**
+ *
+ * @Function: toString
+ * @Description: 重写toString方法
+ *
+ * @param: 无
+ * @return:String 对象字符串表示
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午3:19:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public String toString() {
+ return "Reservation{" +
+ "id=" + id +
+ ", houseId=" + houseId +
+ ", reserveTime=" + reserveTime +
+ ", status='" + status + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/model/entity/User.java b/HRS/src/com/hrs/model/entity/User.java
new file mode 100644
index 0000000..4d5de3e
--- /dev/null
+++ b/HRS/src/com/hrs/model/entity/User.java
@@ -0,0 +1,707 @@
+package com.hrs.model.entity;
+
+import java.util.Date;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: User.java
+* @Description: 用户实体类
+*
+* @version: v1.0.0
+* @author: 赵恒
+* @date: 2026年4月13日 上午10:00:10
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 赵恒 v1.0.0 新建文件
+*/
+public class User {
+
+ // 数据库字段对应
+ private Long id; // 主键ID
+ private String userName; // 用户名
+ private String password; // 密码
+ private String realName; // 真实姓名
+ private String phone; // 手机号
+ private String idCard; // 身份证号
+ private String roleType; // 角色类型:0-租客 1-房东 2-管理员
+ private String status; // 账号状态:0-未认证 1-已认证 2-禁用
+ private String createBy; // 创建人
+ private Date createTime; // 创建时间
+ private String updateBy; // 更新人
+ private Date updateTime; // 更新时间
+ /**
+ *
+ * @Function: User
+ * @Description: 无参构造方法
+ *
+ * @param: 无
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:46:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public User() {
+ }
+ /**
+ *
+ * @Function: User
+ * @Description: 全参构造方法
+ *
+ * @param: id 主键ID, userName 用户名, password 密码, realName 真实姓名, phone 手机号, idCard 身份证号, roleType 角色类型, status 账号状态, createBy 创建人, createTime 创建时间, updateBy 更新人, updateTime 更新时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:47:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public User(Long id, String userName, String password, String realName,
+ String phone, String idCard, String roleType, String status,
+ String createBy, Date createTime, String updateBy, Date updateTime) {
+ this.id = id;
+ this.userName = userName;
+ this.password = password;
+ this.realName = realName;
+ this.phone = phone;
+ this.idCard = idCard;
+ this.roleType = roleType;
+ this.status = status;
+ this.createBy = createBy;
+ this.createTime = createTime;
+ this.updateBy = updateBy;
+ this.updateTime = updateTime;
+ }
+ /**
+ *
+ * @Function: getId
+ * @Description: 获取主键ID
+ *
+ * @param: 无
+ * @return:Long 主键ID
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:48:05
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Long getId() {
+ return id;
+ }
+ /**
+ *
+ * @Function: setId
+ * @Description: 设置主键ID
+ *
+ * @param: id 主键ID
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:48:20
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setId(Long id) {
+ this.id = id;
+ }
+ /**
+ *
+ * @Function: getUserName
+ * @Description: 获取用户名
+ *
+ * @param: 无
+ * @return:String 用户名
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:48:35
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getUserName() {
+ return userName;
+ }
+ /**
+ *
+ * @Function: setUserName
+ * @Description: 设置用户名
+ *
+ * @param: userName 用户名
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:48:50
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+ /**
+ *
+ * @Function: getPassword
+ * @Description: 获取密码
+ *
+ * @param: 无
+ * @return:String 密码
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:49:05
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getPassword() {
+ return password;
+ }
+ /**
+ *
+ * @Function: setPassword
+ * @Description: 设置密码
+ *
+ * @param: password 密码
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:49:20
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setPassword(String password) {
+ this.password = password;
+ }
+ /**
+ *
+ * @Function: getRealName
+ * @Description: 获取真实姓名
+ *
+ * @param: 无
+ * @return:String 真实姓名
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:49:35
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getRealName() {
+ return realName;
+ }
+ /**
+ *
+ * @Function: setRealName
+ * @Description: 设置真实姓名
+ *
+ * @param: realName 真实姓名
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:49:50
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setRealName(String realName) {
+ this.realName = realName;
+ }
+ /**
+ *
+ * @Function: getPhone
+ * @Description: 获取手机号
+ *
+ * @param: 无
+ * @return:String 手机号
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:50:05
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getPhone() {
+ return phone;
+ }
+ /**
+ *
+ * @Function: setPhone
+ * @Description: 设置手机号
+ *
+ * @param: phone 手机号
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:50:20
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setPhone(String phone) {
+ this.phone = phone;
+ }
+ /**
+ *
+ * @Function: getIdCard
+ * @Description: 获取身份证号
+ *
+ * @param: 无
+ * @return:String 身份证号
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:50:35
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getIdCard() {
+ return idCard;
+ }
+ /**
+ *
+ * @Function: setIdCard
+ * @Description: 设置身份证号
+ *
+ * @param: idCard 身份证号
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:50:50
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setIdCard(String idCard) {
+ this.idCard = idCard;
+ }
+ /**
+ *
+ * @Function: getRoleType
+ * @Description: 获取角色类型
+ *
+ * @param: 无
+ * @return:String 角色类型(0-租客 1-房东 2-管理员)
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:51:05
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getRoleType() {
+ return roleType;
+ }
+ /**
+ *
+ * @Function: setRoleType
+ * @Description: 设置角色类型
+ *
+ * @param: roleType 角色类型(0-租客 1-房东 2-管理员)
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:51:20
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setRoleType(String roleType) {
+ this.roleType = roleType;
+ }
+ /**
+ *
+ * @Function: getStatus
+ * @Description: 获取账号状态
+ *
+ * @param: 无
+ * @return:String 账号状态(0-未认证 1-已认证 2-禁用)
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:51:35
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getStatus() {
+ return status;
+ }
+ /**
+ *
+ * @Function: setStatus
+ * @Description: 设置账号状态
+ *
+ * @param: status 账号状态(0-未认证 1-已认证 2-禁用)
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:51:50
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setStatus(String status) {
+ this.status = status;
+ }
+ /**
+ *
+ * @Function: getCreateBy
+ * @Description: 获取创建人
+ *
+ * @param: 无
+ * @return:String 创建人
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:52:05
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getCreateBy() {
+ return createBy;
+ }
+ /**
+ *
+ * @Function: setCreateBy
+ * @Description: 设置创建人
+ *
+ * @param: createBy 创建人
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:52:20
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setCreateBy(String createBy) {
+ this.createBy = createBy;
+ }
+ /**
+ *
+ * @Function: getCreateTime
+ * @Description: 获取创建时间
+ *
+ * @param: 无
+ * @return:Date 创建时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:52:35
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Date getCreateTime() {
+ return createTime;
+ }
+ /**
+ *
+ * @Function: setCreateTime
+ * @Description: 设置创建时间
+ *
+ * @param: createTime 创建时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:52:50
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+ /**
+ *
+ * @Function: getUpdateBy
+ * @Description: 获取更新人
+ *
+ * @param: 无
+ * @return:String 更新人
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:53:05
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public String getUpdateBy() {
+ return updateBy;
+ }
+ /**
+ *
+ * @Function: setUpdateBy
+ * @Description: 设置更新人
+ *
+ * @param: updateBy 更新人
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:53:20
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setUpdateBy(String updateBy) {
+ this.updateBy = updateBy;
+ }
+ /**
+ *
+ * @Function: getUpdateTime
+ * @Description: 获取更新时间
+ *
+ * @param: 无
+ * @return:Date 更新时间
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:53:35
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public Date getUpdateTime() {
+ return updateTime;
+ }
+ /**
+ *
+ * @Function: setUpdateTime
+ * @Description: 设置更新时间
+ *
+ * @param: updateTime 更新时间
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:53:50
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public void setUpdateTime(Date updateTime) {
+ this.updateTime = updateTime;
+ }
+ /**
+ *
+ * @Function: isTenant
+ * @Description: 判断是否为租客
+ *
+ * @param: 无
+ * @return:boolean 是否为租客
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:54:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public boolean isTenant() {
+ return "0".equals(this.roleType);
+ }
+ /**
+ *
+ * @Function: isLandlord
+ * @Description: 判断是否为房东
+ *
+ * @param: 无
+ * @return:boolean 是否为房东
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:54:30
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public boolean isLandlord() {
+ return "1".equals(this.roleType);
+ }
+ /**
+ *
+ * @Function: isAdmin
+ * @Description: 判断是否为管理员
+ *
+ * @param: 无
+ * @return:boolean 是否为管理员
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:54:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+
+ public boolean isAdmin() {
+ return "2".equals(this.roleType);
+ }
+ /**
+ *
+ * @Function: isVerified
+ * @Description: 判断账号是否已认证
+ *
+ * @param: 无
+ * @return:boolean 是否已认证
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:55:00
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ public boolean isVerified() {
+ return "1".equals(this.status);
+ }
+ /**
+ *
+ * @Function: toString
+ * @Description: 重写toString方法
+ *
+ * @param: 无
+ * @return:String 对象字符串表示
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 赵恒
+ * @date: 2025年4月13日 下午2:55:15
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月13日 赵恒 v1.0.0 新建方法
+ */
+ @Override
+ public String toString() {
+ return "User{" +
+ "id=" + id +
+ ", userName='" + userName + '\'' +
+ ", realName='" + realName + '\'' +
+ ", phone='" + phone + '\'' +
+ ", roleType='" + roleType + '\'' +
+ ", status='" + status + '\'' +
+ '}';
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/service/CollectionService.java b/HRS/src/com/hrs/service/CollectionService.java
new file mode 100644
index 0000000..b8f4607
--- /dev/null
+++ b/HRS/src/com/hrs/service/CollectionService.java
@@ -0,0 +1,71 @@
+package com.hrs.service;
+
+import com.hrs.model.entity.Collection;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: CollectionService.java
+* @Description: 收藏业务逻辑接口
+*
+* @version: v1.0.0
+* @author: 黄红
+* @date: 2026年4月13日 上午10:00:51
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 黄红 v1.0.0 新建文件
+*/
+public interface CollectionService {
+
+ /**
+ * 添加收藏
+ * @param tenantId 租客ID
+ * @param houseId 房源ID
+ * @return 添加结果
+ */
+ CollectionResult addCollection(Long tenantId, Long houseId);
+
+ /**
+ * 取消收藏(通过收藏ID)
+ */
+ boolean deleteCollectionById(Long collectionId, Long tenantId);
+
+ /**
+ * 取消收藏(通过房源ID)
+ */
+ boolean deleteCollectionByHouseId(Long houseId, Long tenantId);
+
+ /**
+ * 获取租客的收藏列表(带房源详情)
+ */
+ List getTenantCollections(Long tenantId);
+
+ /**
+ * 检查是否已收藏
+ */
+ boolean isCollected(Long tenantId, Long houseId);
+
+ /**
+ * 获取收藏数量
+ */
+ int getCollectionCount(Long tenantId);
+
+ /**
+ * 收藏操作结果类
+ */
+ class CollectionResult {
+ private boolean success;
+ private String message;
+ private boolean exists;
+
+ public boolean isSuccess() { return success; }
+ public void setSuccess(boolean success) { this.success = success; }
+ public String getMessage() { return message; }
+ public void setMessage(String message) { this.message = message; }
+ public boolean isExists() { return exists; }
+ public void setExists(boolean exists) { this.exists = exists; }
+ }
+}
diff --git a/HRS/src/com/hrs/service/HouseService.java b/HRS/src/com/hrs/service/HouseService.java
new file mode 100644
index 0000000..49a65b1
--- /dev/null
+++ b/HRS/src/com/hrs/service/HouseService.java
@@ -0,0 +1,94 @@
+package com.hrs.service;
+
+import com.hrs.model.entity.House;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: HouseService.java
+* @Description: 房源业务逻辑接口
+*
+* @version: v1.0.0
+* @author: 黄红
+* @date: 2026年4月13日 上午10:01:06
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 黄红 v1.0.0 新建文件
+*/
+public interface HouseService {
+
+ /**
+ * 获取已上架房源(租客端)
+ */
+ List getPublishedHouses();
+
+ /**
+ * 按区域筛选房源
+ */
+ List searchByArea(String area);
+
+ /**
+ * 按价格区间筛选房源
+ */
+ List searchByPrice(int minPrice, int maxPrice);
+
+ /**
+ * 获取房源详情
+ */
+ House getHouseDetail(Long houseId);
+
+ /**
+ * 获取房东的房源列表
+ */
+ List getLandlordHouses(Long landlordId);
+
+ /**
+ * 添加房源
+ * @return 添加结果
+ */
+ AddHouseResult addHouse(House house);
+
+ /**
+ * 更新房源
+ */
+ UpdateHouseResult updateHouse(House house, Long landlordId);
+
+ /**
+ * 删除房源
+ */
+ boolean deleteHouse(Long houseId, Long landlordId);
+
+ /**
+ * 审核房源(管理员)
+ */
+ boolean auditHouse(Long houseId, boolean approved);
+
+ /**
+ * 添加房源结果类
+ */
+ class AddHouseResult {
+ private boolean success;
+ private String message;
+
+ public boolean isSuccess() { return success; }
+ public void setSuccess(boolean success) { this.success = success; }
+ public String getMessage() { return message; }
+ public void setMessage(String message) { this.message = message; }
+ }
+
+ /**
+ * 更新房源结果类
+ */
+ class UpdateHouseResult {
+ private boolean success;
+ private String message;
+
+ public boolean isSuccess() { return success; }
+ public void setSuccess(boolean success) { this.success = success; }
+ public String getMessage() { return message; }
+ public void setMessage(String message) { this.message = message; }
+ }
+}
diff --git a/HRS/src/com/hrs/service/OrderService.java b/HRS/src/com/hrs/service/OrderService.java
new file mode 100644
index 0000000..44b74b2
--- /dev/null
+++ b/HRS/src/com/hrs/service/OrderService.java
@@ -0,0 +1,91 @@
+package com.hrs.service;
+
+import com.hrs.model.entity.Order;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: OrderService.java
+* @Description: 订单业务逻辑接口
+*
+* @version: v1.0.0
+* @author: 黄红
+* @date: 2026年4月13日 上午10:01:16
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 黄红 v1.0.0 新建文件
+*/
+public interface OrderService {
+
+ /**
+ * 创建订单
+ */
+ CreateOrderResult createOrder(Long tenantId, Long houseId, Date startDate, Date endDate);
+
+ /**
+ * 模拟支付
+ */
+ boolean payOrder(Long orderId, Long tenantId);
+
+ /**
+ * 取消订单(租客)
+ */
+ boolean cancelOrder(Long orderId, Long tenantId);
+
+ /**
+ * 获取租客订单列表
+ */
+ List getTenantOrders(Long tenantId);
+
+ /**
+ * 获取房东订单列表
+ */
+ List getLandlordOrders(Long landlordId);
+
+ /**
+ * 获取所有订单(管理员)
+ */
+ List getAllOrders();
+
+ /**
+ * 获取订单详情
+ */
+ Order getOrderDetail(Long orderId);
+
+ /**
+ * 统计租客订单数量
+ */
+ int getTenantOrderCount(Long tenantId);
+
+ /**
+ * 统计所有订单数量
+ */
+ int getAllOrderCount();
+
+ /**
+ * 创建订单结果类
+ */
+ class CreateOrderResult {
+ private boolean success;
+ private String message;
+ private Long orderId;
+ private String orderNo;
+ private BigDecimal totalRent;
+
+ public boolean isSuccess() { return success; }
+ public void setSuccess(boolean success) { this.success = success; }
+ public String getMessage() { return message; }
+ public void setMessage(String message) { this.message = message; }
+ public Long getOrderId() { return orderId; }
+ public void setOrderId(Long orderId) { this.orderId = orderId; }
+ public String getOrderNo() { return orderNo; }
+ public void setOrderNo(String orderNo) { this.orderNo = orderNo; }
+ public BigDecimal getTotalRent() { return totalRent; }
+ public void setTotalRent(BigDecimal totalRent) { this.totalRent = totalRent; }
+ }
+}
diff --git a/HRS/src/com/hrs/service/ReservationService.java b/HRS/src/com/hrs/service/ReservationService.java
new file mode 100644
index 0000000..c023e64
--- /dev/null
+++ b/HRS/src/com/hrs/service/ReservationService.java
@@ -0,0 +1,71 @@
+package com.hrs.service;
+
+import com.hrs.model.entity.Reservation;
+import java.util.Date;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: ReservationService.java
+* @Description: 预约看房业务逻辑接口
+*
+* @version: v1.0.0
+* @author: 黄红
+* @date: 2026年4月13日 上午10:01:27
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 黄红 v1.0.0 新建文件
+*/
+public interface ReservationService {
+
+ /**
+ * 创建预约
+ */
+ ReservationResult createReservation(Long tenantId, Long houseId, Date reserveTime, String remark);
+
+ /**
+ * 获取租客的预约列表
+ */
+ List getTenantReservations(Long tenantId);
+
+ /**
+ * 获取房东收到的预约列表
+ */
+ List getLandlordReservations(Long landlordId);
+
+ /**
+ * 租客取消预约
+ */
+ boolean cancelReservationByTenant(Long reservationId, Long tenantId);
+
+ /**
+ * 房东处理预约(确认/拒绝)
+ */
+ boolean handleReservation(Long reservationId, Long landlordId, boolean approve);
+
+ /**
+ * 获取预约详情
+ */
+ Reservation getReservationDetail(Long reservationId);
+
+ /**
+ * 获取房东待处理预约数量
+ */
+ int getPendingCount(Long landlordId);
+
+ /**
+ * 预约操作结果类
+ */
+ class ReservationResult {
+ private boolean success;
+ private String message;
+
+ public boolean isSuccess() { return success; }
+ public void setSuccess(boolean success) { this.success = success; }
+ public String getMessage() { return message; }
+ public void setMessage(String message) { this.message = message; }
+ }
+}
diff --git a/HRS/src/com/hrs/service/UserService.java b/HRS/src/com/hrs/service/UserService.java
new file mode 100644
index 0000000..15a4eca
--- /dev/null
+++ b/HRS/src/com/hrs/service/UserService.java
@@ -0,0 +1,51 @@
+package com.hrs.service;
+
+import com.hrs.model.entity.User;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: UserService.java
+* @Description: 用户业务逻辑接口
+*
+* @version: v1.0.0
+* @author: 黄红
+* @date: 2026年4月13日 上午10:01:45
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 黄红 v1.0.0 新建文件
+*/
+public interface UserService {
+
+ /**
+ * 用户登录验证
+ * @param username 用户名
+ * @param password 明文密码
+ * @param roleType 角色类型
+ * @return 登录成功返回User对象,失败返回null
+ */
+ User login(String username, String password, String roleType);
+
+ /**
+ * 用户注册
+ * @param user 用户信息
+ * @param confirmPassword 确认密码
+ * @return 注册结果和错误信息
+ */
+ RegisterResult register(User user, String confirmPassword);
+
+ /**
+ * 注册结果类
+ */
+ class RegisterResult {
+ private boolean success;
+ private String message;
+
+ public boolean isSuccess() { return success; }
+ public void setSuccess(boolean success) { this.success = success; }
+ public String getMessage() { return message; }
+ public void setMessage(String message) { this.message = message; }
+ }
+}
diff --git a/HRS/src/com/hrs/service/impl/CollectionServiceImpl.java b/HRS/src/com/hrs/service/impl/CollectionServiceImpl.java
new file mode 100644
index 0000000..bfd197c
--- /dev/null
+++ b/HRS/src/com/hrs/service/impl/CollectionServiceImpl.java
@@ -0,0 +1,156 @@
+package com.hrs.service.impl;
+
+import com.hrs.dao.CollectionDao;
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.CollectionDaoImpl;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.model.entity.Collection;
+import com.hrs.model.entity.House;
+import com.hrs.service.CollectionService;
+
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: CollectionServiceImpl.java
+* @Description: 收藏业务逻辑实现类
+*
+* @version: v1.0.0
+* @author: 黄红
+* @date: 2026年4月13日 上午10:04:16
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 黄红 v1.0.0 新建文件
+*/
+public class CollectionServiceImpl implements CollectionService {
+
+ private CollectionDao collectionDao = new CollectionDaoImpl();
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ /**
+ * 添加收藏
+ * @param tenantId 租客ID
+ * @param houseId 房源ID
+ * @return 添加结果
+ */
+ @Override
+ public CollectionResult addCollection(Long tenantId, Long houseId) {
+ CollectionResult result = new CollectionResult();
+
+ // 1. 参数校验
+ if (tenantId == null || tenantId <= 0) {
+ result.setSuccess(false);
+ result.setMessage("用户未登录");
+ return result;
+ }
+
+ if (houseId == null || houseId <= 0) {
+ result.setSuccess(false);
+ result.setMessage("房源信息错误");
+ return result;
+ }
+
+ // 2. 检查房源是否存在且已上架
+ House house = houseDao.findById(houseId);
+ if (house == null) {
+ result.setSuccess(false);
+ result.setMessage("房源不存在");
+ return result;
+ }
+
+ if (!"1".equals(house.getStatus())) {
+ result.setSuccess(false);
+ result.setMessage("房源已下架,无法收藏");
+ return result;
+ }
+
+ // 3. 检查是否已收藏
+ if (collectionDao.isCollected(tenantId, houseId)) {
+ result.setSuccess(false);
+ result.setMessage("已经收藏过该房源");
+ result.setExists(true);
+ return result;
+ }
+
+ // 4. 添加收藏
+ Collection collection = new Collection();
+ collection.setTenantId(tenantId);
+ collection.setHouseId(houseId);
+
+ boolean success = collectionDao.add(collection);
+ result.setSuccess(success);
+ result.setMessage(success ? "收藏成功" : "收藏失败,请稍后重试");
+
+ return result;
+ }
+
+ /**
+ * 取消收藏(通过收藏ID)
+ */
+ @Override
+ public boolean deleteCollectionById(Long collectionId, Long tenantId) {
+ if (collectionId == null || tenantId == null) {
+ return false;
+ }
+
+ // 验证该收藏是否属于当前用户(实际DAO层可以直接删除,但为了安全可以验证)
+ return collectionDao.deleteById(collectionId);
+ }
+
+ /**
+ * 取消收藏(通过房源ID)
+ */
+ @Override
+ public boolean deleteCollectionByHouseId(Long houseId, Long tenantId) {
+ if (houseId == null || tenantId == null) {
+ return false;
+ }
+
+ return collectionDao.delete(tenantId, houseId);
+ }
+
+ /**
+ * 获取租客的收藏列表(带房源详情)
+ */
+ @Override
+ public List getTenantCollections(Long tenantId) {
+ if (tenantId == null || tenantId <= 0) {
+ return null;
+ }
+
+ List collections = collectionDao.findByTenantId(tenantId);
+
+ // 过滤掉已下架的房源
+ collections.removeIf(c -> {
+ House house = c.getHouse();
+ return house == null || !"1".equals(house.getStatus());
+ });
+
+ return collections;
+ }
+
+ /**
+ * 检查是否已收藏
+ */
+ @Override
+ public boolean isCollected(Long tenantId, Long houseId) {
+ if (tenantId == null || houseId == null) {
+ return false;
+ }
+ return collectionDao.isCollected(tenantId, houseId);
+ }
+
+ /**
+ * 获取收藏数量
+ */
+ @Override
+ public int getCollectionCount(Long tenantId) {
+ if (tenantId == null || tenantId <= 0) {
+ return 0;
+ }
+ return collectionDao.countByTenantId(tenantId);
+ }
+}
diff --git a/HRS/src/com/hrs/service/impl/HouseServiceImpl.java b/HRS/src/com/hrs/service/impl/HouseServiceImpl.java
new file mode 100644
index 0000000..9266c21
--- /dev/null
+++ b/HRS/src/com/hrs/service/impl/HouseServiceImpl.java
@@ -0,0 +1,194 @@
+package com.hrs.service.impl;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.model.entity.House;
+import com.hrs.service.HouseService;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: HouseServiceImpl.java
+* @Description: 房源业务逻辑实现类
+*
+* @version: v1.0.0
+* @author: 黄红
+* @date: 2026年4月13日 上午10:04:33
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 黄红 v1.0.0 新建文件
+*/
+public class HouseServiceImpl implements HouseService {
+
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ /**
+ * 获取已上架房源(租客端)
+ */
+ @Override
+ public List getPublishedHouses() {
+ return houseDao.findPublishedHouses();
+ }
+
+ /**
+ * 按区域筛选房源
+ */
+ @Override
+ public List searchByArea(String area) {
+ if (area == null || area.trim().isEmpty()) {
+ return getPublishedHouses();
+ }
+ return houseDao.findHousesByArea(area);
+ }
+
+ /**
+ * 按价格区间筛选房源
+ */
+ @Override
+ public List searchByPrice(int minPrice, int maxPrice) {
+ if (minPrice <= 0 && maxPrice <= 0) {
+ return getPublishedHouses();
+ }
+ if (minPrice <= 0) {
+ minPrice = 0;
+ }
+ if (maxPrice <= 0) {
+ maxPrice = Integer.MAX_VALUE;
+ }
+ return houseDao.findHousesByPrice(minPrice, maxPrice);
+ }
+
+ /**
+ * 获取房源详情
+ */
+ @Override
+ public House getHouseDetail(Long houseId) {
+ if (houseId == null || houseId <= 0) {
+ return null;
+ }
+ return houseDao.findById(houseId);
+ }
+
+ /**
+ * 获取房东的房源列表
+ */
+ @Override
+ public List getLandlordHouses(Long landlordId) {
+ if (landlordId == null || landlordId <= 0) {
+ return null;
+ }
+ return houseDao.findByLandlordId(landlordId);
+ }
+
+ /**
+ * 添加房源
+ * @return 添加结果
+ */
+ @Override
+ public AddHouseResult addHouse(House house) {
+ AddHouseResult result = new AddHouseResult();
+
+ // 1. 参数校验
+ if (house.getTitle() == null || house.getTitle().trim().isEmpty()) {
+ result.setSuccess(false);
+ result.setMessage("房源标题不能为空");
+ return result;
+ }
+
+ if (house.getRentPrice() == null || house.getRentPrice().compareTo(BigDecimal.ZERO) <= 0) {
+ result.setSuccess(false);
+ result.setMessage("租金不能为空或小于0");
+ return result;
+ }
+
+ if (house.getLandlordId() == null || house.getLandlordId() <= 0) {
+ result.setSuccess(false);
+ result.setMessage("房东信息错误");
+ return result;
+ }
+
+ // 2. 设置默认值
+ if (house.getStatus() == null) {
+ house.setStatus("0"); // 默认待审核
+ }
+
+ // 3. 保存
+ boolean success = houseDao.add(house);
+ result.setSuccess(success);
+ result.setMessage(success ? "房源添加成功,等待管理员审核" : "添加失败,请稍后重试");
+
+ return result;
+ }
+
+ /**
+ * 更新房源
+ */
+ @Override
+ public UpdateHouseResult updateHouse(House house, Long landlordId) {
+ UpdateHouseResult result = new UpdateHouseResult();
+
+ // 1. 参数校验
+ if (house.getId() == null || house.getId() <= 0) {
+ result.setSuccess(false);
+ result.setMessage("房源信息错误");
+ return result;
+ }
+
+ // 2. 验证权限(该房源是否属于当前房东)
+ House existingHouse = houseDao.findById(house.getId());
+ if (existingHouse == null || !existingHouse.getLandlordId().equals(landlordId)) {
+ result.setSuccess(false);
+ result.setMessage("无权修改此房源");
+ return result;
+ }
+
+ // 3. 已上架的房源修改后需要重新审核
+ if ("1".equals(existingHouse.getStatus())) {
+ house.setStatus("0"); // 重新进入待审核状态
+ } else {
+ house.setStatus(existingHouse.getStatus());
+ }
+
+ // 4. 更新
+ boolean success = houseDao.update(house);
+ result.setSuccess(success);
+ result.setMessage(success ? "修改成功" : "修改失败");
+
+ return result;
+ }
+
+ /**
+ * 删除房源
+ */
+ @Override
+ public boolean deleteHouse(Long houseId, Long landlordId) {
+ if (houseId == null || landlordId == null) {
+ return false;
+ }
+
+ House house = houseDao.findById(houseId);
+ if (house == null || !house.getLandlordId().equals(landlordId)) {
+ return false;
+ }
+
+ return houseDao.delete(houseId);
+ }
+
+ /**
+ * 审核房源(管理员)
+ */
+ @Override
+ public boolean auditHouse(Long houseId, boolean approved) {
+ if (houseId == null || houseId <= 0) {
+ return false;
+ }
+
+ String status = approved ? "1" : "3"; // 1-已上架,3-违规/拒绝
+ return houseDao.updateStatus(houseId, status);
+ }
+}
diff --git a/HRS/src/com/hrs/service/impl/OrderServiceImpl.java b/HRS/src/com/hrs/service/impl/OrderServiceImpl.java
new file mode 100644
index 0000000..92215e3
--- /dev/null
+++ b/HRS/src/com/hrs/service/impl/OrderServiceImpl.java
@@ -0,0 +1,241 @@
+package com.hrs.service.impl;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.OrderDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.dao.impl.OrderDaoImpl;
+import com.hrs.model.entity.House;
+import com.hrs.model.entity.Order;
+import com.hrs.service.OrderService;
+
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: OrderServiceImpl.java
+* @Description: 订单业务逻辑实现类
+*
+* @version: v1.0.0
+* @author: 黄红
+* @date: 2026年4月13日 上午10:09:00
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 黄红 v1.0.0 新建文件
+*/
+public class OrderServiceImpl implements OrderService {
+
+ private OrderDao orderDao = new OrderDaoImpl();
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ /**
+ * 创建订单
+ */
+ @Override
+ public CreateOrderResult createOrder(Long tenantId, Long houseId, Date startDate, Date endDate) {
+ CreateOrderResult result = new CreateOrderResult();
+
+ // 1. 参数校验
+ if (tenantId == null || tenantId <= 0) {
+ result.setSuccess(false);
+ result.setMessage("用户未登录");
+ return result;
+ }
+
+ if (houseId == null || houseId <= 0) {
+ result.setSuccess(false);
+ result.setMessage("房源信息错误");
+ return result;
+ }
+
+ if (startDate == null || endDate == null) {
+ result.setSuccess(false);
+ result.setMessage("请选择租赁时间");
+ return result;
+ }
+
+ // 2. 检查房源是否存在且已上架
+ House house = houseDao.findById(houseId);
+ if (house == null) {
+ result.setSuccess(false);
+ result.setMessage("房源不存在");
+ return result;
+ }
+
+ if (!"1".equals(house.getStatus())) {
+ result.setSuccess(false);
+ result.setMessage("房源已下架,无法下单");
+ return result;
+ }
+
+ // 3. 日期校验
+ Date now = new Date();
+ if (startDate.before(now)) {
+ result.setSuccess(false);
+ result.setMessage("租赁开始日期不能早于今天");
+ return result;
+ }
+
+ if (endDate.before(startDate)) {
+ result.setSuccess(false);
+ result.setMessage("结束日期不能早于开始日期");
+ return result;
+ }
+
+ // 4. 计算天数和总租金
+ long diff = endDate.getTime() - startDate.getTime();
+ int days = (int) TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
+ if (days <= 0) {
+ days = 1;
+ }
+
+ // 按比例计算租金
+ BigDecimal monthlyRent = house.getRentPrice();
+ BigDecimal dailyRent = monthlyRent.divide(BigDecimal.valueOf(30), 2, BigDecimal.ROUND_HALF_UP);
+ BigDecimal totalRent = dailyRent.multiply(BigDecimal.valueOf(days)).setScale(2, BigDecimal.ROUND_HALF_UP);
+
+ // 5. 生成订单编号
+ String orderNo = generateOrderNo();
+
+ // 6. 创建订单
+ Order order = new Order();
+ order.setTenantId(tenantId);
+ order.setHouseId(houseId);
+ order.setOrderNo(orderNo);
+ order.setRentStartTime(startDate);
+ order.setRentEndTime(endDate);
+ order.setTotalRent(totalRent);
+ order.setPayStatus("0"); // 待支付
+ order.setStatus("0"); // 待签约
+
+ boolean success = orderDao.add(order);
+
+ result.setSuccess(success);
+ result.setMessage(success ? "订单创建成功,请完成支付" : "订单创建失败,请稍后重试");
+ if (success) {
+ result.setOrderId(order.getId());
+ result.setOrderNo(orderNo);
+ result.setTotalRent(totalRent);
+ }
+
+ return result;
+ }
+
+ /**
+ * 模拟支付
+ */
+ @Override
+ public boolean payOrder(Long orderId, Long tenantId) {
+ if (orderId == null || tenantId == null) {
+ return false;
+ }
+
+ Order order = orderDao.findById(orderId);
+ if (order == null || !order.getTenantId().equals(tenantId)) {
+ return false;
+ }
+
+ // 只有待支付的订单可以支付
+ if (!"0".equals(order.getPayStatus())) {
+ return false;
+ }
+
+ return orderDao.updatePayStatus(orderId, "1");
+ }
+
+ /**
+ * 取消订单(租客)
+ */
+ @Override
+ public boolean cancelOrder(Long orderId, Long tenantId) {
+ if (orderId == null || tenantId == null) {
+ return false;
+ }
+
+ Order order = orderDao.findById(orderId);
+ if (order == null || !order.getTenantId().equals(tenantId)) {
+ return false;
+ }
+
+ // 只有待支付的订单可以取消
+ if (!"0".equals(order.getPayStatus())) {
+ return false;
+ }
+
+ return orderDao.updateStatus(orderId, "3"); // 3-已取消
+ }
+
+ /**
+ * 获取租客订单列表
+ */
+ @Override
+ public List getTenantOrders(Long tenantId) {
+ if (tenantId == null || tenantId <= 0) {
+ return null;
+ }
+ return orderDao.findByTenantId(tenantId);
+ }
+
+ /**
+ * 获取房东订单列表
+ */
+ @Override
+ public List getLandlordOrders(Long landlordId) {
+ if (landlordId == null || landlordId <= 0) {
+ return null;
+ }
+ return orderDao.findByLandlordId(landlordId);
+ }
+
+ /**
+ * 获取所有订单(管理员)
+ */
+ @Override
+ public List getAllOrders() {
+ return orderDao.findAll();
+ }
+
+ /**
+ * 获取订单详情
+ */
+ @Override
+ public Order getOrderDetail(Long orderId) {
+ if (orderId == null || orderId <= 0) {
+ return null;
+ }
+ return orderDao.findById(orderId);
+ }
+
+ /**
+ * 统计租客订单数量
+ */
+ @Override
+ public int getTenantOrderCount(Long tenantId) {
+ if (tenantId == null || tenantId <= 0) {
+ return 0;
+ }
+ return orderDao.countByTenantId(tenantId);
+ }
+
+ /**
+ * 统计所有订单数量
+ */
+ @Override
+ public int getAllOrderCount() {
+ return orderDao.countAll();
+ }
+
+ /**
+ * 生成订单编号
+ */
+ private String generateOrderNo() {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+ return "ORD" + sdf.format(new Date());
+ }
+}
diff --git a/HRS/src/com/hrs/service/impl/ReservationServiceImpl.java b/HRS/src/com/hrs/service/impl/ReservationServiceImpl.java
new file mode 100644
index 0000000..d31338b
--- /dev/null
+++ b/HRS/src/com/hrs/service/impl/ReservationServiceImpl.java
@@ -0,0 +1,187 @@
+package com.hrs.service.impl;
+
+import com.hrs.dao.HouseDao;
+import com.hrs.dao.ReservationDao;
+import com.hrs.dao.impl.HouseDaoImpl;
+import com.hrs.dao.impl.ReservationDaoImpl;
+import com.hrs.model.entity.House;
+import com.hrs.model.entity.Reservation;
+import com.hrs.service.ReservationService;
+
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: ReservationServiceImpl.java
+* @Description: 预约看房业务逻辑实现类
+*
+* @version: v1.0.0
+* @author: 黄红
+* @date: 2026年4月13日 上午10:06:14
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 黄红 v1.0.0 新建文件
+*/
+public class ReservationServiceImpl implements ReservationService {
+
+ private ReservationDao reservationDao = new ReservationDaoImpl();
+ private HouseDao houseDao = new HouseDaoImpl();
+
+ /**
+ * 创建预约
+ */
+ @Override
+ public ReservationResult createReservation(Long tenantId, Long houseId, Date reserveTime, String remark) {
+ ReservationResult result = new ReservationResult();
+
+ // 1. 参数校验
+ if (tenantId == null || tenantId <= 0) {
+ result.setSuccess(false);
+ result.setMessage("用户未登录");
+ return result;
+ }
+
+ if (houseId == null || houseId <= 0) {
+ result.setSuccess(false);
+ result.setMessage("房源信息错误");
+ return result;
+ }
+
+ if (reserveTime == null) {
+ result.setSuccess(false);
+ result.setMessage("请选择预约时间");
+ return result;
+ }
+
+ // 2. 检查房源是否存在且已上架
+ House house = houseDao.findById(houseId);
+ if (house == null) {
+ result.setSuccess(false);
+ result.setMessage("房源不存在");
+ return result;
+ }
+
+ if (!"1".equals(house.getStatus())) {
+ result.setSuccess(false);
+ result.setMessage("房源已下架,无法预约");
+ return result;
+ }
+
+ // 3. 检查预约时间(不能早于当前时间1小时)
+ Date now = new Date();
+ long minReserveTime = now.getTime() + TimeUnit.HOURS.toMillis(1);
+ if (reserveTime.getTime() < minReserveTime) {
+ result.setSuccess(false);
+ result.setMessage("预约时间至少需要提前1小时");
+ return result;
+ }
+
+ // 4. 创建预约
+ Reservation reservation = new Reservation();
+ reservation.setTenantId(tenantId);
+ reservation.setHouseId(houseId);
+ reservation.setLandlordId(house.getLandlordId());
+ reservation.setReserveTime(reserveTime);
+ reservation.setRemark(remark);
+
+ boolean success = reservationDao.add(reservation);
+ result.setSuccess(success);
+ result.setMessage(success ? "预约成功,请等待房东确认" : "预约失败,请稍后重试");
+
+ return result;
+ }
+
+ /**
+ * 获取租客的预约列表
+ */
+ @Override
+ public List getTenantReservations(Long tenantId) {
+ if (tenantId == null || tenantId <= 0) {
+ return null;
+ }
+ return reservationDao.findByTenantId(tenantId);
+ }
+
+ /**
+ * 获取房东收到的预约列表
+ */
+ @Override
+ public List getLandlordReservations(Long landlordId) {
+ if (landlordId == null || landlordId <= 0) {
+ return null;
+ }
+ return reservationDao.findByLandlordId(landlordId);
+ }
+
+ /**
+ * 租客取消预约
+ */
+ @Override
+ public boolean cancelReservationByTenant(Long reservationId, Long tenantId) {
+ if (reservationId == null || tenantId == null) {
+ return false;
+ }
+
+ Reservation reservation = reservationDao.findById(reservationId);
+ if (reservation == null || !reservation.getTenantId().equals(tenantId)) {
+ return false;
+ }
+
+ // 只有待确认的预约可以取消
+ if (!"0".equals(reservation.getStatus())) {
+ return false;
+ }
+
+ return reservationDao.cancel(reservationId, tenantId);
+ }
+
+ /**
+ * 房东处理预约(确认/拒绝)
+ */
+ @Override
+ public boolean handleReservation(Long reservationId, Long landlordId, boolean approve) {
+ if (reservationId == null || landlordId == null) {
+ return false;
+ }
+
+ Reservation reservation = reservationDao.findById(reservationId);
+ if (reservation == null || !reservation.getLandlordId().equals(landlordId)) {
+ return false;
+ }
+
+ // 只有待确认的预约可以处理
+ if (!"0".equals(reservation.getStatus())) {
+ return false;
+ }
+
+ String status = approve ? "1" : "2"; // 1-已确认,2-已取消/拒绝
+ return reservationDao.updateStatus(reservationId, status);
+ }
+
+ /**
+ * 获取预约详情
+ */
+ @Override
+ public Reservation getReservationDetail(Long reservationId) {
+ if (reservationId == null || reservationId <= 0) {
+ return null;
+ }
+ return reservationDao.findById(reservationId);
+ }
+
+ /**
+ * 获取房东待处理预约数量
+ */
+ @Override
+ public int getPendingCount(Long landlordId) {
+ if (landlordId == null || landlordId <= 0) {
+ return 0;
+ }
+ return reservationDao.countByLandlordId(landlordId);
+ }
+}
diff --git a/HRS/src/com/hrs/service/impl/UserServiceImpl.java b/HRS/src/com/hrs/service/impl/UserServiceImpl.java
new file mode 100644
index 0000000..0c36a9b
--- /dev/null
+++ b/HRS/src/com/hrs/service/impl/UserServiceImpl.java
@@ -0,0 +1,128 @@
+package com.hrs.service.impl;
+
+import com.hrs.dao.UserDao;
+import com.hrs.dao.impl.UserDaoImpl;
+import com.hrs.model.entity.User;
+import com.hrs.service.UserService;
+import com.hrs.util.MD5Util;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: UserServiceImpl.java
+* @Description: 用户业务逻辑实现类
+*
+* @version: v1.0.0
+* @author: 黄红
+* @date: 2026年4月13日 上午10:06:30
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 黄红 v1.0.0 新建文件
+*/
+public class UserServiceImpl implements UserService {
+
+ private UserDao userDao = new UserDaoImpl();
+
+ /**
+ * 用户登录验证
+ * @param username 用户名
+ * @param password 明文密码
+ * @param roleType 角色类型
+ * @return 登录成功返回User对象,失败返回null
+ */
+ @Override
+ public User login(String username, String password, String roleType) {
+ // 1. 参数校验
+ if (username == null || username.trim().isEmpty()) {
+ return null;
+ }
+ if (password == null || password.trim().isEmpty()) {
+ return null;
+ }
+
+ // 2. 密码加密
+ String encryptedPassword = MD5Util.md5(password);
+
+ // 3. 查询用户
+ User user = userDao.findByUsernameAndPassword(username, encryptedPassword);
+
+ // 4. 验证角色
+ if (user != null && !user.getRoleType().equals(roleType)) {
+ return null;
+ }
+
+ // 5. 验证账号状态
+ if (user != null && "2".equals(user.getStatus())) {
+ return null;
+ }
+
+ return user;
+ }
+
+ /**
+ * 用户注册
+ * @param user 用户信息
+ * @param confirmPassword 确认密码
+ * @return 注册结果和错误信息
+ */
+ @Override
+ public RegisterResult register(User user, String confirmPassword) {
+ RegisterResult result = new RegisterResult();
+
+ // 1. 参数校验
+ if (user.getUserName() == null || user.getUserName().trim().isEmpty()) {
+ result.setSuccess(false);
+ result.setMessage("用户名不能为空");
+ return result;
+ }
+
+ if (user.getPassword() == null || user.getPassword().trim().isEmpty()) {
+ result.setSuccess(false);
+ result.setMessage("密码不能为空");
+ return result;
+ }
+
+ // 2. 密码一致性校验
+ if (!user.getPassword().equals(confirmPassword)) {
+ result.setSuccess(false);
+ result.setMessage("两次输入的密码不一致");
+ return result;
+ }
+
+ // 3. 手机号格式校验
+ if (user.getPhone() == null || !user.getPhone().matches("^1[3-9]\\d{9}$")) {
+ result.setSuccess(false);
+ result.setMessage("手机号格式不正确");
+ return result;
+ }
+
+ // 4. 用户名唯一性校验
+ User existUser = userDao.findByUsername(user.getUserName());
+ if (existUser != null) {
+ result.setSuccess(false);
+ result.setMessage("用户名已存在");
+ return result;
+ }
+
+ // 5. 手机号唯一性校验
+ User existPhone = userDao.findByPhone(user.getPhone());
+ if (existPhone != null) {
+ result.setSuccess(false);
+ result.setMessage("手机号已注册");
+ return result;
+ }
+
+ // 6. 密码加密
+ user.setPassword(MD5Util.md5(user.getPassword()));
+ user.setStatus("0"); // 默认未认证
+
+ // 7. 保存用户
+ boolean success = userDao.add(user);
+ result.setSuccess(success);
+ result.setMessage(success ? "注册成功" : "注册失败,请稍后重试");
+
+ return result;
+ }
+}
diff --git a/HRS/src/com/hrs/util/DBUtil.java b/HRS/src/com/hrs/util/DBUtil.java
new file mode 100644
index 0000000..7a38f5b
--- /dev/null
+++ b/HRS/src/com/hrs/util/DBUtil.java
@@ -0,0 +1,158 @@
+package com.hrs.util;
+
+import java.sql.*;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: DBUtil.java
+* @Description: 数据库连接工具类
+*
+* @version: v1.0.0
+* @author: 董济硕
+* @date: 2026年4月13日 上午10:08:25
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 董济硕 v1.0.0 新建文件
+*/
+public class DBUtil {
+
+ // 数据库配置信息
+ private static final String DRIVER = "com.mysql.jdbc.Driver";
+ private static final String URL = "jdbc:mysql://localhost:3306/hrs?useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true";
+ private static final String USERNAME = "root"; // MySQL用户名
+ private static final String PASSWORD = "root"; // MySQL密码
+ /**
+ *
+ * @Function:
+ * @Description: 静态代码块:加载数据库驱动
+ *
+ * @param: 无
+ * @return:无
+ * @throws:ClassNotFoundException
+ *
+ * @version: v1.0.0
+ * @author: 董济硕
+ * @date: 2025年4月6日 上午10:11:25
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 董济硕 v1.0.0 新建方法
+ */
+ static {
+ try {
+ Class.forName(DRIVER);
+ System.out.println("✅ MySQL驱动加载成功!");
+ } catch (ClassNotFoundException e) {
+ System.out.println("❌ MySQL驱动加载失败!");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ *
+ * @Function: getConnection
+ * @Description: 获取数据库连接
+ *
+ * @param: 无
+ * @return:Connection 数据库连接对象
+ * @throws:SQLException
+ *
+ * @version: v1.0.0
+ * @author: 董济硕
+ * @date: 2025年4月6日 上午10:14:58
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 董济硕 v1.0.0 新建方法
+ */
+ public static Connection getConnection() throws SQLException {
+ return DriverManager.getConnection(URL, USERNAME, PASSWORD);
+ }
+ /**
+ *
+ * @Function: close
+ * @Description: 关闭连接(查询用)
+ *
+ * @param: ResultSet 结果集, PreparedStatement 预编译语句, Connection 数据库连接
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 董济硕
+ * @date: 2025年4月6日 上午10:19:21
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 董济硕 v1.0.0 新建方法
+ */
+
+ public static void close(ResultSet rs, PreparedStatement pstmt, Connection conn) {
+ if (rs != null) {
+ try { rs.close(); } catch (SQLException e) { e.printStackTrace(); }
+ }
+ close(pstmt, conn);
+ }
+ /**
+ *
+ * @Function: close
+ * @Description: 关闭连接(增删改用)
+ *
+ * @param: PreparedStatement 预编译语句, Connection 数据库连接
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 董济硕
+ * @date: 2025年4月6日 上午10:50:58
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 董济硕 v1.0.0 新建方法
+ */
+ public static void close(PreparedStatement pstmt, Connection conn) {
+ if (pstmt != null) {
+ try { pstmt.close(); } catch (SQLException e) { e.printStackTrace(); }
+ }
+ if (conn != null) {
+ try { conn.close(); } catch (SQLException e) { e.printStackTrace(); }
+ }
+ }
+ /**
+ *
+ * @Function: main
+ * @Description: 测试数据库连接
+ *
+ * @param: String[] 命令行参数
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 董济硕
+ * @date: 2025年4月6日 上午10:55:14
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 董济硕 v1.0.0 新建方法
+ */
+ public static void main(String[] args) {
+ Connection conn = null;
+ try {
+ conn = DBUtil.getConnection();
+ System.out.println("✅ 数据库连接成功!");
+ System.out.println("连接对象:" + conn);
+ } catch (SQLException e) {
+ System.out.println("❌ 数据库连接失败!");
+ e.printStackTrace();
+ } finally {
+ close(null, null, conn);
+ }
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/util/ImageUploadUtil.java b/HRS/src/com/hrs/util/ImageUploadUtil.java
new file mode 100644
index 0000000..4604c68
--- /dev/null
+++ b/HRS/src/com/hrs/util/ImageUploadUtil.java
@@ -0,0 +1,251 @@
+package com.hrs.util;
+
+import javax.servlet.http.Part;
+import java.io.*;
+import java.text.SimpleDateFormat;
+import java.util.*;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: ImageUploadUtil.java
+* @Description: 房源图片上传工具类
+*
+* @version: v1.0.0
+* @author: 黄红
+* @date: 2026年4月13日 上午10:09:44
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 黄红 v1.0.0 新建文件
+*/
+public class ImageUploadUtil {
+
+ // 允许的图片类型
+ private static final Set ALLOWED_TYPES = new HashSet<>(Arrays.asList(
+ "image/jpeg", "image/jpg", "image/png", "image/gif"
+ ));
+
+ // 最大文件大小 5MB
+ private static final long MAX_FILE_SIZE = 5 * 1024 * 1024;
+
+ // 上传目录
+ private static final String UPLOAD_DIR = "upload/house/";
+ /**
+ *
+ * @Function: saveImage
+ * @Description: 保存单张图片
+ *
+ * @param: Part 文件部件, HttpServletRequest 请求对象
+ * @return:String 图片相对路径,失败返回null
+ * @throws:IOException
+ *
+ * @version: v1.0.0
+ * @author: 黄红
+ * @date: 2025年4月6日 上午10:11:11
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 黄红 v1.0.0 新建方法
+ */
+ public static String saveImage(Part part, javax.servlet.http.HttpServletRequest request) {
+ if (part == null || part.getSize() == 0) {
+ return null;
+ }
+
+ // 检查文件类型
+ String contentType = part.getContentType();
+ if (!ALLOWED_TYPES.contains(contentType)) {
+ System.out.println("不支持的文件类型:" + contentType);
+ return null;
+ }
+
+ // 检查文件大小
+ if (part.getSize() > MAX_FILE_SIZE) {
+ System.out.println("文件过大:" + part.getSize());
+ return null;
+ }
+
+ // 获取文件扩展名
+ String extension = getExtension(contentType);
+
+ // 生成唯一文件名
+ String fileName = generateFileName() + extension;
+
+ // 获取上传目录的绝对路径
+ String uploadPath = request.getServletContext().getRealPath("/") + UPLOAD_DIR;
+
+ // 创建目录
+ File uploadDir = new File(uploadPath);
+ if (!uploadDir.exists()) {
+ uploadDir.mkdirs();
+ }
+
+ // 保存文件
+ String filePath = uploadPath + fileName;
+ try (InputStream input = part.getInputStream();
+ OutputStream output = new FileOutputStream(filePath)) {
+
+ byte[] buffer = new byte[1024];
+ int length;
+ while ((length = input.read(buffer)) > 0) {
+ output.write(buffer, 0, length);
+ }
+
+ return UPLOAD_DIR + fileName;
+
+ } catch (IOException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ /**
+ *
+ * @Function: saveMultipleImages
+ * @Description: 保存多张图片(用于添加房源)
+ *
+ * @param: Collection 文件部件集合, HttpServletRequest 请求对象
+ * @return:String 多张图片路径(逗号分隔),失败返回null
+ * @throws:IOException
+ *
+ * @version: v1.0.0
+ * @author: 黄红
+ * @date: 2025年4月6日 上午10:15:28
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 黄红 v1.0.0 新建方法
+ */
+ public static String saveMultipleImages(java.util.Collection parts,
+ javax.servlet.http.HttpServletRequest request) {
+ List savedPaths = new ArrayList<>();
+
+ for (Part part : parts) {
+ if (part.getName().equals("images") && part.getSize() > 0) {
+ String path = saveImage(part, request);
+ if (path != null) {
+ savedPaths.add(path);
+ }
+ }
+ }
+
+ if (savedPaths.isEmpty()) {
+ return null;
+ }
+
+ return String.join(",", savedPaths);
+ }
+ /**
+ *
+ * @Function: deleteImage
+ * @Description: 删除图片文件
+ *
+ * @param: imagePath 图片相对路径, HttpServletRequest 请求对象
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 黄红
+ * @date: 2025年4月6日 上午10:14:23
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 黄红 v1.0.0 新建方法
+ */
+ public static void deleteImage(String imagePath, javax.servlet.http.HttpServletRequest request) {
+ if (imagePath == null || imagePath.trim().isEmpty()) {
+ return;
+ }
+
+ String realPath = request.getServletContext().getRealPath("/") + imagePath;
+ File file = new File(realPath);
+ if (file.exists()) {
+ file.delete();
+ }
+ }
+ /**
+ *
+ * @Function: deleteImages
+ * @Description: 删除多张图片
+ *
+ * @param: imagePaths 多张图片路径(逗号分隔), HttpServletRequest 请求对象
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 黄红
+ * @date: 2025年4月6日 上午10:20:18
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 黄红 v1.0.0 新建方法
+ */
+ public static void deleteImages(String imagePaths, javax.servlet.http.HttpServletRequest request) {
+ if (imagePaths == null || imagePaths.trim().isEmpty()) {
+ return;
+ }
+
+ String[] paths = imagePaths.split(",");
+ for (String path : paths) {
+ deleteImage(path.trim(), request);
+ }
+ }
+ /**
+ *
+ * @Function: getExtension
+ * @Description: 根据内容类型获取文件扩展名
+ *
+ * @param: contentType 文件内容类型
+ * @return:String 文件扩展名
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 黄红
+ * @date: 2025年4月6日 上午10:22:45
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 黄红 v1.0.0 新建方法
+ */
+ private static String getExtension(String contentType) {
+ switch (contentType) {
+ case "image/jpeg":
+ case "image/jpg":
+ return ".jpg";
+ case "image/png":
+ return ".png";
+ case "image/gif":
+ return ".gif";
+ default:
+ return ".jpg";
+ }
+ }
+ /**
+ *
+ * @Function: generateFileName
+ * @Description: 生成唯一文件名
+ *
+ * @param: 无
+ * @return:String 唯一文件名
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 黄红
+ * @date: 2025年4月6日 上午10:24:23
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 黄红 v1.0.0 新建方法
+ */
+ private static String generateFileName() {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
+ return sdf.format(new Date()) + "_" + UUID.randomUUID().toString().substring(0, 8);
+ }
+}
\ No newline at end of file
diff --git a/HRS/src/com/hrs/util/MD5Util.java b/HRS/src/com/hrs/util/MD5Util.java
new file mode 100644
index 0000000..c0050a9
--- /dev/null
+++ b/HRS/src/com/hrs/util/MD5Util.java
@@ -0,0 +1,142 @@
+package com.hrs.util;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+* Copyright: Copyright (c) 2026 chinasofti
+*
+* @ClassName: MD5Util.java
+* @Description: MD5加密工具类
+*
+* @version: v1.0.0
+* @author: 李鑫
+* @date: 2026年4月13日 上午10:10:21
+*
+* Modification History:
+* Date Author Version Description
+*---------------------------------------------------------*
+* 2026年4月13日 李鑫 v1.0.0 新建文件
+*/
+public class MD5Util {
+ /**
+ *
+ * @Function: md5
+ * @Description: 将字符串进行MD5加密
+ *
+ * @param: str 要加密的字符串
+ * @return:String MD5加密后的32位小写字符串
+ * @throws:NoSuchAlgorithmException
+ *
+ * @version: v1.0.0
+ * @author: 李鑫
+ * @date: 2025年4月6日 上午10:20:32
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 李鑫 v1.0.0 新建方法
+ */
+ public static String md5(String str) {
+ if (str == null || str.isEmpty()) {
+ return null;
+ }
+
+ try {
+ MessageDigest md = MessageDigest.getInstance("MD5");
+ byte[] bytes = md.digest(str.getBytes());
+
+ // 将字节数组转换为十六进制字符串
+ StringBuilder sb = new StringBuilder();
+ for (byte b : bytes) {
+ // 取字节的高四位
+ int high = (b >> 4) & 0x0f;
+ // 取字节的低四位
+ int low = b & 0x0f;
+ sb.append(hexChar(high));
+ sb.append(hexChar(low));
+ }
+
+ return sb.toString();
+
+ } catch (NoSuchAlgorithmException e) {
+ e.printStackTrace();
+ return null;
+ }
+ }
+ /**
+ *
+ * @Function: hexChar
+ * @Description: 将0-15的数字转换为十六进制字符
+ *
+ * @param: value 0-15的整数值
+ * @return:char 对应的十六进制字符
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李鑫
+ * @date: 2025年4月6日 上午10:24:58
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 李鑫 v1.0.0 新建方法
+ */
+ private static char hexChar(int value) {
+ if (value >= 0 && value <= 9) {
+ return (char) ('0' + value);
+ } else {
+ return (char) ('a' + (value - 10));
+ }
+ }
+ /**
+ *
+ * @Function: verify
+ * @Description: 验证密码是否匹配
+ *
+ * @param: inputPassword 用户输入的明文密码, storedPassword 数据库中存储的MD5密码
+ * @return:boolean 是否匹配
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李鑫
+ * @date: 2025年4月6日 上午10:28:42
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 李鑫 v1.0.0 新建方法
+ */
+ public static boolean verify(String inputPassword, String storedPassword) {
+ String encrypted = md5(inputPassword);
+ return encrypted != null && encrypted.equals(storedPassword);
+ }
+ /**
+ *
+ * @Function: main
+ * @Description: 测试方法
+ *
+ * @param: String[] 命令行参数
+ * @return:无
+ * @throws:无
+ *
+ * @version: v1.0.0
+ * @author: 李鑫
+ * @date: 2025年4月6日 上午10:30:25
+ *
+ * Modification History:
+ * Date Author Version Description
+ *---------------------------------------------------------*
+ * 2025年4月6日 李鑫 v1.0.0 新建方法
+ */
+ public static void main(String[] args) {
+ String password = "123456";
+ String encrypted = md5(password);
+ System.out.println("明文密码:" + password);
+ System.out.println("MD5加密:" + encrypted);
+ System.out.println("长度:" + encrypted.length());
+
+ // 验证
+ System.out.println("验证结果:" + verify("123456", encrypted));
+ }
+}
\ No newline at end of file