344 lines
7.2 KiB
JavaScript
344 lines
7.2 KiB
JavaScript
// pages/read/read.js
|
||
const app = getApp()
|
||
const paymentUtil = require('../../utils/payment')
|
||
|
||
Page({
|
||
data: {
|
||
chapterId: '',
|
||
chapterInfo: {},
|
||
contentHtml: '',
|
||
loading: true,
|
||
hasPrev: false,
|
||
hasNext: false,
|
||
isBookmarked: false,
|
||
showCatalog: false,
|
||
allChapters: []
|
||
},
|
||
|
||
onLoad(options) {
|
||
const chapterId = options.id
|
||
if (chapterId) {
|
||
this.setData({ chapterId })
|
||
this.loadChapter(chapterId)
|
||
this.loadAllChapters()
|
||
this.checkBookmark(chapterId)
|
||
}
|
||
},
|
||
|
||
// 加载章节内容
|
||
loadChapter(chapterId) {
|
||
this.setData({ loading: true })
|
||
|
||
wx.showLoading({ title: '加载中...', mask: true })
|
||
|
||
wx.request({
|
||
url: `${app.globalData.apiBase}/book/chapter/${chapterId}`,
|
||
header: {
|
||
'Authorization': `Bearer ${wx.getStorageSync('token')}`
|
||
},
|
||
success: (res) => {
|
||
if (res.statusCode === 200) {
|
||
const chapter = res.data
|
||
|
||
// 检查是否需要购买
|
||
if (chapter.needPurchase && !this.checkPurchased()) {
|
||
this.showPurchaseModal()
|
||
return
|
||
}
|
||
|
||
this.setData({
|
||
chapterInfo: {
|
||
title: chapter.title,
|
||
updateTime: chapter.updateTime,
|
||
words: chapter.words,
|
||
readTime: Math.ceil(chapter.words / 300)
|
||
},
|
||
contentHtml: this.markdownToHtml(chapter.content),
|
||
hasPrev: !!chapter.prevChapterId,
|
||
hasNext: !!chapter.nextChapterId,
|
||
loading: false
|
||
})
|
||
|
||
// 记录阅读进度
|
||
this.recordReadProgress(chapterId)
|
||
} else {
|
||
wx.showToast({
|
||
title: '章节加载失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
},
|
||
fail: () => {
|
||
// 使用Mock数据
|
||
this.loadMockChapter(chapterId)
|
||
},
|
||
complete: () => {
|
||
wx.hideLoading()
|
||
}
|
||
})
|
||
},
|
||
|
||
// 加载Mock章节
|
||
loadMockChapter(chapterId) {
|
||
const mockContent = `
|
||
# 这是章节标题
|
||
|
||
这是第一段内容,介绍了关于私域运营的基本概念...
|
||
|
||
## 第一小节
|
||
|
||
详细内容描述...
|
||
|
||
### 要点总结
|
||
|
||
1. 第一点
|
||
2. 第二点
|
||
3. 第三点
|
||
|
||
**重点强调的内容**
|
||
|
||
> 引用的内容或者金句
|
||
`
|
||
|
||
this.setData({
|
||
chapterInfo: {
|
||
title: '第一章|我是谁',
|
||
updateTime: '2天前',
|
||
words: 3200,
|
||
readTime: 11
|
||
},
|
||
contentHtml: this.markdownToHtml(mockContent),
|
||
hasPrev: false,
|
||
hasNext: true,
|
||
loading: false
|
||
})
|
||
},
|
||
|
||
// Markdown转HTML(简单实现)
|
||
markdownToHtml(markdown) {
|
||
if (!markdown) return ''
|
||
|
||
let html = markdown
|
||
.replace(/### (.*)/g, '<h3>$1</h3>')
|
||
.replace(/## (.*)/g, '<h2>$1</h2>')
|
||
.replace(/# (.*)/g, '<h1>$1</h1>')
|
||
.replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
|
||
.replace(/\*(.*?)\*/g, '<em>$1</em>')
|
||
.replace(/> (.*)/g, '<blockquote>$1</blockquote>')
|
||
.replace(/\n/g, '<br/>')
|
||
|
||
return html
|
||
},
|
||
|
||
// 检查是否已购买
|
||
checkPurchased() {
|
||
return paymentUtil.checkPurchaseStatus()
|
||
},
|
||
|
||
// 显示购买弹窗
|
||
showPurchaseModal() {
|
||
wx.showModal({
|
||
title: '需要购买',
|
||
content: '此章节需要购买完整版才能阅读',
|
||
confirmText: '立即购买',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
this.purchase()
|
||
} else {
|
||
wx.navigateBack()
|
||
}
|
||
}
|
||
})
|
||
},
|
||
|
||
// 购买
|
||
purchase() {
|
||
paymentUtil.purchaseFullBook(
|
||
() => {
|
||
wx.showToast({
|
||
title: '购买成功',
|
||
icon: 'success'
|
||
})
|
||
// 重新加载章节
|
||
setTimeout(() => {
|
||
this.loadChapter(this.data.chapterId)
|
||
}, 1500)
|
||
},
|
||
() => {
|
||
wx.showToast({
|
||
title: '购买失败',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
)
|
||
},
|
||
|
||
// 记录阅读进度
|
||
recordReadProgress(chapterId) {
|
||
wx.request({
|
||
url: `${app.globalData.apiBase}/user/read-progress`,
|
||
method: 'POST',
|
||
header: {
|
||
'Authorization': `Bearer ${wx.getStorageSync('token')}`
|
||
},
|
||
data: {
|
||
chapterId,
|
||
timestamp: Date.now()
|
||
}
|
||
})
|
||
},
|
||
|
||
// 加载所有章节
|
||
loadAllChapters() {
|
||
wx.request({
|
||
url: `${app.globalData.apiBase}/book/chapters`,
|
||
success: (res) => {
|
||
if (res.statusCode === 200) {
|
||
this.setData({
|
||
allChapters: res.data.chapters || []
|
||
})
|
||
}
|
||
}
|
||
})
|
||
},
|
||
|
||
// 检查书签
|
||
checkBookmark(chapterId) {
|
||
const bookmarks = wx.getStorageSync('bookmarks') || []
|
||
const isBookmarked = bookmarks.includes(chapterId)
|
||
this.setData({ isBookmarked })
|
||
},
|
||
|
||
// 上一章
|
||
prevChapter() {
|
||
if (!this.data.hasPrev) return
|
||
|
||
// TODO: 获取上一章ID
|
||
wx.showToast({
|
||
title: '功能开发中',
|
||
icon: 'none'
|
||
})
|
||
},
|
||
|
||
// 下一章
|
||
nextChapter() {
|
||
if (!this.data.hasNext) return
|
||
|
||
// TODO: 获取下一章ID
|
||
wx.showToast({
|
||
title: '功能开发中',
|
||
icon: 'none'
|
||
})
|
||
},
|
||
|
||
// 返回
|
||
goBack() {
|
||
wx.navigateBack()
|
||
},
|
||
|
||
// 显示菜单
|
||
showMenu() {
|
||
wx.showActionSheet({
|
||
itemList: ['调整字体', '夜间模式', '分享好友'],
|
||
success: (res) => {
|
||
switch(res.tapIndex) {
|
||
case 0:
|
||
this.adjustFont()
|
||
break
|
||
case 1:
|
||
this.toggleNightMode()
|
||
break
|
||
case 2:
|
||
this.share()
|
||
break
|
||
}
|
||
}
|
||
})
|
||
},
|
||
|
||
// 书签
|
||
bookmark() {
|
||
const chapterId = this.data.chapterId
|
||
let bookmarks = wx.getStorageSync('bookmarks') || []
|
||
|
||
if (this.data.isBookmarked) {
|
||
// 移除书签
|
||
bookmarks = bookmarks.filter(id => id !== chapterId)
|
||
wx.showToast({
|
||
title: '已移除书签',
|
||
icon: 'success'
|
||
})
|
||
} else {
|
||
// 添加书签
|
||
bookmarks.push(chapterId)
|
||
wx.showToast({
|
||
title: '已添加书签',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
|
||
wx.setStorageSync('bookmarks', bookmarks)
|
||
this.setData({
|
||
isBookmarked: !this.data.isBookmarked
|
||
})
|
||
},
|
||
|
||
// 笔记
|
||
note() {
|
||
wx.navigateTo({
|
||
url: `/pages/note/edit?chapterId=${this.data.chapterId}`
|
||
})
|
||
},
|
||
|
||
// 显示目录
|
||
showCatalog() {
|
||
this.setData({ showCatalog: true })
|
||
},
|
||
|
||
// 隐藏目录
|
||
hideCatalog() {
|
||
this.setData({ showCatalog: false })
|
||
},
|
||
|
||
// 选择章节
|
||
selectChapter(e) {
|
||
const chapterId = e.currentTarget.dataset.id
|
||
this.setData({
|
||
chapterId,
|
||
showCatalog: false
|
||
})
|
||
this.loadChapter(chapterId)
|
||
this.checkBookmark(chapterId)
|
||
},
|
||
|
||
// 分享
|
||
share() {
|
||
wx.showShareMenu({
|
||
withShareTicket: true,
|
||
menus: ['shareAppMessage', 'shareTimeline']
|
||
})
|
||
},
|
||
|
||
// 跳转到推广页面
|
||
goToReferral() {
|
||
wx.switchTab({
|
||
url: '/pages/my/my?tab=referral'
|
||
})
|
||
},
|
||
|
||
// 阻止冒泡
|
||
stopPropagation() {},
|
||
|
||
// 分享给好友
|
||
onShareAppMessage() {
|
||
const userInfo = app.getUserInfo()
|
||
const inviteCode = userInfo ? userInfo.inviteCode : ''
|
||
|
||
return {
|
||
title: this.data.chapterInfo.title,
|
||
path: `/pages/read/read?id=${this.data.chapterId}&invite=${inviteCode}`,
|
||
imageUrl: '/assets/images/share-chapter.png'
|
||
}
|
||
}
|
||
})
|