import request from '../../utils/request'; // 定义组件方法接口 interface IComponentMethods { loadChapter: (chapter: number) => Promise; splitPages: () => Promise; prevPage: () => void; nextPage: () => void; touchStart: (e: WechatMiniprogram.TouchEvent) => void; touchEnd: (e: WechatMiniprogram.TouchEvent) => void; toggleToolbar: () => void; toggleMenu: () => void; prevChapter: () => void; nextChapter: () => void; jumpToChapter: (e: WechatMiniprogram.TouchEvent) => void; goBack: () => void; onScroll: (e: WechatMiniprogram.TouchEvent) => void; toggleSettings: () => void; decreaseFontSize: () => void; increaseFontSize: () => void; startTimeUpdate: () => void; calculateProgress: () => void; closeAllPanels: () => void; switchTheme: (e: WechatMiniprogram.TouchEvent) => void; adjustBrightness: (e: WechatMiniprogram.SliderChange) => void; toggleAutoReading: (e: WechatMiniprogram.SwitchChange) => void; setAutoReadingInterval: (e: WechatMiniprogram.PickerChange) => void; startAutoReading: () => void; stopAutoReading: () => void; toggleBookmarks: () => void; addBookmark: () => void; loadBookmarks: () => void; jumpToBookmark: (e: WechatMiniprogram.TouchEvent) => void; toggleNotes: () => void; showTextMenu: (e: WechatMiniprogram.TouchEvent) => void; addNote: () => void; loadNotes: () => void; copyText: () => void; startReadingTimer: () => void; updateReadingTime: () => void; loadTodayReadingTime: () => void; saveReadingProgress: () => void; restoreSettings: () => void; toggleMore: () => void; onSelectText: (e: any) => void; addBookmarkWithSelection: () => void; addNoteWithSelection: () => void; copySelectedText: () => void; hideTextMenu: () => void; startReadingTimer: () => void; stopReadingTimer: () => void; saveReadingRecord: (duration: number) => void; } // 定义组件数据接口 interface IComponentData { bookTitle: string; content: string; currentChapter: number; totalChapters: number; showToolbar: boolean; showMenu: boolean; scrollTop: number; chapters: number[]; lastTapTime: number; pages: string[]; currentPage: number; pageHeight: number; lineHeight: number; fontSize: number; showSettings: boolean; minFontSize: number; maxFontSize: number; currentTime: string; readingProgress: number; themes: Array<{id: string; name: string; bg: string; color: string}>; currentTheme: string; brightness: number; autoReading: boolean; autoReadingInterval: number; showBookmarks: boolean; showNotes: boolean; showTextMenu: boolean; textMenuTop: number; textMenuLeft: number; selectedText: string; bookmarks: any[]; notes: any[]; readingStartTime: number; todayReadingTime: number; showMore: boolean; selectionStart: number; selectionEnd: number; readingDuration: number; isReading: boolean; readingTimer: any; } // 定义组件属性接口 interface IComponentProperties { bookId: string; bookUrl: string; title: string; } Component({ data: { bookTitle: '', content: '', currentChapter: 1, totalChapters: 2541, showToolbar: true, showMenu: false, scrollTop: 0, chapters: [] as number[], lastTapTime: 0, pages: [] as string[], currentPage: 0, pageHeight: 0, lineHeight: 36, fontSize: 32, showSettings: false, minFontSize: 24, maxFontSize: 48, currentTime: '', readingProgress: 0, themes: [ { id: 'default', name: '默认', bg: '#f4ecd8', color: '#333' }, { id: 'night', name: '夜间', bg: '#222', color: '#999' }, { id: 'green', name: '护眼', bg: '#cce8cf', color: '#333' }, { id: 'paper', name: '纸张', bg: '#e8e2d3', color: '#333' } ], currentTheme: 'default', brightness: 100, autoReading: false, autoReadingInterval: 5000, showBookmarks: false, showNotes: false, showTextMenu: false, textMenuTop: 0, textMenuLeft: 0, selectedText: '', bookmarks: [] as any[], notes: [] as any[], readingStartTime: 0, todayReadingTime: 0, showMore: false, selectionStart: -1, selectionEnd: -1, readingDuration: 0, isReading: false, readingTimer: null as any, }, properties: { bookId: String, bookUrl: String, title: String }, lifetimes: { attached() { this.setData({ bookTitle: this.properties.title || '大爱仙尊', chapters: Array.from({length: 2541}, (_, i) => i + 1) }); this.loadChapter(1).then(() => { this.calculateProgress(); }); const savedFontSize = wx.getStorageSync('reader_font_size'); if (savedFontSize) { this.setData({ fontSize: savedFontSize }); } this.startTimeUpdate(); this.startReadingTimer(); this.loadBookmarks(); this.loadNotes(); this.restoreSettings(); // 获取当前屏幕亮度 wx.getScreenBrightness({ success: (res) => { this.setData({ brightness: Math.round(res.value * 100) }); } }); }, detached() { if (this.data.readingTimer) { clearInterval(this.data.readingTimer); } this.updateReadingTime(); this.saveReadingProgress(); if (this.autoReadingTimer) { clearInterval(this.autoReadingTimer); } this.stopReadingTimer(); } }, pageLifetimes: { hide() { this.stopReadingTimer(); }, show() { if (!this.data.readingDuration) { this.startReadingTimer(); } } }, methods: { // 加载章节内容 async loadChapter(chapter: number) { try { wx.showLoading({ title: '加载中...' }); const res = await request.get('/common/getBookContent', { bookName: this.data.bookTitle, id: chapter }); if (res.code === 200) { // 处理换行符 const content = res.data.replace(/\\r\\n/g, '\n'); this.setData({ content, currentChapter: chapter // 更新当前章节号 }); // 分页处理 await this.splitPages(); this.calculateProgress(); } } catch (error) { console.error('加载章节失败:', error); wx.showToast({ title: '加载失败', icon: 'none' }); } finally { wx.hideLoading(); } }, // 分页处理 async splitPages() { // 获取容器尺寸 const query = this.createSelectorQuery(); query.select('.content').boundingClientRect(); const rect = await new Promise(resolve => query.exec(resolve)); const containerHeight = rect[0].height; // 计算每页能显示的行数 const lineHeight = this.data.lineHeight; const linesPerPage = Math.floor((containerHeight - 160) / (lineHeight * 2 / 750 * wx.getSystemInfoSync().windowWidth)); // 按自然段落分割内容 const paragraphs = this.data.content.split('\n').filter(p => p.trim()); // 分页 const pages = []; let currentPage = []; let currentLines = 0; for (const paragraph of paragraphs) { // 计算段落需要的行数 const paragraphLines = Math.ceil(paragraph.length * (this.data.fontSize / 32) / 20); if (currentLines + paragraphLines > linesPerPage) { // 当前页放不下这段,新建一页 if (currentPage.length > 0) { pages.push(currentPage.join('\n')); currentPage = []; currentLines = 0; } // 如果单个段落超过一页 if (paragraphLines > linesPerPage) { const chars = Math.floor(20 * linesPerPage); let p = paragraph; while (p.length > 0) { const pageContent = p.slice(0, chars); pages.push(pageContent); p = p.slice(chars); } } else { currentPage.push(paragraph); currentLines = paragraphLines; } } else { // 当前页能放下这段 currentPage.push(paragraph); currentLines += paragraphLines; } } // 保存最后一页 if (currentPage.length > 0) { pages.push(currentPage.join('\n')); } this.setData({ pages, currentPage: 0, pageHeight: containerHeight }, () => { this.calculateProgress(); }); }, // 上一页 prevPage() { if (this.data.currentPage > 0) { this.setData({ currentPage: this.data.currentPage - 1 }, () => { this.calculateProgress(); }); } else if (this.data.currentChapter > 1) { // 上一章最后一页 const prevChapter = this.data.currentChapter - 1; this.loadChapter(prevChapter).then(() => { this.setData({ currentPage: this.data.pages.length - 1 }, () => { this.calculateProgress(); }); }); } }, // 下一页 nextPage() { if (this.data.currentPage < this.data.pages.length - 1) { this.setData({ currentPage: this.data.currentPage + 1 }, () => { this.calculateProgress(); }); } else if (this.data.currentChapter < this.data.totalChapters) { // 下一章第一页 const nextChapter = this.data.currentChapter + 1; this.loadChapter(nextChapter).then(() => { this.calculateProgress(); }); } }, // 触摸开始 touchStart(e: any) { this.touchStartX = e.touches[0].pageX; }, // 触摸结束 touchEnd(e: any) { const touchEndX = e.changedTouches[0].pageX; const diff = touchEndX - this.touchStartX; if (Math.abs(diff) > 50) { // 滑动距离大于50px才触发翻页 if (diff > 0) { this.prevPage(); } else { this.nextPage(); } } }, // 切换工具栏显示 toggleToolbar() { const now = Date.now(); if (now - this.data.lastTapTime < 300) { // 双击 this.setData({ showToolbar: !this.data.showToolbar }); } this.setData({ lastTapTime: now }); }, // 切换目录显示 toggleMenu() { this.setData({ showMenu: !this.data.showMenu }); }, // 上一章 prevChapter() { if (this.data.currentChapter > 1) { this.loadChapter(this.data.currentChapter - 1); } }, // 下一章 nextChapter() { if (this.data.currentChapter < this.data.totalChapters) { this.loadChapter(this.data.currentChapter + 1); } }, // 跳转到指定章节 jumpToChapter(e: any) { const chapter = e.currentTarget.dataset.chapter; this.loadChapter(Number(chapter)); // 确保 chapter 是数字 this.toggleMenu(); }, // 返回 goBack() { this.stopReadingTimer(); // 停止计时 // 打印阅读时间 const minutes = Math.floor(this.data.readingDuration / 60); const seconds = this.data.readingDuration % 60; console.log(`本次阅读时长: ${minutes}分${seconds}秒`); console.log('详细信息:', { 开始时间: new Date(this.data.readingStartTime).toLocaleString(), 结束时间: new Date().toLocaleString(), 总秒数: this.data.readingDuration, 格式化时长: `${minutes}分${seconds}秒` }); wx.navigateBack(); }, // 滚动处理 onScroll(e: any) { // 可以在这里处理阅读进度保存等逻辑 }, // 切换设置面板 toggleSettings() { console.log('切换设置面板', this.data.showSettings); this.setData({ showSettings: !this.data.showSettings, showMenu: false // 确保目录菜单关闭 }); }, // 减小字体 decreaseFontSize() { if (this.data.fontSize > this.data.minFontSize) { const newSize = this.data.fontSize - 2; this.setData({ fontSize: newSize }, () => { // 重新计算分页 this.splitPages(); // 保存设置到本地 wx.setStorageSync('reader_font_size', newSize); }); } }, // 增大字体 increaseFontSize() { if (this.data.fontSize < this.data.maxFontSize) { const newSize = this.data.fontSize + 2; this.setData({ fontSize: newSize }, () => { // 重新计算分页 this.splitPages(); // 保存设置到本地 wx.setStorageSync('reader_font_size', newSize); }); } }, // 更新时间 startTimeUpdate() { const updateTime = () => { const now = new Date(); const hours = now.getHours().toString().padStart(2, '0'); const minutes = now.getMinutes().toString().padStart(2, '0'); this.setData({ currentTime: `${hours}:${minutes}` }); }; // 立即更新一次 updateTime(); // 每分钟更新一次 this.timeInterval = setInterval(updateTime, 60000); }, // 计算阅读进度 calculateProgress() { // 当前章节进度 const currentChapterProgress = this.data.pages.length > 0 ? (this.data.currentPage + 1) / this.data.pages.length : 0; // 总进度计算:(当前章节 - 1 + 当前章节阅读进度) / 总章节数 const totalProgress = Math.floor( ((this.data.currentChapter - 1 + currentChapterProgress) / this.data.totalChapters) * 100 ); console.log('Progress calculation:', { currentChapter: this.data.currentChapter, totalChapters: this.data.totalChapters, currentPage: this.data.currentPage, totalPages: this.data.pages.length, chapterProgress: currentChapterProgress, totalProgress }); this.setData({ readingProgress: totalProgress }); }, // 关闭所有面板 closeAllPanels() { this.setData({ showSettings: false, showMenu: false }); }, // 切换主题 switchTheme(e: any) { const themeId = e.currentTarget.dataset.theme; this.setData({ currentTheme: themeId, showMore: false // 选择后关闭面板 }); wx.setStorageSync('reader_theme', themeId); }, // 调整屏幕亮度 adjustBrightness(e: WechatMiniprogram.SliderChange) { const value = e.detail.value; console.log('调整亮度:', value); // 添加调试日志 wx.setScreenBrightness({ value: value / 100, success: () => { this.setData({ brightness: value }); wx.setStorageSync('reader_brightness', value); console.log('亮度设置成功:', value); }, fail: (error) => { console.error('设置亮度失败:', error); wx.showToast({ title: '设置亮度失败', icon: 'none' }); } }); }, // 自动阅读相关 toggleAutoReading(e: any) { const isChecked = e.detail.value; this.setData({ autoReading: isChecked }); if (isChecked) { this.startAutoReading(); } else { this.stopAutoReading(); } }, setAutoReadingInterval(e: any) { const interval = [3000, 5000, 8000, 10000][e.detail.value]; this.setData({ autoReadingInterval: interval }); if (this.data.autoReading) { this.stopAutoReading(); this.startAutoReading(); } }, startAutoReading() { this.autoReadingTimer = setInterval(() => { this.nextPage(); }, this.data.autoReadingInterval); }, stopAutoReading() { if (this.autoReadingTimer) { clearInterval(this.autoReadingTimer); } }, // 书签相关 toggleBookmarks() { this.setData({ showBookmarks: !this.data.showBookmarks, showSettings: false, showNotes: false }); }, addBookmark() { const bookmark = { chapter: this.data.currentChapter, page: this.data.currentPage, content: this.data.pages[this.data.currentPage].slice(0, 50), time: new Date().toLocaleString() }; const bookmarks = [...this.data.bookmarks, bookmark]; this.setData({ bookmarks }); wx.setStorageSync(`bookmarks_${this.data.bookTitle}`, bookmarks); wx.showToast({ title: '添加书签成功', icon: 'success' }); }, loadBookmarks() { const bookmarks = wx.getStorageSync(`bookmarks_${this.data.bookTitle}`) || []; this.setData({ bookmarks }); }, jumpToBookmark(e: any) { const bookmark = e.currentTarget.dataset.bookmark; this.loadChapter(bookmark.chapter).then(() => { this.setData({ currentPage: bookmark.page, showBookmarks: false }); }); }, // 笔记相关 toggleNotes() { this.setData({ showNotes: !this.data.showNotes, showSettings: false, showBookmarks: false }); }, showTextMenu(e: any) { const text = this.data.pages[this.data.currentPage]; const start = 0; const end = text.length; this.setData({ selectionStart: start, selectionEnd: end, selectedText: text.substring(start, end), showTextMenu: true, textMenuTop: e.touches[0].clientY, textMenuLeft: e.touches[0].clientX }); }, addNote() { wx.showModal({ title: '添加笔记', editable: true, placeholderText: '请输入笔记内容', success: (res) => { if (res.confirm && res.content) { const note = { chapter: this.data.currentChapter, page: this.data.currentPage, content: res.content, selectedText: this.data.selectedText, time: new Date().toLocaleString() }; const notes = [...this.data.notes, note]; this.setData({ notes, showTextMenu: false }); wx.setStorageSync(`notes_${this.data.bookTitle}`, notes); wx.showToast({ title: '添加笔记成功', icon: 'success' }); } } }); }, loadNotes() { const notes = wx.getStorageSync(`notes_${this.data.bookTitle}`) || []; this.setData({ notes }); }, copyText() { wx.setClipboardData({ data: this.data.selectedText, success: () => { this.setData({ showTextMenu: false }); wx.showToast({ title: '复制成功', icon: 'success' }); } }); }, // 阅读统计相关 startReadingTimer() { this.setData({ readingStartTime: Date.now(), isReading: true, readingDuration: 0 }); // 每秒更新阅读时长 this.data.readingTimer = setInterval(() => { const duration = Math.floor((Date.now() - this.data.readingStartTime) / 1000); this.setData({ readingDuration: duration }); }, 1000); }, updateReadingTime() { const duration = Math.floor((Date.now() - this.data.readingStartTime) / 1000); const today = new Date().toDateString(); const newTodayTime = this.data.todayReadingTime + duration; this.setData({ todayReadingTime: newTodayTime }); let statistics = wx.getStorageSync('reading_statistics') || {}; statistics[today] = newTodayTime; wx.setStorageSync('reading_statistics', statistics); }, loadTodayReadingTime() { const today = new Date().toDateString(); const statistics = wx.getStorageSync('reading_statistics') || {}; this.setData({ todayReadingTime: statistics[today] || 0 }); }, // 保存和恢复设置 saveReadingProgress() { const progress = { chapter: this.data.currentChapter, page: this.data.currentPage, timestamp: Date.now() }; wx.setStorageSync(`reading_progress_${this.data.bookTitle}`, progress); }, restoreSettings() { // 恢复主题 const theme = wx.getStorageSync('reader_theme'); if (theme) { this.setData({ currentTheme: theme }); } // 恢复亮度 const brightness = wx.getStorageSync('reader_brightness'); if (brightness !== undefined) { this.setData({ brightness }); wx.setScreenBrightness({ value: brightness / 100 }); } // 恢复阅读进度 const progress = wx.getStorageSync(`reading_progress_${this.data.bookTitle}`); if (progress) { this.loadChapter(progress.chapter).then(() => { this.setData({ currentPage: progress.page }); }); } }, toggleMore() { this.setData({ showMore: !this.data.showMore, showSettings: false, showMenu: false }); }, // 处理文本选择事件 onSelectText(e: any) { console.log('Selected text:', e.detail); const selectedText = e.detail.text; if (selectedText && selectedText.trim()) { this.setData({ selectedText }); } }, // 隐藏文本菜单 hideTextMenu() { this.setData({ showTextMenu: false, selectionStart: -1, selectionEnd: -1 }); }, // 添加书签 addBookmarkWithSelection() { const bookmark = { chapter: this.data.currentChapter, page: this.data.currentPage, content: this.data.selectedText, time: new Date().toLocaleString() }; const bookmarks = [...this.data.bookmarks, bookmark]; this.setData({ bookmarks, showTextMenu: false }); wx.setStorageSync(`bookmarks_${this.data.bookTitle}`, bookmarks); wx.showToast({ title: '添加书签成功', icon: 'success' }); }, // 添加笔记 addNoteWithSelection() { wx.showModal({ title: '添加笔记', editable: true, placeholderText: '请输入笔记内容', success: (res) => { if (res.confirm && res.content) { const note = { chapter: this.data.currentChapter, page: this.data.currentPage, selectedText: this.data.selectedText, content: res.content, time: new Date().toLocaleString() }; const notes = [...this.data.notes, note]; this.setData({ notes, showTextMenu: false }); wx.setStorageSync(`notes_${this.data.bookTitle}`, notes); wx.showToast({ title: '添加笔记成功', icon: 'success' }); } } }); }, // 复制选中文本 copySelectedText() { if (this.data.selectedText) { wx.setClipboardData({ data: this.data.selectedText, success: () => { this.setData({ showTextMenu: false }); wx.showToast({ title: '复制成功', icon: 'success' }); } }); } }, // 结束计时并保存 stopReadingTimer() { if (!this.data.isReading) return; if (this.data.readingTimer) { clearInterval(this.data.readingTimer); } const endTime = Date.now(); const duration = Math.floor((endTime - this.data.readingStartTime) / 1000); this.setData({ readingDuration: duration, isReading: false }); // 保存阅读记录 this.saveReadingRecord(duration); }, // 保存阅读记录 saveReadingRecord(duration: number) { const readingRecord = { bookId: this.data.bookId, startTime: this.data.readingStartTime, duration: duration, endTime: Date.now() }; // 可以选择保存到本地或发送到服务器 wx.setStorageSync('lastReadingRecord', readingRecord); wx.showToast({ title: `本次阅读 ${Math.floor(duration / 60)} 分钟`, icon: 'none', duration: 2000 }); } } });