feat(student-plan): 添加完成学案功能

- 新增 FinishStudentPlanReqVO 类用于请求参数封装
- 学生端学习计划页面新增“完成”按钮及其交互状态
- 实现 finishLessonPlan API 调用,用于标记学案完成
- 后端新增 finishStudentPlan 接口,处理学案完成逻辑
- StudentLessonPlansDOMapper 增加 finfishStudentPlan 方法及对应 SQL 更新语句
- StudentLessonPlansService 添加 finishStudentLessonPlan 接口实现统计记忆单词数并更新学案状态
- VocabularyBankDOMapper 和 WordMasteryLogDOMapper 增加相关统计查询方法和 SQL
- 前端完善完成按钮状态和操作反馈,防止重复提交
This commit is contained in:
lbw
2025-12-17 17:17:49 +08:00
parent fd828442b1
commit 26674ab8a9
12 changed files with 114 additions and 2 deletions

View File

@@ -7,3 +7,10 @@ export function findStudentLessonPlans(page, size, name) {
name: name ?? ''
})
}
export function finishLessonPlan(studentId, planId) {
return axios.post('/studentLessonPlans/finish', {
studentId: studentId,
planId: planId
})
}

View File

@@ -28,7 +28,7 @@
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作" width="120" fixed="right">
<el-table-column label="操作" width="200" fixed="right">
<template #default="{ row: plan }">
<el-button
type="primary"
@@ -36,6 +36,14 @@
:loading="downloadingIds.includes(plan.id)"
@click="onDownload(plan)"
>下载</el-button>
<el-button
class="ml-2"
type="success"
size="small"
:disabled="plan.isFinished === 1"
:loading="finishingIds.includes(plan.id)"
@click="onFinish(row.id, plan.id, plan)"
>完成</el-button>
</template>
</el-table-column>
</el-table>
@@ -62,7 +70,7 @@
<script setup>
import Header from '@/layouts/components/Header.vue'
import { ref, onMounted } from 'vue'
import { findStudentLessonPlans } from '@/api/studentLessonPlans'
import { findStudentLessonPlans, finishLessonPlan } from '@/api/studentLessonPlans'
import { downloadLessonPlan } from '@/api/plan'
import { showMessage } from '@/composables/util'
@@ -74,6 +82,7 @@ const totalCount = ref(0)
const searchName = ref('')
const tableRef = ref(null)
const downloadingIds = ref([])
const finishingIds = ref([])
async function fetchLessonPlans() {
loading.value = true
@@ -124,6 +133,30 @@ async function onDownload(plan) {
}
}
async function onFinish(studentId, planId, plan) {
if (!studentId || !planId) {
showMessage('参数错误', 'error')
return
}
if (!finishingIds.value.includes(planId)) {
finishingIds.value = [...finishingIds.value, planId]
}
try {
const res = await finishLessonPlan(studentId, planId)
const d = res.data
if (d?.success !== false) {
plan.isFinished = 1
showMessage('已标记完成', 'success')
} else {
showMessage(d?.message || '标记失败', 'error')
}
} catch (e) {
showMessage('标记失败', 'error')
} finally {
finishingIds.value = finishingIds.value.filter(id => id !== planId)
}
}
onMounted(() => {
fetchLessonPlans()
})