feat(student-plan): 添加完成学案功能
- 新增 FinishStudentPlanReqVO 类用于请求参数封装 - 学生端学习计划页面新增“完成”按钮及其交互状态 - 实现 finishLessonPlan API 调用,用于标记学案完成 - 后端新增 finishStudentPlan 接口,处理学案完成逻辑 - StudentLessonPlansDOMapper 增加 finfishStudentPlan 方法及对应 SQL 更新语句 - StudentLessonPlansService 添加 finishStudentLessonPlan 接口实现统计记忆单词数并更新学案状态 - VocabularyBankDOMapper 和 WordMasteryLogDOMapper 增加相关统计查询方法和 SQL - 前端完善完成按钮状态和操作反馈,防止重复提交
This commit is contained in:
@@ -5,12 +5,14 @@ import com.yinlihupo.enlish.service.domain.dataobject.StudentLessonPlansDO;
|
||||
import com.yinlihupo.enlish.service.model.bo.StudentDetail;
|
||||
import com.yinlihupo.enlish.service.model.vo.plan.FindStudentPlansReqVO;
|
||||
import com.yinlihupo.enlish.service.model.vo.plan.FindStudentPlansRspVO;
|
||||
import com.yinlihupo.enlish.service.model.vo.plan.FinishStudentPlanReqVO;
|
||||
import com.yinlihupo.enlish.service.model.vo.plan.LessonPlanItem;
|
||||
import com.yinlihupo.enlish.service.service.LessonPlansService;
|
||||
import com.yinlihupo.enlish.service.service.StudentLessonPlansService;
|
||||
import com.yinlihupo.enlish.service.service.StudentService;
|
||||
import com.yinlihupo.framework.biz.operationlog.aspect.ApiOperationLog;
|
||||
import com.yinlihupo.framework.common.response.PageResponse;
|
||||
import com.yinlihupo.framework.common.response.Response;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
@@ -74,4 +76,17 @@ public class StudentLessonPlansController {
|
||||
|
||||
return PageResponse.success(findStudentPlansRspVOList, page, studentLessonPlanTotal, size);
|
||||
}
|
||||
|
||||
@PostMapping("/finish")
|
||||
@ApiOperationLog(description = "完成学案")
|
||||
public Response<String> finishStudentPlan(@RequestBody FinishStudentPlanReqVO finishStudentPlanReqVO) {
|
||||
Integer studentId = finishStudentPlanReqVO.getStudentId();
|
||||
Integer planId = finishStudentPlanReqVO.getPlanId();
|
||||
int lessonPlan = studentLessonPlansService.finishStudentLessonPlan(studentId, planId);
|
||||
|
||||
if (lessonPlan > 0) {
|
||||
return Response.success("完成学案成功");
|
||||
}
|
||||
return Response.fail("完成学案失败");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,4 +12,6 @@ public interface StudentLessonPlansDOMapper {
|
||||
List<StudentLessonPlansDO> selectStudentLessonPlanList(@Param("startIndex") Integer startIndex, @Param("pageSize") Integer pageSize, @Param("name") String name);
|
||||
|
||||
Integer selectStudentPlanTotal();
|
||||
|
||||
Integer finfishStudentPlan(@Param("studentId") Integer studentId, @Param("planId") Integer planId, @Param("count") Integer count, @Param("mastery") double mastery);
|
||||
}
|
||||
@@ -20,4 +20,6 @@ public interface VocabularyBankDOMapper {
|
||||
List<VocabularyBankDO> selectVocabularyBankListStudentNotMaster(@Param("gradeId") Integer gradeId, @Param("studentId") Integer studentId);
|
||||
|
||||
List<VocabularyBankDO> selectVocabularyBankListSelfCheck(@Param("gradeId") Integer gradeId, @Param("studentId") Integer studentId, @Param("ids") List<Integer> ids, @Param("wordCount") Integer wordCount);
|
||||
|
||||
Integer selectWordTotal();
|
||||
}
|
||||
@@ -14,4 +14,6 @@ public interface WordMasteryLogDOMapper {
|
||||
int batchInsertInitialization(@Param("wordIds") List<Integer> wordIds, @Param("studentId") Integer studentId);
|
||||
|
||||
int batchUpdateStudentMastery(@Param("wordMasteryLogDOs") List<WordMasteryLogDO> wordMasteryLogDOs);
|
||||
|
||||
int selectStudentStrengthCount(@Param("studentId") Integer studentId);
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package com.yinlihupo.enlish.service.model.vo.plan;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Builder
|
||||
@Data
|
||||
public class FinishStudentPlanReqVO {
|
||||
|
||||
private Integer studentId;
|
||||
private Integer planId;
|
||||
}
|
||||
@@ -9,4 +9,6 @@ public interface StudentLessonPlansService {
|
||||
List<StudentLessonPlansDO> findStudentLessonPlansDOList(Integer page, Integer size, String name);
|
||||
|
||||
Integer findStudentLessonPlanTotal();
|
||||
|
||||
int finishStudentLessonPlan(Integer studentId, Integer planId);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package com.yinlihupo.enlish.service.service.plan;
|
||||
|
||||
import com.yinlihupo.enlish.service.domain.dataobject.StudentLessonPlansDO;
|
||||
import com.yinlihupo.enlish.service.domain.mapper.StudentLessonPlansDOMapper;
|
||||
import com.yinlihupo.enlish.service.domain.mapper.VocabularyBankDOMapper;
|
||||
import com.yinlihupo.enlish.service.domain.mapper.WordMasteryLogDOMapper;
|
||||
import com.yinlihupo.enlish.service.service.StudentLessonPlansService;
|
||||
import jakarta.annotation.Resource;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -15,6 +17,10 @@ public class StudentLessonPlansServiceImpl implements StudentLessonPlansService
|
||||
|
||||
@Resource
|
||||
private StudentLessonPlansDOMapper studentLessonPlansDOMapper;
|
||||
@Resource
|
||||
private WordMasteryLogDOMapper wordMasteryLogDOMapper;
|
||||
@Resource
|
||||
private VocabularyBankDOMapper vocabularyBankDOMapper;
|
||||
|
||||
|
||||
@Override
|
||||
@@ -30,4 +36,12 @@ public class StudentLessonPlansServiceImpl implements StudentLessonPlansService
|
||||
public Integer findStudentLessonPlanTotal() {
|
||||
return studentLessonPlansDOMapper.selectStudentPlanTotal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int finishStudentLessonPlan(Integer studentId, Integer planId) {
|
||||
int wordStrengthCount = wordMasteryLogDOMapper.selectStudentStrengthCount(studentId);
|
||||
Integer wordTotal = vocabularyBankDOMapper.selectWordTotal();
|
||||
|
||||
return studentLessonPlansDOMapper.finfishStudentPlan(studentId, planId, wordStrengthCount, (double) wordStrengthCount / wordTotal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
ORDER BY slp_in.student_id
|
||||
LIMIT #{startIndex}, #{pageSize}
|
||||
) AS temp ON slp.student_id = temp.student_id
|
||||
where slp.is_finished = 0
|
||||
ORDER BY slp.id
|
||||
</select>
|
||||
|
||||
@@ -45,4 +46,12 @@
|
||||
FROM student_lesson_plans;
|
||||
</select>
|
||||
|
||||
<update id="finfishStudentPlan">
|
||||
update student_lesson_plans
|
||||
set is_finished = 1,
|
||||
total_count = #{count},
|
||||
mastery_rat = #{mastery}
|
||||
where student_id = #{studentId}
|
||||
and plan_id = #{planId}
|
||||
</update>
|
||||
</mapper>
|
||||
@@ -117,5 +117,9 @@
|
||||
</if>
|
||||
limit #{wordCount}
|
||||
</select>
|
||||
<select id="selectWordTotal" resultType="java.lang.Integer">
|
||||
select count(*)
|
||||
from vocabulary_bank
|
||||
</select>
|
||||
|
||||
</mapper>
|
||||
@@ -22,6 +22,12 @@
|
||||
order by memory_strength desc
|
||||
limit #{limit}
|
||||
</select>
|
||||
<select id="selectStudentStrengthCount" resultType="java.lang.Integer">
|
||||
select count(*)
|
||||
from word_mastery_log
|
||||
where student_id = #{studentId}
|
||||
and memory_strength > 0
|
||||
</select>
|
||||
|
||||
<insert id="batchInsertInitialization">
|
||||
insert into word_mastery_log (student_id, word_id, update_time)
|
||||
|
||||
@@ -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
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user