wangfukang 1 week ago
parent
commit
977ca76dd8
  1. 250
      components/tab-bar/postList.vue
  2. 24
      components/tab-bar/tab-bar.vue

250
components/tab-bar/postList.vue

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

24
components/tab-bar/tab-bar.vue

@ -7,6 +7,9 @@
<view class="red-dot" v-if="index == 1 && indexWorkerCount > 0"> <view class="red-dot" v-if="index == 1 && indexWorkerCount > 0">
{{formatBadgeCount(indexWorkerCount)}} {{formatBadgeCount(indexWorkerCount)}}
</view> </view>
<view class="red-dot" v-if="index == 3 && indexFishCount > 0">
{{formatBadgeCount(indexFishCount)}}
</view>
<view class="red-dot" v-if="index == 4 && indexMyCount > 0"> <view class="red-dot" v-if="index == 4 && indexMyCount > 0">
{{formatBadgeCount(indexMyCount)}} {{formatBadgeCount(indexMyCount)}}
</view> </view>
@ -60,6 +63,7 @@
}], }],
indexZhipaiCount:0, indexZhipaiCount:0,
indexWorkerCount:0, indexWorkerCount:0,
indexFishCount:0,
indexMyCount:0, indexMyCount:0,
countRefreshId:0 countRefreshId:0
} }
@ -90,10 +94,12 @@
}, },
mounted() { mounted() {
uni.$on('deliveryStatusCountsChange', this.setDeliveryStatusCounts) uni.$on('deliveryStatusCountsChange', this.setDeliveryStatusCounts)
uni.$on('fishUnreadChange', this.setFishUnreadCounts)
this.setDeliveryStatusCounts(uni.getStorageSync('deliveryStatusCounts') || {}) this.setDeliveryStatusCounts(uni.getStorageSync('deliveryStatusCounts') || {})
}, },
beforeDestroy() { beforeDestroy() {
uni.$off('deliveryStatusCountsChange', this.setDeliveryStatusCounts) uni.$off('deliveryStatusCountsChange', this.setDeliveryStatusCounts)
uni.$off('fishUnreadChange', this.setFishUnreadCounts)
}, },
methods: { methods: {
hasLogin() { hasLogin() {
@ -115,6 +121,14 @@
this.indexWorkerCount = (Number(counts.daiqu) || 0) + (Number(counts.daisong) || 0) this.indexWorkerCount = (Number(counts.daiqu) || 0) + (Number(counts.daisong) || 0)
this.$forceUpdate() this.$forceUpdate()
}, },
setFishUnreadCounts(summary) {
if (summary && summary.fishUnread !== undefined) {
this.indexFishCount = Number(summary.fishUnread) || 0
this.$forceUpdate()
return
}
this.getWorkerCounts()
},
//tab //tab
clickBar(index) { clickBar(index) {
if (index !== 0 && !this.hasLogin()) { if (index !== 0 && !this.hasLogin()) {
@ -145,7 +159,11 @@
const refreshId = ++this.countRefreshId const refreshId = ++this.countRefreshId
this.indexZhipaiCount = 0 this.indexZhipaiCount = 0
this.indexWorkerCount = 0 this.indexWorkerCount = 0
this.indexFishCount = 0
this.indexMyCount = 0 this.indexMyCount = 0
if (!this.hasLogin()) {
return Promise.resolve()
}
let deliveryStatusCounts = { let deliveryStatusCounts = {
daiqu: 0, daiqu: 0,
daisong: 0 daisong: 0
@ -161,6 +179,12 @@
} }
let shopCounts = 0 let shopCounts = 0
let tasks = [] let tasks = []
tasks.push(this.tui.request("/app/fishmarket/unread/summary", "GET", {}, false, true).then((res) => {
if (res && res.success !== false) {
const result = res.result || res
this.indexFishCount = Number(result.fishUnread) || 0
}
}).catch(() => {}))
if(worker){ if(worker){
const area = uni.getStorageSync('area') ? JSON.parse(uni.getStorageSync('area')) : {} const area = uni.getStorageSync('area') ? JSON.parse(uni.getStorageSync('area')) : {}
tasks.push(this.tui.request("/mall/delivery/countOrderByStatus", "POST", {workerId:worker.workerId,regionId:area.id}, false, true).then((res) => { tasks.push(this.tui.request("/mall/delivery/countOrderByStatus", "POST", {workerId:worker.workerId,regionId:area.id}, false, true).then((res) => {

Loading…
Cancel
Save