892 lines
24 KiB
TypeScript
892 lines
24 KiB
TypeScript
import request from '../../utils/request';
|
||
|
||
// 定义组件方法接口
|
||
interface IComponentMethods {
|
||
loadChapter: (chapter: number) => Promise<void>;
|
||
splitPages: () => Promise<void>;
|
||
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<IComponentData, IComponentProperties, IComponentMethods>({
|
||
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() {
|
||
console.log('Reader组件接收到的属性:', {
|
||
bookId: this.properties.bookId,
|
||
bookUrl: this.properties.bookUrl,
|
||
title: this.properties.title
|
||
});
|
||
|
||
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 });
|
||
},
|
||
|
||
// 保存和<E5AD98><E5928C>复设置
|
||
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
|
||
});
|
||
}
|
||
}
|
||
});
|