340 lines
13 KiB
JavaScript
340 lines
13 KiB
JavaScript
/**
|
||
* 卡若创业派对 - 超级个体/会员详情页
|
||
* 接口:优先 /api/miniprogram/vip/members?id=xx(VIP),回退 /api/miniprogram/users?id=xx(任意用户)
|
||
* 头像/昵称:统一用用户资料(nickname/avatar)优先,随「我的」修改实时生效
|
||
* mbti, region, industry, position, businessScale, skills,
|
||
* storyBestMonth→bestMonth, storyAchievement→achievement, storyTurning→turningPoint,
|
||
* helpOffer→canHelp, helpNeed→needHelp
|
||
* 点头像:若后台 persons.user_id 已绑定则带 ckbLeadToken,走存客宝 CKBLead(与阅读页 @ 一致)
|
||
*/
|
||
const app = getApp()
|
||
const soulBridge = require('../../utils/soulBridge.js')
|
||
|
||
Page({
|
||
data: { statusBarHeight: 44, navBarTotalPx: 88, member: null, loading: true },
|
||
|
||
onLoad(options) {
|
||
wx.showShareMenu({ withShareTimeline: true })
|
||
const sb = app.globalData.statusBarHeight || 44
|
||
this.setData({ statusBarHeight: sb, navBarTotalPx: sb + 44 })
|
||
if (options.id) this.loadMember(options.id)
|
||
},
|
||
|
||
async loadMember(id) {
|
||
try {
|
||
const res = await app.request({ url: `/api/miniprogram/vip/members?id=${id}`, silent: true })
|
||
if (res?.success && res.data) {
|
||
const d = Array.isArray(res.data) ? res.data[0] : res.data
|
||
if (d) { this.setData({ member: this.enrichAndFormat(d), loading: false }); return }
|
||
}
|
||
} catch (e) {}
|
||
|
||
try {
|
||
const dbRes = await app.request({ url: `/api/miniprogram/users?id=${id}`, silent: true })
|
||
if (dbRes?.success && dbRes.data) {
|
||
const u = Array.isArray(dbRes.data) ? dbRes.data[0] : dbRes.data
|
||
if (u) {
|
||
this.setData({ member: this.enrichAndFormat({
|
||
id: u.id, name: u.nickname || u.vipName || u.vip_name || '创业者',
|
||
avatar: u.avatar || u.vipAvatar || u.vip_avatar || '', isVip: !!(u.is_vip),
|
||
contactRaw: u.vipContact || u.vip_contact || u.phone || '',
|
||
wechatId: u.wechatId || u.wechat_id,
|
||
project: u.vipProject || u.vip_project || u.projectIntro || u.project_intro || '',
|
||
industry: u.industry, position: u.position, businessScale: u.businessScale || u.business_scale,
|
||
skills: u.skills, mbti: u.mbti, region: u.region,
|
||
storyBestMonth: u.storyBestMonth || u.story_best_month,
|
||
storyAchievement: u.storyAchievement || u.story_achievement,
|
||
storyTurning: u.storyTurning || u.story_turning,
|
||
helpOffer: u.helpOffer || u.help_offer,
|
||
helpNeed: u.helpNeed || u.help_need,
|
||
ckbLeadToken: u.ckbLeadToken || u.ckb_lead_token,
|
||
}), loading: false })
|
||
return
|
||
}
|
||
}
|
||
} catch (e) {}
|
||
this.setData({ loading: false })
|
||
},
|
||
|
||
// 将空值、「未填写」、纯空格均视为未填写(用于隐藏对应项)
|
||
_emptyIfPlaceholder(v) {
|
||
if (v == null || v === undefined) return ''
|
||
const s = String(v).trim()
|
||
return (s === '' || s === '未填写') ? '' : s
|
||
},
|
||
|
||
enrichAndFormat(raw) {
|
||
const e = (v) => this._emptyIfPlaceholder(v)
|
||
const merged = {
|
||
id: raw.id,
|
||
name: raw.nickname || raw.name || raw.vipName || raw.vip_name || '创业者',
|
||
avatar: raw.avatar || raw.vipAvatar || raw.vip_avatar || '',
|
||
isVip: !!(raw.isVip || raw.is_vip),
|
||
mbti: e(raw.mbti),
|
||
region: e(raw.region),
|
||
industry: e(raw.industry),
|
||
position: e(raw.position),
|
||
businessScale: e(raw.businessScale || raw.business_scale),
|
||
skills: e(raw.skills),
|
||
contactRaw: raw.contactRaw || raw.vipContact || raw.vip_contact || raw.phone || '',
|
||
wechatRaw: raw.wechatRaw || raw.wechatId || raw.wechat_id || '',
|
||
bestMonth: e(raw.bestMonth || raw.storyBestMonth || raw.story_best_month),
|
||
achievement: e(raw.achievement || raw.storyAchievement || raw.story_achievement),
|
||
turningPoint: e(raw.turningPoint || raw.storyTurning || raw.story_turning),
|
||
canHelp: e(raw.canHelp || raw.helpOffer || raw.help_offer),
|
||
needHelp: e(raw.needHelp || raw.helpNeed || raw.help_need),
|
||
project: e(raw.project || raw.vipProject || raw.vip_project || raw.projectIntro || raw.project_intro),
|
||
ckbLeadToken: String(raw.ckbLeadToken || raw.ckb_lead_token || '').trim()
|
||
}
|
||
|
||
const contact = merged.contactRaw || ''
|
||
const wechat = merged.wechatRaw || ''
|
||
const isMatched = (app.globalData.matchedUsers || []).includes(merged.id)
|
||
const unlockData = this._getUnlockData(merged.id)
|
||
merged.contactDisplay = contact ? (contact.slice(0, 3) + '****' + (contact.length > 7 ? contact.slice(-2) : '')) : ''
|
||
merged.contactUnlocked = isMatched || unlockData.contact
|
||
merged.contactFull = contact
|
||
merged.wechatDisplay = wechat ? (wechat.slice(0, 4) + '****' + (wechat.length > 8 ? wechat.slice(-3) : '')) : ''
|
||
merged.wechatUnlocked = isMatched || unlockData.wechat
|
||
merged.wechatFull = wechat
|
||
return merged
|
||
},
|
||
|
||
_getUnlockData(memberId) {
|
||
const userId = app.globalData.userInfo?.id
|
||
if (!userId || !memberId) return { contact: false, wechat: false }
|
||
try {
|
||
const raw = wx.getStorageSync('member_unlocks_' + userId)
|
||
if (Array.isArray(raw) && raw.includes(memberId)) {
|
||
return { contact: true, wechat: true }
|
||
}
|
||
const data = raw && typeof raw === 'object' && !Array.isArray(raw) ? raw : {}
|
||
const member = data[memberId]
|
||
return {
|
||
contact: !!(member && member.contact),
|
||
wechat: !!(member && member.wechat)
|
||
}
|
||
} catch (e) { return { contact: false, wechat: false } }
|
||
},
|
||
|
||
_addUnlock(memberId, field) {
|
||
const userId = app.globalData.userInfo?.id
|
||
if (!userId || !memberId || !field) return
|
||
let obj = wx.getStorageSync('member_unlocks_' + userId)
|
||
if (Array.isArray(obj)) {
|
||
obj = obj.reduce((o, id) => { o[id] = { contact: true, wechat: true }; return o }, {})
|
||
}
|
||
obj = obj && typeof obj === 'object' ? obj : {}
|
||
if (!obj[memberId]) obj[memberId] = {}
|
||
obj[memberId][field] = true
|
||
wx.setStorageSync('member_unlocks_' + userId, obj)
|
||
},
|
||
|
||
_hasUsedFreeForMember(memberId) {
|
||
const d = this._getUnlockData(memberId)
|
||
return d.contact || d.wechat
|
||
},
|
||
|
||
/** VIP 或本会员首次免费:写入解锁;否则弹开通 VIP */
|
||
_tryFreeUnlock(member, field) {
|
||
const isVip = app.globalData.isVip
|
||
const usedFree = this._hasUsedFreeForMember(member.id)
|
||
if (isVip || !usedFree) {
|
||
this._addUnlock(member.id, field)
|
||
return true
|
||
}
|
||
wx.showModal({
|
||
title: '解锁' + (field === 'contact' ? '联系方式' : '微信号'),
|
||
content: '您的免费解锁次数已用完,开通VIP会员(¥1980/年)可无限解锁',
|
||
confirmText: '去开通',
|
||
cancelText: '取消',
|
||
success: (res) => { if (res.confirm) wx.navigateTo({ url: '/pages/vip/vip' }) }
|
||
})
|
||
return false
|
||
},
|
||
|
||
/**
|
||
* 点头像:有存客宝人物 token 时优先 POST /api/miniprogram/ckb/lead(与阅读页 @ 同链路,匹配 persons.ckb_api_key 计划)
|
||
* 否则:解锁后复制微信/手机号并引导
|
||
*/
|
||
startLinkFlow() {
|
||
const member = this.data.member
|
||
if (!member) return
|
||
const leadTok = (member.ckbLeadToken || '').trim()
|
||
if (leadTok) {
|
||
const nickname = ((member.name || 'TA').trim() || 'TA')
|
||
wx.showModal({
|
||
title: '添加好友',
|
||
content: `是否通过获客计划联系 ${nickname}?提交后将按对方在存客宝后台配置的计划执行。`,
|
||
confirmText: '确定',
|
||
cancelText: '取消',
|
||
success: (res) => {
|
||
if (res.confirm) this._doCkbLeadSubmit(leadTok, nickname)
|
||
}
|
||
})
|
||
return
|
||
}
|
||
if (member.wechatRaw || member.wechatDisplay) {
|
||
if (!this._ensureUnlockedForLink('wechat')) return
|
||
const m = this.data.member
|
||
if (m.wechatFull) this._copyAndGuideWechat(m.wechatFull)
|
||
return
|
||
}
|
||
if (member.contactRaw || member.contactDisplay) {
|
||
if (!this._ensureUnlockedForLink('contact')) return
|
||
const m = this.data.member
|
||
if (m.contactFull) this._copyAndGuidePhone(m.contactFull)
|
||
return
|
||
}
|
||
wx.showToast({ title: '暂未公开联系方式', icon: 'none' })
|
||
},
|
||
|
||
/** 与阅读页 @mention 同链路:soulBridge.submitCkbLead */
|
||
async _doCkbLeadSubmit(targetUserId, targetNickname) {
|
||
await soulBridge.submitCkbLead(app, {
|
||
targetUserId,
|
||
targetNickname,
|
||
source: 'member_detail_avatar',
|
||
phoneModalContent: '请先填写手机号(必填),以便对方通过获客计划联系您'
|
||
})
|
||
},
|
||
|
||
_ensureUnlockedForLink(field) {
|
||
const member = this.data.member
|
||
if (!member?.id || (field !== 'contact' && field !== 'wechat')) return false
|
||
if (field === 'wechat' && member.wechatUnlocked) return true
|
||
if (field === 'contact' && member.contactUnlocked) return true
|
||
if (!app.globalData.isLoggedIn) {
|
||
wx.showModal({
|
||
title: '需要登录',
|
||
content: field === 'wechat'
|
||
? '登录后可解锁并复制对方微信号,再按步骤去微信添加好友。'
|
||
: '登录后可解锁并复制对方手机号,便于添加好友或回拨。',
|
||
confirmText: '去登录',
|
||
cancelText: '取消',
|
||
success: (res) => { if (res.confirm) wx.switchTab({ url: '/pages/my/my' }) }
|
||
})
|
||
return false
|
||
}
|
||
const d = this._getUnlockData(member.id)
|
||
if ((field === 'wechat' && d.wechat) || (field === 'contact' && d.contact)) {
|
||
this.setData({ member: this.enrichAndFormat(member) })
|
||
return true
|
||
}
|
||
if (!this._tryFreeUnlock(member, field)) return false
|
||
this.setData({ member: this.enrichAndFormat(member) })
|
||
return true
|
||
},
|
||
|
||
_copyAndGuideWechat(wechatId) {
|
||
if (!wechatId) return
|
||
wx.setClipboardData({
|
||
data: String(wechatId),
|
||
success: () => {
|
||
wx.hideToast()
|
||
setTimeout(() => {
|
||
wx.hideToast()
|
||
wx.showModal({
|
||
title: '添加微信好友',
|
||
content: '微信号已复制。\n\n请打开微信 → 右上角「+」→ 添加朋友 → 粘贴搜索并添加。',
|
||
showCancel: false,
|
||
confirmText: '知道了'
|
||
})
|
||
}, 120)
|
||
},
|
||
fail: () => wx.showToast({ title: '复制失败', icon: 'none' })
|
||
})
|
||
},
|
||
|
||
_copyAndGuidePhone(phone) {
|
||
if (!phone) return
|
||
wx.setClipboardData({
|
||
data: String(phone),
|
||
success: () => {
|
||
wx.hideToast()
|
||
setTimeout(() => {
|
||
wx.hideToast()
|
||
wx.showModal({
|
||
title: '联系对方',
|
||
content: '手机号已复制。\n\n可打开微信「添加朋友」搜索手机号,或使用手机拨号联系对方。',
|
||
showCancel: false,
|
||
confirmText: '知道了'
|
||
})
|
||
}, 120)
|
||
},
|
||
fail: () => wx.showToast({ title: '复制失败', icon: 'none' })
|
||
})
|
||
},
|
||
|
||
unlockField(e) {
|
||
const field = e.currentTarget.dataset.field
|
||
if (!field) return
|
||
const member = this.data.member
|
||
if (!member?.id || (field !== 'contact' && field !== 'wechat')) return
|
||
const isLoggedIn = app.globalData.isLoggedIn
|
||
if (!isLoggedIn) {
|
||
wx.showModal({
|
||
title: '需要登录',
|
||
content: '请先登录后再解锁超级个体联系方式',
|
||
confirmText: '去登录',
|
||
cancelText: '取消',
|
||
success: (res) => { if (res.confirm) wx.switchTab({ url: '/pages/my/my' }) }
|
||
})
|
||
return
|
||
}
|
||
const d = this._getUnlockData(member.id)
|
||
if (d[field]) return
|
||
if (this._tryFreeUnlock(member, field)) {
|
||
const m = this.enrichAndFormat(member)
|
||
this.setData({ member: m })
|
||
wx.showToast({ title: field === 'contact' ? '已解锁联系方式' : '已解锁微信号', icon: 'success' })
|
||
}
|
||
},
|
||
|
||
tapContactRow() {
|
||
const m = this.data.member
|
||
if (!m || !(m.contactRaw || m.contactDisplay)) return
|
||
if (m.contactUnlocked) this.copyContact()
|
||
else this.unlockField({ currentTarget: { dataset: { field: 'contact' } } })
|
||
},
|
||
|
||
tapWechatRow() {
|
||
const m = this.data.member
|
||
if (!m || !(m.wechatRaw || m.wechatDisplay)) return
|
||
if (m.wechatUnlocked) this.copyWechat()
|
||
else this.unlockField({ currentTarget: { dataset: { field: 'wechat' } } })
|
||
},
|
||
|
||
copyContact() {
|
||
const c = this.data.member?.contactFull
|
||
if (!c) return
|
||
wx.setClipboardData({ data: c, success: () => wx.showToast({ title: '已复制', icon: 'success' }) })
|
||
},
|
||
|
||
copyWechat() {
|
||
const w = this.data.member?.wechatFull
|
||
if (!w) return
|
||
wx.setClipboardData({ data: w, success: () => wx.showToast({ title: '已复制', icon: 'success' }) })
|
||
},
|
||
|
||
goToMatch() { wx.switchTab({ url: '/pages/match/match' }) },
|
||
goToVip() { wx.navigateTo({ url: '/pages/vip/vip' }) },
|
||
goBack() { getApp().goBackOrToHome() },
|
||
|
||
onShareAppMessage() {
|
||
const ref = app.getMyReferralCode()
|
||
const id = this.data.member?.id
|
||
return {
|
||
title: '卡若创业派对 - 创业者详情',
|
||
path: id && ref ? `/pages/member-detail/member-detail?id=${id}&ref=${ref}` : id ? `/pages/member-detail/member-detail?id=${id}` : ref ? `/pages/member-detail/member-detail?ref=${ref}` : '/pages/member-detail/member-detail'
|
||
}
|
||
},
|
||
|
||
onShareTimeline() {
|
||
const ref = app.getMyReferralCode()
|
||
const id = this.data.member?.id
|
||
const q = id ? (ref ? `id=${id}&ref=${ref}` : `id=${id}`) : (ref ? `ref=${ref}` : '')
|
||
return { title: '卡若创业派对 - 创业者详情', query: q }
|
||
}
|
||
})
|