70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
import { request } from '../utils/request'
|
|
import * as auth from '../utils/auth'
|
|
import { STORAGE_KEYS } from '../utils/config'
|
|
|
|
// 未读红点轮询最小间隔,避免频繁切 tab 时重复打接口
|
|
const SYNC_INTERVAL = 30 * 1000
|
|
let lastSyncAt = 0
|
|
|
|
Component({
|
|
data: {
|
|
selected: 0,
|
|
unread: 0,
|
|
list: [
|
|
{ pagePath: '/pages/wardrobe/wardrobe', text: '衣橱', icon: 'icon-hanger' },
|
|
{ pagePath: '/pages/outfit/outfit', text: '穿搭', icon: 'icon-shirt' },
|
|
{ pagePath: '/pages/horoscope/horoscope', text: '运势', icon: 'icon-sparkles' },
|
|
{ pagePath: '/pages/closet-share/closet-share', text: '分享', icon: 'icon-share' },
|
|
{ pagePath: '/pages/profile/profile', text: '我的', icon: 'icon-user' },
|
|
],
|
|
},
|
|
|
|
lifetimes: {
|
|
attached() {
|
|
// 首帧渲染流程结束后再更新:先用缓存渲染红点,未登录时不再发请求(否则会批量 401 并触发重定向)
|
|
const cached = (wx.getStorageSync(STORAGE_KEYS.UNREAD) as number) || 0
|
|
wx.nextTick(() => {
|
|
this.setData({ unread: cached })
|
|
this.syncUnread()
|
|
})
|
|
},
|
|
},
|
|
|
|
methods: {
|
|
// 直接更新红点(供页面在已知数量时调用,不再触发二次请求)
|
|
setUnread(n: number) {
|
|
const unread = Number(n) || 0
|
|
wx.setStorageSync(STORAGE_KEYS.UNREAD, unread)
|
|
this.setData({ unread })
|
|
},
|
|
|
|
// 拉取未读数:仅登录态才请求,且做节流
|
|
syncUnread(force?: boolean) {
|
|
if (!auth.isLoggedIn()) {
|
|
this.setUnread(0)
|
|
return
|
|
}
|
|
const now = Date.now()
|
|
if (!force && now - lastSyncAt < SYNC_INTERVAL) return
|
|
lastSyncAt = now
|
|
|
|
request<{ unread_count: number }>({
|
|
url: '/notification/unread',
|
|
showError: false,
|
|
silentAuth: true,
|
|
})
|
|
.then((res) => this.setUnread(res.unread_count || 0))
|
|
.catch(() => {
|
|
// 请求失败时回滚节流时间戳,否则要白等 30s 才能重试
|
|
lastSyncAt = 0
|
|
})
|
|
},
|
|
|
|
switchTab(e: WechatMiniprogram.TouchEvent) {
|
|
const { path, index } = e.currentTarget.dataset as { path: string; index: number }
|
|
wx.switchTab({ url: path })
|
|
this.setData({ selected: index })
|
|
},
|
|
},
|
|
})
|