|
|
|
@ -3,7 +3,7 @@ |
|
|
|
<view class="nav" :style="{ paddingTop: statusBarTop + 'px' }"> |
|
|
|
<view class="nav-btn" @tap="back"><uni-icons type="left" size="24" color="#18372f"></uni-icons></view> |
|
|
|
<view class="nav-title">{{isWant ? '求购详情' : '闲置详情'}}</view> |
|
|
|
<view class="nav-btn" @tap="share"><uni-icons type="redo" size="22" color="#18372f"></uni-icons></view> |
|
|
|
<view class="nav-btn"></view> |
|
|
|
</view> |
|
|
|
|
|
|
|
<scroll-view scroll-y class="content-scroll" :style="{ paddingTop: navHeight + 'px' }"> |
|
|
|
@ -31,6 +31,9 @@ |
|
|
|
<view class="price">{{isWant ? '预算 ¥' : '¥'}}{{displayPrice}}</view> |
|
|
|
<view class="origin" v-if="!isWant && goods.originPrice">¥{{goods.originPrice}}</view> |
|
|
|
<view class="sale-status">{{saleStatusText}}</view> |
|
|
|
<button class="card-share-btn" open-type="share"> |
|
|
|
<uni-icons type="redo" size="18" color="#21b886"></uni-icons> |
|
|
|
</button> |
|
|
|
</view> |
|
|
|
<view class="title">{{goods.title}}</view> |
|
|
|
<view class="meta"> |
|
|
|
@ -79,17 +82,18 @@ |
|
|
|
<image :src="item.userAvatar || defaultAvatar" mode="aspectFill"></image> |
|
|
|
<view class="comment-main"> |
|
|
|
<view class="comment-name"> |
|
|
|
{{item.userName || '校园同学'}} |
|
|
|
半径同学 |
|
|
|
<text v-if="item.sellerReply">卖家</text> |
|
|
|
</view> |
|
|
|
<view class="comment-content">{{item.content}}</view> |
|
|
|
<view class="reply-list" v-if="item.replies && item.replies.length"> |
|
|
|
<view class="reply-item" v-for="reply in item.replies" :key="reply.id"> |
|
|
|
<text class="reply-name">{{reply.userName || '校园同学'}}</text> |
|
|
|
<text class="reply-name">半径同学</text> |
|
|
|
<text class="seller-badge" v-if="reply.sellerReply">卖家</text> |
|
|
|
<text class="reply-target" v-if="reply.replyToUserName"> 回复 {{reply.replyToUserName}}</text> |
|
|
|
<text>:{{reply.content}}</text> |
|
|
|
<text class="reply-action" @tap="replyComment(item, reply)">回复</text> |
|
|
|
<text class="reply-action reply-delete" v-if="reply.userId == currentUserId" @tap="deleteComment(reply)">删除</text> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
<view class="comment-actions"> |
|
|
|
@ -137,7 +141,7 @@ |
|
|
|
</view> |
|
|
|
<view class="bar-action" v-if="!isWant" @tap="favorite"> |
|
|
|
<uni-icons :type="goods && goods.favorited ? 'star-filled' : 'star'" size="22" :color="goods && goods.favorited ? '#ffb22d' : '#59706a'"></uni-icons> |
|
|
|
<text>收藏</text> |
|
|
|
<text>收藏 {{favoriteCountText}}</text> |
|
|
|
</view> |
|
|
|
<view class="bar-action" @tap="reportGoods"> |
|
|
|
<uni-icons type="flag" size="22" color="#59706a"></uni-icons> |
|
|
|
@ -145,6 +149,17 @@ |
|
|
|
</view> |
|
|
|
<view class="consult-btn" @tap="consult">{{isWant ? '我有货' : '立即咨询'}}</view> |
|
|
|
</view> |
|
|
|
<view class="page-like-effect" v-if="pageLikeEffects.length"> |
|
|
|
<view |
|
|
|
class="page-like-heart" |
|
|
|
:class="effect.className" |
|
|
|
:style="effect.style" |
|
|
|
v-for="effect in pageLikeEffects" |
|
|
|
:key="effect.id" |
|
|
|
> |
|
|
|
<view class="page-like-heart-shape"></view> |
|
|
|
</view> |
|
|
|
</view> |
|
|
|
<ie-auth-dialog /> |
|
|
|
</view> |
|
|
|
</template> |
|
|
|
@ -164,6 +179,7 @@ |
|
|
|
} from '@/common/fishMarketApi.js' |
|
|
|
import { getIeProfile } from '@/common/ieApi.js' |
|
|
|
import { ensureIeVerifiedBeforeAction } from '@/common/ieRealNameAuth.js' |
|
|
|
import { buildHomeSharePath } from '@/utils/sharePath.js' |
|
|
|
import IeAuthDialog from '@/package2/components/ie-auth-dialog/ie-auth-dialog.vue' |
|
|
|
|
|
|
|
export default { |
|
|
|
@ -184,9 +200,13 @@ |
|
|
|
commentSubmitting: false, |
|
|
|
replyTarget: {}, |
|
|
|
defaultAvatar: '', |
|
|
|
defaultShareImage: '/static/images/img/songshu.png', |
|
|
|
currentUserId: uni.getStorageSync('id') || '', |
|
|
|
currentImageIndex: 0, |
|
|
|
imageHeights: {} |
|
|
|
imageHeights: {}, |
|
|
|
likeEffectSeq: 0, |
|
|
|
likeEffectTimers: {}, |
|
|
|
pageLikeEffects: [] |
|
|
|
} |
|
|
|
}, |
|
|
|
computed: { |
|
|
|
@ -238,19 +258,47 @@ |
|
|
|
}, |
|
|
|
commentPlaceholder() { |
|
|
|
return this.replyTarget && this.replyTarget.id ? '回复 ' + (this.replyTarget.userName || '校园同学') : '写下你的评论' |
|
|
|
}, |
|
|
|
favoriteCountText() { |
|
|
|
return this.goods && this.goods.favoriteCount ? this.goods.favoriteCount : 0 |
|
|
|
} |
|
|
|
}, |
|
|
|
onLoad(options) { |
|
|
|
this.id = options && options.id ? options.id : '' |
|
|
|
this.detailType = options && options.type == 'want' ? 'want' : 'goods' |
|
|
|
if (uni.getMenuButtonBoundingClientRect) { |
|
|
|
this.statusBarTop = uni.getMenuButtonBoundingClientRect().top || this.statusBarTop |
|
|
|
const rect = uni.getMenuButtonBoundingClientRect() |
|
|
|
this.statusBarTop = rect.top || this.statusBarTop |
|
|
|
} |
|
|
|
this.load() |
|
|
|
}, |
|
|
|
onShareAppMessage() { |
|
|
|
return this.buildShareInfo() |
|
|
|
}, |
|
|
|
onShareTimeline() { |
|
|
|
const info = this.buildShareInfo() |
|
|
|
return { |
|
|
|
title: info.title, |
|
|
|
query: info.path.split('?')[1] || '', |
|
|
|
imageUrl: info.imageUrl |
|
|
|
} |
|
|
|
}, |
|
|
|
onUnload() { |
|
|
|
Object.keys(this.likeEffectTimers || {}).forEach(key => { |
|
|
|
clearTimeout(this.likeEffectTimers[key]) |
|
|
|
}) |
|
|
|
this.likeEffectTimers = {} |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
back() { |
|
|
|
uni.navigateBack() |
|
|
|
const pages = getCurrentPages ? getCurrentPages() : [] |
|
|
|
if (pages && pages.length > 1) { |
|
|
|
uni.navigateBack() |
|
|
|
return |
|
|
|
} |
|
|
|
uni.reLaunch({ |
|
|
|
url: '/pages/index/index?tabIndex=3' |
|
|
|
}) |
|
|
|
}, |
|
|
|
load() { |
|
|
|
if (!this.id) return |
|
|
|
@ -381,19 +429,48 @@ |
|
|
|
}) |
|
|
|
}, |
|
|
|
likeComment(item) { |
|
|
|
const shouldAnimate = !item.liked |
|
|
|
if (shouldAnimate) { |
|
|
|
this.playLikeEffect() |
|
|
|
} |
|
|
|
toggleFishLike({ commentId: item.id, likeType: 'comment' }).then(res => { |
|
|
|
if (!res) return |
|
|
|
this.$set(item, 'liked', !!res.liked) |
|
|
|
item.likeCount = Number(res.count) || 0 |
|
|
|
}) |
|
|
|
}, |
|
|
|
favorite() { |
|
|
|
if (!this.goods) return |
|
|
|
const shouldAnimate = !this.goods.favorited |
|
|
|
if (shouldAnimate) { |
|
|
|
this.playLikeEffect() |
|
|
|
} |
|
|
|
toggleFishFavorite(this.id).then(res => { |
|
|
|
if (!res) return |
|
|
|
this.$set(this.goods, 'favorited', !!res.favorited) |
|
|
|
this.$set(this.goods, 'favoriteCount', Number(res.count) || 0) |
|
|
|
}) |
|
|
|
}, |
|
|
|
playLikeEffect() { |
|
|
|
const burstId = Date.now() + '-' + (++this.likeEffectSeq) |
|
|
|
const tracks = ['one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight'] |
|
|
|
const effects = tracks.map((name, index) => ({ |
|
|
|
id: burstId + '-' + index, |
|
|
|
className: 'page-like-heart--' + name, |
|
|
|
style: `left:${6 + ((index * 59) % 86)}%; animation-delay:${index * 95}ms;` |
|
|
|
})) |
|
|
|
this.pageLikeEffects = effects |
|
|
|
const timerKey = 'page' |
|
|
|
if (this.likeEffectTimers[timerKey]) { |
|
|
|
clearTimeout(this.likeEffectTimers[timerKey]) |
|
|
|
} |
|
|
|
this.likeEffectTimers[timerKey] = setTimeout(() => { |
|
|
|
if (this.pageLikeEffects.length && String(this.pageLikeEffects[0].id).indexOf(burstId) === 0) { |
|
|
|
this.pageLikeEffects = [] |
|
|
|
} |
|
|
|
delete this.likeEffectTimers[timerKey] |
|
|
|
}, 3050) |
|
|
|
}, |
|
|
|
reportGoods() { |
|
|
|
this.report({ complaintType: this.isWant ? 'want' : 'goods', goodsId: this.id }) |
|
|
|
}, |
|
|
|
@ -434,7 +511,27 @@ |
|
|
|
}) |
|
|
|
}, |
|
|
|
share() { |
|
|
|
// #ifdef MP-WEIXIN |
|
|
|
uni.showShareMenu({ |
|
|
|
withShareTicket: true, |
|
|
|
menus: ['shareAppMessage', 'shareTimeline'] |
|
|
|
}) |
|
|
|
uni.showToast({ title: '请点击右上角分享', icon: 'none' }) |
|
|
|
// #endif |
|
|
|
// #ifndef MP-WEIXIN |
|
|
|
uni.showToast({ title: '请使用右上角分享', icon: 'none' }) |
|
|
|
// #endif |
|
|
|
}, |
|
|
|
buildShareInfo() { |
|
|
|
const title = this.goods && this.goods.title ? this.goods.title : (this.isWant ? '校园二手求购' : '校园二手商品') |
|
|
|
const prefix = this.isWant ? '同学正在求购:' : '校园二手好物:' |
|
|
|
const typeQuery = this.isWant ? '&type=want' : '' |
|
|
|
const targetPath = `/package2/IdleTrad/detail?id=${this.id || ''}${typeQuery}` |
|
|
|
return { |
|
|
|
title: prefix + title, |
|
|
|
path: buildHomeSharePath(targetPath), |
|
|
|
imageUrl: this.imageList.length ? this.imageList[0] : this.defaultShareImage |
|
|
|
} |
|
|
|
}, |
|
|
|
copyText(text, title) { |
|
|
|
if (!text) return |
|
|
|
@ -554,6 +651,25 @@ |
|
|
|
font-weight: 800; |
|
|
|
} |
|
|
|
|
|
|
|
.card-share-btn { |
|
|
|
width: 48rpx; |
|
|
|
height: 48rpx; |
|
|
|
margin: 0 0 0 12rpx; |
|
|
|
padding: 0; |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
justify-content: center; |
|
|
|
border: 0; |
|
|
|
border-radius: 24rpx; |
|
|
|
background: #e8fbf3; |
|
|
|
line-height: 48rpx; |
|
|
|
flex-shrink: 0; |
|
|
|
} |
|
|
|
|
|
|
|
.card-share-btn::after { |
|
|
|
border: 0; |
|
|
|
} |
|
|
|
|
|
|
|
.title { |
|
|
|
margin-top: 16rpx; |
|
|
|
font-size: 34rpx; |
|
|
|
@ -752,6 +868,10 @@ |
|
|
|
font-weight: 900; |
|
|
|
} |
|
|
|
|
|
|
|
.reply-delete { |
|
|
|
color: #ef4c3f; |
|
|
|
} |
|
|
|
|
|
|
|
.comment-actions { |
|
|
|
margin-top: 10rpx; |
|
|
|
display: flex; |
|
|
|
@ -881,6 +1001,142 @@ |
|
|
|
line-height: 82rpx; |
|
|
|
} |
|
|
|
|
|
|
|
.page-like-effect { |
|
|
|
position: fixed; |
|
|
|
top: 0; |
|
|
|
left: 0; |
|
|
|
right: 0; |
|
|
|
bottom: 0; |
|
|
|
overflow: hidden; |
|
|
|
pointer-events: none; |
|
|
|
z-index: 99999; |
|
|
|
} |
|
|
|
|
|
|
|
.page-like-heart { |
|
|
|
position: absolute; |
|
|
|
bottom: -230rpx; |
|
|
|
width: 120rpx; |
|
|
|
height: 120rpx; |
|
|
|
opacity: 0; |
|
|
|
transform-origin: center; |
|
|
|
animation-duration: 2600ms; |
|
|
|
animation-timing-function: cubic-bezier(.14, .66, .22, 1); |
|
|
|
animation-fill-mode: forwards; |
|
|
|
} |
|
|
|
|
|
|
|
.page-like-heart-shape { |
|
|
|
position: absolute; |
|
|
|
left: 50%; |
|
|
|
top: 50%; |
|
|
|
width: 72%; |
|
|
|
height: 72%; |
|
|
|
background: linear-gradient(135deg, rgba(255, 176, 207, .72), rgba(255, 88, 148, .36)); |
|
|
|
border-radius: 18rpx 18rpx 10rpx 18rpx; |
|
|
|
box-shadow: |
|
|
|
0 18rpx 42rpx rgba(255, 104, 164, .28), |
|
|
|
inset 14rpx 18rpx 28rpx rgba(255, 255, 255, .32); |
|
|
|
filter: blur(.2rpx); |
|
|
|
transform: translate(-50%, -50%) rotate(45deg); |
|
|
|
} |
|
|
|
|
|
|
|
.page-like-heart-shape::before, |
|
|
|
.page-like-heart-shape::after { |
|
|
|
content: ''; |
|
|
|
position: absolute; |
|
|
|
width: 100%; |
|
|
|
height: 100%; |
|
|
|
border-radius: 50%; |
|
|
|
background: inherit; |
|
|
|
box-shadow: inherit; |
|
|
|
} |
|
|
|
|
|
|
|
.page-like-heart-shape::before { |
|
|
|
left: -50%; |
|
|
|
top: 0; |
|
|
|
} |
|
|
|
|
|
|
|
.page-like-heart-shape::after { |
|
|
|
left: 0; |
|
|
|
top: -50%; |
|
|
|
} |
|
|
|
|
|
|
|
.page-like-heart--one { width: 154rpx; height: 154rpx; animation-name: pageHeartFloatOne; } |
|
|
|
.page-like-heart--two { width: 112rpx; height: 112rpx; animation-name: pageHeartFloatTwo; } |
|
|
|
.page-like-heart--three { width: 188rpx; height: 188rpx; animation-name: pageHeartFloatThree; } |
|
|
|
.page-like-heart--four { width: 92rpx; height: 92rpx; animation-name: pageHeartFloatFour; } |
|
|
|
.page-like-heart--five { width: 136rpx; height: 136rpx; animation-name: pageHeartFloatFive; } |
|
|
|
.page-like-heart--six { width: 82rpx; height: 82rpx; animation-name: pageHeartFloatSix; } |
|
|
|
.page-like-heart--seven { width: 166rpx; height: 166rpx; animation-name: pageHeartFloatSeven; } |
|
|
|
.page-like-heart--eight { width: 104rpx; height: 104rpx; animation-name: pageHeartFloatEight; } |
|
|
|
|
|
|
|
.page-like-heart--three .page-like-heart-shape, |
|
|
|
.page-like-heart--seven .page-like-heart-shape { |
|
|
|
background: linear-gradient(135deg, rgba(255, 198, 220, .66), rgba(255, 103, 158, .28)); |
|
|
|
filter: blur(1rpx); |
|
|
|
} |
|
|
|
|
|
|
|
.page-like-heart--four .page-like-heart-shape, |
|
|
|
.page-like-heart--six .page-like-heart-shape, |
|
|
|
.page-like-heart--eight .page-like-heart-shape { |
|
|
|
background: linear-gradient(135deg, rgba(255, 211, 226, .74), rgba(255, 126, 174, .32)); |
|
|
|
} |
|
|
|
|
|
|
|
@keyframes pageHeartFloatOne { |
|
|
|
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.68) rotate(-8deg); } |
|
|
|
14% { opacity: .82; transform: translate3d(-18rpx, -92rpx, 0) scale(1) rotate(5deg); } |
|
|
|
62% { opacity: .52; transform: translate3d(-72rpx, -370rpx, 0) scale(.94) rotate(-12deg); } |
|
|
|
100% { opacity: 0; transform: translate3d(-112rpx, -650rpx, 0) scale(.72) rotate(-22deg); } |
|
|
|
} |
|
|
|
|
|
|
|
@keyframes pageHeartFloatTwo { |
|
|
|
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.62) rotate(6deg); } |
|
|
|
16% { opacity: .7; transform: translate3d(28rpx, -112rpx, 0) scale(.92) rotate(-6deg); } |
|
|
|
64% { opacity: .44; transform: translate3d(96rpx, -350rpx, 0) scale(.82) rotate(12deg); } |
|
|
|
100% { opacity: 0; transform: translate3d(146rpx, -600rpx, 0) scale(.62) rotate(22deg); } |
|
|
|
} |
|
|
|
|
|
|
|
@keyframes pageHeartFloatThree { |
|
|
|
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.64) rotate(-4deg); } |
|
|
|
12% { opacity: .64; transform: translate3d(8rpx, -86rpx, 0) scale(.94) rotate(7deg); } |
|
|
|
60% { opacity: .38; transform: translate3d(-36rpx, -420rpx, 0) scale(.78) rotate(-12deg); } |
|
|
|
100% { opacity: 0; transform: translate3d(-68rpx, -710rpx, 0) scale(.58) rotate(-24deg); } |
|
|
|
} |
|
|
|
|
|
|
|
@keyframes pageHeartFloatFour { |
|
|
|
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.58) rotate(12deg); } |
|
|
|
18% { opacity: .68; transform: translate3d(-26rpx, -124rpx, 0) scale(.86) rotate(-6deg); } |
|
|
|
66% { opacity: .4; transform: translate3d(-112rpx, -320rpx, 0) scale(.72) rotate(14deg); } |
|
|
|
100% { opacity: 0; transform: translate3d(-166rpx, -560rpx, 0) scale(.54) rotate(26deg); } |
|
|
|
} |
|
|
|
|
|
|
|
@keyframes pageHeartFloatFive { |
|
|
|
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.64) rotate(-10deg); } |
|
|
|
14% { opacity: .72; transform: translate3d(34rpx, -96rpx, 0) scale(.96) rotate(6deg); } |
|
|
|
62% { opacity: .44; transform: translate3d(68rpx, -380rpx, 0) scale(.78) rotate(-10deg); } |
|
|
|
100% { opacity: 0; transform: translate3d(104rpx, -650rpx, 0) scale(.58) rotate(-20deg); } |
|
|
|
} |
|
|
|
|
|
|
|
@keyframes pageHeartFloatSix { |
|
|
|
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.52) rotate(8deg); } |
|
|
|
20% { opacity: .64; transform: translate3d(6rpx, -132rpx, 0) scale(.8) rotate(-8deg); } |
|
|
|
68% { opacity: .36; transform: translate3d(44rpx, -290rpx, 0) scale(.64) rotate(12deg); } |
|
|
|
100% { opacity: 0; transform: translate3d(70rpx, -500rpx, 0) scale(.48) rotate(22deg); } |
|
|
|
} |
|
|
|
|
|
|
|
@keyframes pageHeartFloatSeven { |
|
|
|
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.62) rotate(-8deg); } |
|
|
|
13% { opacity: .62; transform: translate3d(-28rpx, -82rpx, 0) scale(.88) rotate(6deg); } |
|
|
|
58% { opacity: .38; transform: translate3d(-86rpx, -390rpx, 0) scale(.72) rotate(-12deg); } |
|
|
|
100% { opacity: 0; transform: translate3d(-132rpx, -680rpx, 0) scale(.52) rotate(-22deg); } |
|
|
|
} |
|
|
|
|
|
|
|
@keyframes pageHeartFloatEight { |
|
|
|
0% { opacity: 0; transform: translate3d(0, 0, 0) scale(.56) rotate(10deg); } |
|
|
|
18% { opacity: .66; transform: translate3d(38rpx, -118rpx, 0) scale(.84) rotate(-8deg); } |
|
|
|
64% { opacity: .4; transform: translate3d(122rpx, -338rpx, 0) scale(.68) rotate(14deg); } |
|
|
|
100% { opacity: 0; transform: translate3d(178rpx, -580rpx, 0) scale(.5) rotate(26deg); } |
|
|
|
} |
|
|
|
|
|
|
|
.bottom-space { |
|
|
|
height: 170rpx; |
|
|
|
} |
|
|
|
|