From ff742c0c434908e92be02f421de8fe78de06e00a Mon Sep 17 00:00:00 2001 From: TortoiseGit <3490929155@qq.com> Date: Wed, 12 Nov 2025 16:24:31 +0800 Subject: [PATCH] add --- app.js | 10 +- app.json | 14 +- components/navigation-bar/navigation-bar.js | 9 +- pages/guiding/guiding.js | 181 +++-- pages/home/home.js | 86 --- pages/home/home.json | 4 - pages/home/home.wxml | 33 - pages/home/home.wxss | 50 -- pages/index/index.js | 187 ++++- pages/index/index.json | 6 +- pages/index/index.wxml | 70 +- pages/index/index.wxss | 226 +++++- pages/keyWord/keyWord.js | 323 ++++++++- pages/keyWord/keyWord.wxml | 83 ++- pages/keyWord/keyWord.wxss | 232 ++++++- pages/login/login.js | 124 +++- pages/pendingQuestion/pendingQuestion.js | 125 +++- pages/pendingQuestion/pendingQuestion.wxml | 38 +- pages/pendingQuestion/pendingQuestion.wxss | 103 ++- pages/questionAnswer/questionAnswer.js | 66 -- pages/questionAnswer/questionAnswer.json | 3 - pages/questionAnswer/questionAnswer.wxml | 2 - pages/questionAnswer/questionAnswer.wxss | 1 - pages/recite/recite.js | 645 +++++++++++++++-- pages/recite/recite.wxml | 64 +- pages/recite/recite.wxss | 219 +++++- pages/review/review.js | 723 +++++++++++++++++++- pages/review/review.wxml | 56 +- pages/review/review.wxss | 216 +++++- pages/search/search.js | 273 +++++++- pages/search/search.wxml | 98 ++- pages/search/search.wxss | 303 +++++++- pages/study/study.js | 426 +++++++++++- pages/study/study.wxml | 126 +++- pages/study/study.wxss | 351 +++++++++- pages/textbookFilter/textbookFilter.js | 66 -- pages/textbookFilter/textbookFilter.json | 3 - pages/textbookFilter/textbookFilter.wxml | 2 - pages/textbookFilter/textbookFilter.wxss | 1 - project.config.json | 16 +- project.private.config.json | 82 +-- 41 files changed, 5045 insertions(+), 601 deletions(-) delete mode 100644 pages/home/home.js delete mode 100644 pages/home/home.json delete mode 100644 pages/home/home.wxml delete mode 100644 pages/home/home.wxss delete mode 100644 pages/questionAnswer/questionAnswer.js delete mode 100644 pages/questionAnswer/questionAnswer.json delete mode 100644 pages/questionAnswer/questionAnswer.wxml delete mode 100644 pages/questionAnswer/questionAnswer.wxss delete mode 100644 pages/textbookFilter/textbookFilter.js delete mode 100644 pages/textbookFilter/textbookFilter.json delete mode 100644 pages/textbookFilter/textbookFilter.wxml delete mode 100644 pages/textbookFilter/textbookFilter.wxss diff --git a/app.js b/app.js index 4af33be..04da539 100644 --- a/app.js +++ b/app.js @@ -1,2 +1,10 @@ // app.js -App({}) +App({ + onLaunch() { + wx.cloud.init({ + env: 'cloud1-0g2sr1117862afae' + }); + + console.log('小程序启动,云环境初始化完成'); + } +}) diff --git a/app.json b/app.json index 4c253a7..cc97cac 100644 --- a/app.json +++ b/app.json @@ -2,16 +2,16 @@ "pages": [ "pages/guiding/guiding", - "pages/home/home", - "pages/recite/recite", - "pages/review/review", + "pages/login/login", "pages/index/index", + "pages/study/study", "pages/search/search", - "pages/login/login", - "pages/keyWord/keyWord", - "pages/questionAnswer/questionAnswer", + "pages/recite/recite", + "pages/review/review", "pages/pendingQuestion/pendingQuestion", - "pages/textbookFilter/textbookFilter" + "pages/keyWord/keyWord", + "pages/question/question", + "pages/managePoems/managePoems" ], "window": { "navigationBarTitleText": "古诗学习助手", diff --git a/components/navigation-bar/navigation-bar.js b/components/navigation-bar/navigation-bar.js index eb1770e..48ed08c 100644 --- a/components/navigation-bar/navigation-bar.js +++ b/components/navigation-bar/navigation-bar.js @@ -60,10 +60,15 @@ Component({ lifetimes: { attached() { const rect = wx.getMenuButtonBoundingClientRect() - const platform = (wx.getDeviceInfo() || wx.getSystemInfoSync()).platform + const deviceInfo = wx.getDeviceInfo() + const platform = deviceInfo ? deviceInfo.platform : 'devtools' const isAndroid = platform === 'android' const isDevtools = platform === 'devtools' - const { windowWidth, safeArea: { top = 0, bottom = 0 } = {} } = wx.getWindowInfo() || wx.getSystemInfoSync() + const windowInfo = wx.getWindowInfo() + const windowWidth = windowInfo ? windowInfo.windowWidth : 375 + const safeArea = windowInfo && windowInfo.safeArea ? windowInfo.safeArea : {} + const top = safeArea.top || 0 + const bottom = safeArea.bottom || 0 this.setData({ ios: !isAndroid, innerPaddingRight: `padding-right: ${windowWidth - rect.left}px`, diff --git a/pages/guiding/guiding.js b/pages/guiding/guiding.js index 005584b..d37b847 100644 --- a/pages/guiding/guiding.js +++ b/pages/guiding/guiding.js @@ -1,71 +1,134 @@ -// pages/guiding/guiding.js Page({ - - /** - * 页面的初始数据 - */ data: { - + ifEntry: false, + userInfo: null }, - /** - * 生命周期函数--监听页面加载 - */ onLoad(options) { - + // 页面加载时先检查本地缓存 + this.checkLocalLoginStatus(); }, - - /** - * 生命周期函数--监听页面初次渲染完成 - */ - onReady() { - + // 检查本地登录状态(快速检查) + checkLocalLoginStatus() { + try { + const cachedUserInfo = wx.getStorageSync('userInfo'); + if (cachedUserInfo) { + this.setData({ + ifEntry: true, + userInfo: cachedUserInfo + }); + console.log('从缓存读取用户信息:', cachedUserInfo); + } else { + this.setData({ + ifEntry: false, + userInfo: null + }); + } + } catch (error) { + console.error('读取缓存失败:', error); + this.setData({ ifEntry: false }); + } }, - - /** - * 生命周期函数--监听页面显示 - */ - onShow() { - +//检查登录状态 + async checkLoginStatus() { + try { + // 强制清除缓存,确保从服务器获取最新的用户信息 + this.clearStorage(); + // 先检查本地是否有缓存 + const cachedUserInfo = wx.getStorageSync('userInfo'); + if (cachedUserInfo) { + console.log('使用缓存用户信息,直接进入主页'); + this.setData({ + ifEntry: true, + userInfo: cachedUserInfo + }); + // 调试日志:查看缓存中的用户角色值 + console.log('缓存用户角色值:', cachedUserInfo.role, '类型:', typeof cachedUserInfo.role); + + // 有缓存时直接跳转到主页 - 安全比较,处理不同类型的值 + if (cachedUserInfo.role === true || cachedUserInfo.role === 'true') { + console.log('缓存中为普通用户,跳转到index页面'); + wx.reLaunch({ + url: `/pages/index/index?openid=${cachedUserInfo.openid}` + }); + } else { + console.log('缓存中为管理员,跳转到pendingQuestion页面'); + wx.reLaunch({ + url: `/pages/pendingQuestion/pendingQuestion?openid=${cachedUserInfo.openid}` + }); + } + return; // 跳转后可以return,避免后续代码执行 + } + // 1. 如果没有缓存,调用 wx.login() 获取 code + const loginRes = await wx.login(); + const code = loginRes.code; + + if (!code) { + console.error('获取code失败'); + return; + } + + // 2. 调用后端登录接口,将code传给后端 + const result = await wx.cloud.callFunction({ + name: 'auth', + data: { + action: 'loginWithCode', + code: code + } + }); + if (result.result.success) { + const userInfo = result.result.data.userInfo; + wx.setStorageSync('userInfo', userInfo); + // 登录成功,直接进入用户页面 + this.setData({ + ifEntry: true, + userInfo: userInfo + }); + + // 调试日志:查看用户角色值 + console.log('用户角色值:', userInfo.role, '类型:', typeof userInfo.role); + + // 跳转到用户首页 - 安全比较,处理不同类型的值 + if (userInfo.role === true || userInfo.role === 'true') { + console.log('普通用户,跳转到index页面'); + wx.reLaunch({ + url: `/pages/index/index?openid=${userInfo.openid}` + }); + } else { + console.log('管理员,跳转到pendingQuestion页面'); + wx.reLaunch({ + url: `/pages/pendingQuestion/pendingQuestion?openid=${userInfo.openid}` + }); + } + + } else { + // 登录失败 + console.error('登录失败:', result.result.message); + this.setData({ + ifEntry: false + }); + const openid = result.result.openid || ''; + wx.reLaunch({ + url: `/pages/login/login?openid=${openid}` + }); + } + } catch (error) { + console.error('检查登录状态失败:', error); + this.clearStorage(); + } }, - /** - * 生命周期函数--监听页面隐藏 - */ - onHide() { - + clearStorage() { + wx.removeStorageSync('token'); + wx.removeStorageSync('userInfo'); + this.setData({ ifEntry: false }); }, + - /** - * 生命周期函数--监听页面卸载 - */ - onUnload() { - - }, - - /** - * 页面相关事件处理函数--监听用户下拉动作 - */ - onPullDownRefresh() { - - }, - - /** - * 页面上拉触底事件的处理函数 - */ - onReachBottom() { - - }, - - /** - * 用户点击右上角分享 - */ - onShareAppMessage() { - - }, - request_enter(){ - wx.redirectTo({ - url: '/pages/login/login', - }); + // 进入按钮 + async request_enter() { + this.checkLoginStatus(); + + } -}) \ No newline at end of file +}); \ No newline at end of file diff --git a/pages/home/home.js b/pages/home/home.js deleted file mode 100644 index 403ede8..0000000 --- a/pages/home/home.js +++ /dev/null @@ -1,86 +0,0 @@ -// pages/home/nome.js -Page({ - - /** - * 页面的初始数据 - */ - data: { - - }, - - /** - * 生命周期函数--监听页面加载 - */ - onLoad(options) { - - }, - - /** - * 生命周期函数--监听页面初次渲染完成 - */ - onReady() { - - }, - - /** - * 生命周期函数--监听页面显示 - */ - onShow() { - - }, - - /** - * 生命周期函数--监听页面隐藏 - */ - onHide() { - - }, - - /** - * 生命周期函数--监听页面卸载 - */ - onUnload() { - - }, - - /** - * 页面相关事件处理函数--监听用户下拉动作 - */ - onPullDownRefresh() { - - }, - - /** - * 页面上拉触底事件的处理函数 - */ - onReachBottom() { - - }, - - /** - * 用户点击右上角分享 - */ - onShareAppMessage() { - - }, - review(){ - wx.navigateTo({ - url: '/pages/review/review' - }) - }, - filter(){ - wx.navigateTo({ - url: '/pages/textbookFilter/textbookFilter' - }) -}, -question(){ - wx.navigateTo({ - url: '/pages/pendingQuestion/pendingQuestion' - }) -}, -search(){ - wx.navigateTo({ - url: '/pages/search/search' - }) -} -}) \ No newline at end of file diff --git a/pages/home/home.json b/pages/home/home.json deleted file mode 100644 index 105ebcd..0000000 --- a/pages/home/home.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "usingComponents": {} - -} \ No newline at end of file diff --git a/pages/home/home.wxml b/pages/home/home.wxml deleted file mode 100644 index 054d938..0000000 --- a/pages/home/home.wxml +++ /dev/null @@ -1,33 +0,0 @@ - - - - 欢迎回来{{userInfo.nickName || '勤奋的'}}小朋友 - - - - - - - - - - - - - \ No newline at end of file diff --git a/pages/home/home.wxss b/pages/home/home.wxss deleted file mode 100644 index b2849ae..0000000 --- a/pages/home/home.wxss +++ /dev/null @@ -1,50 +0,0 @@ -/* pages/home/home.wxss */ -.bottom-buttons { - display: flex; /* 按钮横向排列 */ - position: fixed; - justify-content: space-around; - bottom: 200rpx ; - border-top: 1px solid rgba(255, 255, 255, 0); /* 顶部边框分隔 */ - border-bottom: 1px solid #eee; - width: 100%; - left : 0%; -} -.func-btn { - display: flex; - flex-direction: column; - align-items: center; - background-color: transparent; /* 清除默认按钮背景 */ - border-top: 1px solid rgba(255, 255, 255, 0); - width: 20%; -} -.btn-icon { - width: 200rpx; -} -.user-info { - display: flex; - align-items: baseline; - padding: 30rpx 20rpx; - top: 0; - right:0; - position: absolute; /* 脱离文档流,基于父容器 .home-container 定位 */ - z-index: 1; /* 确保在其他元素上方显示 */ -} -/* 头像:圆形裁剪,固定大小 */ -.user-avatar { - width: 100rpx; - height: 100rpx; - border-radius: 50%; /* 圆形 */ - border: 2rpx solid #000; /* 白色边框增加层次感 */ - box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.1); /* 轻微阴影 */ - margin-right: 20rpx; /* 与昵称间距 */ -} - -/* 昵称:字体大小和颜色 */ -.user-name { - font-size: 36rpx; - font-weight: 500; - color: #333; -} -.container{ - position: relative; /* 关键:让子元素 .user-info 能基于它做绝对定位 */ -} diff --git a/pages/index/index.js b/pages/index/index.js index 5ac0437..be99d10 100644 --- a/pages/index/index.js +++ b/pages/index/index.js @@ -1,2 +1,185 @@ -// index.js 代码控制 -Page({}) +Page({ + data: { + userInfo: {}, + openid: '', + poems: [], // 所有诗词列表 + reviewedPoems: [], // 需要复习的诗词 + otherPoems: [], // 其他诗词 + isLoading: false + }, + + onLoad(options) { + console.log('首页加载完成'); + if (options.openid) { + this.setData({ + openid: options.openid + }); + console.log('获取到openid:', options.openid); + + // 根据openid加载用户数据和诗词数据 + this.loadUserDataAndPoems(); + } else { + console.error('未收到openid参数'); + wx.showToast({ + title: '参数错误', + icon: 'none' + }); + } + }, +// 加载用户数据和诗词数据 + async loadUserDataAndPoems() { + try { + this.setData({ isLoading: true }); + + // 并行执行:获取用户信息和诗词列表 + const [userResult, poemsResult] = await Promise.all([ + this.getUserInfo(this.data.openid), + this.getAllPoems() + ]); + + if (userResult.success) { + const userInfo = userResult.data.userInfo; + this.setData({ + userInfo: userInfo, + reviewedPoems: userInfo.reviewedPoems || {} + }); + + console.log('用户复习记录:', this.data.reviewedPoems); + } + + if (poemsResult.success) { + const allPoems = poemsResult.data.poems; + // 筛选其他诗词 + const { reviewedPoems, otherPoems } = this.classifyPoems(allPoems); + + this.setData({ + poems: allPoems, + reviewedPoems: reviewedPoems, + otherPoems: otherPoems + }); + + + } + + } catch (error) { + console.error('加载数据失败:', error); + wx.showToast({ + title: '加载失败', + icon: 'none' + }); + } finally { + this.setData({ isLoading: false }); + } + }, + // 获取用户信息 + async getUserInfo(openid) { + try { + const result = await wx.cloud.callFunction({ + name: 'auth', + data: { + action: 'getUserByOpenid', + openid: openid + } + }); + return result.result; + } catch (error) { + console.error('获取用户信息失败:', error); + return { success: false, message: '获取用户信息失败' }; + } + }, + // 获取所有诗词 + async getAllPoems() { + try { + const result = await wx.cloud.callFunction({ + name: 'poemManagement', + data: { + action: 'getAllPoems' + } + }); + return result.result; + } catch (error) { + console.error('获取诗词列表失败:', error); + return { success: false, message: '获取诗词失败' }; + } + }, + // 分类诗词:今天需要复习的 vs 其他诗词 + classifyPoems(allPoems) { + const reviewedPoems = this.data.reviewedPoems; + const otherPoems = []; + + allPoems.forEach(poem => { + const poemReviewData = reviewedPoems[poem._id]; + if (poemReviewData==null){ + otherPoems.push(poem); + } + + }); + + return { reviewedPoems, otherPoems }; + }, + // 进入学习页面 + goToStudy(e) { + const poemId = e.currentTarget.dataset.id; + + wx.navigateTo({ + url: `/pages/study/study?id=${poemId}` + }); + }, + + // 进入背诵页面 + goToRecite(e) { + const poemId = e.currentTarget.dataset.id; + console.log('跳转到背诵页面,诗歌ID:', poemId); + const poem = this.data.poems.find(p => p._id === poemId); + if (poemId && poem) { + wx.navigateTo({ + url: `/pages/recite/recite?id=${poemId}&title=${encodeURIComponent(poem.title)}&author=${encodeURIComponent(poem.author)}` + }); + } + }, + + + review(){ + const userInfo= this.data.userInfo; + console.log('跳转到复习页面,诗歌ID:', userInfo); + wx.navigateTo({ + url: `/pages/review/review?userInfo=${userInfo}` + }) + }, + + + question(){ + wx.navigateTo({ + url: '/pages/question/question' + }) + }, + + search(){ + wx.navigateTo({ + url: '/pages/search/search' + }) + }, + + onShow() { + // 每次显示页面时检查数据 + if (this.data.poems.length === 0 && !this.data.isLoading) { + this.loadPoemsFromDatabase(); + } + }, + + onPullDownRefresh() { + this.loadPoemsFromDatabase().finally(() => { + wx.stopPullDownRefresh(); + }); + }, + + onShareAppMessage() { + return { + title: '古诗学习小程序', + path: '/pages/index/index' + }; + } +}) + + + \ No newline at end of file diff --git a/pages/index/index.json b/pages/index/index.json index b1cb3d1..86104bf 100644 --- a/pages/index/index.json +++ b/pages/index/index.json @@ -1,5 +1,5 @@ { - "usingComponents": { - - } + "usingComponents": {}, + "enablePullDownRefresh": true, + "backgroundTextStyle": "light" } \ No newline at end of file diff --git a/pages/index/index.wxml b/pages/index/index.wxml index e6f2c90..6ccbac6 100644 --- a/pages/index/index.wxml +++ b/pages/index/index.wxml @@ -1,6 +1,68 @@ - + + + + 古诗学习 + 传承经典文化,品味诗词之美 + - - Weixin - + + + + 📚 + 复习 + + + + 问答 + + + 🔎 + 搜索 + + + + + + 推荐诗歌 + + + + + + 加载中... + + + + + ⚠️ + 加载失败,请重试 + + + + + + + 📖 + 暂无诗歌数据 + + + + + + + {{item.title}} + + {{item.author}} + {{item.dynasty}} + + 点击学习经典唐诗 + + + 学习 + 背诵 + + + + + \ No newline at end of file diff --git a/pages/index/index.wxss b/pages/index/index.wxss index 8c2b75a..34a5b36 100644 --- a/pages/index/index.wxss +++ b/pages/index/index.wxss @@ -1,10 +1,226 @@ -/**index.wxss**/ -page { - height: 100vh; +/* 页面容器 */ +.page-container { + min-height: 100vh; + background-color: #f5f5f5; +} + +/* 头部区域 */ +.header-section { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + padding: 60rpx 40rpx; + color: white; +} + +.header-title { + font-size: 48rpx; + font-weight: 700; + margin-bottom: 16rpx; +} + +.header-subtitle { + font-size: 28rpx; + opacity: 0.9; +} + +/* 功能按钮区域 */ +.function-grid { + display: flex; + justify-content: space-between; + padding: 30rpx 40rpx; + background: white; + margin: 20rpx 40rpx; + border-radius: 20rpx; + box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.06); +} + +.function-item { display: flex; flex-direction: column; + align-items: center; + flex: 1; +} + +.function-icon { + width: 80rpx; + height: 80rpx; + margin-bottom: 16rpx; + border-radius: 50%; + background: #f0f7ff; + display: flex; + align-items: center; + justify-content: center; + font-size: 36rpx; +} + +.function-text { + font-size: 24rpx; + color: #333; +} + +/* 诗歌列表区域 */ +.poem-section { + background: white; + margin: 0 40rpx 40rpx; + border-radius: 20rpx; + overflow: hidden; + box-shadow: 0 4rpx 20rpx rgba(0,0,0,0.06); } -.scrollarea { + +.list-header { + padding: 30rpx 40rpx 20rpx; + border-bottom: 2rpx solid #f0f0f0; +} + +.list-title { + font-size: 36rpx; + font-weight: 700; + color: #333; +} + +.poem-list { + padding: 0; +} + +.poem-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 30rpx 40rpx; + border-bottom: 1rpx solid #f8f8f8; + transition: background-color 0.3s; +} + +.poem-item:active { + background-color: #f8f9fa; +} + +.poem-content { flex: 1; - overflow-y: hidden; + margin-right: 30rpx; +} + +.poem-title { + display: block; + font-size: 34rpx; + font-weight: 600; + color: #333; + margin-bottom: 12rpx; +} + +.poem-meta { + display: flex; + align-items: center; + margin-bottom: 8rpx; +} + +.poem-author { + font-size: 26rpx; + color: #666; + margin-right: 20rpx; +} + +.poem-dynasty { + font-size: 24rpx; + color: #999; + background: #f0f0f0; + padding: 4rpx 12rpx; + border-radius: 12rpx; +} + +.poem-preview { + display: block; + font-size: 26rpx; + color: #999; + font-style: italic; + line-height: 1.4; +} + +.action-buttons { + display: flex; + gap: 15rpx; +} + +.btn-study, .btn-recite { + padding: 16rpx 24rpx; + border-radius: 16rpx; + font-size: 24rpx; + font-weight: 500; + transition: all 0.3s; +} + +.btn-study { + background-color: #1989fa; + color: white; +} + +.btn-study:active { + background-color: #1576d9; +} + +.btn-recite { + background-color: #07c160; + color: white; +} + +.btn-recite:active { + background-color: #06a652; +} + +/* 状态样式 */ +.loading-state, .empty-state, .error-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 120rpx 40rpx; + text-align: center; +} + +.loading-state { + color: #666; +} + +.empty-state { + color: #999; +} + +.error-state { + color: #ff4757; +} + +.state-icon { + font-size: 80rpx; + margin-bottom: 30rpx; + opacity: 0.7; +} + +.state-text { + font-size: 32rpx; + margin-bottom: 40rpx; +} + +.btn-retry, .btn-mock { + padding: 20rpx 40rpx; + border-radius: 30rpx; + font-size: 28rpx; + margin: 10rpx 0; + transition: all 0.3s; +} + +.btn-retry { + background-color: #1989fa; + color: white; +} + +.btn-retry:active { + background-color: #1576d9; +} + +.btn-mock { + background-color: #07c160; + color: white; } + +.btn-mock:active { + background-color: #06a652; +} \ No newline at end of file diff --git a/pages/keyWord/keyWord.js b/pages/keyWord/keyWord.js index f624a1a..aea5c78 100644 --- a/pages/keyWord/keyWord.js +++ b/pages/keyWord/keyWord.js @@ -1,20 +1,327 @@ // pages/keyWord/keyWord.js Page({ - - /** - * 页面的初始数据 - */ data: { - + questionId: '', + question: '', + answer: '', + // 关键词相关数据 + allKeywords: [], // 所有关键词数组 + currentLevel: 0, // 当前关键词层级 + selectedKeywords: [], // 已选择的关键词路径 + availableKeywords: [], // 当前层级可用的关键词 + newKeyword: '', // 新建关键词输入 + isCreatingNew: false // 是否正在创建新关键词 }, - /** - * 生命周期函数--监听页面加载 - */ onLoad(options) { + if (options) { + this.setData({ + questionId: options.id || '', + question: options.question ? decodeURIComponent(options.question) : '' + }); + // 加载已有的关键词数据 + this.loadExistingKeywords(); + } + }, + + // 加载已有关键词数据 + async loadExistingKeywords() { + try { + const db = wx.cloud.database(); + // 从数据库获取所有已有的关键词数据 + const result = await db.collection('Answer').get(); + + const allKeywords = []; + result.data.forEach(item => { + if (item.keywords && Array.isArray(item.keywords)) { + // 将每个答案的关键词路径添加到总列表中 + allKeywords.push(item.keywords); + } + }); + + this.setData({ allKeywords }); + this.updateAvailableKeywords(); + + } catch (error) { + console.error('加载关键词失败:', error); + // 如果answers集合不存在,就初始化为空数组 + this.setData({ allKeywords: [] }); + } + }, + + // 更新当前可用的关键词 + updateAvailableKeywords() { + const { selectedKeywords, allKeywords, currentLevel } = this.data; + + // 获取当前层级的所有可能关键词 + const available = new Set(); + + allKeywords.forEach(keywordPath => { + if (keywordPath.length > currentLevel) { + // 检查路径是否匹配已选择的关键词 + let isMatch = true; + for (let i = 0; i < selectedKeywords.length; i++) { + if (keywordPath[i] !== selectedKeywords[i]) { + isMatch = false; + break; + } + } + + if (isMatch && keywordPath[currentLevel]) { + available.add(keywordPath[currentLevel]); + } + } + }); + + this.setData({ + availableKeywords: Array.from(available) + }); + }, + + // 选择关键词 + selectKeyword(e) { + const keyword = e.currentTarget.dataset.keyword; + const { selectedKeywords, currentLevel } = this.data; + + // 更新已选择的关键词路径 + const newSelectedKeywords = [...selectedKeywords]; + if (newSelectedKeywords.length > currentLevel) { + newSelectedKeywords[currentLevel] = keyword; + } else { + newSelectedKeywords.push(keyword); + } + + this.setData({ + selectedKeywords: newSelectedKeywords, + currentLevel: currentLevel + 1, + isCreatingNew: false, + newKeyword: '' + }); + + // 更新可用关键词 + this.updateAvailableKeywords(); + }, + + // 新建关键词 + toggleCreateNew() { + this.setData({ + isCreatingNew: !this.data.isCreatingNew, + newKeyword: '' + }); + }, + // 输入新建关键词 + onNewKeywordInput(e) { + this.setData({ + newKeyword: e.detail.value + }); }, + // 确认新建关键词 + confirmNewKeyword() { + const { newKeyword, selectedKeywords, currentLevel } = this.data; + + if (!newKeyword.trim()) { + wx.showToast({ + title: '请输入关键词', + icon: 'none' + }); + return; + } + + // 更新已选择的关键词路径 + const newSelectedKeywords = [...selectedKeywords]; + if (newSelectedKeywords.length > currentLevel) { + newSelectedKeywords[currentLevel] = newKeyword.trim(); + } else { + newSelectedKeywords.push(newKeyword.trim()); + } + + this.setData({ + selectedKeywords: newSelectedKeywords, + currentLevel: currentLevel + 1, + isCreatingNew: false, + newKeyword: '' + }); + + // 更新可用关键词(新建的关键词会出现在下一级选择中) + this.updateAvailableKeywords(); + }, + + // 返回上一级 + goBack() { + const { currentLevel } = this.data; + if (currentLevel > 0) { + this.setData({ + currentLevel: currentLevel - 1, + isCreatingNew: false, + newKeyword: '' + }); + this.updateAvailableKeywords(); + } + }, + + // 输入回答 + onAnswerInput(e) { + this.setData({ + answer: e.detail.value + }); + }, + + // 获取当前关键词路径显示 + getCurrentKeywordPath() { + const { selectedKeywords, currentLevel } = this.data; + const currentPath = selectedKeywords.slice(0, currentLevel); + + if (currentPath.length === 0) { + return '请选择关键词(从第一级开始)'; + } + + return currentPath.join(' > '); + }, + + // 重置关键词 + resetKeywords() { + this.setData({ + selectedKeywords: [], + currentLevel: 0, + isCreatingNew: false, + newKeyword: '' + }); + this.updateAvailableKeywords(); + + wx.showToast({ + title: '关键词已重置', + icon: 'success' + }); + }, + + // 提交答案和关键词 +async submitAnswer() { + const { questionId, question, selectedKeywords, answer } = this.data; + + // 验证输入 + if (selectedKeywords.length === 0) { + wx.showToast({ + title: '请至少选择一个关键词', + icon: 'none' + }); + return; + } + + if (!answer.trim()) { + wx.showToast({ + title: '请输入答案', + icon: 'none' + }); + return; + } + + // 显示加载中 + wx.showLoading({ + title: '提交中...', + mask: true + }); + + try { + const db = wx.cloud.database(); + + // 1. 从Question集合获取问题详情,包括用户的_openid + let userOpenid = ''; + let questionDocId = questionId; + + if (questionId) { + try { + const questionDetail = await db.collection('Question').doc(questionId).get(); + userOpenid = questionDetail.data._openid || ''; + console.log('获取到用户openid:', userOpenid); + } catch (detailError) { + console.error('获取问题详情失败:', detailError); + // 如果通过ID查询失败,尝试通过问题内容查询 + const queryResult = await db.collection('Question').where({ + question: question + }).get(); + + if (queryResult.data.length > 0) { + const firstQuestion = queryResult.data[0]; + userOpenid = firstQuestion._openid || ''; + questionDocId = firstQuestion._id; + console.log('通过问题内容获取到用户openid:', userOpenid); + } + } + } + + // 2. 保存答案到Answer集合,按照数据库要求的格式 + const saveData = { + createTime: db.serverDate(), // 使用服务器时间 + keywords: selectedKeywords, // 关键词数组 + question: question, // 问题内容 + questionId: questionDocId, // 保存问题ID,便于后续查询 + answers: [answer.trim()], // 答案使用answers数组 + status: 1, // 标记为已回答状态 + userId: userOpenid // 保存提问用户的openid,但使用userId而非_openid,避免系统保留字段冲突 + }; + + await db.collection('Answer').add({ + data: saveData + }); + + console.log('答案保存成功:', saveData); + + // 3. 更新Question集合中对应问题的状态为已回答(status: 1) + if (questionDocId) { + try { + await db.collection('Question').doc(questionDocId).update({ + data: { + status: 1 + } + }); + console.log('问题状态更新成功,问题ID:', questionDocId); + } catch (updateError) { + console.error('更新问题状态失败:', updateError); + // 尝试通过问题内容更新 + const updateResult = await db.collection('Question').where({ + question: question + }).update({ + data: { + status: 1 + } + }); + console.log('通过问题内容更新状态结果:', updateResult); + } + } + + wx.hideLoading(); + wx.showToast({ + title: '提交成功', + icon: 'success', + duration: 2000, + success: () => { + setTimeout(() => { + wx.navigateBack(); + }, 1500); + } + }); + + } catch (error) { + console.error('提交失败:', error); + wx.hideLoading(); + + let errorMsg = '提交失败,请重试'; + if (error.errCode === -502005) { + errorMsg = '数据库集合不存在,请检查配置'; + } else if (error.errCode === -501007) { + errorMsg = '参数错误,请检查输入'; + } + + wx.showToast({ + title: errorMsg, + icon: 'none', + duration: 2000 + }); + } +}, + /** * 生命周期函数--监听页面初次渲染完成 */ diff --git a/pages/keyWord/keyWord.wxml b/pages/keyWord/keyWord.wxml index b9cd149..4929bdd 100644 --- a/pages/keyWord/keyWord.wxml +++ b/pages/keyWord/keyWord.wxml @@ -1,2 +1,83 @@ -pages/keyWord/keyWord.wxml \ No newline at end of file + + 关键词回答 + + + + + + 问题: + + {{question}} + + + + + + 关键词管理: + + + + 当前路径: + {{getCurrentKeywordPath()}} + + + + + 第{{currentLevel + 1}}级关键词 + + + + + + {{item}} + + + + + + + + + + {{isCreatingNew ? '取消新建' : '新建关键词'}} + + + + + + + + + + + + + + + + + + + 答案: + + + + + + + + + + + + + + 背诵评分 + {{accuracyRate}}% + + + + + + + 背诵用时 + {{reciteDuration}} + + + + 背诵时间 + {{reciteDateTime}} + + + + + + + + + + + + + {{accuracyRate >= 90 ? '优秀!背诵得非常准确' : accuracyRate >= 70 ? '良好!继续保持' : accuracyRate >= 50 ? '一般,还需要练习' : '需要多加练习'}} + + + + + + + + + + + \ No newline at end of file diff --git a/pages/recite/recite.wxss b/pages/recite/recite.wxss index 6b0172c..53e3f56 100644 --- a/pages/recite/recite.wxss +++ b/pages/recite/recite.wxss @@ -1 +1,218 @@ -/* pages/recite/recite.wxss */ \ No newline at end of file +/* pages/recite/recite.wxss */ +.recite-container { + padding: 20rpx; + background-color: #f8f8f8; + min-height: 100vh; + box-sizing: border-box; +} + +/* 头部样式 */ +.header { + text-align: center; + margin-bottom: 40rpx; + padding: 30rpx 0; + background: linear-gradient(135deg, #ffecd2 0%, #fcb69f 100%); + border-radius: 15rpx; + box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1); +} + +.title { + font-size: 48rpx; + font-weight: bold; + color: #333; + display: block; + margin-bottom: 10rpx; +} + +.subtitle { + font-size: 32rpx; + color: #666; +} + +/* 原文和识别结果区域 */ +.original-section, +.recognition-section { + background: #fff; + padding: 30rpx; + margin-bottom: 30rpx; + border-radius: 15rpx; + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.08); +} + +.section-title { + font-size: 36rpx; + font-weight: bold; + color: #333; + display: block; + margin-bottom: 20rpx; +} + +.original-text { + font-size: 34rpx; + line-height: 1.8; + color: #444; + white-space: pre-wrap; + word-break: break-all; +} + +.result-textarea { + width: 100%; + min-height: 200rpx; + padding: 20rpx; + font-size: 34rpx; + line-height: 1.6; + color: #333; + background: #f9f9f9; + border: 1rpx solid #ddd; + border-radius: 10rpx; + box-sizing: border-box; +} + +/* 正确率显示区域 */ +.result-section { + text-align: center; + margin: 40rpx 0; +} + +/* 进度条样式正确率显示 */ +.accuracy-progress-container { + background: #fff; + padding: 40rpx; + border-radius: 20rpx; + box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.1); + margin-bottom: 30rpx; +} + +.accuracy-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20rpx; +} + +/* 背诵信息显示区域 */ +.info-section { + margin-bottom: 30rpx; + padding: 15rpx 0; + border-top: 1rpx solid #f0f0f0; +} + +/* 信息项样式 */ +.info-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10rpx 0; +} + +.info-label { + font-size: 32rpx; + color: #666; +} + +.info-value { + font-size: 34rpx; + font-weight: bold; +} + +/* 背诵时长样式 */ +.duration-value { + color: #007AFF; + letter-spacing: 2rpx; +} + +/* 背诵时间样式 */ +.date-value { + color: #34C759; + font-family: 'Courier New', monospace; +} + +.accuracy-title { + font-size: 36rpx; + font-weight: bold; + color: #333; +} + +.accuracy-value { + font-size: 48rpx; + font-weight: bold; + color: #4CAF50; + text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1); +} + +/* 进度条样式 */ +.progress-bar { + margin-bottom: 30rpx; +} + +.progress-bg { + width: 100%; + height: 30rpx; + background: #f0f0f0; + border-radius: 15rpx; + overflow: hidden; + box-shadow: inset 0 2rpx 4rpx rgba(0, 0, 0, 0.1); +} + +.progress-fill { + height: 100%; + border-radius: 15rpx; + transition: width 0.6s ease; + box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.2); +} + +/* 评价文字 */ +.accuracy-comment { + font-size: 32rpx; + color: #666; + display: block; + padding: 20rpx 0; + background: #f9f9f9; + border-radius: 10rpx; + margin-top: 10rpx; +} + +/* 检查按钮区域 */ +.check-section { + text-align: center; + margin: 40rpx 0; +} + +.btn-check { + width: 60%; + font-size: 36rpx; + padding: 20rpx 0; + background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); + border: none; + color: white; +} + +/* 重置按钮 */ +.btn-reset { + margin-top: 30rpx; + font-size: 32rpx; + width: 50%; +} + +/* 控制按钮区域 */ +.control-buttons { + display: flex; + justify-content: space-around; + margin-top: 40rpx; + padding-bottom: 40rpx; +} + +.btn-record-start, +.btn-record-stop { + width: 280rpx; + font-size: 34rpx; + padding: 20rpx 0; +} + +/* 响应式设计 */ +@media screen and (min-width: 768px) { + .recite-container { + max-width: 800rpx; + margin: 0 auto; + } +} \ No newline at end of file diff --git a/pages/review/review.js b/pages/review/review.js index 2945a72..565f5eb 100644 --- a/pages/review/review.js +++ b/pages/review/review.js @@ -1,52 +1,747 @@ // pages/review/review.js + +// SM2算法实现 +class SM2 { + constructor() { + this.ef = 2.5; // 初始易度因子(Easiness Factor) + this.reps = 0; // 重复次数 + this.lastInterval = 0; // 上次复习间隔 + } + + /** + * 根据用户回忆质量计算下次复习间隔和更新易度因子 + * @param {number} quality - 回忆质量 (0-5分): 0=完全错误, 5=完美回忆 + * @returns {object} - {nextInterval: 下次复习间隔(天), newEF: 新的易度因子} + */ + calculateNextReview(quality) { + // 根据回忆质量更新易度因子 + if (quality < 3) { // 回忆失败 (0-2分) + // 重置重复次数,间隔设为1天 + this.reps = 0; + this.lastInterval = 1; + // 降低易度因子,但不低于1.3 + this.ef = Math.max(1.3, this.ef - 0.2); + } else { // 回忆成功 (3-5分) + // 第一次成功后,使用特定的计算方式 + if (this.reps === 0) { + this.lastInterval = 1; // 第一次成功后1天后复习 + } else if (this.reps === 1) { + this.lastInterval = 6; // 第二次成功后6天后复习 + } else { + // 之后使用易度因子计算 + this.lastInterval = Math.round(this.lastInterval * this.ef); + } + // 更新易度因子公式:EF' = EF + (0.1 - (5 - q) * (0.08 + (5 - q) * 0.02)) + this.ef = Math.max(1.3, this.ef + (0.1 - (5 - quality) * (0.08 + (5 - quality) * 0.02))); + this.reps++; + } + + return { + nextInterval: this.lastInterval, + newEF: this.ef, + repetitions: this.reps + }; + } + + /** + * 基于艾宾浩斯公式计算记忆保留率 + * R = e^(-t/S),其中t是时间间隔(小时),S是记忆稳定性 + * @param {number} hoursSinceLastReview - 距离上次复习的小时数 + * @param {number} stability - 记忆稳定性(可从易度因子推导) + * @returns {number} - 记忆保留率 (0-100%) + */ + calculateRetentionRate(hoursSinceLastReview, stability) { + // 默认稳定性,如果未提供则基于易度因子计算 + const S = stability || (this.ef * 10); // 简化:易度因子*10作为稳定性 + const R = Math.exp(-hoursSinceLastReview / S); + return Math.round(R * 100); + } +} + Page({ /** * 页面的初始数据 */ data: { - + // 遗忘曲线数据 - 显示未来7天的复习计划 + 复习计划数据: [], + // 需要复习的古诗列表 + poemsToReview: [], + // Canvas尺寸 + canvasWidth: 0, + canvasHeight: 300, + // 今日需要复习的总数 + todayReviewCount: 0 }, /** * 生命周期函数--监听页面加载 */ - onLoad(options) { - + onLoad: function (options) { + // 初始化数据加载 + this.loadPoemsToReview().then(() => { + // 数据加载完成后绘制图表 + this.drawReviewPlanChart(); + }); + }, + + /** + * 加载需要复习的古诗数据 + */ + async loadPoemsToReview() { + try { + wx.showLoading({ title: '加载复习计划...' }) + + // 从数据库加载真实背诵记录 + let reciteRecords = await this.loadReciteRecordsFromDatabase(); + + // 如果没有记录或记录为空,使用模拟数据 + let recordsToUse = reciteRecords && reciteRecords.length > 0 ? reciteRecords : this.getMockReciteRecords(); + + // 增强:为每条记录获取完整的诗歌信息,特别是作者信息 + if (reciteRecords && reciteRecords.length > 0) { + recordsToUse = await this.enrichRecordsWithPoemDetails(reciteRecords); + } + + // 使用SM2算法计算复习计划 + const poemsWithReviewPlan = this.calculateReviewPlan(recordsToUse); + + // 生成未来7天的复习计划数据(用于图表显示) + const reviewPlanData = this.generateReviewPlanData(poemsWithReviewPlan); + + // 计算今天需要复习的数量 + const todayReviewCount = poemsWithReviewPlan.filter(p => p.needsReviewToday).length; + + this.setData({ + poemsToReview: poemsWithReviewPlan, + 复习计划数据: reviewPlanData, + todayReviewCount + }); + + wx.hideLoading() + return poemsWithReviewPlan; + } catch (error) { + wx.hideLoading() + console.error('加载复习数据失败:', error); + // 出错时使用模拟数据 + const mockRecords = this.getMockReciteRecords(); + const poemsWithReviewPlan = this.calculateReviewPlan(mockRecords); + const reviewPlanData = this.generateReviewPlanData(poemsWithReviewPlan); + const todayReviewCount = poemsWithReviewPlan.filter(p => p.needsReviewToday).length; + + this.setData({ + poemsToReview: poemsWithReviewPlan, + 复习计划数据: reviewPlanData, + todayReviewCount + }); + + return poemsWithReviewPlan; + } + }, + + /** + * 为复习记录获取完整的诗歌详情信息 + */ + async enrichRecordsWithPoemDetails(records) { + try { + console.log('正在获取完整诗歌信息...'); + + // 为每条记录异步获取诗歌详情 + const enrichedRecords = []; + for (const record of records) { + try { + // 调用云函数获取诗歌详情 + const { result } = await wx.cloud.callFunction({ + name: 'poemManagement', + data: { + action: 'getPoemDetail', + id: record.poemId || record._id + } + }); + + // 如果成功获取到详情,更新作者信息 + if (result && result.success && result.data) { + const poemDetail = result.data; + + // 创建增强后的记录,保留原始字段,更新作者信息 + const enrichedRecord = { + ...record, + poemAuthor: poemDetail.author || record.poemAuthor || record.author || '未知作者', + poemTitle: poemDetail.title || record.poemTitle || record.poemName || '未知标题' + }; + + enrichedRecords.push(enrichedRecord); + console.log(`成功获取诗歌ID: ${record.poemId || record._id} 的完整信息`); + } else { + // 获取失败时保留原始记录 + console.log(`无法获取诗歌ID: ${record.poemId || record._id} 的详情,使用原始数据`); + enrichedRecords.push(record); + } + } catch (error) { + // 单条记录获取失败不影响整体 + console.error(`获取诗歌详情失败: ${record.poemId || record._id}`, error); + enrichedRecords.push(record); + } + + // 添加小延迟避免请求过于密集 + await new Promise(resolve => setTimeout(resolve, 50)); + } + + console.log('诗歌信息获取完成'); + return enrichedRecords; + } catch (error) { + console.error('增强诗歌记录时发生错误:', error); + // 如果整体出错,返回原始记录 + return records; + } + }, + + /** + * 获取模拟的背诵记录数据 + */ + getMockReciteRecords() { + // 仅在数据库加载失败时使用模拟数据 + const now = Date.now(); + const dayMs = 24 * 60 * 60 * 1000; + + return [ + { + poemId: 'poet_001', + poemTitle: '静夜思', + poemAuthor: '李白', + lastReciteTime: now - dayMs, // 1天前 + accuracy: 85, + reciteCount: 2, + ef: 2.3, + nextReviewInterval: 1 + }, + { + poemId: 'poet_002', + poemTitle: '春晓', + poemAuthor: '孟浩然', + lastReciteTime: now - 3 * dayMs, // 3天前 + accuracy: 60, + reciteCount: 1, + ef: 2.0, + nextReviewInterval: 1 + }, + { + poemId: 'poet_003', + poemTitle: '望庐山瀑布', + poemAuthor: '李白', + lastReciteTime: now - 0.5 * dayMs, // 0.5天前 + accuracy: 95, + reciteCount: 3, + ef: 2.7, + nextReviewInterval: 6 + }, + { + poemId: 'poet_004', + poemTitle: '登鹳雀楼', + poemAuthor: '王之涣', + lastReciteTime: now - 7 * dayMs, // 7天前 + accuracy: 70, + reciteCount: 2, + ef: 2.1, + nextReviewInterval: 3 + } + ] + }, + + /** + * 从数据库加载真实的背诵记录 + */ + async loadReciteRecordsFromDatabase() { + try { + // 首先获取用户openid + const { result } = await wx.cloud.callFunction({ + name: 'getOpenId' + }) + + if (!result.openid) { + throw new Error('获取用户信息失败') + } + + // 查询用户的背诵记录 + const db = wx.cloud.database() + const records = await db.collection('Review') + .where({ + openid: result.openid + }) + .orderBy('reciteDateTime', 'desc') + .get() + + console.log('从数据库获取的背诵记录:', records.data); + + // 转换数据库记录格式,确保字段名一致 + const formattedRecords = records.data.map(record => { + return { + poemId: record.poemId, + poemTitle: record.poemName || '未知标题', + poemAuthor: record.poemAuthor || record.author || '未知作者', // 尝试多种可能的作者字段 + lastReciteTime: new Date(record.reciteDateTime).getTime(), + accuracy: record.accuracy || record.matchRate || 0, + reciteCount: record.reciteCount || 1, + ef: record.ef || 2.5, + nextReviewInterval: record.nextReviewInterval || 1 + }; + }); + + return formattedRecords; + } catch (error) { + console.error('加载背诵记录失败:', error); + // 如果加载失败,返回空数组,让上层函数处理 + return []; + } + }, + + /** + * 手动初始化数据库 + */ + async initDatabaseManually() { + try { + wx.showLoading({ title: '初始化数据库...' }) + + const result = await wx.cloud.callFunction({ + name: 'initDatabase' + }) + + wx.hideLoading() + + if (result.result && result.result.success) { + wx.showToast({ + title: '数据库初始化成功', + icon: 'success' + }) + // 重新加载数据 + this.loadPoemsToReview() + } else { + wx.showToast({ + title: result.result?.message || '初始化失败', + icon: 'none' + }) + } + } catch (error) { + wx.hideLoading() + wx.showToast({ + title: '初始化失败: ' + error.message, + icon: 'none' + }) + } + }, + + /** + * 基于SM2算法计算复习计划和优先级 + */ + calculateReviewPlan(records) { + const now = Date.now(); + const sm2 = new SM2(); + + // 去重处理,确保每首诗只出现一次 + const uniqueRecords = []; + const poemIdSet = new Set(); + + // 优先保留最新的记录(根据传入的顺序,假设前面的记录更新) + records.forEach(record => { + const poemId = record.poemId || record._id; + if (poemId && !poemIdSet.has(poemId)) { + poemIdSet.add(poemId); + uniqueRecords.push(record); + } + }); + + console.log('去重后的记录数量:', uniqueRecords.length); + + // 计算每首诗的复习状态和下次复习时间 + const poemsWithReviewStatus = uniqueRecords.map(record => { + // 标准化字段名,确保兼容性 + const poem = { + id: record.poemId || record._id, + title: record.poemTitle || record.poemName || '未知标题', + author: record.poemAuthor || '未知作者', + lastReciteTime: record.lastReciteTime || (record.reciteDateTime ? new Date(record.reciteDateTime).getTime() : now - 24 * 60 * 60 * 1000), + accuracy: record.accuracy || record.matchRate || 0, + reciteCount: record.reciteCount || 0, + ef: record.ef || 2.5, // 易度因子 + nextReviewInterval: record.nextReviewInterval || 1 // 下次复习间隔 + }; + + // 计算距离上次背诵的时间(天) + const daysSinceLastRecite = (now - poem.lastReciteTime) / (24 * 60 * 60 * 1000); + + // 根据正确率转换为SM2质量评分 (0-5分) + let quality = 0; + if (poem.accuracy >= 90) quality = 5; + else if (poem.accuracy >= 80) quality = 4; + else if (poem.accuracy >= 60) quality = 3; + else if (poem.accuracy >= 40) quality = 2; + else if (poem.accuracy >= 20) quality = 1; + + // 使用SM2计算下次复习间隔 + sm2.ef = poem.ef; + sm2.reps = poem.reciteCount; + sm2.lastInterval = poem.nextReviewInterval; + + const reviewResult = sm2.calculateNextReview(quality); + + // 判断是否需要今天复习 + const needsReviewToday = daysSinceLastRecite >= poem.nextReviewInterval - 0.1; // 允许0.1天的误差 + + // 计算记忆保留率(基于艾宾浩斯公式) + const hoursSinceLastReview = daysSinceLastRecite * 24; + const retentionRate = sm2.calculateRetentionRate(hoursSinceLastReview, poem.ef * 10); + + return { + ...poem, + daysSinceLastRecite: Math.round(daysSinceLastRecite * 10) / 10, // 保留一位小数 + nextReviewInterval: reviewResult.nextInterval, + newEF: reviewResult.newEF, + needsReviewToday, + retentionRate, + reviewUrgency: needsReviewToday ? (100 - retentionRate) : 0 + }; + }); + + // 按复习紧急程度排序(今天需要复习的排前面,按记忆保留率从低到高) + poemsWithReviewStatus.sort((a, b) => { + if (a.needsReviewToday && !b.needsReviewToday) return -1; + if (!a.needsReviewToday && b.needsReviewToday) return 1; + return b.reviewUrgency - a.reviewUrgency; + }); + + return poemsWithReviewStatus; + }, + + /** + * 生成未来7天的复习计划数据(用于图表显示) + */ + generateReviewPlanData(poems) { + const planData = []; + const now = new Date(); + + // 初始化未来7天的数据 + for (let i = 0; i < 7; i++) { + const date = new Date(now); + date.setDate(date.getDate() + i); + planData.push({ + day: i === 0 ? '今天' : i === 1 ? '明天' : `${i}天后`, + dateStr: `${date.getMonth() + 1}/${date.getDate()}`, + count: 0 + }); + } + + // 统计每天需要复习的古诗数量 + poems.forEach(poem => { + // 优先使用needsReviewToday标志来判断是否今天需要复习 + if (poem.needsReviewToday) { + // 如果标记为今天需要复习,直接计入今天的数量 + planData[0].count++; + return; // 跳过后续计算 + } + + // 对于不是今天需要复习的,正常计算下次复习日期 + const lastReviewDate = new Date(poem.lastReciteTime); + const nextReviewDate = new Date(lastReviewDate); + nextReviewDate.setDate(nextReviewDate.getDate() + poem.nextReviewInterval); + + // 计算下次复习日期距离今天的天数(使用宽松计算,不四舍五入) + const daysUntilNextReview = Math.floor((nextReviewDate - now) / (24 * 60 * 60 * 1000)); + + // 更新对应天数的复习数量 + if (daysUntilNextReview >= 0 && daysUntilNextReview < 7) { + planData[daysUntilNextReview].count++; + } + }); + + return planData; + }, + + /** + * 跳转到学习页面 + */ + goToStudy(e) { + const poemId = e.currentTarget.dataset.id; + if (poemId) { + wx.navigateTo({ + url: `/pages/study/study?id=${poemId}`, + fail: function(res) { + console.error('跳转到学习页面失败:', res); + wx.showToast({ + title: '跳转失败,请重试', + icon: 'none' + }); + } + }); + } else { + console.error('缺少诗歌ID参数'); + wx.showToast({ + title: '参数错误', + icon: 'none' + }); + } + }, + + /** + * 跳转到背诵页面 + */ + goToRecite(e) { + const poemId = e.currentTarget.dataset.id; + const poemTitle = e.currentTarget.dataset.title; + const poemAuthor = e.currentTarget.dataset.author; + if (poemId) { + // 查找对应的诗歌完整数据 + const poem = this.data.poemsToReview.find(p => p.id === poemId); + + try { + if (poem) { + // 构建完整的诗歌数据对象 + const poemData = { + _id: poem.id, + title: poem.title, + author: poem.author, + content: '加载中...' // 实际内容会在背诵页面加载 + }; + + // 编码并传递数据 + const encodedPoemData = encodeURIComponent(JSON.stringify(poemData)); + wx.navigateTo({ + url: `/pages/recite/recite?id=${poemId}&poemData=${encodedPoemData}`, + fail: function(res) { + console.error('跳转到背诵页面失败:', res); + // 降级方案:传递ID、标题和作者 + wx.navigateTo({ + url: `/pages/recite/recite?id=${poemId}&title=${encodeURIComponent(poemTitle || '未知古诗')}&author=${encodeURIComponent(poemAuthor || '未知作者')}` + }); + } + }); + } else { + // 降级方案:传递ID、标题和作者 + console.warn('无法找到完整诗歌数据,传递ID、标题和作者:', poemId); + wx.navigateTo({ + url: `/pages/recite/recite?id=${poemId}&title=${encodeURIComponent(poemTitle || '未知古诗')}&author=${encodeURIComponent(poemAuthor || '未知作者')}`, + fail: function(res) { + console.error('跳转到背诵页面失败:', res); + wx.showToast({ + title: '跳转失败,请重试', + icon: 'none' + }); + } + }); + } + } catch (error) { + console.error('处理诗歌数据时出错:', error); + // 异常情况下,使用降级方案 + wx.navigateTo({ + url: `/pages/recite/recite?id=${poemId}&title=${encodeURIComponent(poemTitle || '未知古诗')}&author=${encodeURIComponent(poemAuthor || '未知作者')}` + }); + } + } else { + console.error('缺少诗歌ID参数'); + wx.showToast({ + title: '参数错误', + icon: 'none' + }); + } }, /** * 生命周期函数--监听页面初次渲染完成 */ - onReady() { - + onReady: function () { + // 获取系统信息设置Canvas尺寸 + const sysInfo = wx.getSystemInfoSync(); + const windowWidth = sysInfo.windowWidth; + + this.setData({ + canvasWidth: windowWidth - 40, // 左右各留20px边距 + canvasHeight: 300 + }); + + // 确保数据加载完成后绘制图表 + if (this.data.复习计划数据 && this.data.复习计划数据.length > 0) { + this.drawReviewPlanChart(); + } }, - + /** * 生命周期函数--监听页面显示 */ - onShow() { - + onShow: function() { + // 每次页面显示时重新加载数据并绘制图表 + this.loadPoemsToReview().then(() => { + setTimeout(() => { + // 延迟执行确保Canvas已准备好 + this.drawReviewPlanChart(); + }, 100); + }); }, /** - * 生命周期函数--监听页面隐藏 + * 绘制复习计划图表 + * 显示未来7天每天需要复习的古诗数量 */ - onHide() { + drawReviewPlanChart() { + const ctx = wx.createCanvasContext('reviewPlanChart'); + const { canvasWidth, canvasHeight } = this.data; + const data = this.data.复习计划数据; + + // 确保有数据 + if (!data || data.length === 0) { + // 绘制无数据状态 + ctx.setFillStyle('#ffffff'); + ctx.fillRect(0, 0, canvasWidth, canvasHeight); + ctx.setFillStyle('#999999'); + ctx.setFontSize(14); + ctx.setTextAlign('center'); + ctx.fillText('暂无复习计划数据', canvasWidth / 2, canvasHeight / 2); + ctx.draw(); + return; + } + + // 设置画布背景 + ctx.setFillStyle('#ffffff'); + ctx.fillRect(0, 0, canvasWidth, canvasHeight); + + // 计算坐标转换参数 + const padding = 40; + const plotWidth = canvasWidth - 2 * padding; + const plotHeight = canvasHeight - 2 * padding; + const maxCount = Math.max(...data.map(item => item.count), 1); // 至少为1,避免除以0 + + // 绘制坐标轴 + ctx.setStrokeStyle('#e0e0e0'); + ctx.setLineWidth(1); + + // 垂直网格线 + for (let i = 0; i <= 6; i++) { + const x = padding + (plotWidth / 6) * i; + ctx.beginPath(); + ctx.moveTo(x, padding); + ctx.lineTo(x, canvasHeight - padding); + ctx.stroke(); + } + + // 水平网格线 + const maxYAxisValue = Math.ceil(maxCount * 1.2); // 留出20%的顶部空间 + const yAxisSteps = Math.min(5, maxYAxisValue); // 最多5条水平线 + for (let i = 0; i <= yAxisSteps; i++) { + const y = padding + (plotHeight / yAxisSteps) * i; + ctx.beginPath(); + ctx.moveTo(padding, y); + ctx.lineTo(canvasWidth - padding, y); + ctx.stroke(); + } + + // 绘制坐标轴标签 + ctx.setFillStyle('#666666'); + ctx.setFontSize(12); + ctx.setTextAlign('center'); + + // X轴标签(显示日期) + data.forEach((item, index) => { + const x = padding + (plotWidth / 6) * index; + + // 绘制日期 + ctx.fillText(item.dateStr, x, canvasHeight - padding + 15); + + // 绘制天数 + ctx.fillText(item.day, x, canvasHeight - padding + 30); + }); + + // Y轴标签 + ctx.setTextAlign('right'); + for (let i = 0; i <= yAxisSteps; i++) { + const count = maxYAxisValue * (1 - i / yAxisSteps); + const y = padding + (plotHeight / yAxisSteps) * i; + ctx.fillText(Math.round(count), padding - 10, y + 5); + } + + // 绘制曲线图 + if (data.length > 1) { + ctx.setStrokeStyle('#4CAF50'); // 使用绿色作为主色调 + ctx.setLineWidth(2); + ctx.beginPath(); + + data.forEach((item, index) => { + const x = padding + (plotWidth / 6) * index; + const valueRatio = item.count / maxYAxisValue; + const y = canvasHeight - padding - (valueRatio * plotHeight); + + // 绘制点 + ctx.beginPath(); + ctx.arc(x, y, 4, 0, 2 * Math.PI); + ctx.fillStyle = '#4CAF50'; + ctx.fill(); + + // 连接点形成曲线 + if (index === 0) { + ctx.moveTo(x, y); + } else { + // 使用贝塞尔曲线使线条更平滑 + const prevItem = data[index - 1]; + const prevX = padding + (plotWidth / 6) * (index - 1); + const prevY = canvasHeight - padding - ((prevItem.count / maxYAxisValue) * plotHeight); + + const cpx1 = prevX + (x - prevX) / 2; + const cpy1 = prevY; + const cpx2 = prevX + (x - prevX) / 2; + const cpy2 = y; + + ctx.bezierCurveTo(cpx1, cpy1, cpx2, cpy2, x, y); + } + }); + + ctx.stroke(); + } + + // 绘制每个数据点的值 + ctx.setFillStyle('#333333'); + ctx.setFontSize(12); + ctx.setTextAlign('center'); + + data.forEach((item, index) => { + const x = padding + (plotWidth / 6) * index; + const valueRatio = item.count / maxYAxisValue; + const y = canvasHeight - padding - (valueRatio * plotHeight); + + // 在点的上方显示数值 + ctx.fillText(item.count.toString(), x, y - 10); + }); + + // 绘制标题 + ctx.setFillStyle('#333333'); + ctx.setFontSize(16); + ctx.setTextAlign('center'); + ctx.fillText('未来7天复习计划', canvasWidth / 2, padding - 10); + + ctx.draw(); + }, + + // 删除不再需要的辅助函数,所有功能现在在drawReviewPlanChart中集中实现 + + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh() { + // 刷新页面数据 + this.drawForgettingCurve(); + wx.stopPullDownRefresh(); }, /** - * 生命周期函数--监听页面卸载 + * 生命周期函数--监听页面隐藏 */ - onUnload() { + onHide() { }, /** - * 页面相关事件处理函数--监听用户下拉动作 + * 生命周期函数--监听页面卸载 */ - onPullDownRefresh() { + onUnload() { }, diff --git a/pages/review/review.wxml b/pages/review/review.wxml index e781415..1836a6c 100644 --- a/pages/review/review.wxml +++ b/pages/review/review.wxml @@ -1,2 +1,56 @@ -pages/review/review.wxml \ No newline at end of file + + + 复习 + + + + + 复习计划 + + + + 根据SM2算法和艾宾浩斯遗忘曲线生成的复习计划,横轴为天数,纵轴为每天需要复习的古诗数量。 + + + + 今日有 {{todayReviewCount}} 首古诗需要复习 + + + 今日暂无需要复习的古诗 + + + + + + 今日推荐复习 + + + + + + {{item.title}} + {{item.author}} + 今日必背 + + + + 上次背诵: {{item.daysSinceLastRecite}}天前 + 正确率: {{item.accuracy}}% + 记忆保留率: {{item.retentionRate}}% + 下次复习: {{item.nextReviewInterval}}天后 + + + + + + + + + + + + 暂无推荐复习的古诗 + 开始学习新古诗后,系统会自动生成复习计划 + + \ No newline at end of file diff --git a/pages/review/review.wxss b/pages/review/review.wxss index f6ff097..a0c419f 100644 --- a/pages/review/review.wxss +++ b/pages/review/review.wxss @@ -1 +1,215 @@ -/* pages/review/review.wxss */ \ No newline at end of file +/* pages/review/review.wxss */ + +/* 页面容器 */ +.container { + padding: 30rpx; + background-color: #f8f8f8; + min-height: 100vh; +} + +/* 页面标题 */ +.page-header { + text-align: center; + margin-bottom: 15rpx; +} + +.page-title { + font-size: 40rpx; + font-weight: bold; + color: #333; +} + +/* 遗忘曲线区域 */ +.curve-section { + background-color: #fff; + border-radius: 20rpx; + padding: 30rpx; + margin-bottom: 30rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); +} + +.section-title { + font-size: 32rpx; + font-weight: 600; + color: #333; + margin-bottom: 20rpx; +} + +.curve-container { + display: flex; + flex-direction: column; + align-items: center; +} + +.curve-description { + margin-top: 20rpx; + font-size: 24rpx; + color: rgb(126, 123, 123); + line-height: 36rpx; + text-align: center; +} + +/* 复习计划区域 */ +.plan-section { + background-color: #fff; + border-radius: 20rpx; + padding: 30rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); +} + +.section-subtitle { + font-size: 24rpx; + color: #666; + margin-bottom: 20rpx; +} + +/* 复习古诗列表 */ +.poem-list { + width: 100%; +} + +.poem-item { + background-color: #ffffff; + border-radius: 20rpx; + padding: 30rpx; + margin-bottom: 20rpx; + box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05); + display: flex; + flex-direction: column; + transition: transform 0.2s ease; + position: relative; +} + +.poem-item.urgent { + border-left: 8rpx solid #ff6b6b; +} + +.poem-item:last-child { + margin-bottom: 0; +} + +.poem-header { + display: flex; + flex-direction: column; + margin-bottom: 20rpx; +} + +.poem-title { + font-size: 28rpx; + font-weight: 600; + color: #333; + margin-bottom: 10rpx; + display: flex; + align-items: center; +} + +.poem-details { + margin-bottom: 15rpx; +} + +.poem-author { + font-size: 24rpx; + color: #666; + margin-bottom: 15rpx; +} + +.review-tag { + background-color: #ff6b6b; + color: white; + padding: 4rpx 16rpx; + border-radius: 20rpx; + font-size: 20rpx; + margin-left: 16rpx; + vertical-align: middle; +} + +.poem-meta { + display: flex; + flex-wrap: wrap; + gap: 20rpx; + margin-bottom: 20rpx; +} + +.meta-item { + font-size: 22rpx; + color: #666; + background-color: #f5f5f5; + padding: 6rpx 16rpx; + border-radius: 24rpx; +} + +.meta-item.retention-rate { + background-color: #e8f5e9; + color: #388e3c; +} + +.meta-item.next-review { + background-color: #e3f2fd; + color: #1976d2; +} + +.poem-stats { + font-size: 24rpx; + color: #999; + margin-bottom: 10rpx; +} + +/* 操作按钮 */ +.action-buttons { + display: flex; + justify-content: space-between; + gap: 20rpx; + margin-top: 10rpx; +} + +.study-btn, .recite-btn { + flex: 1; + font-size: 24rpx; + padding: 16rpx 0; + margin: 0; + border-radius: 40rpx; + border: none; +} + +.study-btn { + background-color: #f0f0f0; + color: #333; +} + +.recite-btn { + background-color: #4CAF50; + color: white; +} + +/* 今日复习统计 */ +.today-summary { + margin-top: 30rpx; + padding: 20rpx; + background-color: #f8f9fa; + border-radius: 16rpx; + text-align: center; +} + +.today-count { + font-size: 28rpx; + color: #555; +} + +.today-count .highlight { + color: #ff6b6b; + font-weight: bold; + font-size: 36rpx; +} + +/* 空状态 */ +.empty-state { + text-align: center; + padding: 60rpx 0; + color: #999; +} + +.empty-state .hint { + margin-top: 20rpx; + font-size: 26rpx; + color: #bbb; +} \ No newline at end of file diff --git a/pages/search/search.js b/pages/search/search.js index 4c1333a..0ff533b 100644 --- a/pages/search/search.js +++ b/pages/search/search.js @@ -5,14 +5,22 @@ Page({ * 页面的初始数据 */ data: { - + keyword: '', + showResults: false, + searchResults: [], + searchHistory: [], + isLoading: false, + hasMore: true, + page: 1, + pageSize: 10, + total: 0 }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { - + this.loadSearchHistory(); }, /** @@ -26,7 +34,246 @@ Page({ * 生命周期函数--监听页面显示 */ onShow() { + this.loadSearchHistory(); + }, + + // 从本地存储加载搜索历史 + loadSearchHistory() { + const history = wx.getStorageSync('searchHistory') || []; + this.setData({ + searchHistory: history + }); + }, + + // 输入处理 + onInput(e) { + const value = e.detail.value; + this.setData({ + keyword: value + }); + + // 如果输入为空,隐藏结果 + if (!value.trim()) { + this.setData({ + showResults: false, + searchResults: [] + }); + } + }, + + // 清空输入框 + clearInput() { + this.setData({ + keyword: '', + showResults: false, + searchResults: [] + }); + }, + + // 执行搜索 + async doSearch() { + const { keyword, page } = this.data; + + if (!keyword.trim()) { + wx.showToast({ + title: '请输入搜索关键词', + icon: 'none' + }); + return; + } + + // 显示加载状态 + if (page === 1) { + this.setData({ + isLoading: true + }); + } + + try { + // 调用云函数搜索 + const result = await wx.cloud.callFunction({ + name: 'poemManagement', + data: { + action: 'searchPoems', + keyword: keyword.trim(), + page: page, + pageSize: this.data.pageSize + } + }); + + if (result.result.success) { + const { poems, total } = result.result.data; + + const newResults = page === 1 ? poems : [...this.data.searchResults, ...poems]; + + this.setData({ + searchResults: newResults, + showResults: true, + total: total, + hasMore: (page * this.data.pageSize) < total, + isLoading: false + }); + + // 添加到搜索历史 + this.addToHistory(keyword.trim()); + + // 显示搜索结果提示 + if (page === 1 && poems.length > 0) { + wx.showToast({ + title: `找到 ${total} 条结果`, + icon: 'success', + duration: 1500 + }); + } + } else { + wx.showToast({ + title: result.result.message || '搜索失败', + icon: 'none' + }); + this.setData({ isLoading: false }); + + // 如果云函数失败,使用模拟数据作为备选 + this.useMockData(keyword); + } + } catch (error) { + console.error('搜索错误:', error); + wx.showToast({ + title: '搜索失败,请检查网络', + icon: 'none' + }); + this.setData({ isLoading: false }); + + // 如果云函数调用失败,使用模拟数据作为备选 + this.useMockData(keyword); + } + }, + + // 使用模拟数据(备选方案) + useMockData(keyword) { + const mockPoems = [ + { + _id: '1', + title: '静夜思', + author: '李白', + dynasty: '唐代', + content: '床前明月光,疑是地上霜。举头望明月,低头思故乡。' + }, + { + _id: '2', + title: '望庐山瀑布', + author: '李白', + dynasty: '唐代', + content: '日照香炉生紫烟,遥看瀑布挂前川。飞流直下三千尺,疑是银河落九天。' + }, + { + _id: '3', + title: '早发白帝城', + author: '李白', + dynasty: '唐代', + content: '朝辞白帝彩云间,千里江陵一日还。两岸猿声啼不住,轻舟已过万重山。' + }, + { + _id: '4', + title: '春晓', + author: '孟浩然', + dynasty: '唐代', + content: '春眠不觉晓,处处闻啼鸟。夜来风雨声,花落知多少。' + }, + { + _id: '5', + title: '登鹳雀楼', + author: '王之涣', + dynasty: '唐代', + content: '白日依山尽,黄河入海流。欲穷千里目,更上一层楼。' + }, + ]; + + // 过滤搜索结果 + const results = mockPoems.filter(poem => + poem.title.includes(keyword) || + poem.author.includes(keyword) || + poem.content.includes(keyword) || + poem.dynasty.includes(keyword) + ); + + this.setData({ + searchResults: results, + showResults: true, + total: results.length, + hasMore: false, + isLoading: false + }); + + // 添加到搜索历史 + this.addToHistory(keyword); + }, + + // 通过历史记录搜索 + searchByHistory(e) { + const keyword = e.currentTarget.dataset.keyword; + this.setData({ + keyword: keyword, + page: 1, + searchResults: [], + hasMore: true + }); + this.doSearch(); + }, + + // 添加到搜索历史 + addToHistory(keyword) { + let { searchHistory } = this.data; + // 移除已存在的相同关键词 + searchHistory = searchHistory.filter(item => item !== keyword); + // 添加到最前面 + searchHistory.unshift(keyword); + // 限制历史记录数量 + if (searchHistory.length > 10) { + searchHistory = searchHistory.slice(0, 10); + } + // 保存到本地存储 + wx.setStorageSync('searchHistory', searchHistory); + this.setData({ + searchHistory: searchHistory + }); + }, + // 清除搜索历史 + clearHistory() { + wx.showModal({ + title: '确认清除', + content: '确定要清除所有搜索历史吗?', + success: (res) => { + if (res.confirm) { + wx.removeStorageSync('searchHistory'); + this.setData({ + searchHistory: [] + }); + } + } + }); + }, + + // 跳转到学习页面 + goToStudy(e) { + const poem = e.currentTarget.dataset.poem; + if (poem && poem._id) { + wx.navigateTo({ + url: `/pages/study/study?id=${poem._id}` + }); + } else { + const id = e.currentTarget.dataset.id; + if (id) { + wx.navigateTo({ + url: `/pages/study/study?id=${id}` + }); + } else { + wx.showToast({ + title: '诗歌信息错误', + icon: 'none' + }); + } + } }, /** @@ -47,14 +294,32 @@ Page({ * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh() { - + this.setData({ + page: 1, + searchResults: [], + hasMore: true + }); + + if (this.data.keyword.trim()) { + this.doSearch().then(() => { + wx.stopPullDownRefresh(); + }); + } else { + wx.stopPullDownRefresh(); + } }, /** * 页面上拉触底事件的处理函数 */ onReachBottom() { - + if (this.data.hasMore && !this.data.isLoading) { + this.setData({ + page: this.data.page + 1 + }, () => { + this.doSearch(); + }); + } }, /** diff --git a/pages/search/search.wxml b/pages/search/search.wxml index 836f6be..c8da72a 100644 --- a/pages/search/search.wxml +++ b/pages/search/search.wxml @@ -1,2 +1,98 @@ -pages/search/search.wxml \ No newline at end of file + + + + + + + + + + 搜索 + + + + + + 搜索中... + + + + + + 搜索历史 + 清除 + + + + {{item}} + + + + + + + 请输入关键词搜索古诗 + 支持搜索古诗名、作者、诗句内容 + + + + + + 搜索结果 ({{total}}) + + + + + + {{item.title}} + + {{item.author}} + {{item.dynasty}} + + {{item.content}} + + + 学习 + + + + + + 🔍 + 没有找到相关古诗 + 换个关键词试试吧 + + + + + 点击加载更多 + 已加载 {{searchResults.length}} / {{total}} 条 + + + + + 没有更多数据了 + + + + \ No newline at end of file diff --git a/pages/search/search.wxss b/pages/search/search.wxss index ab78402..b34eb94 100644 --- a/pages/search/search.wxss +++ b/pages/search/search.wxss @@ -1 +1,302 @@ -/* pages/search/search.wxss */ \ No newline at end of file +/* pages/search/search.wxss */ +.search-container { + min-height: 100vh; + background-color: #f8f9fa; + padding: 20rpx; +} + +/* 搜索栏样式 */ +.search-bar { + display: flex; + align-items: center; + gap: 20rpx; + margin-bottom: 30rpx; +} + +.search-input-wrapper { + flex: 1; + position: relative; + background: #ffffff; + border-radius: 50rpx; + padding: 20rpx 30rpx; + box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.08); +} + +.search-input { + width: 100%; + font-size: 28rpx; + color: #333; +} + +.clear-btn { + position: absolute; + right: 30rpx; + top: 50%; + transform: translateY(-50%); + width: 40rpx; + height: 40rpx; + background: #f0f0f0; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + color: #999; + font-size: 24rpx; +} + +.search-btn { + background: #07c160; + color: white; + padding: 20rpx 40rpx; + border-radius: 50rpx; + font-size: 28rpx; + font-weight: 500; + white-space: nowrap; +} + +/* 加载状态 */ +.loading-section { + display: flex; + flex-direction: column; + align-items: center; + padding: 80rpx 0; +} + +.loading-spinner { + width: 60rpx; + height: 60rpx; + border: 4rpx solid #f0f0f0; + border-top: 4rpx solid #07c160; + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 20rpx; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.loading-text { + font-size: 28rpx; + color: #666; +} + +/* 搜索历史 */ +.history-section { + background: white; + border-radius: 20rpx; + padding: 30rpx; + margin-bottom: 20rpx; +} + +.history-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 25rpx; +} + +.history-title { + font-size: 30rpx; + font-weight: 600; + color: #333; +} + +.clear-history { + font-size: 26rpx; + color: #07c160; +} + +.history-tags { + display: flex; + flex-wrap: wrap; + gap: 20rpx; +} + +.history-tag { + background: #f8f9fa; + padding: 16rpx 30rpx; + border-radius: 30rpx; + font-size: 26rpx; + color: #333; + border: 1rpx solid #e9ecef; +} + +.history-tag:active { + background: #e9ecef; +} + +/* 空状态 */ +.empty-section { + text-align: center; + padding: 120rpx 40rpx; +} + +.empty-text { + display: block; + font-size: 30rpx; + color: #666; + margin-bottom: 15rpx; +} + +.empty-subtext { + display: block; + font-size: 26rpx; + color: #999; +} + +/* 搜索结果 */ +.results-section { + background: white; + border-radius: 20rpx; + overflow: hidden; +} + +.results-header { + padding: 30rpx; + border-bottom: 1rpx solid #f0f0f0; +} + +.results-title { + font-size: 30rpx; + font-weight: 600; + color: #333; + display: block; +} + +.results-list { + padding: 0; +} + +.result-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 30rpx; + border-bottom: 1rpx solid #f8f9fa; + transition: background-color 0.2s; +} + +.result-item:active { + background-color: #f8f9fa; +} + +.result-item:last-child { + border-bottom: none; +} + +.poem-info { + flex: 1; +} + +.poem-title { + font-size: 32rpx; + font-weight: 600; + color: #333; + margin-bottom: 12rpx; +} + +.poem-meta { + display: flex; + align-items: center; + gap: 20rpx; + margin-bottom: 15rpx; +} + +.poem-author { + font-size: 26rpx; + color: #07c160; + font-weight: 500; +} + +.poem-dynasty { + font-size: 24rpx; + color: #999; + background: #f8f9fa; + padding: 4rpx 12rpx; + border-radius: 12rpx; +} + +.poem-content { + font-size: 26rpx; + color: #666; + line-height: 1.5; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + overflow: hidden; +} + +.study-btn { + background: #07c160; + color: white; + padding: 15rpx 25rpx; + border-radius: 20rpx; + font-size: 24rpx; + font-weight: 500; + white-space: nowrap; + margin-left: 20rpx; +} + +/* 空结果状态 */ +.empty-results { + text-align: center; + padding: 80rpx 40rpx; +} + +.empty-icon { + font-size: 80rpx; + display: block; + margin-bottom: 20rpx; +} + +.empty-text { + display: block; + font-size: 30rpx; + color: #666; + margin-bottom: 10rpx; +} + +.empty-subtext { + display: block; + font-size: 26rpx; + color: #999; +} + +/* 加载更多 */ +.load-more { + text-align: center; + padding: 40rpx; + background: #f8f9fa; + margin: 20rpx; + border-radius: 15rpx; +} + +.load-more:active { + background: #e9ecef; +} + +.load-more-text { + display: block; + font-size: 28rpx; + color: #07c160; + margin-bottom: 10rpx; +} + +.load-more-tips { + display: block; + font-size: 24rpx; + color: #999; +} + +/* 没有更多数据 */ +.no-more { + text-align: center; + padding: 30rpx; + color: #999; + font-size: 26rpx; + background: #f8f9fa; + margin: 20rpx; + border-radius: 15rpx; +} \ No newline at end of file diff --git a/pages/study/study.js b/pages/study/study.js index fe324fa..6c575e8 100644 --- a/pages/study/study.js +++ b/pages/study/study.js @@ -1,66 +1,418 @@ -// pages/all.js +// pages/study/study.js +const innerAudioContext = wx.createInnerAudioContext() Page({ - - /** - * 页面的初始数据 - */ data: { - + poemTitle: '加载中...', + poetInfo: '', + originalText: '', + translationText: '', + backgroundInfo: '', + showTranslation: false, + showBackground: false, + poem: null, + isLoading: true, + authorInfo: '', + loadError: false, + poemType: '', + token: '' }, - /** - * 生命周期函数--监听页面加载 - */ onLoad(options) { + console.log('学习页面参数:', options); + this.options = options; + + // 初始化语音上下文事件监听 + this.initAudioEvents(); + + // 获取token + this.getToken(); + + if (options.poemData) { + // 从首页传递的完整诗歌数据 + try { + const poemData = decodeURIComponent(options.poemData); + const poem = JSON.parse(poemData); + console.log('解析后的诗歌数据:', poem); + this.processPoemData(poem); + } catch (error) { + console.error('解析诗歌数据失败:', error); + this.showError('数据解析失败'); + } + } else if (options.id) { + // 根据ID从数据库加载诗词数据 + console.log('通过ID加载诗歌:', options.id); + this.loadPoemFromDatabase(options.id); + } else { + this.showError('缺少诗歌信息'); + } + }, + + // 初始化音频事件监听 + initAudioEvents() { + innerAudioContext.onPlay(() => { + console.log('开始播放语音'); + }); + + innerAudioContext.onStop(() => { + console.log('停止播放语音'); + }); + + innerAudioContext.onEnded(() => { + console.log('语音播放结束'); + }); + + innerAudioContext.onError((res) => { + console.error('语音播放错误:', res); + wx.showToast({ + title: '语音播放失败', + icon: 'none' + }); + }); + }, + + // 获取token(复用recite.js中的逻辑) + getToken() { + let that = this; + wx.getStorage({ + key: 'expires_in', + success(res) { + console.log("缓存中有access_token"); + console.log("token失效时间:", res.data); + const newT = new Date().getTime(); + // 用当前时间和存储的时间判断,token是否已过期 + if (newT > parseInt(res.data)) { + console.log("token过期,重新获取token"); + that.fetchNewToken(); + } else { + console.log("获取本地缓存的token"); + that.setData({ + token: wx.getStorageSync('access_token') + }); + } + }, fail() { + console.log("缓存中没有access_token,直接获取新token"); + // 尝试从storage直接获取token + const token = wx.getStorageSync('access_token'); + if (token) { + that.setData({ token: token }); + } else { + // 直接获取新token,不再依赖背诵功能初始化 + that.fetchNewToken(); + } + } + }); + }, + + // 获取新token + fetchNewToken() { + let that = this; + let ApiKey = 'qdHcePu7v0WpIlJnaeGJZZqp'; + let SecretKey = 'nuZCuBziZoO2gjE6NGEMKCdxKs4sbaNq'; + const url = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=' + ApiKey + '&client_secret=' + SecretKey; + wx.request({ + url: url, + method: 'POST', + success(res) { + console.log("创建access_token成功", res); + // 将access_token存储到storage中 + wx.setStorage({ + key: 'access_token', + data: res.data.access_token + }); + var date = new Date().getTime(); + let time = date + 2592000 * 1000; + console.log('三十天后的时间', time); + wx.setStorage({ + key: 'expires_in', + data: time + }); + that.setData({ + token: res.data.access_token + }); + }, + fail(err) { + console.error('获取token失败:', err); + wx.showToast({ + title: '语音服务初始化失败', + icon: 'none' + }); + } + }); + }, + + // 语音合成播放函数 + playstart(text) { + let that = this; + if (!that.data.token) { + wx.showToast({ + title: '语音服务未初始化', + icon: 'none' + }); + return; + } + + console.log("开始语音合成", text); + // 对文本进行URL编码 + const encodedText = encodeURIComponent(text); + + innerAudioContext.src = 'https://tsn.baidu.com/text2audio?lan=zh&ctp=1&cuid=12_56&tok=' + that.data.token + '&tex=' + encodedText + '&vol=10&per=111&spd=5&pit=5&aue=3'; + innerAudioContext.play(); + + wx.showToast({ + title: '开始朗读', + icon: 'success', + duration: 1000 + }); + }, + // 从数据库加载诗歌数据 + async loadPoemFromDatabase(id) { + try { + console.log('开始从数据库加载诗歌,ID:', id); + + wx.showLoading({ + title: '加载中...', + }); + + const db = wx.cloud.database(); + const result = await db.collection('poeties').doc(id).get(); + + wx.hideLoading(); + + console.log('数据库查询结果:', result); + + if (result.data) { + this.processPoemData(result.data); + } else { + this.showError('诗歌不存在'); + } + } catch (error) { + wx.hideLoading(); + console.error('数据库查询失败:', error); + + // 如果直接查询失败,尝试使用云函数 + this.loadPoemFromCloudFunction(id); + } }, - /** - * 生命周期函数--监听页面初次渲染完成 - */ - onReady() { + // 云函数加载(备用方案) + async loadPoemFromCloudFunction(id) { + try { + console.log('尝试通过云函数加载诗歌,ID:', id); + + const result = await wx.cloud.callFunction({ + name: 'getPoemDetail', + data: { id: id } + }); - }, + console.log('云函数返回结果:', result); - /** - * 生命周期函数--监听页面显示 - */ - onShow() { + if (result.result && result.result.success) { + const poem = result.result.data; + this.processPoemData(poem); + } else { + this.showError(result.result?.message || '诗歌不存在'); + } + } catch (error) { + console.error('调用云函数失败:', error); + + } }, - /** - * 生命周期函数--监听页面隐藏 - */ - onHide() { + + // 处理诗歌数据 + processPoemData(poem) { + console.log('处理诗歌数据:', poem); + + // 设置页面数据 + this.setData({ + poem: poem, + poemTitle: poem.title || '未知标题', + poetInfo: this.formatPoetInfo(poem), + originalText: poem.content || '暂无内容', + translationText: poem.translation || '暂无译文', + backgroundInfo: poem.background || '暂无背景信息', + authorInfo: poem.author_info ? poem.author_info.intro : (poem.author ? `暂无${poem.author}的详细信息` : '暂无作者信息'), + poemType: poem.type || '诗', + isLoading: false, + loadError: false + }); + + // 设置导航栏标题 + wx.setNavigationBarTitle({ + title: poem.title || '古诗学习' + }); }, - /** - * 生命周期函数--监听页面卸载 - */ - onUnload() { + // 格式化作者信息 + formatPoetInfo(poem) { + let info = ''; + if (poem.dynasty) { + info += poem.dynasty; + } + if (poem.author) { + info += (info ? ' • ' : '') + poem.author; + } + return info || '未知信息'; + }, + // 切换译文显示状态 + toggleTranslation() { + this.setData({ + showTranslation: !this.data.showTranslation + }); + }, + + // 切换背景信息显示状态 + toggleBackground() { + this.setData({ + showBackground: !this.data.showBackground + }); }, - /** - * 页面相关事件处理函数--监听用户下拉动作 - */ - onPullDownRefresh() { + // 显示错误信息 + showError(message) { + this.setData({ + isLoading: false, + loadError: true, + poemTitle: '加载失败', + originalText: message + }); + + wx.showToast({ + title: message, + icon: 'none', + duration: 2000 + }); + }, + // 重新加载 + reloadData() { + const options = this.options || {}; + if (options.id) { + this.setData({ isLoading: true, loadError: false }); + this.loadPoemFromDatabase(options.id); + } else { + wx.navigateBack(); + } }, - /** - * 页面上拉触底事件的处理函数 - */ - onReachBottom() { + // 复制诗歌内容 + copyContent() { + const content = this.data.originalText; + wx.setClipboardData({ + data: content, + success: () => { + wx.showToast({ + title: '已复制到剪贴板', + icon: 'success' + }); + } + }); + }, + // 语音播报功能(支持不同类型内容的朗读) + speakPoem(e) { + // 获取要朗读的内容类型 + const contentType = e?.currentTarget?.dataset?.type || 'all'; + let textToSpeak = ''; + let title = ''; + + switch(contentType) { + case 'content': + textToSpeak = this.data.originalText; + title = '朗读原文'; + break; + case 'translation': + textToSpeak = this.data.translationText; + title = '朗读译文'; + break; + case 'background': + textToSpeak = this.data.backgroundInfo; + title = '朗读背景'; + break; + case 'author': + textToSpeak = this.data.authorInfo; + title = '朗读作者简介'; + break; + default: + // 默认朗读全部内容(包括题目、作者、原文、译文、背景、作者简介) + textToSpeak = `${this.data.poemTitle},${this.data.poetInfo},${this.data.originalText},${this.data.translationText},${this.data.backgroundInfo},${this.data.authorInfo}`; + title = '语音播报'; + } + + console.log(`准备朗读${contentType}内容:`, textToSpeak); + + // 调用语音合成播放函数 + this.playstart(textToSpeak); }, - /** - * 用户点击右上角分享 - */ + // 分享功能 onShareAppMessage() { + const poem = this.data.poem; + if (poem && poem._id) { + return { + title: `${poem.title} - ${poem.author}`, + path: `/pages/study/study?id=${poem._id}` + }; + } + return { + title: `${this.data.poemTitle}`, + path: '/pages/study/study' + }; + }, + onReady() { + // 可以在这里添加动画效果等 + }, + + onShow() { + // 页面显示时的逻辑 + }, + + onHide() { + + }, + + onUnload() { + + }, + + onPullDownRefresh() { + const options = this.options || {}; + if (options.poemData) { + // 如果是传递完整数据,不需要重新加载 + wx.stopPullDownRefresh(); + } else if (options.id) { + this.loadPoemFromDatabase(options.id).then(() => { + wx.stopPullDownRefresh(); + }); + } else { + wx.stopPullDownRefresh(); + } + }, + + onReachBottom() { + // 可以在这里添加加载更多相关内容 + }, + + // 跳转到背诵页面 + goToRecite() { + const poem = this.data.poem; + if (poem && poem._id) { + console.log('跳转到背诵页面,诗歌ID:', poem._id); + // 将诗歌数据编码后传递给背诵页面 + const poemData = encodeURIComponent(JSON.stringify(poem)); + wx.navigateTo({ + url: `/pages/recite/recite?id=${poem._id}&poemData=${poemData}` + }); + } else { + wx.showToast({ + title: '背诵功能暂不可用', + icon: 'none' + }); + } } }) \ No newline at end of file diff --git a/pages/study/study.wxml b/pages/study/study.wxml index 9a8ac45..428fa23 100644 --- a/pages/study/study.wxml +++ b/pages/study/study.wxml @@ -1,2 +1,124 @@ - -pages/all.wxml \ No newline at end of file + + + + + + + 诗歌加载中... + + + + + + + + 加载失败 + {{originalText}} + + + + + + + + + + {{poemTitle}} + + {{poetInfo}} + {{poemType}} + + + + + + + + + + + + + 诗歌原文 + + + + + + + + {{originalText}} + + + + + + + + 诗歌译文 + + + + + {{showTranslation ? '收起' : '展开'}} + {{showTranslation ? '▲' : '▼'}} + + + + {{translationText}} + + + + + + + + 创作背景 + + + + + {{showBackground ? '收起' : '展开'}} + {{showBackground ? '▲' : '▼'}} + + + + {{backgroundInfo}} + + + + + + + + + 作者简介 + + + + + + {{authorInfo}} + + + + + + + + + \ No newline at end of file diff --git a/pages/study/study.wxss b/pages/study/study.wxss index 2f7da79..0466732 100644 --- a/pages/study/study.wxss +++ b/pages/study/study.wxss @@ -1 +1,350 @@ -/* pages/all.wxss */ \ No newline at end of file +/* pages/study/study.wxss */ + +/* 页面容器 */ +.study-container { + min-height: 100vh; + background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); + padding: 20rpx; + box-sizing: border-box; +} + +/* 加载状态 */ +.loading-state { + display: flex; + justify-content: center; + align-items: center; + height: 70vh; +} + +.loading-content { + display: flex; + flex-direction: column; + align-items: center; +} + +.loading-icon { + width: 120rpx; + height: 120rpx; + margin-bottom: 30rpx; +} + +.loading-text { + font-size: 32rpx; + color: #666; +} + +/* 错误状态 */ +.error-state { + display: flex; + justify-content: center; + align-items: center; + height: 70vh; +} + +.error-content { + display: flex; + flex-direction: column; + align-items: center; + text-align: center; + padding: 0 60rpx; +} + +.error-icon { + width: 150rpx; + height: 150rpx; + margin-bottom: 30rpx; + opacity: 0.7; +} + +.error-title { + font-size: 36rpx; + font-weight: bold; + color: #ff6b6b; + margin-bottom: 20rpx; +} + +.error-desc { + font-size: 28rpx; + color: #999; + margin-bottom: 50rpx; + line-height: 1.6; +} + +.btn-retry { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border: none; + border-radius: 50rpx; + padding: 20rpx 60rpx; + font-size: 30rpx; + box-shadow: 0 4rpx 15rpx rgba(102, 126, 234, 0.4); +} + +/* 诗歌详情样式 */ +.poem-detail { + padding-bottom: 40rpx; +} + +/* 卡片通用样式 */ +.header-card, +.content-card { + background: white; + border-radius: 20rpx; + box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.08); + margin-bottom: 30rpx; + overflow: hidden; + transition: all 0.3s ease; +} + +.content-card:active { + transform: translateY(-4rpx); + box-shadow: 0 12rpx 40rpx rgba(0, 0, 0, 0.12); +} + +/* 头部卡片 */ +.header-card { + padding: 40rpx 30rpx; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + text-align: center; +} + +/* 操作按钮组 */ +.action-buttons { + display: flex; + justify-content: flex-end; + margin-top: 20rpx; + gap: 20rpx; +} + +.btn-icon { + font-size: 28rpx; + margin-right: 8rpx; +} + +.header-actions { + display: flex; + gap: 10rpx; +} + +/* 文本区域语音播报按钮样式 */ +.btn-speak-text { + margin-top: 20rpx; + font-size: 28rpx; + padding: 0 20rpx; + align-self: flex-start; +} + +/* 小喇叭图标按钮样式 */ +.btn-speak-icon { + margin-left: 8px; + padding: 0; + width: 30px; + height: 30px; + line-height: 30px; + display: flex; + align-items: center; + justify-content: center; + min-width: 30px; +} + +.poem-title { + display: block; + font-size: 48rpx; + font-weight: bold; + margin-bottom: 20rpx; + text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1); +} + +.poem-meta { + display: flex; + justify-content: center; + align-items: center; + flex-wrap: wrap; +} + +.poet-info { + font-size: 30rpx; + opacity: 0.9; + margin-right: 20rpx; +} + +.poem-type-tag { + background: rgba(255, 255, 255, 0.2); + padding: 8rpx 20rpx; + border-radius: 30rpx; + font-size: 24rpx; + backdrop-filter: blur(10rpx); +} + +/* 内容卡片内部样式 */ +.content-card { + padding: 30rpx; +} + +.card-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 25rpx; +} + +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 0; +} + +.section-title-wrapper { + display: flex; + align-items: center; +} + +.section-icon { + width: 36rpx; + height: 36rpx; + margin-right: 15rpx; +} + +.card-title { + font-size: 34rpx; + font-weight: bold; + color: #333; +} + +.toggle-wrapper { + display: flex; + align-items: center; +} + +.toggle-text { + font-size: 26rpx; + color: #666; + margin-right: 10rpx; +} + +.toggle-icon { + font-size: 24rpx; + color: #999; +} + +/* 复制按钮 */ +.btn-copy { + display: flex; + align-items: center; + background: #f8f9fa; + border: 1rpx solid #e9ecef; + border-radius: 30rpx; + padding: 12rpx 24rpx; + font-size: 24rpx; + color: #666; +} + +.btn-speak { + font-size: 28rpx; + padding: 0 20rpx; +} + +.copy-icon { + width: 24rpx; + height: 24rpx; + margin-right: 8rpx; +} + +/* 诗歌内容 */ +.original-text { + padding: 10rpx 0; +} + +.poem-content { + font-size: 36rpx; + line-height: 1.8; + color: #2c3e50; + text-align: center; + white-space: pre-line; +} + +/* 译文内容 */ +.translation-text { + padding-top: 25rpx; + border-top: 1rpx solid #f1f3f4; +} + +.translation-content { + font-size: 30rpx; + line-height: 1.7; + color: #555; + white-space: pre-line; +} + +/* 背景信息 */ +.background-text { + padding-top: 25rpx; + border-top: 1rpx solid #f1f3f4; +} + +.background-content { + font-size: 30rpx; + line-height: 1.7; + color: #555; + white-space: pre-line; +} + +/* 作者信息 */ +.author-text { + padding-top: 10rpx; +} + +.author-content { + font-size: 30rpx; + line-height: 1.7; + color: #555; + white-space: pre-line; + margin-bottom: 16px; /* 恢复正常边距 */ +} + +/* 底部背诵按钮容器 */ +.bottom-container { + margin: 20px; + margin-bottom: 30px; +} + +/* 背诵按钮样式 */ +.recite-button { + width: 100%; + height: 50px; + background-color: #07c160; + color: #fff; + border-radius: 25px; + font-size: 18px; + font-weight: 600; + line-height: 50px; + padding: 0; + box-shadow: 0 4px 12px rgba(7, 193, 96, 0.3); +} + +.recite-button:active { + background-color: #06ad56; + box-shadow: 0 2px 6px rgba(7, 193, 96, 0.4); +} + +/* 响应式调整 */ +@media (max-width: 480px) { + .study-container { + padding: 15rpx; + } + + .header-card, + .content-card { + border-radius: 15rpx; + } + + .poem-title { + font-size: 42rpx; + } + + .poem-content { + font-size: 32rpx; + } +} \ No newline at end of file diff --git a/pages/textbookFilter/textbookFilter.js b/pages/textbookFilter/textbookFilter.js deleted file mode 100644 index 27d8f6d..0000000 --- a/pages/textbookFilter/textbookFilter.js +++ /dev/null @@ -1,66 +0,0 @@ -// pages/textbookFilter/textbookFilter.js -Page({ - - /** - * 页面的初始数据 - */ - data: { - - }, - - /** - * 生命周期函数--监听页面加载 - */ - onLoad(options) { - - }, - - /** - * 生命周期函数--监听页面初次渲染完成 - */ - onReady() { - - }, - - /** - * 生命周期函数--监听页面显示 - */ - onShow() { - - }, - - /** - * 生命周期函数--监听页面隐藏 - */ - onHide() { - - }, - - /** - * 生命周期函数--监听页面卸载 - */ - onUnload() { - - }, - - /** - * 页面相关事件处理函数--监听用户下拉动作 - */ - onPullDownRefresh() { - - }, - - /** - * 页面上拉触底事件的处理函数 - */ - onReachBottom() { - - }, - - /** - * 用户点击右上角分享 - */ - onShareAppMessage() { - - } -}) \ No newline at end of file diff --git a/pages/textbookFilter/textbookFilter.json b/pages/textbookFilter/textbookFilter.json deleted file mode 100644 index 8835af0..0000000 --- a/pages/textbookFilter/textbookFilter.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "usingComponents": {} -} \ No newline at end of file diff --git a/pages/textbookFilter/textbookFilter.wxml b/pages/textbookFilter/textbookFilter.wxml deleted file mode 100644 index 79f5a3d..0000000 --- a/pages/textbookFilter/textbookFilter.wxml +++ /dev/null @@ -1,2 +0,0 @@ - -pages/textbookFilter/textbookFilter.wxml \ No newline at end of file diff --git a/pages/textbookFilter/textbookFilter.wxss b/pages/textbookFilter/textbookFilter.wxss deleted file mode 100644 index 0a28b1c..0000000 --- a/pages/textbookFilter/textbookFilter.wxss +++ /dev/null @@ -1 +0,0 @@ -/* pages/textbookfilter/textbookfilter.wxss */ \ No newline at end of file diff --git a/project.config.json b/project.config.json index 6ddbc3b..e0a5224 100644 --- a/project.config.json +++ b/project.config.json @@ -5,6 +5,7 @@ "minified": true, "uglifyFileName": false, "enhance": true, + "packNpmManually": false, "packNpmRelationList": [], "babelSetting": { "ignore": [], @@ -12,7 +13,15 @@ "outputPath": "" }, "useCompilerPlugins": false, - "minifyWXML": true + "minifyWXML": true, + "compileWorklet": false, + "uploadWithSourceMap": true, + "minifyWXSS": true, + "localPlugins": false, + "disableUseStrict": false, + "condition": false, + "swc": false, + "disableSWC": true }, "compileType": "miniprogram", "simulatorPluginLibVersion": {}, @@ -21,5 +30,8 @@ "include": [] }, "appid": "wx60a2f42279236d44", - "editorSetting": {} + "editorSetting": {}, + "libVersion": "3.10.2", + "cloudfunctionRoot": "cloudfunctions/", + "cloudfunctionTemplateRoot": "cloudfunctionTemplate/" } \ No newline at end of file diff --git a/project.private.config.json b/project.private.config.json index 75f724c..495197f 100644 --- a/project.private.config.json +++ b/project.private.config.json @@ -1,48 +1,42 @@ { - "libVersion": "3.10.2", - "projectname": "miniprogram-1", - "setting": { - "urlCheck": false, - "coverView": true, - "lazyloadPlaceholderEnable": false, - "skylineRenderEnable": false, - "preloadBackgroundData": false, - "autoAudits": false, - "showShadowRootInWxmlPanel": true, - "compileHotReLoad": true - }, - "condition": { - "miniprogram": { - "list": [ - { - "name": "pages/login/login", - "pathName": "pages/login/login", - "query": "", - "scene": null, - "launchMode": "default" - }, - { - "name": "pages/guiding/guiding", - "pathName": "pages/guiding/guiding", - "query": "", - "launchMode": "default", - "scene": null - }, - { - "name": "pages/search/search", - "pathName": "pages/search/search", - "query": "", - "launchMode": "default", - "scene": null - }, - { - "name": "pages/home/home", - "pathName": "pages/home/home", - "query": "", - "launchMode": "default", - "scene": null + "libVersion": "3.10.2", + "projectname": "miniprogram-2", + "setting": { + "urlCheck": false, + "coverView": true, + "lazyloadPlaceholderEnable": false, + "skylineRenderEnable": false, + "preloadBackgroundData": false, + "autoAudits": false, + "showShadowRootInWxmlPanel": true, + "compileHotReLoad": true, + "useApiHook": true, + "useApiHostProcess": true, + "useStaticServer": false, + "useLanDebug": false, + "showES6CompileOption": false, + "checkInvalidKey": true, + "ignoreDevUnusedFiles": true, + "bigPackageSizeSupport": false + }, + "condition": { + "miniprogram": { + "list": [ + { + "name": "pages/question/question", + "pathName": "pages/question/question", + "query": "", + "scene": null, + "launchMode": "default" + }, + { + "name": "pages/managePoems/managePoems", + "pathName": "pages/managePoems/managePoems", + "query": "", + "launchMode": "default", + "scene": null + } + ] } - ] } - } } \ No newline at end of file