feat: 支持章节通过 mid 进行访问,优化阅读跳转逻辑。新增章节数据结构,包含章节的 mid 信息,提升用户体验。更新 API 以支持通过 mid 查询章节内容,确保兼容性与灵活性。
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
console.log('[Index] ===== 首页文件开始加载 =====')
|
||||
|
||||
const app = getApp()
|
||||
const PART_NUMBERS = { 'part-1': '一', 'part-2': '二', 'part-3': '三', 'part-4': '四', 'part-5': '五' }
|
||||
|
||||
Page({
|
||||
data: {
|
||||
@@ -19,31 +20,13 @@ Page({
|
||||
hasFullBook: false,
|
||||
readCount: 0,
|
||||
|
||||
// 书籍数据
|
||||
totalSections: 62,
|
||||
bookData: [],
|
||||
|
||||
// 推荐章节
|
||||
featuredSections: [
|
||||
{ id: '1.1', title: '荷包:电动车出租的被动收入模式', tag: '免费', tagClass: 'tag-free', part: '真实的人' },
|
||||
{ id: '3.1', title: '3000万流水如何跑出来', tag: '热门', tagClass: 'tag-pink', part: '真实的行业' },
|
||||
{ id: '8.1', title: '流量杠杆:抖音、Soul、飞书', tag: '推荐', tagClass: 'tag-purple', part: '真实的赚钱' }
|
||||
],
|
||||
|
||||
// 最新章节(动态计算)
|
||||
featuredSections: [],
|
||||
latestSection: null,
|
||||
latestLabel: '最新更新',
|
||||
|
||||
// 内容概览
|
||||
partsList: [
|
||||
{ id: 'part-1', number: '一', title: '真实的人', subtitle: '人与人之间的底层逻辑' },
|
||||
{ id: 'part-2', number: '二', title: '真实的行业', subtitle: '电商、内容、传统行业解析' },
|
||||
{ id: 'part-3', number: '三', title: '真实的错误', subtitle: '我和别人犯过的错' },
|
||||
{ id: 'part-4', number: '四', title: '真实的赚钱', subtitle: '底层结构与真实案例' },
|
||||
{ id: 'part-5', number: '五', title: '真实的社会', subtitle: '未来职业与商业生态' }
|
||||
],
|
||||
|
||||
// 加载状态
|
||||
partsList: [],
|
||||
prefaceMid: 0,
|
||||
loading: true
|
||||
},
|
||||
|
||||
@@ -98,10 +81,7 @@ Page({
|
||||
this.setData({ loading: true })
|
||||
|
||||
try {
|
||||
// 获取书籍数据
|
||||
await this.loadBookData()
|
||||
// 计算推荐章节
|
||||
this.computeLatestSection()
|
||||
} catch (e) {
|
||||
console.error('初始化失败:', e)
|
||||
} finally {
|
||||
@@ -109,62 +89,82 @@ Page({
|
||||
}
|
||||
},
|
||||
|
||||
// 计算推荐章节(根据用户ID随机、优先未付款)
|
||||
computeLatestSection() {
|
||||
const { hasFullBook, purchasedSections } = app.globalData
|
||||
const userId = app.globalData.userInfo?.id || wx.getStorageSync('userId') || 'guest'
|
||||
|
||||
// 所有章节列表
|
||||
const allSections = [
|
||||
{ id: '9.14', title: '大健康私域:一个月150万的70后', part: '真实的赚钱' },
|
||||
{ id: '9.13', title: 'AI工具推广:一个隐藏的高利润赛道', part: '真实的赚钱' },
|
||||
{ id: '9.12', title: '美业整合:一个人的公司如何月入十万', part: '真实的赚钱' },
|
||||
{ id: '8.6', title: '云阿米巴:分不属于自己的钱', part: '真实的赚钱' },
|
||||
{ id: '8.1', title: '流量杠杆:抖音、Soul、飞书', part: '真实的赚钱' },
|
||||
{ id: '3.1', title: '3000万流水如何跑出来', part: '真实的行业' },
|
||||
{ id: '5.1', title: '拍卖行抱朴:一天240万的摇号生意', part: '真实的行业' },
|
||||
{ id: '4.1', title: '旅游号:30天10万粉的真实逻辑', part: '真实的行业' }
|
||||
]
|
||||
|
||||
// 用户ID生成的随机种子(同一用户每天看到的不同)
|
||||
const today = new Date().toISOString().split('T')[0]
|
||||
const seed = (userId + today).split('').reduce((a, b) => a + b.charCodeAt(0), 0)
|
||||
|
||||
// 筛选未付款章节
|
||||
let candidates = allSections
|
||||
if (!hasFullBook) {
|
||||
const purchased = purchasedSections || []
|
||||
const unpurchased = allSections.filter(s => !purchased.includes(s.id))
|
||||
if (unpurchased.length > 0) {
|
||||
candidates = unpurchased
|
||||
}
|
||||
}
|
||||
|
||||
// 根据种子选择章节
|
||||
const index = seed % candidates.length
|
||||
const selected = candidates[index]
|
||||
|
||||
// 设置标签(如果有新增章节显示"最新更新",否则显示"推荐阅读")
|
||||
const label = candidates === allSections ? '推荐阅读' : '为你推荐'
|
||||
|
||||
this.setData({
|
||||
latestSection: selected,
|
||||
latestLabel: label
|
||||
})
|
||||
},
|
||||
|
||||
// 加载书籍数据
|
||||
async loadBookData() {
|
||||
try {
|
||||
const res = await app.request('/api/miniprogram/book/all-chapters')
|
||||
if (res && res.data) {
|
||||
this.setData({
|
||||
bookData: res.data,
|
||||
totalSections: res.totalSections || 62
|
||||
const [chaptersRes, hotRes] = await Promise.all([
|
||||
app.request('/api/miniprogram/book/all-chapters'),
|
||||
app.request('/api/miniprogram/book/hot')
|
||||
])
|
||||
const list = chaptersRes?.data || []
|
||||
const hotList = hotRes?.data || []
|
||||
app.globalData.bookData = list
|
||||
|
||||
const toSection = (ch) => ({
|
||||
id: ch.id,
|
||||
mid: ch.mid || 0,
|
||||
title: ch.sectionTitle || ch.chapterTitle || ch.id,
|
||||
part: ch.partTitle || ''
|
||||
})
|
||||
|
||||
let featuredSections = []
|
||||
if (hotList.length >= 3) {
|
||||
const freeCh = list.find(c => c.isFree || c.id === '1.1' || c.id === 'preface')
|
||||
const picks = []
|
||||
if (freeCh) picks.push({ ...toSection(freeCh), tag: '免费', tagClass: 'tag-free' })
|
||||
hotList.slice(0, 3 - picks.length).forEach((ch, i) => {
|
||||
if (!picks.find(p => p.id === ch.id)) {
|
||||
picks.push({ ...toSection(ch), tag: i === 0 ? '热门' : '推荐', tagClass: i === 0 ? 'tag-pink' : 'tag-purple' })
|
||||
}
|
||||
})
|
||||
featuredSections = picks.slice(0, 3)
|
||||
}
|
||||
if (featuredSections.length < 3 && list.length > 0) {
|
||||
const fallback = list.filter(c => c.id && !['preface', 'epilogue'].includes(c.id)).slice(0, 3)
|
||||
featuredSections = fallback.map((ch, i) => ({
|
||||
...toSection(ch),
|
||||
tag: ch.isFree ? '免费' : (i === 0 ? '热门' : '推荐'),
|
||||
tagClass: ch.isFree ? 'tag-free' : (i === 0 ? 'tag-pink' : 'tag-purple')
|
||||
}))
|
||||
}
|
||||
|
||||
const partMap = {}
|
||||
list.forEach(ch => {
|
||||
if (!ch.partId || ch.id === 'preface' || ch.id === 'epilogue' || (ch.id || '').startsWith('appendix')) return
|
||||
if (!partMap[ch.partId]) {
|
||||
partMap[ch.partId] = { id: ch.partId, number: PART_NUMBERS[ch.partId] || ch.partId, title: ch.partTitle || ch.partId, subtitle: ch.chapterTitle || '' }
|
||||
}
|
||||
})
|
||||
const partsList = Object.values(partMap).sort((a, b) => (a.id || '').localeCompare(b.id || ''))
|
||||
|
||||
const paidCandidates = list.filter(c => c.id && !['preface', 'epilogue'].includes(c.id) && !(c.id || '').startsWith('appendix') && c.partId)
|
||||
const { hasFullBook, purchasedSections } = app.globalData
|
||||
let candidates = paidCandidates
|
||||
if (!hasFullBook && purchasedSections?.length) {
|
||||
const unpurchased = paidCandidates.filter(c => !purchasedSections.includes(c.id))
|
||||
if (unpurchased.length > 0) candidates = unpurchased
|
||||
}
|
||||
const userId = app.globalData.userInfo?.id || wx.getStorageSync('userId') || 'guest'
|
||||
const today = new Date().toISOString().split('T')[0]
|
||||
const seed = (userId + today).split('').reduce((a, b) => a + b.charCodeAt(0), 0)
|
||||
const selectedCh = candidates[seed % Math.max(candidates.length, 1)]
|
||||
const latestSection = selectedCh ? { ...toSection(selectedCh), mid: selectedCh.mid || 0 } : null
|
||||
const latestLabel = candidates.length === paidCandidates.length ? '推荐阅读' : '为你推荐'
|
||||
|
||||
const prefaceCh = list.find(c => c.id === 'preface')
|
||||
const prefaceMid = prefaceCh?.mid || 0
|
||||
|
||||
this.setData({
|
||||
bookData: list,
|
||||
totalSections: list.length || 62,
|
||||
featuredSections,
|
||||
partsList,
|
||||
latestSection,
|
||||
latestLabel,
|
||||
prefaceMid
|
||||
})
|
||||
} catch (e) {
|
||||
console.error('加载书籍数据失败:', e)
|
||||
this.setData({ featuredSections: [], partsList: [], latestSection: null })
|
||||
}
|
||||
},
|
||||
|
||||
@@ -189,10 +189,11 @@ Page({
|
||||
wx.navigateTo({ url: '/pages/search/search' })
|
||||
},
|
||||
|
||||
// 跳转到阅读页
|
||||
goToRead(e) {
|
||||
const id = e.currentTarget.dataset.id
|
||||
wx.navigateTo({ url: `/pages/read/read?id=${id}` })
|
||||
const mid = e.currentTarget.dataset.mid || app.getSectionMid(id)
|
||||
const q = mid ? `mid=${mid}` : `id=${id}`
|
||||
wx.navigateTo({ url: `/pages/read/read?${q}` })
|
||||
},
|
||||
|
||||
// 跳转到匹配页
|
||||
|
||||
Reference in New Issue
Block a user