This commit is contained in:
Alex-larget
2026-03-24 18:45:32 +08:00
parent dcb7961945
commit f3d74ce94a
68 changed files with 2461 additions and 2535 deletions

View File

@@ -9,7 +9,9 @@ const { checkAndExecute } = require('./utils/ruleEngine.js')
const DEFAULT_APP_ID = 'wxb8bbb2b10dec74aa'
const DEFAULT_MCH_ID = '1318592501'
const DEFAULT_WITHDRAW_TMPL_ID = 'u3MbZGPRkrZIk-I7QdpwzFxnO_CeQPaCWF2FkiIablE'
const PRODUCTION_BASE_URL = 'https://soulapi.quwanzhi.com'
// baseUrl 手动切换(注释方式):
const API_BASE_URL = 'http://localhost:8080'
// const API_BASE_URL = 'https://soulapi.quwanzhi.com'
const CONFIG_CACHE_KEY = 'mpConfigCacheV1'
// 与上传版本号对齐;设置页展示优先用 wx.getAccountInfoSync().miniProgram.version正式版否则用本字段
const APP_DISPLAY_VERSION = '1.7.2'
@@ -19,8 +21,8 @@ App({
// 与微信后台上传版本号一致,供设置页等展示(避免与线上 version 字段混淆)
appDisplayVersion: APP_DISPLAY_VERSION,
// API仓库默认生产release 强制生产develop/trial 可读 storage「apiBaseUrl」或用 env-switch
baseUrl: 'https://soulapi.quwanzhi.com',
// API仅使用代码常量手动切换,不再使用运行时开关
baseUrl: API_BASE_URL,
// 小程序配置 - 真实AppID
appId: DEFAULT_APP_ID,
@@ -98,39 +100,17 @@ App({
lastVipContactCheck: 0,
// 头像昵称检测:上次检测时间戳(与 VIP 检测同周期刷新)
lastAvatarNicknameCheck: 0,
// 登录后规则引擎触发时间(用于与本地引导去重,避免短时间二次弹窗)
lastAfterLoginRuleCheck: 0,
/** MBTI → 默认头像 URL/api/miniprogram/config/mbti-avatars供推广海报等 */
mbtiAvatarsMap: {},
mbtiAvatarsExpires: 0,
},
/** 正式版强制生产 API避免误传 localhost 导致审核/线上全挂 */
initApiBaseUrl() {
const KEY = 'apiBaseUrl'
try {
const info = wx.getAccountInfoSync?.()
const env = info?.miniProgram?.envVersion || 'release'
if (env === 'release') {
this.globalData.baseUrl = PRODUCTION_BASE_URL
try {
const saved = wx.getStorageSync(KEY)
if (saved && saved !== PRODUCTION_BASE_URL) wx.removeStorageSync(KEY)
} catch (_) {}
return
}
const saved = wx.getStorageSync(KEY)
if (saved && typeof saved === 'string' && /^https?:\/\//.test(saved)) {
this.globalData.baseUrl = String(saved).replace(/\/$/, '')
} else {
this.globalData.baseUrl = PRODUCTION_BASE_URL
}
} catch (_) {
this.globalData.baseUrl = PRODUCTION_BASE_URL
}
},
onLaunch(options) {
this.initApiBaseUrl()
// baseUrl 固定取 API_BASE_URL通过注释切换
this.globalData.baseUrl = API_BASE_URL
// 昵称等隐私组件需先授权input type="nickname" 不会主动触发,需配合 wx.requirePrivacyAuthorize 使用
if (typeof wx.onNeedPrivacyAuthorization === 'function') {
wx.onNeedPrivacyAuthorization((resolve) => {
@@ -616,7 +596,12 @@ App({
const isVip = vipRes?.data?.isVip || this.globalData.isVip || false
this.globalData.isVip = isVip
if (!isVip) {
this.checkAvatarNicknameAndGuide()
const now = Date.now()
const lastRuleCheck = Number(this.globalData.lastAfterLoginRuleCheck || 0)
// 登录后若规则引擎刚触发过 after_login引导由规则引擎负责避免与本地提示连弹
if (!lastRuleCheck || now - lastRuleCheck > 5000) {
this.checkAvatarNicknameAndGuide()
}
return
}
@@ -933,27 +918,6 @@ App({
return (msg && String(msg).trim()) ? String(msg).trim() : defaultMsg
},
_shouldFallbackToProduction(err) {
const msg = String((err && err.errMsg) || (err && err.message) || '').toLowerCase()
return (
msg.includes('connection_failed') ||
msg.includes('err_proxy_connection_failed') ||
msg.includes('dns') ||
msg.includes('name not resolved') ||
msg.includes('failed to fetch') ||
msg.includes('econnrefused') ||
msg.includes('network') ||
msg.includes('timeout')
)
},
_switchBaseUrlToProduction() {
this.globalData.baseUrl = PRODUCTION_BASE_URL
try {
wx.setStorageSync('apiBaseUrl', PRODUCTION_BASE_URL)
} catch (_) {}
},
_requestOnce(url, options = {}, silent = false) {
const showError = (msg) => {
if (!silent && msg) wx.showToast({ title: msg, icon: 'none', duration: 2500 })
@@ -972,6 +936,11 @@ App({
},
success: (res) => {
const data = res.data
const rejectWithBody = (message, body) => {
const err = new Error(message)
if (body != null && typeof body === 'object') err.response = body
reject(err)
}
if (res.statusCode === 200) {
if (data && data.success === false) {
const msg = this._getApiErrorMsg(data, '操作失败')
@@ -979,7 +948,7 @@ App({
this.logout()
}
showError(msg)
reject(new Error(msg))
rejectWithBody(msg, data)
return
}
resolve(data)
@@ -988,12 +957,14 @@ App({
if (res.statusCode === 401) {
this.logout()
showError('未授权,请重新登录')
reject(new Error('未授权'))
const err = new Error('未授权')
if (data != null && typeof data === 'object') err.response = data
reject(err)
return
}
const msg = this._getApiErrorMsg(data, res.statusCode >= 500 ? '服务器异常,请稍后重试' : '请求失败')
showError(msg)
reject(new Error(msg))
rejectWithBody(msg, data && typeof data === 'object' ? data : undefined)
},
fail: (err) => {
const msg = (err && err.errMsg)
@@ -1033,13 +1004,10 @@ App({
}
const promise = this._requestOnce(url, options, silent).catch(async (err) => {
const currentBase = String(this.globalData.baseUrl || '').replace(/\/$/, '')
if (currentBase !== PRODUCTION_BASE_URL && this._shouldFallbackToProduction(err)) {
this._switchBaseUrlToProduction()
return this._requestOnce(url, options, silent)
}
const msg = (err && err.message) ? err.message : '网络异常,请重试'
throw new Error(msg)
const next = new Error(msg)
if (err && err.response != null) next.response = err.response
throw next
})
if (method === 'GET') {
@@ -1102,8 +1070,9 @@ App({
this.globalData.vipExpireDate = user.vipExpireDate || ''
// 首次登录注册:强制跳转 avatar-nickname 修改头像昵称(不弹窗)
if (res.isNewUser === true && this._needsAvatarNickname(user)) {
setTimeout(() => wx.redirectTo({ url: '/pages/avatar-nickname/avatar-nickname' }), 1000)
setTimeout(() => wx.redirectTo({ url: '/pages/avatar-nickname/avatar-nickname?from=new_user' }), 1000)
} else {
this.globalData.lastAfterLoginRuleCheck = Date.now()
checkAndExecute('after_login', null)
setTimeout(() => this.checkVipContactRequiredAndGuide(), 1200)
setTimeout(() => this.connectWsHeartbeat(), 2000)
@@ -1173,8 +1142,9 @@ App({
this.globalData.vipExpireDate = user.vipExpireDate || ''
// 首次登录注册:强制跳转 avatar-nickname
if (res.isNewUser === true && this._needsAvatarNickname(user)) {
setTimeout(() => wx.redirectTo({ url: '/pages/avatar-nickname/avatar-nickname' }), 1000)
setTimeout(() => wx.redirectTo({ url: '/pages/avatar-nickname/avatar-nickname?from=new_user' }), 1000)
} else {
this.globalData.lastAfterLoginRuleCheck = Date.now()
checkAndExecute('after_login', null)
setTimeout(() => this.checkVipContactRequiredAndGuide(), 1200)
}
@@ -1234,8 +1204,9 @@ App({
// 首次登录注册:强制跳转 avatar-nickname
if (res.isNewUser === true && this._needsAvatarNickname(user)) {
setTimeout(() => wx.redirectTo({ url: '/pages/avatar-nickname/avatar-nickname' }), 1000)
setTimeout(() => wx.redirectTo({ url: '/pages/avatar-nickname/avatar-nickname?from=new_user' }), 1000)
} else {
this.globalData.lastAfterLoginRuleCheck = Date.now()
checkAndExecute('after_login', null)
setTimeout(() => this.checkVipContactRequiredAndGuide(), 1200)
}