微信小程序:自定义底栏接入 AI 入口(含图标与样式)、AI 聊天相关页面与历史/报告等能力;审核模式与配置联动;资料/企业/首页/授权等页面与 app 入口配合调整。
后端 API:AI 对话/报告/余额告警 等服务与路由;小程序 tabBar 配置与分润相关能力;出站推送 Webhook 与管理端调试;飞书留资、小程序数据分析 等支撑;多份 数据库迁移(AI 聊天、灵魂文章、tabBar、分润等)。 管理端 / 超管:看板、用户/订单/分销/财务、设置与 小程序 tabBar 管理、分润规则、灵魂文章、AI 配置与监控 等大量页面与能力扩展;主题与布局更新。 抖音小程序:与微信侧在 结果页/购买/个人中心 等方向做了同步或优化。 另含 部署/脚本、开发文档 等配套更新。 邀请码与解锁:后端 分销/邀请码 接口与 add_invite_codes 等 SQL;小程序侧 邀请码弹窗组件、个人中心/推广/多类结果页 的填写入口与 解锁门控(inviteCodeGate、unlockGate);并补充 《小程序解锁引导与邀请码方案》 文档。 超管后台:路由与 企业中心(EnterpriseHub) 等交互与结构优化。 小程序体验:在 首页结果、推广、各测评结果页 上继续打磨;与 邀请码门控、审核门控 小步联动。
This commit is contained in:
@@ -4,6 +4,7 @@ const { getTypeOnly } = require('../../utils/resultFormat')
|
||||
const { request } = require('../../utils/request')
|
||||
const { buildRecoMiniProgramPath } = require('../../utils/recoMiniProgram.js')
|
||||
const { isAuditHideAiMode } = require('../../utils/miniprogramAuditGate.js')
|
||||
const inviteCodeGate = require('../../utils/inviteCodeGate.js')
|
||||
|
||||
/** 与超管「小程序 · 推荐文章展示」中「区块标题」一致;接口无字段时的兜底 */
|
||||
const PROFILE_RECO_LABEL_FALLBACK = '我的由来'
|
||||
@@ -79,7 +80,13 @@ Page({
|
||||
profileRecoSectionLabel: '',
|
||||
profileRecoArticle: null,
|
||||
/** 与神仙 AI 精选推荐同源:配置了 AppID 时优先跳转目标小程序 */
|
||||
profileRecoJump: null
|
||||
profileRecoJump: null,
|
||||
/** 拉取自 /api/distribution/my-invite-code,与推广中心一致 */
|
||||
myInviteCode: '',
|
||||
myInviteCodeLoadState: 'idle',
|
||||
myInviteCodeErrMsg: '',
|
||||
myInviteCodeHint: '',
|
||||
showInviteCodeDialog: false
|
||||
},
|
||||
|
||||
_computeShowLatestTestRow(d) {
|
||||
@@ -223,19 +230,127 @@ Page({
|
||||
|
||||
// 2. 已登录则从服务端拉取最近记录;失败降级读 localStorage
|
||||
if (token || userInfo) {
|
||||
if (token && this.data.permDistribution) {
|
||||
this.setData({ myInviteCodeLoadState: 'loading', myInviteCodeErrMsg: '' })
|
||||
}
|
||||
this._loadRecentFromAPI()
|
||||
this._loadPromoStats()
|
||||
this._loadMyInviteCode()
|
||||
this._loadProfileRecoTeaser()
|
||||
} else {
|
||||
this.setData({
|
||||
profileRecoShow: false,
|
||||
profileRecoArticle: null,
|
||||
profileRecoSectionLabel: '',
|
||||
profileRecoJump: null
|
||||
profileRecoJump: null,
|
||||
myInviteCode: '',
|
||||
myInviteCodeLoadState: 'idle',
|
||||
myInviteCodeErrMsg: '',
|
||||
myInviteCodeHint: '',
|
||||
showInviteCodeDialog: false
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
openInviteCodeFill() {
|
||||
app.ensureLogin().then((ok) => {
|
||||
if (!ok) {
|
||||
wx.showToast({ title: '请先登录', icon: 'none' })
|
||||
return
|
||||
}
|
||||
inviteCodeGate.openInviteCodeDialog(this)
|
||||
})
|
||||
},
|
||||
|
||||
onInviteCodeSkip() {
|
||||
inviteCodeGate.finishInviteCodeGate(this, true)
|
||||
},
|
||||
|
||||
onInviteCodeSuccess() {
|
||||
inviteCodeGate.finishInviteCodeGate(this, true)
|
||||
},
|
||||
|
||||
_loadMyInviteCode() {
|
||||
const token = app.globalData.token || wx.getStorageSync('token')
|
||||
if (!token || !this.data.permDistribution) {
|
||||
this.setData({
|
||||
myInviteCode: '',
|
||||
myInviteCodeLoadState: 'idle',
|
||||
myInviteCodeErrMsg: '',
|
||||
myInviteCodeHint: ''
|
||||
})
|
||||
return
|
||||
}
|
||||
this.setData({
|
||||
myInviteCodeLoadState: 'loading',
|
||||
myInviteCodeErrMsg: ''
|
||||
})
|
||||
request({
|
||||
url: '/api/distribution/my-invite-code',
|
||||
method: 'GET',
|
||||
success: (res) => {
|
||||
const payload = res && res.data
|
||||
const httpOk = res.statusCode >= 200 && res.statusCode < 300
|
||||
const bizOk = payload && Number(payload.code) === 200
|
||||
if (!httpOk || !bizOk) {
|
||||
const msg =
|
||||
(payload && payload.message) ||
|
||||
(typeof res.statusCode === 'number' ? `请求失败 (${res.statusCode})` : '加载失败')
|
||||
this.setData({
|
||||
myInviteCode: '',
|
||||
myInviteCodeLoadState: 'error',
|
||||
myInviteCodeErrMsg: msg,
|
||||
myInviteCodeHint: ''
|
||||
})
|
||||
return
|
||||
}
|
||||
const data = payload.data || {}
|
||||
const raw = data.code != null ? String(data.code).trim() : ''
|
||||
const code = raw ? raw.toUpperCase() : ''
|
||||
const hint = (data.hint && String(data.hint).trim()) || ''
|
||||
if (code) {
|
||||
this.setData({
|
||||
myInviteCode: code,
|
||||
myInviteCodeLoadState: 'ready',
|
||||
myInviteCodeErrMsg: '',
|
||||
myInviteCodeHint: ''
|
||||
})
|
||||
} else {
|
||||
this.setData({
|
||||
myInviteCode: '',
|
||||
myInviteCodeLoadState: 'nodata',
|
||||
myInviteCodeErrMsg: '',
|
||||
myInviteCodeHint: hint || '暂无可用邀请码'
|
||||
})
|
||||
}
|
||||
},
|
||||
fail: () =>
|
||||
this.setData({
|
||||
myInviteCode: '',
|
||||
myInviteCodeLoadState: 'error',
|
||||
myInviteCodeErrMsg: '网络异常',
|
||||
myInviteCodeHint: ''
|
||||
})
|
||||
})
|
||||
},
|
||||
|
||||
onInviteStripTap() {
|
||||
if (this.data.myInviteCodeLoadState === 'error') {
|
||||
this._loadMyInviteCode()
|
||||
return
|
||||
}
|
||||
this.goToPromo()
|
||||
},
|
||||
|
||||
copyMyInviteCode() {
|
||||
const code = (this.data.myInviteCode || '').trim()
|
||||
if (!code) return
|
||||
wx.setClipboardData({
|
||||
data: code,
|
||||
success: () => wx.showToast({ title: '已复制邀请码', icon: 'success' })
|
||||
})
|
||||
},
|
||||
|
||||
_parseRecoJumpFromDisplay(d) {
|
||||
if (!d || typeof d !== 'object') return null
|
||||
const appId = ((d.recoJumpMiniAppId || '') + '').trim()
|
||||
|
||||
Reference in New Issue
Block a user