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/HRS/.classpath b/HRS/HRS/.classpath new file mode 100644 index 0000000..cd67f69 --- /dev/null +++ b/HRS/HRS/.classpath @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/HRS/HRS/.project b/HRS/HRS/.project new file mode 100644 index 0000000..91242a4 --- /dev/null +++ b/HRS/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/HRS/.settings/.jsdtscope b/HRS/HRS/.settings/.jsdtscope new file mode 100644 index 0000000..92e666d --- /dev/null +++ b/HRS/HRS/.settings/.jsdtscope @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/HRS/HRS/.settings/org.eclipse.jdt.core.prefs b/HRS/HRS/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..0c68a61 --- /dev/null +++ b/HRS/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/HRS/.settings/org.eclipse.wst.common.component b/HRS/HRS/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..b729e7b --- /dev/null +++ b/HRS/HRS/.settings/org.eclipse.wst.common.component @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/HRS/HRS/.settings/org.eclipse.wst.common.project.facet.core.xml b/HRS/HRS/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..95377b2 --- /dev/null +++ b/HRS/HRS/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/HRS/HRS/.settings/org.eclipse.wst.jsdt.ui.superType.container b/HRS/HRS/.settings/org.eclipse.wst.jsdt.ui.superType.container new file mode 100644 index 0000000..3bd5d0a --- /dev/null +++ b/HRS/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/HRS/.settings/org.eclipse.wst.jsdt.ui.superType.name b/HRS/HRS/.settings/org.eclipse.wst.jsdt.ui.superType.name new file mode 100644 index 0000000..05bd71b --- /dev/null +++ b/HRS/HRS/.settings/org.eclipse.wst.jsdt.ui.superType.name @@ -0,0 +1 @@ +Window \ No newline at end of file diff --git a/HRS/HRS/WebContent/META-INF/MANIFEST.MF b/HRS/HRS/WebContent/META-INF/MANIFEST.MF new file mode 100644 index 0000000..254272e --- /dev/null +++ b/HRS/HRS/WebContent/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/HRS/HRS/WebContent/WEB-INF/lib/mysql-connector-java-5.1.49.jar b/HRS/HRS/WebContent/WEB-INF/lib/mysql-connector-java-5.1.49.jar new file mode 100644 index 0000000..0b6e2a6 Binary files /dev/null and b/HRS/HRS/WebContent/WEB-INF/lib/mysql-connector-java-5.1.49.jar differ diff --git a/HRS/HRS/WebContent/WEB-INF/web.xml b/HRS/HRS/WebContent/WEB-INF/web.xml new file mode 100644 index 0000000..f3419fc --- /dev/null +++ b/HRS/HRS/WebContent/WEB-INF/web.xml @@ -0,0 +1,29 @@ + + + + HRS + + + + index.jsp + + + + + encodingFilter + com.hrs.filter.EncodingFilter + + encoding + UTF-8 + + + + encodingFilter + /* + + + \ No newline at end of file diff --git a/HRS/HRS/WebContent/jsp/admin/index.jsp b/HRS/HRS/WebContent/jsp/admin/index.jsp new file mode 100644 index 0000000..147acf8 --- /dev/null +++ b/HRS/HRS/WebContent/jsp/admin/index.jsp @@ -0,0 +1,20 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="com.hrs.model.entity.User" %> +<% + User loginUser = (User)session.getAttribute("loginUser"); + if(loginUser == null || !"2".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } +%> + + + + + 管理员首页 + + +

欢迎管理员:<%= loginUser.getRealName() %>

+ 退出登录 + + \ No newline at end of file diff --git a/HRS/HRS/WebContent/jsp/landlord/index.jsp b/HRS/HRS/WebContent/jsp/landlord/index.jsp new file mode 100644 index 0000000..2351d47 --- /dev/null +++ b/HRS/HRS/WebContent/jsp/landlord/index.jsp @@ -0,0 +1,20 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="com.hrs.model.entity.User" %> +<% + User loginUser = (User)session.getAttribute("loginUser"); + if(loginUser == null || !"1".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } +%> + + + + + 房东首页 + + +

欢迎房东:<%= loginUser.getRealName() %>

+ 退出登录 + + \ No newline at end of file diff --git a/HRS/HRS/WebContent/jsp/landlord/reservation_list.jsp b/HRS/HRS/WebContent/jsp/landlord/reservation_list.jsp new file mode 100644 index 0000000..e099acf --- /dev/null +++ b/HRS/HRS/WebContent/jsp/landlord/reservation_list.jsp @@ -0,0 +1,324 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="java.util.List, java.text.SimpleDateFormat, com.hrs.model.entity.Reservation, com.hrs.model.entity.House, com.hrs.model.entity.User" %> +<% + User loginUser = (User) session.getAttribute("loginUser"); + if (loginUser == null || !"1".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } + + List reservationList = (List) request.getAttribute("reservationList"); + Integer totalCount = (Integer) request.getAttribute("totalCount"); + String msg = request.getParameter("msg"); + String error = request.getParameter("error"); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); +%> + + + + + 预约管理 - 房东后台 + + + +
+
+ + + +
+
+ +
+ + + <% if (msg != null) { %> +
<%= msg %>
+ <% } %> + <% if (error != null) { %> +
<%= error %>
+ <% } %> + +
+ 📋 共有 <%= totalCount %> 条预约记录 +
+ +
+ <% + if (reservationList != null && !reservationList.isEmpty()) { + %> + + + + + + + + + + + + + <% + for (Reservation reservation : reservationList) { + House house = reservation.getHouse(); + User tenant = reservation.getTenant(); + %> + + + + + + + + + <% + } + %> + +
租客信息房源信息预约时间状态备注操作
+ <%= tenant.getRealName() != null ? tenant.getRealName() : tenant.getUserName() %>
+ <%= tenant.getPhone() %> +
+ <%= house.getTitle() %>
+ <%= house.getArea() %> +
<%= sdf.format(reservation.getReserveTime()) %> + "> + <%= reservation.getStatusText() %> + + + <%= reservation.getRemark() != null ? reservation.getRemark() : "-" %> + + <% if ("0".equals(reservation.getStatus())) { %> + 确认 + 拒绝 + <% } else { %> + 已处理 + <% } %> +
+ <% + } else { + %> +
+
📅
+

暂无预约记录

+
+ <% + } + %> +
+
+ + + + \ No newline at end of file diff --git a/HRS/HRS/WebContent/jsp/user/collection_list.jsp b/HRS/HRS/WebContent/jsp/user/collection_list.jsp new file mode 100644 index 0000000..3adf659 --- /dev/null +++ b/HRS/HRS/WebContent/jsp/user/collection_list.jsp @@ -0,0 +1,418 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="java.util.List, com.hrs.model.entity.Collection, com.hrs.model.entity.House, com.hrs.model.entity.User" %> +<% + User loginUser = (User) session.getAttribute("loginUser"); + if (loginUser == null || !"0".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } + + List collectionList = (List) request.getAttribute("collectionList"); + Integer totalCount = (Integer) request.getAttribute("totalCount"); + String msg = request.getParameter("msg"); + String error = request.getParameter("error"); +%> + + + + + 我的收藏 - 租房系统 + + + +
+
+ + + +
+
+ +
+ + + <% if (msg != null) { %> +
<%= msg %>
+ <% } %> + <% if (error != null) { %> +
<%= error %>
+ <% } %> + +
+ 📚 共收藏 <%= totalCount %> 套房源 +
+ +
+ <% + if (collectionList != null && !collectionList.isEmpty()) { + for (Collection collection : collectionList) { + House house = collection.getHouse(); + if (house != null) { + %> +
+
');"> + <% if (house.getFirstImage() == null) { %> +
🏠 暂无图片
+ <% } %> +
+ +
+ +
+ 📍 <%= house.getArea() %> | <%= house.getHouseType() %> | <%= house.getRentTypeText() %> +
+
+ ¥<%= house.getRentPrice() %>/月 +
+
+ 收藏时间:<%= collection.getCollectTime() %> +
+
+
+ <% + } + } + } else { + %> +
+
❤️
+

还没有收藏任何房源

+

去浏览房源 >>

+
+ <% + } + %> +
+
+ + + + + + \ No newline at end of file diff --git a/HRS/HRS/WebContent/jsp/user/house_detail.jsp b/HRS/HRS/WebContent/jsp/user/house_detail.jsp new file mode 100644 index 0000000..6b6be5b --- /dev/null +++ b/HRS/HRS/WebContent/jsp/user/house_detail.jsp @@ -0,0 +1,597 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="com.hrs.model.entity.House, com.hrs.model.entity.User" %> +<% + User loginUser = (User) session.getAttribute("loginUser"); + if (loginUser == null || !"0".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } + + House house = (House) request.getAttribute("house"); + if (house == null) { + response.sendRedirect(request.getContextPath() + "/user/house/list"); + return; + } +%> + + + + + <%= house.getTitle() %> - 租房系统 + + + + +
+
+ + + +
+
+ +
+ + + +
+ +
+
');"> + <% if (house.getFirstImage() == null) { %> +
🏠 暂无图片
+ <% } %> +
+
+ <% + String[] images = null; + if (house.getImgUrl() != null && !house.getImgUrl().isEmpty()) { + images = house.getImgUrl().split(","); + for (int i = 0; i < images.length; i++) { + %> +
+ <% + } + } + %> +
+
+ + +
+
<%= house.getTitle() %>
+ +
+ ¥<%= house.getRentPrice() %>/月 +
+ +
+
+
户型
+
<%= house.getHouseType() != null ? house.getHouseType() : "待定" %>
+
+
+
面积
+
<%= house.getArea() != null ? house.getArea() : "待定" %>
+
+
+
租赁类型
+
<%= house.getRentTypeText() %>
+
+
+
房源编号
+
<%= house.getHouseNo() %>
+
+
+ +
+
📍 房源地址
+

<%= house.getAddress() != null ? house.getAddress() : "暂无地址信息" %>

+
+ +
+
🛋️ 配套设施
+
+ <% + String facility = house.getFacility(); + if (facility != null && !facility.isEmpty()) { + String[] facilities = facility.split(","); + for (String f : facilities) { + %> + <%= f.trim() %> + <% + } + } else { + %> + 暂无设施信息 + <% + } + %> +
+
+ +
+
📝 房源描述
+
+ <%= house.getDescription() != null ? house.getDescription() : "暂无描述信息" %> +
+
+
+
+ + +
+
👤 房东信息
+
+
👨
+
+

<%= house.getLandlordName() != null ? house.getLandlordName() : "房东" %>

+

📞 <%= house.getLandlordPhone() != null ? house.getLandlordPhone() : "暂无联系方式" %>

+

⭐ 认证房东 · 已发布房源

+
+
+
+ + +
+ + <% + // 检查是否已收藏 + com.hrs.model.dao.CollectionDAO collectionDAO = new com.hrs.model.dao.CollectionDAO(); + boolean isCollected = collectionDAO.isCollected(loginUser.getId(), house.getId()); + if (isCollected) { + %> + + <% + } else { + %> + + <% + } + %> + 🔙 返回列表 +
+
+ + + + + + + \ No newline at end of file diff --git a/HRS/HRS/WebContent/jsp/user/house_list.jsp b/HRS/HRS/WebContent/jsp/user/house_list.jsp new file mode 100644 index 0000000..c5e1043 --- /dev/null +++ b/HRS/HRS/WebContent/jsp/user/house_list.jsp @@ -0,0 +1,412 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="java.util.List, com.hrs.model.entity.House, com.hrs.model.entity.User" %> +<% + User loginUser = (User) session.getAttribute("loginUser"); + if (loginUser == null || !"0".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } + + List houseList = (List) request.getAttribute("houseList"); + Integer totalCount = (Integer) request.getAttribute("totalCount"); +%> + + + + + 房源列表 - 租房系统 + + + + +
+
+ + + +
+
+ + + + +
+ +
+ 📊 共找到 <%= totalCount %> 套房源 +
+ + +
+ <% + if (houseList != null && !houseList.isEmpty()) { + for (House house : houseList) { + %> +
+
');"> + <% if (house.getFirstImage() == null) { %> +
🏠 暂无图片
+ <% } %> +
+
+ +
+ 📍 <%= house.getArea() %> | <%= house.getHouseType() %> | <%= house.getRentTypeText() %> +
+
+ ¥<%= house.getRentPrice() %>/月 +
+
+ #<%= house.getHouseType() %> + #<%= house.getArea() %> +
+ +
+
+ <% + } + } else { + %> +
+
🏠
+

暂无房源,请稍后再来

+
+ <% + } + %> +
+
+ + + + + \ No newline at end of file diff --git a/HRS/HRS/WebContent/jsp/user/index.jsp b/HRS/HRS/WebContent/jsp/user/index.jsp new file mode 100644 index 0000000..67c74d8 --- /dev/null +++ b/HRS/HRS/WebContent/jsp/user/index.jsp @@ -0,0 +1,5 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<% + // 重定向到房源列表页 + response.sendRedirect(request.getContextPath() + "/user/house/list"); +%> \ No newline at end of file diff --git a/HRS/HRS/WebContent/jsp/user/login.jsp b/HRS/HRS/WebContent/jsp/user/login.jsp new file mode 100644 index 0000000..068c479 --- /dev/null +++ b/HRS/HRS/WebContent/jsp/user/login.jsp @@ -0,0 +1,151 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + + + + + 租房系统登录 + + + + + + \ No newline at end of file diff --git a/HRS/HRS/WebContent/jsp/user/register.jsp b/HRS/HRS/WebContent/jsp/user/register.jsp new file mode 100644 index 0000000..0421653 --- /dev/null +++ b/HRS/HRS/WebContent/jsp/user/register.jsp @@ -0,0 +1,218 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + + + + + 租房系统注册 + + + +
+

租房系统注册

+ + <%-- 显示错误信息 --%> + <% + String error = (String)request.getAttribute("error"); + if(error != null) { + %> +
<%= error %>
+ <% + } + %> + + <%-- 显示成功信息 --%> + <% + String message = (String)request.getAttribute("message"); + if(message != null) { + %> +
<%= message %>
+ <% + } + %> + +
+
+ + +
+ +
+ + +
密码长度6-20位,建议使用字母+数字组合
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
房东认证需要提供身份证号
+
+ +
+ +
+ + +
+
房东需要管理员审核认证后才能发布房源
+
+ + +
+ + +
+ + + + \ No newline at end of file diff --git a/HRS/HRS/WebContent/jsp/user/reservation_add.jsp b/HRS/HRS/WebContent/jsp/user/reservation_add.jsp new file mode 100644 index 0000000..8fa4252 --- /dev/null +++ b/HRS/HRS/WebContent/jsp/user/reservation_add.jsp @@ -0,0 +1,313 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="com.hrs.model.entity.House, com.hrs.model.entity.User" %> +<% + User loginUser = (User) session.getAttribute("loginUser"); + if (loginUser == null || !"0".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } + + House house = (House) request.getAttribute("house"); + if (house == null) { + response.sendRedirect(request.getContextPath() + "/user/house/list"); + return; + } + + String error = (String) request.getAttribute("error"); +%> + + + + + 预约看房 - 租房系统 + + + +
+
+ + + +
+
+ +
+ + +
+

📅 预约看房

+ + <% if (error != null) { %> +
<%= error %>
+ <% } %> + + +
+
');"> + <% if (house.getFirstImage() == null) { %> +
🏠
+ <% } %> +
+
+
<%= house.getTitle() %>
+
📍 <%= house.getArea() %> | <%= house.getHouseType() %> | <%= house.getRentTypeText() %>
+
¥<%= house.getRentPrice() %>/月
+
+
+ +
+ + +
+ + "> +
请选择您方便的看房日期
+
+ +
+ + +
建议选择 9:00-18:00 之间的时间
+
+ +
+ + +
+ +
+ + 返回 +
+
+
+
+ + + + + + \ No newline at end of file diff --git a/HRS/HRS/WebContent/jsp/user/reservation_list.jsp b/HRS/HRS/WebContent/jsp/user/reservation_list.jsp new file mode 100644 index 0000000..a42c9d5 --- /dev/null +++ b/HRS/HRS/WebContent/jsp/user/reservation_list.jsp @@ -0,0 +1,347 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="java.util.List, java.text.SimpleDateFormat, com.hrs.model.entity.Reservation, com.hrs.model.entity.House, com.hrs.model.entity.User" %> +<% + User loginUser = (User) session.getAttribute("loginUser"); + if (loginUser == null || !"0".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } + + List reservationList = (List) request.getAttribute("reservationList"); + Integer totalCount = (Integer) request.getAttribute("totalCount"); + String msg = request.getParameter("msg"); + String error = request.getParameter("error"); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); +%> + + + + + 我的预约 - 租房系统 + + + +
+
+ + + +
+
+ +
+ + + <% if (msg != null) { %> +
<%= msg %>
+ <% } %> + <% if (error != null) { %> +
<%= error %>
+ <% } %> + +
+ 📋 共有 <%= totalCount %> 条预约记录 +
+ +
+ <% + if (reservationList != null && !reservationList.isEmpty()) { + %> + + + + + + + + + + + + <% + for (Reservation reservation : reservationList) { + House house = reservation.getHouse(); + %> + + + + + + + + <% + } + %> + +
房源信息预约时间状态备注操作
+ + <%= house.getTitle() %> +
+ <%= house.getArea() %> | ¥<%= house.getRentPrice() %>/月 +
<%= sdf.format(reservation.getReserveTime()) %> + "> + <%= reservation.getStatusText() %> + + + <%= reservation.getRemark() != null ? reservation.getRemark() : "-" %> + + <% if ("0".equals(reservation.getStatus())) { %> + 取消 + <% } else { %> + 已处理 + <% } %> +
+ <% + } else { + %> +
+
📅
+

还没有任何预约记录

+

去浏览房源 >>

+
+ <% + } + %> +
+
+ + + + \ No newline at end of file diff --git a/HRS/HRS/build/classes/com/hrs/controller/landlord/ReservationHandleController.class b/HRS/HRS/build/classes/com/hrs/controller/landlord/ReservationHandleController.class new file mode 100644 index 0000000..7669648 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/controller/landlord/ReservationHandleController.class differ diff --git a/HRS/HRS/build/classes/com/hrs/controller/landlord/ReservationManageController.class b/HRS/HRS/build/classes/com/hrs/controller/landlord/ReservationManageController.class new file mode 100644 index 0000000..f905516 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/controller/landlord/ReservationManageController.class differ diff --git a/HRS/HRS/build/classes/com/hrs/controller/user/CollectionAddController.class b/HRS/HRS/build/classes/com/hrs/controller/user/CollectionAddController.class new file mode 100644 index 0000000..0c19cd3 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/controller/user/CollectionAddController.class differ diff --git a/HRS/HRS/build/classes/com/hrs/controller/user/CollectionDeleteController.class b/HRS/HRS/build/classes/com/hrs/controller/user/CollectionDeleteController.class new file mode 100644 index 0000000..f432e95 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/controller/user/CollectionDeleteController.class differ diff --git a/HRS/HRS/build/classes/com/hrs/controller/user/CollectionListController.class b/HRS/HRS/build/classes/com/hrs/controller/user/CollectionListController.class new file mode 100644 index 0000000..3e10dc1 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/controller/user/CollectionListController.class differ diff --git a/HRS/HRS/build/classes/com/hrs/controller/user/HouseDetailController.class b/HRS/HRS/build/classes/com/hrs/controller/user/HouseDetailController.class new file mode 100644 index 0000000..946e166 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/controller/user/HouseDetailController.class differ diff --git a/HRS/HRS/build/classes/com/hrs/controller/user/HouseListController.class b/HRS/HRS/build/classes/com/hrs/controller/user/HouseListController.class new file mode 100644 index 0000000..b925e26 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/controller/user/HouseListController.class differ diff --git a/HRS/HRS/build/classes/com/hrs/controller/user/LoginController.class b/HRS/HRS/build/classes/com/hrs/controller/user/LoginController.class new file mode 100644 index 0000000..d610f8c Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/controller/user/LoginController.class differ diff --git a/HRS/HRS/build/classes/com/hrs/controller/user/LogoutController.class b/HRS/HRS/build/classes/com/hrs/controller/user/LogoutController.class new file mode 100644 index 0000000..e077aa5 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/controller/user/LogoutController.class differ diff --git a/HRS/HRS/build/classes/com/hrs/controller/user/RegisterController.class b/HRS/HRS/build/classes/com/hrs/controller/user/RegisterController.class new file mode 100644 index 0000000..eb9d7ac Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/controller/user/RegisterController.class differ diff --git a/HRS/HRS/build/classes/com/hrs/controller/user/ReservationAddController.class b/HRS/HRS/build/classes/com/hrs/controller/user/ReservationAddController.class new file mode 100644 index 0000000..2e18798 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/controller/user/ReservationAddController.class differ diff --git a/HRS/HRS/build/classes/com/hrs/controller/user/ReservationCancelController.class b/HRS/HRS/build/classes/com/hrs/controller/user/ReservationCancelController.class new file mode 100644 index 0000000..d432545 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/controller/user/ReservationCancelController.class differ diff --git a/HRS/HRS/build/classes/com/hrs/controller/user/ReservationListController.class b/HRS/HRS/build/classes/com/hrs/controller/user/ReservationListController.class new file mode 100644 index 0000000..e2ae5eb Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/controller/user/ReservationListController.class differ diff --git a/HRS/HRS/build/classes/com/hrs/filter/EncodingFilter.class b/HRS/HRS/build/classes/com/hrs/filter/EncodingFilter.class new file mode 100644 index 0000000..b4eeb4c Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/filter/EncodingFilter.class differ diff --git a/HRS/HRS/build/classes/com/hrs/filter/LoginFilter.class b/HRS/HRS/build/classes/com/hrs/filter/LoginFilter.class new file mode 100644 index 0000000..37f063f Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/filter/LoginFilter.class differ diff --git a/HRS/HRS/build/classes/com/hrs/model/dao/CollectionDAO.class b/HRS/HRS/build/classes/com/hrs/model/dao/CollectionDAO.class new file mode 100644 index 0000000..ecaaf73 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/model/dao/CollectionDAO.class differ diff --git a/HRS/HRS/build/classes/com/hrs/model/dao/HouseDAO.class b/HRS/HRS/build/classes/com/hrs/model/dao/HouseDAO.class new file mode 100644 index 0000000..00d5728 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/model/dao/HouseDAO.class differ diff --git a/HRS/HRS/build/classes/com/hrs/model/dao/ReservationDAO.class b/HRS/HRS/build/classes/com/hrs/model/dao/ReservationDAO.class new file mode 100644 index 0000000..72ce4af Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/model/dao/ReservationDAO.class differ diff --git a/HRS/HRS/build/classes/com/hrs/model/dao/UserDAO.class b/HRS/HRS/build/classes/com/hrs/model/dao/UserDAO.class new file mode 100644 index 0000000..4dbca1e Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/model/dao/UserDAO.class differ diff --git a/HRS/HRS/build/classes/com/hrs/model/entity/Collection.class b/HRS/HRS/build/classes/com/hrs/model/entity/Collection.class new file mode 100644 index 0000000..3e1e1ae Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/model/entity/Collection.class differ diff --git a/HRS/HRS/build/classes/com/hrs/model/entity/House.class b/HRS/HRS/build/classes/com/hrs/model/entity/House.class new file mode 100644 index 0000000..fa98b27 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/model/entity/House.class differ diff --git a/HRS/HRS/build/classes/com/hrs/model/entity/Reservation.class b/HRS/HRS/build/classes/com/hrs/model/entity/Reservation.class new file mode 100644 index 0000000..d61d630 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/model/entity/Reservation.class differ diff --git a/HRS/HRS/build/classes/com/hrs/model/entity/User.class b/HRS/HRS/build/classes/com/hrs/model/entity/User.class new file mode 100644 index 0000000..6767596 Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/model/entity/User.class differ diff --git a/HRS/HRS/build/classes/com/hrs/util/DBUtil.class b/HRS/HRS/build/classes/com/hrs/util/DBUtil.class new file mode 100644 index 0000000..6fa843c Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/util/DBUtil.class differ diff --git a/HRS/HRS/build/classes/com/hrs/util/MD5Util.class b/HRS/HRS/build/classes/com/hrs/util/MD5Util.class new file mode 100644 index 0000000..d58b17f Binary files /dev/null and b/HRS/HRS/build/classes/com/hrs/util/MD5Util.class differ diff --git a/HRS/HRS/sql/hrs_init.sql b/HRS/HRS/sql/hrs_init.sql new file mode 100644 index 0000000..0d6f4c6 --- /dev/null +++ b/HRS/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/HRS/src/com/hrs/controller/landlord/ReservationHandleController.java b/HRS/HRS/src/com/hrs/controller/landlord/ReservationHandleController.java new file mode 100644 index 0000000..4d5fe14 --- /dev/null +++ b/HRS/HRS/src/com/hrs/controller/landlord/ReservationHandleController.java @@ -0,0 +1,60 @@ +package com.hrs.controller.landlord; + +import com.hrs.model.dao.ReservationDAO; +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; + +/** + * 房东处理预约控制器 + */ +@WebServlet("/landlord/reservation/handle") +public class ReservationHandleController extends HttpServlet { + + private ReservationDAO reservationDAO = new ReservationDAO(); + + @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) { + response.sendRedirect(request.getContextPath() + "/landlord/reservation/list?msg=" + + ("confirm".equals(action) ? "已确认预约" : "已拒绝预约")); + } else { + response.sendRedirect(request.getContextPath() + "/landlord/reservation/list?error=操作失败"); + } + } +} \ No newline at end of file diff --git a/HRS/HRS/src/com/hrs/controller/landlord/ReservationManageController.java b/HRS/HRS/src/com/hrs/controller/landlord/ReservationManageController.java new file mode 100644 index 0000000..4b5147c --- /dev/null +++ b/HRS/HRS/src/com/hrs/controller/landlord/ReservationManageController.java @@ -0,0 +1,50 @@ +package com.hrs.controller.landlord; + +import com.hrs.model.dao.ReservationDAO; +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; + +/** + * 房东预约管理控制器 + */ +@WebServlet("/landlord/reservation/list") +public class ReservationManageController extends HttpServlet { + + private ReservationDAO reservationDAO = new ReservationDAO(); + + @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/HRS/src/com/hrs/controller/user/CollectionAddController.java b/HRS/HRS/src/com/hrs/controller/user/CollectionAddController.java new file mode 100644 index 0000000..97dfab7 --- /dev/null +++ b/HRS/HRS/src/com/hrs/controller/user/CollectionAddController.java @@ -0,0 +1,79 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.CollectionDAO; +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; + +/** + * 添加收藏控制器 + * AJAX请求,返回文本结果 + */ +@WebServlet("/user/collection/add") +public class CollectionAddController extends HttpServlet { + + private CollectionDAO collectionDAO = new CollectionDAO(); + + @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; + } + + // 3. 检查是否已收藏 + boolean exists = collectionDAO.isCollected(loginUser.getId(), houseId); + if (exists) { + out.print("exists"); + return; + } + + // 4. 添加收藏 + com.hrs.model.entity.Collection collection = new com.hrs.model.entity.Collection(); + collection.setTenantId(loginUser.getId()); + collection.setHouseId(houseId); + + boolean success = collectionDAO.add(collection); + + if (success) { + out.print("success"); + } else { + out.print("error"); + } + } +} \ No newline at end of file diff --git a/HRS/HRS/src/com/hrs/controller/user/CollectionDeleteController.java b/HRS/HRS/src/com/hrs/controller/user/CollectionDeleteController.java new file mode 100644 index 0000000..56a20b1 --- /dev/null +++ b/HRS/HRS/src/com/hrs/controller/user/CollectionDeleteController.java @@ -0,0 +1,111 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.CollectionDAO; +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; + +/** + * 取消收藏控制器 + * 支持两种删除方式: + * 1. AJAX删除(收藏列表页)- 返回JSON + * 2. 页面跳转删除(详情页)- 重定向 + */ +@WebServlet("/user/collection/delete") +public class CollectionDeleteController extends HttpServlet { + + private CollectionDAO collectionDAO = new CollectionDAO(); + + @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) { + // 从详情页删除,跳回详情页 + response.sendRedirect(request.getContextPath() + "/user/house/detail?id=" + houseIdStr + "&msg=取消收藏成功"); + } else if ("list".equals(from)) { + // 从收藏列表删除,跳回收藏列表 + response.sendRedirect(request.getContextPath() + "/user/collection/list?msg=取消收藏成功"); + } else { + // 默认跳回收藏列表 + response.sendRedirect(request.getContextPath() + "/user/collection/list?msg=取消收藏成功"); + } + } else { + if ("detail".equals(from) && houseIdStr != null) { + response.sendRedirect(request.getContextPath() + "/user/house/detail?id=" + houseIdStr + "&error=取消收藏失败"); + } else { + response.sendRedirect(request.getContextPath() + "/user/collection/list?error=取消收藏失败"); + } + } + } + } +} \ No newline at end of file diff --git a/HRS/HRS/src/com/hrs/controller/user/CollectionListController.java b/HRS/HRS/src/com/hrs/controller/user/CollectionListController.java new file mode 100644 index 0000000..c1db6df --- /dev/null +++ b/HRS/HRS/src/com/hrs/controller/user/CollectionListController.java @@ -0,0 +1,52 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.CollectionDAO; +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; + +/** + * 我的收藏列表控制器 + */ +@WebServlet("/user/collection/list") +public class CollectionListController extends HttpServlet { + + private CollectionDAO collectionDAO = new CollectionDAO(); + + @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/HRS/src/com/hrs/controller/user/HouseDetailController.java b/HRS/HRS/src/com/hrs/controller/user/HouseDetailController.java new file mode 100644 index 0000000..66de6c5 --- /dev/null +++ b/HRS/HRS/src/com/hrs/controller/user/HouseDetailController.java @@ -0,0 +1,62 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.HouseDAO; +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; + +/** + * 房源详情控制器 + * 租客端查看房源详情 + * URL映射:/user/house/detail + */ +@WebServlet("/user/house/detail") +public class HouseDetailController extends HttpServlet { + + private HouseDAO houseDAO = new HouseDAO(); + + @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/HRS/src/com/hrs/controller/user/HouseListController.java b/HRS/HRS/src/com/hrs/controller/user/HouseListController.java new file mode 100644 index 0000000..a444317 --- /dev/null +++ b/HRS/HRS/src/com/hrs/controller/user/HouseListController.java @@ -0,0 +1,63 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.HouseDAO; +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; + +/** + * 房源列表控制器 + * 租客端查看房源列表 + * URL映射:/user/house/list + */ +@WebServlet("/user/house/list") +public class HouseListController extends HttpServlet { + + private HouseDAO houseDAO = new HouseDAO(); + + @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/HRS/src/com/hrs/controller/user/LoginController.java b/HRS/HRS/src/com/hrs/controller/user/LoginController.java new file mode 100644 index 0000000..053fea6 --- /dev/null +++ b/HRS/HRS/src/com/hrs/controller/user/LoginController.java @@ -0,0 +1,106 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.UserDAO; +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; + +/** + * 登录控制器 + * 处理用户登录请求 + * URL映射:/user/login + */ +@WebServlet("/user/login") +public class LoginController extends HttpServlet { + + private UserDAO userDAO = new UserDAO(); + + @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. 调用DAO查询用户 + User user = userDAO.findByUsernameAndPassword(username, encryptedPassword); + + // 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/HRS/src/com/hrs/controller/user/LogoutController.java b/HRS/HRS/src/com/hrs/controller/user/LogoutController.java new file mode 100644 index 0000000..95156f9 --- /dev/null +++ b/HRS/HRS/src/com/hrs/controller/user/LogoutController.java @@ -0,0 +1,38 @@ +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; + +/** + * 退出登录控制器 + */ +@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/HRS/src/com/hrs/controller/user/RegisterController.java b/HRS/HRS/src/com/hrs/controller/user/RegisterController.java new file mode 100644 index 0000000..b541454 --- /dev/null +++ b/HRS/HRS/src/com/hrs/controller/user/RegisterController.java @@ -0,0 +1,120 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.UserDAO; +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 java.io.IOException; + +/** + * 注册控制器 + * 处理用户注册请求 + * URL映射:/user/register + */ +@WebServlet("/user/register") +public class RegisterController extends HttpServlet { + + private UserDAO userDAO = new UserDAO(); + + @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. 基础验证 + if (username == null || username.trim().isEmpty()) { + request.setAttribute("error", "用户名不能为空"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + return; + } + + if (password == null || password.trim().isEmpty()) { + request.setAttribute("error", "密码不能为空"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + return; + } + + // 3. 验证两次密码是否一致 + if (!password.equals(confirmPassword)) { + request.setAttribute("error", "两次输入的密码不一致"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + return; + } + + // 4. 验证手机号格式(简单验证) + if (phone == null || phone.trim().isEmpty() || !phone.matches("^1[3-9]\\d{9}$")) { + request.setAttribute("error", "手机号格式不正确"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + return; + } + + // 5. 检查用户名是否已存在 + User existUser = userDAO.findByUsername(username); + if (existUser != null) { + request.setAttribute("error", "用户名已存在,请换一个"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + return; + } + + // 6. 检查手机号是否已注册 + User existPhone = userDAO.findByPhone(phone); + if (existPhone != null) { + request.setAttribute("error", "手机号已注册"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + return; + } + + // 7. 创建用户对象 + User user = new User(); + user.setUserName(username); + user.setPassword(MD5Util.md5(password)); // 密码MD5加密 + user.setRealName(realName); + user.setPhone(phone); + user.setIdCard(idCard); + user.setRoleType(roleType); // 0-租客 1-房东 + user.setStatus("0"); // 默认未认证状态 + + // 8. 保存到数据库 + boolean success = userDAO.add(user); + + if (success) { + // 注册成功,跳转到登录页面 + request.setAttribute("message", "注册成功,请登录"); + request.getRequestDispatcher("/jsp/user/login.jsp").forward(request, response); + } else { + // 注册失败 + request.setAttribute("error", "注册失败,请稍后重试"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + } + if (success) { + // 注册成功,跳转到登录页面,并带上成功消息 + response.sendRedirect(request.getContextPath() + "/user/login?message=注册成功,请登录"); + } else { + // 注册失败 + request.setAttribute("error", "注册失败,请稍后重试"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + } + } +} \ No newline at end of file diff --git a/HRS/HRS/src/com/hrs/controller/user/ReservationAddController.java b/HRS/HRS/src/com/hrs/controller/user/ReservationAddController.java new file mode 100644 index 0000000..c04be9d --- /dev/null +++ b/HRS/HRS/src/com/hrs/controller/user/ReservationAddController.java @@ -0,0 +1,135 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.HouseDAO; +import com.hrs.model.dao.ReservationDAO; +import com.hrs.model.entity.House; +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.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * 添加预约控制器 + */ +@WebServlet("/user/reservation/add") +public class ReservationAddController extends HttpServlet { + + private ReservationDAO reservationDAO = new ReservationDAO(); + private HouseDAO houseDAO = new HouseDAO(); + + @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) { + response.sendRedirect(request.getContextPath() + "/user/house/list"); + 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); + } + + @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 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; + } + + Long houseId = Long.parseLong(houseIdStr); + House house = houseDAO.findById(houseId); + + if (house == null) { + request.setAttribute("error", "房源不存在"); + doGet(request, response); + return; + } + + // 组合预约时间 + String datetimeStr = reserveDate + " " + reserveTime + ":00"; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date reserveDateTime; + try { + reserveDateTime = sdf.parse(datetimeStr); + } catch (ParseException e) { + request.setAttribute("error", "时间格式错误"); + doGet(request, response); + return; + } + + // 检查预约时间是否在今天之后 + if (reserveDateTime.before(new Date())) { + request.setAttribute("error", "预约时间不能早于当前时间"); + doGet(request, response); + 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); + + if (success) { + response.sendRedirect(request.getContextPath() + "/user/reservation/list?msg=预约成功,请等待房东确认"); + } else { + request.setAttribute("error", "预约失败,请稍后重试"); + doGet(request, response); + } + } +} \ No newline at end of file diff --git a/HRS/HRS/src/com/hrs/controller/user/ReservationCancelController.java b/HRS/HRS/src/com/hrs/controller/user/ReservationCancelController.java new file mode 100644 index 0000000..6fb496f --- /dev/null +++ b/HRS/HRS/src/com/hrs/controller/user/ReservationCancelController.java @@ -0,0 +1,57 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.ReservationDAO; +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; + +/** + * 取消预约控制器(租客端) + */ +@WebServlet("/user/reservation/cancel") +public class ReservationCancelController extends HttpServlet { + + private ReservationDAO reservationDAO = new ReservationDAO(); + + @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; + } + + // 获取预约ID + String idStr = request.getParameter("id"); + if (idStr == null || idStr.trim().isEmpty()) { + response.sendRedirect(request.getContextPath() + "/user/reservation/list"); + return; + } + + Long id = Long.parseLong(idStr); + + // 取消预约 + boolean success = reservationDAO.cancel(id, loginUser.getId()); + + if (success) { + response.sendRedirect(request.getContextPath() + "/user/reservation/list?msg=取消预约成功"); + } else { + response.sendRedirect(request.getContextPath() + "/user/reservation/list?error=取消预约失败"); + } + } +} \ No newline at end of file diff --git a/HRS/HRS/src/com/hrs/controller/user/ReservationListController.java b/HRS/HRS/src/com/hrs/controller/user/ReservationListController.java new file mode 100644 index 0000000..2b3abfb --- /dev/null +++ b/HRS/HRS/src/com/hrs/controller/user/ReservationListController.java @@ -0,0 +1,50 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.ReservationDAO; +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; + +/** + * 我的预约列表控制器(租客端) + */ +@WebServlet("/user/reservation/list") +public class ReservationListController extends HttpServlet { + + private ReservationDAO reservationDAO = new ReservationDAO(); + + @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/HRS/src/com/hrs/filter/EncodingFilter.java b/HRS/HRS/src/com/hrs/filter/EncodingFilter.java new file mode 100644 index 0000000..e2f2ce1 --- /dev/null +++ b/HRS/HRS/src/com/hrs/filter/EncodingFilter.java @@ -0,0 +1,37 @@ +package com.hrs.filter; + +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import java.io.IOException; + +/** + * 字符编码过滤器 + */ +@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/HRS/src/com/hrs/filter/LoginFilter.java b/HRS/HRS/src/com/hrs/filter/LoginFilter.java new file mode 100644 index 0000000..0b28035 --- /dev/null +++ b/HRS/HRS/src/com/hrs/filter/LoginFilter.java @@ -0,0 +1,93 @@ +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; + +/** + * 登录过滤器 + * 拦截未登录的请求 + */ +@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/HRS/src/com/hrs/model/dao/CollectionDAO.java b/HRS/HRS/src/com/hrs/model/dao/CollectionDAO.java new file mode 100644 index 0000000..8b6b000 --- /dev/null +++ b/HRS/HRS/src/com/hrs/model/dao/CollectionDAO.java @@ -0,0 +1,204 @@ +package com.hrs.model.dao; + +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; + +/** + * 收藏数据访问类 + */ +public class CollectionDAO { + + private HouseDAO houseDAO = new HouseDAO(); + + /** + * 添加收藏 + */ + 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; + } + + /** + * 检查是否已收藏 + */ + 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; + } + + /** + * 取消收藏 + */ + 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删除 + */ + 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; + } + + /** + * 查询租客的所有收藏 + */ + 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; + } + + /** + * 查询租客的收藏数量 + */ + 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; + } +} \ No newline at end of file diff --git a/HRS/HRS/src/com/hrs/model/dao/HouseDAO.java b/HRS/HRS/src/com/hrs/model/dao/HouseDAO.java new file mode 100644 index 0000000..cb20c14 --- /dev/null +++ b/HRS/HRS/src/com/hrs/model/dao/HouseDAO.java @@ -0,0 +1,397 @@ +package com.hrs.model.dao; + +import com.hrs.model.entity.House; +import com.hrs.util.DBUtil; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +/** + * 房源数据访问类 + * 负责房源表的增删改查操作 + */ +public class HouseDAO { + + /** + * 查询已上架的房源(供租客查看) + */ + 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; + } + + /** + * 根据区域筛选房源 + */ + 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; + } + + /** + * 根据价格区间筛选房源 + */ + 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查询详情 + */ + 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; + } + + /** + * 查询房东自己的房源 + */ + 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; + } + + /** + * 查询所有房源(管理员用) + */ + 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; + } + + /** + * 添加房源 + */ + 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; + } + + /** + * 更新房源 + */ + 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; + } + + /** + * 更新房源状态(审核/上架/下架) + */ + 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; + } + + /** + * 删除房源 + */ + 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; + } + + /** + * 统计已上架房源数量 + */ + 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; + } + + /** + * 将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; + } +} \ No newline at end of file diff --git a/HRS/HRS/src/com/hrs/model/dao/ReservationDAO.java b/HRS/HRS/src/com/hrs/model/dao/ReservationDAO.java new file mode 100644 index 0000000..df01f51 --- /dev/null +++ b/HRS/HRS/src/com/hrs/model/dao/ReservationDAO.java @@ -0,0 +1,286 @@ +package com.hrs.model.dao; + +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; + +/** + * 预约看房数据访问类 + */ +public class ReservationDAO { + + private HouseDAO houseDAO = new HouseDAO(); + private UserDAO userDAO = new UserDAO(); + + /** + * 添加预约 + */ + 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; + } + + /** + * 查询租客的所有预约 + */ + 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; + } + + /** + * 查询房东收到的预约 + */ + 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查询预约 + */ + 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; + } + + /** + * 更新预约状态(房东确认/取消) + */ + 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; + } + + /** + * 取消预约(租客取消) + */ + 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; + } + + /** + * 统计租客预约数量 + */ + 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; + } + + /** + * 统计房东收到的预约数量 + */ + 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 = ? AND status = '0'"; + 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; + } + + /** + * 将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; + } +} \ No newline at end of file diff --git a/HRS/HRS/src/com/hrs/model/dao/UserDAO.java b/HRS/HRS/src/com/hrs/model/dao/UserDAO.java new file mode 100644 index 0000000..ff6759c --- /dev/null +++ b/HRS/HRS/src/com/hrs/model/dao/UserDAO.java @@ -0,0 +1,399 @@ +package com.hrs.model.dao; + +import com.hrs.model.entity.User; +import com.hrs.util.DBUtil; +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +/** + * 用户数据访问类 + * 负责用户表的增删改查操作 + */ +public class UserDAO { + + /** + * 根据用户名和密码查询用户(登录用) + */ + 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; + } + + /** + * 根据用户名查询用户(检查用户名是否已存在) + */ + 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; + } + + /** + * 根据手机号查询用户(检查手机号是否已注册) + */ + 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; + } + + /** + * 根据ID查询用户 + */ + 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; + } + + /** + * 查询所有租客 + */ + 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; + } + + /** + * 查询所有房东 + */ + 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; + } + + /** + * 添加用户(注册用) + */ + 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; + } + + /** + * 更新用户信息 + */ + 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; + } + + /** + * 更新用户状态(启用/禁用) + */ + 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; + } + + /** + * 删除用户(物理删除,一般不建议) + */ + 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; + } + + /** + * 统计用户总数 + */ + 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; + } + + /** + * 将ResultSet转换为User对象 + */ + 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; + } + + /** + * 测试方法 + */ + public static void main(String[] args) { + UserDAO userDAO = new UserDAO(); + + // 测试1:查询所有租客 + System.out.println("=== 查询所有租客 ==="); + List tenants = userDAO.findAllTenants(); + for (User user : tenants) { + System.out.println(user); + } + + // 测试2:管理员登录测试(admin/e10adc3949ba59abbe56e057f20f883e = 123456的MD5) + System.out.println("\n=== 管理员登录测试 ==="); + User admin = userDAO.findByUsernameAndPassword("admin", "e10adc3949ba59abbe56e057f20f883e"); + if (admin != null) { + System.out.println("登录成功:" + admin); + System.out.println("是否是管理员:" + admin.isAdmin()); + } else { + System.out.println("登录失败"); + } + + // 测试3:房东登录测试 + System.out.println("\n=== 房东登录测试 ==="); + User landlord = userDAO.findByUsernameAndPassword("landlord01", "e10adc3949ba59abbe56e057f20f883e"); + if (landlord != null) { + System.out.println("登录成功:" + landlord); + System.out.println("是否是房东:" + landlord.isLandlord()); + } else { + System.out.println("登录失败"); + } + + // 测试4:统计用户总数 + System.out.println("\n=== 用户总数 ==="); + int count = userDAO.count(); + System.out.println("当前用户总数:" + count); + } +} \ No newline at end of file diff --git a/HRS/HRS/src/com/hrs/model/entity/Collection.java b/HRS/HRS/src/com/hrs/model/entity/Collection.java new file mode 100644 index 0000000..1bab86d --- /dev/null +++ b/HRS/HRS/src/com/hrs/model/entity/Collection.java @@ -0,0 +1,85 @@ +package com.hrs.model.entity; + +import java.util.Date; + +/** + * 收藏实体类 + * 对应数据库表:hrs_collection + */ +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; // 房源详情 + + public Collection() { + } + + public Collection(Long tenantId, Long houseId) { + this.tenantId = tenantId; + this.houseId = houseId; + } + + // Getter 和 Setter + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getTenantId() { + return tenantId; + } + + public void setTenantId(Long tenantId) { + this.tenantId = tenantId; + } + + public Long getHouseId() { + return houseId; + } + + public void setHouseId(Long houseId) { + this.houseId = houseId; + } + + public Date getCollectTime() { + return collectTime; + } + + public void setCollectTime(Date collectTime) { + this.collectTime = collectTime; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public House getHouse() { + return house; + } + + public void setHouse(House house) { + this.house = house; + } +} \ No newline at end of file diff --git a/HRS/HRS/src/com/hrs/model/entity/House.java b/HRS/HRS/src/com/hrs/model/entity/House.java new file mode 100644 index 0000000..5848d6a --- /dev/null +++ b/HRS/HRS/src/com/hrs/model/entity/House.java @@ -0,0 +1,226 @@ +package com.hrs.model.entity; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 房源实体类 + * 对应数据库表:hrs_house + * + * 房源状态:0-待审核;1-已上架;2-已下架;3-违规 + * 租赁类型:0-整租;1-合租 + */ +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; // 房东电话 + + public House() { + } + + // Getter 和 Setter + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getLandlordId() { + return landlordId; + } + + public void setLandlordId(Long landlordId) { + this.landlordId = landlordId; + } + + public String getHouseNo() { + return houseNo; + } + + public void setHouseNo(String houseNo) { + this.houseNo = houseNo; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getArea() { + return area; + } + + public void setArea(String area) { + this.area = area; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getHouseType() { + return houseType; + } + + public void setHouseType(String houseType) { + this.houseType = houseType; + } + + public BigDecimal getRentPrice() { + return rentPrice; + } + + public void setRentPrice(BigDecimal rentPrice) { + this.rentPrice = rentPrice; + } + + public String getRentType() { + return rentType; + } + + public void setRentType(String rentType) { + this.rentType = rentType; + } + + public String getRentTypeText() { + return "0".equals(rentType) ? "整租" : "合租"; + } + + public String getFacility() { + return facility; + } + + public void setFacility(String facility) { + this.facility = facility; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getImgUrl() { + return imgUrl; + } + + public void setImgUrl(String imgUrl) { + this.imgUrl = imgUrl; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getStatusText() { + switch (status) { + case "0": return "待审核"; + case "1": return "已上架"; + case "2": return "已下架"; + case "3": return "违规"; + default: return "未知"; + } + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public String getLandlordName() { + return landlordName; + } + + public void setLandlordName(String landlordName) { + this.landlordName = landlordName; + } + + public String getLandlordPhone() { + return landlordPhone; + } + + public void setLandlordPhone(String landlordPhone) { + this.landlordPhone = landlordPhone; + } + + // 辅助方法:获取第一张图片(用于列表展示) + public String getFirstImage() { + if (imgUrl != null && !imgUrl.isEmpty()) { + String[] images = imgUrl.split(","); + return images[0]; + } + return null; + } + + @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/HRS/src/com/hrs/model/entity/Reservation.java b/HRS/HRS/src/com/hrs/model/entity/Reservation.java new file mode 100644 index 0000000..ea163ce --- /dev/null +++ b/HRS/HRS/src/com/hrs/model/entity/Reservation.java @@ -0,0 +1,174 @@ +package com.hrs.model.entity; + +import java.util.Date; + +/** + * 预约看房实体类 + * 对应数据库表:hrs_reservation + * + * 预约状态:0-待确认;1-已确认;2-已取消;3-已完成 + */ +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; // 房东信息 + + public Reservation() { + } + + // Getter 和 Setter + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getTenantId() { + return tenantId; + } + + public void setTenantId(Long tenantId) { + this.tenantId = tenantId; + } + + public Long getHouseId() { + return houseId; + } + + public void setHouseId(Long houseId) { + this.houseId = houseId; + } + + public Long getLandlordId() { + return landlordId; + } + + public void setLandlordId(Long landlordId) { + this.landlordId = landlordId; + } + + public Date getReserveTime() { + return reserveTime; + } + + public void setReserveTime(Date reserveTime) { + this.reserveTime = reserveTime; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getStatusText() { + switch (status) { + case "0": return "待确认"; + case "1": return "已确认"; + case "2": return "已取消"; + case "3": return "已完成"; + default: return "未知"; + } + } + + public Date getHandleTime() { + return handleTime; + } + + public void setHandleTime(Date handleTime) { + this.handleTime = handleTime; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public House getHouse() { + return house; + } + + public void setHouse(House house) { + this.house = house; + } + + public User getTenant() { + return tenant; + } + + public void setTenant(User tenant) { + this.tenant = tenant; + } + + public User getLandlord() { + return landlord; + } + + public void setLandlord(User landlord) { + this.landlord = landlord; + } + + @Override + public String toString() { + return "Reservation{" + + "id=" + id + + ", houseId=" + houseId + + ", reserveTime=" + reserveTime + + ", status='" + status + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/HRS/HRS/src/com/hrs/model/entity/User.java b/HRS/HRS/src/com/hrs/model/entity/User.java new file mode 100644 index 0000000..bf68ae1 --- /dev/null +++ b/HRS/HRS/src/com/hrs/model/entity/User.java @@ -0,0 +1,186 @@ +package com.hrs.model.entity; + +import java.util.Date; + +/** + * 用户实体类 + * 对应数据库表:hrs_user + * + * 角色类型:0-租客 1-房东 2-管理员 + * 账号状态:0-未认证 1-已认证 2-禁用 + */ +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; // 更新时间 + + // 无参构造方法 + public User() { + } + + // 全参构造方法 + 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; + } + + // Getter 和 Setter 方法 + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getRealName() { + return realName; + } + + public void setRealName(String realName) { + this.realName = realName; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getIdCard() { + return idCard; + } + + public void setIdCard(String idCard) { + this.idCard = idCard; + } + + public String getRoleType() { + return roleType; + } + + public void setRoleType(String roleType) { + this.roleType = roleType; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + /** + * 辅助方法:判断是否为租客 + */ + public boolean isTenant() { + return "0".equals(this.roleType); + } + + /** + * 辅助方法:判断是否为房东 + */ + public boolean isLandlord() { + return "1".equals(this.roleType); + } + + /** + * 辅助方法:判断是否为管理员 + */ + public boolean isAdmin() { + return "2".equals(this.roleType); + } + + /** + * 辅助方法:判断账号是否已认证 + */ + public boolean isVerified() { + return "1".equals(this.status); + } + + @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/HRS/src/com/hrs/util/DBUtil.java b/HRS/HRS/src/com/hrs/util/DBUtil.java new file mode 100644 index 0000000..c0399b7 --- /dev/null +++ b/HRS/HRS/src/com/hrs/util/DBUtil.java @@ -0,0 +1,91 @@ +package com.hrs.util; + +import java.sql.*; + +/** + * 数据库连接工具类 - 土办法版 + * 只要jar包在WEB-INF/lib里就能用 + */ +public class DBUtil { + + // 数据库配置(改成你的) + private static final String URL = "jdbc:mysql://localhost:3306/hrs?useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai"; + private static final String USERNAME = "root"; // 你的MySQL用户名 + private static final String PASSWORD = "root"; // 你的MySQL密码 + + // 驱动类名 + private static final String DRIVER = "com.mysql.jdbc.Driver"; + + /** + * 静态代码块:加载驱动 + */ + static { + try { + Class.forName(DRIVER); + System.out.println("✅ MySQL驱动加载成功!"); + } catch (ClassNotFoundException e) { + System.out.println("❌ MySQL驱动加载失败!"); + System.out.println("请检查:WEB-INF/lib 下是否有 mysql-connector-java-5.1.49.jar"); + e.printStackTrace(); + } + } + + /** + * 获取数据库连接 + */ + public static Connection getConnection() throws SQLException { + return DriverManager.getConnection(URL, USERNAME, PASSWORD); + } + + /** + * 关闭连接(查询用) + */ + public static void close(ResultSet rs, PreparedStatement pstmt, Connection conn) { + if (rs != null) { + try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } + } + close(pstmt, conn); + } + + /** + * 关闭连接(增删改用) + */ + 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(); } + } + } + + /** + * 测试方法 + */ + public static void main(String[] args) { + Connection conn = null; + try { + // 1. 获取连接 + conn = DBUtil.getConnection(); + System.out.println("✅ 数据库连接成功!"); + System.out.println("连接对象:" + conn); + + // 2. 简单测试查询 + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM hrs_user"); + if (rs.next()) { + int count = rs.getInt(1); + System.out.println("✅ 用户表中共有 " + count + " 条记录"); + } + rs.close(); + stmt.close(); + + } catch (SQLException e) { + System.out.println("❌ 数据库连接失败!"); + System.out.println("错误信息:" + e.getMessage()); + e.printStackTrace(); + } finally { + close(null, null, conn); + } + } +} \ No newline at end of file diff --git a/HRS/HRS/src/com/hrs/util/MD5Util.java b/HRS/HRS/src/com/hrs/util/MD5Util.java new file mode 100644 index 0000000..0ce86f8 --- /dev/null +++ b/HRS/HRS/src/com/hrs/util/MD5Util.java @@ -0,0 +1,80 @@ +package com.hrs.util; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * MD5加密工具类 + * 用于密码加密 + */ +public class MD5Util { + + /** + * 将字符串进行MD5加密 + * @param str 要加密的字符串 + * @return MD5加密后的32位小写字符串 + */ + 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; + } + } + + /** + * 将0-15的数字转换为十六进制字符 + */ + private static char hexChar(int value) { + if (value >= 0 && value <= 9) { + return (char) ('0' + value); + } else { + return (char) ('a' + (value - 10)); + } + } + + /** + * 验证密码是否匹配 + * @param inputPassword 用户输入的明文密码 + * @param storedPassword 数据库中存储的MD5密码 + * @return 是否匹配 + */ + public static boolean verify(String inputPassword, String storedPassword) { + String encrypted = md5(inputPassword); + return encrypted != null && encrypted.equals(storedPassword); + } + + /** + * 测试方法 + */ + 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 diff --git a/HRS/WebContent/META-INF/MANIFEST.MF b/HRS/WebContent/META-INF/MANIFEST.MF new file mode 100644 index 0000000..254272e --- /dev/null +++ b/HRS/WebContent/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/HRS/WebContent/WEB-INF/lib/mysql-connector-java-5.1.49.jar b/HRS/WebContent/WEB-INF/lib/mysql-connector-java-5.1.49.jar new file mode 100644 index 0000000..0b6e2a6 Binary files /dev/null and b/HRS/WebContent/WEB-INF/lib/mysql-connector-java-5.1.49.jar differ diff --git a/HRS/WebContent/WEB-INF/web.xml b/HRS/WebContent/WEB-INF/web.xml new file mode 100644 index 0000000..f3419fc --- /dev/null +++ b/HRS/WebContent/WEB-INF/web.xml @@ -0,0 +1,29 @@ + + + + HRS + + + + index.jsp + + + + + encodingFilter + com.hrs.filter.EncodingFilter + + encoding + UTF-8 + + + + encodingFilter + /* + + + \ No newline at end of file diff --git a/HRS/WebContent/jsp/admin/index.jsp b/HRS/WebContent/jsp/admin/index.jsp new file mode 100644 index 0000000..147acf8 --- /dev/null +++ b/HRS/WebContent/jsp/admin/index.jsp @@ -0,0 +1,20 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="com.hrs.model.entity.User" %> +<% + User loginUser = (User)session.getAttribute("loginUser"); + if(loginUser == null || !"2".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } +%> + + + + + 管理员首页 + + +

欢迎管理员:<%= loginUser.getRealName() %>

+ 退出登录 + + \ No newline at end of file diff --git a/HRS/WebContent/jsp/landlord/index.jsp b/HRS/WebContent/jsp/landlord/index.jsp new file mode 100644 index 0000000..2351d47 --- /dev/null +++ b/HRS/WebContent/jsp/landlord/index.jsp @@ -0,0 +1,20 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="com.hrs.model.entity.User" %> +<% + User loginUser = (User)session.getAttribute("loginUser"); + if(loginUser == null || !"1".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } +%> + + + + + 房东首页 + + +

欢迎房东:<%= loginUser.getRealName() %>

+ 退出登录 + + \ No newline at end of file diff --git a/HRS/WebContent/jsp/landlord/reservation_list.jsp b/HRS/WebContent/jsp/landlord/reservation_list.jsp new file mode 100644 index 0000000..e099acf --- /dev/null +++ b/HRS/WebContent/jsp/landlord/reservation_list.jsp @@ -0,0 +1,324 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="java.util.List, java.text.SimpleDateFormat, com.hrs.model.entity.Reservation, com.hrs.model.entity.House, com.hrs.model.entity.User" %> +<% + User loginUser = (User) session.getAttribute("loginUser"); + if (loginUser == null || !"1".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } + + List reservationList = (List) request.getAttribute("reservationList"); + Integer totalCount = (Integer) request.getAttribute("totalCount"); + String msg = request.getParameter("msg"); + String error = request.getParameter("error"); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); +%> + + + + + 预约管理 - 房东后台 + + + +
+
+ + + +
+
+ +
+ + + <% if (msg != null) { %> +
<%= msg %>
+ <% } %> + <% if (error != null) { %> +
<%= error %>
+ <% } %> + +
+ 📋 共有 <%= totalCount %> 条预约记录 +
+ +
+ <% + if (reservationList != null && !reservationList.isEmpty()) { + %> + + + + + + + + + + + + + <% + for (Reservation reservation : reservationList) { + House house = reservation.getHouse(); + User tenant = reservation.getTenant(); + %> + + + + + + + + + <% + } + %> + +
租客信息房源信息预约时间状态备注操作
+ <%= tenant.getRealName() != null ? tenant.getRealName() : tenant.getUserName() %>
+ <%= tenant.getPhone() %> +
+ <%= house.getTitle() %>
+ <%= house.getArea() %> +
<%= sdf.format(reservation.getReserveTime()) %> + "> + <%= reservation.getStatusText() %> + + + <%= reservation.getRemark() != null ? reservation.getRemark() : "-" %> + + <% if ("0".equals(reservation.getStatus())) { %> + 确认 + 拒绝 + <% } else { %> + 已处理 + <% } %> +
+ <% + } else { + %> +
+
📅
+

暂无预约记录

+
+ <% + } + %> +
+
+ + + + \ No newline at end of file diff --git a/HRS/WebContent/jsp/user/collection_list.jsp b/HRS/WebContent/jsp/user/collection_list.jsp new file mode 100644 index 0000000..3adf659 --- /dev/null +++ b/HRS/WebContent/jsp/user/collection_list.jsp @@ -0,0 +1,418 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="java.util.List, com.hrs.model.entity.Collection, com.hrs.model.entity.House, com.hrs.model.entity.User" %> +<% + User loginUser = (User) session.getAttribute("loginUser"); + if (loginUser == null || !"0".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } + + List collectionList = (List) request.getAttribute("collectionList"); + Integer totalCount = (Integer) request.getAttribute("totalCount"); + String msg = request.getParameter("msg"); + String error = request.getParameter("error"); +%> + + + + + 我的收藏 - 租房系统 + + + +
+
+ + + +
+
+ +
+ + + <% if (msg != null) { %> +
<%= msg %>
+ <% } %> + <% if (error != null) { %> +
<%= error %>
+ <% } %> + +
+ 📚 共收藏 <%= totalCount %> 套房源 +
+ +
+ <% + if (collectionList != null && !collectionList.isEmpty()) { + for (Collection collection : collectionList) { + House house = collection.getHouse(); + if (house != null) { + %> +
+
');"> + <% if (house.getFirstImage() == null) { %> +
🏠 暂无图片
+ <% } %> +
+ +
+ +
+ 📍 <%= house.getArea() %> | <%= house.getHouseType() %> | <%= house.getRentTypeText() %> +
+
+ ¥<%= house.getRentPrice() %>/月 +
+
+ 收藏时间:<%= collection.getCollectTime() %> +
+
+
+ <% + } + } + } else { + %> +
+
❤️
+

还没有收藏任何房源

+

去浏览房源 >>

+
+ <% + } + %> +
+
+ + + + + + \ No newline at end of file diff --git a/HRS/WebContent/jsp/user/house_detail.jsp b/HRS/WebContent/jsp/user/house_detail.jsp new file mode 100644 index 0000000..6b6be5b --- /dev/null +++ b/HRS/WebContent/jsp/user/house_detail.jsp @@ -0,0 +1,597 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="com.hrs.model.entity.House, com.hrs.model.entity.User" %> +<% + User loginUser = (User) session.getAttribute("loginUser"); + if (loginUser == null || !"0".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } + + House house = (House) request.getAttribute("house"); + if (house == null) { + response.sendRedirect(request.getContextPath() + "/user/house/list"); + return; + } +%> + + + + + <%= house.getTitle() %> - 租房系统 + + + + +
+
+ + + +
+
+ +
+ + + +
+ +
+
');"> + <% if (house.getFirstImage() == null) { %> +
🏠 暂无图片
+ <% } %> +
+
+ <% + String[] images = null; + if (house.getImgUrl() != null && !house.getImgUrl().isEmpty()) { + images = house.getImgUrl().split(","); + for (int i = 0; i < images.length; i++) { + %> +
+ <% + } + } + %> +
+
+ + +
+
<%= house.getTitle() %>
+ +
+ ¥<%= house.getRentPrice() %>/月 +
+ +
+
+
户型
+
<%= house.getHouseType() != null ? house.getHouseType() : "待定" %>
+
+
+
面积
+
<%= house.getArea() != null ? house.getArea() : "待定" %>
+
+
+
租赁类型
+
<%= house.getRentTypeText() %>
+
+
+
房源编号
+
<%= house.getHouseNo() %>
+
+
+ +
+
📍 房源地址
+

