Merge branch 'yongpxu-soul' of https://github.com/fnvtk/Mycontent into yongpxu-soul
# Conflicts: # miniprogram/app.js resolved by origin/yongpxu-soul(远端) version # miniprogram/app.json resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/addresses/addresses.js resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/addresses/edit.js resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/agreement/agreement.js resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/chapters/chapters.js resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/index/index.js resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/index/index.wxml resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/match/match.js resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/my/my.js resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/my/my.wxml resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/my/my.wxss resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/privacy/privacy.js resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/purchases/purchases.js resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/read/read.js resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/read/read.wxml resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/referral/referral.js resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/referral/referral.wxml resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/referral/referral.wxss resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/settings/settings.js resolved by origin/yongpxu-soul(远端) version # miniprogram/pages/withdraw-records/withdraw-records.js resolved by origin/yongpxu-soul(远端) version # miniprogram/project.config.json resolved by origin/yongpxu-soul(远端) version # miniprogram/project.private.config.json resolved by origin/yongpxu-soul(远端) version # miniprogram/utils/chapterAccessManager.js resolved by origin/yongpxu-soul(远端) version
This commit is contained in:
@@ -38,7 +38,6 @@ Page({
|
||||
todayMatchCount: 0,
|
||||
totalMatchesAllowed: FREE_MATCH_LIMIT,
|
||||
matchesRemaining: FREE_MATCH_LIMIT,
|
||||
showQuotaExhausted: false,
|
||||
needPayToMatch: false,
|
||||
|
||||
// 匹配状态
|
||||
@@ -67,53 +66,19 @@ Page({
|
||||
// 解锁弹窗
|
||||
showUnlockModal: false,
|
||||
|
||||
// 手机号绑定弹窗(一键加好友前校验)
|
||||
showBindPhoneModal: false,
|
||||
pendingAddWechatAfterBind: false,
|
||||
bindPhoneInput: '',
|
||||
showMatchPhoneManualInput: false,
|
||||
|
||||
// 登录弹窗(未登录时点击匹配弹出)
|
||||
showLoginModal: false,
|
||||
isLoggingIn: false,
|
||||
agreeProtocol: false,
|
||||
|
||||
// 匹配价格(可配置)
|
||||
matchPrice: 1,
|
||||
extraMatches: 0,
|
||||
// 好友优惠展示(与 read 页一致)
|
||||
userDiscount: 5,
|
||||
hasReferralDiscount: false,
|
||||
showDiscountHint: false,
|
||||
displayMatchPrice: 1
|
||||
extraMatches: 0
|
||||
},
|
||||
|
||||
onLoad(options = {}) {
|
||||
// ref:支持 query.ref 或 scene 中的 ref=xxx(分享进入时)
|
||||
let ref = options.ref
|
||||
if (!ref && options.scene) {
|
||||
const sceneStr = (typeof options.scene === 'string' ? decodeURIComponent(options.scene) : '').trim()
|
||||
const parts = sceneStr.split(/[&_]/)
|
||||
for (const part of parts) {
|
||||
const eq = part.indexOf('=')
|
||||
if (eq > 0) {
|
||||
const k = part.slice(0, eq)
|
||||
const v = part.slice(eq + 1)
|
||||
if (k === 'ref' && v) { ref = v; break }
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ref) {
|
||||
wx.setStorageSync('referral_code', ref)
|
||||
app.handleReferralCode({ query: { ref } })
|
||||
}
|
||||
onLoad() {
|
||||
this.setData({
|
||||
statusBarHeight: app.globalData.statusBarHeight || 44,
|
||||
_ref: ref
|
||||
statusBarHeight: app.globalData.statusBarHeight || 44
|
||||
})
|
||||
this.loadMatchConfig()
|
||||
this.loadStoredContact()
|
||||
this.refreshMatchCountAndStatus()
|
||||
this.loadTodayMatchCount()
|
||||
this.initUserStatus()
|
||||
},
|
||||
|
||||
onShow() {
|
||||
@@ -125,53 +90,43 @@ Page({
|
||||
tabBar.setData({ selected: 2 })
|
||||
}
|
||||
}
|
||||
this.loadStoredContact()
|
||||
this.refreshMatchCountAndStatus()
|
||||
this.initUserStatus()
|
||||
},
|
||||
|
||||
// 加载匹配配置(含 userDiscount 用于好友优惠展示)
|
||||
// 加载匹配配置
|
||||
async loadMatchConfig() {
|
||||
try {
|
||||
const userId = app.globalData.userInfo?.id
|
||||
const [matchRes, configRes] = await Promise.all([
|
||||
app.request('/api/miniprogram/match/config', { method: 'GET' }),
|
||||
app.request('/api/miniprogram/config', { method: 'GET' })
|
||||
])
|
||||
|
||||
const matchPrice = matchRes?.success && matchRes?.data ? (matchRes.data.matchPrice || 1) : 1
|
||||
const userDiscount = configRes?.userDiscount ?? 5
|
||||
const hasReferral = !!(wx.getStorageSync('referral_code') || this.data._ref)
|
||||
const hasReferralDiscount = hasReferral && userDiscount > 0
|
||||
const displayMatchPrice = hasReferralDiscount
|
||||
? Math.round(matchPrice * (1 - userDiscount / 100) * 100) / 100
|
||||
: matchPrice
|
||||
|
||||
if (matchRes?.success && matchRes?.data) {
|
||||
MATCH_TYPES = matchRes.data.matchTypes || MATCH_TYPES
|
||||
FREE_MATCH_LIMIT = matchRes.data.freeMatchLimit || FREE_MATCH_LIMIT
|
||||
}
|
||||
|
||||
this.setData({
|
||||
matchTypes: MATCH_TYPES,
|
||||
totalMatchesAllowed: FREE_MATCH_LIMIT,
|
||||
matchPrice,
|
||||
userDiscount,
|
||||
hasReferralDiscount,
|
||||
showDiscountHint: userDiscount > 0,
|
||||
displayMatchPrice
|
||||
const res = await app.request({ url: '/api/match/config', silent: true, method: 'GET',
|
||||
method: 'GET'
|
||||
})
|
||||
|
||||
console.log('[Match] 加载匹配配置成功:', { matchPrice, userDiscount, hasReferralDiscount, displayMatchPrice })
|
||||
if (res.success && res.data) {
|
||||
// 更新全局配置
|
||||
MATCH_TYPES = res.data.matchTypes || MATCH_TYPES
|
||||
FREE_MATCH_LIMIT = res.data.freeMatchLimit || FREE_MATCH_LIMIT
|
||||
const matchPrice = res.data.matchPrice || 1
|
||||
|
||||
this.setData({
|
||||
matchTypes: MATCH_TYPES,
|
||||
totalMatchesAllowed: FREE_MATCH_LIMIT,
|
||||
matchPrice: matchPrice
|
||||
})
|
||||
|
||||
console.log('[Match] 加载匹配配置成功:', {
|
||||
types: MATCH_TYPES.length,
|
||||
freeLimit: FREE_MATCH_LIMIT,
|
||||
price: matchPrice
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('[Match] 加载匹配配置失败,使用默认配置:', e)
|
||||
}
|
||||
},
|
||||
|
||||
// 加载本地存储的联系方式(含用户资料的手机号、微信号)
|
||||
// 加载本地存储的联系方式
|
||||
loadStoredContact() {
|
||||
const ui = app.globalData.userInfo || {}
|
||||
const phone = wx.getStorageSync('user_phone') || ui.phone || ''
|
||||
const wechat = wx.getStorageSync('user_wechat') || ui.wechat || ui.wechatId || ''
|
||||
const phone = wx.getStorageSync('user_phone') || ''
|
||||
const wechat = wx.getStorageSync('user_wechat') || ''
|
||||
this.setData({
|
||||
phoneNumber: phone,
|
||||
wechatId: wechat,
|
||||
@@ -179,55 +134,49 @@ Page({
|
||||
})
|
||||
},
|
||||
|
||||
// 从服务端刷新匹配配额并初始化用户状态(前后端双向校验,服务端为权威)
|
||||
async refreshMatchCountAndStatus() {
|
||||
if (app.globalData.isLoggedIn && app.globalData.userInfo?.id) {
|
||||
try {
|
||||
const res = await app.request(`/api/miniprogram/user/purchase-status?userId=${encodeURIComponent(app.globalData.userInfo.id)}`)
|
||||
if (res.success && res.data) {
|
||||
app.globalData.matchCount = res.data.matchCount ?? 0
|
||||
app.globalData.matchQuota = res.data.matchQuota || null
|
||||
// 根据 hasReferrer 更新优惠展示(与 read 页一致)
|
||||
const hasReferral = !!(wx.getStorageSync('referral_code') || this.data._ref || res.data.hasReferrer)
|
||||
const matchPrice = this.data.matchPrice ?? 1
|
||||
const userDiscount = this.data.userDiscount ?? 5
|
||||
const hasReferralDiscount = hasReferral && userDiscount > 0
|
||||
const displayMatchPrice = hasReferralDiscount
|
||||
? Math.round(matchPrice * (1 - userDiscount / 100) * 100) / 100
|
||||
: matchPrice
|
||||
this.setData({ hasReferralDiscount, displayMatchPrice })
|
||||
// 加载今日匹配次数
|
||||
loadTodayMatchCount() {
|
||||
try {
|
||||
const today = new Date().toISOString().split('T')[0]
|
||||
const stored = wx.getStorageSync('match_count_data')
|
||||
if (stored) {
|
||||
const data = typeof stored === 'string' ? JSON.parse(stored) : stored
|
||||
if (data.date === today) {
|
||||
this.setData({ todayMatchCount: data.count })
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('[Match] 拉取 matchQuota 失败:', e)
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载匹配次数失败:', e)
|
||||
}
|
||||
this.initUserStatus()
|
||||
},
|
||||
|
||||
// 初始化用户状态(matchQuota 服务端纯计算:订单+match_records)
|
||||
// 保存今日匹配次数
|
||||
saveTodayMatchCount(count) {
|
||||
const today = new Date().toISOString().split('T')[0]
|
||||
wx.setStorageSync('match_count_data', { date: today, count })
|
||||
},
|
||||
|
||||
// 初始化用户状态
|
||||
initUserStatus() {
|
||||
const { isLoggedIn, hasFullBook, purchasedSections } = app.globalData
|
||||
const quota = app.globalData.matchQuota
|
||||
|
||||
// 今日剩余次数、今日已用:来自服务端 matchQuota(未登录无法计算,不能显示已用完)
|
||||
const remainToday = quota?.remainToday ?? 0
|
||||
const matchesUsedToday = quota?.matchesUsedToday ?? 0
|
||||
const purchasedRemain = quota?.purchasedRemain ?? 0
|
||||
const totalMatchesAllowed = hasFullBook ? 999999 : (quota ? remainToday + matchesUsedToday : FREE_MATCH_LIMIT)
|
||||
// 仅登录且服务端返回配额时,才判断是否已用完;未登录时显示「开始匹配」
|
||||
const needPayToMatch = isLoggedIn && !hasFullBook && (quota ? remainToday <= 0 : false)
|
||||
const showQuotaExhausted = isLoggedIn && !hasFullBook && (quota ? remainToday <= 0 : false)
|
||||
|
||||
|
||||
// 获取额外购买的匹配次数
|
||||
const extraMatches = wx.getStorageSync('extra_match_count') || 0
|
||||
|
||||
// 总匹配次数 = 每日免费(3) + 额外购买次数
|
||||
// 全书用户无限制
|
||||
const totalMatchesAllowed = hasFullBook ? 999999 : FREE_MATCH_LIMIT + extraMatches
|
||||
const matchesRemaining = hasFullBook ? 999999 : Math.max(0, totalMatchesAllowed - this.data.todayMatchCount)
|
||||
const needPayToMatch = !hasFullBook && matchesRemaining <= 0
|
||||
|
||||
this.setData({
|
||||
isLoggedIn,
|
||||
hasFullBook,
|
||||
hasPurchased: true,
|
||||
todayMatchCount: matchesUsedToday,
|
||||
hasPurchased: true, // 所有用户都可以使用匹配功能
|
||||
totalMatchesAllowed,
|
||||
matchesRemaining: hasFullBook ? 999999 : (isLoggedIn && quota ? remainToday : (isLoggedIn ? 0 : FREE_MATCH_LIMIT)),
|
||||
matchesRemaining,
|
||||
needPayToMatch,
|
||||
showQuotaExhausted,
|
||||
extraMatches: purchasedRemain
|
||||
extraMatches
|
||||
})
|
||||
},
|
||||
|
||||
@@ -243,16 +192,25 @@ Page({
|
||||
|
||||
// 点击匹配按钮
|
||||
handleMatchClick() {
|
||||
// 检测是否登录,未登录则弹出登录弹窗
|
||||
if (!this.data.isLoggedIn) {
|
||||
this.setData({ showLoginModal: true, agreeProtocol: false })
|
||||
return
|
||||
}
|
||||
|
||||
const currentType = MATCH_TYPES.find(t => t.id === this.data.selectedType)
|
||||
|
||||
// 资源对接类型需要购买章节才能使用
|
||||
// 资源对接类型需要登录+购买章节才能使用
|
||||
if (currentType && currentType.id === 'investor') {
|
||||
// 检查是否登录
|
||||
if (!this.data.isLoggedIn) {
|
||||
wx.showModal({
|
||||
title: '需要登录',
|
||||
content: '请先登录后再使用资源对接功能',
|
||||
confirmText: '去登录',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
wx.switchTab({ url: '/pages/my/my' })
|
||||
}
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否购买过章节
|
||||
const hasPurchased = app.globalData.purchasedSections?.length > 0 || app.globalData.hasFullBook
|
||||
if (!hasPurchased) {
|
||||
@@ -262,7 +220,7 @@ Page({
|
||||
confirmText: '去购买',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
wx.switchTab({ url: '/pages/chapters/chapters' })
|
||||
wx.switchTab({ url: '/pages/catalog/catalog' })
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -277,8 +235,7 @@ Page({
|
||||
const hasWechat = !!this.data.wechatId
|
||||
|
||||
if (!hasPhone && !hasWechat) {
|
||||
// 没有绑定联系方式,先显示绑定提示(仍尝试加载已有资料填充)
|
||||
this.loadStoredContact()
|
||||
// 没有绑定联系方式,先显示绑定提示
|
||||
this.setData({
|
||||
showJoinModal: true,
|
||||
joinType: currentType.id,
|
||||
@@ -295,12 +252,12 @@ Page({
|
||||
return
|
||||
}
|
||||
|
||||
// 创业合伙类型 - 超过匹配次数时直接弹出付费弹窗
|
||||
if (this.data.showQuotaExhausted || this.data.needPayToMatch) {
|
||||
// 创业合伙类型 - 真正的匹配功能
|
||||
if (this.data.needPayToMatch) {
|
||||
this.setData({ showUnlockModal: true })
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
this.startMatch()
|
||||
},
|
||||
|
||||
@@ -322,8 +279,6 @@ Page({
|
||||
const delay = Math.random() * 2000 + 1000
|
||||
setTimeout(() => {
|
||||
clearInterval(timer)
|
||||
// 打开弹窗前调取用户资料填充手机号、微信号
|
||||
this.loadStoredContact()
|
||||
this.setData({
|
||||
isMatching: false,
|
||||
showJoinModal: true,
|
||||
@@ -352,7 +307,6 @@ Page({
|
||||
|
||||
// 开始匹配 - 只匹配数据库中的真实用户
|
||||
async startMatch() {
|
||||
this.loadStoredContact()
|
||||
this.setData({
|
||||
isMatching: true,
|
||||
matchAttempts: 0,
|
||||
@@ -364,28 +318,20 @@ Page({
|
||||
this.setData({ matchAttempts: this.data.matchAttempts + 1 })
|
||||
}, 1000)
|
||||
|
||||
// 从数据库获取真实用户匹配(后端会校验剩余次数)
|
||||
// 从数据库获取真实用户匹配
|
||||
let matchedUser = null
|
||||
let quotaExceeded = false
|
||||
try {
|
||||
const ui = app.globalData.userInfo || {}
|
||||
const phone = (wx.getStorageSync('user_phone') || ui.phone || this.data.phoneNumber || '').trim()
|
||||
const wechatId = (wx.getStorageSync('user_wechat') || ui.wechat || ui.wechatId || this.data.wechatId || '').trim()
|
||||
const res = await app.request('/api/miniprogram/match/users', {
|
||||
const res = await app.request({ url: '/api/match/users', silent: true,
|
||||
method: 'POST',
|
||||
data: {
|
||||
matchType: this.data.selectedType,
|
||||
userId: app.globalData.userInfo?.id || '',
|
||||
phone,
|
||||
wechatId
|
||||
userId: app.globalData.userInfo?.id || ''
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
if (res.success && res.data) {
|
||||
matchedUser = res.data
|
||||
console.log('[Match] 从数据库匹配到用户:', matchedUser.nickname)
|
||||
} else if (res.code === 'QUOTA_EXCEEDED') {
|
||||
quotaExceeded = true
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('[Match] 数据库匹配失败:', e)
|
||||
@@ -395,14 +341,7 @@ Page({
|
||||
const delay = Math.random() * 2000 + 2000
|
||||
setTimeout(() => {
|
||||
clearInterval(timer)
|
||||
|
||||
// 次数用尽(后端校验)- 直接弹出付费弹窗
|
||||
if (quotaExceeded) {
|
||||
this.setData({ isMatching: false, showUnlockModal: true })
|
||||
this.refreshMatchCountAndStatus()
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// 如果没有匹配到用户,提示用户
|
||||
if (!matchedUser) {
|
||||
this.setData({ isMatching: false })
|
||||
@@ -414,17 +353,23 @@ Page({
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 匹配成功:从服务端刷新配额(后端已写入 match_records)
|
||||
|
||||
// 增加今日匹配次数
|
||||
const newCount = this.data.todayMatchCount + 1
|
||||
const matchesRemaining = this.data.hasFullBook ? 999999 : Math.max(0, this.data.totalMatchesAllowed - newCount)
|
||||
|
||||
this.setData({
|
||||
isMatching: false,
|
||||
currentMatch: matchedUser,
|
||||
needPayToMatch: false
|
||||
todayMatchCount: newCount,
|
||||
matchesRemaining,
|
||||
needPayToMatch: !this.data.hasFullBook && matchesRemaining <= 0
|
||||
})
|
||||
this.refreshMatchCountAndStatus()
|
||||
|
||||
this.saveTodayMatchCount(newCount)
|
||||
|
||||
// 上报匹配行为到存客宝
|
||||
this.reportMatch(matchedUser)
|
||||
|
||||
}, delay)
|
||||
},
|
||||
|
||||
@@ -460,7 +405,7 @@ Page({
|
||||
// 上报匹配行为
|
||||
async reportMatch(matchedUser) {
|
||||
try {
|
||||
await app.request('/api/miniprogram/ckb/match', {
|
||||
await app.request({ url: '/api/ckb/match', silent: true,
|
||||
method: 'POST',
|
||||
data: {
|
||||
matchType: this.data.selectedType,
|
||||
@@ -490,78 +435,26 @@ Page({
|
||||
this.setData({ currentMatch: null })
|
||||
},
|
||||
|
||||
// 添加微信好友(先校验手机号绑定)
|
||||
// 添加微信好友
|
||||
handleAddWechat() {
|
||||
if (!this.data.currentMatch) return
|
||||
|
||||
// 未登录需先登录
|
||||
if (!app.globalData.isLoggedIn) {
|
||||
wx.showModal({
|
||||
title: '需要登录',
|
||||
content: '请先登录后再添加好友',
|
||||
confirmText: '去登录',
|
||||
success: (res) => {
|
||||
if (res.confirm) wx.switchTab({ url: '/pages/my/my' })
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 判断是否已绑定手机号(本地缓存或用户资料)
|
||||
const hasPhone = !!(
|
||||
wx.getStorageSync('user_phone') ||
|
||||
app.globalData.userInfo?.phone
|
||||
)
|
||||
|
||||
if (!hasPhone) {
|
||||
this.setData({
|
||||
showBindPhoneModal: true,
|
||||
pendingAddWechatAfterBind: true
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
this.doCopyWechat()
|
||||
},
|
||||
|
||||
// 执行复制联系方式(优先微信号,无则复制手机号)
|
||||
doCopyWechat() {
|
||||
if (!this.data.currentMatch) return
|
||||
const wechat = (this.data.currentMatch.wechat || this.data.currentMatch.wechatId || '').trim()
|
||||
const phone = (this.data.currentMatch.phone || '').trim()
|
||||
const toCopy = wechat || phone
|
||||
if (!toCopy) {
|
||||
wx.showModal({
|
||||
title: '暂无可复制',
|
||||
content: '该用户未提供微信号或手机号,请通过其他方式联系',
|
||||
showCancel: false,
|
||||
confirmText: '知道了'
|
||||
})
|
||||
return
|
||||
}
|
||||
const label = wechat ? '微信号' : '手机号'
|
||||
wx.setClipboardData({
|
||||
data: toCopy,
|
||||
data: this.data.currentMatch.wechat,
|
||||
success: () => {
|
||||
wx.showModal({
|
||||
title: wechat ? '微信号已复制' : '手机号已复制',
|
||||
content: wechat
|
||||
? `${label}:${toCopy}\n\n请打开微信添加好友,备注"创业合作"即可`
|
||||
: `${label}:${toCopy}\n\n可通过微信搜索该手机号添加好友`,
|
||||
title: '微信号已复制',
|
||||
content: `微信号:${this.data.currentMatch.wechat}\n\n请打开微信添加好友,备注"创业合作"即可`,
|
||||
showCancel: false,
|
||||
confirmText: '知道了'
|
||||
})
|
||||
},
|
||||
fail: () => {
|
||||
wx.showToast({ title: '复制失败,请重试', icon: 'none' })
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 切换联系方式类型(同步刷新用户资料填充)
|
||||
// 切换联系方式类型
|
||||
switchContactType(e) {
|
||||
const type = e.currentTarget.dataset.type
|
||||
this.loadStoredContact()
|
||||
this.setData({ contactType: type, joinError: '' })
|
||||
},
|
||||
|
||||
@@ -672,150 +565,6 @@ Page({
|
||||
this.setData({ showJoinModal: false, joinError: '' })
|
||||
},
|
||||
|
||||
// 关闭手机绑定弹窗
|
||||
closeBindPhoneModal() {
|
||||
this.setData({
|
||||
showBindPhoneModal: false,
|
||||
pendingAddWechatAfterBind: false,
|
||||
bindPhoneInput: '',
|
||||
showMatchPhoneManualInput: false
|
||||
})
|
||||
},
|
||||
|
||||
// 关闭登录弹窗
|
||||
closeLoginModal() {
|
||||
if (this.data.isLoggingIn) return
|
||||
this.setData({ showLoginModal: false })
|
||||
},
|
||||
|
||||
// 切换协议勾选
|
||||
toggleAgree() {
|
||||
this.setData({ agreeProtocol: !this.data.agreeProtocol })
|
||||
},
|
||||
|
||||
// 打开用户协议
|
||||
openUserProtocol() {
|
||||
wx.navigateTo({ url: '/pages/agreement/agreement' })
|
||||
},
|
||||
|
||||
// 打开隐私政策
|
||||
openPrivacy() {
|
||||
wx.navigateTo({ url: '/pages/privacy/privacy' })
|
||||
},
|
||||
|
||||
// 微信登录(匹配页)
|
||||
async handleMatchWechatLogin() {
|
||||
if (!this.data.agreeProtocol) {
|
||||
wx.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' })
|
||||
return
|
||||
}
|
||||
this.setData({ isLoggingIn: true })
|
||||
try {
|
||||
const result = await app.login()
|
||||
if (result) {
|
||||
// 登录成功后必须拉取 matchQuota,否则无法正确显示剩余次数
|
||||
await this.refreshMatchCountAndStatus()
|
||||
this.setData({ showLoginModal: false, agreeProtocol: false })
|
||||
wx.showToast({ title: '登录成功', icon: 'success' })
|
||||
} else {
|
||||
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[Match] 微信登录错误:', e)
|
||||
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
|
||||
} finally {
|
||||
this.setData({ isLoggingIn: false })
|
||||
}
|
||||
},
|
||||
|
||||
// 一键获取手机号(匹配页加好友前绑定)
|
||||
async onMatchGetPhoneNumber(e) {
|
||||
if (e.detail.errMsg !== 'getPhoneNumber:ok') {
|
||||
wx.showToast({ title: '授权失败', icon: 'none' })
|
||||
return
|
||||
}
|
||||
const code = e.detail.code
|
||||
if (!code) {
|
||||
this.setData({ showMatchPhoneManualInput: true })
|
||||
return
|
||||
}
|
||||
try {
|
||||
wx.showLoading({ title: '获取中...', mask: true })
|
||||
const userId = app.globalData.userInfo?.id
|
||||
const res = await app.request('/api/miniprogram/phone', {
|
||||
method: 'POST',
|
||||
data: { code, userId }
|
||||
})
|
||||
wx.hideLoading()
|
||||
if (res.success && res.phoneNumber) {
|
||||
await this.saveMatchPhoneAndContinue(res.phoneNumber)
|
||||
} else {
|
||||
this.setData({ showMatchPhoneManualInput: true })
|
||||
}
|
||||
} catch (err) {
|
||||
wx.hideLoading()
|
||||
this.setData({ showMatchPhoneManualInput: true })
|
||||
}
|
||||
},
|
||||
|
||||
// 切换为手动输入
|
||||
onMatchShowManualInput() {
|
||||
this.setData({ showMatchPhoneManualInput: true })
|
||||
},
|
||||
|
||||
// 手动输入手机号
|
||||
onMatchPhoneInput(e) {
|
||||
this.setData({
|
||||
bindPhoneInput: e.detail.value.replace(/\D/g, '').slice(0, 11)
|
||||
})
|
||||
},
|
||||
|
||||
// 确认手动绑定手机号
|
||||
async confirmMatchPhoneBind() {
|
||||
const { bindPhoneInput } = this.data
|
||||
if (!bindPhoneInput || bindPhoneInput.length !== 11) {
|
||||
wx.showToast({ title: '请输入正确的11位手机号', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (!/^1[3-9]\d{9}$/.test(bindPhoneInput)) {
|
||||
wx.showToast({ title: '请输入正确的手机号', icon: 'none' })
|
||||
return
|
||||
}
|
||||
await this.saveMatchPhoneAndContinue(bindPhoneInput)
|
||||
},
|
||||
|
||||
// 保存手机号到本地+服务器,并继续加好友
|
||||
async saveMatchPhoneAndContinue(phone) {
|
||||
wx.setStorageSync('user_phone', phone)
|
||||
if (app.globalData.userInfo) {
|
||||
app.globalData.userInfo.phone = phone
|
||||
wx.setStorageSync('userInfo', app.globalData.userInfo)
|
||||
}
|
||||
this.setData({
|
||||
phoneNumber: phone,
|
||||
userPhone: phone,
|
||||
bindPhoneInput: ''
|
||||
})
|
||||
this.loadStoredContact()
|
||||
try {
|
||||
const userId = app.globalData.userInfo?.id
|
||||
if (userId) {
|
||||
await app.request('/api/miniprogram/user/profile', {
|
||||
method: 'POST',
|
||||
data: { userId, phone }
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('[Match] 同步手机号到服务器失败:', e)
|
||||
}
|
||||
const pending = this.data.pendingAddWechatAfterBind
|
||||
this.closeBindPhoneModal()
|
||||
if (pending) {
|
||||
wx.showToast({ title: '绑定成功', icon: 'success' })
|
||||
setTimeout(() => this.doCopyWechat(), 500)
|
||||
}
|
||||
},
|
||||
|
||||
// 显示解锁弹窗
|
||||
showUnlockModal() {
|
||||
this.setData({ showUnlockModal: true })
|
||||
@@ -826,24 +575,7 @@ Page({
|
||||
this.setData({ showUnlockModal: false })
|
||||
},
|
||||
|
||||
// 支付成功后立即查询订单状态并刷新(首轮 0 延迟,之后每 800ms 重试)
|
||||
async pollOrderAndRefresh(orderSn) {
|
||||
const maxAttempts = 12
|
||||
const interval = 800
|
||||
for (let i = 0; i < maxAttempts; i++) {
|
||||
try {
|
||||
const r = await app.request(`/api/miniprogram/pay?orderSn=${encodeURIComponent(orderSn)}`, { method: 'GET', silent: true })
|
||||
if (r?.data?.status === 'paid') {
|
||||
await this.refreshMatchCountAndStatus()
|
||||
return
|
||||
}
|
||||
} catch (_) {}
|
||||
if (i < maxAttempts - 1) await new Promise(r => setTimeout(r, interval))
|
||||
}
|
||||
await this.refreshMatchCountAndStatus()
|
||||
},
|
||||
|
||||
// 购买匹配次数(与购买章节逻辑一致,写入订单)
|
||||
// 购买匹配次数
|
||||
async buyMatchCount() {
|
||||
this.setData({ showUnlockModal: false })
|
||||
|
||||
@@ -859,17 +591,16 @@ Page({
|
||||
return
|
||||
}
|
||||
|
||||
const matchPrice = this.data.matchPrice || 1
|
||||
// 邀请码:与章节支付一致,写入订单便于分销归属与对账
|
||||
const referralCode = wx.getStorageSync('referral_code') || ''
|
||||
// 调用支付接口购买匹配次数(productType: match,订单类型:购买匹配次数)
|
||||
// 调用支付接口购买匹配次数
|
||||
const res = await app.request('/api/miniprogram/pay', {
|
||||
method: 'POST',
|
||||
data: {
|
||||
openId,
|
||||
productType: 'match',
|
||||
productId: 'match_1',
|
||||
amount: matchPrice,
|
||||
amount: 1,
|
||||
description: '匹配次数x1',
|
||||
userId: app.globalData.userInfo?.id || '',
|
||||
referralCode: referralCode || undefined
|
||||
@@ -877,7 +608,6 @@ Page({
|
||||
})
|
||||
|
||||
if (res.success && res.data?.payParams) {
|
||||
const orderSn = res.data.orderSn
|
||||
// 调用微信支付
|
||||
await new Promise((resolve, reject) => {
|
||||
wx.requestPayment({
|
||||
@@ -886,9 +616,13 @@ Page({
|
||||
fail: reject
|
||||
})
|
||||
})
|
||||
|
||||
// 支付成功,增加匹配次数
|
||||
const extraMatches = (wx.getStorageSync('extra_match_count') || 0) + 1
|
||||
wx.setStorageSync('extra_match_count', extraMatches)
|
||||
|
||||
wx.showToast({ title: '购买成功', icon: 'success' })
|
||||
// 轮询订单状态,确认已支付后再刷新(不依赖 PayNotify 回调时机)
|
||||
this.pollOrderAndRefresh(orderSn)
|
||||
this.initUserStatus()
|
||||
} else {
|
||||
throw new Error(res.error || '创建订单失败')
|
||||
}
|
||||
@@ -896,13 +630,14 @@ Page({
|
||||
if (e.errMsg && e.errMsg.includes('cancel')) {
|
||||
wx.showToast({ title: '已取消', icon: 'none' })
|
||||
} else {
|
||||
// 测试模式(无支付环境时本地模拟)
|
||||
// 测试模式
|
||||
wx.showModal({
|
||||
title: '支付服务暂不可用',
|
||||
content: '是否使用测试模式购买?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
app.globalData.matchCount = (app.globalData.matchCount ?? 0) + 1
|
||||
const extraMatches = (wx.getStorageSync('extra_match_count') || 0) + 1
|
||||
wx.setStorageSync('extra_match_count', extraMatches)
|
||||
wx.showToast({ title: '测试购买成功', icon: 'success' })
|
||||
this.initUserStatus()
|
||||
}
|
||||
@@ -924,13 +659,5 @@ Page({
|
||||
},
|
||||
|
||||
// 阻止事件冒泡
|
||||
preventBubble() {},
|
||||
|
||||
onShareAppMessage() {
|
||||
const ref = app.getMyReferralCode()
|
||||
return {
|
||||
title: 'Soul创业派对 - 找伙伴',
|
||||
path: ref ? `/pages/match/match?ref=${ref}` : '/pages/match/match'
|
||||
}
|
||||
}
|
||||
preventBubble() {}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user