const app = getApp() Page({ data: { statusBarHeight: 44, navBarHeight: 88, totalSections: 62, bookData: [], expandedPart: 'part-1', hasFullBook: false, purchasedSections: [], appendixList: [ { id: 'appendix-1', title: '附录1|Soul派对房精选对话' }, { id: 'appendix-2', title: '附录2|创业者自检清单' }, { id: 'appendix-3', title: '附录3|本书提到的工具和资源' } ] }, onLoad() { this.setNavBarHeight() this.loadChapters() this.syncUserStatus() }, onShow() { if (typeof this.getTabBar === 'function' && this.getTabBar()) this.getTabBar().setData({ selected: 1 }) this.setNavBarHeight() this.syncUserStatus() }, setNavBarHeight() { const statusBarHeight = app.globalData.statusBarHeight || 44 const navBarHeight = app.globalData.navBarHeight || (statusBarHeight + 44) this.setData({ statusBarHeight, navBarHeight }) }, loadChapters() { app.request('/api/book/all-chapters').then((res) => { if (res && res.data && Array.isArray(res.data)) { const bookData = this.normalizeBookData(res.data) const totalSections = res.totalSections || res.total || res.data.length || 62 this.setData({ bookData, totalSections }) } else if (res && res.chapters) { const bookData = this.normalizeBookData(res.chapters) this.setData({ bookData, totalSections: res.chapters.length || 62 }) } }).catch(() => {}) }, normalizeBookData(list) { if (!Array.isArray(list) || list.length === 0) return [] const partOrder = ['part-1', 'part-2', 'part-3', 'part-4', 'part-5'] const partTitles = ['真实的人', '真实的行业', '真实的错误', '真实的赚钱', '真实的未来'] const partMap = {} const subtitles = ['人性观察与社交逻辑', '社会运作的底层规则', '错过机会比失败更贵', '所有行业的杠杆结构', '人与系统的关系'] partOrder.forEach((id, i) => { partMap[id] = { id, number: String(i + 1).padStart(2, '0'), title: partTitles[i] || ('篇' + (i + 1)), subtitle: subtitles[i] || '', chapters: [] } }) list.forEach((s) => { let partId = s.partId || s.part_id if (!partId && s.id) { const num = String(s.id).split('.')[0] partId = partOrder[parseInt(num, 10) - 1] || 'part-1' } partId = partId || 'part-1' if (!partMap[partId]) partMap[partId] = { id: partId, number: '99', title: '其他', subtitle: '', chapters: [] } const chId = s.chapterId || s.chapter_id || 'ch1' let ch = partMap[partId].chapters.find(c => c.id === chId) if (!ch) { ch = { id: chId, title: s.chapterTitle || s.chapter_title || '章节', sections: [] } partMap[partId].chapters.push(ch) } ch.sections.push({ id: s.id, title: s.sectionTitle || s.title || s.section_title || '', isFree: !!s.isFree || !!s.is_free, price: s.price != null ? s.price : 1 }) }) const out = partOrder.map(id => partMap[id]).filter(p => p.chapters.length > 0) out.forEach(p => { p.sectionCount = p.chapters.reduce((acc, ch) => acc + (ch.sections ? ch.sections.length : 0), 0) }) if (out.length === 0) { const sections = list.map(s => ({ id: s.id, title: s.sectionTitle || s.title || s.section_title || '', isFree: !!s.isFree || !!s.is_free, price: s.price != null ? s.price : 1 })) const single = { id: 'part-1', number: '01', title: '全部', subtitle: '', sectionCount: sections.length, chapters: [{ id: 'ch1', title: '章节', sections }] } return [single] } return out }, syncUserStatus() { const { hasFullBook, purchasedSections } = app.globalData this.setData({ hasFullBook: !!hasFullBook, purchasedSections: purchasedSections || [] }) }, hasPurchased(sectionId) { const { hasFullBook, purchasedSections } = app.globalData if (hasFullBook) return true return (purchasedSections || []).indexOf(sectionId) >= 0 }, togglePart(e) { const id = e.currentTarget.dataset.id const expandedPart = this.data.expandedPart === id ? '' : id this.setData({ expandedPart }) }, goToSearch() { wx.navigateTo({ url: '/pages/search/search' }) }, goToRead(e) { const id = e.currentTarget.dataset.id if (!id) return wx.navigateTo({ url: '/pages/read/read?id=' + encodeURIComponent(id) }) }, onPullDownRefresh() { this.loadChapters() this.syncUserStatus() wx.stopPullDownRefresh() } })