删除过时的部署管理端触发词文档,并更新相关索引以反映新的触发词约定,确保文档一致性和准确性。

This commit is contained in:
Alex-larget
2026-03-20 14:38:51 +08:00
parent 385e47bc55
commit d34d209b37
84 changed files with 1127 additions and 4241 deletions

View File

@@ -1,6 +1,7 @@
{
"usingComponents": {
"icon": "/components/icon/icon"
"icon": "/components/icon/icon",
"login-modal": "/components/login-modal/login-modal"
},
"pages": [
"pages/chapters/chapters",

View File

@@ -0,0 +1,79 @@
/**
* Soul 创业派对 - 公用登录弹窗
* 手机号一键登录 + 隐私协议
*/
Component({
properties: {
show: { type: Boolean, value: false },
desc: { type: String, value: '登录后可购买章节、解锁更多内容' },
showPrivacyModal: { type: Boolean, value: false },
showCancel: { type: Boolean, value: false }
},
data: {
agreeProtocol: false,
isLoggingIn: false
},
observers: {
show(v) {
if (!v) this.setData({ agreeProtocol: false, isLoggingIn: false })
}
},
methods: {
stopPropagation() {},
onClose() {
this.triggerEvent('close')
},
onToggleAgree() {
this.setData({ agreeProtocol: !this.data.agreeProtocol })
},
onOpenUserProtocol() {
wx.navigateTo({ url: '/pages/agreement/agreement' })
},
onOpenPrivacy() {
wx.navigateTo({ url: '/pages/privacy/privacy' })
},
onAgreePrivacy() {
const app = getApp()
if (app._privacyResolve) {
app._privacyResolve({ buttonId: 'agree-privacy-btn', event: 'agree' })
app._privacyResolve = null
}
this.triggerEvent('privacyagree')
},
async onPhoneLogin(e) {
if (!e.detail.code) {
return this._fallbackWechatLogin()
}
const app = getApp()
this.setData({ isLoggingIn: true })
try {
const result = await app.loginWithPhone(e.detail.code)
this.setData({ isLoggingIn: false })
if (result) {
this.triggerEvent('success')
} else {
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
} catch (err) {
this.setData({ isLoggingIn: false })
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
},
async _fallbackWechatLogin() {
const app = getApp()
this.setData({ isLoggingIn: true })
try {
const result = await app.login()
this.setData({ isLoggingIn: false })
if (result) {
this.triggerEvent('success')
} else {
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
} catch (err) {
this.setData({ isLoggingIn: false })
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
}
}
})

View File

@@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"icon": "/components/icon/icon"
}
}

View File

@@ -0,0 +1,27 @@
<!-- Soul 创业派对 - 公用登录弹窗 -->
<view class="modal-overlay" wx:if="{{show}}" bindtap="onClose">
<view class="modal-content login-modal" catchtap="stopPropagation">
<view class="modal-close" bindtap="onClose"><icon name="x" size="36" color="#8e8e93"></icon></view>
<view class="login-icon"><icon name="lock" size="80" color="#00CED1"></icon></view>
<text class="login-title">登录 卡若创业派对</text>
<text class="login-desc">{{desc}}</text>
<button id="agree-phone-btn" class="btn-wechat {{agreeProtocol ? '' : 'btn-wechat-disabled'}}" open-type="getPhoneNumber|agreePrivacyAuthorization" bindgetphonenumber="onPhoneLogin" bindagreeprivacyauthorization="onAgreePrivacy" disabled="{{isLoggingIn || !agreeProtocol}}">
<text class="btn-wechat-icon">微</text>
<text>{{isLoggingIn ? '登录中...' : '手机号一键登录'}}</text>
</button>
<view class="privacy-wechat-row" wx:if="{{showPrivacyModal}}">
<text class="privacy-wechat-desc">为获取手机号,请先同意《用户隐私保护指引》</text>
<button id="agree-privacy-btn" class="privacy-agree-btn" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="onAgreePrivacy">同意</button>
</view>
<view class="login-modal-cancel" wx:if="{{showCancel}}" bindtap="onClose">取消</view>
<view class="login-agree-row" catchtap="onToggleAgree">
<view class="agree-checkbox {{agreeProtocol ? 'agree-checked' : ''}}"><icon wx:if="{{agreeProtocol}}" name="check" size="24" color="#34C759"></icon></view>
<text class="agree-text">我已阅读并同意</text>
<text class="agree-link" catchtap="onOpenUserProtocol">《用户协议》</text>
<text class="agree-text">和</text>
<text class="agree-link" catchtap="onOpenPrivacy">《隐私政策》</text>
</view>
</view>
</view>

View File

@@ -0,0 +1,136 @@
/* Soul 创业派对 - 公用登录弹窗 */
.modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.7);
z-index: 1000;
display: flex;
align-items: center;
justify-content: center;
padding: 48rpx;
}
.modal-content {
width: 100%;
max-width: 600rpx;
background: #1c1c1e;
border-radius: 32rpx;
overflow: hidden;
}
.modal-close {
position: absolute;
top: 24rpx;
right: 24rpx;
z-index: 1;
padding: 16rpx;
}
.login-modal {
padding: 48rpx 32rpx;
text-align: center;
}
.login-icon {
font-size: 80rpx;
display: block;
margin-bottom: 24rpx;
}
.login-title {
font-size: 36rpx;
font-weight: 700;
color: #ffffff;
display: block;
margin-bottom: 16rpx;
}
.login-desc {
font-size: 26rpx;
color: rgba(255, 255, 255, 0.5);
display: block;
margin-bottom: 48rpx;
}
.btn-wechat {
display: flex;
align-items: center;
justify-content: center;
gap: 16rpx;
padding: 28rpx;
background: #07C160;
color: #ffffff;
font-size: 30rpx;
font-weight: 600;
border-radius: 24rpx;
margin-bottom: 20rpx;
border: none;
}
.btn-wechat::after { border: none; }
.btn-wechat-icon {
width: 40rpx;
height: 40rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 8rpx;
font-size: 24rpx;
display: flex;
align-items: center;
justify-content: center;
}
.btn-wechat-disabled { opacity: 0.6; }
.login-modal-cancel {
margin-top: 24rpx;
padding: 24rpx;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.5);
text-align: center;
}
.privacy-wechat-row {
margin: 24rpx 0;
padding: 24rpx;
background: rgba(0, 206, 209, 0.1);
border-radius: 16rpx;
}
.privacy-wechat-desc {
display: block;
font-size: 26rpx;
color: rgba(255, 255, 255, 0.8);
margin-bottom: 16rpx;
}
.privacy-agree-btn {
width: 100%;
padding: 20rpx;
background: #07C160;
color: #fff;
font-size: 28rpx;
border-radius: 16rpx;
border: none;
}
.privacy-agree-btn::after { border: none; }
.login-agree-row {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
margin-top: 32rpx;
font-size: 22rpx;
color: rgba(255, 255, 255, 0.5);
}
.agree-checkbox {
width: 32rpx;
height: 32rpx;
border: 2rpx solid rgba(255, 255, 255, 0.5);
border-radius: 6rpx;
margin-right: 12rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 22rpx;
flex-shrink: 0;
}
.agree-checked {
background: #00CED1;
border-color: #00CED1;
}
.agree-text { color: rgba(255, 255, 255, 0.6); }
.agree-link {
color: #00CED1;
text-decoration: underline;
padding: 0 4rpx;
}

View File

@@ -18,7 +18,6 @@ Page({
amountDisplay: '0.00',
isSinglePageMode: false,
showLoginModal: false,
agreeProtocol: false,
showPrivacyModal: false,
// 创建态
isCreateMode: false,
@@ -227,7 +226,7 @@ Page({
}
const userId = app.globalData.userInfo?.id
if (!userId) {
this.setData({ showLoginModal: true, agreeProtocol: false })
this.setData({ showLoginModal: true })
return
}
await this._doRedeem()
@@ -265,51 +264,15 @@ Page({
}
},
closeLoginModal() {
onLoginModalClose() {
this.setData({ showLoginModal: false, showPrivacyModal: false })
},
toggleAgree() {
this.setData({ agreeProtocol: !this.data.agreeProtocol })
},
async handleWechatLogin() {
if (!this.data.agreeProtocol) {
wx.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' })
return
}
try {
const result = await app.login()
if (!result) return
this.setData({ showLoginModal: false, agreeProtocol: false })
await this._doRedeem()
} catch (e) {
wx.showToast({ title: '登录失败', icon: 'none' })
}
},
handleAgreePrivacyForPhone() {
if (app._privacyResolve) {
app._privacyResolve({ buttonId: 'agree-privacy-btn', event: 'agree' })
app._privacyResolve = null
}
onLoginModalPrivacyAgree() {
this.setData({ showPrivacyModal: false })
},
async handlePhoneLogin(e) {
if (!e.detail.code) return this.handleWechatLogin()
try {
const result = await app.loginWithPhone(e.detail.code)
if (!result) return
this.setData({ showLoginModal: false })
await this._doRedeem()
} catch (e) {
wx.showToast({ title: '登录失败', icon: 'none' })
}
},
stopPropagation() {},
openUserProtocol() {
wx.navigateTo({ url: '/pages/agreement/agreement' })
},
openPrivacy() {
wx.navigateTo({ url: '/pages/privacy/privacy' })
async onLoginModalSuccess() {
this.setData({ showLoginModal: false })
await this._doRedeem()
},
goBack() {

View File

@@ -145,30 +145,15 @@
</view>
</view>
<!-- 登录弹窗(好友领取时未登录 -->
<view class="modal-overlay" wx:if="{{showLoginModal}}" bindtap="closeLoginModal">
<view class="modal-content login-modal" catchtap="stopPropagation">
<view class="modal-close" bindtap="closeLoginModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
<view class="login-icon"><icon name="lock" size="80" color="#00CED1"></icon></view>
<text class="login-title">登录 卡若创业派对</text>
<text class="login-desc">登录后可免费领取并阅读</text>
<button id="agree-phone-btn" class="btn-wechat {{agreeProtocol ? '' : 'btn-wechat-disabled'}}" open-type="getPhoneNumber|agreePrivacyAuthorization" bindgetphonenumber="handlePhoneLogin" bindagreeprivacyauthorization="handleAgreePrivacyForPhone" disabled="{{!agreeProtocol}}">
<text class="btn-wechat-icon">微</text>
<text>手机号一键登录</text>
</button>
<view class="privacy-wechat-row" wx:if="{{showPrivacyModal}}">
<text class="privacy-wechat-desc">为获取手机号,请先同意《用户隐私保护指引》</text>
<button id="agree-privacy-btn" class="privacy-agree-btn" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="handleAgreePrivacyForPhone">同意</button>
</view>
<view class="login-agree-row" catchtap="toggleAgree">
<view class="agree-checkbox {{agreeProtocol ? 'agree-checked' : ''}}"><icon wx:if="{{agreeProtocol}}" name="check" size="24" color="#34C759"></icon></view>
<text class="agree-text">我已阅读并同意</text>
<text class="agree-link" bindtap="openUserProtocol">《用户协议》</text>
<text class="agree-text">和</text>
<text class="agree-link" bindtap="openPrivacy">《隐私政策》</text>
</view>
</view>
</view>
<!-- 登录弹窗(公用组件 -->
<login-modal
show="{{showLoginModal}}"
desc="登录后可免费领取并阅读"
showPrivacyModal="{{showPrivacyModal}}"
bind:close="onLoginModalClose"
bind:success="onLoginModalSuccess"
bind:privacyagree="onLoginModalPrivacyAgree"
/>
<!-- 背景光效 -->
<view class="bg-effects">

View File

@@ -60,9 +60,6 @@ Page({
// 登录弹窗
showLoginModal: false,
isLoggingIn: false,
// 用户须主动勾选同意协议(审核要求:不得默认同意)
agreeProtocol: false,
showPrivacyModal: false,
// 修改昵称弹窗
@@ -691,93 +688,23 @@ Page({
console.warn('[My] 检测单页模式失败,回退为正常登录弹窗:', e)
}
try {
this.setData({ showLoginModal: true, agreeProtocol: false })
this.setData({ showLoginModal: true })
} catch (e) {
console.error('[My] showLogin error:', e)
this.setData({ showLoginModal: true })
}
},
// 切换协议勾选(用户主动勾选,非默认同意)
toggleAgree() {
this.setData({ agreeProtocol: !this.data.agreeProtocol })
},
// 打开用户协议页(审核要求:点击《用户协议》需有响应)
openUserProtocol() {
wx.navigateTo({ url: '/pages/agreement/agreement' })
},
// 打开隐私政策页(审核要求:点击《隐私政策》需有响应)
openPrivacy() {
wx.navigateTo({ url: '/pages/privacy/privacy' })
},
// 关闭登录弹窗
closeLoginModal() {
if (this.data.isLoggingIn) return
onLoginModalClose() {
this.setData({ showLoginModal: false, showPrivacyModal: false })
},
// 微信登录(须已勾选同意协议,且做好错误处理避免审核报错)
async handleWechatLogin() {
if (!this.data.agreeProtocol) {
wx.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' })
return
}
this.setData({ isLoggingIn: true })
try {
const result = await app.login()
if (result) {
this.initUserStatus()
this.setData({ showLoginModal: false, agreeProtocol: false })
wx.showToast({ title: '登录成功', icon: 'success' })
} else {
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
} catch (e) {
console.error('[My] 微信登录错误:', e)
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
} finally {
this.setData({ isLoggingIn: false })
}
},
// 微信隐私协议同意getPhoneNumber 需先同意)
handleAgreePrivacyForPhone() {
if (app._privacyResolve) {
app._privacyResolve({ buttonId: 'agree-privacy-btn', event: 'agree' })
app._privacyResolve = null
}
onLoginModalPrivacyAgree() {
this.setData({ showPrivacyModal: false })
},
// 手机号登录(需要用户授权)
async handlePhoneLogin(e) {
// 检查是否有授权code
if (!e.detail.code) {
// 用户拒绝授权或获取失败,尝试使用微信登录
console.log('手机号授权失败,尝试微信登录')
return this.handleWechatLogin()
}
this.setData({ isLoggingIn: true })
try {
const result = await app.loginWithPhone(e.detail.code)
if (result) {
this.initUserStatus()
this.setData({ showLoginModal: false })
wx.showToast({ title: '登录成功', icon: 'success' })
} else {
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
} catch (e) {
console.error('手机号登录错误:', e)
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
} finally {
this.setData({ isLoggingIn: false })
}
onLoginModalSuccess() {
this.initUserStatus()
this.setData({ showLoginModal: false })
wx.showToast({ title: '登录成功', icon: 'success' })
},
// 点击菜单

View File

@@ -171,31 +171,16 @@
</view>
</view>
<!-- 登录弹窗 -->
<view class="modal-overlay" wx:if="{{showLoginModal}}" bindtap="closeLoginModal">
<view class="modal-content login-modal-content" catchtap="stopPropagation">
<view class="modal-close" bindtap="closeLoginModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
<view class="login-icon"><icon name="lock" size="80" color="#00CED1"></icon></view>
<text class="login-title">登录 卡若创业派对</text>
<text class="login-desc">登录后可购买章节、解锁更多内容</text>
<button id="agree-phone-btn" class="btn-wechat {{agreeProtocol ? '' : 'btn-wechat-disabled'}}" open-type="getPhoneNumber|agreePrivacyAuthorization" bindgetphonenumber="handlePhoneLogin" bindagreeprivacyauthorization="handleAgreePrivacyForPhone" disabled="{{isLoggingIn || !agreeProtocol}}">
<text class="btn-wechat-icon">微</text>
<text>{{isLoggingIn ? '登录中...' : '手机号一键登录'}}</text>
</button>
<view class="privacy-wechat-row" wx:if="{{showPrivacyModal}}">
<text class="privacy-wechat-desc">为获取手机号,请先同意《用户隐私保护指引》</text>
<button id="agree-privacy-btn" class="privacy-agree-btn" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="handleAgreePrivacyForPhone">同意</button>
</view>
<view class="login-modal-cancel" bindtap="closeLoginModal">取消</view>
<view class="login-agree-row" catchtap="toggleAgree">
<view class="agree-checkbox {{agreeProtocol ? 'agree-checked' : ''}}"><icon wx:if="{{agreeProtocol}}" name="check" size="24" color="#34C759"></icon></view>
<text class="agree-text">我已阅读并同意</text>
<text class="agree-link" catchtap="openUserProtocol">《用户协议》</text>
<text class="agree-text">和</text>
<text class="agree-link" catchtap="openPrivacy">《隐私政策》</text>
</view>
</view>
</view>
<!-- 登录弹窗(公用组件) -->
<login-modal
show="{{showLoginModal}}"
desc="登录后可购买章节、解锁更多内容"
showPrivacyModal="{{showPrivacyModal}}"
showCancel="{{true}}"
bind:close="onLoginModalClose"
bind:success="onLoginModalSuccess"
bind:privacyagree="onLoginModalPrivacyAgree"
/>
<!-- 手机/微信号弹窗 -->
<view class="modal-overlay contact-modal-overlay" wx:if="{{showContactModal}}" bindtap="closeContactModal">

View File

@@ -74,7 +74,6 @@ Page({
giftPaid: false,
giftRequestSn: '',
showLoginModal: false,
agreeProtocol: false,
showPrivacyModal: false,
showPosterModal: false,
isPaying: false,
@@ -975,78 +974,23 @@ Page({
console.warn('[Read] 检测单页模式失败,回退为正常登录流程:', e)
}
try {
this.setData({ showLoginModal: true, agreeProtocol: false })
this.setData({ showLoginModal: true })
} catch (e) {
console.error('[Read] showLoginModal error:', e)
this.setData({ showLoginModal: true })
}
},
closeLoginModal() {
onLoginModalClose() {
this.setData({ showLoginModal: false, showPrivacyModal: false })
},
toggleAgree() {
this.setData({ agreeProtocol: !this.data.agreeProtocol })
},
openUserProtocol() {
wx.navigateTo({ url: '/pages/agreement/agreement' })
},
openPrivacy() {
wx.navigateTo({ url: '/pages/privacy/privacy' })
},
// 从服务端刷新购买状态,避免登录后误用旧数据导致误解锁
// 【重构】微信登录(须先勾选同意协议,符合审核要求)
async handleWechatLogin() {
if (!this.data.agreeProtocol) {
wx.showToast({ title: '请先阅读并同意用户协议和隐私政策', icon: 'none' })
return
}
try {
const result = await app.login()
if (!result) return
this.setData({ showLoginModal: false, agreeProtocol: false })
await this.onLoginSuccess()
wx.showToast({ title: '登录成功', icon: 'success' })
} catch (e) {
console.error('[Read] 登录失败:', e)
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
},
// 微信隐私协议同意getPhoneNumber 需先同意)
handleAgreePrivacyForPhone() {
const app = getApp()
if (app._privacyResolve) {
app._privacyResolve({ buttonId: 'agree-privacy-btn', event: 'agree' })
app._privacyResolve = null
}
onLoginModalPrivacyAgree() {
this.setData({ showPrivacyModal: false })
},
// 【重构】手机号登录(标准流程)
async handlePhoneLogin(e) {
if (!e.detail.code) {
return this.handleWechatLogin()
}
try {
const result = await app.loginWithPhone(e.detail.code)
if (!result) return
this.setData({ showLoginModal: false })
await this.onLoginSuccess()
wx.showToast({ title: '登录成功', icon: 'success' })
} catch (e) {
console.error('[Read] 手机号登录失败:', e)
wx.showToast({ title: '登录失败', icon: 'none' })
}
async onLoginModalSuccess() {
this.setData({ showLoginModal: false })
await this.onLoginSuccess()
wx.showToast({ title: '登录成功', icon: 'success' })
},
// 【新增】登录成功后的标准处理流程

View File

@@ -333,32 +333,15 @@
</view>
</view>
<!-- 登录弹窗 - 须勾选同意协议,《用户协议》《隐私政策》可点击查看 -->
<view class="modal-overlay" wx:if="{{showLoginModal}}" bindtap="closeLoginModal">
<view class="modal-content login-modal" catchtap="stopPropagation">
<view class="modal-close" bindtap="closeLoginModal"><icon name="x" size="36" color="#8e8e93"></icon></view>
<view class="login-icon"><icon name="lock" size="80" color="#00CED1"></icon></view>
<text class="login-title">登录 卡若创业派对</text>
<text class="login-desc">登录后可购买章节、解锁更多内容</text>
<button id="agree-phone-btn" class="btn-wechat {{agreeProtocol ? '' : 'btn-wechat-disabled'}}" open-type="getPhoneNumber|agreePrivacyAuthorization" bindgetphonenumber="handlePhoneLogin" bindagreeprivacyauthorization="handleAgreePrivacyForPhone" disabled="{{!agreeProtocol}}">
<text class="btn-wechat-icon">微</text>
<text>手机号一键登录</text>
</button>
<view class="privacy-wechat-row" wx:if="{{showPrivacyModal}}">
<text class="privacy-wechat-desc">为获取手机号,请先同意《用户隐私保护指引》</text>
<button id="agree-privacy-btn" class="privacy-agree-btn" open-type="agreePrivacyAuthorization" bindagreeprivacyauthorization="handleAgreePrivacyForPhone">同意</button>
</view>
<view class="login-agree-row" catchtap="toggleAgree">
<view class="agree-checkbox {{agreeProtocol ? 'agree-checked' : ''}}"><icon wx:if="{{agreeProtocol}}" name="check" size="24" color="#34C759"></icon></view>
<text class="agree-text">我已阅读并同意</text>
<text class="agree-link" catchtap="openUserProtocol">《用户协议》</text>
<text class="agree-text">和</text>
<text class="agree-link" catchtap="openPrivacy">《隐私政策》</text>
</view>
</view>
</view>
<!-- 登录弹窗(公用组件) -->
<login-modal
show="{{showLoginModal}}"
desc="登录后可购买章节、解锁更多内容"
showPrivacyModal="{{showPrivacyModal}}"
bind:close="onLoginModalClose"
bind:success="onLoginModalSuccess"
bind:privacyagree="onLoginModalPrivacyAgree"
/>
<!-- 支付中提示 -->
<view class="modal-overlay" wx:if="{{isPaying}}" catchtap="">

View File

@@ -16,7 +16,14 @@
* 浏览导师页 → browse_mentor
*/
const app = getApp()
function getAppInstance() {
try {
const a = getApp()
return a && a.globalData ? a : null
} catch (e) {
return null
}
}
const RULE_COOLDOWN_KEY = 'rule_engine_cooldown'
const COOLDOWN_MS = 60 * 1000
@@ -60,11 +67,14 @@ function setCooldown(ruleId) {
}
function getUserInfo() {
return app.globalData.userInfo || {}
const app = getAppInstance()
return app ? (app.globalData.userInfo || {}) : {}
}
async function loadRules() {
if (_cachedRules && Date.now() - _cacheTs < CACHE_TTL) return _cachedRules
const app = getAppInstance()
if (!app) return _cachedRules || []
try {
const res = await app.request({ url: '/api/miniprogram/user-rules', method: 'GET', silent: true })
if (res && res.success && res.rules) {
@@ -90,7 +100,8 @@ function getRuleInfo(rules, triggerName) {
// VIP 用户不触发:统一由 checkVipContactRequiredAndGuide 引导到 profile-edit避免与主流程冲突
function checkRule_FillAvatar(rules) {
if (!isRuleEnabled(rules, '注册')) return null
if (app.globalData.isVip) return null
const app = getAppInstance()
if (app && app.globalData.isVip) return null
const user = getUserInfo()
if (!user.id) return null
const avatar = user.avatar || user.avatarUrl || ''
@@ -147,7 +158,8 @@ function checkRule_ShareAfter5Chapters(rules) {
if (!isRuleEnabled(rules, '累计浏览5章节')) return null
const user = getUserInfo()
if (!user.id) return null
const readCount = (typeof app.getReadCount === 'function' ? app.getReadCount() : (app.globalData.readCount || 0))
const app = getAppInstance()
const readCount = app ? (typeof app.getReadCount === 'function' ? app.getReadCount() : (app.globalData.readCount || 0)) : 0
if (readCount < 5) return null
if (isInCooldown('share_after_5')) return null
setCooldown('share_after_5')
@@ -166,7 +178,8 @@ function checkRule_FillVipInfo(rules) {
if (!isRuleEnabled(rules, '完成付款')) return null
const user = getUserInfo()
if (!user.id) return null
if (!(app.globalData.hasFullBook || app.globalData.hasPurchasedFull)) return null
const app = getAppInstance()
if (!app || !(app.globalData.hasFullBook || app.globalData.hasPurchasedFull)) return null
if (user.wechatId && user.address) return null
if (isInCooldown('fill_vip_info')) return null
setCooldown('fill_vip_info')
@@ -218,7 +231,8 @@ function checkRule_Withdraw(rules) {
if (!isRuleEnabled(rules, '收益满50元')) return null
const user = getUserInfo()
if (!user.id) return null
const earnings = app.globalData.totalEarnings || 0
const app = getAppInstance()
const earnings = app ? (app.globalData.totalEarnings || 0) : 0
if (earnings < 50) return null
if (isInCooldown('withdraw_50')) return null
setCooldown('withdraw_50')
@@ -280,6 +294,8 @@ function executeRule(rule, pageInstance) {
function _trackRuleAction(ruleId, action) {
const userId = getUserInfo().id
if (!userId) return
const app = getAppInstance()
if (!app) return
app.request({
url: '/api/miniprogram/track',
method: 'POST',