|
|
|
@ -60,6 +60,7 @@ |
|
|
|
> |
|
|
|
<view class="shortcut-icon"> |
|
|
|
<image class="shortcut-icon-image" :src="getPostListImage(item.imageKey)" mode="aspectFit"></image> |
|
|
|
<view class="shortcut-badge" v-if="item.action == 'sessions' && fishUnread > 0">{{formatBadgeCount(fishUnread)}}</view> |
|
|
|
</view> |
|
|
|
<view class="shortcut-name">{{item.name}}</view> |
|
|
|
<view class="shortcut-desc">{{item.action == 'publishSell' ? '点我发布' : item.desc}}</view> |
|
|
|
@ -114,7 +115,7 @@ |
|
|
|
<view class="want-count" @tap.stop="toggleLike(item)"> |
|
|
|
<uni-icons |
|
|
|
:type="item.liked ? 'heart-filled' : 'heart'" |
|
|
|
size="16" |
|
|
|
size="20" |
|
|
|
:color="item.liked ? '#27b889' : '#a5aeab'" |
|
|
|
></uni-icons> |
|
|
|
<text>{{item.xiangyao}}</text> |
|
|
|
@ -133,6 +134,17 @@ |
|
|
|
<view class="bottom-space"></view> |
|
|
|
</view> |
|
|
|
</scroll-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> |
|
|
|
</view> |
|
|
|
</template> |
|
|
|
|
|
|
|
@ -141,7 +153,8 @@ |
|
|
|
listFishCategories, |
|
|
|
pageFishGoods, |
|
|
|
pageFishWants, |
|
|
|
toggleFishLike |
|
|
|
toggleFishLike, |
|
|
|
getFishUnreadSummary |
|
|
|
} from '@/common/fishMarketApi.js' |
|
|
|
|
|
|
|
const POST_LIST_IMAGE_CACHE_KEY = 'post_list_image_cache_v1' |
|
|
|
@ -169,7 +182,7 @@ |
|
|
|
desc: '大家想要的', |
|
|
|
category: '求购', |
|
|
|
imageKey: 'wanted', |
|
|
|
action: 'category' |
|
|
|
action: 'wantSquare' |
|
|
|
}, { |
|
|
|
name: '拼团购', |
|
|
|
desc: '暂未开放', |
|
|
|
@ -195,14 +208,18 @@ |
|
|
|
imageKey: 'graduation', |
|
|
|
action: 'mine' |
|
|
|
}], |
|
|
|
baseCategories: ['推荐', '附近', '最新', '求购'], |
|
|
|
baseCategories: ['推荐', '最新'], |
|
|
|
categoryList: [], |
|
|
|
goodsList: [], |
|
|
|
pageNum: 1, |
|
|
|
pageSize: 10, |
|
|
|
totalPages: 1, |
|
|
|
loading: false, |
|
|
|
sortType: 'hot' |
|
|
|
sortType: 'hot', |
|
|
|
likeEffectSeq: 0, |
|
|
|
likeEffectTimers: {}, |
|
|
|
pageLikeEffects: [], |
|
|
|
fishUnread: 0 |
|
|
|
} |
|
|
|
}, |
|
|
|
computed: { |
|
|
|
@ -232,6 +249,14 @@ |
|
|
|
}, |
|
|
|
created() { |
|
|
|
this.applyCachedPostListImages() |
|
|
|
uni.$on('fishUnreadChange', this.handleFishUnreadChange) |
|
|
|
}, |
|
|
|
beforeDestroy() { |
|
|
|
Object.keys(this.likeEffectTimers || {}).forEach(key => { |
|
|
|
clearTimeout(this.likeEffectTimers[key]) |
|
|
|
}) |
|
|
|
this.likeEffectTimers = {} |
|
|
|
uni.$off('fishUnreadChange', this.handleFishUnreadChange) |
|
|
|
}, |
|
|
|
methods: { |
|
|
|
getPostListImage(key) { |
|
|
|
@ -375,8 +400,32 @@ |
|
|
|
} |
|
|
|
} |
|
|
|
this.loadCategories() |
|
|
|
this.loadFishUnread() |
|
|
|
this.reloadGoods() |
|
|
|
}, |
|
|
|
formatBadgeCount(count) { |
|
|
|
const value = Number(count) || 0 |
|
|
|
return value > 99 ? '99+' : value |
|
|
|
}, |
|
|
|
loadFishUnread() { |
|
|
|
const token = uni.getStorageSync('hiver_token') |
|
|
|
if (!token) { |
|
|
|
this.fishUnread = 0 |
|
|
|
return |
|
|
|
} |
|
|
|
getFishUnreadSummary().then(res => { |
|
|
|
this.fishUnread = Number(res && res.fishUnread) || 0 |
|
|
|
}).catch(() => { |
|
|
|
this.fishUnread = 0 |
|
|
|
}) |
|
|
|
}, |
|
|
|
handleFishUnreadChange(summary) { |
|
|
|
if (summary && summary.fishUnread !== undefined) { |
|
|
|
this.fishUnread = Number(summary.fishUnread) || 0 |
|
|
|
return |
|
|
|
} |
|
|
|
this.loadFishUnread() |
|
|
|
}, |
|
|
|
handleSearch() { |
|
|
|
uni.hideKeyboard() |
|
|
|
this.reloadGoods() |
|
|
|
@ -410,6 +459,10 @@ |
|
|
|
this.goFishSessions() |
|
|
|
return |
|
|
|
} |
|
|
|
if (item.action == 'wantSquare') { |
|
|
|
this.goWantSquare() |
|
|
|
return |
|
|
|
} |
|
|
|
const index = this.categories.indexOf(item.category) |
|
|
|
if (index > -1) { |
|
|
|
this.categoryIndex = index |
|
|
|
@ -555,12 +608,36 @@ |
|
|
|
uni.showToast({ title: '商品ID不能为空', icon: 'none' }) |
|
|
|
return |
|
|
|
} |
|
|
|
const shouldAnimate = !item.liked |
|
|
|
if (shouldAnimate) { |
|
|
|
this.playLikeEffect(item) |
|
|
|
} |
|
|
|
toggleFishLike({ goodsId: item.id, likeType: 'goods' }).then(res => { |
|
|
|
if (!res) return |
|
|
|
item.liked = !!res.liked |
|
|
|
item.xiangyao = Number(res.count) || 0 |
|
|
|
}) |
|
|
|
}, |
|
|
|
playLikeEffect(item) { |
|
|
|
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) |
|
|
|
}, |
|
|
|
goDetail(item) { |
|
|
|
if (!item) return |
|
|
|
if (item.type == 'want') { |
|
|
|
@ -585,6 +662,11 @@ |
|
|
|
uni.navigateTo({ |
|
|
|
url: '/package2/IdleTrad/sessionList' |
|
|
|
}) |
|
|
|
}, |
|
|
|
goWantSquare() { |
|
|
|
uni.navigateTo({ |
|
|
|
url: '/package2/IdleTrad/wantList' |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -816,7 +898,7 @@ |
|
|
|
} |
|
|
|
|
|
|
|
.shortcut-item--publish { |
|
|
|
margin-top: -8rpx; |
|
|
|
margin-top: 4rpx; |
|
|
|
} |
|
|
|
|
|
|
|
.shortcut-item--publish::before { |
|
|
|
@ -836,6 +918,7 @@ |
|
|
|
width: 84rpx; |
|
|
|
height: 84rpx; |
|
|
|
margin: 0 auto 10rpx; |
|
|
|
position: relative; |
|
|
|
} |
|
|
|
|
|
|
|
.shortcut-item--publish .shortcut-icon { |
|
|
|
@ -852,6 +935,24 @@ |
|
|
|
display: block; |
|
|
|
} |
|
|
|
|
|
|
|
.shortcut-badge { |
|
|
|
position: absolute; |
|
|
|
right: -8rpx; |
|
|
|
top: -8rpx; |
|
|
|
min-width: 30rpx; |
|
|
|
height: 30rpx; |
|
|
|
padding: 0 8rpx; |
|
|
|
border-radius: 18rpx; |
|
|
|
background: #ff4d5f; |
|
|
|
color: #fff; |
|
|
|
font-size: 18rpx; |
|
|
|
font-weight: 900; |
|
|
|
line-height: 30rpx; |
|
|
|
text-align: center; |
|
|
|
box-shadow: 0 6rpx 14rpx rgba(255, 77, 95, .26); |
|
|
|
box-sizing: border-box; |
|
|
|
} |
|
|
|
|
|
|
|
.shortcut-name { |
|
|
|
color: #29342f; |
|
|
|
font-size: 21rpx; |
|
|
|
@ -1084,6 +1185,7 @@ |
|
|
|
} |
|
|
|
|
|
|
|
.want-count { |
|
|
|
position: relative; |
|
|
|
display: flex; |
|
|
|
align-items: center; |
|
|
|
gap: 3rpx; |
|
|
|
@ -1091,6 +1193,142 @@ |
|
|
|
font-size: 17rpx; |
|
|
|
} |
|
|
|
|
|
|
|
.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); } |
|
|
|
} |
|
|
|
|
|
|
|
.empty-state { |
|
|
|
padding: 100rpx 0; |
|
|
|
color: #77827d; |
|
|
|
|