189 lines
5.8 KiB
JavaScript
189 lines
5.8 KiB
JavaScript
/**
|
||
* 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')
|
||
}
|
||
})
|