@@ -4,7 +4,9 @@
* 稳定版兼容: readCount 用 getReadCount(), hasPurchasedFull 用 hasFullBook, 完善头像跳 avatar-nickname
*
* trigger → scene 映射:
* 注册 → after_login
* 注册 → after_login(头像或昵称未完善)
* update_avatar / 完善头像 → 仅头像未完善
* update_nickname / 修改昵称 → 仅昵称为默认
* 点击收费章节 → before_read
* 完成匹配 → after_match
* 完成付款 → after_pay
@@ -34,6 +36,8 @@ const CACHE_TTL = 5 * 60 * 1000
const TRIGGER _SCENE _MAP = {
'注册' : 'after_login' ,
'完善头像' : 'after_login' ,
'修改昵称' : 'after_login' ,
'点击收费章节' : 'before_read' ,
'完成匹配' : 'after_match' ,
'完成付款' : 'after_pay' ,
@@ -46,6 +50,10 @@ const TRIGGER_SCENE_MAP = {
'浏览导师页' : 'browse_mentor' ,
}
// 与后台「规则类型 trigger」一致: 支持英文 key 与同义中文(逻辑在 isRuleEnabled 定义之后)
const TRIGGER _KEYS _AVATAR = [ 'update_avatar' , '完善头像' ]
const TRIGGER _KEYS _NICKNAME = [ 'update_nickname' , '修改昵称' ]
function isInCooldown ( ruleId ) {
if ( ! COOLDOWN _MS || COOLDOWN _MS <= 0 ) return false
try {
@@ -132,6 +140,29 @@ function getRuleInfo(rules, triggerName) {
return rules . find ( r => r . trigger === triggerName && ! r . completed )
}
function isAnyTriggerEnabled ( rules , keys ) {
return keys . some ( ( k ) => isRuleEnabled ( rules , k ) )
}
function getFirstRuleInfo ( rules , keys ) {
for ( let i = 0 ; i < keys . length ; i ++ ) {
const info = getRuleInfo ( rules , keys [ i ] )
if ( info ) return info
}
return null
}
function isAvatarMissingOrDefault ( user ) {
user = user || getUserInfo ( )
const avatar = user . avatar || user . avatarUrl || ''
return ! avatar || avatar . includes ( 'default' )
}
function isNicknamePlaceholder ( nickname ) {
const n = trimStr ( nickname )
return ! n || n === '微信用户' || n . startsWith ( '微信用户' )
}
function markRuleCompleted ( ruleId ) {
const userId = getUserInfo ( ) . id
if ( ! userId || ! ruleId ) return
@@ -147,7 +178,54 @@ function markRuleCompleted(ruleId) {
} ) . catch ( ( ) => { } )
}
// 稳定版:跳转 avatar-nickname( 专注头像+昵称,首次登录由 app.login 强制 redirect)
// 仅头像: trigger = update_avatar 或 完善头像
function checkRule _UpdateAvatar ( rules ) {
if ( ! isAnyTriggerEnabled ( rules , TRIGGER _KEYS _AVATAR ) ) return null
const app = getAppInstance ( )
if ( app && app . globalData . isVip ) return null
const user = getUserInfo ( )
if ( ! user . id ) return null
if ( ! isAvatarMissingOrDefault ( user ) ) return null
if ( isInCooldown ( 'update_avatar' ) ) return null
setCooldown ( 'update_avatar' )
const info = getFirstRuleInfo ( rules , TRIGGER _KEYS _AVATAR )
return {
ruleId : 'update_avatar' ,
serverRuleId : info ? . id ,
title : info ? . title || '上传头像' ,
message : info ? . description || '换一张清晰头像,伙伴在名片和匹配里更容易认出你。' ,
confirmText : '去设置' ,
cancelText : '关闭' ,
action : 'navigate' ,
target : '/pages/avatar-nickname/avatar-nickname?focus=avatar'
}
}
// 仅昵称: trigger = update_nickname 或 修改昵称
function checkRule _UpdateNickname ( rules ) {
if ( ! isAnyTriggerEnabled ( rules , TRIGGER _KEYS _NICKNAME ) ) return null
const app = getAppInstance ( )
if ( app && app . globalData . isVip ) return null
const user = getUserInfo ( )
if ( ! user . id ) return null
const nickname = user . nickname || user . nickName || ''
if ( ! isNicknamePlaceholder ( nickname ) ) return null
if ( isInCooldown ( 'update_nickname' ) ) return null
setCooldown ( 'update_nickname' )
const info = getFirstRuleInfo ( rules , TRIGGER _KEYS _NICKNAME )
return {
ruleId : 'update_nickname' ,
serverRuleId : info ? . id ,
title : info ? . title || '修改昵称' ,
message : info ? . description || '改一个真实好记的昵称,方便伙伴称呼你。' ,
confirmText : '去填写' ,
cancelText : '关闭' ,
action : 'navigate' ,
target : '/pages/avatar-nickname/avatar-nickname?focus=nickname'
}
}
// 稳定版: trigger=注册 时头像或昵称任一未完善则引导(与上面两项拆分配置并存)
// VIP 用户不触发:统一由 checkVipContactRequiredAndGuide 跳转 profile-edit, 避免与主流程冲突
function checkRule _FillAvatar ( rules ) {
if ( ! isRuleEnabled ( rules , '注册' ) ) return null
@@ -155,12 +233,15 @@ function checkRule_FillAvatar(rules) {
if ( app && app . globalData . isVip ) return null
const user = getUserInfo ( )
if ( ! user . id ) return null
const avatar = user . avatar || user . avatarUrl || ''
const nickname = us er. nickname || ''
if ( avatar && ! avatar . includes ( 'default' ) && nickname && nickname !== '微信用户' && ! nickname . startsWith ( '微信用户' ) ) return null
const nickname = user . nickname || user . nickName || ''
if ( ! isAvatarMissingOrDefault ( user ) && ! isNicknamePlacehold er( nickname ) ) return null
if ( isInCooldown ( 'fill_avatar' ) ) return null
setCooldown ( 'fill_avatar' )
const info = getRuleInfo ( rules , '注册' )
const needNick = isNicknamePlaceholder ( nickname )
const needAv = isAvatarMissingOrDefault ( user )
const focus = needAv && ! needNick ? 'avatar' : needNick && ! needAv ? 'nickname' : ''
const qs = focus ? ` ?focus= ${ focus } ` : ''
return {
ruleId : 'fill_avatar' ,
serverRuleId : info ? . id ,
@@ -169,10 +250,15 @@ function checkRule_FillAvatar(rules) {
confirmText : '去设置' ,
cancelText : '关闭' ,
action : 'navigate' ,
target : '/pages/avatar-nickname/avatar-nickname'
target : '/pages/avatar-nickname/avatar-nickname' + qs
}
}
/** 头像/昵称类引导:优先拆条规则(完善头像、修改昵称),其次合并规则(注册) */
function checkAvatarNicknameGuides ( rules ) {
return checkRule _UpdateAvatar ( rules ) || checkRule _UpdateNickname ( rules ) || checkRule _FillAvatar ( rules )
}
function checkRule _BindPhone ( rules ) {
if ( ! isRuleEnabled ( rules , '点击收费章节' ) ) return null
const user = getUserInfo ( )
@@ -332,17 +418,17 @@ function checkRulesSync(scene, rules) {
switch ( scene ) {
case 'after_login' :
return checkRule _FillAvatar ( rules )
return checkAvatarNicknameGuides ( rules )
case 'before_read' :
return checkRule _BindPhone ( rules ) || checkRule _FillAvatar ( rules )
return checkRule _BindPhone ( rules ) || checkAvatarNicknameGuides ( rules )
case 'before_pay' :
return checkRule _FillAvatar ( rules ) || checkRule _BindPhone ( rules ) || checkRule _FillProfile ( rules )
return checkAvatarNicknameGuides ( rules ) || checkRule _BindPhone ( rules ) || checkRule _FillProfile ( rules )
case 'after_match' :
return null
case 'after_pay' :
return checkRule _FillVipInfo ( rules ) || checkRule _FillProfile ( rules )
case 'page_show' :
return checkRule _FillAvatar ( rules ) || checkRule _ShareAfter5Chapters ( rules ) || checkRule _BindWechat ( rules ) || checkRule _Withdraw ( rules )
return checkAvatarNicknameGuides ( rules ) || checkRule _ShareAfter5Chapters ( rules ) || checkRule _BindWechat ( rules ) || checkRule _Withdraw ( rules )
case 'before_join_party' :
return checkRule _JoinParty ( rules )
default :