引言
随着高校扩招和城市化进程的加速,大学生校外租房需求日益增长。然而,传统租房市场存在信息不对称、租赁流程繁琐、安全保障不足等问题。本文介绍一个基于Java全栈技术的大学生租房管理系统,旨在为大学生提供便捷、安全、高效的租房服务平台。
系统概述
大学生租房管理系统是一个面向高校学生、房东和管理员的综合性租房服务平台。该系统采用前后端分离架构,前端使用Vue.js框架,后端基于Spring Boot + MyBatis构建,数据库采用MySQL,实现了房源信息管理、用户认证、在线签约、租金支付、投诉处理等核心功能。
技术栈
前端技术
- Vue.js: 构建用户界面
- Element UI: 组件库
- Axios: HTTP客户端
- Vuex: 状态管理
- Vue Router: 前端路由
后端技术
- Spring Boot: 简化Spring应用开发
- Spring Security: 认证和授权
- MyBatis: ORM框架
- Redis: 缓存
- JWT: 用户认证
- Swagger: API文档
数据库
- MySQL: 关系型数据库
- Druid: 数据库连接池
开发工具
- IntelliJ IDEA: Java开发IDE
- VS Code: 前端开发IDE
- Maven: 项目管理工具
- Git: 版本控制
- Docker: 容器化部署
系统架构
系统采用经典的三层架构:
- 表现层:Vue.js构建的前端界面
- 业务逻辑层:Spring Boot实现的后端服务
- 数据访问层:MyBatis + MySQL实现的数据持久化
同时,系统还集成了以下中间件:
- Redis:用于缓存热点数据,提高系统响应速度
- Nginx:实现负载均衡和静态资源服务
- RabbitMQ:处理异步消息,如通知、邮件发送等
核心功能模块
1. 用户管理模块
- 用户注册与登录
- 身份认证(学生认证、房东认证)
- 个人信息管理
- 角色权限控制
2. 房源管理模块
- 房源信息发布
- 房源搜索与筛选
- 房源详情展示
- 收藏与比较
3. 预约看房模块
- 在线预约
- 预约日程管理
- 看房反馈
- 房源评价
数据库设计
系统的核心数据表包括:
- 用户表(user):存储用户基本信息
- 学生认证表(student_verification):存储学生认证信息
- 房东表(landlord):存储房东信息
- 房源表(house):存储房源基本信息
- 房源详情表(house_detail):存储房源详细信息
- 房源图片表(house_image):存储房源图片
- 预约表(appointment):存储看房预约信息
- 合同表(contract):存储租赁合同信息
- 支付表(payment):存储支付记录
- 维修表(maintenance):存储维修记录
- 评价表(review):存储用户评价
- 消息表(message):存储系统消息
核心表结构示例
-- 用户表
CREATE TABLE `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(100) NOT NULL COMMENT '密码',
`real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',
`id_card` varchar(18) DEFAULT NULL COMMENT '身份证号',
`phone` varchar(11) NOT NULL COMMENT '手机号',
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像',
`gender` tinyint(1) DEFAULT NULL COMMENT '性别:0-女,1-男',
`role` varchar(20) NOT NULL COMMENT '角色:STUDENT-学生,LANDLORD-房东,ADMIN-管理员',
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态:0-禁用,1-正常',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_username` (`username`),
UNIQUE KEY `uk_phone` (`phone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-- 房源表
CREATE TABLE `house` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`landlord_id` bigint(20) NOT NULL COMMENT '房东ID',
`title` varchar(100) NOT NULL COMMENT '标题',
`address` varchar(255) NOT NULL COMMENT '地址',
`area` decimal(10,2) NOT NULL COMMENT '面积(平方米)',
`price` decimal(10,2) NOT NULL COMMENT '月租金',
`deposit` decimal(10,2) NOT NULL COMMENT '押金',
`house_type` varchar(50) NOT NULL COMMENT '户型',
`orientation` varchar(20) DEFAULT NULL COMMENT '朝向',
`floor` varchar(20) DEFAULT NULL COMMENT '楼层',
`has_elevator` tinyint(1) DEFAULT NULL COMMENT '是否有电梯',
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '状态:0-下架,1-上架',
`create_time` datetime NOT NULL COMMENT '创建时间',
`update_time` datetime NOT NULL COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_landlord_id` (`landlord_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='房源表';
接口设计
系统API接口采用RESTful风格设计,主要包括以下几类:
用户接口
POST /api/auth/register
:用户注册POST /api/auth/login
:用户登录GET /api/users/current
:获取当前用户信息PUT /api/users/{id}
:更新用户信息POST /api/students/verify
:学生认证
房源接口
POST /api/houses
:发布房源GET /api/houses
:查询房源列表GET /api/houses/{id}
:获取房源详情PUT /api/houses/{id}
:更新房源信息DELETE /api/houses/{id}
:删除房源
预约接口
POST /api/appointments
:创建预约GET /api/appointments
:查询预约列表PUT /api/appointments/{id}
:更新预约状态DELETE /api/appointments/{id}
:取消预约
合同接口
POST /api/contracts
:创建合同GET /api/contracts
:查询合同列表GET /api/contracts/{id}
:获取合同详情PUT /api/contracts/{id}
:更新合同状态
支付接口
POST /api/payments
:创建支付GET /api/payments
:查询支付记录GET /api/payments/{id}
:获取支付详情
系统实现
前端实现
前端基于Vue.js框架实现,主要页面包括:
- 首页:展示系统概览、热门房源、最新公告等
- 房源列表页:展示房源列表,提供筛选和排序功能
- 房源详情页:展示房源详细信息,提供预约功能
- 个人中心:管理个人信息、预约、合同等
- 后台管理:提供系统管理功能
后端实现
后端基于Spring Boot实现,主要包括以下几个层次:
- Controller层:处理HTTP请求,返回响应
- Service层:实现业务逻辑
- DAO层:实现数据访问
- Entity层:定义数据实体
- DTO层:定义数据传输对象
- Util层:提供工具类
安全实现
系统安全主要通过以下几个方面实现:
- 用户认证:基于JWT实现无状态认证
- 权限控制:基于RBAC模型实现权限管理
- 数据加密:敏感数据加密存储
- 防SQL注入:使用参数化查询
- 防XSS攻击:输入输出过滤
- HTTPS:传输层加密
系统部署
系统采用Docker容器化部署,主要包括以下几个容器:
- 前端容器:部署Vue.js应用
- 后端容器:部署Spring Boot应用
- MySQL容器:部署数据库
- Redis容器:部署缓存
- Nginx容器:部署反向代理
部署架构图如下:
┌─────────────┐
│ Nginx │
└─────────────┘
│
┌────────────┴────────────┐
│ │
┌───────▼──────┐ ┌───────▼──────┐
│ Frontend │ │ Backend │
│ (Vue.js) │ │ (Spring Boot)│
└───────┬──────┘ └───────┬──────┘
│ │
│ ┌────────┴────────┐
│ │ │
┌───────▼──────┐ ┌──────▼─────┐ ┌──────▼─────┐
│ Browser │ │ MySQL │ │ Redis │
└──────────────┘ └────────────┘ └────────────┘
系统测试
系统测试主要包括以下几个方面:
- 单元测试:使用JUnit测试各个组件
- 集成测试:测试组件之间的交互
- 接口测试:使用Postman测试API接口
- 性能测试:使用JMeter测试系统性能
- 安全测试:进行渗透测试和安全扫描
项目亮点
- 前后端分离架构:提高开发效率和系统可维护性
- 微服务设计思想:模块化设计,便于扩展
- 响应式设计:适配不同终端设备
- 实时通信:基于WebSocket实现实时消息推送
- 数据可视化:直观展示系统运营数据
- 智能推荐:基于用户行为推荐合适房源
项目难点及解决方案
1. 高并发处理
- 问题:节假日期间,系统面临高并发访问压力
- 解决方案:
- 使用Redis缓存热点数据
- 实现接口限流
- 采用异步处理非核心业务
- 数据库读写分离
2. 数据一致性
- 问题:支付过程中的数据一致性问题
- 解决方案:
- 采用分布式事务
- 实现补偿机制
- 引入消息队列
3. 安全问题
- 问题:用户敏感信息保护
- 解决方案:
- 数据脱敏存储
- 传输加密
- 权限精细化控制
系统优化
1. 性能优化
- 数据库索引优化
- SQL语句优化
- JVM参数调优
- 前端资源压缩与CDN加速
2. 用户体验优化
- 页面加载速度优化
- 表单交互优化
- 响应式布局优化
- 操作流程简化
未来展望
- 移动端应用:开发Android和iOS原生应用
- 智能推荐系统:基于机器学习的房源推荐
- VR看房:实现虚拟现实看房体验
- 区块链合同:基于区块链技术的智能合约
- 大数据分析:深度挖掘租房市场数据
总结
大学生租房管理系统是一个综合性的Java全栈项目,涵盖了前端开发、后端开发、数据库设计、系统架构等多个方面。通过该项目,不仅能够解决大学生租房过程中的实际问题,还能够全面提升开发者的技术能力和项目经验。
本项目采用主流的Java全栈技术栈,具有良好的可扩展性和可维护性,为后续功能迭代和系统优化提供了坚实的基础。同时,项目中涉及的高并发处理、数据一致性、安全防护等技术难点,也为开发者提供了宝贵的实践经验。
代码:
Directory Content Summary
Generated at: 2025-02-27 12:58:48
Source Directory: ./rental-system
Directory Structure
rental-system/
backend/
pom.xml
src/
main/
java/
com/
rental/
RentalApplication.java
RentalSystemApplication.java
config/
SecurityConfig.java
WebMvcConfig.java
controller/
AppointmentController.java
FavoriteController.java
HouseController.java
HouseReviewController.java
ReviewReplyController.java
UserController.java
VerificationController.java
ViewingFeedbackController.java
dao/
AppointmentDao.java
ComparisonDao.java
FavoriteDao.java
HouseDao.java
HouseDetailDao.java
HouseImageDao.java
HouseReviewDao.java
LandlordVerificationDao.java
PermissionDao.java
ReviewReplyDao.java
RoleDao.java
StudentVerificationDao.java
UserDao.java
ViewingFeedbackDao.java
dto/
AppointmentDTO.java
FeedbackDTO.java
HouseDetailDTO.java
HouseDTO.java
HouseSearchDTO.java
LandlordVerificationDTO.java
LoginDTO.java
PageResult.java
RegisterDTO.java
ReplyDTO.java
Result.java
ReviewDTO.java
StudentVerificationDTO.java
UserDTO.java
entity/
Appointment.java
Comparison.java
Favorite.java
House.java
HouseDetail.java
HouseImage.java
HouseReview.java
LandlordVerification.java
Permission.java
ReviewReply.java
Role.java
StudentVerification.java
User.java
ViewingFeedback.java
exception/
BusinessException.java
GlobalExceptionHandler.java
UnauthorizedException.java
interceptor/
AuthenticationInterceptor.java
AuthInterceptor.java
service/
AppointmentService.java
FavoriteService.java
HouseReviewService.java
HouseService.java
ReviewReplyService.java
UserService.java
VerificationService.java
ViewingFeedbackService.java
impl/
AppointmentServiceImpl.java
FavoriteServiceImpl.java
HouseReviewServiceImpl.java
HouseServiceImpl.java
ReviewReplyServiceImpl.java
UserServiceImpl.java
VerificationServiceImpl.java
ViewingFeedbackServiceImpl.java
util/
JsonUtil.java
JwtUtil.java
PasswordEncoder.java
PasswordUtil.java
resources/
application.properties
application.yml
schema.sql
mapper/
AppointmentMapper.xml
HouseDetailMapper.xml
HouseMapper.xml
HouseReviewMapper.xml
ReviewReplyMapper.xml
UserMapper.xml
ViewingFeedbackMapper.xml
sql/
appointment_module.sql
target/
classes/
application.properties
application.yml
schema.sql
com/
rental/
config/
controller/
dao/
dto/
entity/
exception/
interceptor/
service/
impl/
util/
mapper/
AppointmentMapper.xml
HouseDetailMapper.xml
HouseMapper.xml
HouseReviewMapper.xml
ReviewReplyMapper.xml
UserMapper.xml
ViewingFeedbackMapper.xml
sql/
appointment_module.sql
generated-sources/
annotations/
generated-test-sources/
test-annotations/
test-classes/
frontend/
package.json
src/
App.vue
main.js
api/
appointment.js
favorite.js
feedback.js
house.js
review.js
user.js
verification.js
assets/
css/
global.css
router/
index.js
modules/
appointment.js
store/
index.js
modules/
appointment.js
utils/
auth.js
date.js
request.js
views/
Home.vue
Login.vue
Register.vue
admin/
Dashboard.vue
appointment/
AppointmentCalendar.vue
AppointmentDetail.vue
AppointmentDetail.vue (continuation)
AppointmentForm.vue
AppointmentList.vue
house/
Detail.vue
components/
HouseFeedbacks.vue
HouseReviews.vue
user/
Favorite.vue
Profile.vue
verification/
StudentVerification.vue
sql/
01_create_tables.sql
02_init_data.sql
File Contents
backend\pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.rental</groupId>
<artifactId>rental-system</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>rental-system</name>
<description>College Student Rental Housing Management System</description>
<properties>
<java.version>1.8</java.version>
<mybatis.version>2.2.2</mybatis.version>
<druid.version>1.2.8</druid.version>
<jwt.version>0.9.1</jwt.version>
<swagger.version>3.0.0</swagger.version>
<fastjson.version>2.0.12</fastjson.version>
<commons-lang3.version>3.12.0</commons-lang3.version>
<commons-io.version>2.11.0</commons-io.version>
<commons-fileupload.version>1.4</commons-fileupload.version>
</properties>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- MyBatis -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis.version}</version>
</dependency>
<!-- MySQL -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- Druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>${druid.version}</version>
</dependency>
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>${jwt.version}</version>
</dependency>
<!-- Swagger -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-boot-starter</artifactId>
<version>${swagger.version}</version>
</dependency>
<!-- FastJSON -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- Commons -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io.version}</version>
</dependency>
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>${commons-fileupload.version}</version>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
backend\src\main\java\com\rental\RentalApplication.java
package com.rental;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* 租房管理系统启动类
*/
@SpringBootApplication
@EnableTransactionManagement
public class RentalApplication {
public static void main(String[] args) {
SpringApplication.run(RentalApplication.class, args);
}
}
Security Configuration
backend\src\main\java\com\rental\RentalSystemApplication.java
package com.rental;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* 大学生租房管理系统启动类
*/
@SpringBootApplication
@EnableTransactionManagement
@MapperScan("com.rental.dao")
public class RentalSystemApplication {
public static void main(String[] args) {
SpringApplication.run(RentalSystemApplication.class, args);
}
}
backend\src\main\java\com\rental\config\SecurityConfig.java
package com.rental.config;
import com.rental.interceptor.AuthenticationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* 安全配置
*/
@Configuration
public class SecurityConfig implements WebMvcConfigurer {
/**
* 注册拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册认证拦截器
registry.addInterceptor(authenticationInterceptor())
.addPathPatterns("/**")
.excludePathPatterns("/user/login", "/user/register", "/house/list", "/house/search", "/house/detail/**");
}
/**
* 跨域配置
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.maxAge(3600);
}
/**
* 认证拦截器
*/
@Bean
public AuthenticationInterceptor authenticationInterceptor() {
return new AuthenticationInterceptor();
}
}
Authentication Interceptor
backend\src\main\java\com\rental\config\WebMvcConfig.java
package com.rental.config;
import com.rental.interceptor.AuthInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
/**
* Web配置
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Autowired
private AuthInterceptor authInterceptor;
/**
* 添加拦截器
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(authInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns("/api/user/login", "/api/user/register");
}
/**
* 跨域配置
*/
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.allowedHeaders("*")
.allowCredentials(true)
.maxAge(3600);
}
}
backend\src\main\java\com\rental\controller\AppointmentController.java
package com.rental.controller;
import com.rental.dto.AppointmentDTO;
import com.rental.entity.Appointment;
import com.rental.dto.Result;
import com.rental.service.AppointmentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.Date;
import java.util.List;
import java.util.Map;
/**
* 预约控制器
*/
@RestController
@RequestMapping("/appointment")
public class AppointmentController {
@Autowired
private AppointmentService appointmentService;
/**
* 创建预约
*/
@PostMapping("/create")
public Result<Appointment> createAppointment(@RequestBody @Valid AppointmentDTO appointmentDTO, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return appointmentService.createAppointment(appointmentDTO, userId);
}
/**
* 确认预约
*/
@PostMapping("/confirm/{id}")
public Result<Void> confirmAppointment(@PathVariable("id") Long appointmentId, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return appointmentService.confirmAppointment(appointmentId, userId);
}
/**
* 取消预约
*/
@PostMapping("/cancel/{id}")
public Result<Void> cancelAppointment(@PathVariable("id") Long appointmentId, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return appointmentService.cancelAppointment(appointmentId, userId);
}
/**
* 完成预约
*/
@PostMapping("/complete/{id}")
public Result<Void> completeAppointment(@PathVariable("id") Long appointmentId, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return appointmentService.completeAppointment(appointmentId, userId);
}
/**
* 获取预约详情
*/
@GetMapping("/detail/{id}")
public Result<Appointment> getAppointmentDetail(@PathVariable("id") Long appointmentId) {
return appointmentService.getAppointmentById(appointmentId);
}
/**
* 获取用户的预约列表
*/
@GetMapping("/user")
public Result<List<Appointment>> getUserAppointments(HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return appointmentService.getUserAppointments(userId);
}
/**
* 获取房东的预约列表
*/
@GetMapping("/landlord")
public Result<List<Appointment>> getLandlordAppointments(HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return appointmentService.getLandlordAppointments(userId);
}
/**
* 获取房源的预约列表
*/
@GetMapping("/house/{houseId}")
public Result<List<Appointment>> getHouseAppointments(@PathVariable("houseId") Long houseId) {
return appointmentService.getHouseAppointments(houseId);
}
/**
* 获取指定日期范围内的预约
*/
@GetMapping("/date-range")
public Result<List<Appointment>> getAppointmentsByDateRange(
@RequestParam("startDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date startDate,
@RequestParam("endDate") @DateTimeFormat(pattern = "yyyy-MM-dd") Date endDate,
HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return appointmentService.getAppointmentsByDateRange(startDate, endDate, userId);
}
/**
* 获取预约统计数据
*/
@GetMapping("/statistics")
public Result<Map<String, Object>> getAppointmentStatistics(HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return appointmentService.getAppointmentStatistics(userId);
}
}
backend\src\main\java\com\rental\controller\FavoriteController.java
package com.rental.controller;
import com.rental.dto.HouseDTO;
import com.rental.dto.Result;
import com.rental.service.FavoriteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 收藏控制器
*/
@RestController
@RequestMapping("/api/favorite")
public class FavoriteController {
@Autowired
private FavoriteService favoriteService;
/**
* 添加收藏
*/
@PostMapping("/{userId}/{houseId}")
public Result<Boolean> addFavorite(@PathVariable Long userId, @PathVariable Long houseId) {
boolean result = favoriteService.addFavorite(userId, houseId);
return Result.success(result);
}
/**
* 取消收藏
*/
@DeleteMapping("/{userId}/{houseId}")
public Result<Boolean> cancelFavorite(@PathVariable Long userId, @PathVariable Long houseId) {
boolean result = favoriteService.cancelFavorite(userId, houseId);
return Result.success(result);
}
/**
* 查询是否收藏
*/
@GetMapping("/{userId}/{houseId}")
public Result<Boolean> isFavorite(@PathVariable Long userId, @PathVariable Long houseId) {
boolean result = favoriteService.isFavorite(userId, houseId);
return Result.success(result);
}
/**
* 获取收藏列表
*/
@GetMapping("/list/{userId}")
public Result<List<HouseDTO>> getFavoriteList(@PathVariable Long userId) {
List<HouseDTO> favoriteList = favoriteService.getFavoriteList(userId);
return Result.success(favoriteList);
}
}
backend\src\main\java\com\rental\controller\HouseController.java
package com.rental.controller;
import com.rental.dto.HouseDTO;
import com.rental.dto.HouseSearchDTO;
import com.rental.dto.PageResult;
import com.rental.dto.Result;
import com.rental.entity.House;
import com.rental.service.HouseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
/**
* 房源控制器
*/
@RestController
@RequestMapping("/api/house")
public class HouseController {
@Autowired
private HouseService houseService;
/**
* 获取房源详情
*/
@GetMapping("/{id}")
public Result<HouseDTO> getHouseDetail(@PathVariable Long id) {
HouseDTO houseDTO = houseService.getHouseById(id);
if (houseDTO == null) {
return Result.error("房源不存在");
}
return Result.success(houseDTO);
}
/**
* 获取房东的房源列表
*/
@GetMapping("/landlord/{landlordId}")
public Result<List<HouseDTO>> getLandlordHouseList(@PathVariable Long landlordId) {
List<HouseDTO> houseList = houseService.getHouseListByLandlordId(landlordId);
return Result.success(houseList);
}
/**
* 搜索房源
*/
@PostMapping("/search")
public Result<PageResult<HouseDTO>> searchHouse(@RequestBody HouseSearchDTO searchDTO) {
PageResult<HouseDTO> pageResult = houseService.searchHouse(searchDTO);
return Result.success(pageResult);
}
/**
* 发布房源
*/
@PostMapping
public Result<Long> addHouse(@RequestBody @Valid HouseDTO houseDTO) {
Long houseId = houseService.addHouse(houseDTO);
return Result.success(houseId);
}
/**
* 更新房源
*/
@PutMapping
public Result<Boolean> updateHouse(@RequestBody @Valid HouseDTO houseDTO) {
boolean result = houseService.updateHouse(houseDTO);
return Result.success(result);
}
/**
* 删除房源
*/
@DeleteMapping("/{id}")
public Result<Boolean> deleteHouse(@PathVariable Long id) {
boolean result = houseService.deleteHouse(id);
return Result.success(result);
}
/**
* 批量删除房源
*/
@DeleteMapping("/batch")
public Result<Boolean> deleteHouseBatch(@RequestBody Long[] ids) {
boolean result = houseService.deleteHouseBatch(ids);
return Result.success(result);
}
/**
* 更新房源状态
*/
@PutMapping("/{id}/status/{status}")
public Result<Boolean> updateHouseStatus(@PathVariable Long id, @PathVariable Integer status) {
boolean result = houseService.updateHouseStatus(id, status);
return Result.success(result);
}
/**
* 获取房源列表
*/
@GetMapping("/list")
public Result<List<HouseDTO>> getHouseList(House house) {
List<HouseDTO> houseList = houseService.getHouseList(house);
return Result.success(houseList);
}
}
backend\src\main\java\com\rental\controller\HouseReviewController.java
package com.rental.controller;
import com.rental.dto.ReviewDTO;
import com.rental.entity.HouseReview;
import com.rental.dto.Result;
import com.rental.service.HouseReviewService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
import java.util.Map;
/**
* 房源评价控制器
*/
@RestController
@RequestMapping("/review")
public class HouseReviewController {
@Autowired
private HouseReviewService houseReviewService;
/**
* 提交房源评价
*/
@PostMapping("/submit")
public Result<HouseReview> submitReview(@RequestBody @Valid ReviewDTO reviewDTO, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return houseReviewService.submitReview(reviewDTO, userId);
}
/**
* 更新房源评价
*/
@PutMapping("/update/{id}")
public Result<Void> updateReview(@PathVariable("id") Long reviewId, @RequestBody @Valid ReviewDTO reviewDTO, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return houseReviewService.updateReview(reviewId, reviewDTO, userId);
}
/**
* 删除房源评价
*/
@DeleteMapping("/delete/{id}")
public Result<Void> deleteReview(@PathVariable("id") Long reviewId, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return houseReviewService.deleteReview(reviewId, userId);
}
/**
* 获取评价详情
*/
@GetMapping("/detail/{id}")
public Result<HouseReview> getReviewDetail(@PathVariable("id") Long reviewId) {
return houseReviewService.getReviewById(reviewId);
}
/**
* 获取房源的评价列表
*/
@GetMapping("/house/{houseId}")
public Result<List<HouseReview>> getHouseReviews(@PathVariable("houseId") Long houseId) {
return houseReviewService.getHouseReviews(houseId);
}
/**
* 获取用户的评价列表
*/
@GetMapping("/user")
public Result<List<HouseReview>> getUserReviews(HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return houseReviewService.getUserReviews(userId);
}
/**
* 获取房源评价统计数据
*/
@GetMapping("/statistics/{houseId}")
public Result<Map<String, Object>> getHouseReviewStatistics(@PathVariable("houseId") Long houseId) {
return houseReviewService.getHouseReviewStatistics(houseId);
}
/**
* 检查用户是否已评价房源
*/
@GetMapping("/check/{houseId}")
public Result<Boolean> checkUserReviewed(@PathVariable("houseId") Long houseId, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return houseReviewService.checkUserReviewed(houseId, userId);
}
}
backend\src\main\java\com\rental\controller\ReviewReplyController.java
package com.rental.controller;
import com.rental.dto.ReplyDTO;
import com.rental.entity.ReviewReply;
import com.rental.dto.Result;
import com.rental.service.ReviewReplyService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
/**
* 评价回复控制器
*/
@RestController
@RequestMapping("/reply")
public class ReviewReplyController {
@Autowired
private ReviewReplyService reviewReplyService;
/**
* 提交评价回复
*/
@PostMapping("/submit")
public Result<ReviewReply> submitReply(@RequestBody @Valid ReplyDTO replyDTO, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return reviewReplyService.submitReply(replyDTO, userId);
}
/**
* 更新评价回复
*/
@PutMapping("/update/{id}")
public Result<Void> updateReply(@PathVariable("id") Long replyId, @RequestBody @Valid ReplyDTO replyDTO, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return reviewReplyService.updateReply(replyId, replyDTO, userId);
}
/**
* 删除评价回复
*/
@DeleteMapping("/delete/{id}")
public Result<Void> deleteReply(@PathVariable("id") Long replyId, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return reviewReplyService.deleteReply(replyId, userId);
}
/**
* 获取回复详情
*/
@GetMapping("/detail/{id}")
public Result<ReviewReply> getReplyDetail(@PathVariable("id") Long replyId) {
return reviewReplyService.getReplyById(replyId);
}
/**
* 获取评价的回复列表
*/
@GetMapping("/review/{reviewId}")
public Result<List<ReviewReply>> getReviewReplies(@PathVariable("reviewId") Long reviewId) {
return reviewReplyService.getReviewReplies(reviewId);
}
}
3.1 API Services
backend\src\main\java\com\rental\controller\UserController.java
package com.rental.controller;
import com.rental.dto.LoginDTO;
import com.rental.dto.RegisterDTO;
import com.rental.dto.Result;
import com.rental.dto.UserDTO;
import com.rental.entity.User;
import com.rental.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
/**
* 用户控制器
*/
@RestController
@RequestMapping("/api/user")
public class UserController {
@Autowired
private UserService userService;
/**
* 用户登录
*/
@PostMapping("/login")
public Result<UserDTO> login(@RequestBody @Valid LoginDTO loginDTO) {
UserDTO userDTO = userService.login(loginDTO);
return Result.success(userDTO);
}
/**
* 用户注册
*/
@PostMapping("/register")
public Result<UserDTO> register(@RequestBody @Valid RegisterDTO registerDTO) {
UserDTO userDTO = userService.register(registerDTO);
return Result.success(userDTO);
}
/**
* 获取用户信息
*/
@GetMapping("/{id}")
public Result<UserDTO> getUserInfo(@PathVariable Long id) {
UserDTO userDTO = userService.getUserById(id);
if (userDTO == null) {
return Result.error("用户不存在");
}
return Result.success(userDTO);
}
/**
* 更新用户信息
*/
@PutMapping
public Result<Boolean> updateUser(@RequestBody User user) {
boolean result = userService.updateUser(user);
return Result.success(result);
}
/**
* 更新用户状态
*/
@PutMapping("/{id}/status/{status}")
public Result<Boolean> updateUserStatus(@PathVariable Long id, @PathVariable Integer status) {
boolean result = userService.updateUserStatus(id, status);
return Result.success(result);
}
/**
* 删除用户
*/
@DeleteMapping("/{id}")
public Result<Boolean> deleteUser(@PathVariable Long id) {
boolean result = userService.deleteUser(id);
return Result.success(result);
}
/**
* 修改密码
*/
@PutMapping("/password")
public Result<Boolean> updatePassword(@RequestParam Long id,
@RequestParam String oldPassword,
@RequestParam String newPassword) {
boolean result = userService.updatePassword(id, oldPassword, newPassword);
return Result.success(result);
}
/**
* 获取用户列表
*/
@GetMapping("/list")
public Result<List<UserDTO>> getUserList(User user) {
List<UserDTO> userList = userService.getUserList(user);
return Result.success(userList);
}
}
backend\src\main\java\com\rental\controller\VerificationController.java
package com.rental.controller;
import com.rental.dto.LandlordVerificationDTO;
import com.rental.dto.Result;
import com.rental.dto.StudentVerificationDTO;
import com.rental.entity.LandlordVerification;
import com.rental.entity.StudentVerification;
import com.rental.service.VerificationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
/**
* 认证控制器
*/
@RestController
@RequestMapping("/api/verification")
public class VerificationController {
@Autowired
private VerificationService verificationService;
/**
* 提交学生认证
*/
@PostMapping("/student")
public Result<Boolean> submitStudentVerification(@RequestBody @Valid StudentVerificationDTO verificationDTO) {
boolean result = verificationService.submitStudentVerification(verificationDTO);
return Result.success(result);
}
/**
* 提交房东认证
*/
@PostMapping("/landlord")
public Result<Boolean> submitLandlordVerification(@RequestBody @Valid LandlordVerificationDTO verificationDTO) {
boolean result = verificationService.submitLandlordVerification(verificationDTO);
return Result.success(result);
}
/**
* 获取用户的学生认证信息
*/
@GetMapping("/student/user/{userId}")
public Result<StudentVerification> getStudentVerification(@PathVariable Long userId) {
StudentVerification verification = verificationService.getStudentVerificationByUserId(userId);
return Result.success(verification);
}
/**
* 获取用户的房东认证信息
*/
@GetMapping("/landlord/user/{userId}")
public Result<LandlordVerification> getLandlordVerification(@PathVariable Long userId) {
LandlordVerification verification = verificationService.getLandlordVerificationByUserId(userId);
return Result.success(verification);
}
/**
* 获取学生认证列表
*/
@GetMapping("/student/list")
public Result<List<StudentVerification>> getStudentVerificationList(StudentVerification verification) {
List<StudentVerification> verificationList = verificationService.getStudentVerificationList(verification);
return Result.success(verificationList);
}
/**
* 获取房东认证列表
*/
@GetMapping("/landlord/list")
public Result<List<LandlordVerification>> getLandlordVerificationList(LandlordVerification verification) {
List<LandlordVerification> verificationList = verificationService.getLandlordVerificationList(verification);
return Result.success(verificationList);
}
/**
* 审核学生认证
*/
@PutMapping("/student/{id}/audit")
public Result<Boolean> auditStudentVerification(@PathVariable Long id,
@RequestParam Integer status,
@RequestParam(required = false) String remark) {
boolean result = verificationService.auditStudentVerification(id, status, remark);
return Result.success(result);
}
/**
* 审核房东认证
*/
@PutMapping("/landlord/{id}/audit")
public Result<Boolean> auditLandlordVerification(@PathVariable Long id,
@RequestParam Integer status,
@RequestParam(required = false) String remark) {
boolean result = verificationService.auditLandlordVerification(id, status, remark);
return Result.success(result);
}
}
backend\src\main\java\com\rental\controller\ViewingFeedbackController.java
package com.rental.controller;
import com.rental.dto.FeedbackDTO;
import com.rental.entity.ViewingFeedback;
import com.rental.dto.Result;
import com.rental.service.ViewingFeedbackService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
/**
* 看房反馈控制器
*/
@RestController
@RequestMapping("/feedback")
public class ViewingFeedbackController {
@Autowired
private ViewingFeedbackService viewingFeedbackService;
/**
* 提交看房反馈
*/
@PostMapping("/submit")
public Result<ViewingFeedback> submitFeedback(@RequestBody @Valid FeedbackDTO feedbackDTO, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return viewingFeedbackService.submitFeedback(feedbackDTO, userId);
}
/**
* 更新看房反馈
*/
@PutMapping("/update/{id}")
public Result<Void> updateFeedback(@PathVariable("id") Long feedbackId, @RequestBody @Valid FeedbackDTO feedbackDTO, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return viewingFeedbackService.updateFeedback(feedbackId, feedbackDTO, userId);
}
/**
* 删除看房反馈
*/
@DeleteMapping("/delete/{id}")
public Result<Void> deleteFeedback(@PathVariable("id") Long feedbackId, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return viewingFeedbackService.deleteFeedback(feedbackId, userId);
}
/**
* 设置反馈是否公开
*/
@PutMapping("/public/{id}")
public Result<Void> setFeedbackPublic(@PathVariable("id") Long feedbackId, @RequestParam("isPublic") Integer isPublic, HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return viewingFeedbackService.setFeedbackPublic(feedbackId, isPublic, userId);
}
/**
* 获取反馈详情
*/
@GetMapping("/detail/{id}")
public Result<ViewingFeedback> getFeedbackDetail(@PathVariable("id") Long feedbackId) {
return viewingFeedbackService.getFeedbackById(feedbackId);
}
/**
* 获取用户的反馈列表
*/
@GetMapping("/user")
public Result<List<ViewingFeedback>> getUserFeedbacks(HttpServletRequest request) {
Long userId = (Long) request.getAttribute("userId");
return viewingFeedbackService.getUserFeedbacks(userId);
}
/**
* 获取房源的公开反馈列表
*/
@GetMapping("/house/{houseId}")
public Result<List<ViewingFeedback>> getHousePublicFeedbacks(@PathVariable("houseId") Long houseId) {
return viewingFeedbackService.getHousePublicFeedbacks(houseId);
}
/**
* 获取预约的反馈
*/
@GetMapping("/appointment/{appointmentId}")
public Result<ViewingFeedback> getAppointmentFeedback(@PathVariable("appointmentId") Long appointmentId) {
return viewingFeedbackService.getAppointmentFeedback(appointmentId);
}
}
backend\src\main\java\com\rental\dao\AppointmentDao.java
package com.rental.dao;
import com.rental.entity.Appointment;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
/**
* 预约DAO接口
*/
@Mapper
public interface AppointmentDao {
/**
* 根据ID查询预约
*/
Appointment selectById(Long id);
/**
* 根据用户ID查询预约列表
*/
List<Appointment> selectByUserId(Long userId);
/**
* 根据房东ID查询预约列表
*/
List<Appointment> selectByLandlordId(Long landlordId);
/**
* 根据房源ID查询预约列表
*/
List<Appointment> selectByHouseId(Long houseId);
/**
* 查询指定日期范围内的预约
*/
List<Appointment> selectByDateRange(@Param("startDate") Date startDate, @Param("endDate") Date endDate);
/**
* 查询预约列表
*/
List<Appointment> selectList(Appointment appointment);
/**
* 新增预约
*/
int insert(Appointment appointment);
/**
* 更新预约
*/
int update(Appointment appointment);
/**
* 更新预约状态
*/
int updateStatus(@Param("id") Long id, @Param("status") Integer status);
/**
* 删除预约
*/
int deleteById(Long id);
/**
* 检查时间冲突
*/
int checkTimeConflict(@Param("houseId") Long houseId, @Param("appointmentTime") Date appointmentTime);
}
backend\src\main\java\com\rental\dao\ComparisonDao.java
package com.rental.dao;
import com.rental.entity.Comparison;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* 比较DAO接口
*/
@Repository
public interface ComparisonDao {
/**
* 根据ID查询比较
*
* @param id ID
* @return 比较对象
*/
Comparison selectById(Long id);
/**
* 根据用户ID查询比较列表
*
* @param userId 用户ID
* @return 比较列表
*/
List<Comparison> selectByUserId(Long userId);
/**
* 新增比较
*
* @param comparison 比较对象
* @return 影响行数
*/
int insert(Comparison comparison);
/**
* 更新比较
*
* @param comparison 比较对象
* @return 影响行数
*/
int update(Comparison comparison);
/**
* 删除比较
*
* @param id ID
* @return 影响行数
*/
int deleteById(Long id);
/**
* 根据用户ID删除比较
*
* @param userId 用户ID
* @return 影响行数
*/
int deleteByUserId(Long userId);
}
backend\src\main\java\com\rental\dao\FavoriteDao.java
package com.rental.dao;
import com.rental.entity.Favorite;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 收藏DAO接口
*/
@Mapper
public interface FavoriteDao {
/**
* 根据ID查询收藏
*/
Favorite selectById(Long id);
/**
* 根据用户ID查询收藏列表
*/
List<Favorite> selectByUserId(Long userId);
/**
* 根据用户ID和房源ID查询收藏
*/
Favorite selectByUserIdAndHouseId(@Param("userId") Long userId, @Param("houseId") Long houseId);
/**
* 新增收藏
*/
int insert(Favorite favorite);
/**
* 删除收藏
*/
int deleteById(Long id);
/**
* 根据用户ID和房源ID删除收藏
*/
int deleteByUserIdAndHouseId(@Param("userId") Long userId, @Param("houseId") Long houseId);
}
Frontend Files
backend\src\main\java\com\rental\dao\HouseDao.java
package com.rental.dao;
import com.rental.entity.House;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* 房源DAO接口
*/
@Mapper
public interface HouseDao {
/**
* 根据ID查询房源
*/
House selectById(Long id);
/**
* 根据房东ID查询房源列表
*/
List<House> selectByLandlordId(Long landlordId);
/**
* 查询房源列表
*/
List<House> selectList(House house);
/**
* 搜索房源
*/
List<House> search(Map<String, Object> params);
/**
* 新增房源
*/
int insert(House house);
/**
* 更新房源
*/
int update(House house);
/**
* 更新房源状态
*/
int updateStatus(@Param("id") Long id, @Param("status") Integer status);
/**
* 删除房源
*/
int deleteById(Long id);
/**
* 批量删除房源
*/
int deleteBatchByIds(Long[] ids);
}
backend\src\main\java\com\rental\dao\HouseDetailDao.java
package com.rental.dao;
import com.rental.entity.HouseDetail;
import org.apache.ibatis.annotations.Mapper;
/**
* 房源详情DAO接口
*/
@Mapper
public interface HouseDetailDao {
/**
* 根据ID查询房源详情
*/
HouseDetail selectById(Long id);
/**
* 根据房源ID查询房源详情
*/
HouseDetail selectByHouseId(Long houseId);
/**
* 新增房源详情
*/
int insert(HouseDetail houseDetail);
/**
* 更新房源详情
*/
int update(HouseDetail houseDetail);
/**
* 删除房源详情
*/
int deleteById(Long id);
/**
* 根据房源ID删除房源详情
*/
int deleteByHouseId(Long houseId);
}
backend\src\main\java\com\rental\dao\HouseImageDao.java
package com.rental.dao;
import com.rental.entity.HouseImage;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 房源图片DAO接口
*/
@Mapper
public interface HouseImageDao {
/**
* 根据ID查询房源图片
*/
HouseImage selectById(Long id);
/**
* 根据房源ID查询房源图片列表
*/
List<HouseImage> selectByHouseId(Long houseId);
/**
* 根据房源ID查询封面图片
*/
HouseImage selectCoverByHouseId(Long houseId);
/**
* 新增房源图片
*/
int insert(HouseImage houseImage);
/**
* 批量新增房源图片
*/
int insertBatch(List<HouseImage> houseImages);
/**
* 更新房源图片
*/
int update(HouseImage houseImage);
/**
* 设置房源封面图片
*/
int setCover(@Param("houseId") Long houseId, @Param("imageId") Long imageId);
/**
* 删除房源图片
*/
int deleteById(Long id);
/**
* 根据房源ID删除房源图片
*/
int deleteByHouseId(Long houseId);
}
backend\src\main\java\com\rental\dao\HouseReviewDao.java
package com.rental.dao;
import com.rental.entity.HouseReview;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 房源评价DAO接口
*/
@Mapper
public interface HouseReviewDao {
/**
* 根据ID查询房源评价
*/
HouseReview selectById(Long id);
/**
* 根据房源ID查询房源评价列表
*/
List<HouseReview> selectByHouseId(Long houseId);
/**
* 根据用户ID查询房源评价列表
*/
List<HouseReview> selectByUserId(Long userId);
/**
* 根据房源ID和用户ID查询房源评价
*/
HouseReview selectByHouseIdAndUserId(@Param("houseId") Long houseId, @Param("userId") Long userId);
/**
* 查询房源评价列表
*/
List<HouseReview> selectList(HouseReview review);
/**
* 新增房源评价
*/
int insert(HouseReview review);
/**
* 更新房源评价
*/
int update(HouseReview review);
/**
* 删除房源评价
*/
int deleteById(Long id);
/**
* 计算房源平均评分
*/
Double calculateAverageRating(Long houseId);
}
backend\src\main\java\com\rental\dao\LandlordVerificationDao.java
package com.rental.dao;
import com.rental.entity.LandlordVerification;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 房东认证DAO接口
*/
@Mapper
public interface LandlordVerificationDao {
/**
* 根据ID查询房东认证
*/
LandlordVerification selectById(Long id);
/**
* 根据用户ID查询房东认证
*/
LandlordVerification selectByUserId(Long userId);
/**
* 查询房东认证列表
*/
List<LandlordVerification> selectList(LandlordVerification verification);
/**
* 新增房东认证
*/
int insert(LandlordVerification verification);
/**
* 更新房东认证
*/
int update(LandlordVerification verification);
/**
* 更新房东认证状态
*/
int updateStatus(@Param("id") Long id, @Param("status") Integer status, @Param("remark") String remark);
/**
* 删除房东认证
*/
int deleteById(Long id);
}
backend\src\main\java\com\rental\dao\PermissionDao.java
package com.rental.dao;
import com.rental.entity.Permission;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* 权限DAO接口
*/
@Repository
public interface PermissionDao {
/**
* 根据ID查询权限
*
* @param id 权限ID
* @return 权限对象
*/
Permission selectById(Long id);
/**
* 根据编码查询权限
*
* @param code 权限编码
* @return 权限对象
*/
Permission selectByCode(String code);
/**
* 查询权限列表
*
* @param permission 查询条件
* @return 权限列表
*/
List<Permission> selectList(Permission permission);
/**
* 根据角色ID查询权限列表
*
* @param roleId 角色ID
* @return 权限列表
*/
List<Permission> selectByRoleId(Long roleId);
/**
* 根据用户ID查询权限列表
*
* @param userId 用户ID
* @return 权限列表
*/
List<Permission> selectByUserId(Long userId);
/**
* 新增权限
*
* @param permission 权限对象
* @return 影响行数
*/
int insert(Permission permission);
/**
* 更新权限
*
* @param permission 权限对象
* @return 影响行数
*/
int update(Permission permission);
/**
* 删除权限
*
* @param id 权限ID
* @return 影响行数
*/
int deleteById(Long id);
}
backend\src\main\java\com\rental\dao\ReviewReplyDao.java
package com.rental.dao;
import com.rental.entity.ReviewReply;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* 评价回复DAO接口
*/
@Mapper
public interface ReviewReplyDao {
/**
* 根据ID查询评价回复
*/
ReviewReply selectById(Long id);
/**
* 根据评价ID查询评价回复列表
*/
List<ReviewReply> selectByReviewId(Long reviewId);
/**
* 根据用户ID查询评价回复列表
*/
List<ReviewReply> selectByUserId(Long userId);
/**
* 新增评价回复
*/
int insert(ReviewReply reply);
/**
* 更新评价回复
*/
int update(ReviewReply reply);
/**
* 删除评价回复
*/
int deleteById(Long id);
}
2.4 MyBatis Mapper XML Files
backend\src\main\java\com\rental\dao\RoleDao.java
package com.rental.dao;
import com.rental.entity.Role;
import org.springframework.stereotype.Repository;
import java.util.List;
/**
* 角色DAO接口
*/
@Repository
public interface RoleDao {
/**
* 根据ID查询角色
*
* @param id 角色ID
* @return 角色对象
*/
Role selectById(Long id);
/**
* 根据编码查询角色
*
* @param code 角色编码
* @return 角色对象
*/
Role selectByCode(String code);
/**
* 查询角色列表
*
* @param role 查询条件
* @return 角色列表
*/
List<Role> selectList(Role role);
/**
* 根据用户ID查询角色列表
*
* @param userId 用户ID
* @return 角色列表
*/
List<Role> selectByUserId(Long userId);
/**
* 新增角色
*
* @param role 角色对象
* @return 影响行数
*/
int insert(Role role);
/**
* 更新角色
*
* @param role 角色对象
* @return 影响行数
*/
int update(Role role);
/**
* 删除角色
*
* @param id 角色ID
* @return 影响行数
*/
int deleteById(Long id);
}
backend\src\main\java\com\rental\dao\StudentVerificationDao.java
package com.rental.dao;
import com.rental.entity.StudentVerification;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 学生认证DAO接口
*/
@Mapper
public interface StudentVerificationDao {
/**
* 根据ID查询学生认证
*/
StudentVerification selectById(Long id);
/**
* 根据用户ID查询学生认证
*/
StudentVerification selectByUserId(Long userId);
/**
* 查询学生认证列表
*/
List<StudentVerification> selectList(StudentVerification verification);
/**
* 新增学生认证
*/
int insert(StudentVerification verification);
/**
* 更新学生认证
*/
int update(StudentVerification verification);
/**
* 更新学生认证状态
*/
int updateStatus(@Param("id") Long id, @Param("status") Integer status, @Param("remark") String remark);
/**
* 删除学生认证
*/
int deleteById(Long id);
}
backend\src\main\java\com\rental\dao\UserDao.java
package com.rental.dao;
import com.rental.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 用户DAO接口
*/
@Mapper
public interface UserDao {
/**
* 根据ID查询用户
*/
User selectById(Long id);
/**
* 根据用户名查询用户
*/
User selectByUsername(String username);
/**
* 根据手机号查询用户
*/
User selectByPhone(String phone);
/**
* 查询用户列表
*/
List<User> selectList(User user);
/**
* 新增用户
*/
int insert(User user);
/**
* 更新用户
*/
int update(User user);
/**
* 更新用户状态
*/
int updateStatus(@Param("id") Long id, @Param("status") Integer status);
/**
* 删除用户
*/
int deleteById(Long id);
/**
* 新增用户角色关联
*/
int insertUserRole(@Param("userId") Long userId, @Param("roleId") Long roleId);
/**
* 删除用户角色关联
*/
int deleteUserRole(Long userId);
}
backend\src\main\java\com\rental\dao\ViewingFeedbackDao.java
package com.rental.dao;
import com.rental.entity.ViewingFeedback;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 看房反馈DAO接口
*/
@Mapper
public interface ViewingFeedbackDao {
/**
* 根据ID查询看房反馈
*/
ViewingFeedback selectById(Long id);
/**
* 根据预约ID查询看房反馈
*/
ViewingFeedback selectByAppointmentId(Long appointmentId);
/**
* 根据用户ID查询看房反馈列表
*/
List<ViewingFeedback> selectByUserId(Long userId);
/**
* 根据房源ID查询公开的看房反馈列表
*/
List<ViewingFeedback> selectPublicByHouseId(Long houseId);
/**
* 查询看房反馈列表
*/
List<ViewingFeedback> selectList(ViewingFeedback feedback);
/**
* 新增看房反馈
*/
int insert(ViewingFeedback feedback);
/**
* 更新看房反馈
*/
int update(ViewingFeedback feedback);
/**
* 更新是否公开
*/
int updateIsPublic(@Param("id") Long id, @Param("isPublic") Integer isPublic);
/**
* 删除看房反馈
*/
int deleteById(Long id);
}
backend\src\main\java\com\rental\dto\AppointmentDTO.java
package com.rental.dto;
import lombok.Data;
import javax.validation.constraints.Future;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import java.util.Date;
/**
* 预约DTO
*/
@Data
public class AppointmentDTO {
/**
* 房源ID
*/
@NotNull(message = "房源ID不能为空")
private Long houseId;
/**
* 预约时间
*/
@NotNull(message = "预约时间不能为空")
@Future(message = "预约时间必须是将来的时间")
private Date appointmentTime;
/**
* 联系人姓名
*/
@NotBlank(message = "联系人姓名不能为空")
private String contactName;
/**
* 联系电话
*/
@NotBlank(message = "联系电话不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号码格式不正确")
private String contactPhone;
/**
* 预约备注
*/
private String appointmentNotes;
}
backend\src\main\java\com\rental\dto\FeedbackDTO.java
package com.rental.dto;
import lombok.Data;
import javax.validation.constraints.*;
/**
* 看房反馈DTO
*/
@Data
public class FeedbackDTO {
/**
* 预约ID
*/
@NotNull(message = "预约ID不能为空")
private Long appointmentId;
/**
* 反馈内容
*/
@NotBlank(message = "反馈内容不能为空")
@Size(min = 10, max = 500, message = "反馈内容长度必须在10-500个字符之间")
private String feedbackContent;
/**
* 满意度:1-5星
*/
@NotNull(message = "满意度不能为空")
@Min(value = 1, message = "满意度最小为1星")
@Max(value = 5, message = "满意度最大为5星")
private Integer satisfactionLevel;
/**
* 是否公开:0-私密,1-公开
*/
@NotNull(message = "是否公开不能为空")
private Integer isPublic;
}
backend\src\main\java\com\rental\dto\HouseDetailDTO.java
package com.rental.dto;
import lombok.Data;
import java.io.Serializable;
/**
* 房源详情DTO
*/
@Data
public class HouseDetailDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 房源ID
*/
private Long houseId;
/**
* 房屋类型:1-普通住宅,2-公寓,3-别墅,4-其他
*/
private Integer houseCategory;
/**
* 出租方式:1-整租,2-合租
*/
private Integer rentType;
/**
* 支付方式:1-月付,2-季付,3-半年付,4-年付
*/
private Integer paymentType;
/**
* 是否有电梯:0-无,1-有
*/
private Integer hasElevator;
/**
* 供暖方式:1-集中供暖,2-自采暖,3-无供暖
*/
private Integer heatingType;
/**
* 水费
*/
private Double waterFee;
/**
* 电费
*/
private Double electricityFee;
/**
* 燃气费
*/
private Double gasFee;
/**
* 网费
*/
private Double internetFee;
/**
* 物业费
*/
private Double propertyFee;
/**
* 车位:0-无,1-有
*/
private Integer hasParking;
/**
* 入住时间
*/
private String checkInTime;
/**
* 最短租期
*/
private String minRentPeriod;
/**
* 最长租期
*/
private String maxRentPeriod;
/**
* 配套设施,逗号分隔:1-床,2-衣柜,3-沙发,4-电视,5-冰箱,6-洗衣机,7-空调,8-热水器,9-宽带,10-暖气,11-燃气灶,12-独立卫生间,13-阳台
*/
private String facilities;
/**
* 交通状况
*/
private String transportation;
/**
* 周边配套
*/
private String surroundings;
/**
* 详细描述
*/
private String description;
}
backend\src\main\java\com\rental\dto\HouseDTO.java
package com.rental.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* 房源DTO
*/
@Data
public class HouseDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 房源ID
*/
private Long id;
/**
* 房东ID
*/
@NotNull(message = "房东ID不能为空")
private Long landlordId;
/**
* 标题
*/
@NotBlank(message = "标题不能为空")
private String title;
/**
* 价格
*/
@NotNull(message = "价格不能为空")
private Double price;
/**
* 面积
*/
@NotNull(message = "面积不能为空")
private Double area;
/**
* 户型
*/
@NotBlank(message = "户型不能为空")
private String houseType;
/**
* 楼层
*/
private String floor;
/**
* 朝向
*/
private String orientation;
/**
* 装修
*/
private String decoration;
/**
* 小区
*/
@NotBlank(message = "小区不能为空")
private String community;
/**
* 地址
*/
@NotBlank(message = "地址不能为空")
private String address;
/**
* 经度
*/
private Double longitude;
/**
* 纬度
*/
private Double latitude;
/**
* 联系人
*/
@NotBlank(message = "联系人不能为空")
private String contact;
/**
* 联系电话
*/
@NotBlank(message = "联系电话不能为空")
private String contactPhone;
/**
* 状态:0-下架,1-上架
*/
private Integer status;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
/**
* 房源详情
*/
private HouseDetailDTO detail;
/**
* 房源图片列表
*/
private List<String> images;
}
backend\src\main\java\com\rental\dto\HouseSearchDTO.java
package com.rental.dto;
import lombok.Data;
import java.io.Serializable;
/**
* 房源搜索DTO
*/
@Data
public class HouseSearchDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 关键词
*/
private String keyword;
/**
* 最低价格
*/
private Double minPrice;
/**
* 最高价格
*/
private Double maxPrice;
/**
* 户型
*/
private String houseType;
/**
* 最小面积
*/
private Double minArea;
/**
* 最大面积
*/
private Double maxArea;
/**
* 朝向
*/
private String orientation;
/**
* 装修
*/
private String decoration;
/**
* 房屋类型:1-普通住宅,2-公寓,3-别墅,4-其他
*/
private Integer houseCategory;
/**
* 出租方式:1-整租,2-合租
*/
private Integer rentType;
/**
* 是否有电梯:0-无,1-有
*/
private Integer hasElevator;
/**
* 供暖方式:1-集中供暖,2-自采暖,3-无供暖
*/
private Integer heatingType;
/**
* 配套设施,逗号分隔:1-床,2-衣柜,3-沙发,4-电视,5-冰箱,6-洗衣机,7-空调,8-热水器,9-宽带,10-暖气,11-燃气灶,12-独立卫生间,13-阳台
*/
private String facilities;
/**
* 当前页码
*/
private Integer pageNum = 1;
/**
* 每页数量
*/
private Integer pageSize = 10;
}
backend\src\main\java\com\rental\dto\LandlordVerificationDTO.java
package com.rental.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* 房东认证DTO
*/
@Data
public class LandlordVerificationDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
@NotNull(message = "用户ID不能为空")
private Long userId;
/**
* 真实姓名
*/
@NotBlank(message = "真实姓名不能为空")
private String realName;
/**
* 身份证号
*/
@NotBlank(message = "身份证号不能为空")
private String idCard;
/**
* 身份证正面照片
*/
@NotBlank(message = "身份证正面照片不能为空")
private String idCardFrontImg;
/**
* 身份证背面照片
*/
@NotBlank(message = "身份证背面照片不能为空")
private String idCardBackImg;
/**
* 手持身份证照片
*/
@NotBlank(message = "手持身份证照片不能为空")
private String idCardHandImg;
}
backend\src\main\java\com\rental\dto\LoginDTO.java
package com.rental.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import java.io.Serializable;
/**
* 登录请求DTO
*/
@Data
public class LoginDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户名/手机号
*/
@NotBlank(message = "用户名不能为空")
private String username;
/**
* 密码
*/
@NotBlank(message = "密码不能为空")
private String password;
}
backend\src\main\java\com\rental\dto\PageResult.java
package com.rental.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
* 分页结果
*/
@Data
public class PageResult<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 总记录数
*/
private Long total;
/**
* 当前页码
*/
private Integer pageNum;
/**
* 每页数量
*/
private Integer pageSize;
/**
* 总页数
*/
private Integer pages;
/**
* 数据列表
*/
private List<T> list;
/**
* 构造方法
*/
public PageResult() {
}
/**
* 构造方法
*/
public PageResult(Long total, List<T> list) {
this.total = total;
this.list = list;
}
/**
* 构造方法
*/
public PageResult(Long total, Integer pageNum, Integer pageSize, List<T> list) {
this.total = total;
this.pageNum = pageNum;
this.pageSize = pageSize;
this.list = list;
this.pages = (int) Math.ceil((double) total / pageSize);
}
}
backend\src\main\java\com\rental\dto\RegisterDTO.java
package com.rental.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.Pattern;
import java.io.Serializable;
/**
* 注册请求DTO
*/
@Data
public class RegisterDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户名
*/
@NotBlank(message = "用户名不能为空")
@Pattern(regexp = "^[a-zA-Z0-9_]{4,16}$", message = "用户名必须为4-16位字母、数字或下划线")
private String username;
/**
* 密码
*/
@NotBlank(message = "密码不能为空")
@Pattern(regexp = "^[a-zA-Z0-9_]{6,20}$", message = "密码必须为6-20位字母、数字或下划线")
private String password;
/**
* 手机号
*/
@NotBlank(message = "手机号不能为空")
@Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
private String phone;
/**
* 角色:STUDENT-学生,LANDLORD-房东
*/
@NotBlank(message = "角色不能为空")
private String role;
}
backend\src\main\java\com\rental\dto\ReplyDTO.java
package com.rental.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* 评价回复DTO
*/
@Data
public class ReplyDTO {
/**
* 评价ID
*/
@NotNull(message = "评价ID不能为空")
private Long reviewId;
/**
* 回复内容
*/
@NotBlank(message = "回复内容不能为空")
@Size(min = 5, max = 200, message = "回复内容长度必须在5-200个字符之间")
private String content;
}
2.3 DAO Interfaces
backend\src\main\java\com\rental\dto\Result.java
package com.rental.dto;
import lombok.Data;
import java.io.Serializable;
/**
* 统一返回结果
*/
@Data
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 状态码
*/
private Integer code;
/**
* 消息
*/
private String message;
/**
* 数据
*/
private T data;
/**
* 成功
*/
public static <T> Result<T> success() {
return success(null);
}
/**
* 成功
*/
public static <T> Result<T> success(T data) {
Result<T> result = new Result<>();
result.setCode(200);
result.setMessage("操作成功");
result.setData(data);
return result;
}
/**
* 失败
*/
public static <T> Result<T> error() {
return error(500, "操作失败");
}
/**
* 失败
*/
public static <T> Result<T> error(String message) {
return error(500, message);
}
/**
* 失败
*/
public static <T> Result<T> error(Integer code, String message) {
Result<T> result = new Result<>();
result.setCode(code);
result.setMessage(message);
return result;
}
}
backend\src\main\java\com\rental\dto\ReviewDTO.java
package com.rental.dto;
import lombok.Data;
import javax.validation.constraints.*;
import java.util.List;
/**
* 房源评价DTO
*/
@Data
public class ReviewDTO {
/**
* 房源ID
*/
@NotNull(message = "房源ID不能为空")
private Long houseId;
/**
* 评价内容
*/
@NotBlank(message = "评价内容不能为空")
@Size(min = 10, max = 500, message = "评价内容长度必须在10-500个字符之间")
private String content;
/**
* 总体评分:1-5星
*/
@NotNull(message = "总体评分不能为空")
@Min(value = 1, message = "评分最小为1星")
@Max(value = 5, message = "评分最大为5星")
private Integer rating;
/**
* 位置评分:1-5星
*/
@NotNull(message = "位置评分不能为空")
@Min(value = 1, message = "评分最小为1星")
@Max(value = 5, message = "评分最大为5星")
private Integer locationRating;
/**
* 清洁度评分:1-5星
*/
@NotNull(message = "清洁度评分不能为空")
@Min(value = 1, message = "评分最小为1星")
@Max(value = 5, message = "评分最大为5星")
private Integer cleanlinessRating;
/**
* 性价比评分:1-5星
*/
@NotNull(message = "性价比评分不能为空")
@Min(value = 1, message = "评分最小为1星")
@Max(value = 5, message = "评分最大为5星")
private Integer valueRating;
/**
* 房东评分:1-5星
*/
@NotNull(message = "房东评分不能为空")
@Min(value = 1, message = "评分最小为1星")
@Max(value = 5, message = "评分最大为5星")
private Integer landlordRating;
/**
* 评价图片
*/
private List<String> images;
}
backend\src\main\java\com\rental\dto\StudentVerificationDTO.java
package com.rental.dto;
import lombok.Data;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.io.Serializable;
/**
* 学生认证DTO
*/
@Data
public class StudentVerificationDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
@NotNull(message = "用户ID不能为空")
private Long userId;
/**
* 学号
*/
@NotBlank(message = "学号不能为空")
private String studentId;
/**
* 学校
*/
@NotBlank(message = "学校不能为空")
private String school;
/**
* 学院
*/
private String college;
/**
* 专业
*/
private String major;
/**
* 入学年份
*/
private Integer admissionYear;
/**
* 学生证照片
*/
@NotBlank(message = "学生证照片不能为空")
private String studentCardImg;
}
backend\src\main\java\com\rental\dto\UserDTO.java
package com.rental.dto;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* 用户DTO
*/
@Data
public class UserDTO implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
private Long id;
/**
* 用户名
*/
private String username;
/**
* 真实姓名
*/
private String realName;
/**
* 手机号
*/
private String phone;
/**
* 邮箱
*/
private String email;
/**
* 头像
*/
private String avatar;
/**
* 性别:0-女,1-男
*/
private Integer gender;
/**
* 角色:STUDENT-学生,LANDLORD-房东,ADMIN-管理员
*/
private String role;
/**
* 状态:0-禁用,1-正常
*/
private Integer status;
/**
* 创建时间
*/
private Date createTime;
/**
* 角色列表
*/
private List<String> roles;
/**
* 权限列表
*/
private List<String> permissions;
/**
* 认证状态:0-未认证,1-已认证,2-认证中,3-认证失败
*/
private Integer verificationStatus;
/**
* token
*/
private String token;
}
backend\src\main\java\com\rental\entity\Appointment.java
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 预约看房实体类
*/
@Data
public class Appointment implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 预约ID
*/
private Long id;
/**
* 房源ID
*/
private Long houseId;
/**
* 用户ID
*/
private Long userId;
/**
* 房东ID
*/
private Long landlordId;
/**
* 预约时间
*/
private Date appointmentTime;
/**
* 联系人姓名
*/
private String contactName;
/**
* 联系电话
*/
private String contactPhone;
/**
* 预约备注
*/
private String appointmentNotes;
/**
* 状态:0-待确认,1-已确认,2-已取消,3-已完成
*/
private Integer status;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
backend\src\main\java\com\rental\entity\Comparison.java
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 比较实体类
*/
@Data
public class Comparison implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 用户ID
*/
private Long userId;
/**
* 房源ID列表,逗号分隔
*/
private String houseIds;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
backend\src\main\java\com\rental\entity\Favorite.java
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 收藏实体类
*/
@Data
public class Favorite implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 用户ID
*/
private Long userId;
/**
* 房源ID
*/
private Long houseId;
/**
* 创建时间
*/
private Date createTime;
}
DAO Interfaces
backend\src\main\java\com\rental\entity\House.java
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 房源实体类
*/
@Data
public class House implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 房源ID
*/
private Long id;
/**
* 房东ID
*/
private Long landlordId;
/**
* 标题
*/
private String title;
/**
* 租金
*/
private BigDecimal price;
/**
* 面积
*/
private BigDecimal area;
/**
* 户型
*/
private String houseType;
/**
* 楼层
*/
private String floor;
/**
* 朝向
*/
private String orientation;
/**
* 装修
*/
private String decoration;
/**
* 小区名称
*/
private String community;
/**
* 详细地址
*/
private String address;
/**
* 经度
*/
private BigDecimal longitude;
/**
* 纬度
*/
private BigDecimal latitude;
/**
* 联系人
*/
private String contact;
/**
* 联系电话
*/
private String contactPhone;
/**
* 状态:0-待审核,1-已上架,2-已下架,3-已出租
*/
private Integer status;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
backend\src\main\java\com\rental\entity\HouseDetail.java
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 房源详情实体类
*/
@Data
public class HouseDetail implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 房源ID
*/
private Long houseId;
/**
* 房源类别:整租、合租
*/
private String houseCategory;
/**
* 出租方式:月付、季付、半年付、年付
*/
private String rentType;
/**
* 付款方式:押一付一、押一付三、押二付三等
*/
private String paymentType;
/**
* 是否有电梯:0-无,1-有
*/
private Integer hasElevator;
/**
* 供暖方式
*/
private String heatingType;
/**
* 水费
*/
private String waterFee;
/**
* 电费
*/
private String electricityFee;
/**
* 燃气费
*/
private String gasFee;
/**
* 网费
*/
private String internetFee;
/**
* 物业费
*/
private String propertyFee;
/**
* 是否有停车位:0-无,1-有
*/
private Integer hasParking;
/**
* 入住时间
*/
private Date checkInTime;
/**
* 最短租期(月)
*/
private Integer minRentPeriod;
/**
* 最长租期(月)
*/
private Integer maxRentPeriod;
/**
* 配套设施
*/
private String facilities;
/**
* 交通情况
*/
private String transportation;
/**
* 周边配套
*/
private String surroundings;
/**
* 房源描述
*/
private String description;
}
backend\src\main\java\com\rental\entity\HouseImage.java
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 房源图片实体类
*/
@Data
public class HouseImage implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 房源ID
*/
private Long houseId;
/**
* 图片URL
*/
private String url;
/**
* 是否封面:0-否,1-是
*/
private Integer isCover;
/**
* 排序
*/
private Integer sort;
/**
* 创建时间
*/
private Date createTime;
}
backend\src\main\java\com\rental\entity\HouseReview.java
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 房源评价实体类
*/
@Data
public class HouseReview implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 评价ID
*/
private Long id;
/**
* 房源ID
*/
private Long houseId;
/**
* 用户ID
*/
private Long userId;
/**
* 评价内容
*/
private String content;
/**
* 评分:1-5星
*/
private Integer rating;
/**
* 位置评分:1-5星
*/
private Integer locationRating;
/**
* 清洁度评分:1-5星
*/
private Integer cleanlinessRating;
/**
* 性价比评分:1-5星
*/
private Integer valueRating;
/**
* 房东评分:1-5星
*/
private Integer landlordRating;
/**
* 评价图片,多个图片用逗号分隔
*/
private String images;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
backend\src\main\java\com\rental\entity\LandlordVerification.java
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 房东认证实体类
*/
@Data
public class LandlordVerification implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 用户ID
*/
private Long userId;
/**
* 真实姓名
*/
private String realName;
/**
* 身份证号
*/
private String idCard;
/**
* 身份证正面照
*/
private String idCardFront;
/**
* 身份证背面照
*/
private String idCardBack;
/**
* 房产证照片
*/
private String houseCertificate;
/**
* 状态:0-待审核,1-已通过,2-已拒绝
*/
private Integer status;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
backend\src\main\java\com\rental\entity\Permission.java
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 权限实体类
*/
@Data
public class Permission implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 权限ID
*/
private Long id;
/**
* 权限名称
*/
private String name;
/**
* 权限编码
*/
private String code;
/**
* 权限描述
*/
private String description;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
backend\src\main\java\com\rental\entity\ReviewReply.java
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 评价回复实体类
*/
@Data
public class ReviewReply implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 回复ID
*/
private Long id;
/**
* 评价ID
*/
private Long reviewId;
/**
* 用户ID
*/
private Long userId;
/**
* 回复内容
*/
private String content;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
2.2 DTO Classes
backend\src\main\java\com\rental\entity\Role.java
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 角色实体类
*/
@Data
public class Role implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 角色ID
*/
private Long id;
/**
* 角色名称
*/
private String name;
/**
* 角色编码
*/
private String code;
/**
* 角色描述
*/
private String description;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
backend\src\main\java\com\rental\entity\StudentVerification.java
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 学生认证实体类
*/
@Data
public class StudentVerification implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 用户ID
*/
private Long userId;
/**
* 学号
*/
private String studentId;
/**
* 学校
*/
private String school;
/**
* 学院
*/
private String college;
/**
* 专业
*/
private String major;
/**
* 身份证号
*/
private String idCard;
/**
* 身份证正面照
*/
private String idCardFront;
/**
* 身份证背面照
*/
private String idCardBack;
/**
* 学生证照片
*/
private String studentCard;
/**
* 状态:0-待审核,1-已通过,2-已拒绝
*/
private Integer status;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
backend\src\main\java\com\rental\entity\User.java
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 用户实体类
*/
@Data
public class User implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 用户ID
*/
private Long id;
/**
* 用户名
*/
private String username;
/**
* 密码
*/
private String password;
/**
* 真实姓名
*/
private String realName;
/**
* 手机号码
*/
private String phone;
/**
* 邮箱
*/
private String email;
/**
* 头像
*/
private String avatar;
/**
* 性别:0-未知,1-男,2-女
*/
private Integer gender;
/**
* 状态:0-禁用,1-正常
*/
private Integer status;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
2. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\entity\Role.java
java
CopyInsert
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 角色实体类
*/
@Data
public class Role implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 角色ID
*/
private Long id;
/**
* 角色名称
*/
private String name;
/**
* 角色编码
*/
private String code;
/**
* 角色描述
*/
private String description;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
3. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\entity\House.java
java
CopyInsert
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 房源实体类
*/
@Data
public class House implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 房源ID
*/
private Long id;
/**
* 房东ID
*/
private Long landlordId;
/**
* 标题
*/
private String title;
/**
* 租金
*/
private BigDecimal price;
/**
* 面积
*/
private BigDecimal area;
/**
* 户型
*/
private String houseType;
/**
* 楼层
*/
private String floor;
/**
* 朝向
*/
private String orientation;
/**
* 装修
*/
private String decoration;
/**
* 小区名称
*/
private String community;
/**
* 详细地址
*/
private String address;
/**
* 经度
*/
private BigDecimal longitude;
/**
* 纬度
*/
private BigDecimal latitude;
/**
* 联系人
*/
private String contact;
/**
* 联系电话
*/
private String contactPhone;
/**
* 状态:0-待审核,1-已上架,2-已下架,3-已出租
*/
private Integer status;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
4. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\entity\HouseDetail.java
java
CopyInsert
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 房源详情实体类
*/
@Data
public class HouseDetail implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 房源ID
*/
private Long houseId;
/**
* 房源类别:整租、合租
*/
private String houseCategory;
/**
* 出租方式:月付、季付、半年付、年付
*/
private String rentType;
/**
* 付款方式:押一付一、押一付三、押二付三等
*/
private String paymentType;
/**
* 是否有电梯:0-无,1-有
*/
private Integer hasElevator;
/**
* 供暖方式
*/
private String heatingType;
/**
* 水费
*/
private String waterFee;
/**
* 电费
*/
private String electricityFee;
/**
* 燃气费
*/
private String gasFee;
/**
* 网费
*/
private String internetFee;
/**
* 物业费
*/
private String propertyFee;
/**
* 是否有停车位:0-无,1-有
*/
private Integer hasParking;
/**
* 入住时间
*/
private Date checkInTime;
/**
* 最短租期(月)
*/
private Integer minRentPeriod;
/**
* 最长租期(月)
*/
private Integer maxRentPeriod;
/**
* 配套设施
*/
private String facilities;
/**
* 交通情况
*/
private String transportation;
/**
* 周边配套
*/
private String surroundings;
/**
* 房源描述
*/
private String description;
}
5. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\entity\HouseImage.java
java
CopyInsert
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 房源图片实体类
*/
@Data
public class HouseImage implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 房源ID
*/
private Long houseId;
/**
* 图片URL
*/
private String url;
/**
* 是否封面:0-否,1-是
*/
private Integer isCover;
/**
* 排序
*/
private Integer sort;
/**
* 创建时间
*/
private Date createTime;
}
6. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\entity\StudentVerification.java
java
CopyInsert
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 学生认证实体类
*/
@Data
public class StudentVerification implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 用户ID
*/
private Long userId;
/**
* 学号
*/
private String studentId;
/**
* 学校
*/
private String school;
/**
* 学院
*/
private String college;
/**
* 专业
*/
private String major;
/**
* 身份证号
*/
private String idCard;
/**
* 身份证正面照
*/
private String idCardFront;
/**
* 身份证背面照
*/
private String idCardBack;
/**
* 学生证照片
*/
private String studentCard;
/**
* 状态:0-待审核,1-已通过,2-已拒绝
*/
private Integer status;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
7. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\entity\LandlordVerification.java
java
CopyInsert
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 房东认证实体类
*/
@Data
public class LandlordVerification implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 用户ID
*/
private Long userId;
/**
* 真实姓名
*/
private String realName;
/**
* 身份证号
*/
private String idCard;
/**
* 身份证正面照
*/
private String idCardFront;
/**
* 身份证背面照
*/
private String idCardBack;
/**
* 房产证照片
*/
private String houseCertificate;
/**
* 状态:0-待审核,1-已通过,2-已拒绝
*/
private Integer status;
/**
* 备注
*/
private String remark;
/**
* 创建时间
*/
private Date createTime;
/**
* 更新时间
*/
private Date updateTime;
}
8. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\entity\Favorite.java
java
CopyInsert
package com.rental.entity;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
/**
* 收藏实体类
*/
@Data
public class Favorite implements Serializable {
private static final long serialVersionUID = 1L;
/**
* ID
*/
private Long id;
/**
* 用户ID
*/
private Long userId;
/**
* 房源ID
*/
private Long houseId;
/**
* 创建时间
*/
private Date createTime;
}
DAO Interfaces
9. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\dao\UserDao.java
java
CopyInsert
package com.rental.dao;
import com.rental.entity.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 用户DAO接口
*/
@Mapper
public interface UserDao {
/**
* 根据ID查询用户
*/
User selectById(Long id);
/**
* 根据用户名查询用户
*/
User selectByUsername(String username);
/**
* 根据手机号查询用户
*/
User selectByPhone(String phone);
/**
* 查询用户列表
*/
List<User> selectList(User user);
/**
* 新增用户
*/
int insert(User user);
/**
* 更新用户
*/
int update(User user);
/**
* 更新用户状态
*/
int updateStatus(@Param("id") Long id, @Param("status") Integer status);
/**
* 删除用户
*/
int deleteById(Long id);
/**
* 新增用户角色关联
*/
int insertUserRole(@Param("userId") Long userId, @Param("roleId") Long roleId);
/**
* 删除用户角色关联
*/
int deleteUserRole(Long userId);
}
10. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\dao\HouseDao.java
java
CopyInsert
package com.rental.dao;
import com.rental.entity.House;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
import java.util.Map;
/**
* 房源DAO接口
*/
@Mapper
public interface HouseDao {
/**
* 根据ID查询房源
*/
House selectById(Long id);
/**
* 根据房东ID查询房源列表
*/
List<House> selectByLandlordId(Long landlordId);
/**
* 查询房源列表
*/
List<House> selectList(House house);
/**
* 搜索房源
*/
List<House> search(Map<String, Object> params);
/**
* 新增房源
*/
int insert(House house);
/**
* 更新房源
*/
int update(House house);
/**
* 更新房源状态
*/
int updateStatus(@Param("id") Long id, @Param("status") Integer status);
/**
* 删除房源
*/
int deleteById(Long id);
/**
* 批量删除房源
*/
int deleteBatchByIds(Long[] ids);
}
11. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\dao\HouseDetailDao.java
java
CopyInsert
package com.rental.dao;
import com.rental.entity.HouseDetail;
import org.apache.ibatis.annotations.Mapper;
/**
* 房源详情DAO接口
*/
@Mapper
public interface HouseDetailDao {
/**
* 根据ID查询房源详情
*/
HouseDetail selectById(Long id);
/**
* 根据房源ID查询房源详情
*/
HouseDetail selectByHouseId(Long houseId);
/**
* 新增房源详情
*/
int insert(HouseDetail houseDetail);
/**
* 更新房源详情
*/
int update(HouseDetail houseDetail);
/**
* 删除房源详情
*/
int deleteById(Long id);
/**
* 根据房源ID删除房源详情
*/
int deleteByHouseId(Long houseId);
}
12. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\dao\HouseImageDao.java
java
CopyInsert
package com.rental.dao;
import com.rental.entity.HouseImage;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 房源图片DAO接口
*/
@Mapper
public interface HouseImageDao {
/**
* 根据ID查询房源图片
*/
HouseImage selectById(Long id);
/**
* 根据房源ID查询房源图片列表
*/
List<HouseImage> selectByHouseId(Long houseId);
/**
* 根据房源ID查询封面图片
*/
HouseImage selectCoverByHouseId(Long houseId);
/**
* 新增房源图片
*/
int insert(HouseImage houseImage);
/**
* 批量新增房源图片
*/
int insertBatch(List<HouseImage> houseImages);
/**
* 更新房源图片
*/
int update(HouseImage houseImage);
/**
* 设置房源封面图片
*/
int setCover(@Param("houseId") Long houseId, @Param("imageId") Long imageId);
/**
* 删除房源图片
*/
int deleteById(Long id);
/**
* 根据房源ID删除房源图片
*/
int deleteByHouseId(Long houseId);
}
13. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\dao\StudentVerificationDao.java
java
CopyInsert
package com.rental.dao;
import com.rental.entity.StudentVerification;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 学生认证DAO接口
*/
@Mapper
public interface StudentVerificationDao {
/**
* 根据ID查询学生认证
*/
StudentVerification selectById(Long id);
/**
* 根据用户ID查询学生认证
*/
StudentVerification selectByUserId(Long userId);
/**
* 查询学生认证列表
*/
List<StudentVerification> selectList(StudentVerification verification);
/**
* 新增学生认证
*/
int insert(StudentVerification verification);
/**
* 更新学生认证
*/
int update(StudentVerification verification);
/**
* 更新学生认证状态
*/
int updateStatus(@Param("id") Long id, @Param("status") Integer status, @Param("remark") String remark);
/**
* 删除学生认证
*/
int deleteById(Long id);
}
14. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\dao\LandlordVerificationDao.java
java
CopyInsert
package com.rental.dao;
import com.rental.entity.LandlordVerification;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 房东认证DAO接口
*/
@Mapper
public interface LandlordVerificationDao {
/**
* 根据ID查询房东认证
*/
LandlordVerification selectById(Long id);
/**
* 根据用户ID查询房东认证
*/
LandlordVerification selectByUserId(Long userId);
/**
* 查询房东认证列表
*/
List<LandlordVerification> selectList(LandlordVerification verification);
/**
* 新增房东认证
*/
int insert(LandlordVerification verification);
/**
* 更新房东认证
*/
int update(LandlordVerification verification);
/**
* 更新房东认证状态
*/
int updateStatus(@Param("id") Long id, @Param("status") Integer status, @Param("remark") String remark);
/**
* 删除房东认证
*/
int deleteById(Long id);
}
15. File: d:\htsun\Docs\资料\文章\rental-system\backend\src\main\java\com\rental\dao\FavoriteDao.java
java
CopyInsert
package com.rental.dao;
import com.rental.entity.Favorite;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 收藏DAO接口
*/
@Mapper
public interface FavoriteDao {
/**
* 根据ID查询收藏
*/
Favorite selectById(Long id);
/**
* 根据用户ID查询收藏列表
*/
List<Favorite> selectByUserId(Long userId);
/**
* 根据用户ID和房源ID查询收藏
*/
Favorite selectByUserIdAndHouseId(@Param("userId") Long userId, @Param("houseId") Long houseId);
/**
* 新增收藏
*/
int insert(Favorite favorite);
/**
* 删除收藏
*/
int deleteById(Long id);
/**
* 根据用户ID和房源ID删除收藏
*/
int deleteByUserIdAndHouseId(@Param("userId") Long userId, @Param("houseId") Long houseId);
}
Frontend Files
16. File: d:\htsun\Docs\资料\文章\rental-system\frontend\src\views\house\Detail.vue
vue
CopyInsert
<template>
<div class="house-detail-container">
<!-- 头部导航 -->
<div class="header">
<div class="container">
<div class="logo">大学生租房管理系统</div>
<div class="nav">
<router-link to="/home" class="nav-item">首页</router-link>
<router-link to="/house/map" class="nav-item">地图找房</router-link>
<router-link to="/news" class="nav-item">租房资讯</router-link>
</div>
<div class="user-info">
<template v-if="isLogin">
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link">
{{ username }}<i class="el-icon-arrow-down el-icon--right"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="profile">个人中心</el-dropdown-item>
<el-dropdown-item command="favorite">我的收藏</el-dropdown-item>
<el-dropdown-item v-if="isAdmin" command="admin">管理后台</el-dropdown-item>
<el-dropdown-item v-if="isLandlord" command="landlord">房源管理</el-dropdown-item>
<el-dropdown-item command="logout" divided>退出登录</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<template v-else>
<router-link to="/login" class="login-btn">登录</router-link>
<router-link to="/register" class="register-btn">注册</router-link>
</template>
</div>
</div>
</div>
<!-- 房源详情内容 -->
<div class="detail-content">
<div class="container">
<div class="house-title">
<h1>{{ house.title }}</h1>
<div class="house-tags">
<span class="tag">{{ house.houseType }}</span>
<span class="tag">{{ house.area }}㎡</span>
<span class="tag">{{ house.orientation }}</span>
<span class="tag">{{ house.decoration }}</span>
</div>
</div>
<div class="detail-main">
<!-- 左侧图片 -->
<div class="detail-left">
<div class="house-images">
<el-carousel height="400px">
<el-carousel-item v-for="(image, index) in houseImages" :key="index">
<img :src="image.url" alt="房源图片">
</el-carousel-item>
</el-carousel>
</div>
</div>
<!-- 右侧信息 -->
<div class="detail-right">
<div class="price-info">
<div class="price">
<span class="price-num">{{ house.price }}</span>
<span class="price-unit">元/月</span>
</div>
<div class="price-tags">
<span>押一付三</span>
<span>{{ houseDetail.rentType }}</span>
</div>
</div>
<div class="landlord-info">
<div class="landlord-avatar">
<img src="https://via.placeholder.com/60" alt="房东头像">
</div>
<div class="landlord-detail">
<div class="landlord-name">{{ house.contact }}</div>
<div class="landlord-phone">{{ house.contactPhone }}</div>
</div>
<el-button type="primary" @click="handleContact">联系房东</el-button>
</div>
<div class="action-buttons">
<el-button type="primary" @click="handleAppointment">预约看房</el-button>
<el-button :type="isFavorite ? 'danger' : 'info'" @click="handleFavorite">
<i :class="isFavorite ? 'el-icon-star-on' : 'el-icon-star-off'"></i>
{{ isFavorite ? '已收藏' : '收藏' }}
</el-button>
</div>
</div>
</div>
<!-- 房源详情信息 -->
<div class="detail-info">
<el-tabs v-model="activeTab">
<el-tab-pane label="房源信息" name="info">
<div class="info-section">
<h3>基本信息</h3>
<div class="info-list">
<div class="info-item">
<span class="info-label">房源类型</span>
<span class="info-value">{{ houseDetail.houseCategory }}</span>
</div>
<div class="info-item">
<span class="info-label">户型</span>
<span class="info-value">{{ house.houseType }}</span>
</div>
<div class="info-item">
<span class="info-label">面积</span>
<span class="info-value">{{ house.area }}㎡</span>
</div>
<div class="info-item">
<span class="info-label">楼层</span>
<span class="info-value">{{ house.floor }}</span>
</div>
<div class="info-item">
<span class="info-label">朝向</span>
<span class="info-value">{{ house.orientation }}</span>
</div>
<div class="info-item">
<span class="info-label">装修</span>
<span class="info-value">{{ house.decoration }}</span>
</div>
<div class="info-item">
<span class="info-label">电梯</span>
<span class="info-value">{{ houseDetail.hasElevator === 1 ? '有' : '无' }}</span>
</div>
<div class="info-item">
<span class="info-label">停车位</span>
<span class="info-value">{{ houseDetail.hasParking === 1 ? '有' : '无' }}</span>
</div>
</div>
</div>
<div class="info-section">
<h3>租金信息</h3>
<div class="info-list">
<div class="info-item">
<span class="info-label">租金</span>
<span class="info-value">{{ house.price }}元/月</span>
</div>
<div class="info-item">
<span class="info-label">付款方式</span>
<span class="info-value">{{ houseDetail.paymentType }}</span>
</div>
<div class="info-item">
<span class="info-label">出租方式</span>
<span class="info-value">{{ houseDetail.rentType }}</span>
</div>
<div class="info-item">
<span class="info-label">最短租期</span>
<span class="info-value">{{ houseDetail.minRentPeriod }}个月</span>
</div>
<div class="info-item">
<span class="info-label">入住时间</span>
<span class="info-value">{{ formatDate(houseDetail.checkInTime) }}</span>
</div>
</div>
</div>
<div class="info-section">
<h3>费用信息</h3>
<div class="info-list">
<div class="info-item">
<span class="info-label">水费</span>
<span class="info-value">{{ houseDetail.waterFee }}</span>
</div>
<div class="info-item">
<span class="info-label">电费</span>
<span class="info-value">{{ houseDetail.electricityFee }}</span>
</div>
<div class="info-item">
<span class="info-label">燃气费</span>
<span class="info-value">{{ houseDetail.gasFee }}</span>
</div>
<div class="info-item">
<span class="info-label">网费</span>
<span class="info-value">{{ houseDetail.internetFee }}</span>
</div>
<div class="info-item">
<span class="info-label">物业费</span>
<span class="info-value">{{ houseDetail.propertyFee }}</span>
</div>
</div>
</div>
<div class="info-section">
<h3>房源描述</h3>
<div class="description">
{{ houseDetail.description }}
</div>
</div>
<div class="info-section">
<h3>配套设施</h3>
<div class="facilities">
<el-tag v-for="(item, index) in facilitiesList" :key="index" size="medium">{{ item }}</el-tag>
</div>
</div>
</el-tab-pane>
<el-tab-pane label="位置交通" name="location">
<div class="info-section">
<h3>位置信息</h3>
<div class="location-info">
<div class="address">
<span class="info-label">小区名称</span>
<span class="info-value">{{ house.community }}</span>
</div>
<div class="address">
<span class="info-label">详细地址</span>
<span class="info-value">{{ house.address }}</span>
</div>
</div>
<div class="map-container" id="map" style="height: 400px; margin-top: 20px;"></div>
</div>
<div class="info-section">
<h3>交通情况</h3>
<div class="transportation">
{{ houseDetail.transportation }}
</div>
</div>
<div class="info-section">
<h3>周边配套</h3>
<div class="surroundings">
{{ houseDetail.surroundings }}
</div>
</div>
</el-tab-pane>
</el-tabs>
</div>
</div>
</div>
</div>
</template>
<script>
import { getHouseDetail, getHouseImages } from '@/api/house';
import { addFavorite, cancelFavorite, checkFavorite } from '@/api/favorite';
import { mapGetters } from 'vuex';
import { formatDate } from '@/utils/date';
export default {
name: 'HouseDetail',
data() {
return {
house: {},
houseDetail: {},
houseImages: [],
activeTab: 'info',
isFavorite: false,
facilitiesList: []
};
},
computed: {
...mapGetters(['isLogin', 'username', 'userId', 'isAdmin', 'isLandlord']),
houseId() {
return this.$route.params.id;
}
},
created() {
this.fetchHouseDetail();
this.fetchHouseImages();
if (this.isLogin) {
this.checkIsFavorite();
}
},
methods: {
formatDate,
async fetchHouseDetail() {
try {
const res = await getHouseDetail(this.houseId);
if (res.code === 200) {
this.house = res.data.house;
this.houseDetail = res.data.houseDetail;
// 处理配套设施
if (this.houseDetail.facilities) {
this.facilitiesList = this.houseDetail.facilities.split(',');
}
// 加载地图
this.$nextTick(() => {
this.initMap();
});
}
} catch (error) {
this.$message.error('获取房源详情失败');
console.error(error);
}
},
async fetchHouseImages() {
try {
const res = await getHouseImages(this.houseId);
if (res.code === 200) {
this.houseImages = res.data;
}
} catch (error) {
this.$message.error('获取房源图片失败');
console.error(error);
}
},
async checkIsFavorite() {
try {
const res = await checkFavorite(this.houseId);
if (res.code === 200) {
this.isFavorite = res.data;
}
} catch (error) {
console.error(error);
}
},
async handleFavorite() {
if (!this.isLogin) {
this.$message.warning('请先登录');
this.$router.push(`/login?redirect=/house/detail/${this.houseId}`);
return;
}
try {
if (this.isFavorite) {
const res = await cancelFavorite(this.houseId);
if (res.code === 200) {
this.isFavorite = false;
this.$message.success('取消收藏成功');
}
} else {
const res = await addFavorite(this.houseId);
if (res.code === 200) {
this.isFavorite = true;
this.$message.success('收藏成功');
}
}
} catch (error) {
this.$message.error('操作失败');
console.error(error);
}
},
handleContact() {
if (!this.isLogin) {
this.$message.warning('请先登录');
this.$router.push(`/login?redirect=/house/detail/${this.houseId}`);
return;
}
this.$alert(`联系人:${this.house.contact}<br/>联系电话:${this.house.contactPhone}`, '联系房东', {
dangerouslyUseHTMLString: true,
confirmButtonText: '确定'
});
},
handleAppointment() {
if (!this.isLogin) {
this.$message.warning('请先登录');
this.$router.push(`/login?redirect=/house/detail/${this.houseId}`);
return;
}
this.$message.info('预约功能即将上线,敬请期待');
},
initMap() {
// 此处为地图初始化代码,需要引入地图API
// 例如使用百度地图或高德地图
console.log('初始化地图,经度:', this.house.longitude, '纬度:', this.house.latitude);
},
handleCommand(command) {
switch (command) {
case 'profile':
this.$router.push('/user/profile');
break;
case 'favorite':
this.$router.push('/user/favorite');
break;
case 'admin':
this.$router.push('/admin');
break;
case 'landlord':
this.$router.push('/landlord');
break;
case 'logout':
this.$store.dispatch('logout');
this.$router.push('/login');
break;
}
}
}
};
</script>
<style scoped>
.house-detail-container {
min-height: 100vh;
background-color: #f5f5f5;
}
.header {
background-color: #fff;
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
position: sticky;
top: 0;
z-index: 100;
}
.header .container {
display: flex;
align-items: center;
justify-content: space-between;
height: 60px;
padding: 0 20px;
max-width: 1200px;
margin: 0 auto;
}
.logo {
font-size: 20px;
font-weight: bold;
color: #409EFF;
}
.nav {
display: flex;
}
.nav-item {
margin: 0 15px;
color: #333;
text-decoration: none;
}
.nav-item:hover {
color: #409EFF;
}
.user-info {
display: flex;
align-items: center;
}
.login-btn, .register-btn {
padding: 5px 15px;
margin-left: 10px;
border-radius: 4px;
text-decoration: none;
}
.login-btn {
color: #409EFF;
}
.register-btn {
background-color: #409EFF;
color: #fff;
}
.detail-content {
padding: 20px 0;
}
.container {
max-width: 1200px;
margin: 0 auto;
padding: 0 20px;
}
.house-title {
margin-bottom: 20px;
}
.house-title h1 {
font-size: 24px;
margin-bottom: 10px;
}
.house-tags {
display: flex;
flex-wrap: wrap;
}
.tag {
background-color: #f0f9ff;
color: #409EFF;
padding: 2px 8px;
margin-right: 10px;
border-radius: 4px;
font-size: 12px;
}
.detail-main {
display: flex;
margin-bottom: 30px;
}
.detail-left {
flex: 2;
margin-right: 20px;
}
.detail-right {
flex: 1;
background-color: #fff;
padding: 20px;
border-radius: 4px;
}
.price-info {
margin-bottom: 20px;
padding-bottom: 20px;
border-bottom: 1px solid #eee;
}
.price {
display: flex;
align-items: baseline;
margin-bottom: 10px;
}
.price-num {
font-size: 28px;
color: #ff5a5f;
font-weight: bold;
}
.price-unit {
font-size: 14px;
color: #666;
margin-left: 5px;
}
.price-tags span {
background-color: #fff5f5;
color: #ff5a5f;
padding: 2px 8px;
margin-right: 10px;
border-radius: 4px;
font-size: 12px;
}
.landlord-info {
display: flex;
align-items: center;
margin-bottom: 20px;
padding-bottom: 20px;
border-bottom: 1px solid #eee;
}
.landlord-avatar {
margin-right: 15px;
}
.landlord-avatar img {
width: 60px;
height: 60px;
border-radius: 50%;
}
.landlord-detail {
flex: 1;
}
.landlord-name {
font-size: 16px;
font-weight: bold;
margin-bottom: 5px;
}
.landlord-phone {
color: #666;
}
.action-buttons {
display: flex;
justify-content: space-between;
}
.detail-info {
background-color: #fff;
padding: 20px;
border-radius: 4px;
}
.info-section {
margin-bottom: 30px;
}
.info-section h3 {
font-size: 18px;
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
.info-list {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 15px;
}
.info-item {
display: flex;
}
.info-label {
color: #666;
margin-right: 10px;
min-width: 70px;
}
.info-value {
color: #333;
font-weight: 500;
}
.description, .transportation, .surroundings {
line-height: 1.8;
color: #333;
}
.facilities {
display: flex;
flex-wrap: wrap;
}
.facilities .el-tag {
margin-right: 10px;
margin-bottom: 10px;
}
.location-info {
margin-bottom: 15px;
}
.address {
margin-bottom: 10px;
}
</style>
API Service Files