开始补全后端与前端交互代码

This commit is contained in:
taiyi 2026-04-19 10:04:00 +08:00
parent 1c72434102
commit ec78c47b3d
10 changed files with 275 additions and 54 deletions

View File

@ -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 } })
}
},
})
},
})
},
})

View File

@ -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 }),
})
},
})

View File

@ -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' }),
})
},
})

View File

@ -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' })
},

View File

@ -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) {

View File

@ -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 || [] }),
})
},
})

View File

@ -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' })
},
})
},
})

View File

@ -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

View File

@ -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' }),
})
},
})

View File

@ -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' })
},
})