340 lines
7.8 KiB
Vue
340 lines
7.8 KiB
Vue
<template>
|
|
<view class="card-item" @click="handleUserClick">
|
|
<view class="user" >
|
|
<image :src="item.user.avatar_pull || '/static/image/user.png'" class="avatar"></image>
|
|
<view class="info">
|
|
<view class="name">{{ item.user.nickname || '用户名' }}</view>
|
|
<view class="time">{{ item.created_at }}</view>
|
|
</view>
|
|
<button v-if="!ismysq" class="chat-btn" @click.stop="handleContact">联系门店</button>
|
|
<button
|
|
v-else
|
|
class="chat-btn"
|
|
:class="item.status==1 ? 'chat-btn1' : item.status==2 ? 'chat-btn2' : item.status==3 ? 'chat-btn3' : 'chat-btn4'"
|
|
>
|
|
{{ item.status==1 ? '已发布' : item.status==2 ? '审核中' : item.status==3 ? '未通过' : '已过期' }}
|
|
</button>
|
|
</view>
|
|
|
|
<view class="content">
|
|
<u-read-more :showHeight="80" ref="uReadMore" color="#999999" closeText="查看更多">
|
|
<rich-text :nodes="item.content" @load="handleContentLoad"></rich-text>
|
|
</u-read-more>
|
|
</view>
|
|
|
|
<!-- <view class="tags" v-if="item.tag && item.tag.length">
|
|
<text v-for="(tag, index) in item.tag" :key="index">{{ tag }}</text>
|
|
</view> -->
|
|
<view class="tags">
|
|
<text>#{{ item.age}}</text>
|
|
</view>
|
|
<view class="imgs" v-if="item.media && item.media.length">
|
|
<image
|
|
v-for="(img, index) in item.media"
|
|
:key="index"
|
|
:src="getImgUrl(img)"
|
|
class="img"
|
|
mode="aspectFill"
|
|
@click.stop="previewImage(index)"
|
|
@longpress.stop="downloadImage(img)"
|
|
/>
|
|
</view>
|
|
|
|
<view class="location" v-if="item.location_name" @click.stop="locationfn(item)">
|
|
<uni-icons type="location" color="#999" size="18"></uni-icons>
|
|
<text>{{ item.location_name }}</text>
|
|
</view>
|
|
|
|
<view class="comment" @click="handleComment">
|
|
评论({{ item.comment || 0 }})
|
|
</view>
|
|
<view v-if="ismysq" class="actions">
|
|
<view class="edit-btn" @click.stop="handleEdit">编辑</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import uReadMore from '@/uni_modules/uview-ui/components/u-read-more/u-read-more.vue'
|
|
|
|
export default {
|
|
name: 'PostCard',
|
|
components: {
|
|
uReadMore
|
|
},
|
|
props: {
|
|
item: {
|
|
type: Object,
|
|
required: true,
|
|
default: () => ({})
|
|
},
|
|
ismysq:{
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
},
|
|
methods: {
|
|
getImgUrl(img) {
|
|
if (!img) return '';
|
|
if (typeof img === 'string') return img;
|
|
return img.img_src || img.url_pull || img.url || '';
|
|
},
|
|
handleContentLoad() {
|
|
this.$nextTick(() => {
|
|
if (this.$refs.uReadMore) {
|
|
this.$refs.uReadMore.init();
|
|
}
|
|
});
|
|
},
|
|
handleUserClick() {
|
|
this.$emit('userClick', this.item);
|
|
},
|
|
handleContact() {
|
|
this.$emit('contact', this.item);
|
|
},
|
|
handleView() {
|
|
this.$emit('view', this.item);
|
|
},
|
|
previewImage(index) {
|
|
if (!this.item.media || !this.item.media.length) return;
|
|
const urls = this.item.media.map(m => this.getImgUrl(m)).filter(Boolean);
|
|
uni.previewImage({
|
|
current: index,
|
|
urls
|
|
});
|
|
},
|
|
downloadImage(img) {
|
|
const url = this.getImgUrl(img);
|
|
if (!url) return;
|
|
uni.showActionSheet({
|
|
itemList: ['保存图片'],
|
|
success: (res) => {
|
|
if (res.tapIndex === 0) {
|
|
uni.showLoading({ title: '下载中...', mask: true });
|
|
uni.downloadFile({
|
|
url,
|
|
success: (downloadRes) => {
|
|
if (downloadRes.statusCode === 200) {
|
|
uni.saveImageToPhotosAlbum({
|
|
filePath: downloadRes.tempFilePath,
|
|
success: () => {
|
|
uni.hideLoading();
|
|
uni.showToast({ title: '保存成功', icon: 'success' });
|
|
},
|
|
fail: () => {
|
|
uni.hideLoading();
|
|
uni.showToast({ title: '保存失败', icon: 'none' });
|
|
}
|
|
});
|
|
} else {
|
|
uni.hideLoading();
|
|
uni.showToast({ title: '下载失败', icon: 'none' });
|
|
}
|
|
},
|
|
fail: () => {
|
|
uni.hideLoading();
|
|
uni.showToast({ title: '下载失败', icon: 'none' });
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
},
|
|
handleComment() {
|
|
this.$emit('comment', this.item);
|
|
},
|
|
handleEdit() {
|
|
this.$emit('edit', this.item);
|
|
},
|
|
// 点击位置:获取(模糊)当前位置 -> 打开系统地图并可导航到店铺位置
|
|
async locationfn(item) {
|
|
try {
|
|
const lat = Number((item && item.latitude));
|
|
const lng = Number((item && item.longitude));
|
|
if (!Number.isFinite(lat) || !Number.isFinite(lng)) {
|
|
uni.showToast({ title: '该店铺未设置定位', icon: 'none' });
|
|
return;
|
|
}
|
|
|
|
// 1) 先尝试获取(模糊)当前位置,主要用于触发授权 & 让地图页显示“我的位置”
|
|
await this._getFuzzyCurrentLocationSafe();
|
|
|
|
// 2) 打开地图并指向店铺坐标;地图页自带“导航/到这去”
|
|
uni.openLocation({
|
|
latitude: lat,
|
|
longitude: lng,
|
|
name: (item && item.location_name) || '店铺位置',
|
|
address: (item && item.location_address) || (item && item.location_name) || '',
|
|
scale: 16,
|
|
fail: () => {
|
|
uni.showToast({ title: '打开地图失败', icon: 'none' });
|
|
}
|
|
});
|
|
} catch (e) {
|
|
// 兜底:即使定位授权失败,也尽量打开店铺位置
|
|
const lat = Number((item && item.latitude));
|
|
const lng = Number((item && item.longitude));
|
|
if (Number.isFinite(lat) && Number.isFinite(lng)) {
|
|
uni.openLocation({
|
|
latitude: lat,
|
|
longitude: lng,
|
|
name: (item && item.location_name) || '店铺位置',
|
|
address: (item && item.location_address) || (item && item.location_name) || '',
|
|
scale: 16
|
|
});
|
|
} else {
|
|
uni.showToast({ title: '打开地图失败', icon: 'none' });
|
|
}
|
|
}
|
|
},
|
|
|
|
// 获取模糊定位(不抛错版本):用于触发授权&让地图显示“我的位置”
|
|
_getFuzzyCurrentLocationSafe() {
|
|
return new Promise((resolve) => {
|
|
// 仅微信小程序支持 getFuzzyLocation
|
|
// #ifdef MP-WEIXIN
|
|
uni.authorize({
|
|
scope: 'scope.userFuzzyLocation',
|
|
success: () => {
|
|
// 直接调用微信的模糊定位
|
|
wx.getFuzzyLocation({
|
|
type: 'wgs84',
|
|
success: () => resolve(),
|
|
fail: () => resolve()
|
|
});
|
|
},
|
|
fail: () => resolve()
|
|
});
|
|
// #endif
|
|
|
|
// #ifndef MP-WEIXIN
|
|
// 其他端不处理,直接放过
|
|
resolve();
|
|
// #endif
|
|
});
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.card-item {
|
|
margin-bottom: 40rpx;
|
|
background: #fff;
|
|
padding: 20rpx;
|
|
border-radius: 10rpx;
|
|
}
|
|
|
|
.user {
|
|
flex-direction: row;
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.avatar {
|
|
width: 110rpx;
|
|
height: 110rpx;
|
|
border-radius: 50%;
|
|
}
|
|
.info {
|
|
margin-left: 20rpx;
|
|
flex: 1;
|
|
.name {
|
|
font-size: 30rpx;
|
|
font-weight: bold;
|
|
}
|
|
.time {
|
|
font-size: 24rpx;
|
|
color: #777;
|
|
margin-top: 6rpx;
|
|
}
|
|
}
|
|
.chat-btn {
|
|
padding: 0 26rpx;
|
|
height: 45rpx;
|
|
line-height: 45rpx;
|
|
border-radius: 10rpx;
|
|
background: #3BC6BD;
|
|
color: #fff;
|
|
font-size: 22rpx;
|
|
border: none;
|
|
}
|
|
.chat-btn1{
|
|
background:rgb(59 198 189 / 20%);
|
|
color: #3BC6BD;
|
|
}
|
|
.chat-btn2{
|
|
background: rgb(62 94 215 / 20%);
|
|
color: #3E5ED7;
|
|
|
|
}
|
|
.chat-btn3{
|
|
background: rgb(255 0 0 / 20%);
|
|
color: #FF0000;
|
|
}
|
|
.chat-btn4{
|
|
background: rgb(105 105 105 / 20%);
|
|
color: #696969;
|
|
}
|
|
}
|
|
|
|
.content {
|
|
margin-top: 20rpx;
|
|
font-size: 28rpx;
|
|
color: #444;
|
|
}
|
|
|
|
.tags {
|
|
margin-top: 20rpx;
|
|
|
|
text {
|
|
margin-right: 20rpx;
|
|
padding: 10rpx 20rpx;
|
|
border-radius: 30rpx;
|
|
font-size: 24rpx;
|
|
color: #3BC6BD;
|
|
}
|
|
}
|
|
|
|
.imgs {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
margin-top: 20rpx;
|
|
|
|
.img {
|
|
width: 30%;
|
|
margin-right: 3%;
|
|
margin-bottom: 3%;
|
|
border-radius: 12rpx;
|
|
height: 190rpx;
|
|
}
|
|
}
|
|
|
|
.location {
|
|
display: flex;
|
|
align-items: center;
|
|
color: #666666;
|
|
font-size: 22rpx;
|
|
margin-top: 20rpx;
|
|
gap: 8rpx;
|
|
}
|
|
|
|
.comment {
|
|
border: 1px solid #ccc;
|
|
text-align: center;
|
|
line-height: 66rpx;
|
|
border-radius: 34rpx;
|
|
margin: 20rpx 0;
|
|
font-size: 26rpx;
|
|
color: #666;
|
|
}
|
|
.actions{
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
}
|
|
.edit-btn{
|
|
font-size: 26rpx;
|
|
color: #3BC6BD;
|
|
padding: 10rpx 0;
|
|
}
|
|
</style>
|