<%= house.getAddress() != null ? house.getAddress() : "暂无地址信息" %>

+
+ +
+
🛋️ 配套设施
+
+ <% + String facility = house.getFacility(); + if (facility != null && !facility.isEmpty()) { + String[] facilities = facility.split(","); + for (String f : facilities) { + %> + <%= f.trim() %> + <% + } + } else { + %> + 暂无设施信息 + <% + } + %> +
+
+ +
+
📝 房源描述
+
+ <%= house.getDescription() != null ? house.getDescription() : "暂无描述信息" %> +
+
+
+
+ + +
+
👤 房东信息
+
+
👨
+
+

<%= house.getLandlordName() != null ? house.getLandlordName() : "房东" %>

+

📞 <%= house.getLandlordPhone() != null ? house.getLandlordPhone() : "暂无联系方式" %>

+

⭐ 认证房东 · 已发布房源

+
+
+
+ + +
+ + <% + // 检查是否已收藏 + com.hrs.model.dao.CollectionDAO collectionDAO = new com.hrs.model.dao.CollectionDAO(); + boolean isCollected = collectionDAO.isCollected(loginUser.getId(), house.getId()); + if (isCollected) { + %> + + <% + } else { + %> + + <% + } + %> + 🔙 返回列表 +
+
+ + + + + + + \ No newline at end of file diff --git a/HRS/WebContent/jsp/user/house_list.jsp b/HRS/WebContent/jsp/user/house_list.jsp new file mode 100644 index 0000000..c5e1043 --- /dev/null +++ b/HRS/WebContent/jsp/user/house_list.jsp @@ -0,0 +1,412 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="java.util.List, com.hrs.model.entity.House, com.hrs.model.entity.User" %> +<% + User loginUser = (User) session.getAttribute("loginUser"); + if (loginUser == null || !"0".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } + + List houseList = (List) request.getAttribute("houseList"); + Integer totalCount = (Integer) request.getAttribute("totalCount"); +%> + + + + + 房源列表 - 租房系统 + + + + +
+
+ + + +
+
+ + + + +
+ +
+ 📊 共找到 <%= totalCount %> 套房源 +
+ + +
+ <% + if (houseList != null && !houseList.isEmpty()) { + for (House house : houseList) { + %> +
+
');"> + <% if (house.getFirstImage() == null) { %> +
🏠 暂无图片
+ <% } %> +
+
+ +
+ 📍 <%= house.getArea() %> | <%= house.getHouseType() %> | <%= house.getRentTypeText() %> +
+
+ ¥<%= house.getRentPrice() %>/月 +
+
+ #<%= house.getHouseType() %> + #<%= house.getArea() %> +
+ +
+
+ <% + } + } else { + %> +
+
🏠
+

暂无房源,请稍后再来

+
+ <% + } + %> +
+
+ + + + + \ No newline at end of file diff --git a/HRS/WebContent/jsp/user/index.jsp b/HRS/WebContent/jsp/user/index.jsp new file mode 100644 index 0000000..67c74d8 --- /dev/null +++ b/HRS/WebContent/jsp/user/index.jsp @@ -0,0 +1,5 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<% + // 重定向到房源列表页 + response.sendRedirect(request.getContextPath() + "/user/house/list"); +%> \ No newline at end of file diff --git a/HRS/WebContent/jsp/user/login.jsp b/HRS/WebContent/jsp/user/login.jsp new file mode 100644 index 0000000..068c479 --- /dev/null +++ b/HRS/WebContent/jsp/user/login.jsp @@ -0,0 +1,151 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + + + + + 租房系统登录 + + + + + + \ No newline at end of file diff --git a/HRS/WebContent/jsp/user/register.jsp b/HRS/WebContent/jsp/user/register.jsp new file mode 100644 index 0000000..0421653 --- /dev/null +++ b/HRS/WebContent/jsp/user/register.jsp @@ -0,0 +1,218 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> + + + + + 租房系统注册 + + + +
+

