Browse Source

feat(房源管理): 添加我发布的房源页面及功能

- 新增我发布的房源页面,包含列表展示、编辑和删除功能
- 实现房源列表的分页加载和下拉刷新
- 添加空状态提示和发布房源引导按钮
- 修改用户信息获取逻辑,从Vuex store获取最新数据
- 更新首页轮播图API调用和数据结构
- 在用户中心添加我发布的房源入口
master
前端-胡立永 1 month ago
parent
commit
a0e887c68d
6 changed files with 376 additions and 18 deletions
  1. +3
    -0
      common/api.js
  2. +10
    -0
      pages.json
  3. +17
    -3
      pages/home/index.vue
  4. +44
    -15
      pages/login/index.vue
  5. +17
    -0
      pages/user/index.vue
  6. +285
    -0
      pages_subpack/my-published-houses/index.vue

+ 3
- 0
common/api.js View File

@ -82,3 +82,6 @@ export const houseYear = (params) => http.get('/houserent-admin/comment/getHouse
// 经济人获取账号密码以及邀请码
export const accountCode = (params) => http.get('/houserent-admin/comment/getAccountCode', {params,params})
export const getBanner = (params) => http.get('/houserent-admin/common_index/queryBannerList', {params})

+ 10
- 0
pages.json View File

@ -210,6 +210,16 @@
"navigationBarBackgroundColor": "#1EC77A",
"navigationBarTextStyle": "white"
}
},
{
"path": "my-published-houses/index",
"style": {
"navigationBarTitleText": "我发布的房源",
"enablePullDownRefresh": true,
"onReachBottomDistance": 100,
"navigationBarBackgroundColor": "#1EC77A",
"navigationBarTextStyle": "white"
}
}
]
}


+ 17
- 3
pages/home/index.vue View File

