284 lines
8.2 KiB
Vue
284 lines
8.2 KiB
Vue
<template>
|
||
<!-- <pageTopBar :bannerList="bannerList.data.apartment"></pageTopBar> -->
|
||
<pageTopBar></pageTopBar>
|
||
<!-- 筛选 -->
|
||
<div class="screen-box wid1200">
|
||
<seach-module @handleTransfer="handleTransfer" :count="listCount" :initPitchValue="pitchValue"></seach-module>
|
||
</div>
|
||
|
||
<div class="list wid1200 flexflex" ref="gridContainer">
|
||
<template v-if="list.length != 0">
|
||
<apartment-item v-for="(item, index) in list" :key="index" :item="item" :pitchValue="pitchValue" :masonryInstance="masonryInstance" @handlecollect="handlecollect"></apartment-item>
|
||
</template>
|
||
</div>
|
||
|
||
<div v-if="list.length == 0" class="empty-box wid1200 flexcenter">
|
||
<empty-duck :hintTextTwo="'建议放宽筛选条件'"></empty-duck>
|
||
</div>
|
||
|
||
<!-- 其他附近房源 -->
|
||
<div v-if="moreList.length != 0" class="other-nearby-listings-box flexcenter">没有找到更多房源,为您推荐其他附近房源</div>
|
||
<div class="wid1200" ref="moreShowList">
|
||
<apartment-item v-for="(item, index) in moreList" :key="index" :item="item" :pitchValue="pitchValue"></apartment-item>
|
||
</div>
|
||
|
||
<div class="bottom-tps" v-if="list.length != 0 && page == 0">- 到底了 -</div>
|
||
<div class="bottom-tps" v-if="page != 0">- 下拉加载更多 -</div>
|
||
|
||
<have-questions></have-questions>
|
||
|
||
<!-- 页尾 -->
|
||
<page-footer></page-footer>
|
||
|
||
<!-- 右下角咨询 -->
|
||
<circle-btn></circle-btn>
|
||
<back-to-top></back-to-top>
|
||
</template>
|
||
|
||
<script setup>
|
||
import pageTopBar from "../../components/pageTopBar/pageTopBar.vue"
|
||
import seachModule from "@/components/apartment/seachModule.vue"
|
||
import apartmentItem from "@/components/public/apartment-item.vue"
|
||
import haveQuestions from "@/components/public/have-questions.vue"
|
||
import pageFooter from "@/components/footer/footer.vue"
|
||
import emptyDuck from "@/components/public/empty-duck.vue"
|
||
import circleBtn from "@/components/public/circle-btn.vue"
|
||
import { ref, onMounted, onUnmounted, watch, getCurrentInstance, nextTick, reactive } from "vue"
|
||
import { ElLoading } from "element-plus"
|
||
import Masonry from "masonry-layout"
|
||
import { useRoute, useRouter } from "vue-router"
|
||
import backToTop from "@/components/public/backToTop.vue"
|
||
import store from "../../store/index"
|
||
import api from "../../utils/api"
|
||
import { ElMessage } from "element-plus"
|
||
|
||
const { proxy } = getCurrentInstance()
|
||
|
||
const route = useRoute()
|
||
|
||
const props = defineProps({
|
||
item: Object,
|
||
})
|
||
|
||
const gridContainer = ref(null)
|
||
|
||
let list = ref([])
|
||
let listCount = ref(0) // 列表数量
|
||
|
||
let masonryInstance = null
|
||
// let masonryInstanceMore = null
|
||
|
||
onMounted(() => {
|
||
// 初始化瀑布流
|
||
masonryInstance = new Masonry(gridContainer.value, {
|
||
itemSelector: ".item",
|
||
gutter: 22,
|
||
})
|
||
|
||
// masonryInstanceMore = new Masonry(moreShowList.value, {
|
||
// itemSelector: ".item",
|
||
// gutter: 20,
|
||
// })
|
||
|
||
pitchValue.value = store.state.apartmentPitchValue
|
||
if (route.query["companyid"]) pitchValue.value["companyid"] = route.query["companyid"]
|
||
|
||
// banner() // 获取轮播图数据
|
||
getData() // 获取列表数据
|
||
|
||
window.addEventListener("scroll", handleScroll)
|
||
})
|
||
|
||
onUnmounted(() => {
|
||
window.removeEventListener("scroll", handleScroll)
|
||
window.removeEventListener("scroll", getMoreScroll, true)
|
||
})
|
||
|
||
let loading = null // 加载
|
||
let requestLoading = false // 接口加载中
|
||
let page = 1
|
||
const getData = () => {
|
||
if (page == 0 || requestLoading) return
|
||
loading = ElLoading.service({
|
||
lock: true,
|
||
text: "Loading",
|
||
background: "rgba(0, 0, 0, 0.7)",
|
||
})
|
||
|
||
requestLoading = true
|
||
|
||
proxy
|
||
.$post("/tenement/pc/api/apartment", {
|
||
limit: 10,
|
||
page,
|
||
...pitchValue.value,
|
||
})
|
||
.then(res => {
|
||
if (res.code != 200) return
|
||
let data = res.data
|
||
list.value = list.value.concat(data.data || [])
|
||
page = data.page * data.limit >= data.count ? 0 : page + 1
|
||
|
||
listCount = data.count
|
||
nextTick(() => {
|
||
masonryInstance.reloadItems()
|
||
masonryInstance.layout()
|
||
loading.close()
|
||
requestLoading = false
|
||
})
|
||
|
||
// 小于20 代表筛选 数据不够了,需要加载更多的 随便在这里初始化 更多的 瀑布流 HTML
|
||
// if (data.data.length < 20 && (pitchValue.value["school"] || pitchValue.value["location"].length != 0)) {
|
||
// morePage.value = 1
|
||
// getMoreList()
|
||
// }
|
||
})
|
||
.catch(err => {
|
||
loading.close()
|
||
requestLoading = false
|
||
})
|
||
}
|
||
|
||
const handleScroll = () => {
|
||
const scrollHeight = document.documentElement.scrollHeight
|
||
const clientHeight = document.documentElement.clientHeight
|
||
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop
|
||
if (scrollTop + clientHeight >= scrollHeight - 350) getData()
|
||
}
|
||
|
||
let pitchValue = ref({
|
||
companyid: 0,
|
||
roomtype: 0,
|
||
rent_min: null, // 租金
|
||
rent_max: null, // 租金
|
||
location: [],
|
||
school: 0,
|
||
roomlistings: 0,
|
||
keyword: "",
|
||
})
|
||
|
||
// 筛选组件的参数的中转
|
||
const handleTransfer = data => {
|
||
for (const key in data.value) {
|
||
if (data.value[key] != pitchValue.value[key]) {
|
||
pitchValue.value = { ...data.value }
|
||
store.state.apartmentPitchValue = pitchValue.value
|
||
page = 1
|
||
list.value = []
|
||
getData()
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
let moreShowList = ref(null)
|
||
let moreState = ref(false) // 更多列表 显示状态
|
||
let morePage = ref(1)
|
||
let moreList = ref([])
|
||
let moreLoading = ref(false)
|
||
|
||
// 加载更多数据列表
|
||
const getMoreList = () => {
|
||
if (morePage.value == 0 || moreLoading.value) return
|
||
moreLoading.value = true
|
||
let postData = {
|
||
page: morePage.value,
|
||
...pitchValue.value,
|
||
}
|
||
|
||
api.getMoreLists(postData).then(res => {
|
||
if (res.code != 200) return
|
||
const data = res.data
|
||
if (!data.data) return
|
||
|
||
moreList.value = moreList.value.concat(data.data)
|
||
moreState.value = true
|
||
if (data.data && data.data.length < data.limit) morePage.value = 0
|
||
else {
|
||
morePage.value++
|
||
window.addEventListener("scroll", getMoreScroll, true)
|
||
}
|
||
nextTick(() => {
|
||
masonryInstanceMore.reloadItems()
|
||
masonryInstanceMore.layout()
|
||
moreLoading.value = false
|
||
})
|
||
})
|
||
}
|
||
|
||
const getMoreScroll = () => {
|
||
let body = document.documentElement ? document.documentElement : document.body ? document.body : document.querySelector(".element")
|
||
let scrollTop = body.scrollTop
|
||
let clientHeight = body.clientHeight
|
||
let offsetHeight = body.offsetHeight
|
||
if (scrollTop + clientHeight >= offsetHeight - 200 && !moreLoading.value) getMoreList()
|
||
}
|
||
|
||
// 处理列表的点击收藏
|
||
const handlecollect = uniqid => {
|
||
let targetIndex = 0
|
||
let token = ""
|
||
|
||
list.value.forEach((element, index) => {
|
||
if (element.uniqid == uniqid) {
|
||
targetIndex = index
|
||
token = element.token || ""
|
||
}
|
||
})
|
||
|
||
api.apartmentCollection({ token }).then(res => {
|
||
if (res.code != 200) return
|
||
const data = res.data
|
||
list.value[targetIndex]["iscollect"] = data.status
|
||
ElMessage.success(res.message)
|
||
})
|
||
}
|
||
</script>
|
||
<style lang="less" scoped>
|
||
.screen-box {
|
||
margin: 0 auto 20px;
|
||
}
|
||
|
||
.list {
|
||
margin: 20px auto 0;
|
||
flex-wrap: wrap;
|
||
justify-content: space-between;
|
||
|
||
&:after {
|
||
content: "";
|
||
height: 0;
|
||
width: 386px;
|
||
}
|
||
}
|
||
|
||
.empty-box {
|
||
width: 1200px;
|
||
height: 500px;
|
||
background-color: rgba(255, 255, 255, 1);
|
||
border-radius: 16px;
|
||
-moz-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.0784313725490196);
|
||
-webkit-box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.0784313725490196);
|
||
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.0784313725490196);
|
||
justify-content: center;
|
||
margin: 0 auto;
|
||
}
|
||
|
||
.bottom-tps {
|
||
font-weight: 400;
|
||
font-size: 14px;
|
||
color: #555555;
|
||
text-align: center;
|
||
padding: 30px 0;
|
||
}
|
||
|
||
.other-nearby-listings-box {
|
||
width: 100%;
|
||
height: 32px;
|
||
color: #525151;
|
||
background: rgba(245, 251, 255, 1);
|
||
font-size: 14px;
|
||
margin-top: 40px;
|
||
margin-bottom: 43px;
|
||
}
|
||
</style>
|