From 9da98e9c82b4f44c30ab58765698f4befe19b5b1 Mon Sep 17 00:00:00 2001 From: taiyi Date: Mon, 27 Apr 2026 15:42:58 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=A1=AB=E7=A9=BA=E5=A4=8D?= =?UTF-8?q?=E4=B9=A0=E5=8A=9F=E8=83=BD2.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- review-config/review-config.js | 58 ++++++++++++++++++++---------- review-session/review-session.js | 55 ++++++++++++++++++++++++++-- review-session/review-session.wxml | 16 ++++----- review-session/review-session.wxss | 2 +- 4 files changed, 100 insertions(+), 31 deletions(-) diff --git a/review-config/review-config.js b/review-config/review-config.js index 781b6b2..be521bf 100644 --- a/review-config/review-config.js +++ b/review-config/review-config.js @@ -69,25 +69,45 @@ Page({ const question_mode = questionModeMap[this.data.activeMode] const scope_config = {} this.setData({ loading: true, error: '' }) - 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.reviewOrder === 'shuffle' ? 'shuffle' : 'sequential', - total_count: this.data.questionCount, - }, - success: (res) => { - app.globalData.reviewSessionMeta = res.data?.data || null - wx.navigateTo({ url: '/pages/review-session/review-session' }) - }, - fail: () => this.setData({ error: '生成复习会话失败' }), - complete: () => this.setData({ loading: false }), + app.ensureLogin().then((openid) => { + if (!openid) { + this.setData({ loading: false, error: '请先登录后再开始复习' }) + return + } + wx.request({ + url: `${app.globalData.baseUrl}/api/v1/review/generate`, + method: 'POST', + header: { 'Content-Type': 'application/json', 'X-OpenID': openid }, + data: { + scope_type, + scope_config, + content_type, + question_mode, + review_strategy: this.data.onlyReview ? 'review_only' : 'all', + sort_mode: this.data.reviewOrder === 'shuffle' ? 'shuffle' : 'sequential', + total_count: this.data.questionCount, + }, + success: (res) => { + const session = res.data?.data || null + if (res.statusCode < 200 || res.statusCode >= 300 || !session?.id) { + const message = res.data?.detail || res.data?.message || '生成复习会话失败' + this.setData({ error: message }) + wx.showToast({ title: message, icon: 'none' }) + return + } + if (!session.record_ids?.length) { + const message = '当前条件下没有可复习题目,请切换时间范围或关闭仅复习' + this.setData({ error: message }) + wx.showToast({ title: message, icon: 'none' }) + return + } + app.globalData.reviewSessionMeta = session + wx.setStorageSync('reviewSessionMeta', session) + wx.navigateTo({ url: '/pages/review-session/review-session' }) + }, + fail: () => this.setData({ error: '生成复习会话失败' }), + complete: () => this.setData({ loading: false }), + }) }) }, goHome() { diff --git a/review-session/review-session.js b/review-session/review-session.js index 729b1a2..840df68 100644 --- a/review-session/review-session.js +++ b/review-session/review-session.js @@ -36,6 +36,7 @@ Page({ currentClozeQuestion: null, currentClozeResults: [], showClozeFeedback: false, + clozeSegments: [], }, submitting: false, judged: false, @@ -61,17 +62,55 @@ Page({ }, }) }, + buildClozeSegments(clozeQuestion) { + if (!clozeQuestion || !Array.isArray(clozeQuestion.blanks)) return [] + const prompt = clozeQuestion.prompt_text || '' + const segments = [] + let blankIndex = 0 + if (prompt.includes('____')) { + prompt.split('____').forEach((text, index, parts) => { + if (text) segments.push({ type: 'text', text, index: `text-${index}` }) + if (index < parts.length - 1) { + segments.push({ type: 'blank', blankIndex, index: `blank-${blankIndex}` }) + blankIndex += 1 + } + }) + return segments + } + + const blanks = clozeQuestion.blanks || [] + let cursor = 0 + blanks.forEach((blank, idx) => { + const start = Math.max(0, Number(blank.start || 0)) + const end = Math.max(start, Number(blank.end || start + 1)) + if (start > cursor) { + segments.push({ type: 'text', text: prompt.slice(cursor, start), index: `text-${idx}` }) + } + segments.push({ type: 'blank', blankIndex: idx, index: `blank-${idx}` }) + cursor = end + }) + if (cursor < prompt.length) { + segments.push({ type: 'text', text: prompt.slice(cursor), index: `text-tail` }) + } + return segments + }, loadQuestions() { - const session = app.globalData.reviewSessionMeta - if (!session) { + const session = app.globalData.reviewSessionMeta || wx.getStorageSync('reviewSessionMeta') + if (!session?.id) { this.setData({ error: '暂无复习会话' }) return } + app.globalData.reviewSessionMeta = session this.setData({ loading: true, error: '' }) wx.request({ url: `${app.globalData.baseUrl}/api/v1/review/questions?session_id=${session.id}`, header: { 'X-OpenID': app.globalData.openid || '' }, success: (res) => { + if (res.statusCode < 200 || res.statusCode >= 300) { + const message = res.data?.detail || res.data?.message || '题目加载失败' + this.setData({ error: message, questions: [] }) + return + } const questions = (res.data?.data || []).map((item) => { if (item.question_mode === 'C') { return { @@ -85,6 +124,10 @@ Page({ entry_type: item.entry_type || 'word', } }) + if (!questions.length) { + this.setData({ error: '当前复习会话没有题目,请返回重新选择范围', questions: [] }) + return + } app.globalData.reviewSession = { deck: questions, currentIndex: 0, @@ -115,7 +158,7 @@ Page({ word: isCloze ? (current?.blank_prompt || clozeQuestion?.prompt_text || current?.prompt || '') : (current?.prompt || ''), meaning: isCloze ? (current?.answer_hint || '') : '', answer: session.currentAnswer || '', - clozeAnswers: isCloze ? (session.currentAnswers || []) : [], + clozeAnswers: isCloze ? (Array.isArray(session.currentAnswers) ? session.currentAnswers : Array.from({ length: currentClozeQuestion?.blanks?.length || 0 }, () => '')) : [], feedback: '', revealAnswer: '', feedbackType: '', @@ -128,6 +171,7 @@ Page({ currentClozeQuestion: clozeQuestion, currentClozeResults: session.lastClozeResults || [], showClozeFeedback: false, + clozeSegments: isCloze ? this.buildClozeSegments(clozeQuestion) : [], }) }, onAnswerInput(e) { @@ -202,6 +246,10 @@ Page({ showClozeFeedback: clozeResults.length > 0, currentClozeResults: clozeResults, }) + if (this.data.isCloze) { + app.globalData.reviewSession.currentAnswers = [] + this.setData({ clozeAnswers: [] }) + } if (this.data.settings.autoNextQuestion || advanceAfterSubmit) { setTimeout(() => this.nextQuestion(), shouldShowAnswer ? 1200 : 0) } @@ -239,6 +287,7 @@ Page({ } session.currentIndex += 1 session.currentAnswer = '' + session.currentAnswers = [] this.syncSession() }, markMastered() { diff --git a/review-session/review-session.wxml b/review-session/review-session.wxml index b2a7e9d..12e9e5e 100644 --- a/review-session/review-session.wxml +++ b/review-session/review-session.wxml @@ -10,7 +10,7 @@ 暂无题目 - 请先生成复习会话 + {{error || '请先生成复习会话'}} @@ -23,14 +23,14 @@ - {{word}} - - - 空 {{blankIndex + 1}} - 提示:首字母 {{blank.hint.first_letter}} · 长度 {{blank.hint.length}} - - + + + {{segment.text}} + + + {{word}} + {{word}} diff --git a/review-session/review-session.wxss b/review-session/review-session.wxss index 98c4827..74b4cd8 100644 --- a/review-session/review-session.wxss +++ b/review-session/review-session.wxss @@ -1 +1 @@ -page{background:#0c0e12;color:#f6f6fc}.page{min-height:100vh;background:#0c0e12}.topbar{display:flex;justify-content:space-between;align-items:center;padding:24rpx 32rpx;background:rgba(12,14,18,.8);border-bottom:1rpx solid rgba(255,255,255,.08);backdrop-filter:blur(24px);box-shadow:0 1rpx 20rpx rgba(0,0,0,.08)}.topbar-left{display:flex;align-items:center;gap:18rpx}.avatar-shell{width:80rpx;height:80rpx;border-radius:9999rpx;overflow:hidden;border:2rpx solid rgba(193,156,255,.2);flex-shrink:0}.avatar-img{width:100%;height:100%}.brand-text{font-size:38rpx;font-weight:800;color:#c19cff}.topbar-icon{width:72rpx;height:72rpx;border-radius:9999rpx;background:rgba(255,255,255,.06);display:flex;align-items:center;justify-content:center}.content{height:calc(100vh - 120rpx);padding:32rpx;box-sizing:border-box}.progress-box{margin-bottom:28rpx}.progress-head{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:16rpx}.progress-label{font-size:24rpx;color:#aaabb0}.progress-count{font-size:28rpx;font-weight:700;color:#00e3fd}.progress-total{color:#aaabb0;font-size:22rpx;font-weight:400}.progress-bar{height:12rpx;background:#23262c;border-radius:9999rpx;overflow:hidden}.ghost-border{border:1rpx solid rgba(255,255,255,.1)}.progress-fill{height:100%;background:linear-gradient(90deg,#c19cff,#00e3fd)}.glass-card{background:rgba(29,32,37,.4);backdrop-filter:blur(24rpx)}.question-card{position:relative;overflow:hidden;border-radius:32rpx;padding:40rpx 32rpx;text-align:center;box-shadow:0 20rpx 40rpx rgba(0,0,0,.4);border:1rpx solid rgba(255,255,255,.1)}.ambient-glow{position:absolute;inset:0;background:linear-gradient(to bottom,rgba(193,156,255,.05),transparent);pointer-events:none}.mode-tag-wrap{display:flex;justify-content:center;margin-bottom:20rpx}.mode-tag{display:inline-flex;align-items:center;gap:10rpx;padding:10rpx 22rpx;border-radius:9999rpx;background:rgba(193,156,255,.12);border:1rpx solid rgba(193,156,255,.18);color:#d8c7ff;font-size:22rpx;letter-spacing:2rpx}.meaning-wrap{margin-bottom:28rpx}.meaning{display:block;color:#aaabb0;font-size:26rpx;letter-spacing:2rpx}.cloze-wrap,.word-wrap{margin:14rpx 0 10rpx}.cloze,.word{display:block;font-size:58rpx;font-weight:800;letter-spacing:2rpx;line-height:1.25}.cloze{color:#f6f6fc}.word{color:#f6f6fc}.entry-type-hint{margin-top:14rpx;color:#8f9198;font-size:22rpx;line-height:1.6}.cloze-input-list{margin-top:28rpx;display:flex;flex-direction:column;gap:20rpx}.cloze-input-item{padding:20rpx 18rpx;border-radius:24rpx;background:rgba(255,255,255,.04);border:1rpx solid rgba(255,255,255,.08);text-align:left}.cloze-input-label{display:block;margin-bottom:12rpx;color:#d8c7ff;font-size:22rpx;font-weight:700;letter-spacing:1rpx}.cloze-hint{margin-bottom:12rpx;color:#8f9198;font-size:20rpx;line-height:1.5}.input-shell{margin:26rpx auto 0;max-width:520rpx;background:rgba(255,255,255,.04);border:1rpx solid rgba(255,255,255,.08);border-radius:9999rpx}.answer{padding:22rpx 28rpx;text-align:center;color:#f6f6fc;font-size:32rpx;caret-color:#c19cff}.cloze-answer{max-width:100%;background:rgba(12,14,18,.35);border-radius:18rpx;border:1rpx solid rgba(255,255,255,.08);text-align:left;padding:22rpx 24rpx;margin:0 4rpx}.answer::placeholder{color:rgba(170,171,176,.72)}.answer::-webkit-input-placeholder{color:rgba(170,171,176,.72)}.answer::-moz-placeholder{color:rgba(170,171,176,.72)}.answer:-ms-input-placeholder{color:rgba(170,171,176,.72)}.feedback-box{margin-top:22rpx;padding:20rpx 24rpx;border-radius:24rpx;background:rgba(255,255,255,.04);border:1rpx solid rgba(255,255,255,.06)}.feedback{display:block;color:#00e3fd}.reveal-answer{display:block;margin-top:10rpx;color:#f6f6fc;font-weight:700}.cloze-feedback-list{margin-top:18rpx;display:flex;flex-direction:column;gap:14rpx}.cloze-feedback-item{padding:18rpx 16rpx;border-radius:18rpx;background:rgba(255,255,255,.04);border:1rpx solid rgba(255,255,255,.06)}.cloze-feedback-title{display:block;margin-bottom:8rpx;font-size:22rpx;font-weight:700;color:#c19cff}.cloze-feedback-text{display:block;font-size:22rpx;line-height:1.55;color:#e8e9ee}.actions-cluster{display:flex;flex-direction:row;gap:18rpx;justify-content:center;align-items:center;margin-top:24rpx}.secondary-btn,.primary-btn{flex:1;border-radius:9999rpx;padding:24rpx 0;font-weight:700}.secondary-btn{background:#23262c;color:#f6f6fc}.primary-btn{background:linear-gradient(90deg,#c19cff,#9146ff);color:#fff}.master-action{margin-top:34rpx;text-align:center}.master-text{color:#aaabb0;font-size:22rpx;border-bottom:1rpx solid transparent}.master-text.active{color:#00e5fd;border-color:#00e5fd} +page{background:#0c0e12;color:#f6f6fc}.page{min-height:100vh;background:#0c0e12}.topbar{display:flex;justify-content:space-between;align-items:center;padding:24rpx 32rpx;background:rgba(12,14,18,.8);border-bottom:1rpx solid rgba(255,255,255,.08);backdrop-filter:blur(24px);box-shadow:0 1rpx 20rpx rgba(0,0,0,.08)}.topbar-left{display:flex;align-items:center;gap:18rpx}.avatar-shell{width:80rpx;height:80rpx;border-radius:9999rpx;overflow:hidden;border:2rpx solid rgba(193,156,255,.2);flex-shrink:0}.avatar-img{width:100%;height:100%}.brand-text{font-size:38rpx;font-weight:800;color:#c19cff}.topbar-icon{width:72rpx;height:72rpx;border-radius:9999rpx;background:rgba(255,255,255,.06);display:flex;align-items:center;justify-content:center}.content{height:calc(100vh - 120rpx);padding:32rpx;box-sizing:border-box}.progress-box{margin-bottom:28rpx}.progress-head{display:flex;justify-content:space-between;align-items:flex-end;margin-bottom:16rpx}.progress-label{font-size:24rpx;color:#aaabb0}.progress-count{font-size:28rpx;font-weight:700;color:#00e3fd}.progress-total{color:#aaabb0;font-size:22rpx;font-weight:400}.progress-bar{height:12rpx;background:#23262c;border-radius:9999rpx;overflow:hidden}.ghost-border{border:1rpx solid rgba(255,255,255,.1)}.progress-fill{height:100%;background:linear-gradient(90deg,#c19cff,#00e3fd)}.glass-card{background:rgba(29,32,37,.4);backdrop-filter:blur(24rpx)}.question-card{position:relative;overflow:hidden;border-radius:32rpx;padding:40rpx 32rpx;text-align:center;box-shadow:0 20rpx 40rpx rgba(0,0,0,.4);border:1rpx solid rgba(255,255,255,.1)}.ambient-glow{position:absolute;inset:0;background:linear-gradient(to bottom,rgba(193,156,255,.05),transparent);pointer-events:none}.mode-tag-wrap{display:flex;justify-content:center;margin-bottom:20rpx}.mode-tag{display:inline-flex;align-items:center;gap:10rpx;padding:10rpx 22rpx;border-radius:9999rpx;background:rgba(193,156,255,.12);border:1rpx solid rgba(193,156,255,.18);color:#d8c7ff;font-size:22rpx;letter-spacing:2rpx}.meaning-wrap{margin-bottom:28rpx}.meaning{display:block;color:#aaabb0;font-size:26rpx;letter-spacing:2rpx}.cloze-wrap,.word-wrap{margin:14rpx 0 10rpx}.cloze,.word{display:block;font-size:58rpx;font-weight:800;letter-spacing:2rpx;line-height:1.25}.cloze{color:#f6f6fc}.word{color:#f6f6fc}.entry-type-hint{margin-top:14rpx;color:#8f9198;font-size:22rpx;line-height:1.6}.inline-cloze{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;gap:12rpx;font-size:44rpx;font-weight:800;line-height:1.5;color:#f6f6fc}.cloze-segment-text{display:inline;white-space:pre-wrap}.inline-cloze-answer{display:inline-flex;width:180rpx;min-height:64rpx;padding:8rpx 14rpx;border-radius:16rpx;background:rgba(12,14,18,.45);border:1rpx solid rgba(193,156,255,.28);font-size:28rpx}.cloze-input-list{margin-top:28rpx;display:flex;flex-direction:column;gap:20rpx}.cloze-input-item{padding:20rpx 18rpx;border-radius:24rpx;background:rgba(255,255,255,.04);border:1rpx solid rgba(255,255,255,.08);text-align:left}.cloze-input-label{display:block;margin-bottom:12rpx;color:#d8c7ff;font-size:22rpx;font-weight:700;letter-spacing:1rpx}.cloze-hint{margin-bottom:12rpx;color:#8f9198;font-size:20rpx;line-height:1.5}.input-shell{margin:26rpx auto 0;max-width:520rpx;background:rgba(255,255,255,.04);border:1rpx solid rgba(255,255,255,.08);border-radius:9999rpx}.answer{padding:22rpx 28rpx;text-align:center;color:#f6f6fc;font-size:32rpx;caret-color:#c19cff}.cloze-answer{max-width:100%;background:rgba(12,14,18,.35);border-radius:18rpx;border:1rpx solid rgba(255,255,255,.08);text-align:left;padding:22rpx 24rpx;margin:0 4rpx}.answer::placeholder{color:rgba(170,171,176,.72)}.answer::-webkit-input-placeholder{color:rgba(170,171,176,.72)}.answer::-moz-placeholder{color:rgba(170,171,176,.72)}.answer:-ms-input-placeholder{color:rgba(170,171,176,.72)}.feedback-box{margin-top:22rpx;padding:20rpx 24rpx;border-radius:24rpx;background:rgba(255,255,255,.04);border:1rpx solid rgba(255,255,255,.06)}.feedback{display:block;color:#00e3fd}.reveal-answer{display:block;margin-top:10rpx;color:#f6f6fc;font-weight:700}.cloze-feedback-list{margin-top:18rpx;display:flex;flex-direction:column;gap:14rpx}.cloze-feedback-item{padding:18rpx 16rpx;border-radius:18rpx;background:rgba(255,255,255,.04);border:1rpx solid rgba(255,255,255,.06)}.cloze-feedback-title{display:block;margin-bottom:8rpx;font-size:22rpx;font-weight:700;color:#c19cff}.cloze-feedback-text{display:block;font-size:22rpx;line-height:1.55;color:#e8e9ee}.actions-cluster{display:flex;flex-direction:row;gap:18rpx;justify-content:center;align-items:center;margin-top:24rpx}.secondary-btn,.primary-btn{flex:1;border-radius:9999rpx;padding:24rpx 0;font-weight:700}.secondary-btn{background:#23262c;color:#f6f6fc}.primary-btn{background:linear-gradient(90deg,#c19cff,#9146ff);color:#fff}.master-action{margin-top:34rpx;text-align:center}.master-text{color:#aaabb0;font-size:22rpx;border-bottom:1rpx solid transparent}.master-text.active{color:#00e5fd;border-color:#00e5fd}