代码3:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rental.dao.HouseDao">
<resultMap id="BaseResultMap" type="com.rental.entity.House">
<id column="id" property="id"/>
<result column="landlord_id" property="landlordId"/>
<result column="title" property="title"/>
<result column="price" property="price"/>
<result column="area" property="area"/>
<result column="house_type" property="houseType"/>
<result column="floor" property="floor"/>
<result column="orientation" property="orientation"/>
<result column="decoration" property="decoration"/>
<result column="community" property="community"/>
<result column="address" property="address"/>
<result column="longitude" property="longitude"/>
<result column="latitude" property="latitude"/>
<result column="contact" property="contact"/>
<result column="contact_phone" property="contactPhone"/>
<result column="status" property="status"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<sql id="Base_Column_List">
id, landlord_id, title, price, area, house_type, floor, orientation, decoration, community, address,
longitude, latitude, contact, contact_phone, status, create_time, update_time
</sql>
<select id="selectById" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house
where id = #{id}
</select>
<select id="selectByLandlordId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house
where landlord_id = #{landlordId}
order by create_time desc
</select>
<select id="selectList" parameterType="com.rental.entity.House" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house
<where>
<if test="landlordId != null">
and landlord_id = #{landlordId}
</if>
<if test="title != null and title != ''">
and title like concat('%', #{title}, '%')
</if>
<if test="houseType != null and houseType != ''">
and house_type = #{houseType}
</if>
<if test="community != null and community != ''">
and community like concat('%', #{community}, '%')
</if>
<if test="status != null">
and status = #{status}
</if>
</where>
order by create_time desc
</select>
<select id="search" parameterType="java.util.Map" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house
<where>
<if test="keyword != null and keyword != ''">
and (
title like concat('%', #{keyword}, '%')
or community like concat('%', #{keyword}, '%')
or address like concat('%', #{keyword}, '%')
)
</if>
<if test="minPrice != null">
and price >= #{minPrice}
</if>
<if test="maxPrice != null">
and price <= #{maxPrice}
</if>
<if test="minArea != null">
and area >= #{minArea}
</if>
<if test="maxArea != null">
and area <= #{maxArea}
</if>
<if test="houseType != null and houseType != ''">
and house_type = #{houseType}
</if>
<if test="orientation != null and orientation != ''">
and orientation = #{orientation}
</if>
<if test="decoration != null and decoration != ''">
and decoration = #{decoration}
</if>
<if test="status != null">
and status = #{status}
</if>
<if test="status == null">
and status = 1
</if>
</where>
order by
<choose>
<when test="orderBy != null and orderBy == 'price_asc'">
price asc
</when>
<when test="orderBy != null and orderBy == 'price_desc'">
price desc
</when>
<when test="orderBy != null and orderBy == 'area_asc'">
area asc
</when>
<when test="orderBy != null and orderBy == 'area_desc'">
area desc
</when>
<when test="orderBy != null and orderBy == 'time_asc'">
create_time asc
</when>
<otherwise>
create_time desc
</otherwise>
</choose>
</select>
<insert id="insert" parameterType="com.rental.entity.House" useGeneratedKeys="true" keyProperty="id">
insert into house
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="landlordId != null">landlord_id,</if>
<if test="title != null">title,</if>
<if test="price != null">price,</if>
<if test="area != null">area,</if>
<if test="houseType != null">house_type,</if>
<if test="floor != null">floor,</if>
<if test="orientation != null">orientation,</if>
<if test="decoration != null">decoration,</if>
<if test="community != null">community,</if>
<if test="address != null">address,</if>
<if test="longitude != null">longitude,</if>
<if test="latitude != null">latitude,</if>
<if test="contact != null">contact,</if>
<if test="contactPhone != null">contact_phone,</if>
<if test="status != null">status,</if>
create_time,
update_time,
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="landlordId != null">#{landlordId},</if>
<if test="title != null">#{title},</if>
<if test="price != null">#{price},</if>
<if test="area != null">#{area},</if>
<if test="houseType != null">#{houseType},</if>
<if test="floor != null">#{floor},</if>
<if test="orientation != null">#{orientation},</if>
<if test="decoration != null">#{decoration},</if>
<if test="community != null">#{community},</if>
<if test="address != null">#{address},</if>
<if test="longitude != null">#{longitude},</if>
<if test="latitude != null">#{latitude},</if>
<if test="contact != null">#{contact},</if>
<if test="contactPhone != null">#{contactPhone},</if>
<if test="status != null">#{status},</if>
now(),
now(),
</trim>
</insert>
<update id="update" parameterType="com.rental.entity.House">
update house
<set>
<if test="title != null">title = #{title},</if>
<if test="price != null">price = #{price},</if>
<if test="area != null">area = #{area},</if>
<if test="houseType != null">house_type = #{houseType},</if>
<if test="floor != null">floor = #{floor},</if>
<if test="orientation != null">orientation = #{orientation},</if>
<if test="decoration != null">decoration = #{decoration},</if>
<if test="community != null">community = #{community},</if>
<if test="address != null">address = #{address},</if>
<if test="longitude != null">longitude = #{longitude},</if>
<if test="latitude != null">latitude = #{latitude},</if>
<if test="contact != null">contact = #{contact},</if>
<if test="contactPhone != null">contact_phone = #{contactPhone},</if>
<if test="status != null">status = #{status},</if>
update_time = now(),
</set>
where id = #{id}
</update>
<update id="updateStatus">
update house
set status = #{status}, update_time = now()
where id = #{id}
</update>
<delete id="deleteById" parameterType="java.lang.Long">
delete from house
where id = #{id}
</delete>
<delete id="deleteBatchByIds" parameterType="java.lang.Long">
delete from house
where id in
<foreach collection="array" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
backend\src\main\resources\mapper\HouseReviewMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rental.dao.HouseReviewDao">
<resultMap id="BaseResultMap" type="com.rental.entity.HouseReview">
<id column="id" property="id"/>
<result column="house_id" property="houseId"/>
<result column="user_id" property="userId"/>
<result column="content" property="content"/>
<result column="rating" property="rating"/>
<result column="location_rating" property="locationRating"/>
<result column="cleanliness_rating" property="cleanlinessRating"/>
<result column="value_rating" property="valueRating"/>
<result column="landlord_rating" property="landlordRating"/>
<result column="images" property="images"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<sql id="Base_Column_List">
id, house_id, user_id, content, rating, location_rating, cleanliness_rating, value_rating,
landlord_rating, images, create_time, update_time
</sql>
<select id="selectById" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house_review
where id = #{id}
</select>
<select id="selectByHouseId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house_review
where house_id = #{houseId}
order by create_time desc
</select>
<select id="selectByUserId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house_review
where user_id = #{userId}
order by create_time desc
</select>
<select id="selectByHouseIdAndUserId" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house_review
where house_id = #{houseId} and user_id = #{userId}
limit 1
</select>
<select id="selectList" parameterType="com.rental.entity.HouseReview" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house_review
<where>
<if test="houseId != null">
and house_id = #{houseId}
</if>
<if test="userId != null">
and user_id = #{userId}
</if>
<if test="rating != null">
and rating = #{rating}
</if>
</where>
order by create_time desc
</select>
<select id="calculateAverageRating" parameterType="java.lang.Long" resultType="java.lang.Double">
select avg(rating)
from house_review
where house_id = #{houseId}
</select>
<insert id="insert" parameterType="com.rental.entity.HouseReview" useGeneratedKeys="true" keyProperty="id">
insert into house_review
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="houseId != null">house_id,</if>
<if test="userId != null">user_id,</if>
<if test="content != null">content,</if>
<if test="rating != null">rating,</if>
<if test="locationRating != null">location_rating,</if>
<if test="cleanlinessRating != null">cleanliness_rating,</if>
<if test="valueRating != null">value_rating,</if>
<if test="landlordRating != null">landlord_rating,</if>
<if test="images != null">images,</if>
create_time,
update_time,
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="houseId != null">#{houseId},</if>
<if test="userId != null">#{userId},</if>
<if test="content != null">#{content},</if>
<if test="rating != null">#{rating},</if>
<if test="locationRating != null">#{locationRating},</if>
<if test="cleanlinessRating != null">#{cleanlinessRating},</if>
<if test="valueRating != null">#{valueRating},</if>
<if test="landlordRating != null">#{landlordRating},</if>
<if test="images != null">#{images},</if>
now(),
now(),
</trim>
</insert>
<update id="update" parameterType="com.rental.entity.HouseReview">
update house_review
<set>
<if test="content != null">content = #{content},</if>
<if test="rating != null">rating = #{rating},</if>
<if test="locationRating != null">location_rating = #{locationRating},</if>
<if test="cleanlinessRating != null">cleanliness_rating = #{cleanlinessRating},</if>
<if test="valueRating != null">value_rating = #{valueRating},</if>
<if test="landlordRating != null">landlord_rating = #{landlordRating},</if>
<if test="images != null">images = #{images},</if>
update_time = now(),
</set>
where id = #{id}
</update>
<delete id="deleteById" parameterType="java.lang.Long">
delete from house_review
where id = #{id}
</delete>
</mapper>
backend\src\main\resources\mapper\ReviewReplyMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rental.dao.ReviewReplyDao">
<resultMap id="BaseResultMap" type="com.rental.entity.ReviewReply">
<id column="id" property="id"/>
<result column="review_id" property="reviewId"/>
<result column="user_id" property="userId"/>
<result column="content" property="content"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<sql id="Base_Column_List">
id, review_id, user_id, content, create_time, update_time
</sql>
<select id="selectById" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from review_reply
where id = #{id}
</select>
<select id="selectByReviewId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from review_reply
where review_id = #{reviewId}
order by create_time asc
</select>
<select id="selectByUserId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from review_reply
where user_id = #{userId}
order by create_time desc
</select>
<insert id="insert" parameterType="com.rental.entity.ReviewReply" useGeneratedKeys="true" keyProperty="id">
insert into review_reply
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="reviewId != null">review_id,</if>
<if test="userId != null">user_id,</if>
<if test="content != null">content,</if>
create_time,
update_time,
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="reviewId != null">#{reviewId},</if>
<if test="userId != null">#{userId},</if>
<if test="content != null">#{content},</if>
now(),
now(),
</trim>
</insert>
<update id="update" parameterType="com.rental.entity.ReviewReply">
update review_reply
<set>
<if test="content != null">content = #{content},</if>
update_time = now(),
</set>
where id = #{id}
</update>
<delete id="deleteById" parameterType="java.lang.Long">
delete from review_reply
where id = #{id}
</delete>
</mapper>
2.5 Service Interfaces
backend\src\main\resources\mapper\UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rental.dao.UserDao">
<resultMap id="BaseResultMap" type="com.rental.entity.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="real_name" property="realName"/>
<result column="phone" property="phone"/>
<result column="email" property="email"/>
<result column="avatar" property="avatar"/>
<result column="gender" property="gender"/>
<result column="status" property="status"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<sql id="Base_Column_List">
id, username, password, real_name, phone, email, avatar, gender, status, create_time, update_time
</sql>
<select id="selectById" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from user
where id = #{id}
</select>
<select id="selectByUsername" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from user
where username = #{username}
</select>
<select id="selectByPhone" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from user
where phone = #{phone}
</select>
<select id="selectList" parameterType="com.rental.entity.User" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from user
<where>
<if test="username != null and username != ''">
and username like concat('%', #{username}, '%')
</if>
<if test="realName != null and realName != ''">
and real_name like concat('%', #{realName}, '%')
</if>
<if test="phone != null and phone != ''">
and phone like concat('%', #{phone}, '%')
</if>
<if test="email != null and email != ''">
and email like concat('%', #{email}, '%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="status != null">
and status = #{status}
</if>
</where>
order by create_time desc
</select>
<insert id="insert" parameterType="com.rental.entity.User" useGeneratedKeys="true" keyProperty="id">
insert into user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username != null">username,</if>
<if test="password != null">password,</if>
<if test="realName != null">real_name,</if>
<if test="phone != null">phone,</if>
<if test="email != null">email,</if>
<if test="avatar != null">avatar,</if>
<if test="gender != null">gender,</if>
<if test="status != null">status,</if>
create_time,
update_time,
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="username != null">#{username},</if>
<if test="password != null">#{password},</if>
<if test="realName != null">#{realName},</if>
<if test="phone != null">#{phone},</if>
<if test="email != null">#{email},</if>
<if test="avatar != null">#{avatar},</if>
<if test="gender != null">#{gender},</if>
<if test="status != null">#{status},</if>
now(),
now(),
</trim>
</insert>
<update id="update" parameterType="com.rental.entity.User">
update user
<set>
<if test="username != null">username = #{username},</if>
<if test="password != null">password = #{password},</if>
<if test="realName != null">real_name = #{realName},</if>
<if test="phone != null">phone = #{phone},</if>
<if test="email != null">email = #{email},</if>
<if test="avatar != null">avatar = #{avatar},</if>
<if test="gender != null">gender = #{gender},</if>
<if test="status != null">status = #{status},</if>
update_time = now(),
</set>
where id = #{id}
</update>
<update id="updateStatus">
update user
set status = #{status}, update_time = now()
where id = #{id}
</update>
<delete id="deleteById" parameterType="java.lang.Long">
delete from user
where id = #{id}
</delete>
<insert id="insertUserRole">
insert into user_role (user_id, role_id) values (#{userId}, #{roleId})
</insert>
<delete id="deleteUserRole" parameterType="java.lang.Long">
delete from user_role
where user_id = #{userId}
</delete>
</mapper>
backend\src\main\resources\mapper\ViewingFeedbackMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rental.dao.ViewingFeedbackDao">
<resultMap id="BaseResultMap" type="com.rental.entity.ViewingFeedback">
<id column="id" property="id"/>
<result column="appointment_id" property="appointmentId"/>
<result column="user_id" property="userId"/>
<result column="house_id" property="houseId"/>
<result column="feedback_content" property="feedbackContent"/>
<result column="satisfaction_level" property="satisfactionLevel"/>
<result column="is_public" property="isPublic"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<sql id="Base_Column_List">
id, appointment_id, user_id, house_id, feedback_content, satisfaction_level, is_public,
create_time, update_time
</sql>
<select id="selectById" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from viewing_feedback
where id = #{id}
</select>
<select id="selectByAppointmentId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from viewing_feedback
where appointment_id = #{appointmentId}
</select>
<select id="selectByUserId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from viewing_feedback
where user_id = #{userId}
order by create_time desc
</select>
<select id="selectPublicByHouseId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from viewing_feedback
where house_id = #{houseId} and is_public = 1
order by create_time desc
</select>
<select id="selectList" parameterType="com.rental.entity.ViewingFeedback" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from viewing_feedback
<where>
<if test="appointmentId != null">
and appointment_id = #{appointmentId}
</if>
<if test="userId != null">
and user_id = #{userId}
</if>
<if test="houseId != null">
and house_id = #{houseId}
</if>
<if test="isPublic != null">
and is_public = #{isPublic}
</if>
</where>
order by create_time desc
</select>
<insert id="insert" parameterType="com.rental.entity.ViewingFeedback" useGeneratedKeys="true" keyProperty="id">
insert into viewing_feedback
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="appointmentId != null">appointment_id,</if>
<if test="userId != null">user_id,</if>
<if test="houseId != null">house_id,</if>
<if test="feedbackContent != null">feedback_content,</if>
<if test="satisfactionLevel != null">satisfaction_level,</if>
<if test="isPublic != null">is_public,</if>
create_time,
update_time,
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="appointmentId != null">#{appointmentId},</if>
<if test="userId != null">#{userId},</if>
<if test="houseId != null">#{houseId},</if>
<if test="feedbackContent != null">#{feedbackContent},</if>
<if test="satisfactionLevel != null">#{satisfactionLevel},</if>
<if test="isPublic != null">#{isPublic},</if>
now(),
now(),
</trim>
</insert>
<update id="update" parameterType="com.rental.entity.ViewingFeedback">
update viewing_feedback
<set>
<if test="feedbackContent != null">feedback_content = #{feedbackContent},</if>
<if test="satisfactionLevel != null">satisfaction_level = #{satisfactionLevel},</if>
<if test="isPublic != null">is_public = #{isPublic},</if>
update_time = now(),
</set>
where id = #{id}
</update>
<update id="updateIsPublic">
update viewing_feedback
set is_public = #{isPublic}, update_time = now()
where id = #{id}
</update>
<delete id="deleteById" parameterType="java.lang.Long">
delete from viewing_feedback
where id = #{id}
</delete>
</mapper>
backend\src\main\resources\sql\appointment_module.sql
-- 预约看房表
CREATE TABLE appointment (
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '预约ID',
house_id BIGINT NOT NULL COMMENT '房源ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
landlord_id BIGINT NOT NULL COMMENT '房东ID',
appointment_time DATETIME NOT NULL COMMENT '预约时间',
contact_name VARCHAR(50) NOT NULL COMMENT '联系人姓名',
contact_phone VARCHAR(20) NOT NULL COMMENT '联系电话',
appointment_notes VARCHAR(500) COMMENT '预约备注',
status TINYINT NOT NULL DEFAULT 0 COMMENT '状态:0-待确认,1-已确认,2-已取消,3-已完成',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_house_id (house_id),
INDEX idx_user_id (user_id),
INDEX idx_landlord_id (landlord_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='预约看房表';
-- 看房反馈表
CREATE TABLE viewing_feedback (
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '反馈ID',
appointment_id BIGINT NOT NULL COMMENT '预约ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
house_id BIGINT NOT NULL COMMENT '房源ID',
feedback_content TEXT NOT NULL COMMENT '反馈内容',
satisfaction_level TINYINT NOT NULL COMMENT '满意度:1-5星',
is_public TINYINT NOT NULL DEFAULT 0 COMMENT '是否公开:0-私密,1-公开',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_appointment_id (appointment_id),
INDEX idx_user_id (user_id),
INDEX idx_house_id (house_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='看房反馈表';
-- 房源评价表
CREATE TABLE house_review (
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '评价ID',
house_id BIGINT NOT NULL COMMENT '房源ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
content TEXT NOT NULL COMMENT '评价内容',
rating TINYINT NOT NULL COMMENT '评分:1-5星',
location_rating TINYINT NOT NULL COMMENT '位置评分:1-5星',
cleanliness_rating TINYINT NOT NULL COMMENT '清洁度评分:1-5星',
value_rating TINYINT NOT NULL COMMENT '性价比评分:1-5星',
landlord_rating TINYINT NOT NULL COMMENT '房东评分:1-5星',
images VARCHAR(1000) COMMENT '评价图片,多个图片用逗号分隔',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_house_id (house_id),
INDEX idx_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='房源评价表';
-- 评价回复表
CREATE TABLE review_reply (
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '回复ID',
review_id BIGINT NOT NULL COMMENT '评价ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
content TEXT NOT NULL COMMENT '回复内容',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_review_id (review_id),
INDEX idx_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评价回复表';
2.1 Entity Classes
backend\target\classes\application.properties
# 服务配置
server.port=8080
server.servlet.context-path=/
# 数据库配置
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/rental_system?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456
# MyBatis配置
mybatis.mapper-locations=classpath:mapper/*.xml
mybatis.type-aliases-package=com.rental.entity
mybatis.configuration.map-underscore-to-camel-case=true
# 日志配置
logging.level.com.rental=debug
logging.pattern.console=%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n
# 文件上传配置
spring.servlet.multipart.max-file-size=10MB
spring.servlet.multipart.max-request-size=100MB
# 文件上传路径
file.upload.path=D:/rental-system/upload/
# 文件访问路径
file.access.path=/upload/
# JWT配置
jwt.secret=rental-system-secret-key
jwt.expiration=86400000
# 分页配置
pagehelper.helper-dialect=mysql
pagehelper.reasonable=true
pagehelper.support-methods-arguments=true
pagehelper.params=count=countSql
backend\target\classes\application.yml
server:
port: 8080
servlet:
context-path: /api
spring:
application:
name: rental-system
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/rental_system?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=Asia/Shanghai
username: root
password: 123456
druid:
initial-size: 5
min-idle: 5
max-active: 20
max-wait: 60000
time-between-eviction-runs-millis: 60000
min-evictable-idle-time-millis: 300000
validation-query: SELECT 1 FROM DUAL
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true
max-pool-prepared-statement-per-connection-size: 20
filters: stat,wall
redis:
host: localhost
port: 6379
database: 0
timeout: 10000
servlet:
multipart:
max-file-size: 10MB
max-request-size: 20MB
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.rental.entity
configuration:
map-underscore-to-camel-case: true
cache-enabled: true
logging:
level:
com.rental: debug
# JWT配置
jwt:
# JWT加密密钥
secret: rental-system-secret
# token有效时间(单位:秒)
expiration: 86400
# 文件上传配置
file:
upload-dir: ./uploads
allowed-types: jpg,jpeg,png,gif
max-size: 10485760
backend\target\classes\schema.sql
-- 创建数据库
CREATE DATABASE IF NOT EXISTS rental_system DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
USE rental_system;
-- 用户表
CREATE TABLE IF NOT EXISTS `user` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '用户ID',
`username` varchar(50) NOT NULL COMMENT '用户名',
`password` varchar(100) NOT NULL COMMENT '密码',
`real_name` varchar(50) DEFAULT NULL COMMENT '真实姓名',
`phone` varchar(20) DEFAULT NULL COMMENT '手机号码',
`email` varchar(100) DEFAULT NULL COMMENT '邮箱',
`avatar` varchar(255) DEFAULT NULL COMMENT '头像',
`gender` tinyint(1) DEFAULT 0 COMMENT '性别:0-未知,1-男,2-女',
`status` tinyint(1) DEFAULT 1 COMMENT '状态:0-禁用,1-正常',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_username` (`username`),
UNIQUE KEY `idx_phone` (`phone`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
-- 角色表
CREATE TABLE IF NOT EXISTS `role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '角色ID',
`name` varchar(50) NOT NULL COMMENT '角色名称',
`code` varchar(50) NOT NULL COMMENT '角色编码',
`description` varchar(255) DEFAULT NULL COMMENT '角色描述',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
-- 用户角色关联表
CREATE TABLE IF NOT EXISTS `user_role` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`role_id` bigint(20) NOT NULL COMMENT '角色ID',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_role` (`user_id`, `role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户角色关联表';
-- 学生认证表
CREATE TABLE IF NOT EXISTS `student_verification` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`student_id` varchar(50) NOT NULL COMMENT '学号',
`school` varchar(100) NOT NULL COMMENT '学校',
`college` varchar(100) DEFAULT NULL COMMENT '学院',
`major` varchar(100) DEFAULT NULL COMMENT '专业',
`id_card` varchar(50) NOT NULL COMMENT '身份证号',
`id_card_front` varchar(255) NOT NULL COMMENT '身份证正面照',
`id_card_back` varchar(255) NOT NULL COMMENT '身份证背面照',
`student_card` varchar(255) NOT NULL COMMENT '学生证照片',
`status` tinyint(1) DEFAULT 0 COMMENT '状态:0-待审核,1-已通过,2-已拒绝',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='学生认证表';
-- 房东认证表
CREATE TABLE IF NOT EXISTS `landlord_verification` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`real_name` varchar(50) NOT NULL COMMENT '真实姓名',
`id_card` varchar(50) NOT NULL COMMENT '身份证号',
`id_card_front` varchar(255) NOT NULL COMMENT '身份证正面照',
`id_card_back` varchar(255) NOT NULL COMMENT '身份证背面照',
`house_certificate` varchar(255) DEFAULT NULL COMMENT '房产证照片',
`status` tinyint(1) DEFAULT 0 COMMENT '状态:0-待审核,1-已通过,2-已拒绝',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='房东认证表';
-- 房源表
CREATE TABLE IF NOT EXISTS `house` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '房源ID',
`landlord_id` bigint(20) NOT NULL COMMENT '房东ID',
`title` varchar(100) NOT NULL COMMENT '标题',
`price` decimal(10,2) NOT NULL COMMENT '租金',
`area` decimal(10,2) NOT NULL COMMENT '面积',
`house_type` varchar(50) NOT NULL COMMENT '户型',
`floor` varchar(50) DEFAULT NULL COMMENT '楼层',
`orientation` varchar(50) DEFAULT NULL COMMENT '朝向',
`decoration` varchar(50) DEFAULT NULL COMMENT '装修',
`community` varchar(100) NOT NULL COMMENT '小区名称',
`address` varchar(255) NOT NULL COMMENT '详细地址',
`longitude` decimal(10,6) DEFAULT NULL COMMENT '经度',
`latitude` decimal(10,6) DEFAULT NULL COMMENT '纬度',
`contact` varchar(50) DEFAULT NULL COMMENT '联系人',
`contact_phone` varchar(20) DEFAULT NULL COMMENT '联系电话',
`status` tinyint(1) DEFAULT 0 COMMENT '状态:0-待审核,1-已上架,2-已下架,3-已出租',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_landlord_id` (`landlord_id`),
KEY `idx_community` (`community`),
KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='房源表';
-- 房源详情表
CREATE TABLE IF NOT EXISTS `house_detail` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`house_id` bigint(20) NOT NULL COMMENT '房源ID',
`house_category` varchar(50) DEFAULT NULL COMMENT '房源类别:整租、合租',
`rent_type` varchar(50) DEFAULT NULL COMMENT '出租方式:月付、季付、半年付、年付',
`payment_type` varchar(50) DEFAULT NULL COMMENT '付款方式:押一付一、押一付三、押二付三等',
`has_elevator` tinyint(1) DEFAULT NULL COMMENT '是否有电梯:0-无,1-有',
`heating_type` varchar(50) DEFAULT NULL COMMENT '供暖方式',
`water_fee` varchar(50) DEFAULT NULL COMMENT '水费',
`electricity_fee` varchar(50) DEFAULT NULL COMMENT '电费',
`gas_fee` varchar(50) DEFAULT NULL COMMENT '燃气费',
`internet_fee` varchar(50) DEFAULT NULL COMMENT '网费',
`property_fee` varchar(50) DEFAULT NULL COMMENT '物业费',
`has_parking` tinyint(1) DEFAULT NULL COMMENT '是否有停车位:0-无,1-有',
`check_in_time` date DEFAULT NULL COMMENT '入住时间',
`min_rent_period` int(11) DEFAULT NULL COMMENT '最短租期(月)',
`max_rent_period` int(11) DEFAULT NULL COMMENT '最长租期(月)',
`facilities` text DEFAULT NULL COMMENT '配套设施',
`transportation` text DEFAULT NULL COMMENT '交通情况',
`surroundings` text DEFAULT NULL COMMENT '周边配套',
`description` text DEFAULT NULL COMMENT '房源描述',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_house_id` (`house_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='房源详情表';
-- 房源图片表
CREATE TABLE IF NOT EXISTS `house_image` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`house_id` bigint(20) NOT NULL COMMENT '房源ID',
`url` varchar(255) NOT NULL COMMENT '图片URL',
`is_cover` tinyint(1) DEFAULT 0 COMMENT '是否封面:0-否,1-是',
`sort` int(11) DEFAULT 0 COMMENT '排序',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `idx_house_id` (`house_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='房源图片表';
-- 收藏表
CREATE TABLE IF NOT EXISTS `favorite` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`house_id` bigint(20) NOT NULL COMMENT '房源ID',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_user_house` (`user_id`, `house_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='收藏表';
-- 浏览记录表
CREATE TABLE IF NOT EXISTS `browse_record` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`house_id` bigint(20) NOT NULL COMMENT '房源ID',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_house_id` (`house_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='浏览记录表';
-- 预约看房表
CREATE TABLE IF NOT EXISTS `appointment` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`user_id` bigint(20) NOT NULL COMMENT '用户ID',
`house_id` bigint(20) NOT NULL COMMENT '房源ID',
`landlord_id` bigint(20) NOT NULL COMMENT '房东ID',
`appointment_time` datetime NOT NULL COMMENT '预约时间',
`contact` varchar(50) NOT NULL COMMENT '联系人',
`contact_phone` varchar(20) NOT NULL COMMENT '联系电话',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`status` tinyint(1) DEFAULT 0 COMMENT '状态:0-待确认,1-已确认,2-已取消,3-已完成',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_user_id` (`user_id`),
KEY `idx_house_id` (`house_id`),
KEY `idx_landlord_id` (`landlord_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='预约看房表';
-- 合同表
CREATE TABLE IF NOT EXISTS `contract` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`house_id` bigint(20) NOT NULL COMMENT '房源ID',
`landlord_id` bigint(20) NOT NULL COMMENT '房东ID',
`tenant_id` bigint(20) NOT NULL COMMENT '租客ID',
`contract_no` varchar(50) NOT NULL COMMENT '合同编号',
`start_date` date NOT NULL COMMENT '开始日期',
`end_date` date NOT NULL COMMENT '结束日期',
`rent` decimal(10,2) NOT NULL COMMENT '租金',
`deposit` decimal(10,2) NOT NULL COMMENT '押金',
`payment_type` varchar(50) NOT NULL COMMENT '付款方式',
`payment_cycle` int(11) NOT NULL COMMENT '付款周期(月)',
`file_url` varchar(255) DEFAULT NULL COMMENT '合同文件URL',
`status` tinyint(1) DEFAULT 0 COMMENT '状态:0-待签署,1-已签署,2-已终止',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
UNIQUE KEY `idx_contract_no` (`contract_no`),
KEY `idx_house_id` (`house_id`),
KEY `idx_landlord_id` (`landlord_id`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='合同表';
-- 租金支付记录表
CREATE TABLE IF NOT EXISTS `rent_payment` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID',
`contract_id` bigint(20) NOT NULL COMMENT '合同ID',
`tenant_id` bigint(20) NOT NULL COMMENT '租客ID',
`amount` decimal(10,2) NOT NULL COMMENT '金额',
`payment_date` date NOT NULL COMMENT '支付日期',
`payment_method` varchar(50) DEFAULT NULL COMMENT '支付方式',
`status` tinyint(1) DEFAULT 0 COMMENT '状态:0-未支付,1-已支付',
`remark` varchar(255) DEFAULT NULL COMMENT '备注',
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`),
KEY `idx_contract_id` (`contract_id`),
KEY `idx_tenant_id` (`tenant_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='租金支付记录表';
-- 初始化角色数据
INSERT INTO `role` (`name`, `code`, `description`) VALUES
('管理员', 'admin', '系统管理员'),
('房东', 'landlord', '房源发布者'),
('学生', 'student', '租房学生');
-- 初始化管理员账号
INSERT INTO `user` (`username`, `password`, `real_name`, `phone`, `email`, `status`) VALUES
('admin', 'jGl25bVBBBW96Qi9Te4V37Fnqchz/Eu4qB9vKrRIqRg=', '管理员', '13800138000', 'admin@example.com', 1);
-- 关联管理员角色
INSERT INTO `user_role` (`user_id`, `role_id`) VALUES (1, 1);
backend\target\classes\mapper\AppointmentMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rental.dao.AppointmentDao">
<resultMap id="BaseResultMap" type="com.rental.entity.Appointment">
<id column="id" property="id"/>
<result column="house_id" property="houseId"/>
<result column="user_id" property="userId"/>
<result column="landlord_id" property="landlordId"/>
<result column="appointment_time" property="appointmentTime"/>
<result column="contact_name" property="contactName"/>
<result column="contact_phone" property="contactPhone"/>
<result column="appointment_notes" property="appointmentNotes"/>
<result column="status" property="status"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<sql id="Base_Column_List">
id, house_id, user_id, landlord_id, appointment_time, contact_name, contact_phone,
appointment_notes, status, create_time, update_time
</sql>
<select id="selectById" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from appointment
where id = #{id}
</select>
<select id="selectByUserId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from appointment
where user_id = #{userId}
order by appointment_time desc
</select>
<select id="selectByLandlordId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from appointment
where landlord_id = #{landlordId}
order by appointment_time desc
</select>
<select id="selectByHouseId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from appointment
where house_id = #{houseId}
order by appointment_time desc
</select>
<select id="selectByDateRange" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from appointment
where appointment_time between #{startDate} and #{endDate}
order by appointment_time
</select>
<select id="selectList" parameterType="com.rental.entity.Appointment" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from appointment
<where>
<if test="houseId != null">
and house_id = #{houseId}
</if>
<if test="userId != null">
and user_id = #{userId}
</if>
<if test="landlordId != null">
and landlord_id = #{landlordId}
</if>
<if test="status != null">
and status = #{status}
</if>
</where>
order by appointment_time desc
</select>
<select id="checkTimeConflict" resultType="java.lang.Integer">
select count(1)
from appointment
where house_id = #{houseId}
and status in (0, 1)
and appointment_time between date_sub(#{appointmentTime}, interval 1 hour)
and date_add(#{appointmentTime}, interval 1 hour)
</select>
<insert id="insert" parameterType="com.rental.entity.Appointment" useGeneratedKeys="true" keyProperty="id">
insert into appointment
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="houseId != null">house_id,</if>
<if test="userId != null">user_id,</if>
<if test="landlordId != null">landlord_id,</if>
<if test="appointmentTime != null">appointment_time,</if>
<if test="contactName != null">contact_name,</if>
<if test="contactPhone != null">contact_phone,</if>
<if test="appointmentNotes != null">appointment_notes,</if>
<if test="status != null">status,</if>
create_time,
update_time,
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="houseId != null">#{houseId},</if>
<if test="userId != null">#{userId},</if>
<if test="landlordId != null">#{landlordId},</if>
<if test="appointmentTime != null">#{appointmentTime},</if>
<if test="contactName != null">#{contactName},</if>
<if test="contactPhone != null">#{contactPhone},</if>
<if test="appointmentNotes != null">#{appointmentNotes},</if>
<if test="status != null">#{status},</if>
now(),
now(),
</trim>
</insert>
<update id="update" parameterType="com.rental.entity.Appointment">
update appointment
<set>
<if test="appointmentTime != null">appointment_time = #{appointmentTime},</if>
<if test="contactName != null">contact_name = #{contactName},</if>
<if test="contactPhone != null">contact_phone = #{contactPhone},</if>
<if test="appointmentNotes != null">appointment_notes = #{appointmentNotes},</if>
<if test="status != null">status = #{status},</if>
update_time = now(),
</set>
where id = #{id}
</update>
<update id="updateStatus">
update appointment
set status = #{status}, update_time = now()
where id = #{id}
</update>
<delete id="deleteById" parameterType="java.lang.Long">
delete from appointment
where id = #{id}
</delete>
</mapper>
backend\target\classes\mapper\HouseDetailMapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.rental.dao.HouseDetailDao">
<resultMap id="BaseResultMap" type="com.rental.entity.HouseDetail">
<id column="id" property="id" />
<result column="house_id" property="houseId" />
<result column="house_category" property="houseCategory" />
<result column="rent_type" property="rentType" />
<result column="payment_type" property="paymentType" />
<result column="has_elevator" property="hasElevator" />
<result column="heating_type" property="heatingType" />
<result column="water_fee" property="waterFee" />
<result column="electricity_fee" property="electricityFee" />
<result column="gas_fee" property="gasFee" />
<result column="internet_fee" property="internetFee" />
<result column="property_fee" property="propertyFee" />
<result column="has_parking" property="hasParking" />
<result column="check_in_time" property="checkInTime" />
<result column="min_rent_period" property="minRentPeriod" />
<result column="max_rent_period" property="maxRentPeriod" />
<result column="facilities" property="facilities" />
<result column="transportation" property="transportation" />
<result column="surroundings" property="surroundings" />
<result column="description" property="description" />
</resultMap>
<sql id="Base_Column_List">
id, house_id, house_category, rent_type, payment_type, has_elevator, heating_type,
water_fee, electricity_fee, gas_fee, internet_fee, property_fee, has_parking,
check_in_time, min_rent_period, max_rent_period, facilities, transportation,
surroundings, description
</sql>
<select id="selectById" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List" />
FROM house_detail
WHERE id = #{id}
</select>
<select id="selectByHouseId" resultMap="BaseResultMap">
SELECT <include refid="Base_Column_List" />
FROM house_detail
WHERE house_id = #{houseId}
</select>
<insert id="insert" useGeneratedKeys="true" keyProperty="id">
INSERT INTO house_detail (
house_id, house_category, rent_type, payment_type, has_elevator, heating_type,
water_fee, electricity_fee, gas_fee, internet_fee, property_fee, has_parking,
check_in_time, min_rent_period, max_rent_period, facilities, transportation,
surroundings, description
) VALUES (
#{houseId}, #{houseCategory}, #{rentType}, #{paymentType}, #{hasElevator}, #{heatingType},
#{waterFee}, #{electricityFee}, #{gasFee}, #{internetFee}, #{propertyFee}, #{hasParking},
#{checkInTime}, #{minRentPeriod}, #{maxRentPeriod}, #{facilities}, #{transportation},
#{surroundings}, #{description}
)
</insert>
<update id="update">
UPDATE house_detail
<set>
<if test="houseCategory != null">house_category = #{houseCategory},</if>
<if test="rentType != null">rent_type = #{rentType},</if>
<if test="paymentType != null">payment_type = #{paymentType},</if>
<if test="hasElevator != null">has_elevator = #{hasElevator},</if>
<if test="heatingType != null">heating_type = #{heatingType},</if>
<if test="waterFee != null">water_fee = #{waterFee},</if>
<if test="electricityFee != null">electricity_fee = #{electricityFee},</if>
<if test="gasFee != null">gas_fee = #{gasFee},</if>
<if test="internetFee != null">internet_fee = #{internetFee},</if>
<if test="propertyFee != null">property_fee = #{propertyFee},</if>
<if test="hasParking != null">has_parking = #{hasParking},</if>
<if test="checkInTime != null">check_in_time = #{checkInTime},</if>
<if test="minRentPeriod != null">min_rent_period = #{minRentPeriod},</if>
<if test="maxRentPeriod != null">max_rent_period = #{maxRentPeriod},</if>
<if test="facilities != null">facilities = #{facilities},</if>
<if test="transportation != null">transportation = #{transportation},</if>
<if test="surroundings != null">surroundings = #{surroundings},</if>
<if test="description != null">description = #{description},</if>
</set>
WHERE id = #{id}
</update>
<delete id="deleteById">
DELETE FROM house_detail
WHERE id = #{id}
</delete>
<delete id="deleteByHouseId">
DELETE FROM house_detail
WHERE house_id = #{houseId}
</delete>
</mapper>
backend\target\classes\mapper\HouseMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rental.dao.HouseDao">
<resultMap id="BaseResultMap" type="com.rental.entity.House">
<id column="id" property="id"/>
<result column="landlord_id" property="landlordId"/>
<result column="title" property="title"/>
<result column="price" property="price"/>
<result column="area" property="area"/>
<result column="house_type" property="houseType"/>
<result column="floor" property="floor"/>
<result column="orientation" property="orientation"/>
<result column="decoration" property="decoration"/>
<result column="community" property="community"/>
<result column="address" property="address"/>
<result column="longitude" property="longitude"/>
<result column="latitude" property="latitude"/>
<result column="contact" property="contact"/>
<result column="contact_phone" property="contactPhone"/>
<result column="status" property="status"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<sql id="Base_Column_List">
id, landlord_id, title, price, area, house_type, floor, orientation, decoration, community, address,
longitude, latitude, contact, contact_phone, status, create_time, update_time
</sql>
<select id="selectById" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house
where id = #{id}
</select>
<select id="selectByLandlordId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house
where landlord_id = #{landlordId}
order by create_time desc
</select>
<select id="selectList" parameterType="com.rental.entity.House" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house
<where>
<if test="landlordId != null">
and landlord_id = #{landlordId}
</if>
<if test="title != null and title != ''">
and title like concat('%', #{title}, '%')
</if>
<if test="houseType != null and houseType != ''">
and house_type = #{houseType}
</if>
<if test="community != null and community != ''">
and community like concat('%', #{community}, '%')
</if>
<if test="status != null">
and status = #{status}
</if>
</where>
order by create_time desc
</select>
<select id="search" parameterType="java.util.Map" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house
<where>
<if test="keyword != null and keyword != ''">
and (
title like concat('%', #{keyword}, '%')
or community like concat('%', #{keyword}, '%')
or address like concat('%', #{keyword}, '%')
)
</if>
<if test="minPrice != null">
and price >= #{minPrice}
</if>
<if test="maxPrice != null">
and price <= #{maxPrice}
</if>
<if test="minArea != null">
and area >= #{minArea}
</if>
<if test="maxArea != null">
and area <= #{maxArea}
</if>
<if test="houseType != null and houseType != ''">
and house_type = #{houseType}
</if>
<if test="orientation != null and orientation != ''">
and orientation = #{orientation}
</if>
<if test="decoration != null and decoration != ''">
and decoration = #{decoration}
</if>
<if test="status != null">
and status = #{status}
</if>
<if test="status == null">
and status = 1
</if>
</where>
order by
<choose>
<when test="orderBy != null and orderBy == 'price_asc'">
price asc
</when>
<when test="orderBy != null and orderBy == 'price_desc'">
price desc
</when>
<when test="orderBy != null and orderBy == 'area_asc'">
area asc
</when>
<when test="orderBy != null and orderBy == 'area_desc'">
area desc
</when>
<when test="orderBy != null and orderBy == 'time_asc'">
create_time asc
</when>
<otherwise>
create_time desc
</otherwise>
</choose>
</select>
<insert id="insert" parameterType="com.rental.entity.House" useGeneratedKeys="true" keyProperty="id">
insert into house
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="landlordId != null">landlord_id,</if>
<if test="title != null">title,</if>
<if test="price != null">price,</if>
<if test="area != null">area,</if>
<if test="houseType != null">house_type,</if>
<if test="floor != null">floor,</if>
<if test="orientation != null">orientation,</if>
<if test="decoration != null">decoration,</if>
<if test="community != null">community,</if>
<if test="address != null">address,</if>
<if test="longitude != null">longitude,</if>
<if test="latitude != null">latitude,</if>
<if test="contact != null">contact,</if>
<if test="contactPhone != null">contact_phone,</if>
<if test="status != null">status,</if>
create_time,
update_time,
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="landlordId != null">#{landlordId},</if>
<if test="title != null">#{title},</if>
<if test="price != null">#{price},</if>
<if test="area != null">#{area},</if>
<if test="houseType != null">#{houseType},</if>
<if test="floor != null">#{floor},</if>
<if test="orientation != null">#{orientation},</if>
<if test="decoration != null">#{decoration},</if>
<if test="community != null">#{community},</if>
<if test="address != null">#{address},</if>
<if test="longitude != null">#{longitude},</if>
<if test="latitude != null">#{latitude},</if>
<if test="contact != null">#{contact},</if>
<if test="contactPhone != null">#{contactPhone},</if>
<if test="status != null">#{status},</if>
now(),
now(),
</trim>
</insert>
<update id="update" parameterType="com.rental.entity.House">
update house
<set>
<if test="title != null">title = #{title},</if>
<if test="price != null">price = #{price},</if>
<if test="area != null">area = #{area},</if>
<if test="houseType != null">house_type = #{houseType},</if>
<if test="floor != null">floor = #{floor},</if>
<if test="orientation != null">orientation = #{orientation},</if>
<if test="decoration != null">decoration = #{decoration},</if>
<if test="community != null">community = #{community},</if>
<if test="address != null">address = #{address},</if>
<if test="longitude != null">longitude = #{longitude},</if>
<if test="latitude != null">latitude = #{latitude},</if>
<if test="contact != null">contact = #{contact},</if>
<if test="contactPhone != null">contact_phone = #{contactPhone},</if>
<if test="status != null">status = #{status},</if>
update_time = now(),
</set>
where id = #{id}
</update>
<update id="updateStatus">
update house
set status = #{status}, update_time = now()
where id = #{id}
</update>
<delete id="deleteById" parameterType="java.lang.Long">
delete from house
where id = #{id}
</delete>
<delete id="deleteBatchByIds" parameterType="java.lang.Long">
delete from house
where id in
<foreach collection="array" item="id" open="(" separator="," close=")">
#{id}
</foreach>
</delete>
</mapper>
backend\target\classes\mapper\HouseReviewMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rental.dao.HouseReviewDao">
<resultMap id="BaseResultMap" type="com.rental.entity.HouseReview">
<id column="id" property="id"/>
<result column="house_id" property="houseId"/>
<result column="user_id" property="userId"/>
<result column="content" property="content"/>
<result column="rating" property="rating"/>
<result column="location_rating" property="locationRating"/>
<result column="cleanliness_rating" property="cleanlinessRating"/>
<result column="value_rating" property="valueRating"/>
<result column="landlord_rating" property="landlordRating"/>
<result column="images" property="images"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<sql id="Base_Column_List">
id, house_id, user_id, content, rating, location_rating, cleanliness_rating, value_rating,
landlord_rating, images, create_time, update_time
</sql>
<select id="selectById" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house_review
where id = #{id}
</select>
<select id="selectByHouseId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house_review
where house_id = #{houseId}
order by create_time desc
</select>
<select id="selectByUserId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house_review
where user_id = #{userId}
order by create_time desc
</select>
<select id="selectByHouseIdAndUserId" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house_review
where house_id = #{houseId} and user_id = #{userId}
limit 1
</select>
<select id="selectList" parameterType="com.rental.entity.HouseReview" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from house_review
<where>
<if test="houseId != null">
and house_id = #{houseId}
</if>
<if test="userId != null">
and user_id = #{userId}
</if>
<if test="rating != null">
and rating = #{rating}
</if>
</where>
order by create_time desc
</select>
<select id="calculateAverageRating" parameterType="java.lang.Long" resultType="java.lang.Double">
select avg(rating)
from house_review
where house_id = #{houseId}
</select>
<insert id="insert" parameterType="com.rental.entity.HouseReview" useGeneratedKeys="true" keyProperty="id">
insert into house_review
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="houseId != null">house_id,</if>
<if test="userId != null">user_id,</if>
<if test="content != null">content,</if>
<if test="rating != null">rating,</if>
<if test="locationRating != null">location_rating,</if>
<if test="cleanlinessRating != null">cleanliness_rating,</if>
<if test="valueRating != null">value_rating,</if>
<if test="landlordRating != null">landlord_rating,</if>
<if test="images != null">images,</if>
create_time,
update_time,
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="houseId != null">#{houseId},</if>
<if test="userId != null">#{userId},</if>
<if test="content != null">#{content},</if>
<if test="rating != null">#{rating},</if>
<if test="locationRating != null">#{locationRating},</if>
<if test="cleanlinessRating != null">#{cleanlinessRating},</if>
<if test="valueRating != null">#{valueRating},</if>
<if test="landlordRating != null">#{landlordRating},</if>
<if test="images != null">#{images},</if>
now(),
now(),
</trim>
</insert>
<update id="update" parameterType="com.rental.entity.HouseReview">
update house_review
<set>
<if test="content != null">content = #{content},</if>
<if test="rating != null">rating = #{rating},</if>
<if test="locationRating != null">location_rating = #{locationRating},</if>
<if test="cleanlinessRating != null">cleanliness_rating = #{cleanlinessRating},</if>
<if test="valueRating != null">value_rating = #{valueRating},</if>
<if test="landlordRating != null">landlord_rating = #{landlordRating},</if>
<if test="images != null">images = #{images},</if>
update_time = now(),
</set>
where id = #{id}
</update>
<delete id="deleteById" parameterType="java.lang.Long">
delete from house_review
where id = #{id}
</delete>
</mapper>
backend\target\classes\mapper\ReviewReplyMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rental.dao.ReviewReplyDao">
<resultMap id="BaseResultMap" type="com.rental.entity.ReviewReply">
<id column="id" property="id"/>
<result column="review_id" property="reviewId"/>
<result column="user_id" property="userId"/>
<result column="content" property="content"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<sql id="Base_Column_List">
id, review_id, user_id, content, create_time, update_time
</sql>
<select id="selectById" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from review_reply
where id = #{id}
</select>
<select id="selectByReviewId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from review_reply
where review_id = #{reviewId}
order by create_time asc
</select>
<select id="selectByUserId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from review_reply
where user_id = #{userId}
order by create_time desc
</select>
<insert id="insert" parameterType="com.rental.entity.ReviewReply" useGeneratedKeys="true" keyProperty="id">
insert into review_reply
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="reviewId != null">review_id,</if>
<if test="userId != null">user_id,</if>
<if test="content != null">content,</if>
create_time,
update_time,
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="reviewId != null">#{reviewId},</if>
<if test="userId != null">#{userId},</if>
<if test="content != null">#{content},</if>
now(),
now(),
</trim>
</insert>
<update id="update" parameterType="com.rental.entity.ReviewReply">
update review_reply
<set>
<if test="content != null">content = #{content},</if>
update_time = now(),
</set>
where id = #{id}
</update>
<delete id="deleteById" parameterType="java.lang.Long">
delete from review_reply
where id = #{id}
</delete>
</mapper>
2.5 Service Interfaces
backend\target\classes\mapper\UserMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rental.dao.UserDao">
<resultMap id="BaseResultMap" type="com.rental.entity.User">
<id column="id" property="id"/>
<result column="username" property="username"/>
<result column="password" property="password"/>
<result column="real_name" property="realName"/>
<result column="phone" property="phone"/>
<result column="email" property="email"/>
<result column="avatar" property="avatar"/>
<result column="gender" property="gender"/>
<result column="status" property="status"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<sql id="Base_Column_List">
id, username, password, real_name, phone, email, avatar, gender, status, create_time, update_time
</sql>
<select id="selectById" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from user
where id = #{id}
</select>
<select id="selectByUsername" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from user
where username = #{username}
</select>
<select id="selectByPhone" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from user
where phone = #{phone}
</select>
<select id="selectList" parameterType="com.rental.entity.User" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from user
<where>
<if test="username != null and username != ''">
and username like concat('%', #{username}, '%')
</if>
<if test="realName != null and realName != ''">
and real_name like concat('%', #{realName}, '%')
</if>
<if test="phone != null and phone != ''">
and phone like concat('%', #{phone}, '%')
</if>
<if test="email != null and email != ''">
and email like concat('%', #{email}, '%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="status != null">
and status = #{status}
</if>
</where>
order by create_time desc
</select>
<insert id="insert" parameterType="com.rental.entity.User" useGeneratedKeys="true" keyProperty="id">
insert into user
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="username != null">username,</if>
<if test="password != null">password,</if>
<if test="realName != null">real_name,</if>
<if test="phone != null">phone,</if>
<if test="email != null">email,</if>
<if test="avatar != null">avatar,</if>
<if test="gender != null">gender,</if>
<if test="status != null">status,</if>
create_time,
update_time,
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="username != null">#{username},</if>
<if test="password != null">#{password},</if>
<if test="realName != null">#{realName},</if>
<if test="phone != null">#{phone},</if>
<if test="email != null">#{email},</if>
<if test="avatar != null">#{avatar},</if>
<if test="gender != null">#{gender},</if>
<if test="status != null">#{status},</if>
now(),
now(),
</trim>
</insert>
<update id="update" parameterType="com.rental.entity.User">
update user
<set>
<if test="username != null">username = #{username},</if>
<if test="password != null">password = #{password},</if>
<if test="realName != null">real_name = #{realName},</if>
<if test="phone != null">phone = #{phone},</if>
<if test="email != null">email = #{email},</if>
<if test="avatar != null">avatar = #{avatar},</if>
<if test="gender != null">gender = #{gender},</if>
<if test="status != null">status = #{status},</if>
update_time = now(),
</set>
where id = #{id}
</update>
<update id="updateStatus">
update user
set status = #{status}, update_time = now()
where id = #{id}
</update>
<delete id="deleteById" parameterType="java.lang.Long">
delete from user
where id = #{id}
</delete>
<insert id="insertUserRole">
insert into user_role (user_id, role_id) values (#{userId}, #{roleId})
</insert>
<delete id="deleteUserRole" parameterType="java.lang.Long">
delete from user_role
where user_id = #{userId}
</delete>
</mapper>
backend\target\classes\mapper\ViewingFeedbackMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rental.dao.ViewingFeedbackDao">
<resultMap id="BaseResultMap" type="com.rental.entity.ViewingFeedback">
<id column="id" property="id"/>
<result column="appointment_id" property="appointmentId"/>
<result column="user_id" property="userId"/>
<result column="house_id" property="houseId"/>
<result column="feedback_content" property="feedbackContent"/>
<result column="satisfaction_level" property="satisfactionLevel"/>
<result column="is_public" property="isPublic"/>
<result column="create_time" property="createTime"/>
<result column="update_time" property="updateTime"/>
</resultMap>
<sql id="Base_Column_List">
id, appointment_id, user_id, house_id, feedback_content, satisfaction_level, is_public,
create_time, update_time
</sql>
<select id="selectById" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from viewing_feedback
where id = #{id}
</select>
<select id="selectByAppointmentId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from viewing_feedback
where appointment_id = #{appointmentId}
</select>
<select id="selectByUserId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from viewing_feedback
where user_id = #{userId}
order by create_time desc
</select>
<select id="selectPublicByHouseId" parameterType="java.lang.Long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from viewing_feedback
where house_id = #{houseId} and is_public = 1
order by create_time desc
</select>
<select id="selectList" parameterType="com.rental.entity.ViewingFeedback" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from viewing_feedback
<where>
<if test="appointmentId != null">
and appointment_id = #{appointmentId}
</if>
<if test="userId != null">
and user_id = #{userId}
</if>
<if test="houseId != null">
and house_id = #{houseId}
</if>
<if test="isPublic != null">
and is_public = #{isPublic}
</if>
</where>
order by create_time desc
</select>
<insert id="insert" parameterType="com.rental.entity.ViewingFeedback" useGeneratedKeys="true" keyProperty="id">
insert into viewing_feedback
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="appointmentId != null">appointment_id,</if>
<if test="userId != null">user_id,</if>
<if test="houseId != null">house_id,</if>
<if test="feedbackContent != null">feedback_content,</if>
<if test="satisfactionLevel != null">satisfaction_level,</if>
<if test="isPublic != null">is_public,</if>
create_time,
update_time,
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="appointmentId != null">#{appointmentId},</if>
<if test="userId != null">#{userId},</if>
<if test="houseId != null">#{houseId},</if>
<if test="feedbackContent != null">#{feedbackContent},</if>
<if test="satisfactionLevel != null">#{satisfactionLevel},</if>
<if test="isPublic != null">#{isPublic},</if>
now(),
now(),
</trim>
</insert>
<update id="update" parameterType="com.rental.entity.ViewingFeedback">
update viewing_feedback
<set>
<if test="feedbackContent != null">feedback_content = #{feedbackContent},</if>
<if test="satisfactionLevel != null">satisfaction_level = #{satisfactionLevel},</if>
<if test="isPublic != null">is_public = #{isPublic},</if>
update_time = now(),
</set>
where id = #{id}
</update>
<update id="updateIsPublic">
update viewing_feedback
set is_public = #{isPublic}, update_time = now()
where id = #{id}
</update>
<delete id="deleteById" parameterType="java.lang.Long">
delete from viewing_feedback
where id = #{id}
</delete>
</mapper>
backend\target\classes\sql\appointment_module.sql
-- 预约看房表
CREATE TABLE appointment (
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '预约ID',
house_id BIGINT NOT NULL COMMENT '房源ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
landlord_id BIGINT NOT NULL COMMENT '房东ID',
appointment_time DATETIME NOT NULL COMMENT '预约时间',
contact_name VARCHAR(50) NOT NULL COMMENT '联系人姓名',
contact_phone VARCHAR(20) NOT NULL COMMENT '联系电话',
appointment_notes VARCHAR(500) COMMENT '预约备注',
status TINYINT NOT NULL DEFAULT 0 COMMENT '状态:0-待确认,1-已确认,2-已取消,3-已完成',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_house_id (house_id),
INDEX idx_user_id (user_id),
INDEX idx_landlord_id (landlord_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='预约看房表';
-- 看房反馈表
CREATE TABLE viewing_feedback (
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '反馈ID',
appointment_id BIGINT NOT NULL COMMENT '预约ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
house_id BIGINT NOT NULL COMMENT '房源ID',
feedback_content TEXT NOT NULL COMMENT '反馈内容',
satisfaction_level TINYINT NOT NULL COMMENT '满意度:1-5星',
is_public TINYINT NOT NULL DEFAULT 0 COMMENT '是否公开:0-私密,1-公开',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_appointment_id (appointment_id),
INDEX idx_user_id (user_id),
INDEX idx_house_id (house_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='看房反馈表';
-- 房源评价表
CREATE TABLE house_review (
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '评价ID',
house_id BIGINT NOT NULL COMMENT '房源ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
content TEXT NOT NULL COMMENT '评价内容',
rating TINYINT NOT NULL COMMENT '评分:1-5星',
location_rating TINYINT NOT NULL COMMENT '位置评分:1-5星',
cleanliness_rating TINYINT NOT NULL COMMENT '清洁度评分:1-5星',
value_rating TINYINT NOT NULL COMMENT '性价比评分:1-5星',
landlord_rating TINYINT NOT NULL COMMENT '房东评分:1-5星',
images VARCHAR(1000) COMMENT '评价图片,多个图片用逗号分隔',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_house_id (house_id),
INDEX idx_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='房源评价表';
-- 评价回复表
CREATE TABLE review_reply (
id BIGINT PRIMARY KEY AUTO_INCREMENT COMMENT '回复ID',
review_id BIGINT NOT NULL COMMENT '评价ID',
user_id BIGINT NOT NULL COMMENT '用户ID',
content TEXT NOT NULL COMMENT '回复内容',
create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
INDEX idx_review_id (review_id),
INDEX idx_user_id (user_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='评价回复表';
2.1 Entity Classes
frontend\package.json
{
"name": "rental-system-frontend",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.21.1",
"core-js": "^3.6.5",
"element-ui": "^2.15.6",
"vue": "^2.6.11",
"vue-router": "^3.2.0",
"vuex": "^3.4.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-plugin-router": "~4.5.0",
"@vue/cli-plugin-vuex": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"sass": "^1.26.5",
"sass-loader": "^8.0.2",
"vue-template-compiler": "^2.6.11"
}
}
frontend\src\App.vue
<template>
<div id="app">
<router-view />
</div>
</template>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
color: #2c3e50;
height: 100%;
}
</style>
frontend\src\main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import './assets/css/global.css'
import axios from 'axios'
Vue.config.productionTip = false
// 使用ElementUI
Vue.use(ElementUI)
// 配置axios
axios.defaults.baseURL = 'http://localhost:8080/api'
// 请求拦截器,添加token
axios.interceptors.request.use(config => {
const token = store.state.token
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
// 响应拦截器,处理错误
axios.interceptors.response.use(
response => {
return response
},
error => {
if (error.response) {
if (error.response.status === 401) {
// 未授权,跳转到登录页
store.commit('CLEAR_USER_INFO')
router.push('/login')
ElementUI.Message.error('登录已过期,请重新登录')
} else {
// 其他错误
ElementUI.Message.error(error.response.data.message || '服务器错误')
}
} else {
ElementUI.Message.error('网络错误,请稍后再试')
}
return Promise.reject(error)
}
)
Vue.prototype.$http = axios
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
frontend\src\api\appointment.js
import request from '@/utils/request';
/**
* 预约相关API
*/
export default {
/**
* 创建预约
* @param {Object} data 预约信息
*/
createAppointment(data) {
return request({
url: '/appointment/create',
method: 'post',
data
});
},
/**
* 确认预约
* @param {Number} id 预约ID
*/
confirmAppointment(id) {
return request({
url: `/appointment/confirm/${id}`,
method: 'post'
});
},
/**
* 取消预约
* @param {Number} id 预约ID
*/
cancelAppointment(id) {
return request({
url: `/appointment/cancel/${id}`,
method: 'post'
});
},
/**
* 完成预约
* @param {Number} id 预约ID
*/
completeAppointment(id) {
return request({
url: `/appointment/complete/${id}`,
method: 'post'
});
},
/**
* 获取预约详情
* @param {Number} id 预约ID
*/
getAppointmentDetail(id) {
return request({
url: `/appointment/detail/${id}`,
method: 'get'
});
},
/**
* 获取用户的预约列表
*/
getUserAppointments() {
return request({
url: '/appointment/user',
method: 'get'
});
},
/**
* 获取房东的预约列表
*/
getLandlordAppointments() {
return request({
url: '/appointment/landlord',
method: 'get'
});
},
/**
* 获取房源的预约列表
* @param {Number} houseId 房源ID
*/
getHouseAppointments(houseId) {
return request({
url: `/appointment/house/${houseId}`,
method: 'get'
});
},
/**
* 获取指定日期范围内的预约
* @param {Date} startDate 开始日期
* @param {Date} endDate 结束日期
*/
getAppointmentsByDateRange(startDate, endDate) {
return request({
url: '/appointment/date-range',
method: 'get',
params: {
startDate,
endDate
}
});
},
/**
* 获取预约统计数据
*/
getAppointmentStatistics() {
return request({
url: '/appointment/statistics',
method: 'get'
});
}
};
frontend\src\api\favorite.js
import request from '@/utils/request';
// 添加收藏
export function addFavorite(houseId) {
return request({
url: '/favorite/add',
method: 'post',
data: {
houseId
}
});
}
// 取消收藏
export function cancelFavorite(houseId) {
return request({
url: '/favorite/cancel',
method: 'delete',
params: {
houseId
}
});
}
// 获取收藏列表
export function getFavoriteList() {
return request({
url: '/favorite/list',
method: 'get'
});
}
// 检查是否已收藏
export function checkFavorite(houseId) {
return request({
url: '/favorite/check',
method: 'get',
params: {
houseId
}
});
}
frontend\src\api\feedback.js
import request from '@/utils/request';
/**
* 看房反馈相关API
*/
export default {
/**
* 提交看房反馈
* @param {Object} data 反馈信息
*/
submitFeedback(data) {
return request({
url: '/feedback/submit',
method: 'post',
data
});
},
/**
* 更新看房反馈
* @param {Number} id 反馈ID
* @param {Object} data 反馈信息
*/
updateFeedback(id, data) {
return request({
url: `/feedback/update/${id}`,
method: 'put',
data
});
},
/**
* 删除看房反馈
* @param {Number} id 反馈ID
*/
deleteFeedback(id) {
return request({
url: `/feedback/delete/${id}`,
method: 'delete'
});
},
/**
* 设置反馈是否公开
* @param {Number} id 反馈ID
* @param {Number} isPublic 是否公开:0-私密,1-公开
*/
setFeedbackPublic(id, isPublic) {
return request({
url: `/feedback/public/${id}`,
method: 'put',
params: {
isPublic
}
});
},
/**
* 获取反馈详情
* @param {Number} id 反馈ID
*/
getFeedbackDetail(id) {
return request({
url: `/feedback/detail/${id}`,
method: 'get'
});
},
/**
* 获取用户的反馈列表
*/
getUserFeedbacks() {
return request({
url: '/feedback/user',
method: 'get'
});
},
/**
* 获取房源的公开反馈列表
* @param {Number} houseId 房源ID
*/
getHousePublicFeedbacks(houseId) {
return request({
url: `/feedback/house/${houseId}`,
method: 'get'
});
},
/**
* 获取预约的反馈
* @param {Number} appointmentId 预约ID
*/
getAppointmentFeedback(appointmentId) {
return request({
url: `/feedback/appointment/${appointmentId}`,
method: 'get'
});
}
};
frontend\src\api\house.js
import request from '@/utils/request';
// 获取房源列表
export function getHouseList(params) {
return request({
url: '/house/list',
method: 'get',
params
});
}
// 搜索房源
export function searchHouse(params) {
return request({
url: '/house/search',
method: 'get',
params
});
}
// 获取房源详情
export function getHouseDetail(id) {
return request({
url: `/house/detail/${id}`,
method: 'get'
});
}
// 获取房源图片
export function getHouseImages(houseId) {
return request({
url: `/house/images/${houseId}`,
method: 'get'
});
}
// 添加房源
export function addHouse(data) {
return request({
url: '/house/add',
method: 'post',
data
});
}
// 更新房源
export function updateHouse(data) {
return request({
url: '/house/update',
method: 'put',
data
});
}
// 删除房源
export function deleteHouse(id) {
return request({
url: `/house/delete/${id}`,
method: 'delete'
});
}
// 上传房源图片
export function uploadHouseImage(data) {
return request({
url: '/house/upload',
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data'
}
});
}
// 设置封面图片
export function setCoverImage(houseId, imageId) {
return request({
url: '/house/setCover',
method: 'put',
data: {
houseId,
imageId
}
});
}
// 获取房东的房源列表
export function getLandlordHouses() {
return request({
url: '/house/landlord',
method: 'get'
});
}
frontend\src\api\review.js
import request from '@/utils/request';
/**
* 房源评价相关API
*/
export default {
/**
* 提交房源评价
* @param {Object} data 评价信息
*/
submitReview(data) {
return request({
url: '/review/submit',
method: 'post',
data
});
},
/**
* 更新房源评价
* @param {Number} id 评价ID
* @param {Object} data 评价信息
*/
updateReview(id, data) {
return request({
url: `/review/update/${id}`,
method: 'put',
data
});
},
/**
* 删除房源评价
* @param {Number} id 评价ID
*/
deleteReview(id) {
return request({
url: `/review/delete/${id}`,
method: 'delete'
});
},
/**
* 获取评价详情
* @param {Number} id 评价ID
*/
getReviewDetail(id) {
return request({
url: `/review/detail/${id}`,
method: 'get'
});
},
/**
* 获取房源的评价列表
* @param {Number} houseId 房源ID
*/
getHouseReviews(houseId) {
return request({
url: `/review/house/${houseId}`,
method: 'get'
});
},
/**
* 获取用户的评价列表
*/
getUserReviews() {
return request({
url: '/review/user',
method: 'get'
});
},
/**
* 获取房源评价统计数据
* @param {Number} houseId 房源ID
*/
getHouseReviewStatistics(houseId) {
return request({
url: `/review/statistics/${houseId}`,
method: 'get'
});
},
/**
* 检查用户是否已评价房源
* @param {Number} houseId 房源ID
*/
checkUserReviewed(houseId) {
return request({
url: `/review/check/${houseId}`,
method: 'get'
});
},
/**
* 提交评价回复
* @param {Object} data 回复信息
*/
submitReply(data) {
return request({
url: '/reply/submit',
method: 'post',
data
});
},
/**
* 更新评价回复
* @param {Number} id 回复ID
* @param {Object} data 回复信息
*/
updateReply(id, data) {
return request({
url: `/reply/update/${id}`,
method: 'put',
data
});
},
/**
* 删除评价回复
* @param {Number} id 回复ID
*/
deleteReply(id) {
return request({
url: `/reply/delete/${id}`,
method: 'delete'
});
},
/**
* 获取回复详情
* @param {Number} id 回复ID
*/
getReplyDetail(id) {
return request({
url: `/reply/detail/${id}`,
method: 'get'
});
},
/**
* 获取评价的回复列表
* @param {Number} reviewId 评价ID
*/
getReviewReplies(reviewId) {
return request({
url: `/reply/review/${reviewId}`,
method: 'get'
});
}
};
3.2 Vue Components
frontend\src\api\user.js
import request from '@/utils/request';
// 用户登录
export function login(data) {
return request({
url: '/user/login',
method: 'post',
data
});
}
// 用户注册
export function register(data) {
return request({
url: '/user/register',
method: 'post',
data
});
}
// 获取用户信息
export function getUserInfo() {
return request({
url: '/user/info',
method: 'get'
});
}
// 更新用户信息
export function updateUserInfo(data) {
return request({
url: '/user/update',
method: 'put',
data
});
}
// 修改密码
export function changePassword(data) {
return request({
url: '/user/changePassword',
method: 'put',
data
});
}
// 上传头像
export function uploadAvatar(data) {
return request({
url: '/user/avatar',
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data'
}
});
}
frontend\src\api\verification.js
import request from '@/utils/request';
// 提交学生认证
export function submitStudentVerification(data) {
return request({
url: '/verification/student/submit',
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data'
}
});
}
// 提交房东认证
export function submitLandlordVerification(data) {
return request({
url: '/verification/landlord/submit',
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data'
}
});
}
// 获取学生认证状态
export function getStudentVerificationStatus() {
return request({
url: '/verification/student/status',
method: 'get'
});
}
// 获取房东认证状态
export function getLandlordVerificationStatus() {
return request({
url: '/verification/landlord/status',
method: 'get'
});
}
// 获取学生认证列表(管理员)
export function getStudentVerificationList(params) {
return request({
url: '/verification/student/list',
method: 'get',
params
});
}
// 获取房东认证列表(管理员)
export function getLandlordVerificationList(params) {
return request({
url: '/verification/landlord/list',
method: 'get',
params
});
}
// 审核学生认证(管理员)
export function reviewStudentVerification(data) {
return request({
url: '/verification/student/review',
method: 'put',
data
});
}
// 审核房东认证(管理员)
export function reviewLandlordVerification(data) {
return request({
url: '/verification/landlord/review',
method: 'put',
data
});
}
User Profile Component
frontend\src\assets\css\global.css
/* 全局样式 */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
body {
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", "微软雅黑", Arial, sans-serif;
background-color: #f5f5f5;
}
/* 清除浮动 */
.clearfix:after {
content: "";
display: block;
clear: both;
}
/* 页面容器 */
.container {
width: 1200px;
margin: 0 auto;
}
/* 页面内容区域 */
.content {
padding: 20px;
background-color: #fff;
border-radius: 4px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}
/* 页面标题 */
.page-title {
font-size: 20px;
font-weight: bold;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #eee;
}
/* 表单项间距 */
.el-form-item {
margin-bottom: 20px;
}
/* 按钮组 */
.button-group {
margin-top: 20px;
text-align: center;
}
/* 卡片样式 */
.card {
background-color: #fff;
border-radius: 4px;
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
margin-bottom: 20px;
overflow: hidden;
}
.card-header {
padding: 15px;
border-bottom: 1px solid #eee;
font-weight: bold;
}
.card-body {
padding: 15px;
}
/* 价格文本 */
.price {
color: #ff6700;
font-weight: bold;
}
/* 标签样式 */
.tag {
display: inline-block;
padding: 2px 8px;
border-radius: 2px;
font-size: 12px;
margin-right: 5px;
}
.tag-primary {
background-color: #409EFF;
color: #fff;
}
.tag-success {
background-color: #67C23A;
color: #fff;
}
.tag-warning {
background-color: #E6A23C;
color: #fff;
}
.tag-danger {
background-color: #F56C6C;
color: #fff;
}
/* 图片容器 */
.image-container {
position: relative;
overflow: hidden;
}
.image-container img {
width: 100%;
transition: transform 0.3s;
}
.image-container:hover img {
transform: scale(1.05);
}
/* 分页容器 */
.pagination-container {
text-align: center;
margin-top: 20px;
}