/** * Soul创业派对 - 目录页 * 开发: 卡若 * 技术支持: 存客宝 * 数据: 完整真实文章标题 */ const app = getApp() Page({ data: { // 系统信息 statusBarHeight: 44, navBarHeight: 88, // 用户状态 isLoggedIn: false, hasFullBook: false, purchasedSections: [], // 书籍数据:以后台内容管理为准,仅用接口 /api/miniprogram/book/all-chapters 返回的数据 totalSections: 0, bookData: [], // 展开状态:默认不展开任何篇章,直接显示目录 expandedPart: null, // 附录 appendixList: [ { id: 'appendix-1', title: '附录1|Soul派对房精选对话' }, { id: 'appendix-2', title: '附录2|创业者自检清单' }, { id: 'appendix-3', title: '附录3|本书提到的工具和资源' } ], // 每日新增章节 dailyChapters: [] }, onLoad() { wx.showShareMenu({ withShareTimeline: true }) this.setData({ statusBarHeight: app.globalData.statusBarHeight, navBarHeight: app.globalData.navBarHeight }) this.updateUserStatus() this.loadChaptersOnce() }, // 固定模块(序言、尾声、附录)不参与中间篇章 _isFixedPart(pt) { if (!pt) return false const p = String(pt).toLowerCase().replace(/[_\s||]/g, '') return p.includes('序言') || p.includes('尾声') || p.includes('附录') }, // 一次请求拉取全量目录,以后台内容管理为准;同时更新 totalSections / bookData / dailyChapters async loadChaptersOnce() { try { const res = await app.request({ url: '/api/miniprogram/book/all-chapters', silent: true }) const rows = (res && res.data) || (res && res.chapters) || [] // 无数据时清空目录,避免展示旧数据 if (rows.length === 0) { app.globalData.bookData = [] wx.setStorageSync('bookData', []) this.setData({ bookData: [], totalSections: 0, dailyChapters: [], expandedPart: null }) return } const totalSections = res.total ?? rows.length app.globalData.bookData = rows wx.setStorageSync('bookData', rows) // bookData:过滤序言/尾声/附录,按 part 聚合,篇章顺序按 sort_order 与后台一致(含「2026每日派对干货」等) const filtered = rows.filter(r => !this._isFixedPart(r.partTitle || r.part_title)) const partMap = new Map() const numbers = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二'] filtered.forEach((r) => { const pid = r.partId || r.part_id || 'part-1' const cid = r.chapterId || r.chapter_id || 'chapter-1' const sortOrder = r.sectionOrder ?? r.sort_order ?? 999999 if (!partMap.has(pid)) { const partIdx = partMap.size partMap.set(pid, { id: pid, number: numbers[partIdx] || String(partIdx + 1), title: r.partTitle || r.part_title || '未分类', subtitle: r.chapterTitle || r.chapter_title || '', chapters: new Map(), minSortOrder: sortOrder }) } const part = partMap.get(pid) if (sortOrder < part.minSortOrder) part.minSortOrder = sortOrder if (!part.chapters.has(cid)) { part.chapters.set(cid, { id: cid, title: r.chapterTitle || r.chapter_title || '未分类', sections: [] }) } const ch = part.chapters.get(cid) ch.sections.push({ id: r.id, mid: r.mid ?? r.MID ?? 0, title: r.sectionTitle || r.section_title || r.title || '', isFree: r.isFree === true || (r.price !== undefined && r.price === 0), price: r.price ?? 1, isNew: r.isNew === true || r.is_new === true }) }) const partList = Array.from(partMap.values()) partList.sort((a, b) => (a.minSortOrder ?? 999999) - (b.minSortOrder ?? 999999)) const bookData = partList.map((p, idx) => ({ id: p.id, number: numbers[idx] || String(idx + 1), title: p.title, subtitle: p.subtitle, chapters: Array.from(p.chapters.values()) })) const baseSort = 62 const daily = rows .filter(r => (r.sectionOrder ?? r.sort_order ?? 0) > baseSort) .sort((a, b) => new Date(b.updatedAt || b.updated_at || 0) - new Date(a.updatedAt || a.updated_at || 0)) .slice(0, 20) .map(c => { const d = new Date(c.updatedAt || c.updated_at || Date.now()) return { id: c.id, mid: c.mid ?? c.MID ?? 0, title: c.section_title || c.title || c.sectionTitle, price: c.price ?? 1, dateStr: `${d.getMonth() + 1}/${d.getDate()}` } }) this.setData({ bookData, totalSections, dailyChapters: daily, expandedPart: this.data.expandedPart }) } catch (e) { console.log('[Chapters] 加载目录失败:', e) this.setData({ bookData: [], totalSections: 0 }) } }, onPullDownRefresh() { this.loadChaptersOnce().then(() => wx.stopPullDownRefresh()).catch(() => wx.stopPullDownRefresh()) }, onShow() { // 设置TabBar选中状态 if (typeof this.getTabBar === 'function' && this.getTabBar()) { const tabBar = this.getTabBar() if (tabBar.updateSelected) { tabBar.updateSelected() } else { tabBar.setData({ selected: 1 }) } } this.updateUserStatus() }, // 更新用户状态 updateUserStatus() { const { isLoggedIn, hasFullBook, purchasedSections } = app.globalData this.setData({ isLoggedIn, hasFullBook, purchasedSections }) }, // 切换展开状态 togglePart(e) { const partId = e.currentTarget.dataset.id this.setData({ expandedPart: this.data.expandedPart === partId ? null : partId }) }, // 跳转到阅读页(优先传 mid,与分享逻辑一致) goToRead(e) { const id = e.currentTarget.dataset.id const mid = e.currentTarget.dataset.mid || app.getSectionMid(id) const q = mid ? `mid=${mid}` : `id=${id}` wx.navigateTo({ url: `/pages/read/read?${q}` }) }, // 检查是否已购买 hasPurchased(sectionId) { if (this.data.hasFullBook) return true return this.data.purchasedSections.includes(sectionId) }, // 返回首页 goBack() { wx.switchTab({ url: '/pages/index/index' }) }, // 跳转到搜索页 goToSearch() { wx.navigateTo({ url: '/pages/search/search' }) }, onShareAppMessage() { const ref = app.getMyReferralCode() return { title: 'Soul创业派对 - 目录', path: ref ? `/pages/chapters/chapters?ref=${ref}` : '/pages/chapters/chapters' } }, onShareTimeline() { const ref = app.getMyReferralCode() return { title: 'Soul创业派对 - 真实商业故事', query: ref ? `ref=${ref}` : '' } } })