Files
HRS/HRS/WebContent/jsp/user/collection_list.jsp
2026-04-14 12:29:29 +08:00

418 lines
13 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<%@ 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<Collection> collectionList = (List<Collection>) request.getAttribute("collectionList");
Integer totalCount = (Integer) request.getAttribute("totalCount");
String msg = request.getParameter("msg");
String error = request.getParameter("error");
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>我的收藏 - 租房系统</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: Arial, "微软雅黑", sans-serif;
background-color: #f5f5f5;
}
.header {
background-color: #4CAF50;
color: white;
padding: 15px 0;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}
.container {
width: 1200px;
margin: 0 auto;
overflow: hidden;
}
.logo {
float: left;
font-size: 24px;
font-weight: bold;
}
.nav {
float: right;
margin-top: 5px;
}
.nav a {
color: white;
text-decoration: none;
margin-left: 20px;
padding: 5px 10px;
}
.nav a:hover, .nav a.active {
background-color: #45a049;
border-radius: 4px;
}
.user-info {
float: right;
margin-right: 20px;
font-size: 14px;
}
.breadcrumb {
background-color: white;
padding: 12px 0;
margin-bottom: 20px;
border-radius: 4px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.breadcrumb a {
color: #4CAF50;
text-decoration: none;
}
.stats {
background-color: white;
padding: 10px 15px;
border-radius: 4px;
margin-bottom: 20px;
color: #666;
}
.message {
background-color: #e8f5e9;
color: #2e7d32;
padding: 12px;
border-radius: 4px;
margin-bottom: 20px;
text-align: center;
animation: fadeOut 3s ease forwards;
}
.error-message {
background-color: #ffebee;
color: #c62828;
padding: 12px;
border-radius: 4px;
margin-bottom: 20px;
text-align: center;
animation: fadeOut 3s ease forwards;
}
@keyframes fadeOut {
0% { opacity: 1; }
70% { opacity: 1; }
100% { opacity: 0; display: none; }
}
.collection-list {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
gap: 20px;
margin-bottom: 30px;
}
.collection-card {
background-color: white;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 5px rgba(0,0,0,0.1);
transition: transform 0.3s;
position: relative;
}
.collection-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0,0,0,0.2);
}
.house-image {
height: 200px;
background-color: #e0e0e0;
background-size: cover;
background-position: center;
}
.house-image .no-image {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
color: #999;
font-size: 14px;
}
.house-info {
padding: 15px;
}
.house-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
}
.house-title a {
color: #333;
text-decoration: none;
}
.house-title a:hover {
color: #4CAF50;
}
.house-detail {
color: #666;
font-size: 14px;
margin-bottom: 8px;
}
.house-price {
color: #f44336;
font-size: 20px;
font-weight: bold;
margin: 10px 0;
}
.house-price span {
font-size: 14px;
font-weight: normal;
}
.collect-time {
font-size: 12px;
color: #999;
margin-top: 10px;
}
.delete-btn {
position: absolute;
top: 10px;
right: 10px;
background-color: rgba(0,0,0,0.6);
color: white;
border: none;
border-radius: 50%;
width: 30px;
height: 30px;
cursor: pointer;
font-size: 18px;
transition: background-color 0.3s;
z-index: 10;
}
.delete-btn:hover {
background-color: #f44336;
}
.empty-state {
text-align: center;
padding: 80px;
background-color: white;
border-radius: 8px;
color: #999;
}
.empty-state p {
margin-top: 20px;
font-size: 16px;
}
.empty-state a {
color: #4CAF50;
text-decoration: none;
}
.footer {
background-color: #333;
color: white;
text-align: center;
padding: 20px;
margin-top: 40px;
}
.toast {
position: fixed;
top: 80px;
right: 20px;
padding: 12px 24px;
border-radius: 4px;
color: white;
z-index: 1000;
animation: slideIn 0.3s ease;
}
.toast-success {
background-color: #4CAF50;
}
.toast-error {
background-color: #f44336;
}
@keyframes slideIn {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.clearfix::after {
content: "";
clear: both;
display: table;
}
</style>
</head>
<body>
<div class="header">
<div class="container clearfix">
<div class="logo">🏠 租房系统</div>
<div class="user-info">
欢迎,<%= loginUser.getRealName() %> |
<a href="${pageContext.request.contextPath}/user/logout" style="color:white;">退出</a>
</div>
<div class="nav">
<a href="${pageContext.request.contextPath}/user/house/list">首页</a>
<a href="${pageContext.request.contextPath}/user/collection/list" class="active">我的收藏</a>
<a href="${pageContext.request.contextPath}/user/reservation/list">我的预约</a>
<a href="${pageContext.request.contextPath}/user/order/list">我的订单</a>
</div>
</div>
</div>
<div class="container">
<div class="breadcrumb">
<a href="${pageContext.request.contextPath}/user/house/list">首页</a> &gt;
<span>我的收藏</span>
</div>
<% if (msg != null) { %>
<div class="message"><%= msg %></div>
<% } %>
<% if (error != null) { %>
<div class="error-message"><%= error %></div>
<% } %>
<div class="stats">
📚 共收藏 <strong id="totalCount"><%= totalCount %></strong> 套房源
</div>
<div class="collection-list" id="collectionList">
<%
if (collectionList != null && !collectionList.isEmpty()) {
for (Collection collection : collectionList) {
House house = collection.getHouse();
if (house != null) {
%>
<div class="collection-card" data-id="<%= collection.getId() %>">
<div class="house-image" style="background-image: url('/HRS/<%= house.getFirstImage() != null ? house.getFirstImage() : "" %>');">
<% if (house.getFirstImage() == null) { %>
<div class="no-image">🏠 暂无图片</div>
<% } %>
</div>
<button class="delete-btn" onclick="deleteCollection(<%= collection.getId() %>)" title="取消收藏">×</button>
<div class="house-info">
<div class="house-title">
<a href="${pageContext.request.contextPath}/user/house/detail?id=<%= house.getId() %>">
<%= house.getTitle() %>
</a>
</div>
<div class="house-detail">
📍 <%= house.getArea() %> | <%= house.getHouseType() %> | <%= house.getRentTypeText() %>
</div>
<div class="house-price">
¥<%= house.getRentPrice() %><span>/月</span>
</div>
<div class="collect-time">
收藏时间:<%= collection.getCollectTime() %>
</div>
</div>
</div>
<%
}
}
} else {
%>
<div class="empty-state">
<div style="font-size: 64px;">❤️</div>
<p>还没有收藏任何房源</p>
<p><a href="${pageContext.request.contextPath}/user/house/list">去浏览房源 &gt;&gt;</a></p>
</div>
<%
}
%>
</div>
</div>
<div class="footer">
<p>© 2026 租房系统 | 让租房更简单</p>
</div>
<script>
// AJAX删除收藏
function deleteCollection(id) {
if (confirm('确定要取消收藏这套房源吗?')) {
// 发送AJAX请求
var xhr = new XMLHttpRequest();
xhr.open('GET', '${pageContext.request.contextPath}/user/collection/delete?id=' + id + '&ajax=true&from=list', true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
var result = JSON.parse(xhr.responseText);
if (result.success) {
// 移除DOM元素
var card = document.querySelector('.collection-card[data-id="' + id + '"]');
if (card) {
card.remove();
}
// 更新计数
var totalSpan = document.getElementById('totalCount');
var currentCount = parseInt(totalSpan.innerText);
totalSpan.innerText = currentCount - 1;
// 显示成功提示
showToast('取消收藏成功', 'success');
// 检查是否还有收藏
var remainingCards = document.querySelectorAll('.collection-card');
if (remainingCards.length == 0) {
location.reload(); // 刷新页面显示空状态
}
} else {
showToast(result.msg || '取消收藏失败', 'error');
}
}
};
xhr.send();
}
}
// 显示提示消息
function showToast(msg, type) {
var toast = document.createElement('div');
toast.className = 'toast toast-' + type;
toast.innerHTML = msg;
document.body.appendChild(toast);
setTimeout(function() {
toast.remove();
}, 2000);
}
</script>
</body>
</html>