更新开发文档,强调接口路径必须按使用方区分,禁止通用路径混用。新增小程序分享功能,统一使用推荐码,确保用户体验一致性。
This commit is contained in:
169
miniprogram2/pages/chapters/chapters.js
Normal file
169
miniprogram2/pages/chapters/chapters.js
Normal file
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
* Soul创业派对 - 目录页
|
||||
* 开发: 卡若
|
||||
* 技术支持: 存客宝
|
||||
* 数据: 完整真实文章标题
|
||||
*/
|
||||
|
||||
const app = getApp()
|
||||
const PART_NUMBERS = { 'part-1': '一', 'part-2': '二', 'part-3': '三', 'part-4': '四', 'part-5': '五' }
|
||||
|
||||
function buildNestedBookData(list) {
|
||||
const parts = {}
|
||||
const appendices = []
|
||||
let epilogueMid = 0
|
||||
let prefaceMid = 0
|
||||
list.forEach(ch => {
|
||||
if (ch.id === 'preface') {
|
||||
prefaceMid = ch.mid || 0
|
||||
return
|
||||
}
|
||||
const section = {
|
||||
id: ch.id,
|
||||
mid: ch.mid || 0,
|
||||
title: ch.sectionTitle || ch.chapterTitle || ch.id,
|
||||
isFree: !!ch.isFree,
|
||||
price: ch.price != null ? Number(ch.price) : 1
|
||||
}
|
||||
if (ch.id === 'epilogue') {
|
||||
epilogueMid = ch.mid || 0
|
||||
return
|
||||
}
|
||||
if ((ch.id || '').startsWith('appendix')) {
|
||||
appendices.push({ id: ch.id, mid: ch.mid || 0, title: ch.sectionTitle || ch.chapterTitle || ch.id })
|
||||
return
|
||||
}
|
||||
if (!ch.partId || ch.id === 'preface') return
|
||||
const pid = ch.partId
|
||||
const cid = ch.chapterId || 'chapter-' + (ch.id || '').split('.')[0]
|
||||
if (!parts[pid]) {
|
||||
parts[pid] = { id: pid, number: PART_NUMBERS[pid] || pid, title: ch.partTitle || pid, subtitle: ch.chapterTitle || '', chapters: {} }
|
||||
}
|
||||
if (!parts[pid].chapters[cid]) {
|
||||
parts[pid].chapters[cid] = { id: cid, title: ch.chapterTitle || cid, sections: [] }
|
||||
}
|
||||
parts[pid].chapters[cid].sections.push(section)
|
||||
})
|
||||
const bookData = Object.values(parts)
|
||||
.sort((a, b) => (a.id || '').localeCompare(b.id || ''))
|
||||
.map(p => ({
|
||||
...p,
|
||||
chapters: Object.values(p.chapters).sort((a, b) => (a.id || '').localeCompare(b.id || ''))
|
||||
}))
|
||||
return { bookData, appendixList: appendices, epilogueMid, prefaceMid }
|
||||
}
|
||||
|
||||
Page({
|
||||
data: {
|
||||
statusBarHeight: 44,
|
||||
navBarHeight: 88,
|
||||
isLoggedIn: false,
|
||||
hasFullBook: false,
|
||||
purchasedSections: [],
|
||||
totalSections: 62,
|
||||
bookData: [],
|
||||
expandedPart: null,
|
||||
appendixList: [],
|
||||
epilogueMid: 0,
|
||||
prefaceMid: 0
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.setData({
|
||||
statusBarHeight: app.globalData.statusBarHeight,
|
||||
navBarHeight: app.globalData.navBarHeight
|
||||
})
|
||||
this.updateUserStatus()
|
||||
this.loadAndEnrichBookData()
|
||||
},
|
||||
|
||||
async loadAndEnrichBookData() {
|
||||
try {
|
||||
let list = app.globalData.bookData || []
|
||||
if (!list.length) {
|
||||
const res = await app.request('/api/miniprogram/book/all-chapters')
|
||||
if (res?.data) {
|
||||
list = res.data
|
||||
app.globalData.bookData = list
|
||||
}
|
||||
}
|
||||
if (!list.length) {
|
||||
this.setData({ bookData: [], appendixList: [] })
|
||||
return
|
||||
}
|
||||
const { bookData, appendixList, epilogueMid, prefaceMid } = buildNestedBookData(list)
|
||||
const firstPartId = bookData[0]?.id || null
|
||||
this.setData({
|
||||
bookData,
|
||||
appendixList,
|
||||
epilogueMid,
|
||||
prefaceMid,
|
||||
totalSections: list.length,
|
||||
expandedPart: firstPartId || this.data.expandedPart
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('[Chapters] 加载目录失败:', e)
|
||||
this.setData({ bookData: [], appendixList: [] })
|
||||
}
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.updateUserStatus()
|
||||
if (!app.globalData.bookData?.length) {
|
||||
this.loadAndEnrichBookData()
|
||||
}
|
||||
if (typeof this.getTabBar === 'function' && this.getTabBar()) {
|
||||
const tabBar = this.getTabBar()
|
||||
if (tabBar.updateSelected) {
|
||||
tabBar.updateSelected()
|
||||
} else {
|
||||
tabBar.setData({ selected: 1 })
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 更新用户状态
|
||||
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
|
||||
})
|
||||
},
|
||||
|
||||
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'
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user