223 lines
6.9 KiB
JavaScript
223 lines
6.9 KiB
JavaScript
/**
|
||
* 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}` : '' }
|
||
}
|
||
})
|