feat(exam): 添加按班级、年级、学生姓名筛选考试结果功能
- 在ExamWordsResultReqVO中新增classId、gradeId、studentName字段 - 修改ExamWordsJudgeService接口及实现,支持按筛选条件获取考试结果 - 在ExamWordsJudgeResultDOMapper中添加按学生ID列表分页查询方法 - 扩展StudentDOMapper,新增按班级、年级和姓名查询学生列表方法 - 修改ExamWordsController,支持从请求体接收筛选参数 - 修改前端exam.js,调用接口时传递筛选参数 - 在uploadpng.vue页面新增筛选表单,支持班级、年级、学生姓名输入 - 增加班级和年级选项数据的获取 - 实现筛选查询、重置功能及班级切换自动同步年级 - 在App.vue中配置Element Plus中文语言环境 - 调整配置文件,更新学习计划模板路径 - 修改接口权限配置,关闭plan/word/voice路径的鉴权
This commit is contained in:
@@ -25,9 +25,11 @@ public class SaTokenConfigure implements WebMvcConfigurer {
|
|||||||
|
|
||||||
SaRouter.match("/**")
|
SaRouter.match("/**")
|
||||||
.notMatch("/login/**")
|
.notMatch("/login/**")
|
||||||
|
.notMatch("plan/word/voice")
|
||||||
.check(r -> StpUtil.checkLogin());
|
.check(r -> StpUtil.checkLogin());
|
||||||
|
|
||||||
SaRouter.match("/admin/**")
|
SaRouter.match("/admin/**")
|
||||||
|
.notMatch("plan/word/voice")
|
||||||
.check(r -> StpUtil.checkRole("root"));
|
.check(r -> StpUtil.checkRole("root"));
|
||||||
|
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -107,8 +107,11 @@ public class ExamWordsController {
|
|||||||
PageResponse<ExamWordsResultRspVO> getExamWordsResult(@RequestBody ExamWordsResultReqVO examWordsResultReqVO) {
|
PageResponse<ExamWordsResultRspVO> getExamWordsResult(@RequestBody ExamWordsResultReqVO examWordsResultReqVO) {
|
||||||
Integer page = examWordsResultReqVO.getPage();
|
Integer page = examWordsResultReqVO.getPage();
|
||||||
Integer size = examWordsResultReqVO.getSize();
|
Integer size = examWordsResultReqVO.getSize();
|
||||||
|
Integer classId = examWordsResultReqVO.getClassId();
|
||||||
|
Integer gradeId = examWordsResultReqVO.getGradeId();
|
||||||
|
String studentName = examWordsResultReqVO.getStudentName();
|
||||||
Integer total = examWordsJudgeService.getExamWordsJudgeResultCount();
|
Integer total = examWordsJudgeService.getExamWordsJudgeResultCount();
|
||||||
List<ExamWordsJudgeResultDO> examWordsJudgeResult = examWordsJudgeService.getExamWordsJudgeResult(page, size);
|
List<ExamWordsJudgeResultDO> examWordsJudgeResult = examWordsJudgeService.getExamWordsJudgeResult(page, size, classId, gradeId, studentName);
|
||||||
List<ExamWordsResultRspVO> list = examWordsJudgeResult.stream().map(examWordsJudgeResultDO -> ExamWordsResultRspVO
|
List<ExamWordsResultRspVO> list = examWordsJudgeResult.stream().map(examWordsJudgeResultDO -> ExamWordsResultRspVO
|
||||||
.builder()
|
.builder()
|
||||||
.id(examWordsJudgeResultDO.getId())
|
.id(examWordsJudgeResultDO.getId())
|
||||||
|
|||||||
@@ -24,4 +24,6 @@ public interface ExamWordsJudgeResultDOMapper {
|
|||||||
List<ExamWordsJudgeResultDO> selectByStudentId(@Param("studentId") Integer studentId);
|
List<ExamWordsJudgeResultDO> selectByStudentId(@Param("studentId") Integer studentId);
|
||||||
|
|
||||||
List<ExamWordsJudgeResultDO> selectByStudentIdAndLimitTime(@Param("studentId") Integer studentId);
|
List<ExamWordsJudgeResultDO> selectByStudentIdAndLimitTime(@Param("studentId") Integer studentId);
|
||||||
|
|
||||||
|
List<ExamWordsJudgeResultDO> selectByPageAndStudentIds(@Param("startIndex") Integer startIndex, @Param("pageSize") Integer pageSize, @Param("studentIds") List<Integer> studentIds);
|
||||||
}
|
}
|
||||||
@@ -23,4 +23,10 @@ public interface StudentDOMapper {
|
|||||||
int selectStudentCountByClassId(@Param("classId") Integer classId);
|
int selectStudentCountByClassId(@Param("classId") Integer classId);
|
||||||
|
|
||||||
int updateStudentActualGradeId(@Param("studentId") Integer studentId, @Param("gradeId") Integer gradeId);
|
int updateStudentActualGradeId(@Param("studentId") Integer studentId, @Param("gradeId") Integer gradeId);
|
||||||
|
|
||||||
|
List<StudentDO> selectStudentDOListByClassId(@Param("classId") Integer classId);
|
||||||
|
|
||||||
|
List<StudentDO> selectStudentDOListByGradeId(@Param("gradeId") Integer gradeId);
|
||||||
|
|
||||||
|
List<StudentDO> selectStudentDOListByName(@Param("name") String name);
|
||||||
}
|
}
|
||||||
@@ -13,4 +13,8 @@ public class ExamWordsResultReqVO {
|
|||||||
|
|
||||||
private Integer page;
|
private Integer page;
|
||||||
private Integer size;
|
private Integer size;
|
||||||
|
|
||||||
|
private Integer classId;
|
||||||
|
private Integer gradeId;
|
||||||
|
private String studentName;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.yinlihupo.enlish.service.model.vo.student;
|
package com.yinlihupo.enlish.service.model.vo.student;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -16,5 +17,6 @@ public class AddStudentReqVO {
|
|||||||
private String name;
|
private String name;
|
||||||
private Integer classId;
|
private Integer classId;
|
||||||
private Integer gradeId;
|
private Integer gradeId;
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
|
||||||
private LocalDateTime createTime;
|
private LocalDateTime createTime;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public interface ExamWordsJudgeService {
|
|||||||
|
|
||||||
void judgeExamWords(int count);
|
void judgeExamWords(int count);
|
||||||
|
|
||||||
List<ExamWordsJudgeResultDO> getExamWordsJudgeResult(Integer page, Integer pageSize);
|
List<ExamWordsJudgeResultDO> getExamWordsJudgeResult(Integer page, Integer pageSize, Integer classId, Integer gradeId, String studentName);
|
||||||
|
|
||||||
Integer getExamWordsJudgeResultCount();
|
Integer getExamWordsJudgeResultCount();
|
||||||
|
|
||||||
|
|||||||
@@ -326,8 +326,24 @@ public class ExamWordsJudgeServiceImpl implements ExamWordsJudgeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<ExamWordsJudgeResultDO> getExamWordsJudgeResult(Integer page, Integer pageSize) {
|
public List<ExamWordsJudgeResultDO> getExamWordsJudgeResult(Integer page, Integer pageSize, Integer classId, Integer gradeId, String studentName) {
|
||||||
return examWordsJudgeResultDOMapper.selectByPage((page - 1) * pageSize, pageSize);
|
|
||||||
|
List<Integer> studentIds = new ArrayList<>();
|
||||||
|
if (classId != null) {
|
||||||
|
studentIds.addAll(studentDOMapper.selectStudentDOListByClassId(classId).stream().map(StudentDO::getId).toList());
|
||||||
|
}
|
||||||
|
if (gradeId != null) {
|
||||||
|
studentIds.addAll(studentDOMapper.selectStudentDOListByGradeId(gradeId).stream().map(StudentDO::getId).toList());
|
||||||
|
}
|
||||||
|
if (!studentName.isEmpty()) {
|
||||||
|
studentIds.addAll(studentDOMapper.selectStudentDOListByName(studentName).stream().map(StudentDO::getId).toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (studentIds.isEmpty()) {
|
||||||
|
return examWordsJudgeResultDOMapper.selectByPage((page - 1) * pageSize, pageSize);
|
||||||
|
} else {
|
||||||
|
return examWordsJudgeResultDOMapper.selectByPageAndStudentIds((page - 1) * pageSize, page * pageSize, studentIds);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ templates:
|
|||||||
count: 100
|
count: 100
|
||||||
data: C:\project\tess
|
data: C:\project\tess
|
||||||
plan:
|
plan:
|
||||||
weekday: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\templates\tem_study_plan_v5.docx
|
weekday: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\templates\tem_study_plan_v6.docx
|
||||||
weekend: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\templates\study_plan_review_v2.docx
|
weekend: C:\project\java\enlish_edu\enlish\enlish-service\src\main\resources\templates\study_plan_review_v2.docx
|
||||||
plan_day: 7
|
plan_day: 7
|
||||||
tmp:
|
tmp:
|
||||||
|
|||||||
@@ -83,4 +83,16 @@
|
|||||||
and start_date between date_sub(now(), interval 7 day) and now()
|
and start_date between date_sub(now(), interval 7 day) and now()
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectByPageAndStudentIds" resultMap="BaseResultMap">
|
||||||
|
select *
|
||||||
|
from exam_words_judge_result
|
||||||
|
where student_id in
|
||||||
|
<foreach item="item" index="index" collection="studentIds"
|
||||||
|
open="(" separator="," close=")">
|
||||||
|
#{item}
|
||||||
|
</foreach>
|
||||||
|
order by start_date
|
||||||
|
limit #{startIndex}, #{pageSize}
|
||||||
|
</select>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
@@ -75,4 +75,24 @@
|
|||||||
where class_id = #{classId}
|
where class_id = #{classId}
|
||||||
and is_deleted = 0
|
and is_deleted = 0
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<select id="selectStudentDOListByClassId" resultMap="BaseResultMap">
|
||||||
|
select *
|
||||||
|
from student
|
||||||
|
where class_id = #{classId}
|
||||||
|
and is_deleted = 0
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectStudentDOListByGradeId" resultMap="BaseResultMap">
|
||||||
|
select *
|
||||||
|
from student
|
||||||
|
where grade_id = #{gradeId}
|
||||||
|
and is_deleted = 0
|
||||||
|
</select>
|
||||||
|
<select id="selectStudentDOListByName" resultMap="BaseResultMap">
|
||||||
|
select *
|
||||||
|
from student
|
||||||
|
where name like concat('%', #{name}, '%')
|
||||||
|
and is_deleted = 0
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
Binary file not shown.
@@ -56,8 +56,8 @@ public class ExamWordsJudgeServiceTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void selectExamWordsJudgeResult() {
|
public void selectExamWordsJudgeResult() {
|
||||||
List<ExamWordsJudgeResultDO> examWordsJudgeResult = examWordsJudgeService.getExamWordsJudgeResult(1, 10);
|
// List<ExamWordsJudgeResultDO> examWordsJudgeResult = examWordsJudgeService.getExamWordsJudgeResult(1, 10);
|
||||||
log.info("examWordsJudgeResult:{}", examWordsJudgeResult);
|
// log.info("examWordsJudgeResult:{}", examWordsJudgeResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test
|
// @Test
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
|
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<router-view></router-view>
|
<el-config-provider :locale="locale">
|
||||||
|
<router-view />
|
||||||
|
</el-config-provider>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import zhCn from 'element-plus/es/locale/lang/zh-cn'
|
||||||
|
const locale = zhCn
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|||||||
@@ -5,10 +5,13 @@ export function uploadExamWordsPng(data) {
|
|||||||
return axios.post('/exam/words/submit', data)
|
return axios.post('/exam/words/submit', data)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getExamWordsResult(page, size) {
|
export function getExamWordsResult(page, size, classId, gradeId, studentName) {
|
||||||
return axios.post('/exam/words/get', {
|
return axios.post('/exam/words/get', {
|
||||||
page: page,
|
page: page,
|
||||||
size: size
|
size: size,
|
||||||
|
classId: classId,
|
||||||
|
gradeId: gradeId,
|
||||||
|
studentName: studentName
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,35 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
|
<div class="bg-white dark:bg-gray-800 rounded-lg shadow p-6">
|
||||||
<div class="text-lg font-semibold mb-4">结果集</div>
|
<div class="text-lg font-semibold mb-4">结果集</div>
|
||||||
|
<el-form :inline="true" class="mb-4">
|
||||||
|
<el-form-item label="班级">
|
||||||
|
<el-select v-model="classId" placeholder="选择班级" clearable filterable @change="onClassChange" style="min-width: 220px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in classOptions"
|
||||||
|
:key="item.id"
|
||||||
|
:label="`${item.title}${item.gradeName ? '(' + item.gradeName + ')' : ''}`"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="年级">
|
||||||
|
<el-select v-model="gradeId" placeholder="选择年级" clearable filterable style="min-width: 220px">
|
||||||
|
<el-option
|
||||||
|
v-for="g in gradeOptions"
|
||||||
|
:key="g.id"
|
||||||
|
:label="g.title"
|
||||||
|
:value="g.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="学生姓名">
|
||||||
|
<el-input v-model="studentName" placeholder="学生姓名" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="handleSearch">查询</el-button>
|
||||||
|
<el-button @click="handleReset">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
<el-table
|
<el-table
|
||||||
:data="list"
|
:data="list"
|
||||||
border
|
border
|
||||||
@@ -70,6 +99,8 @@ import Header from '@/layouts/components/Header.vue'
|
|||||||
import ExamWordsDetailCard from '@/layouts/components/ExamWordsDetailCard.vue'
|
import ExamWordsDetailCard from '@/layouts/components/ExamWordsDetailCard.vue'
|
||||||
import { ref, onMounted } from 'vue'
|
import { ref, onMounted } from 'vue'
|
||||||
import { uploadExamWordsPng, getExamWordsResult } from '@/api/exam'
|
import { uploadExamWordsPng, getExamWordsResult } from '@/api/exam'
|
||||||
|
import { getClassList } from '@/api/class'
|
||||||
|
import { getGradeList } from '@/api/grade'
|
||||||
|
|
||||||
const list = ref([])
|
const list = ref([])
|
||||||
const pageNo = ref(1)
|
const pageNo = ref(1)
|
||||||
@@ -78,11 +109,22 @@ const totalCount = ref(0)
|
|||||||
const loading = ref(false)
|
const loading = ref(false)
|
||||||
const showDetail = ref(false)
|
const showDetail = ref(false)
|
||||||
const selectedId = ref(null)
|
const selectedId = ref(null)
|
||||||
|
const classId = ref(null)
|
||||||
|
const gradeId = ref(null)
|
||||||
|
const studentName = ref('')
|
||||||
|
const classOptions = ref([])
|
||||||
|
const gradeOptions = ref([])
|
||||||
|
|
||||||
async function fetchList() {
|
async function fetchList() {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
const res = await getExamWordsResult(pageNo.value, pageSize.value)
|
const res = await getExamWordsResult(
|
||||||
|
pageNo.value,
|
||||||
|
pageSize.value,
|
||||||
|
classId.value,
|
||||||
|
gradeId.value,
|
||||||
|
studentName.value
|
||||||
|
)
|
||||||
const d = res.data
|
const d = res.data
|
||||||
list.value = Array.isArray(d.data) ? d.data : []
|
list.value = Array.isArray(d.data) ? d.data : []
|
||||||
totalCount.value = d.totalCount || 0
|
totalCount.value = d.totalCount || 0
|
||||||
@@ -93,6 +135,18 @@ async function fetchList() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function fetchClassOptions() {
|
||||||
|
const res = await getClassList(1, 200)
|
||||||
|
const d = res.data
|
||||||
|
classOptions.value = Array.isArray(d.data) ? d.data : []
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchGradeOptions() {
|
||||||
|
const res = await getGradeList(1, 200)
|
||||||
|
const d = res.data
|
||||||
|
gradeOptions.value = Array.isArray(d.data) ? d.data : []
|
||||||
|
}
|
||||||
|
|
||||||
function handlePageChange(p) {
|
function handlePageChange(p) {
|
||||||
pageNo.value = p
|
pageNo.value = p
|
||||||
fetchList()
|
fetchList()
|
||||||
@@ -117,8 +171,28 @@ function handleRowClick(row) {
|
|||||||
showDetail.value = true
|
showDetail.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleSearch() {
|
||||||
|
pageNo.value = 1
|
||||||
|
fetchList()
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleReset() {
|
||||||
|
classId.value = null
|
||||||
|
gradeId.value = null
|
||||||
|
studentName.value = ''
|
||||||
|
pageNo.value = 1
|
||||||
|
fetchList()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClassChange(val) {
|
||||||
|
const item = classOptions.value.find(i => i.id === val)
|
||||||
|
gradeId.value = item ? item.gradeId : null
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
fetchList()
|
fetchList()
|
||||||
|
fetchClassOptions()
|
||||||
|
fetchGradeOptions()
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user