feat: 小程序与管理端迭代(神仙AI、了解自己CRM、AI测试入口、报表与分润等)
Made-with: Cursor
This commit is contained in:
@@ -3,15 +3,23 @@ const app = getApp()
|
||||
const payment = require('../../utils/payment')
|
||||
const { getTypeOnly } = require('../../utils/resultFormat')
|
||||
const { isReportProfileComplete } = require('../../utils/phoneAuth.js')
|
||||
|
||||
function toProfileLockedPdp(full) {
|
||||
if (!full) return full
|
||||
const desc = full.description || {}
|
||||
return {
|
||||
description: { type: desc.type || '', emoji: desc.emoji || '' },
|
||||
locked: true
|
||||
}
|
||||
}
|
||||
const {
|
||||
slicePreviewText,
|
||||
slicePreviewList,
|
||||
openTimelineShareHint
|
||||
} = require('../../utils/resultProfileGate.js')
|
||||
const {
|
||||
getPdpInsight,
|
||||
getPdpTags,
|
||||
buildPdpDimensions
|
||||
} = require('../../utils/pdpInsights.js')
|
||||
const { decorateCareers } = require('../../utils/mbtiInsights.js')
|
||||
const {
|
||||
computeJourney,
|
||||
markShared,
|
||||
markCamera
|
||||
} = require('../../utils/resultJourneyState.js')
|
||||
const resultScrollSync = require('../../utils/resultSectionScrollSync.js')
|
||||
|
||||
const PDP_KEYS = ['Tiger', 'Peacock', 'Koala', 'Owl', 'Chameleon']
|
||||
|
||||
@@ -46,10 +54,54 @@ Page({
|
||||
testResultId: null,
|
||||
shareToken: '',
|
||||
hasReloadedAfterPay: false,
|
||||
fromShare: false
|
||||
fromShare: false,
|
||||
profileGate: false,
|
||||
previewPdpDescription: '',
|
||||
previewPdpStrengths: [],
|
||||
pdpDimensions: [],
|
||||
pdpInsight: null,
|
||||
pdpTags: [],
|
||||
pdpCareerItems: [],
|
||||
journey: { step1Unlocked: false, step2Unlocked: false, step3Unlocked: false, activeStep: 1 },
|
||||
sectionNav: [
|
||||
{ id: 'sec-hero', label: 'PDP 画像', emoji: '🦁' },
|
||||
{ id: 'sec-insight', label: '深度洞察', emoji: '🧠' },
|
||||
{ id: 'sec-dim', label: '五维得分', emoji: '📊' },
|
||||
{ id: 'sec-trait', label: '优势与注意', emoji: '✨' },
|
||||
{ id: 'sec-team', label: '团队角色', emoji: '🤝' },
|
||||
{ id: 'sec-career', label: '推荐职业', emoji: '💼' },
|
||||
{ id: 'sec-cta', label: '深度方案', emoji: '💎' }
|
||||
],
|
||||
scrollTarget: '',
|
||||
activeSection: ''
|
||||
},
|
||||
|
||||
onTapSectionNav(e) {
|
||||
const id = e && e.detail && e.detail.id
|
||||
if (!id) return
|
||||
this.setData({ scrollTarget: '', activeSection: id }, () => {
|
||||
this.setData({ scrollTarget: id })
|
||||
})
|
||||
},
|
||||
|
||||
onSectionScroll(e) {
|
||||
resultScrollSync.onScroll(this, e)
|
||||
},
|
||||
|
||||
_syncJourney() {
|
||||
this.setData({
|
||||
journey: computeJourney({
|
||||
profileGate: !!this.data.profileGate,
|
||||
payRequired: !!(this.data.payInfo && this.data.payInfo.requiresPayment),
|
||||
isPaid: !!(this.data.payInfo && this.data.payInfo.isPaid)
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
try {
|
||||
wx.showShareMenu({ withShareTicket: true, menus: ['shareAppMessage', 'shareTimeline'] })
|
||||
} catch (e) {}
|
||||
const fromShareFs =
|
||||
options && (String(options.fs) === '1' || options.from === 'share')
|
||||
const id = options && options.id != null && options.id !== '' ? String(options.id) : ''
|
||||
@@ -72,6 +124,7 @@ Page({
|
||||
result: withPercentagesInt(result),
|
||||
typeSummaryLine: getTypeOnly(result, 'pdp')
|
||||
})
|
||||
this._syncPdpGate()
|
||||
this.initPayInfoFromRuntime('pdp')
|
||||
} else {
|
||||
wx.showToast({ title: '暂无测试结果', icon: 'none' })
|
||||
@@ -90,6 +143,7 @@ Page({
|
||||
typeSummaryLine: getTypeOnly(data, 'pdp'),
|
||||
shareToken: payload.shareToken || ''
|
||||
})
|
||||
this._syncPdpGate()
|
||||
const payInfo = {
|
||||
requiresPayment: needPaymentToUnlock,
|
||||
isPaid,
|
||||
@@ -100,6 +154,7 @@ Page({
|
||||
patch.testResultId = String(payload.id)
|
||||
}
|
||||
this.setData(patch)
|
||||
this._reportPaywallOnce('pdp', payInfo)
|
||||
},
|
||||
|
||||
loadDetail(id) {
|
||||
@@ -148,20 +203,100 @@ Page({
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this._syncJourney()
|
||||
if (this.data.testResultId) return
|
||||
const raw = wx.getStorageSync('pdpResult')
|
||||
if (!raw) return
|
||||
const gated = isReportProfileComplete() ? raw : toProfileLockedPdp(raw)
|
||||
this.setData({
|
||||
result: withPercentagesInt(gated),
|
||||
typeSummaryLine: getTypeOnly(gated, 'pdp')
|
||||
result: withPercentagesInt(raw),
|
||||
typeSummaryLine: getTypeOnly(raw, 'pdp')
|
||||
})
|
||||
this._syncPdpGate()
|
||||
},
|
||||
|
||||
_syncPdpGate() {
|
||||
const r = this.data.result
|
||||
const fromShare = !!this.data.fromShare
|
||||
const profileGate = !fromShare && !isReportProfileComplete()
|
||||
const desc = (r && r.description) || {}
|
||||
const code = (r && (r.dominantType || (desc && desc.type))) || ''
|
||||
this.setData({
|
||||
profileGate,
|
||||
previewPdpDescription: slicePreviewText(desc.description || '', 0.3),
|
||||
previewPdpStrengths: slicePreviewList(desc.strengths || [], 0.3),
|
||||
pdpDimensions: r ? buildPdpDimensions(r) : [],
|
||||
pdpInsight: getPdpInsight(code),
|
||||
pdpTags: getPdpTags(code),
|
||||
pdpCareerItems: decorateCareers(desc.careers || [])
|
||||
})
|
||||
this._syncJourney()
|
||||
},
|
||||
|
||||
onTapDeepService() {
|
||||
try { require('../../utils/analytics').track('tap_deep_service_from_pdp', {}) } catch (e) {}
|
||||
wx.navigateTo({ url: '/pages/purchase/index' })
|
||||
},
|
||||
|
||||
onTapPromoCenter() {
|
||||
try { require('../../utils/analytics').track('tap_promo_from_pdp', {}) } catch (e) {}
|
||||
wx.navigateTo({ url: '/pages/promo/index' })
|
||||
},
|
||||
|
||||
onTapReadFull() {
|
||||
try { require('../../utils/analytics').track('tap_read_full', { type: 'pdp' }) } catch (e) {}
|
||||
if (this.data.profileGate) {
|
||||
this.goCompleteProfile()
|
||||
return
|
||||
}
|
||||
if (this.data.payInfo.requiresPayment && !this.data.payInfo.isPaid) {
|
||||
this.unlockFullReport()
|
||||
return
|
||||
}
|
||||
wx.showToast({ title: '当前已是完整报告', icon: 'none' })
|
||||
},
|
||||
|
||||
onTapShareMoment() {
|
||||
try { require('../../utils/analytics').track('tap_share_moment', { type: 'pdp' }) } catch (e) {}
|
||||
if (!this.data.journey.step1Unlocked) {
|
||||
wx.showToast({ title: '请先解锁全文', icon: 'none' })
|
||||
this.onTapReadFull()
|
||||
return
|
||||
}
|
||||
markShared()
|
||||
this._syncJourney()
|
||||
openTimelineShareHint()
|
||||
},
|
||||
|
||||
onTapFaceCamera() {
|
||||
try { require('../../utils/analytics').track('tap_face_camera', { from: 'pdp' }) } catch (e) {}
|
||||
if (!this.data.journey.step2Unlocked) {
|
||||
wx.showToast({ title: '请先分享朋友圈', icon: 'none' })
|
||||
return
|
||||
}
|
||||
markCamera()
|
||||
this._syncJourney()
|
||||
wx.switchTab({ url: '/pages/index/camera' })
|
||||
},
|
||||
|
||||
goReadFullFromShare() {
|
||||
try { require('../../utils/analytics').track('tap_read_full', { type: 'pdp', from: 'share' }) } catch (e) {}
|
||||
wx.switchTab({ url: '/pages/profile/index' })
|
||||
},
|
||||
|
||||
goCompleteProfile() {
|
||||
try { require('../../utils/analytics').track('tap_complete_profile', { from: 'pdp' }) } catch (e) {}
|
||||
wx.navigateTo({ url: '/pages/user-profile/index' })
|
||||
},
|
||||
|
||||
_reportPaywallOnce(testType, payInfo) {
|
||||
if (!payInfo || !payInfo.requiresPayment || payInfo.isPaid) return
|
||||
if (this._paywallReported) return
|
||||
this._paywallReported = true
|
||||
try {
|
||||
require('../../utils/analytics').track('paywall_view', { type: testType, amountYuan: payInfo.amountYuan })
|
||||
} catch (e) {}
|
||||
},
|
||||
|
||||
initPayInfoFromRuntime(testType) {
|
||||
app.getRuntimeConfig()
|
||||
.then((cfg) => {
|
||||
@@ -169,9 +304,10 @@ Page({
|
||||
const pricing = cfg.pricing || {}
|
||||
const requiresPayment = !!(reportRequires && reportRequires[testType])
|
||||
const amountYuan = Number(pricing[testType]) || (requiresPayment ? 1.98 : 0)
|
||||
this.setData({
|
||||
payInfo: { requiresPayment, isPaid: false, amountYuan }
|
||||
})
|
||||
const payInfo = { requiresPayment, isPaid: false, amountYuan }
|
||||
this.setData({ payInfo })
|
||||
this._reportPaywallOnce(testType, payInfo)
|
||||
this._syncJourney()
|
||||
})
|
||||
.catch(() => this.setData({ payInfo: { requiresPayment: false, isPaid: false, amountYuan: 0 } }))
|
||||
},
|
||||
@@ -179,6 +315,7 @@ Page({
|
||||
unlockFullReport() {
|
||||
const { payInfo, testResultId, hasReloadedAfterPay } = this.data
|
||||
if (!payInfo.requiresPayment || payInfo.isPaid) return
|
||||
try { require('../../utils/analytics').track('tap_unlock_full', { type: 'pdp', amountYuan: payInfo.amountYuan }) } catch (e) {}
|
||||
app.ensureLogin && app.ensureLogin().then((logged) => {
|
||||
if (!logged) { wx.showToast({ title: '请先登录', icon: 'none' }); return }
|
||||
payment.purchasePdpTest({
|
||||
@@ -186,6 +323,7 @@ Page({
|
||||
success: () => {
|
||||
wx.showToast({ title: '已解锁完整报告', icon: 'success' })
|
||||
this.setData({ 'payInfo.isPaid': true })
|
||||
this._syncJourney()
|
||||
if (testResultId && !hasReloadedAfterPay) {
|
||||
this.setData({ hasReloadedAfterPay: true })
|
||||
setTimeout(() => this.loadDetail(testResultId), 500)
|
||||
|
||||
Reference in New Issue
Block a user