Files
danyang-match/miniapp/pages/index/index.ts
T

277 lines
11 KiB
TypeScript
Raw Normal View History

2026-09-09 22:05:00 +08:00
/**
* 首页 - V1.1 新版(U18)
* 结构:品牌区 → 用户状态条 → Banner → 8入口 → 推荐 → 服务建议 → 活动 → 服务站 → 安全提醒
*/
2026-09-14 06:19:11 +08:00
const { authStore, appStore } = require('../../stores')
2026-09-09 22:05:00 +08:00
const api = require('../../utils/api')
2026-09-14 06:19:11 +08:00
const ENTRY_VISUALS = {
find_object: { tone: 'rose', iconAsset: '/assets/tabbar/discover-active.png' },
matchmaker: { tone: 'purple', iconAsset: '/assets/brand/logo-mark.png' },
activities: { tone: 'blue', iconAsset: '/assets/tabbar/activity-active.png' },
counseling: { tone: 'pink', iconAsset: '/assets/tabbar/message-active.png' },
classroom: { tone: 'amber', iconAsset: '/assets/covers/classroom-default.jpg' },
premarital: { tone: 'indigo', iconAsset: '/assets/tabbar/home-active.png' },
anti_fraud: { tone: 'red', iconAsset: '/assets/covers/anti-fraud-default.jpg' },
service_station: { tone: 'green', iconAsset: '/assets/covers/station-default.jpg' },
}
const QUICK_ENTRIES = [
{ code: 'find_object', label: '找对象', targetPage: '/pages/discover/discover', enabled: true },
{ code: 'matchmaker', label: '公益红娘', targetPage: '/pages/matchmaker/matchmaker', enabled: true },
{ code: 'activities', label: '公益活动', targetPage: '/pages/activity/activity', enabled: true },
{ code: 'counseling', label: '婚恋咨询', targetPage: '/pages/counseling-intro/counseling-intro', enabled: true },
{ code: 'classroom', label: '婚恋课堂', targetPage: '/pages/content/content', enabled: true },
{ code: 'premarital', label: '婚前辅导', targetPage: '/pages/premarital-intro/premarital-intro', enabled: true },
{ code: 'anti_fraud', label: '婚恋反诈', targetPage: '/pages/anti-fraud/anti-fraud', enabled: true },
{ code: 'service_station', label: '善缘服务站', targetPage: '/pages/service-station/service-station', enabled: true },
].map((entry) => ({ ...entry, ...ENTRY_VISUALS[entry.code] }))
2026-09-09 22:05:00 +08:00
Page({
data: {
unreadCount: 0,
2026-09-14 06:19:11 +08:00
loading: true,
loadError: false,
2026-09-09 22:05:00 +08:00
userState: null,
isOnboarding: false,
isVerified: false,
isPaused: false,
isSuccessful: false,
onboardingMessage: '',
onboardingActions: [],
statusChecks: [],
banners: [],
currentBannerIndex: 0,
2026-09-14 06:19:11 +08:00
quickEntries: QUICK_ENTRIES,
2026-09-09 22:05:00 +08:00
recommendations: [],
recState: 'idle',
actionLoadingUserId: '',
serviceRecommendations: [],
activities: [],
serviceLocation: null,
articles: [],
safetyNotice: {
text: '实名认证和人工审核可以提高信息真实性,交往过程中仍请谨慎涉及借款、投资和个人隐私。',
ctaText: '查看婚恋反诈指南',
ctaTarget: ''
},
emptyActions: [
{ text: '查看择偶条件', event: 'preference', variant: 'secondary' },
{ text: '申请公益红娘', event: 'matchmaker', variant: 'primary' },
],
},
onLoad() {
this.checkAuthAndLoad()
},
onShow() {
2026-09-14 06:19:11 +08:00
if (authStore.state.isLoggedIn && !this.data.loading) {
2026-09-09 22:05:00 +08:00
this.loadHomeData()
}
},
onPullDownRefresh() {
this.loadHomeData().finally(() => wx.stopPullDownRefresh())
},
// ==================== 核心加载 ====================
async checkAuthAndLoad() {
if (!authStore.state.isLoggedIn) {
this.setData({
2026-09-14 06:19:11 +08:00
loading: false,
2026-09-09 22:05:00 +08:00
isOnboarding: true,
onboardingMessage: '登录后即可开始寻找合适的人',
onboardingActions: [{ text: '去登录', event: 'login', variant: 'primary' }],
})
return
}
await this.loadHomeData()
},
async loadHomeData() {
2026-09-14 06:19:11 +08:00
this.setData({ loading: true, loadError: false })
2026-09-09 22:05:00 +08:00
try {
const res = await api.get('/home')
this.processHomeData(res)
} catch (err) {
console.error('首页数据加载失败', err)
2026-09-14 06:19:11 +08:00
this.setData({ loading: false, loadError: true, recState: 'error' })
2026-09-09 22:05:00 +08:00
}
},
processHomeData(data) {
const { userState, banners, quickEntries, recommendations,
serviceRecommendations, activities, serviceLocation, safetyNotice } = data
const relStatus = userState?.relationshipStatus || ''
const profileStatus = userState?.profileStatus || ''
const eligStatus = userState?.localEligibilityStatus || 'not_declared'
2026-09-14 06:19:11 +08:00
const isOnboarding = !userState || !userState.verified || (profileStatus !== 'approved' && profileStatus !== 'completed')
2026-09-09 22:05:00 +08:00
const isPaused = relStatus === 'paused'
const isSuccessful = relStatus === 'matched_successfully'
const isVerified = eligStatus === 'verified'
const checks = [
{ label: '已实名', done: userState?.verified || false },
2026-09-14 06:19:11 +08:00
{ label: '本地资格', done: eligStatus === 'verified' },
2026-09-09 22:05:00 +08:00
{ label: '资料已审核', done: profileStatus === 'approved' || profileStatus === 'completed' },
]
this.setData({
2026-09-14 06:19:11 +08:00
loading: false, loadError: false,
2026-09-09 22:05:00 +08:00
userState,
isOnboarding, isVerified, isPaused, isSuccessful,
onboardingMessage: this.buildOnboardingMessage(userState, profileStatus, eligStatus),
onboardingActions: this.buildOnboardingActions(userState, profileStatus, eligStatus),
statusChecks: checks,
2026-09-14 06:19:11 +08:00
banners: banners || [],
quickEntries: quickEntries?.length
? quickEntries.map((entry) => ({ ...entry, ...ENTRY_VISUALS[entry.code] }))
: QUICK_ENTRIES,
2026-09-09 22:05:00 +08:00
recommendations: recommendations || [],
recState: (recommendations && recommendations.length > 0) ? 'loaded' : 'empty',
2026-09-14 06:19:11 +08:00
serviceRecommendations: serviceRecommendations || [], activities: activities || [], serviceLocation,
articles: data.articles || [],
2026-09-09 22:05:00 +08:00
safetyNotice: safetyNotice || this.data.safetyNotice,
})
},
buildOnboardingMessage(state, profileStatus, eligStatus) {
if (!state) return '登录后即可开始寻找合适的人'
2026-09-14 06:19:11 +08:00
if (!state.verified) return '完成实名认证后,即可继续完善资料并使用公益婚恋服务'
if (profileStatus === 'pending_review') return '资料正在人工审核,请耐心等待审核结果'
2026-09-09 22:05:00 +08:00
if (eligStatus === 'not_declared') return '完成本地资格声明后即可开始寻找合适的人'
if (eligStatus === 'needs_evidence') return '补充本地资格佐证后即可开始寻找合适的人'
if (profileStatus !== 'approved' && profileStatus !== 'completed') return '资料审核通过后即可开始寻找合适的人'
return '完成资料后开始寻找合适的人'
},
buildOnboardingActions(state, profileStatus, eligStatus) {
if (!state) return [{ text: '去登录', event: 'login', variant: 'primary' }]
const actions = []
if (eligStatus === 'not_declared' || eligStatus === 'needs_evidence') {
actions.push({ text: '声明本地资格', event: 'local-eligibility', variant: 'primary' })
}
if (profileStatus !== 'approved' && profileStatus !== 'completed') {
actions.push({ text: '完善资料', event: 'profile', variant: 'secondary' })
}
if (actions.length === 0) {
actions.push({ text: '开始寻找', event: 'discover', variant: 'primary' })
}
return actions
},
// ==================== 事件处理 ====================
onBannerChange(e) {
this.setData({ currentBannerIndex: e.detail.current })
},
onBannerTap(e) {
const { targetType, targetValue } = e.currentTarget.dataset.item
if (targetType === 'activity' && targetValue) {
wx.navigateTo({ url: `/pages/activity-detail/activity-detail?id=${targetValue}` })
} else if (targetType === 'matchmaker') {
wx.navigateTo({ url: '/pages/matchmaker/matchmaker' })
2026-09-14 06:19:11 +08:00
} else {
const routes = { matchmaker: '/pages/matchmaker/matchmaker', counseling: '/pages/counseling-intro/counseling-intro', premarital: '/pages/premarital-intro/premarital-intro', service_location: '/pages/service-station/service-station', article: '/pages/content-detail/content-detail', internal_page: targetValue }
const url = routes[targetType]
if (url && /^\/pages\//.test(url)) wx.navigateTo({ url })
2026-09-09 22:05:00 +08:00
}
},
onEntryTap(e) {
const { code, enabled, targetPage } = e.currentTarget.dataset.entry
if (!enabled) {
2026-09-14 06:19:11 +08:00
wx.showToast({ title: e.currentTarget.dataset.entry.disabledReason || '暂不可使用此功能', icon: 'none' })
2026-09-09 22:05:00 +08:00
return
}
2026-09-14 06:19:11 +08:00
if (targetPage === '/pages/discover/discover' || targetPage === '/pages/activity/activity') wx.switchTab({ url: targetPage })
else if (targetPage?.startsWith('/pages/')) wx.navigateTo({ url: targetPage })
2026-09-09 22:05:00 +08:00
},
onViewDetail(e) {
const userId = e.detail?.userId || e.currentTarget.dataset?.userId
if (userId) wx.navigateTo({ url: `/pages/profile-detail/profile-detail?id=${userId}` })
},
onLike(e) {
const userId = e.detail?.userId
if (!userId) return
this.setData({ actionLoadingUserId: userId })
setTimeout(() => this.setData({ actionLoadingUserId: '' }), 500)
},
onPass(e) {
const userId = e.detail?.userId
if (!userId) return
this.setData({ actionLoadingUserId: userId })
setTimeout(() => this.setData({ actionLoadingUserId: '' }), 500)
},
onEmptyAction(e) {
const event = e.currentTarget.dataset.event
switch (event) {
case 'login':
wx.reLaunch({ url: '/pages/login/login' })
break
case 'discover':
wx.switchTab({ url: '/pages/discover/discover' })
break
case 'matchmaker':
wx.navigateTo({ url: '/pages/matchmaker/matchmaker' })
break
case 'preference':
wx.navigateTo({ url: '/pages/profile-preference/profile-preference' })
break
case 'local-eligibility':
wx.navigateTo({ url: '/pages/local-eligibility/local-eligibility' })
break
case 'profile':
wx.navigateTo({ url: '/pages/profile-basic/profile-basic' })
break
}
},
onResume() {
2026-09-14 06:19:11 +08:00
wx.navigateTo({ url: '/pages/relationship-status/relationship-status' })
2026-09-09 22:05:00 +08:00
},
onSeeMore() { wx.switchTab({ url: '/pages/discover/discover' }) },
onSeeAllActivities() { wx.switchTab({ url: '/pages/activity/activity' }) },
onActivityTap(e) {
const id = e.currentTarget.dataset.id
if (id) wx.navigateTo({ url: `/pages/activity-detail/activity-detail?id=${id}` })
},
onStationTap() {
2026-09-14 06:19:11 +08:00
wx.navigateTo({ url: '/pages/service-station/service-station' })
2026-09-09 22:05:00 +08:00
},
onServiceTap(e) {
const type = e.currentTarget.dataset.type
switch (type) {
case 'matchmaker': wx.navigateTo({ url: '/pages/matchmaker/matchmaker' })
break
case 'counseling':
2026-09-14 06:19:11 +08:00
wx.navigateTo({ url: '/pages/counseling-intro/counseling-intro' })
break
2026-09-09 22:05:00 +08:00
case 'premarital':
2026-09-14 06:19:11 +08:00
wx.navigateTo({ url: '/pages/premarital-intro/premarital-intro' })
2026-09-09 22:05:00 +08:00
break
}
},
onSafetyTap() {
2026-09-14 06:19:11 +08:00
wx.navigateTo({ url: '/pages/anti-fraud/anti-fraud' })
2026-09-09 22:05:00 +08:00
},
2026-09-14 06:19:11 +08:00
onArticleTap(e) { wx.navigateTo({ url: `/pages/content-detail/content-detail?id=${e.currentTarget.dataset.id}` }) },
2026-09-09 22:05:00 +08:00
onMessages() { wx.switchTab({ url: '/pages/messages/messages' }) },
formatDate(timestamp) {
if (!timestamp) return ''
const d = new Date(timestamp)
return `${d.getMonth() + 1}月${d.getDate()}日 ${String(d.getHours()).padStart(2, '0')}:${String(d.getMinutes()).padStart(2, '0')}`
},
})