租房系统注册

+ + <%-- 显示错误信息 --%> + <% + String error = (String)request.getAttribute("error"); + if(error != null) { + %> +
<%= error %>
+ <% + } + %> + + <%-- 显示成功信息 --%> + <% + String message = (String)request.getAttribute("message"); + if(message != null) { + %> +
<%= message %>
+ <% + } + %> + +
+
+ + +
+ +
+ + +
密码长度6-20位,建议使用字母+数字组合
+
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
房东认证需要提供身份证号
+
+ +
+ +
+ + +
+
房东需要管理员审核认证后才能发布房源
+
+ + +
+ + +
+ + + + \ No newline at end of file diff --git a/HRS/WebContent/jsp/user/reservation_add.jsp b/HRS/WebContent/jsp/user/reservation_add.jsp new file mode 100644 index 0000000..8fa4252 --- /dev/null +++ b/HRS/WebContent/jsp/user/reservation_add.jsp @@ -0,0 +1,313 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="com.hrs.model.entity.House, com.hrs.model.entity.User" %> +<% + User loginUser = (User) session.getAttribute("loginUser"); + if (loginUser == null || !"0".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } + + House house = (House) request.getAttribute("house"); + if (house == null) { + response.sendRedirect(request.getContextPath() + "/user/house/list"); + return; + } + + String error = (String) request.getAttribute("error"); +%> + + + + + 预约看房 - 租房系统 + + + +
+
+ + + +
+
+ +
+ + +
+