@ -13,7 +13,9 @@
</view>
<!-- backdrop -->
<view class=" se-mb-20">
<uv-swiper height="300rpx" :list="bannerList"></uv-swiper>
<uv-swiper height="300rpx"
keyName="image"
:list="bannerList"></uv-swiper>
<!-- <image class="se-w-vw-100 se-h-400" src="@/static/image/banner.png" mode=""></image> -->
</view>
<!-- se-mt-300 -->
@ -88,7 +90,7 @@
</template>
<script>
import { housePageList,houseType,noticeObjApi,getConfig,commonIndexIndexIcon, getInfo } from "@/common/api.js"
import { housePageList,houseType,noticeObjApi,getConfig,commonIndexIndexIcon, getInfo, getBanner } from "@/common/api.js"
import citySelect from "@/components/cityselect/index.vue"
const lineBg = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAANCAYAAAC3mX7tAAAAAXNSR0IArs4c6QAAAbxJREFUOE+lk0FrE1EUhc+ZDOhMigjZdNcWdCPJqNCdlkZw4TKL2mVwkKLQ/gAFRcEu/AEKuumDrEopNEsXSlNoV+2iTYIbBdNdNwGpmRmFyVx5oQk6mYSpvt1799z7zTnvDQPlBAJcRGxZOLXotn7Gz8ftZePaROCZP+IaEh36a04LxFS8mMmgcKFcb54H9Kvi5LtdNIZ6BMf0lVMDMD88UJ7abuP1eUDeWuEZyVcJPZ/oKeclgRcJxRMrG17l4udOGthZbF8ATMb1IvKcXiU/y66xnziM2LQf1O+nAfnq+hYgpSStCeMmdcFXzi6AWyMGrlvZcGmUs54T31QQLIzo37Pd+u0eKFD5osDYHvPlJyLyNopYnbgUtrSuc2pOG4aUSC4nxTWYFXHOfni02wPp5anCO4KP0sSUViOQ91m38VjrByDZLprBt/ZHkAkvMO3oP3QiO9ZM7i7v1MK/QHoj6sblQLrV/4ZpCDMluoff++iBo/6Bdua32m/+NUYdlz2dW+k7GQnqF84eyOqY1xjPcw8Rn+iLTwp6yFFcpP8zhLxHsgjBFRrI9WKO0AbxVURqMOVDttw8GHeTvwFKoZ4cmcUYJAAAAABJRU5ErkJggg==";
import QQMapWX from "@/util/qqmap-wx-jssdk.min.js"
@ -103,7 +105,11 @@
city:"",
keyword:"",
lineBg: lineBg,
bannerList:["https://image.hhlm1688.com/2025-08-05/b9b3d015-fcaf-4667-8946-ad9436503a25.jpg"],
bannerList:[
{
image : "https://image.hhlm1688.com/2025-08-05/b9b3d015-fcaf-4667-8946-ad9436503a25.jpg"
}
],
nav:[],
noticeObj:{},
houseTypeList:[],
@ -147,6 +153,7 @@
this.onNotice();
this.onHousePageList();
this.onHouseType();
this.getBanner();
// this.onGetConfig()
},
@ -188,6 +195,12 @@
}
})
},
getBanner(){
getBanner()
.then(res => {
this.bannerList = res.result.records
})
},
onNavigator(){
let token = uni.getStorageSync('token');
if(!token){
@ -270,6 +283,7 @@
pageSize:that.pageSize
}
housePageList(params).then((response) => {
uni.stopPullDownRefresh()
console.info("responseindexsindexsindexs",response.result.records)
response.result.records.forEach((items,indexs)=>{
if(items.image){


+ 44
- 15
pages/login/index.vue View File

@ -56,14 +56,27 @@
}
},
onLoad(options) {
this.imagUrl = uni.getStorageSync('userInfo').headImage
this.nameUser = uni.getStorageSync('userInfo').nickName
this.phone = uni.getStorageSync('userInfo').phone
if(options.back==1){
this.back = options.back
}
//
this.loadUserInfo()
},
onShow() {
//
this.loadUserInfo()
},
methods: {
//
loadUserInfo() {
// Vuex store
const storeUserInfo = this.$store.state.userInfo || {}
this.imagUrl = storeUserInfo.headImage || ''
this.nameUser = storeUserInfo.nickName || ''
this.phone = storeUserInfo.phone || ''
},
bindblur(event) {
this.nameUser = event.target.value
},
@ -110,18 +123,34 @@
}
UpdateInfo(params).then((response) => {
if(this.back==1){
uni.navigateBack({
delta:1
})
}else{
uni.switchTab({
url:"/pages/home/index"
})
}
}).catch((error) =>{
})
// Vuex store
const updatedUserInfo = {
...uni.getStorageSync('userInfo'),
headImage: that.imagUrl,
nickName: that.nameUser,
phone: that.phone
}
//
uni.setStorageSync('userInfo', updatedUserInfo)
// Vuex store
if(that.$store) {
that.$store.state.userInfo = updatedUserInfo
}
if(this.back==1){
uni.navigateBack({
delta:1
})
}else{
uni.switchTab({
url:"/pages/home/index"
})
}
}).catch((error) =>{
})
}


+ 17
- 0
pages/user/index.vue View File

@ -100,6 +100,19 @@
</view> -->
</template>
<!-- 需要登录的功能 -->
<!-- <template v-if="isLoggedIn">
<view class="se-py-30 se-px-20 se-flex se-flex-h-sb se-b-b" @click="onMyPublishedHouses">
<view class="se-flex se-flex-ai-c">
<image class="se-a-30" src="@/static/image/home4734.png" mode=""></image>
<text class="se-ml-20 se-fs-24 se-fw-5">我发布的房源</text>
</view>
<view class="se-flex se-flex-ai-c">
<uv-icon name="arrow-right"></uv-icon>
</view>
</view>
</template> -->
<!-- 通用功能 -->
<view class="se-py-30 se-px-20 se-flex se-flex-h-sb se-b-b" @click="onCustomerService">
<view class="se-flex se-flex-ai-c">
@ -211,6 +224,10 @@
onBrokerAccount() {
this.checkLoginAndNavigate("/pages_subpack/broker-account/index", "经纪人账号")
},
//
onMyPublishedHouses() {
this.checkLoginAndNavigate("/pages_subpack/my-published-houses/index", "我发布的房源")
},
onLogOut() {
if (!this.isLoggedIn) {
uni.showToast({


+ 285
- 0
pages_subpack/my-published-houses/index.vue View File

@ -0,0 +1,285 @@
<template>
<view>
<!-- 房源列表 -->
<view class="se-pb-200">
<view v-if="list.length > 0">
<view @click="onDetail(item)" class="se-my-10 se-mx-20 se-px-20 se-py-20 se-br-20 se-bgc-white se-flex se-pos" v-for="(item, index) in list" :key="index">
<view class="se-pos se-w-260 se-h-180">
<image v-if="item.iconImage" class="se-a-80 se-pos-lt" :src="item.iconImage" mode=""></image>
<image class="se-w-260 se-h-180 se-br-10" :src="item.images && item.images[0] ? item.images[0] : '/static/image/header.png'" mode="aspectFill"></image>
</view>
<view class="se-pl-10 se-w-p-100">
<view class="se-c-black se-fs-28">
{{ item.title }}
</view>
<view class="se-flex se-flex-h-sb se-flex-ai-c se-fs-24 se-mt-10 se-c-66">
<text>{{ item.homeType }}</text>
<text v-if="item.timeGo">{{ item.timeGo }}</text>
</view>
<view class="se-flex se-flex-h-sb se-flex-ai-c se-mt-10">
<template v-if="item.iconTitles && item.iconTitles.length > 0">
<view class="se-flex">
<view class="se-display-ib se-c-white se-bgc-orange se-fs-22 se-br-8 se-px-10 se-py-5 se-mr-10" v-for="(tag, tagIndex) in item.iconTitles" :key="tagIndex">
{{ tag }}
</view>
</view>
</template>
<template v-else><view></view></template>
<view class="se-c-66 se-flex se-flex-ai-c">
<uv-icon name="eye"></uv-icon>
<text class="se-ml-5 se-fs-18">{{ item.num || 0 }}</text>
</view>
</view>
<view class="se-flex se-flex-h-sb se-flex-ai-c se-mt-10">
<text class="se-c-red se-fs-24 se-fw-6 se-toe-1">{{ item.price }}/{{ item.unit }}</text>
<text class="se-c-66 se-fs-22 se-toe-1">{{ item.address }}</text>
</view>
</view>
<!-- 操作按钮 -->
<view class="action-buttons">
<view class="action-btn edit-btn" @click.stop="onEdit(item)">
<uv-icon name="edit-pen" size="16"></uv-icon>
<text>编辑</text>
</view>
<view class="action-btn delete-btn" @click.stop="onDelete(item)">
<uv-icon name="trash" size="16"></uv-icon>
<text>删除</text>
</view>
</view>
</view>
</view>
<!-- 空状态 -->
<view v-else class="empty-container">
<uv-empty mode="list" text="暂无发布的房源"></uv-empty>
<view class="empty-tip">快去发布您的第一套房源吧</view>
<view class="publish-btn" @click="goToPublish">
<uv-button type="primary" text="立即发布" customStyle="background-color: #1EC77A; border-radius: 30px;"></uv-button>
</view>
</view>
</view>
</view>
</template>
<script>
import { MyHousePageList, deleteHouse } from "@/common/api.js"
export default {
data() {
return {
list: [],
pageNo: 1,
pageSize: 10,
loading: false
}
},
onLoad() {
//
uni.setNavigationBarTitle({
title: '我发布的房源'
})
this.loadMyHouses()
},
onShow() {
//
this.refreshData()
},
onPullDownRefresh() {
this.refreshData()
},
onReachBottom() {
this.loadMore()
},
methods: {
//
loadMyHouses() {
if (this.loading) return
this.loading = true
const params = {
pageNo: this.pageNo,
pageSize: this.pageSize
}
MyHousePageList(params).then(response => {
uni.stopPullDownRefresh()
this.loading = false
if (response && response.result && response.result.records) {
//
response.result.records.forEach(item => {
if (item.image) {
item.images = item.image.split(',')
} else {
item.images = []
}
if (item.homeImage) {
item.homeImages = item.homeImage.split(',')
} else {
item.homeImages = []
}
if (item.iconTitle) {
item.iconTitles = item.iconTitle.split(',')
} else {
item.iconTitles = []
}
})
if (this.pageNo === 1) {
this.list = response.result.records
} else {
this.list = this.list.concat(response.result.records)
}
}
}).catch(error => {
uni.stopPullDownRefresh()
this.loading = false
console.error('获取房源列表失败:', error)
uni.showToast({
title: '获取数据失败',
icon: 'none'
})
})
},
//
refreshData() {
this.pageNo = 1
this.list = []
this.loadMyHouses()
},
//
loadMore() {
this.pageNo += 1
this.loadMyHouses()
},
//
onDetail(item) {
uni.navigateTo({
url: `/pages_subpack/detail/index?id=${item.id}`
})
},
//
onEdit(item) {
//
let editUrl = '/pages_subpack/house/index'
//
if (item.category === 'farmhouse') {
editUrl = '/pages_subpack/house/farmhouse'
} else if (item.category === 'commercial') {
editUrl = '/pages_subpack/house/commercial'
} else if (item.category === 'other') {
editUrl = '/pages_subpack/house/other'
}
uni.navigateTo({
url: `${editUrl}?id=${item.id}&mode=edit`
})
},
//
onDelete(item) {
uni.showModal({
title: '确认删除',
content: '确定要删除这个房源吗?删除后无法恢复。',
cancelText: '取消',
confirmText: '删除',
confirmColor: '#ff4757',
success: (res) => {
if (res.confirm) {
this.deleteHouse(item.id)
}
}
})
},
//
deleteHouse(houseId) {
uni.showLoading({
title: '删除中...'
})
deleteHouse({ id: houseId }).then(response => {
uni.hideLoading()
uni.showToast({
title: '删除成功',
icon: 'success'
})
//
this.refreshData()
}).catch(error => {
uni.hideLoading()
console.error('删除房源失败:', error)
uni.showToast({
title: '删除失败',
icon: 'none'
})
})
},
//
goToPublish() {
uni.navigateTo({
url: '/pages_subpack/house/select'
})
}
}
}
</script>
<style>
page {
background-color: #f5f5f5;
}
/* 操作按钮样式 */
.action-buttons {
position: absolute;
top: 20rpx;
right: 20rpx;
display: flex;
gap: 10rpx;
}
.action-btn {
display: flex;
flex-direction: column;
align-items: center;
padding: 8rpx 12rpx;
border-radius: 10rpx;
background: rgba(255, 255, 255, 0.95);
box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.1);
font-size: 20rpx;
min-width: 60rpx;
}
.edit-btn {
color: #1EC77A;
}
.delete-btn {
color: #ff4757;
}
/* 空状态样式 */
.empty-container {
padding: 100rpx 40rpx;
text-align: center;
}
.empty-tip {
margin: 30rpx 0;
font-size: 28rpx;
color: #666;
}
.publish-btn {
margin-top: 40rpx;
}
</style>

Loading…
Cancel
Save