From ec78c47b3dc3c0d076c73048e666cb9624d81d86 Mon Sep 17 00:00:00 2001 From: taiyi Date: Sun, 19 Apr 2026 10:04:00 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=80=E5=A7=8B=E8=A1=A5=E5=85=A8=E5=90=8E?= =?UTF-8?q?=E7=AB=AF=E4=B8=8E=E5=89=8D=E7=AB=AF=E4=BA=A4=E4=BA=92=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- batch-upload/batch-upload.js | 32 +++++++++++++- checkin-detail/checkin-detail.js | 15 ++++++- entry-edit/entry-edit.js | 39 ++++++++++++++++- index/index.js | 17 ++++++++ me/me.js | 27 +++++++++--- progress-list/progress-list.js | 24 ++++++++++- review-config/review-config.js | 42 +++++++++++++----- review-session/review-session.js | 74 +++++++++++++++++++------------- settings/settings.js | 27 +++++++++++- vocab-manage/vocab-manage.js | 32 +++++++++++++- 10 files changed, 275 insertions(+), 54 deletions(-) diff --git a/batch-upload/batch-upload.js b/batch-upload/batch-upload.js index ba76804..f0a245e 100644 --- a/batch-upload/batch-upload.js +++ b/batch-upload/batch-upload.js @@ -1 +1,31 @@ -Page({}) +const app = getApp() + +Page({ + data: { + result: null, + fileName: '', + }, + chooseFile() { + wx.chooseMessageFile({ + count: 1, + type: 'file', + success: (res) => { + const file = res.tempFiles[0] + this.setData({ fileName: file.name }) + wx.uploadFile({ + url: `${app.globalData.baseUrl}/api/v1/entries/upload-file`, + filePath: file.path, + name: 'file', + header: { 'X-OpenID': app.globalData.openid || '' }, + success: (uploadRes) => { + try { + this.setData({ result: JSON.parse(uploadRes.data) }) + } catch (e) { + this.setData({ result: { total: 0, success: 0, failed: 0 } }) + } + }, + }) + }, + }) + }, +}) diff --git a/checkin-detail/checkin-detail.js b/checkin-detail/checkin-detail.js index ba76804..294bce6 100644 --- a/checkin-detail/checkin-detail.js +++ b/checkin-detail/checkin-detail.js @@ -1 +1,14 @@ -Page({}) +const app = getApp() + +Page({ + data: { + stats: null, + }, + onShow() { + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/checkin/stats`, + header: { 'X-OpenID': app.globalData.openid || '' }, + success: (res) => this.setData({ stats: res.data }), + }) + }, +}) diff --git a/entry-edit/entry-edit.js b/entry-edit/entry-edit.js index ba76804..8df9f45 100644 --- a/entry-edit/entry-edit.js +++ b/entry-edit/entry-edit.js @@ -1 +1,38 @@ -Page({}) +const app = getApp() + +Page({ + data: { + entryType: 'word', + enText: '', + zhText: '', + exampleText: '', + }, + goBack() { + wx.navigateBack() + }, + onEnInput(e) { + this.setData({ enText: e.detail.value }) + }, + onZhInput(e) { + this.setData({ zhText: e.detail.value }) + }, + onExampleInput(e) { + this.setData({ exampleText: e.detail.value }) + }, + save() { + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/entries`, + method: 'POST', + header: { 'Content-Type': 'application/json', 'X-OpenID': app.globalData.openid || '' }, + data: { + entry_type: this.data.entryType, + en_text: this.data.enText, + zh_text: this.data.zhText, + example_text: this.data.exampleText, + source_type: 'manual', + upload_date: new Date().toISOString().slice(0, 10), + }, + success: () => wx.showToast({ title: '已保存', icon: 'success' }), + }) + }, +}) diff --git a/index/index.js b/index/index.js index b5c42e9..c96df21 100644 --- a/index/index.js +++ b/index/index.js @@ -1,4 +1,21 @@ +const app = getApp() + Page({ + data: { + stats: { total_entries: 0, review_count: 0, mastered_count: 0, checkin_count: 0, review_records: 0 }, + }, + onShow() { + this.loadStats() + }, + loadStats() { + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/home/stats`, + header: { 'X-OpenID': app.globalData.openid || '' }, + success: (res) => { + if (res.data) this.setData({ stats: res.data }) + }, + }) + }, goToReview() { wx.navigateTo({ url: '/pages/review-config/review-config' }) }, diff --git a/me/me.js b/me/me.js index 6001614..2d1a3a6 100644 --- a/me/me.js +++ b/me/me.js @@ -5,13 +5,28 @@ Page({ name: '', days: 0, badges: 0, + openid: '', }, - onLoad() { - const { userInfo } = app.globalData - this.setData({ - name: userInfo.name, - days: userInfo.days, - badges: userInfo.badges, + onShow() { + this.loadProfile() + }, + loadProfile() { + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/auth/wx-login`, + method: 'POST', + data: { code: app.globalData.wxCode || 'dev-code' }, + success: (res) => { + app.globalData.openid = res.data.openid + this.setData({ openid: res.data.openid, name: '考研搭子' }) + }, + }) + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/achievements`, + header: { 'X-OpenID': app.globalData.openid || '' }, + success: (res) => { + const badges = (res.data || []).filter((i) => i.is_unlocked).length + this.setData({ badges }) + }, }) }, goTo(e) { diff --git a/progress-list/progress-list.js b/progress-list/progress-list.js index ba76804..33bf5bb 100644 --- a/progress-list/progress-list.js +++ b/progress-list/progress-list.js @@ -1 +1,23 @@ -Page({}) +const app = getApp() + +Page({ + data: { + reviewList: [], + masteredList: [], + }, + onShow() { + this.loadData() + }, + loadData() { + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/progress/review`, + header: { 'X-OpenID': app.globalData.openid || '' }, + success: (res) => this.setData({ reviewList: res.data || [] }), + }) + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/progress/mastered`, + header: { 'X-OpenID': app.globalData.openid || '' }, + success: (res) => this.setData({ masteredList: res.data || [] }), + }) + }, +}) diff --git a/review-config/review-config.js b/review-config/review-config.js index d03b298..cfca36a 100644 --- a/review-config/review-config.js +++ b/review-config/review-config.js @@ -2,7 +2,7 @@ const app = getApp() Page({ data: { - timeRanges: ['今日', '本周', '自定义区间'], + timeRanges: ['今日', '本周', '本月', '自定义区间'], activeTimeRange: 0, contentTypes: ['单词', '句子'], activeContentType: 0, @@ -52,19 +52,39 @@ Page({ this.persistPatch({ shuffle }) }, onQuestionCountInput(e) { - const questionCount = e.detail.value + const questionCount = Number(e.detail.value || 0) this.setData({ questionCount }) this.persistPatch({ questionCount }) }, startReview() { - app.globalData.reviewSession = { - deck: [], - currentIndex: 0, - correctCount: 0, - wrongCount: 0, - completed: false, - currentAnswer: '', - } - wx.navigateTo({ url: '/pages/review-session/review-session' }) + const scopeTypeMap = ['today', 'week', 'month', 'custom'] + const contentTypeMap = ['word', 'sentence'] + const questionModeMap = ['A', 'B', 'C'] + const scope_type = scopeTypeMap[this.data.activeTimeRange] + const content_type = contentTypeMap[this.data.activeContentType] + const question_mode = questionModeMap[this.data.activeMode] + const today = new Date() + const yyyy = today.getFullYear() + const mm = String(today.getMonth() + 1).padStart(2, '0') + const dd = String(today.getDate()).padStart(2, '0') + const scope_config = scope_type === 'custom' ? { start_date: `${yyyy}-${mm}-${dd}`, end_date: `${yyyy}-${mm}-${dd}` } : {} + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/review/generate`, + method: 'POST', + header: { 'Content-Type': 'application/json', 'X-OpenID': app.globalData.openid || '' }, + data: { + scope_type, + scope_config, + content_type, + question_mode, + review_strategy: this.data.onlyReview ? 'review_only' : 'all', + sort_mode: this.data.shuffle ? 'shuffle' : 'sequential', + total_count: this.data.questionCount, + }, + success: (res) => { + app.globalData.reviewSessionMeta = res.data + wx.navigateTo({ url: '/pages/review-session/review-session' }) + }, + }) }, }) diff --git a/review-session/review-session.js b/review-session/review-session.js index 023d05d..ba86933 100644 --- a/review-session/review-session.js +++ b/review-session/review-session.js @@ -1,13 +1,5 @@ const app = getApp() -const deckTemplate = [ - { word: 'prosperity', meaning: 'n. 繁荣, 兴旺', answer: 'pe' }, - { word: 'sustainable', meaning: 'adj. 可持续的', answer: 'sus' }, - { word: 'acquire', meaning: 'v. 获取, 获得', answer: 'ac' }, - { word: 'abstract', meaning: 'adj. 抽象的', answer: 'ab' }, - { word: 'benevolent', meaning: 'adj. 仁慈的', answer: 'be' }, -] - Page({ data: { progress: 0, @@ -20,22 +12,24 @@ Page({ showFeedback: false, completed: false, masterHint: false, + questions: [], }, onLoad() { - if (!app.globalData.reviewSession.deck.length) { - const { questionCount, shuffle } = app.globalData.reviewPlan - let deck = deckTemplate.slice(0, Math.max(1, Math.min(questionCount, deckTemplate.length))) - if (shuffle) deck = deck.slice().sort(() => Math.random() - 0.5) - app.globalData.reviewSession = { - deck, - currentIndex: 0, - correctCount: 0, - wrongCount: 0, - completed: false, - currentAnswer: '', - } - } - this.syncSession() + this.loadQuestions() + }, + loadQuestions() { + const session = app.globalData.reviewSessionMeta + if (!session) return + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/review/questions?session_id=${session.id}`, + header: { 'X-OpenID': app.globalData.openid || '' }, + success: (res) => { + const questions = res.data || [] + app.globalData.reviewSession = { deck: questions, currentIndex: 0, correctCount: 0, wrongCount: 0, completed: false, currentAnswer: '' } + this.setData({ questions }) + this.syncSession() + }, + }) }, syncSession() { const session = app.globalData.reviewSession @@ -45,8 +39,8 @@ Page({ progress: Math.round((session.currentIndex / total) * 100), current: session.currentIndex + 1, total, - word: current?.word || '', - meaning: current?.meaning || '', + word: current?.prompt || '', + meaning: current?.answer_hint || '', answer: session.currentAnswer || '', feedback: '', showFeedback: false, @@ -63,12 +57,25 @@ Page({ const session = app.globalData.reviewSession const current = session.deck[session.currentIndex] if (!current) return - const correct = (this.data.answer || '').trim().toLowerCase() === current.answer.toLowerCase() - session.correctCount += correct ? 1 : 0 - session.wrongCount += correct ? 0 : 1 - this.setData({ - feedback: correct ? '回答正确' : `正确答案:${current.answer}`, - showFeedback: true, + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/review/submit`, + method: 'POST', + header: { 'Content-Type': 'application/json', 'X-OpenID': app.globalData.openid || '' }, + data: { + session_id: app.globalData.reviewSessionMeta.id, + entry_id: current.entry_id, + question_mode: current.question_mode, + user_answer: this.data.answer, + }, + success: (res) => { + const result = res.data || {} + session.correctCount += result.is_correct ? 1 : 0 + session.wrongCount += result.is_correct ? 0 : 1 + this.setData({ + feedback: result.is_correct ? '回答正确' : `正确答案:${result.correct_answer}`, + showFeedback: true, + }) + }, }) }, nextQuestion() { @@ -76,7 +83,12 @@ Page({ if (!session.deck.length) return if (session.currentIndex >= session.deck.length - 1) { session.completed = true - wx.navigateTo({ url: '/pages/review-result/review-result' }) + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/review/finish?session_id=${app.globalData.reviewSessionMeta.id}`, + method: 'POST', + header: { 'X-OpenID': app.globalData.openid || '' }, + success: () => wx.navigateTo({ url: '/pages/review-result/review-result' }), + }) return } session.currentIndex += 1 diff --git a/settings/settings.js b/settings/settings.js index ba76804..0ef212d 100644 --- a/settings/settings.js +++ b/settings/settings.js @@ -1 +1,26 @@ -Page({}) +const app = getApp() + +Page({ + data: { + settings: null, + }, + onShow() { + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/settings`, + header: { 'X-OpenID': app.globalData.openid || '' }, + success: (res) => { + this.setData({ settings: res.data }) + }, + }) + }, + save() { + const settings = this.data.settings || {} + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/settings`, + method: 'PUT', + header: { 'Content-Type': 'application/json', 'X-OpenID': app.globalData.openid || '' }, + data: settings, + success: () => wx.showToast({ title: '已保存', icon: 'success' }), + }) + }, +}) diff --git a/vocab-manage/vocab-manage.js b/vocab-manage/vocab-manage.js index ba76804..77c0ae7 100644 --- a/vocab-manage/vocab-manage.js +++ b/vocab-manage/vocab-manage.js @@ -1 +1,31 @@ -Page({}) +const app = getApp() + +Page({ + data: { + list: [], + }, + onShow() { + this.loadList() + }, + loadList() { + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/entries`, + header: { 'X-OpenID': app.globalData.openid || '' }, + success: (res) => { + this.setData({ list: res.data || [] }) + }, + }) + }, + goAdd() { + wx.navigateTo({ url: '/pages/entry-edit/entry-edit' }) + }, + goBatch() { + wx.navigateTo({ url: '/pages/batch-upload/batch-upload' }) + }, + goProgress() { + wx.navigateTo({ url: '/pages/progress-list/progress-list' }) + }, + goSettings() { + wx.navigateTo({ url: '/pages/settings/settings' }) + }, +})