📅 预约看房

+ + <% if (error != null) { %> +
<%= error %>
+ <% } %> + + +
+
');"> + <% if (house.getFirstImage() == null) { %> +
🏠
+ <% } %> +
+
+
<%= house.getTitle() %>
+
📍 <%= house.getArea() %> | <%= house.getHouseType() %> | <%= house.getRentTypeText() %>
+
¥<%= house.getRentPrice() %>/月
+
+
+ +
+ + +
+ + "> +
请选择您方便的看房日期
+
+ +
+ + +
建议选择 9:00-18:00 之间的时间
+
+ +
+ + +
+ +
+ + 返回 +
+
+
+
+ + + + + + \ No newline at end of file diff --git a/HRS/WebContent/jsp/user/reservation_list.jsp b/HRS/WebContent/jsp/user/reservation_list.jsp new file mode 100644 index 0000000..a42c9d5 --- /dev/null +++ b/HRS/WebContent/jsp/user/reservation_list.jsp @@ -0,0 +1,347 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="java.util.List, java.text.SimpleDateFormat, com.hrs.model.entity.Reservation, com.hrs.model.entity.House, com.hrs.model.entity.User" %> +<% + User loginUser = (User) session.getAttribute("loginUser"); + if (loginUser == null || !"0".equals(loginUser.getRoleType())) { + response.sendRedirect(request.getContextPath() + "/user/login"); + return; + } + + List reservationList = (List) request.getAttribute("reservationList"); + Integer totalCount = (Integer) request.getAttribute("totalCount"); + String msg = request.getParameter("msg"); + String error = request.getParameter("error"); + + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm"); +%> + + + + + 我的预约 - 租房系统 + + + +
+
+ + + +
+
+ +
+ + + <% if (msg != null) { %> +
<%= msg %>
+ <% } %> + <% if (error != null) { %> +
<%= error %>
+ <% } %> + +
+ 📋 共有 <%= totalCount %> 条预约记录 +
+ +
+ <% + if (reservationList != null && !reservationList.isEmpty()) { + %> + + + + + + + + + + + + <% + for (Reservation reservation : reservationList) { + House house = reservation.getHouse(); + %> + + + + + + + + <% + } + %> + +
房源信息预约时间状态备注操作
+ + <%= house.getTitle() %> +
+ <%= house.getArea() %> | ¥<%= house.getRentPrice() %>/月 +
<%= sdf.format(reservation.getReserveTime()) %> + "> + <%= reservation.getStatusText() %> + + + <%= reservation.getRemark() != null ? reservation.getRemark() : "-" %> + + <% if ("0".equals(reservation.getStatus())) { %> + 取消 + <% } else { %> + 已处理 + <% } %> +
+ <% + } else { + %> +
+
📅
+

还没有任何预约记录

+

去浏览房源 >>

+
+ <% + } + %> +
+
+ + + + \ No newline at end of file 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..7669648 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..f905516 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..0c19cd3 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..f432e95 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..3e10dc1 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..946e166 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..b925e26 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..d610f8c 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..e077aa5 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/RegisterController.class b/HRS/build/classes/com/hrs/controller/user/RegisterController.class new file mode 100644 index 0000000..eb9d7ac 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..2e18798 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..d432545 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..e2ae5eb Binary files /dev/null and b/HRS/build/classes/com/hrs/controller/user/ReservationListController.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..b4eeb4c 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..37f063f Binary files /dev/null and b/HRS/build/classes/com/hrs/filter/LoginFilter.class differ diff --git a/HRS/build/classes/com/hrs/model/dao/CollectionDAO.class b/HRS/build/classes/com/hrs/model/dao/CollectionDAO.class new file mode 100644 index 0000000..ecaaf73 Binary files /dev/null and b/HRS/build/classes/com/hrs/model/dao/CollectionDAO.class differ diff --git a/HRS/build/classes/com/hrs/model/dao/HouseDAO.class b/HRS/build/classes/com/hrs/model/dao/HouseDAO.class new file mode 100644 index 0000000..00d5728 Binary files /dev/null and b/HRS/build/classes/com/hrs/model/dao/HouseDAO.class differ diff --git a/HRS/build/classes/com/hrs/model/dao/ReservationDAO.class b/HRS/build/classes/com/hrs/model/dao/ReservationDAO.class new file mode 100644 index 0000000..72ce4af Binary files /dev/null and b/HRS/build/classes/com/hrs/model/dao/ReservationDAO.class differ diff --git a/HRS/build/classes/com/hrs/model/dao/UserDAO.class b/HRS/build/classes/com/hrs/model/dao/UserDAO.class new file mode 100644 index 0000000..4dbca1e Binary files /dev/null and b/HRS/build/classes/com/hrs/model/dao/UserDAO.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..3e1e1ae 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..fa98b27 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/Reservation.class b/HRS/build/classes/com/hrs/model/entity/Reservation.class new file mode 100644 index 0000000..d61d630 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..6767596 Binary files /dev/null and b/HRS/build/classes/com/hrs/model/entity/User.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..6fa843c Binary files /dev/null and b/HRS/build/classes/com/hrs/util/DBUtil.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..d58b17f 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/landlord/ReservationHandleController.java b/HRS/src/com/hrs/controller/landlord/ReservationHandleController.java new file mode 100644 index 0000000..4d5fe14 --- /dev/null +++ b/HRS/src/com/hrs/controller/landlord/ReservationHandleController.java @@ -0,0 +1,60 @@ +package com.hrs.controller.landlord; + +import com.hrs.model.dao.ReservationDAO; +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; + +/** + * 房东处理预约控制器 + */ +@WebServlet("/landlord/reservation/handle") +public class ReservationHandleController extends HttpServlet { + + private ReservationDAO reservationDAO = new ReservationDAO(); + + @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) { + response.sendRedirect(request.getContextPath() + "/landlord/reservation/list?msg=" + + ("confirm".equals(action) ? "已确认预约" : "已拒绝预约")); + } else { + response.sendRedirect(request.getContextPath() + "/landlord/reservation/list?error=操作失败"); + } + } +} \ 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..4b5147c --- /dev/null +++ b/HRS/src/com/hrs/controller/landlord/ReservationManageController.java @@ -0,0 +1,50 @@ +package com.hrs.controller.landlord; + +import com.hrs.model.dao.ReservationDAO; +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; + +/** + * 房东预约管理控制器 + */ +@WebServlet("/landlord/reservation/list") +public class ReservationManageController extends HttpServlet { + + private ReservationDAO reservationDAO = new ReservationDAO(); + + @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..97dfab7 --- /dev/null +++ b/HRS/src/com/hrs/controller/user/CollectionAddController.java @@ -0,0 +1,79 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.CollectionDAO; +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; + +/** + * 添加收藏控制器 + * AJAX请求,返回文本结果 + */ +@WebServlet("/user/collection/add") +public class CollectionAddController extends HttpServlet { + + private CollectionDAO collectionDAO = new CollectionDAO(); + + @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; + } + + // 3. 检查是否已收藏 + boolean exists = collectionDAO.isCollected(loginUser.getId(), houseId); + if (exists) { + out.print("exists"); + return; + } + + // 4. 添加收藏 + com.hrs.model.entity.Collection collection = new com.hrs.model.entity.Collection(); + collection.setTenantId(loginUser.getId()); + collection.setHouseId(houseId); + + boolean success = collectionDAO.add(collection); + + if (success) { + 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..56a20b1 --- /dev/null +++ b/HRS/src/com/hrs/controller/user/CollectionDeleteController.java @@ -0,0 +1,111 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.CollectionDAO; +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; + +/** + * 取消收藏控制器 + * 支持两种删除方式: + * 1. AJAX删除(收藏列表页)- 返回JSON + * 2. 页面跳转删除(详情页)- 重定向 + */ +@WebServlet("/user/collection/delete") +public class CollectionDeleteController extends HttpServlet { + + private CollectionDAO collectionDAO = new CollectionDAO(); + + @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) { + // 从详情页删除,跳回详情页 + response.sendRedirect(request.getContextPath() + "/user/house/detail?id=" + houseIdStr + "&msg=取消收藏成功"); + } else if ("list".equals(from)) { + // 从收藏列表删除,跳回收藏列表 + response.sendRedirect(request.getContextPath() + "/user/collection/list?msg=取消收藏成功"); + } else { + // 默认跳回收藏列表 + response.sendRedirect(request.getContextPath() + "/user/collection/list?msg=取消收藏成功"); + } + } else { + if ("detail".equals(from) && houseIdStr != null) { + response.sendRedirect(request.getContextPath() + "/user/house/detail?id=" + houseIdStr + "&error=取消收藏失败"); + } else { + response.sendRedirect(request.getContextPath() + "/user/collection/list?error=取消收藏失败"); + } + } + } + } +} \ 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..c1db6df --- /dev/null +++ b/HRS/src/com/hrs/controller/user/CollectionListController.java @@ -0,0 +1,52 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.CollectionDAO; +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; + +/** + * 我的收藏列表控制器 + */ +@WebServlet("/user/collection/list") +public class CollectionListController extends HttpServlet { + + private CollectionDAO collectionDAO = new CollectionDAO(); + + @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..66de6c5 --- /dev/null +++ b/HRS/src/com/hrs/controller/user/HouseDetailController.java @@ -0,0 +1,62 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.HouseDAO; +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; + +/** + * 房源详情控制器 + * 租客端查看房源详情 + * URL映射:/user/house/detail + */ +@WebServlet("/user/house/detail") +public class HouseDetailController extends HttpServlet { + + private HouseDAO houseDAO = new HouseDAO(); + + @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..a444317 --- /dev/null +++ b/HRS/src/com/hrs/controller/user/HouseListController.java @@ -0,0 +1,63 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.HouseDAO; +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; + +/** + * 房源列表控制器 + * 租客端查看房源列表 + * URL映射:/user/house/list + */ +@WebServlet("/user/house/list") +public class HouseListController extends HttpServlet { + + private HouseDAO houseDAO = new HouseDAO(); + + @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..053fea6 --- /dev/null +++ b/HRS/src/com/hrs/controller/user/LoginController.java @@ -0,0 +1,106 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.UserDAO; +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; + +/** + * 登录控制器 + * 处理用户登录请求 + * URL映射:/user/login + */ +@WebServlet("/user/login") +public class LoginController extends HttpServlet { + + private UserDAO userDAO = new UserDAO(); + + @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. 调用DAO查询用户 + User user = userDAO.findByUsernameAndPassword(username, encryptedPassword); + + // 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..95156f9 --- /dev/null +++ b/HRS/src/com/hrs/controller/user/LogoutController.java @@ -0,0 +1,38 @@ +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; + +/** + * 退出登录控制器 + */ +@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/RegisterController.java b/HRS/src/com/hrs/controller/user/RegisterController.java new file mode 100644 index 0000000..b541454 --- /dev/null +++ b/HRS/src/com/hrs/controller/user/RegisterController.java @@ -0,0 +1,120 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.UserDAO; +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 java.io.IOException; + +/** + * 注册控制器 + * 处理用户注册请求 + * URL映射:/user/register + */ +@WebServlet("/user/register") +public class RegisterController extends HttpServlet { + + private UserDAO userDAO = new UserDAO(); + + @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. 基础验证 + if (username == null || username.trim().isEmpty()) { + request.setAttribute("error", "用户名不能为空"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + return; + } + + if (password == null || password.trim().isEmpty()) { + request.setAttribute("error", "密码不能为空"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + return; + } + + // 3. 验证两次密码是否一致 + if (!password.equals(confirmPassword)) { + request.setAttribute("error", "两次输入的密码不一致"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + return; + } + + // 4. 验证手机号格式(简单验证) + if (phone == null || phone.trim().isEmpty() || !phone.matches("^1[3-9]\\d{9}$")) { + request.setAttribute("error", "手机号格式不正确"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + return; + } + + // 5. 检查用户名是否已存在 + User existUser = userDAO.findByUsername(username); + if (existUser != null) { + request.setAttribute("error", "用户名已存在,请换一个"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + return; + } + + // 6. 检查手机号是否已注册 + User existPhone = userDAO.findByPhone(phone); + if (existPhone != null) { + request.setAttribute("error", "手机号已注册"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + return; + } + + // 7. 创建用户对象 + User user = new User(); + user.setUserName(username); + user.setPassword(MD5Util.md5(password)); // 密码MD5加密 + user.setRealName(realName); + user.setPhone(phone); + user.setIdCard(idCard); + user.setRoleType(roleType); // 0-租客 1-房东 + user.setStatus("0"); // 默认未认证状态 + + // 8. 保存到数据库 + boolean success = userDAO.add(user); + + if (success) { + // 注册成功,跳转到登录页面 + request.setAttribute("message", "注册成功,请登录"); + request.getRequestDispatcher("/jsp/user/login.jsp").forward(request, response); + } else { + // 注册失败 + request.setAttribute("error", "注册失败,请稍后重试"); + request.getRequestDispatcher("/jsp/user/register.jsp").forward(request, response); + } + if (success) { + // 注册成功,跳转到登录页面,并带上成功消息 + response.sendRedirect(request.getContextPath() + "/user/login?message=注册成功,请登录"); + } else { + // 注册失败 + request.setAttribute("error", "注册失败,请稍后重试"); + 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..c04be9d --- /dev/null +++ b/HRS/src/com/hrs/controller/user/ReservationAddController.java @@ -0,0 +1,135 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.HouseDAO; +import com.hrs.model.dao.ReservationDAO; +import com.hrs.model.entity.House; +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.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * 添加预约控制器 + */ +@WebServlet("/user/reservation/add") +public class ReservationAddController extends HttpServlet { + + private ReservationDAO reservationDAO = new ReservationDAO(); + private HouseDAO houseDAO = new HouseDAO(); + + @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) { + response.sendRedirect(request.getContextPath() + "/user/house/list"); + 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); + } + + @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 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; + } + + Long houseId = Long.parseLong(houseIdStr); + House house = houseDAO.findById(houseId); + + if (house == null) { + request.setAttribute("error", "房源不存在"); + doGet(request, response); + return; + } + + // 组合预约时间 + String datetimeStr = reserveDate + " " + reserveTime + ":00"; + SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + Date reserveDateTime; + try { + reserveDateTime = sdf.parse(datetimeStr); + } catch (ParseException e) { + request.setAttribute("error", "时间格式错误"); + doGet(request, response); + return; + } + + // 检查预约时间是否在今天之后 + if (reserveDateTime.before(new Date())) { + request.setAttribute("error", "预约时间不能早于当前时间"); + doGet(request, response); + 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); + + if (success) { + response.sendRedirect(request.getContextPath() + "/user/reservation/list?msg=预约成功,请等待房东确认"); + } else { + request.setAttribute("error", "预约失败,请稍后重试"); + 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..6fb496f --- /dev/null +++ b/HRS/src/com/hrs/controller/user/ReservationCancelController.java @@ -0,0 +1,57 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.ReservationDAO; +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; + +/** + * 取消预约控制器(租客端) + */ +@WebServlet("/user/reservation/cancel") +public class ReservationCancelController extends HttpServlet { + + private ReservationDAO reservationDAO = new ReservationDAO(); + + @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; + } + + // 获取预约ID + String idStr = request.getParameter("id"); + if (idStr == null || idStr.trim().isEmpty()) { + response.sendRedirect(request.getContextPath() + "/user/reservation/list"); + return; + } + + Long id = Long.parseLong(idStr); + + // 取消预约 + boolean success = reservationDAO.cancel(id, loginUser.getId()); + + if (success) { + response.sendRedirect(request.getContextPath() + "/user/reservation/list?msg=取消预约成功"); + } else { + response.sendRedirect(request.getContextPath() + "/user/reservation/list?error=取消预约失败"); + } + } +} \ 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..2b3abfb --- /dev/null +++ b/HRS/src/com/hrs/controller/user/ReservationListController.java @@ -0,0 +1,50 @@ +package com.hrs.controller.user; + +import com.hrs.model.dao.ReservationDAO; +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; + +/** + * 我的预约列表控制器(租客端) + */ +@WebServlet("/user/reservation/list") +public class ReservationListController extends HttpServlet { + + private ReservationDAO reservationDAO = new ReservationDAO(); + + @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/filter/EncodingFilter.java b/HRS/src/com/hrs/filter/EncodingFilter.java new file mode 100644 index 0000000..e2f2ce1 --- /dev/null +++ b/HRS/src/com/hrs/filter/EncodingFilter.java @@ -0,0 +1,37 @@ +package com.hrs.filter; + +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import java.io.IOException; + +/** + * 字符编码过滤器 + */ +@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..0b28035 --- /dev/null +++ b/HRS/src/com/hrs/filter/LoginFilter.java @@ -0,0 +1,93 @@ +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; + +/** + * 登录过滤器 + * 拦截未登录的请求 + */ +@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/dao/CollectionDAO.java b/HRS/src/com/hrs/model/dao/CollectionDAO.java new file mode 100644 index 0000000..8b6b000 --- /dev/null +++ b/HRS/src/com/hrs/model/dao/CollectionDAO.java @@ -0,0 +1,204 @@ +package com.hrs.model.dao; + +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; + +/** + * 收藏数据访问类 + */ +public class CollectionDAO { + + private HouseDAO houseDAO = new HouseDAO(); + + /** + * 添加收藏 + */ + 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; + } + + /** + * 检查是否已收藏 + */ + 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; + } + + /** + * 取消收藏 + */ + 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删除 + */ + 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; + } + + /** + * 查询租客的所有收藏 + */ + 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; + } + + /** + * 查询租客的收藏数量 + */ + 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; + } +} \ No newline at end of file diff --git a/HRS/src/com/hrs/model/dao/HouseDAO.java b/HRS/src/com/hrs/model/dao/HouseDAO.java new file mode 100644 index 0000000..cb20c14 --- /dev/null +++ b/HRS/src/com/hrs/model/dao/HouseDAO.java @@ -0,0 +1,397 @@ +package com.hrs.model.dao; + +import com.hrs.model.entity.House; +import com.hrs.util.DBUtil; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +/** + * 房源数据访问类 + * 负责房源表的增删改查操作 + */ +public class HouseDAO { + + /** + * 查询已上架的房源(供租客查看) + */ + 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; + } + + /** + * 根据区域筛选房源 + */ + 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; + } + + /** + * 根据价格区间筛选房源 + */ + 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查询详情 + */ + 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; + } + + /** + * 查询房东自己的房源 + */ + 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; + } + + /** + * 查询所有房源(管理员用) + */ + 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; + } + + /** + * 添加房源 + */ + 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; + } + + /** + * 更新房源 + */ + 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; + } + + /** + * 更新房源状态(审核/上架/下架) + */ + 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; + } + + /** + * 删除房源 + */ + 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; + } + + /** + * 统计已上架房源数量 + */ + 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; + } + + /** + * 将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; + } +} \ No newline at end of file diff --git a/HRS/src/com/hrs/model/dao/ReservationDAO.java b/HRS/src/com/hrs/model/dao/ReservationDAO.java new file mode 100644 index 0000000..df01f51 --- /dev/null +++ b/HRS/src/com/hrs/model/dao/ReservationDAO.java @@ -0,0 +1,286 @@ +package com.hrs.model.dao; + +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; + +/** + * 预约看房数据访问类 + */ +public class ReservationDAO { + + private HouseDAO houseDAO = new HouseDAO(); + private UserDAO userDAO = new UserDAO(); + + /** + * 添加预约 + */ + 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; + } + + /** + * 查询租客的所有预约 + */ + 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; + } + + /** + * 查询房东收到的预约 + */ + 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查询预约 + */ + 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; + } + + /** + * 更新预约状态(房东确认/取消) + */ + 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; + } + + /** + * 取消预约(租客取消) + */ + 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; + } + + /** + * 统计租客预约数量 + */ + 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; + } + + /** + * 统计房东收到的预约数量 + */ + 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 = ? AND status = '0'"; + 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; + } + + /** + * 将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; + } +} \ No newline at end of file diff --git a/HRS/src/com/hrs/model/dao/UserDAO.java b/HRS/src/com/hrs/model/dao/UserDAO.java new file mode 100644 index 0000000..ff6759c --- /dev/null +++ b/HRS/src/com/hrs/model/dao/UserDAO.java @@ -0,0 +1,399 @@ +package com.hrs.model.dao; + +import com.hrs.model.entity.User; +import com.hrs.util.DBUtil; +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +/** + * 用户数据访问类 + * 负责用户表的增删改查操作 + */ +public class UserDAO { + + /** + * 根据用户名和密码查询用户(登录用) + */ + 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; + } + + /** + * 根据用户名查询用户(检查用户名是否已存在) + */ + 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; + } + + /** + * 根据手机号查询用户(检查手机号是否已注册) + */ + 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; + } + + /** + * 根据ID查询用户 + */ + 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; + } + + /** + * 查询所有租客 + */ + 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; + } + + /** + * 查询所有房东 + */ + 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; + } + + /** + * 添加用户(注册用) + */ + 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; + } + + /** + * 更新用户信息 + */ + 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; + } + + /** + * 更新用户状态(启用/禁用) + */ + 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; + } + + /** + * 删除用户(物理删除,一般不建议) + */ + 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; + } + + /** + * 统计用户总数 + */ + 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; + } + + /** + * 将ResultSet转换为User对象 + */ + 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; + } + + /** + * 测试方法 + */ + public static void main(String[] args) { + UserDAO userDAO = new UserDAO(); + + // 测试1:查询所有租客 + System.out.println("=== 查询所有租客 ==="); + List tenants = userDAO.findAllTenants(); + for (User user : tenants) { + System.out.println(user); + } + + // 测试2:管理员登录测试(admin/e10adc3949ba59abbe56e057f20f883e = 123456的MD5) + System.out.println("\n=== 管理员登录测试 ==="); + User admin = userDAO.findByUsernameAndPassword("admin", "e10adc3949ba59abbe56e057f20f883e"); + if (admin != null) { + System.out.println("登录成功:" + admin); + System.out.println("是否是管理员:" + admin.isAdmin()); + } else { + System.out.println("登录失败"); + } + + // 测试3:房东登录测试 + System.out.println("\n=== 房东登录测试 ==="); + User landlord = userDAO.findByUsernameAndPassword("landlord01", "e10adc3949ba59abbe56e057f20f883e"); + if (landlord != null) { + System.out.println("登录成功:" + landlord); + System.out.println("是否是房东:" + landlord.isLandlord()); + } else { + System.out.println("登录失败"); + } + + // 测试4:统计用户总数 + System.out.println("\n=== 用户总数 ==="); + int count = userDAO.count(); + System.out.println("当前用户总数:" + count); + } +} \ 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..1bab86d --- /dev/null +++ b/HRS/src/com/hrs/model/entity/Collection.java @@ -0,0 +1,85 @@ +package com.hrs.model.entity; + +import java.util.Date; + +/** + * 收藏实体类 + * 对应数据库表:hrs_collection + */ +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; // 房源详情 + + public Collection() { + } + + public Collection(Long tenantId, Long houseId) { + this.tenantId = tenantId; + this.houseId = houseId; + } + + // Getter 和 Setter + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getTenantId() { + return tenantId; + } + + public void setTenantId(Long tenantId) { + this.tenantId = tenantId; + } + + public Long getHouseId() { + return houseId; + } + + public void setHouseId(Long houseId) { + this.houseId = houseId; + } + + public Date getCollectTime() { + return collectTime; + } + + public void setCollectTime(Date collectTime) { + this.collectTime = collectTime; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public House getHouse() { + return house; + } + + 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..5848d6a --- /dev/null +++ b/HRS/src/com/hrs/model/entity/House.java @@ -0,0 +1,226 @@ +package com.hrs.model.entity; + +import java.math.BigDecimal; +import java.util.Date; + +/** + * 房源实体类 + * 对应数据库表:hrs_house + * + * 房源状态:0-待审核;1-已上架;2-已下架;3-违规 + * 租赁类型:0-整租;1-合租 + */ +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; // 房东电话 + + public House() { + } + + // Getter 和 Setter + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getLandlordId() { + return landlordId; + } + + public void setLandlordId(Long landlordId) { + this.landlordId = landlordId; + } + + public String getHouseNo() { + return houseNo; + } + + public void setHouseNo(String houseNo) { + this.houseNo = houseNo; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getArea() { + return area; + } + + public void setArea(String area) { + this.area = area; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getHouseType() { + return houseType; + } + + public void setHouseType(String houseType) { + this.houseType = houseType; + } + + public BigDecimal getRentPrice() { + return rentPrice; + } + + public void setRentPrice(BigDecimal rentPrice) { + this.rentPrice = rentPrice; + } + + public String getRentType() { + return rentType; + } + + public void setRentType(String rentType) { + this.rentType = rentType; + } + + public String getRentTypeText() { + return "0".equals(rentType) ? "整租" : "合租"; + } + + public String getFacility() { + return facility; + } + + public void setFacility(String facility) { + this.facility = facility; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getImgUrl() { + return imgUrl; + } + + public void setImgUrl(String imgUrl) { + this.imgUrl = imgUrl; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getStatusText() { + switch (status) { + case "0": return "待审核"; + case "1": return "已上架"; + case "2": return "已下架"; + case "3": return "违规"; + default: return "未知"; + } + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public String getLandlordName() { + return landlordName; + } + + public void setLandlordName(String landlordName) { + this.landlordName = landlordName; + } + + public String getLandlordPhone() { + return landlordPhone; + } + + public void setLandlordPhone(String landlordPhone) { + this.landlordPhone = landlordPhone; + } + + // 辅助方法:获取第一张图片(用于列表展示) + public String getFirstImage() { + if (imgUrl != null && !imgUrl.isEmpty()) { + String[] images = imgUrl.split(","); + return images[0]; + } + return null; + } + + @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/Reservation.java b/HRS/src/com/hrs/model/entity/Reservation.java new file mode 100644 index 0000000..ea163ce --- /dev/null +++ b/HRS/src/com/hrs/model/entity/Reservation.java @@ -0,0 +1,174 @@ +package com.hrs.model.entity; + +import java.util.Date; + +/** + * 预约看房实体类 + * 对应数据库表:hrs_reservation + * + * 预约状态:0-待确认;1-已确认;2-已取消;3-已完成 + */ +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; // 房东信息 + + public Reservation() { + } + + // Getter 和 Setter + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getTenantId() { + return tenantId; + } + + public void setTenantId(Long tenantId) { + this.tenantId = tenantId; + } + + public Long getHouseId() { + return houseId; + } + + public void setHouseId(Long houseId) { + this.houseId = houseId; + } + + public Long getLandlordId() { + return landlordId; + } + + public void setLandlordId(Long landlordId) { + this.landlordId = landlordId; + } + + public Date getReserveTime() { + return reserveTime; + } + + public void setReserveTime(Date reserveTime) { + this.reserveTime = reserveTime; + } + + public String getRemark() { + return remark; + } + + public void setRemark(String remark) { + this.remark = remark; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getStatusText() { + switch (status) { + case "0": return "待确认"; + case "1": return "已确认"; + case "2": return "已取消"; + case "3": return "已完成"; + default: return "未知"; + } + } + + public Date getHandleTime() { + return handleTime; + } + + public void setHandleTime(Date handleTime) { + this.handleTime = handleTime; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + public House getHouse() { + return house; + } + + public void setHouse(House house) { + this.house = house; + } + + public User getTenant() { + return tenant; + } + + public void setTenant(User tenant) { + this.tenant = tenant; + } + + public User getLandlord() { + return landlord; + } + + public void setLandlord(User landlord) { + this.landlord = landlord; + } + + @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..bf68ae1 --- /dev/null +++ b/HRS/src/com/hrs/model/entity/User.java @@ -0,0 +1,186 @@ +package com.hrs.model.entity; + +import java.util.Date; + +/** + * 用户实体类 + * 对应数据库表:hrs_user + * + * 角色类型:0-租客 1-房东 2-管理员 + * 账号状态:0-未认证 1-已认证 2-禁用 + */ +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; // 更新时间 + + // 无参构造方法 + public User() { + } + + // 全参构造方法 + 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; + } + + // Getter 和 Setter 方法 + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUserName() { + return userName; + } + + public void setUserName(String userName) { + this.userName = userName; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getRealName() { + return realName; + } + + public void setRealName(String realName) { + this.realName = realName; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getIdCard() { + return idCard; + } + + public void setIdCard(String idCard) { + this.idCard = idCard; + } + + public String getRoleType() { + return roleType; + } + + public void setRoleType(String roleType) { + this.roleType = roleType; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getCreateBy() { + return createBy; + } + + public void setCreateBy(String createBy) { + this.createBy = createBy; + } + + public Date getCreateTime() { + return createTime; + } + + public void setCreateTime(Date createTime) { + this.createTime = createTime; + } + + public String getUpdateBy() { + return updateBy; + } + + public void setUpdateBy(String updateBy) { + this.updateBy = updateBy; + } + + public Date getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(Date updateTime) { + this.updateTime = updateTime; + } + + /** + * 辅助方法:判断是否为租客 + */ + public boolean isTenant() { + return "0".equals(this.roleType); + } + + /** + * 辅助方法:判断是否为房东 + */ + public boolean isLandlord() { + return "1".equals(this.roleType); + } + + /** + * 辅助方法:判断是否为管理员 + */ + public boolean isAdmin() { + return "2".equals(this.roleType); + } + + /** + * 辅助方法:判断账号是否已认证 + */ + public boolean isVerified() { + return "1".equals(this.status); + } + + @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/util/DBUtil.java b/HRS/src/com/hrs/util/DBUtil.java new file mode 100644 index 0000000..c0399b7 --- /dev/null +++ b/HRS/src/com/hrs/util/DBUtil.java @@ -0,0 +1,91 @@ +package com.hrs.util; + +import java.sql.*; + +/** + * 数据库连接工具类 - 土办法版 + * 只要jar包在WEB-INF/lib里就能用 + */ +public class DBUtil { + + // 数据库配置(改成你的) + private static final String URL = "jdbc:mysql://localhost:3306/hrs?useSSL=false&characterEncoding=utf8&serverTimezone=Asia/Shanghai"; + private static final String USERNAME = "root"; // 你的MySQL用户名 + private static final String PASSWORD = "root"; // 你的MySQL密码 + + // 驱动类名 + private static final String DRIVER = "com.mysql.jdbc.Driver"; + + /** + * 静态代码块:加载驱动 + */ + static { + try { + Class.forName(DRIVER); + System.out.println("✅ MySQL驱动加载成功!"); + } catch (ClassNotFoundException e) { + System.out.println("❌ MySQL驱动加载失败!"); + System.out.println("请检查:WEB-INF/lib 下是否有 mysql-connector-java-5.1.49.jar"); + e.printStackTrace(); + } + } + + /** + * 获取数据库连接 + */ + public static Connection getConnection() throws SQLException { + return DriverManager.getConnection(URL, USERNAME, PASSWORD); + } + + /** + * 关闭连接(查询用) + */ + public static void close(ResultSet rs, PreparedStatement pstmt, Connection conn) { + if (rs != null) { + try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } + } + close(pstmt, conn); + } + + /** + * 关闭连接(增删改用) + */ + 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(); } + } + } + + /** + * 测试方法 + */ + public static void main(String[] args) { + Connection conn = null; + try { + // 1. 获取连接 + conn = DBUtil.getConnection(); + System.out.println("✅ 数据库连接成功!"); + System.out.println("连接对象:" + conn); + + // 2. 简单测试查询 + Statement stmt = conn.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT COUNT(*) FROM hrs_user"); + if (rs.next()) { + int count = rs.getInt(1); + System.out.println("✅ 用户表中共有 " + count + " 条记录"); + } + rs.close(); + stmt.close(); + + } catch (SQLException e) { + System.out.println("❌ 数据库连接失败!"); + System.out.println("错误信息:" + e.getMessage()); + e.printStackTrace(); + } finally { + close(null, null, conn); + } + } +} \ 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..0ce86f8 --- /dev/null +++ b/HRS/src/com/hrs/util/MD5Util.java @@ -0,0 +1,80 @@ +package com.hrs.util; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * MD5加密工具类 + * 用于密码加密 + */ +public class MD5Util { + + /** + * 将字符串进行MD5加密 + * @param str 要加密的字符串 + * @return MD5加密后的32位小写字符串 + */ + 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; + } + } + + /** + * 将0-15的数字转换为十六进制字符 + */ + private static char hexChar(int value) { + if (value >= 0 && value <= 9) { + return (char) ('0' + value); + } else { + return (char) ('a' + (value - 10)); + } + } + + /** + * 验证密码是否匹配 + * @param inputPassword 用户输入的明文密码 + * @param storedPassword 数据库中存储的MD5密码 + * @return 是否匹配 + */ + public static boolean verify(String inputPassword, String storedPassword) { + String encrypted = md5(inputPassword); + return encrypted != null && encrypted.equals(storedPassword); + } + + /** + * 测试方法 + */ + 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