gterFang/src/views/user.vue
A1300399510 54bc83080d 修改
2023-08-01 13:26:33 +08:00

581 lines
20 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

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

<template>
<pageTopBar></pageTopBar>
<div class="user-box">
<div class="info-box flexacenter">
<div class="info-left flexacenter flex1">
<a href="https://bbs.gter.net/account.php?a=avatar" target="_blank">
<img class="info-user-icon" :src="user['avatar'] || store.state.user['avatar'] || require('@/assets/img/publicImage/defaultAvatar.png')">
</a>
<div class="info-user-box">
<div class="info-user-top flexacenter">
<a href="https://bbs.gter.net/account.php?a=info" target="_blank" class="info-user-username">{{
user['nickname'] }}</a>
<a href="https://bbs.gter.net/account.php?a=info" target="_blank">
<img class="info-user-edit" src="@/assets/img/publicImage/edit-pen.png">
</a>
<img class="info-user-certifying" v-if="user.intermediary == 1"
src="@/assets/img/publicImage/certifying-agent.png">
<div class="info-user-validity" v-if="validityidentity">有效期至{{ validityidentity }}</div>
</div>
<div class="info-user-bottom flexacenter">UID{{ user['uid'] }}</div>
</div>
</div>
<div class="info-right flexacenter">
<div class="operate-item message flexcenter" @click="systematicState = true; newmessagenum = 0">
<div class="operate-item-shell flexcenter">
<div class="newmessagenum flexcenter" v-if="newmessagenum > 0">{{ newmessagenum }}</div>
<img class="operate-icon" src="@/assets/img/publicImage/message-icon.svg">
</div>
<div class="operate-text">消息提醒</div>
</div>
<img class="" src="@/assets/img/publicImage/cut-off-rule.svg">
<div class="operate-item flexcenter add">
<div class="operate-item-shell flexcenter">
<img class="operate-icon" src="@/assets/img/publicImage/add-icon.svg">
</div>
<div class="operate-text">发布房源</div>
<choosing-identity></choosing-identity>
</div>
<template v-if="user['uid'] && user.identity != 0">
<img class="" src="@/assets/img/publicImage/cut-off-rule.svg">
<el-popover placement="bottom" :width="360" trigger="hover" :show-arrow="false"
popper-style="background: transparent;padding:0;box-shadow: none;border: none;">
<template #reference>
<div class="operate-item flexcenter identity">
<div class="operate-item-shell flexcenter"
:class="{ 'intermediary': user.identity == 1, 'personage': user.identity == -1 }">
<img class="operate-icon" src="@/assets/img/publicImage/intermediary-icon.png">
</div>
<div class="operate-text">{{ identityObj[user.identity || -1] }}</div>
</div>
</template>
<!-- <img v-if="user.identity == 1" style="width: 360px;"
src="@/assets/img/publicImage/mediation-authentication-code.svg">
<img v-else style="width: 360px;" src="@/assets/img/publicImage/housing-certification-code.svg"> -->
<div v-if="user.identity == 1" class="btn-qrcode">
<img class="bj" src="@/assets/img/publicImage/mediation-authentication-bj.jpg">
<img class="QR-code" src="https://app.gter.net/tenement/pc/api/qrcode?type=middlemanAuth">
</div>
<div v-else class="btn-qrcode">
<img class="bj" src="@/assets/img/publicImage/housing-certification-bj.jpg">
<img class="QR-code" src="https://app.gter.net/tenement/pc/api/qrcode?type=propertyAuth">
</div>
</el-popover>
</template>
</div>
</div>
<div class="tab-box flexacenter">
<div class="tab-item flexcenter" :class="{ 'pitch': tabState == 'fav' }" @click="cutTab('fav')">我的收藏</div>
<div class="tab-item flexcenter" :class="{ 'pitch': tabState == 'publish' }" @click="cutTab('publish')">我的发布
</div>
</div>
</div>
<div class="quantity wid1200" v-if="tabState == 'fav'">共收藏 <b>{{ count['fav'] }}</b> 个房源</div>
<div class="quantity wid1200" v-else> <b>{{ count['publish'] }}</b> 条房源上架 {{ stat['listing'] }} | 草稿 {{ stat['draft']
}} | 下架 {{ stat['offshelf'] }}</div>
<div class="list wid1200 flexflex" v-show="tabState == 'fav'" ref="gridContainer">
<div class="item" v-for="(item, index) in favData['list']" :key="item.id">
<public-list-item :item="item" :index="index" @cancelCollection="cancelCollection"></public-list-item>
</div>
</div>
<div class="list wid1200 flexflex" v-show="tabState == 'publish'" ref="gridContainerpublish">
<div class="item" v-for="(item, index) in publishData['list']" :key="item.id">
<public-list-item :item="item" :index="index" @cancelCollection="cancelCollection" :ispublish="true"
@goUp="goUp" @undercarriage="undercarriage" @handleDelete="handleDelete"></public-list-item>
</div>
</div>
<div class="empty-box flexcenter wid1200"
v-if="(tabState == 'fav' && favData['list'].length == 0) || (tabState == 'publish' && publishData['list'].length == 0)">
<empty-duck></empty-duck>
</div>
<div class="bottom-tps"
v-if="(tabState == 'fav' && favData['list'].length != 0 && favData['page'] == 0) || (tabState == 'publish' && publishData['list'].length != 0 && publishData['page'] == 0)">
- 到底了 -</div>
<!-- 有疑问 -->
<have-questions></have-questions>
<!-- 页底 -->
<page-footer></page-footer>
<!-- 系统通知弹窗 -->
<systematic-notification-pop v-if="systematicState" @close="systematicState = false"></systematic-notification-pop>
<back-to-top></back-to-top>
</template>
<script setup>
import pageTopBar from '../components/pageTopBar/pageTopBar.vue';
import systematicNotificationPop from '@/components/user/systematic-notification-pop.vue'
import haveQuestions from '@/components/public/have-questions.vue'
import pageFooter from '@/components/footer/footer.vue'
import publicListItem from '@/components/public/public-list-item.vue'
import emptyDuck from '@/components/public/empty-duck.vue'
import choosingIdentity from '@/components/edit/choosingIdentity.vue'
import backToTop from '@/components/public/backToTop.vue'
import { ref, reactive, onMounted, onUnmounted, getCurrentInstance, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router';
import { ElLoading, ElMessage } from 'element-plus'
import Masonry from 'masonry-layout';
import store from '@/store/index';
const { proxy } = getCurrentInstance()
const route = useRoute();
const gridContainer = ref(null);
const gridContainerpublish = ref(null);
let masonryInstance = null
let masonryInstancepublish = null
onMounted(() => {
masonryInstance = new Masonry(gridContainer.value, {
itemSelector: '.item',
gutter: 20
});
masonryInstancepublish = new Masonry(gridContainerpublish.value, {
itemSelector: '.item',
gutter: 20
});
init()
window.addEventListener('scroll', handleScroll);
})
let systematicState = ref(false) // 系统通知
let user = ref({})
let count = ref({}) // 发布和收藏的数量
let newmessagenum = ref(0)
let validityidentity = ref('')
let tabState = ref('publish') // fav publish
const identityObj = {
1: "中介认证",
"-1": "房源认证"
}
const init = () => {
proxy.$post("/tenement/pc/api/user").then(res => {
if (res.code != 200) return
let data = res.data
if (!route.query['tab']) {
if (data.count['publish'] > 0) tabState.value = 'publish'
else tabState.value = 'fav'
} else tabState.value = route.query['tab']
if (tabState.value == 'publish') getPublishData()
else getFavData()
user.value = data.user
count.value = data.count
newmessagenum.value = data.newmessagenum
store.state.user['messagenum'] = data.newmessagenum
validityidentity.value = data.validityidentity
}).finally(() => { })
}
let loading = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
visible: false
});
let publishData = ref({
page: 1,
list: []
})
let stat = ref({}) // 我的发布的详细数量
// 获取发布数据
const getPublishData = () => {
if (publishData.value['page'] == 0 || loading['visible'].value) return
loading = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
})
proxy.$post("/tenement/pc/api/user/publishList", {
page: publishData.value['page']
}).then(res => {
if (res.code != 200) return
let data = res.data
// data.data[0]['verifiedstatus'] = 1
stat.value = data['stat']
publishData.value['page'] = data['page'] * data['limit'] >= data['count'] ? 0 : data['page'] + 1
publishData.value['list'] = publishData.value['list'].concat(data['data'] || [])
nextTick(() => {
masonryInstancepublish.reloadItems();
masonryInstancepublish.layout();
loading.close()
})
}).finally(() => {
loading.close()
})
}
let favData = ref({
page: 1,
list: []
})
// 获取收藏数据
const getFavData = () => {
if (favData.value['page'] == 0 || loading['visible'].value) return
loading = ElLoading.service({
lock: true,
text: 'Loading',
background: 'rgba(0, 0, 0, 0.7)',
})
proxy.$post("/tenement/pc/api/user/favList", {
page: favData.value['page']
}).then(res => {
if (res.code != 200) return
let data = res.data
favData.value['page'] = data['page'] * data['limit'] >= data['count'] ? 0 : data['page'] + 1
favData.value['list'] = favData.value['list'].concat(data['data'] || [])
nextTick(() => {
masonryInstance.reloadItems();
masonryInstance.layout();
loading.close()
})
}).finally(() => {
loading.close()
})
}
// 切换 tab
const cutTab = (value) => {
tabState.value = value
if (tabState.value == 'publish' && publishData.value['list'].length == 0) getPublishData()
else if (tabState.value == 'fav' && favData.value['list'].length == 0) getFavData()
}
// 取消收藏
let cancelCollection = data => {
proxy.$post("/tenement/pc/api/user/operation", {
token: data['token']
}).then(res => {
if (res.code != 200) return
favData.value.list.splice(data['index'], 1)
count.value['fav']--
nextTick(() => {
masonryInstance.reloadItems();
masonryInstance.layout();
loading.close()
})
})
}
// 点击下架都修改状态
const undercarriage = (index, status) => {
stat.value['listing']--
stat.value['offshelf']++
publishData.value['list'][index].status = status
}
// 点击顶上去后改 数据 状态
const goUp = index => publishData.value['list'][index].isding = 1
// 点击删除
const handleDelete = (index, status) => {
if (status == 0) stat.value['draft']--
else if (status == 1) stat.value['listing']--
else stat.value['offshelf']--
publishData.value['list'].splice(index, 1)
nextTick(() => {
masonryInstancepublish.reloadItems();
masonryInstancepublish.layout();
loading.close()
})
}
// 监听滚动到底部
const handleScroll = () => {
// console.log(user.value, "user");
if (!user.value['uid']) return
const scrollHeight = document.documentElement.scrollHeight;
const clientHeight = document.documentElement.clientHeight;
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
if (scrollTop + clientHeight >= scrollHeight - 350) {
if (tabState.value == 'publish') getPublishData()
else getFavData()
}
};
onUnmounted(() => {
window.removeEventListener('scroll', handleScroll);
});
</script>
<style lang="less" scoped>
.user-box {
width: 1200px;
height: 238px;
margin: 30px auto 26px;
font-size: 14px;
background: linear-gradient(0deg, rgba(214, 236, 255, 1) -4%, rgba(232, 244, 255, 1) 34%, rgba(176, 216, 255, 1) 131%);
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);
.info-box {
height: 160px;
border-bottom: 2px solid #ddeeff;
.info-left {
padding-left: 40px;
.info-user-icon {
width: 80px;
height: 80px;
border-radius: 50%;
}
.info-user-box {
margin-left: 20px;
.info-user-top {
height: 28px;
.info-user-username {
font-size: 16px;
color: #333;
}
.info-user-edit {
width: 16px;
height: 16px;
margin-left: 5px;
cursor: pointer;
margin-right: 29px;
}
.info-user-certifying {
width: 85px;
height: 20px;
}
.info-user-validity {
color: #aaa;
font-size: 13px;
}
}
.info-user-bottom {
height: 24px;
color: #7F7F7F;
}
}
}
.info-right {
.operate-item {
flex-direction: column;
margin: 0 52px;
position: relative;
cursor: pointer;
.operate-item-shell {
width: 40px;
height: 40px;
border-radius: 20px;
margin-bottom: 7px;
}
&.message {
.operate-item-shell {
position: relative;
background-color: rgba(80, 227, 194, 1);
border-radius: 8px;
-moz-box-shadow: 0px 0px 5px rgba(80, 227, 194, 1);
-webkit-box-shadow: 0px 0px 5px rgba(80, 227, 194, 1);
box-shadow: 0px 0px 5px rgba(80, 227, 194, 1);
.operate-icon {
width: 32px;
height: 28px;
}
.newmessagenum {
position: absolute;
top: 0;
right: 0;
transform: translate(50%, -50%);
width: 16px;
height: 16px;
font-size: 13px;
background: #f95d5d;
color: #FFFFFF;
border-radius: 50%;
}
}
}
&.add {
.operate-item-shell {
background-color: rgba(253, 223, 109, 1);
-moz-box-shadow: 0px 0px 5px rgba(253, 223, 109, 1);
-webkit-box-shadow: 0px 0px 5px rgba(253, 223, 109, 1);
box-shadow: 0px 0px 5px rgba(253, 223, 109, 1);
.operate-icon {
width: 16px;
height: 16px;
}
}
}
&.identity {
.operate-item-shell {
&.intermediary {
background-color: rgba(46, 207, 226, 1);
-moz-box-shadow: 0px 0px 5px rgba(46, 207, 226, 1);
-webkit-box-shadow: 0px 0px 5px rgba(46, 207, 226, 1);
box-shadow: 0px 0px 5px rgba(46, 207, 226, 1);
}
&.personage {
background-color: rgba(171, 169, 255, 1);
-moz-box-shadow: 0px 0px 5px rgba(123, 121, 255, 1);
-webkit-box-shadow: 0px 0px 5px rgba(123, 121, 255, 1);
box-shadow: 0px 0px 5px rgba(123, 121, 255, 1);
}
}
.operate-icon {
width: 22px;
height: 22px;
}
}
.operate-text {
color: #555;
font-size: 14px;
height: 24px;
}
}
}
}
.tab-box {
height: 78px;
padding-left: 20px;
.tab-item {
width: 160px;
height: 48px;
background-color: rgba(205, 227, 247, 1);
border-radius: 8px;
font-size: 18px;
color: #555555;
margin-right: 10px;
cursor: pointer;
&.pitch {
background-color: rgba(98, 177, 255, 1);
border-radius: 8px;
font-family: 'PingFangSC-Semibold', 'PingFang SC Semibold', 'PingFang SC', sans-serif;
font-weight: 650;
font-style: normal;
font-size: 18px;
color: #FFFFFF;
position: relative;
&::after {
content: "";
position: absolute;
bottom: -5px;
width: 14px;
height: 8px;
background-image: url('@/assets/img/publicImage/green-arrow-below.svg');
}
}
}
}
}
.quantity {
margin: 0 auto;
font-size: 14px;
color: #555;
margin-bottom: 24px;
b {
color: #000;
}
}
.list {
margin: 0 auto;
flex-wrap: wrap;
justify-content: space-between;
.item {
cursor: pointer;
}
}
.empty-box {
background-color: #FFFFFF;
height: 500px;
margin: 0 auto;
justify-content: center;
align-items: center;
border-radius: 16px;
}
.bottom-tps {
font-weight: 400;
font-size: 14px;
color: #555555;
text-align: center;
padding: 30px 0;
}
.btn-qrcode {
width: 360px;
margin: 0 auto;
.bj {
width: 100%;
box-shadow: 0px 0px 8px rgba(0, 0, 0, 0.2784313725490196);
border-radius: 10px;
}
.QR-code {
position: absolute;
width: 110px;
height: 110px;
border-radius: 50%;
bottom: 86px;
left: 50%;
transform: translateX(-50%);
}
}
</style>