2025-09-28 15:37:59 +08:00

402 lines
17 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>
<view class="community-list-container">
<view class="top">
<image src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/communityTopImg.png" mode=""></image>
</view>
<view class="community-list">
<view class="community-item-box" v-for="(item, index) in communityList" :key="index">
<view class="community-item">
<view class="community-image" @tap="enterCommunity(item)">
<!-- 使用默认图片作为 fallback -->
<image :src="item.pic || defaultCommunityImage" mode="aspectFill"
@error="handleImageError(item)"></image>
</view>
<view class="community-info">
<view class="community-name" @tap="enterCommunity(item)">{{ item.name }}</view>
<view class="community-property">物业公司{{ item.property || '-' }}</view>
<view class="community-distance">距我当前{{ item.distance || '未知' }}</view>
<view class="community-buttons">
<view class="community-action-btn" @tap="navigate(item)">
<uni-icons type="paperplane-filled" size="18"></uni-icons>
<text class="btn-text">导航</text>
</view>
<view class="community-action-btn" @tap="callPhone(item)" v-if="item.property_server_phone">
<uni-icons type="phone-filled" size="18"></uni-icons>
<view class="btn-text">电话</view>
</view>
</view>
<view v-if="item.isShow" class="enter-btn" @tap="enterCommunity(item)">进入小区</view>
</view>
</view>
<view class="community-address">
<image id="local"
src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/local_localIcon.png"
mode="aspectFill"></image>
<view class="community-address-text">{{ item.addr }}</view>
</view>
</view>
</view>
<nav-footer :current="0" />
</view>
</template>
<script>
import {
request,
picUrl,
uniqueByField,
menuButtonInfo,
NavgateTo,
calculateDistance
} from "../../../utils";
import { apiArr } from "../../../api/community";
export default {
name: 'CommunityList',
data() {
return {
communityList: [], // 用于显示的列表
allCommunityList: [], // 存储所有数据的列表
currentPage: 1,
pageSize: 16,
hasMoreData: true,
isLoading: false,
tencentMapKey: '55NBZ-MUQYW-EAJRL-YIWPA-ZXCR6-4NBPP', // 腾讯地图API Key
defaultCommunityImage: 'https://wechat-img-file.oss-cn-beijing.aliyuncs.com/community_no_image3.png' // 默认小区图片
};
},
methods: {
async getCommunityList() {
// 如果正在加载中,则不再请求
if (this.isLoading) {
return;
}
// 显示加载中提示
uni.showLoading({
title: '加载中...'
});
this.isLoading = true;
try {
// 获取用户当前位置
const locationData = await this.getUserLocation();
if (!locationData) {
throw new Error('无法获取用户位置');
}
const userLat = parseFloat(locationData.lat);
const userLng = parseFloat(locationData.lng);
// 获取现有小区列表
const res = await request(apiArr.getAllList, "POST", {
page_num: 1,
page_size: 9999
});
if (res && res.rows) {
// 处理现有数据只保留距离1km以内的小区
let processedList = res.rows.map(item => {
// 处理图片路径
if (item.pic) {
item.pic = picUrl + item.pic;
}
try {
// 只有当经纬度都有效时才计算距离
if (userLat && userLng && item.lat && item.lng) {
const parkLat = parseFloat(item.lat);
const parkLng = parseFloat(item.lng);
// 使用Haversine公式计算距离单位千米
const distance = calculateDistance(userLat, userLng, parkLat, parkLng);
item.distance = distance.toFixed(2) + 'km';
item.distanceValue = distance; // 保存数值型距离用于排序
}
} catch (error) {
console.error('计算距离失败:', error);
item.distanceValue = Infinity;
}
// 初始化isShow属性
item.isShow = true;
return item;
});
// 过滤出距离1km以内的数据
processedList = processedList.filter(item =>
item.distanceValue && item.distanceValue <= 1
);
// 调用腾讯地图API获取附近1km的小区包含图片信息
const nearbyCommunities = await this.getNearbyCommunities(userLat, userLng);
// 合并现有数据和腾讯地图API返回的数据
let mergedList = [...processedList];
if (nearbyCommunities && nearbyCommunities.length > 0) {
// 处理腾讯地图返回的数据,提取图片信息
const tencentCommunities = nearbyCommunities.map(item => {
// 计算距离
const distance = calculateDistance(userLat, userLng, item.lat, item.lng);
// 提取图片腾讯地图POI可能包含多张图片
let communityImage = '';
if (item.photos && item.photos.length > 0) {
// 取第一张图片
communityImage = item.photos[0].url;
}
return {
name: item.title,
addr: item.address,
lat: item.lat,
lng: item.lng,
distance: distance.toFixed(2) + 'km',
distanceValue: distance,
// 补充其他必要字段
pic: communityImage || this.defaultCommunityImage, // 使用腾讯地图图片或默认图片
property: item.extension && item.extension.property_company ? item.extension.property_company : '-',
property_server_phone: item.tel || '',
community_id: `tencent_${item.id}` // 为腾讯地图数据设置唯一ID
};
});
// 过滤腾讯地图数据只保留那些name不在接口返回数据中的小区
// 创建一个包含接口返回数据所有name的Set
const processedNames = new Set(processedList.map(item => item.name));
// 过滤腾讯地图数据
const filteredTencentCommunities = tencentCommunities.filter(item =>
!processedNames.has(item.name)
);
// 合并数据
mergedList = [...processedList, ...filteredTencentCommunities];
// 根据community_id去重
mergedList = uniqueByField(mergedList, 'community_id');
}
// 根据距离排序
mergedList.sort((a, b) => {
const distanceA = a.distanceValue || Infinity;
const distanceB = b.distanceValue || Infinity;
return distanceA - distanceB;
});
// 保存所有数据到allCommunityList
this.allCommunityList = mergedList;
this.currentPage = 1;
this.updateDisplayList();
}
} catch (error) {
console.error('获取社区列表失败:', error);
uni.showToast({
title: '获取数据失败',
icon: 'none',
duration: 1500
});
} finally {
this.isLoading = false;
// 隐藏加载中提示
uni.hideLoading();
}
},
// 获取用户当前位置
getUserLocation() {
return new Promise((resolve, reject) => {
try {
let locationData = uni.getStorageSync('location');
if (locationData) {
// 确保locationData是对象而不是字符串
const location = typeof locationData === 'string' ? JSON.parse(locationData) : locationData;
if (location.lat && location.lng) {
resolve(location);
return;
}
}
} catch (error) {
console.error('从缓存获取位置失败:', error);
}
// 如果缓存中没有有效位置,则请求新的位置
uni.getLocation({
type: 'gcj02',
altitude: true,
success: (res) => {
const location = {
lat: res.latitude,
lng: res.longitude
};
// 保存到缓存
uni.setStorageSync('location', location);
resolve(location);
},
fail: (err) => {
console.error('获取位置失败:', err);
reject(err);
}
});
});
},
// 调用腾讯地图API获取附近1km的小区包含图片信息
async getNearbyCommunities(lat, lng) {
try {
const keyword = '小区';
const radius = 1000; // 1km范围
const pageSize = 20;
// 使用uni.request调用腾讯地图API增加extensions=all参数获取更多信息
return new Promise((resolve, reject) => {
uni.request({
url: 'https://apis.map.qq.com/ws/place/v1/search',
method: 'GET',
data: {
keyword: keyword,
boundary: `nearby(${lat},${lng},${radius})`,
key: this.tencentMapKey,
page_size: pageSize,
extensions: 'all' // 获取详细信息,包括图片
},
success: (res) => {
if (res.statusCode === 200 && res.data.status === 0) {
// 提取需要的数据,包括图片信息
const results = res.data.data.map(item => ({
id: item.id,
title: item.title,
address: item.address,
lat: item.location.lat,
lng: item.location.lng,
tel: item.tel || '',
photos: item.photos || [], // 提取图片数组
extension: item.extension || {}, // 提取扩展信息,可能包含物业公司
isShow: false
}));
resolve(results);
} else {
console.error('腾讯地图API请求失败:', res.data);
resolve([]);
}
},
fail: (err) => {
console.error('腾讯地图API请求错误:', err);
resolve([]);
}
});
});
} catch (error) {
console.error('获取附近小区失败:', error);
return [];
}
},
// 图片加载失败时使用默认图片
handleImageError(item) {
item.pic = this.defaultCommunityImage;
},
// 更新显示的列表数据
updateDisplayList() {
const startIndex = 0;
const endIndex = this.currentPage * this.pageSize;
this.communityList = this.allCommunityList.slice(startIndex, endIndex);
this.hasMoreData = endIndex < this.allCommunityList.length;
},
navigate(item) {
// 实现导航功能
if (item.lat && item.lng) {
// 确保经纬度是有效的数字
const latitude = parseFloat(item.lat);
const longitude = parseFloat(item.lng);
if (!isNaN(latitude) && !isNaN(longitude)) {
uni.openLocation({
latitude: latitude,
longitude: longitude,
name: item.name || '未知小区',
address: item.addr || '',
scale: 18,
success: () => {
console.log('打开地图成功:', item.name);
},
fail: (error) => {
console.error('打开地图失败:', error);
}
});
} else {
uni.showToast({
title: '位置信息无效',
icon: 'none',
duration: 1500
});
}
} else {
uni.showToast({
title: '暂无位置信息',
icon: 'none',
duration: 1500
});
}
},
callPhone(item) {
if (item.property_server_phone) {
uni.makePhoneCall({
phoneNumber: item.property_server_phone,
success: () => {
},
fail: (error) => {
}
});
} else {
uni.showToast({
title: '暂无联系电话',
icon: 'none',
duration: 1500
});
}
},
enterCommunity(item) {
request(apiArr.checkComm, "POST", {
community_id: item.community_id,
user_id: uni.getStorageSync("userId"),
}).then((res) => {
uni.setStorageSync("is_me", res.is_me)
NavgateTo("/packages/community/index/index?item=" + JSON.stringify(item));
})
},
// 下拉加载更多
loadMore() {
if (this.hasMoreData && !this.isLoading) {
this.currentPage += 1;
this.updateDisplayList();
}
}
},
onLoad() {
this.getCommunityList();
},
// 监听页面滚动到底部
onReachBottom() {
this.loadMore();
},
// 下拉刷新
onPullDownRefresh() {
this.currentPage = 1;
this.hasMoreData = true;
this.getCommunityList().then(() => {
uni.stopPullDownRefresh();
});
}
};
</script>
<style>
@import url("./index.css");
</style>