Files
soul-yongping/miniprogram/app.js

189 lines
5.8 KiB
JavaScript
Raw Normal View History

/**
* Soul创业派对 - 小程序入口
*/
App({
globalData: {
baseUrl: 'https://soul.quwanzhi.com',
appId: 'wxb8bbb2b10dec74aa',
userInfo: null,
openId: null,
isLoggedIn: false,
purchasedSections: [],
hasFullBook: false,
pendingReferralCode: null,
theme: {
brandColor: '#00CED1',
brandSecondary: '#20B2AA',
goldColor: '#FFD700',
bgColor: '#000000',
cardBg: '#1c1c1e'
},
systemInfo: null,
statusBarHeight: 44,
navBarHeight: 88,
capsulePaddingRight: 0,
currentTab: 0,
features: null,
matchEnabled: false,
_featureConfigLastFetch: 0
},
onLaunch(options) {
try {
this.getSystemInfo()
this.checkLoginStatus()
this.handleReferralCode(options)
// 异步请求不阻塞启动失败也不影响模拟器启动loadBookData 内部已 catch
this.loadFeatureConfig().catch(() => {})
this.loadBookData()
} catch (e) {
console.error('[App] onLaunch error', e)
}
},
onShow(options) {
this.handleReferralCode(options)
this.loadFeatureConfig()
},
loadFeatureConfig(forceRefresh) {
const now = Date.now()
const throttleMs = 15000
if (!forceRefresh && this.globalData._featureConfigLastFetch && (now - this.globalData._featureConfigLastFetch < throttleMs)) {
return Promise.resolve(this.globalData.features)
}
return this.request('/api/db/config')
.then((res) => {
if (res && res.features) {
this.globalData.features = res.features
this.globalData.matchEnabled = res.features.matchEnabled === true
this.globalData._featureConfigLastFetch = Date.now()
return this.globalData.features
}
return this.globalData.features
})
.catch((e) => {
console.log('[App] 加载功能配置失败', e)
return this.globalData.features
})
},
handleReferralCode(options) {
const query = options?.query || {}
const refCode = query.ref || query.referralCode
if (refCode) {
this.globalData.pendingReferralCode = refCode
wx.setStorageSync('pendingReferralCode', refCode)
}
},
getSystemInfo() {
try {
const systemInfo = wx.getSystemInfoSync()
this.globalData.systemInfo = systemInfo
const statusBarHeight = systemInfo.statusBarHeight || 44
this.globalData.statusBarHeight = statusBarHeight
const menuButton = wx.getMenuButtonBoundingClientRect()
if (menuButton && menuButton.top != null) {
this.globalData.navBarHeight = (menuButton.top - statusBarHeight) * 2 + menuButton.height + statusBarHeight
const w = systemInfo.windowWidth || 375
this.globalData.capsulePaddingRight = Math.ceil(w - menuButton.left + 8)
} else {
this.globalData.navBarHeight = statusBarHeight + 44
}
} catch (e) {
console.error('获取系统信息失败', e)
}
},
checkLoginStatus() {
try {
const userInfo = wx.getStorageSync('userInfo')
const token = wx.getStorageSync('token')
if (userInfo && token) {
this.globalData.userInfo = userInfo
this.globalData.isLoggedIn = true
this.globalData.purchasedSections = userInfo.purchasedSections || []
this.globalData.hasFullBook = userInfo.hasFullBook || false
}
} catch (e) {
console.error('检查登录状态失败', e)
}
},
loadBookData() {
this.request('/api/book/all-chapters')
.then((res) => {
if (res && res.data) {
this.globalData.bookData = res.data
wx.setStorageSync('bookData', res.data)
}
})
.catch((e) => console.error('加载书籍数据失败', e))
},
request(url, options = {}) {
return new Promise((resolve, reject) => {
const token = wx.getStorageSync('token')
const fullUrl = this.globalData.baseUrl + url
wx.request({
url: fullUrl,
method: options.method || 'GET',
data: options.data || {},
header: {
'Content-Type': 'application/json',
'Authorization': token ? `Bearer ${token}` : '',
...options.header
},
success: (res) => {
if (res.statusCode === 200) resolve(res.data)
else if (res.statusCode === 401) {
this.logout()
reject(new Error('未授权'))
} else reject(new Error(res.data?.message || '请求失败'))
},
fail: (err) => {
console.warn('[Request] fail', fullUrl, err)
reject(err && err.errMsg ? new Error(err.errMsg) : new Error('网络请求失败'))
}
})
})
},
async login() {
try {
const loginRes = await new Promise((resolve, reject) => wx.login({ success: resolve, fail: reject }))
const res = await this.request('/api/miniprogram/login', { method: 'POST', data: { code: loginRes.code } })
if (res && res.success && res.data) {
if (res.data.openId) {
this.globalData.openId = res.data.openId
wx.setStorageSync('openId', res.data.openId)
}
if (res.data.user) {
this.globalData.userInfo = res.data.user
this.globalData.isLoggedIn = true
this.globalData.purchasedSections = res.data.user.purchasedSections || []
this.globalData.hasFullBook = res.data.user.hasFullBook || false
wx.setStorageSync('userInfo', res.data.user)
wx.setStorageSync('token', res.data.token || '')
}
return res.data
}
} catch (e) {
console.error('登录失败', e)
wx.showToast({ title: '登录失败,请重试', icon: 'none' })
}
return null
},
logout() {
this.globalData.userInfo = null
this.globalData.isLoggedIn = false
this.globalData.purchasedSections = []
this.globalData.hasFullBook = false
wx.removeStorageSync('userInfo')
wx.removeStorageSync('token')
}
})