修改互助详情评论列表

This commit is contained in:
qiuyuan 2025-07-28 18:51:47 +08:00
parent a2dda03fdb
commit 68354f01d4
3 changed files with 366 additions and 167 deletions

View File

@ -113,12 +113,22 @@
<u-icon name="map-fill" color="#fff" size="28"></u-icon>
<text>导航前往</text>
</button>
<button class="share-button" @click="handleShare">
<u-icon name="share-square" color="#8dbafc" size="28"></u-icon>
<text>分享</text>
<button class="share-button" open-type="share" @click="handleShareClick">
<u-icon name="share-square" color="#8dbafc" size="28"></u-icon>
<text>分享</text>
</button>
</view>
</view>
<!-- 授权弹窗 -->
<u-modal
v-model="showLocationModal"
title="位置授权提示"
:content="locationModalContent"
show-cancel-button
@confirm="handleAuthConfirm"
@cancel="handleAuthCancel"
></u-modal>
</view>
</template>
@ -158,6 +168,10 @@ export default {
status: 1
},
local: null,
showLocationModal: false,
locationModalContent: '我们需要获取您的位置信息,以便提供更精准的服务',
userLocation: null,
isRequestingLocation: false
}
},
computed: {
@ -188,10 +202,17 @@ export default {
}
},
onLoad(options) {
if (options && options.Id && options.local) {
this.Id = options.Id;
this.local = options.local;
if (options?.Id) {
this.Id = options.Id;
this.local = options.local || null;
this.getAroundDetail();
}
//
wx.showShareMenu({
withShareTicket: true,
menus: ['shareAppMessage', 'shareTimeline']
});
},
mounted() {
this.getAroundDetail();
@ -207,26 +228,147 @@ export default {
},
async getAroundDetail() {
try {
const res = await get(`/api/v1/apps/surrounding/${this.Id}`);
if (!res || !res.success) {
throw new Error('获取详情失败');
}
if (res.data.storeCover) {
res.data.storeCover = res.data.storeCover.startsWith('http') ? res.data.storeCover : IMAGE_BASE_URL + res.data.storeCover;
}
this.detailInfo = {...this.detailInfo, ...res.data};
} catch (err) {
console.error('获取详情失败:', err);
uni.showToast({
title: '获取详情失败',
icon: 'none'
});
}
try {
const res = await get(`/api/v1/apps/surrounding/${this.Id}`);
if (res?.success) {
this.detailInfo = {
...this.detailInfo,
...res.data,
storeCover: res.data.storeCover?.startsWith('http')
? res.data.storeCover
: IMAGE_BASE_URL + res.data.storeCover
};
}
} catch (error) {
console.error('获取详情失败:', error);
uni.showToast({ title: '获取详情失败', icon: 'none' });
}
},
//
async handleShareClick() {
this.isRequestingLocation = true;
try {
await this.checkLocationPermission();
} catch (error) {
console.error('位置授权异常:', error);
} finally {
this.isRequestingLocation = false;
}
},
//
async checkLocationPermission() {
const status = await this.getPermissionStatus();
if (status === 'granted') {
await this.getUserLocation();
return;
}
if (status === 'none') {
//
this.requestLocationPermission();
} else {
//
this.showLocationModal = true;
}
},
//
getPermissionStatus() {
return new Promise((resolve) => {
uni.getSetting({
success: (res) => {
if (res.authSetting['scope.userLocation'] === undefined) {
resolve('none');
} else if (res.authSetting['scope.userLocation']) {
resolve('granted');
} else {
resolve('denied');
}
},
fail: () => resolve('none')
});
});
},
//
requestLocationPermission() {
uni.authorize({
scope: 'scope.userLocation',
success: () => this.getUserLocation(),
fail: (err) => {
console.error('授权失败:', err);
this.showLocationModal = true;
}
});
},
//
getUserLocation() {
return new Promise((resolve, reject) => {
uni.getLocation({
type: 'wgs84',
success: (res) => {
this.userLocation = {
latitude: res.latitude,
longitude: res.longitude
};
resolve(res);
},
fail: (err) => {
console.error('获取位置失败:', err);
reject(err);
}
});
});
},
//
handleAuthConfirm() {
uni.openSetting({
success: (res) => {
if (res.authSetting['scope.userLocation']) {
this.getUserLocation().catch(() => {
uni.showToast({ title: '获取位置失败', icon: 'none' });
});
}
this.showLocationModal = false;
}
});
},
//
handleAuthCancel() {
this.showLocationModal = false;
uni.showToast({ title: '已取消位置授权', icon: 'none' });
},
//
onShareAppMessage() {
return {
title: this.detailInfo.storeName || '发现一个好地方',
path: `/pages/surrounding/detail?Id=${this.Id}`,
imageUrl: this.detailInfo.storeCover,
success: () => {
this.logShareEvent();
},
fail: (err) => {
console.error('分享失败:', err);
}
};
},
//
onShareTimeline() {
return {
title: this.detailInfo.storeName || '发现一个好地方',
query: `Id=${this.Id}`,
imageUrl: this.detailInfo.storeCover
};
},
openMap() {
const { latitude, longitude, storeName, storeAddress } = this.detailInfo;
if (latitude && longitude) {

View File

@ -1,17 +1,20 @@
<template>
<view class="container">
<view v-for="(item, index) in list" :key="index" class="shop-card" @click="goPage('aroundDetail')">
<view v-for="(item, index) in list" :key="index" class="shop-card" @click="goDetail(item.id,item.distance)">
<u-cell :border="false" class="custom-cell">
<image slot="icon" :src="item.image" mode="aspectFill" class="cell-image"></image>
<image slot="icon" :src="`${IMAGE_BASE_URL}`+item.storeCover" mode="aspectFill" class="cell-image"></image>
<view slot="title" class="cell-right">
<view class="shop-name">{{ item.name }}</view>
<view class="shop-name">{{ item.storeName }}</view>
<view class="shop-info">
<!-- <text> {{ item.rating }} </text> -->
<text>人均¥{{ item.perCapita }}</text>
<text class="distance">直线{{ item.distance }}m</text>
<text class="price">{{ item.price > 0 ? `人均¥${item.price}` : '免费开放' }}</text>
<text class="distance">{{ formatDistance(item.distance) }}</text>
</view>
<view class="desc-container">
<text class="desc">{{ "“" + item.desc + "”" }}</text>
<view class="shop-desc" v-if="item.content">
<text>{{ truncateContent(item.content) }}</text>
</view>
<view class="open-time" v-if="item.openAt">
<u-icon name="clock" size="24" color="#8a8a8a"></u-icon>
<text>开放时间{{ item.openAt }}</text>
</view>
</view>
</u-cell>
@ -20,128 +23,173 @@
</template>
<script>
import { get, post } from '@/utils/request';
import { IMAGE_BASE_URL, BASE_URL } from '@/utils/config';
export default {
data() {
return {
list: [{
image: "/static/imgs/service/hema.png", // static
name: '肯德基(南通紫琅店)',
rating: 4.8,
monthSales: 4683,
perCapita: 30,
distance: 221,
desc: '超棒,同学们都说好吃'
},
{
image: "/static/imgs/service/hema.png",
name: '汉堡王(南通紫琅店)',
rating: 4.8,
monthSales: 4683,
perCapita: 30,
distance: 221,
desc: '超棒,同学们都说好吃'
},
{
image: "/static/imgs/service/hema.png",
name: '瑞幸咖啡(南通紫琅店)',
rating: 4.8,
monthSales: 4683,
perCapita: 30,
distance: 221,
desc: '超棒,同学们都说不错'
},
{
image: "/static/imgs/service/hema.png",
name: '绿茶餐厅',
rating: 4.8,
monthSales: 4683,
perCapita: 30,
distance: 221,
desc: '超棒,同学们都说好吃'
}
]
IMAGE_BASE_URL,
Id: null,
latitude: null,
longitude: null,
list: []
};
},
onLoad() {
onLoad(options) {
if (options && options.Id && options.latitude && options.longitude) {
this.Id = options.Id;
this.longitude = options.longitude;
this.latitude = options.latitude;
}
},
mounted() {
this.getAroundList();
},
methods: {
//
goPage(page) {
console.log("==进来", page)
uni.navigateTo({
url: `/pages/${page}/index`,
success: () => {
console.log('切换到tabBar页面成功');
},
fail: (err) => {
console.error('切换到tabBar页面失败:', err);
async getAroundList() {
let params = {
current: 1,
pageSize: 100,
longitude: this.longitude,
latitude: this.latitude,
typeId: this.Id,
}
try {
const res = await get('/api/v1/apps/surrounding', params);
if (!res || !res.success) {
throw new Error('获取列表失败');
}
this.list = res.data || [];
} catch (err) {
console.error('获取列表失败:', err);
uni.showToast({
title: '加载失败',
icon: 'none'
});
}
},
goDetail(id, local) {
uni.navigateTo({
url: `/pages/aroundDetail/index?Id=${id}&local=${local}`,
});
},
formatDistance(distance) {
if (distance >= 1000) {
return `距离${(distance / 1000).toFixed(1)}km`;
}
return `距离${Math.round(distance)}m`;
},
truncateContent(content) {
if (content.length > 60) {
return content.substring(0, 60) + '...';
}
return content;
}
}
};
</script>
<style lang="scss" scoped>
.container {
padding: 10px;
padding: 20rpx;
background-color: #f8f9fa;
min-height: 100vh;
}
.shop-card {
margin-bottom: 15px;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
background-color: #fff;
.shop-card {
margin-bottom: 24rpx;
border-radius: 16rpx;
background-color: #fff;
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
overflow: hidden;
transition: all 0.2s ease;
&:active {
transform: scale(0.98);
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
}
}
.custom-cell {
padding: 0;
}
.cell-image {
width: 240rpx;
height: 240rpx;
flex-shrink: 0;
background-color: #f5f5f5;
}
.cell-right {
padding: 24rpx;
flex: 1;
}
.shop-name {
font-size: 32rpx;
font-weight: 600;
color: #2c3e50;
margin-bottom: 12rpx;
line-height: 1.4;
}
.shop-info {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12rpx;
font-size: 26rpx;
.price {
color: #3498db;
font-weight: 500;
background-color: rgba(52, 152, 219, 0.1);
padding: 4rpx 12rpx;
border-radius: 6rpx;
}
.custom-cell {
.distance {
color: #7f8c8d;
font-size: 24rpx;
display: flex;
align-items: center;
padding: 12px 15px;
}
.cell-image {
width: 80px;
height: 80px;
border-radius: 8px;
}
.cell-right {
display: flex;
flex-direction: column;
margin-left: 10px;
.shop-name {
font-size: 16px;
font-weight: bold;
margin-bottom: 4px;
}
.shop-info {
font-size: 12px;
color: #999;
margin-bottom: 4px;
display: flex;
flex-wrap: wrap;
.distance {
margin-left: auto;
}
}
.desc-container {
display: inline-block;
margin-top: 5px;
}
.desc {
font-size: 12px;
padding: 5px 10px;
color: rgba(128, 128, 128, 1);
background: rgba(229, 229, 229, 0.5);
border-radius: 4px;
&::before {
content: '';
display: inline-block;
width: 24rpx;
height: 24rpx;
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="%237f8c8d"><path d="M12 2C8.13 2 5 5.13 5 9c0 5.25 7 13 7 13s7-7.75 7-13c0-3.87-3.13-7-7-7zm0 9.5c-1.38 0-2.5-1.12-2.5-2.5s1.12-2.5 2.5-2.5 2.5 1.12 2.5 2.5-1.12 2.5-2.5 2.5z"/></svg>');
background-size: contain;
background-repeat: no-repeat;
margin-right: 6rpx;
}
}
}
.shop-desc {
font-size: 26rpx;
color: #555;
line-height: 1.6;
margin: 12rpx 0;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
text-overflow: ellipsis;
}
.open-time {
display: flex;
align-items: center;
font-size: 24rpx;
color: #7f8c8d;
margin-top: 8rpx;
.u-icon {
margin-right: 8rpx;
}
}
</style>

View File

@ -3,7 +3,7 @@
<view class="nearby-page">
<!-- 附近美食模块 -->
<view class="section shadow" v-for="(item,index) in aroundList" :key="index">
<view class="section-header" @click="goPage('aroundList')">
<view class="section-header" @click="goPage(item.id)">
<view class="section-title">{{item.label}}</view>
<u-icon name="arrow-right" size="20" color="#999"></u-icon>
</view>
@ -38,7 +38,9 @@
data() {
return {
IMAGE_BASE_URL,
aroundList:[]
aroundList:[],
longitude:null,
latitude:null,
}
},
onLoad() {},
@ -51,6 +53,11 @@
url: `/pages/aroundDetail/index?Id=${id}&local=${local}`,
});
},
goPage(id){
uni.navigateTo({
url: `/pages/aroundList/index?Id=${id}&latitude=${this.latitude}&longitude=${this.longitude}`,
});
},
formatDistance(distance) {
if (!distance) return '未知距离';
if (distance < 1000) {
@ -61,6 +68,8 @@
},
async surroundingList() {
const position = await this.getCurrentPosition();
this.latitude = position.latitude;
this.longitude = position.longitude;
let params = {
current: 1,
pageSize: 10,