教师端完善批改中心,增加教师端查看试卷功能,完善学生端部分功能缺少

main
yuan 8 months ago
parent 48a4c772b4
commit 390dd6aa8f

@ -128,8 +128,8 @@ public class StudentHomePageController {
return R.ok(iQuestionanswerService.selectQuestionanswer(id,testid)); return R.ok(iQuestionanswerService.selectQuestionanswer(id,testid));
} }
//观题自动更改 //观题自动更改
@ApiOperation("任务中心观题批改") @ApiOperation("任务中心观题批改")
@GetMapping("task_answerDisplay") @GetMapping("task_answerDisplay")
public R<String> taskAnswerDisplay(Long id) { public R<String> taskAnswerDisplay(Long id) {
SysUser sysUser = SecurityUtils.getLoginUser().getUser(); SysUser sysUser = SecurityUtils.getLoginUser().getUser();
@ -143,7 +143,7 @@ public class StudentHomePageController {
return R.fail("查不到该学生的考试记录!"); return R.fail("查不到该学生的考试记录!");
} }
@ApiOperation("任务中心批改观题") @ApiOperation("任务中心批改观题")
@PostMapping("task_markObjectiveQuestions") @PostMapping("task_markObjectiveQuestions")
public R<String> taskMarkObjectiveQuestions(@RequestBody QuestionAnswerDO questionAnswerDO) { public R<String> taskMarkObjectiveQuestions(@RequestBody QuestionAnswerDO questionAnswerDO) {
if(iQuestionanswerService.markObjectiveQuestions(questionAnswerDO)!=0){ if(iQuestionanswerService.markObjectiveQuestions(questionAnswerDO)!=0){

@ -4,13 +4,17 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysUser; import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.utils.SecurityUtils; import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.test.domain.DO.Correct;
import com.ruoyi.test.domain.DO.QuestionAnswerDO; import com.ruoyi.test.domain.DO.QuestionAnswerDO;
import com.ruoyi.test.domain.Markedtest; import com.ruoyi.test.domain.Markedtest;
import com.ruoyi.test.domain.Message;
import com.ruoyi.test.domain.StudentClass; import com.ruoyi.test.domain.StudentClass;
import com.ruoyi.test.domain.TeacherManageClass; import com.ruoyi.test.domain.TeacherManageClass;
import com.ruoyi.test.domain.Vo.MessageVo;
import com.ruoyi.test.seriver.*; import com.ruoyi.test.seriver.*;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import io.swagger.models.auth.In;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -43,12 +47,31 @@ public class TeacherAnswerSheetController {
@Autowired @Autowired
private ITeacherManageClassService iTeacherManageClassService; private ITeacherManageClassService iTeacherManageClassService;
@Autowired
private IMassageService iMassageService;
@ApiOperation("查看学生的考试情况(最新)") @ApiOperation("查看学生的考试情况(最新)")
@GetMapping("selectQuestionanswer") @GetMapping("selectQuestionanswer")
public R<QuestionAnswerDO> selectQuestionanswer(Long senderId, Long testid) { public R<QuestionAnswerDO> selectQuestionanswer(Long senderId, Long testid) {
System.out.println("==============="+senderId+" "+testid);
return R.ok(iQuestionanswerService.selectQuestionanswer(senderId,testid)); return R.ok(iQuestionanswerService.selectQuestionanswer(senderId,testid));
} }
@ApiOperation("检查是否批改")
@GetMapping("selectMarkedtestList")
public R<List<Correct>> selectMarkedtestList() {
SysUser sysUser = SecurityUtils.getLoginUser().getUser();
List<TeacherManageClass> teacherManageClass = iTeacherManageClassService.selectById(sysUser.getUserId());
List<Long> list = iStudentClassService.selectByTeacherIdList(teacherManageClass);
return R.ok(iMarkedtestService.selectByStudentList(sysUser.getUserId(),list));
}
@ApiOperation("添加提醒消息")
@PostMapping("addMessage")
public R<Integer> addMessage(@RequestBody MessageVo messageVo) {
return R.ok(iMassageService.addMessage(messageVo));
}
@ApiOperation("批改客观题") @ApiOperation("批改客观题")
@PostMapping("markObjectiveQuestions") @PostMapping("markObjectiveQuestions")
public R<String> markObjectiveQuestions(@RequestBody QuestionAnswerDO questionAnswerDO) { public R<String> markObjectiveQuestions(@RequestBody QuestionAnswerDO questionAnswerDO) {
@ -58,6 +81,12 @@ public class TeacherAnswerSheetController {
return R.fail("批改提交失败!"); return R.fail("批改提交失败!");
} }
@ApiOperation("获取某一张的分数")
@GetMapping("getScoreByTestId")
public R<Markedtest> getScoreByTestId(Long studentId,Long testId) {
return R.ok(iMarkedtestService.selectmarkedtestByTestid(studentId,testId));
}
@ApiOperation("试卷批改完毕提交") @ApiOperation("试卷批改完毕提交")
@PostMapping("addmarkedtest") @PostMapping("addmarkedtest")

@ -0,0 +1,15 @@
package com.ruoyi.test.domain.DO;
import lombok.Data;
@Data
public class Correct {
private Long sendId;
private Long testId;
private String subject;
private String name;
private String senderName;
private Integer status;
}

@ -8,9 +8,9 @@ import lombok.Data;
public class Markedtest { public class Markedtest {
private Long senderId; private Long senderId;
private long testid; private Long testid;
private double score; private Double score;
private double totalscore; private Double totalscore;
private Integer totalquestions; private Integer totalquestions;
private Integer tquestions; private Integer tquestions;
private Integer time; private Integer time;

@ -0,0 +1,13 @@
package com.ruoyi.test.domain;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
@Data
@TableName("message")
public class Message {
private Long teacherId;
private Long studentId;
private String source;
private String tf;
}

@ -0,0 +1,12 @@
package com.ruoyi.test.domain.Vo;
import lombok.Data;
@Data
public class MessageVo {
private Long teacherId;
private Long studentId;
private String source;
private String tf;
private String name;
}

@ -2,11 +2,15 @@ package com.ruoyi.test.domain.Vo;
import lombok.Data; import lombok.Data;
import java.util.List;
import java.util.Map;
@Data @Data
public class QuestionanswerVo { public class QuestionanswerVo {
private Long id; private Long id;
private String content; private String content;
private List<Map<String,String>> chance;
//学生给的答案 //学生给的答案
private String idanswer; private String idanswer;
@ -20,4 +24,6 @@ public class QuestionanswerVo {
private String analysis; private String analysis;
private String type;
} }

@ -0,0 +1,12 @@
package com.ruoyi.test.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.test.domain.Message;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@Mapper
public interface MessageMapper extends BaseMapper<Message> {
int addMessage(@Param("message") Message message);
}

@ -15,4 +15,5 @@ public interface IAnswerService {
Boolean selectBySenderIdAndTestId(Long senderId,Long testid); Boolean selectBySenderIdAndTestId(Long senderId,Long testid);
} }

@ -1,6 +1,7 @@
package com.ruoyi.test.seriver; package com.ruoyi.test.seriver;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.test.domain.DO.Correct;
import com.ruoyi.test.domain.Markedtest; import com.ruoyi.test.domain.Markedtest;
import com.ruoyi.test.domain.StudentClass; import com.ruoyi.test.domain.StudentClass;
@ -25,4 +26,6 @@ public interface IMarkedtestService {
Markedtest selectmarkedtestBySenderIdAndTestid(Long senderId,Long testId); Markedtest selectmarkedtestBySenderIdAndTestid(Long senderId,Long testId);
Markedtest selectmarkedtestByTestid(Long id,Long testId); Markedtest selectmarkedtestByTestid(Long id,Long testId);
List<Correct> selectByStudentList(Long id,List<Long> list);
} }

@ -0,0 +1,8 @@
package com.ruoyi.test.seriver;
import com.ruoyi.test.domain.Vo.MessageVo;
public interface IMassageService {
int addMessage(MessageVo messageVo);
}

@ -15,4 +15,7 @@ public interface IStudentClassService {
StudentClass selectById(Long id); StudentClass selectById(Long id);
List<Long> selectByTeacherIdList(List<TeacherManageClass> teacherManageClasses);
} }

@ -13,4 +13,8 @@ public interface ITeacherManageClassService {
int addclass1(Long teacherid,String grade,String Class1); int addclass1(Long teacherid,String grade,String Class1);
TeacherManageClass selectByGradeAndClass(String grade,String Class1); TeacherManageClass selectByGradeAndClass(String grade,String Class1);
List<TeacherManageClass> selectById(Long teacherid);
List<String> selectByTeacherId(Long teacherid);
} }

@ -6,6 +6,6 @@ import java.util.List;
public interface ITeacherSubjectService { public interface ITeacherSubjectService {
List<TeacherSubject> select(Long teacherid); List<String> select(Long teacherid);
} }

@ -4,7 +4,9 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.test.domain.*; import com.ruoyi.test.domain.*;
import com.ruoyi.test.domain.DO.Correct;
import com.ruoyi.test.domain.DO.QuestionAnswerDO; import com.ruoyi.test.domain.DO.QuestionAnswerDO;
import com.ruoyi.test.domain.Vo.MarkedtestVo; import com.ruoyi.test.domain.Vo.MarkedtestVo;
import com.ruoyi.test.domain.Vo.QuestionanswerVo; import com.ruoyi.test.domain.Vo.QuestionanswerVo;
@ -19,9 +21,8 @@ import org.springframework.data.domain.PageRequest;
import org.springframework.security.core.parameters.P; import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.*;
import java.util.Collections; import java.util.stream.Collectors;
import java.util.List;
@Service @Service
public class MarkedtestServiceImpl extends ServiceImpl<MarkedtestMapper, Markedtest> implements IMarkedtestService { public class MarkedtestServiceImpl extends ServiceImpl<MarkedtestMapper, Markedtest> implements IMarkedtestService {
@ -44,13 +45,21 @@ public class MarkedtestServiceImpl extends ServiceImpl<MarkedtestMapper, Markedt
@Autowired @Autowired
private IExamPaperService iExamPaperService; private IExamPaperService iExamPaperService;
@Autowired
private ISysUserService iSysUserService;
@Autowired
private ITeacherSubjectService iTeacherSubjectService;
@Autowired
private ITeacherManageClassService iTeacherManageClassService;
@Override @Override
public int addmarkedtest(Long senderId,Long testid) { public int addmarkedtest(Long senderId,Long testid) {
QuestionAnswerDO questionAnswerDO = iQuestionanswerService.selectQuestionanswer(senderId,testid); QuestionAnswerDO questionAnswerDO = iQuestionanswerService.selectQuestionanswer(senderId,testid);
int totalscore = 0; double totalscore = 0;
int score = 0; double score = 0;
int tquestions = 0; int tquestions = 0;
int totalquestions = 0; int totalquestions = 0;
@ -176,4 +185,46 @@ public class MarkedtestServiceImpl extends ServiceImpl<MarkedtestMapper, Markedt
return markedtestMapper.selectOne(queryWrapper); return markedtestMapper.selectOne(queryWrapper);
} }
@Override
public List<Correct> selectByStudentList(Long id,List<Long> list) {
List<String> teacherSubjectList = iTeacherSubjectService.select(id);
List<String> teacherManageClasses = iTeacherManageClassService.selectByTeacherId(id);
LambdaQueryWrapper<ExamPaper> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(ExamPaper::getSubject,teacherSubjectList)
.in(ExamPaper::getGrade,teacherManageClasses);
List<ExamPaper> examPapers = examPaperMapper.selectList(queryWrapper);
List<Correct> list1 = list.stream()
.flatMap(studentId -> {
List<Correct> list2 = new ArrayList<>();
for(ExamPaper examPaper : examPapers){
Correct correct = new Correct();
correct.setSubject(examPaper.getSubject());
correct.setTestId(examPaper.getId());
correct.setName(examPaper.getName());
correct.setSenderName(iSysUserService.selectUserById(studentId).getUserName());
correct.setSendId(studentId);
if(iAnswerService.selectBySenderIdAndTestId(studentId,examPaper.getId())){
LambdaQueryWrapper<Markedtest> queryWrapper1 = new LambdaQueryWrapper<>();
queryWrapper1.eq(Markedtest::getSenderId,studentId)
.eq(Markedtest::getTestid,examPaper.getId());
if(markedtestMapper.selectCount(queryWrapper1)>0){
correct.setStatus(0);
}else{
correct.setStatus(1);
}
}else{
correct.setStatus(2);
}
list2.add(correct);
}
return list2.stream();
})
.collect(Collectors.toList());
return list1;
}
} }

@ -0,0 +1,31 @@
package com.ruoyi.test.seriver.Impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.test.domain.Message;
import com.ruoyi.test.domain.Vo.MessageVo;
import com.ruoyi.test.mapper.MessageMapper;
import com.ruoyi.test.seriver.IMassageService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MessageServiceImpl extends ServiceImpl<MessageMapper, Message> implements IMassageService {
@Autowired
private MessageMapper messageMapper;
@Autowired
private ISysUserService iSysUserService;
@Override
public int addMessage(MessageVo messageVo) {
Message message = new Message();
BeanUtils.copyProperties(messageVo,message);
String teahcerName = iSysUserService.selectUserById(message.getTeacherId()).getUserName();
String source = "教师"+teahcerName+"提醒你请尽快完成"+messageVo.getName();
message.setSource(source);
return messageMapper.addMessage(message);
}
}

@ -12,6 +12,7 @@ import com.ruoyi.test.domain.Questionbank;
import com.ruoyi.test.domain.Vo.AnswerVo; import com.ruoyi.test.domain.Vo.AnswerVo;
import com.ruoyi.test.domain.Vo.QuestionanswerVo; import com.ruoyi.test.domain.Vo.QuestionanswerVo;
import com.ruoyi.test.mapper.QuestionanswerMapper; import com.ruoyi.test.mapper.QuestionanswerMapper;
import com.ruoyi.test.seriver.IQuestionTypeService;
import com.ruoyi.test.seriver.IQuestionanswerService; import com.ruoyi.test.seriver.IQuestionanswerService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -24,6 +25,9 @@ public class QuestionanswerServiceImpl extends ServiceImpl<QuestionanswerMapper,
@Autowired @Autowired
private QuestionanswerMapper questionanswerMapper; private QuestionanswerMapper questionanswerMapper;
@Autowired
private IQuestionTypeService iQuestionTypeService;
@Override @Override
public QuestionAnswerDO createTest(List<Questionbank> list, Answer answer) { public QuestionAnswerDO createTest(List<Questionbank> list, Answer answer) {
QuestionAnswerDO questionAnswerDO = new QuestionAnswerDO(); QuestionAnswerDO questionAnswerDO = new QuestionAnswerDO();
@ -44,6 +48,10 @@ public class QuestionanswerServiceImpl extends ServiceImpl<QuestionanswerMapper,
questionanswerVo.setDifficulty(questionbank.getDifficulty()); questionanswerVo.setDifficulty(questionbank.getDifficulty());
questionanswerVo.setAnalysis(questionbank.getAnalysis()); questionanswerVo.setAnalysis(questionbank.getAnalysis());
questionanswerVo.setAnswer(questionbank.getAnswer()); questionanswerVo.setAnswer(questionbank.getAnswer());
String chance = questionbank.getChance();
List<Map<String,String>> listMap = gson.fromJson(chance,List.class);
questionanswerVo.setChance(listMap);
questionanswerVo.setType(iQuestionTypeService.getQuestiontype(questionbank.getQuestiontype()));
// 使用流和 Lambda 表达式查找具有特定键的 HashMap // 使用流和 Lambda 表达式查找具有特定键的 HashMap
Optional<AnswerVo> result = dataList.stream() Optional<AnswerVo> result = dataList.stream()
@ -97,14 +105,14 @@ public class QuestionanswerServiceImpl extends ServiceImpl<QuestionanswerMapper,
queryWrapper.eq(Questionanswer::getTestid,id); queryWrapper.eq(Questionanswer::getTestid,id);
queryWrapper.orderByDesc(Questionanswer::getCreatetime).last("LIMIT 1"); queryWrapper.orderByDesc(Questionanswer::getCreatetime).last("LIMIT 1");
Questionanswer questionanswer = questionanswerMapper.selectOne(queryWrapper); Questionanswer questionanswer = questionanswerMapper.selectOne(queryWrapper);
System.out.println("========"+questionanswer);
String qa = questionanswer.getQa(); String qa = questionanswer.getQa();
// System.out.println(qa);
Gson gson = new Gson(); Gson gson = new Gson();
List<QuestionanswerVo> dataList = gson.fromJson(qa,List.class); Type listType = new TypeToken<List<QuestionanswerVo>>(){}.getType();
List<QuestionanswerVo> questionAnswerList = gson.fromJson(qa, listType);
QuestionAnswerDO questionAnswerDO = new QuestionAnswerDO(); QuestionAnswerDO questionAnswerDO = new QuestionAnswerDO();
questionAnswerDO.setSenderId(senderId);
questionAnswerDO.setTestid(questionanswer.getTestid()); questionAnswerDO.setTestid(questionanswer.getTestid());
questionAnswerDO.setList(dataList); questionAnswerDO.setList(questionAnswerList);
// System.out.println(questionAnswerDO); // System.out.println(questionAnswerDO);
return questionAnswerDO; return questionAnswerDO;
} }
@ -117,6 +125,7 @@ public class QuestionanswerServiceImpl extends ServiceImpl<QuestionanswerMapper,
Gson gson = new Gson(); Gson gson = new Gson();
String qa = gson.toJson(list); String qa = gson.toJson(list);
questionanswer.setQa(qa); questionanswer.setQa(qa);
questionanswer.setSenderId(questionAnswerDO.getSenderId());
return questionanswerMapper.addQuestionanswer(questionanswer); return questionanswerMapper.addQuestionanswer(questionanswer);
} }
} }

@ -9,7 +9,9 @@ import com.ruoyi.test.seriver.IStudentClassService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
@Service @Service
public class StudentClassServiceImpl extends ServiceImpl<StudentClassMapper, StudentClass> implements IStudentClassService { public class StudentClassServiceImpl extends ServiceImpl<StudentClassMapper, StudentClass> implements IStudentClassService {
@ -49,5 +51,27 @@ public class StudentClassServiceImpl extends ServiceImpl<StudentClassMapper, Stu
return studentClassMapper.selectOne(queryWrapper); return studentClassMapper.selectOne(queryWrapper);
} }
@Override
public List<Long> selectByTeacherIdList(List<TeacherManageClass> teacherManageClasses) {
// 用于存储查询结果的学生ID列表
List<Long> studentIds = teacherManageClasses.stream()
.flatMap(teacherManageClass -> {
// 对每个TeacherManageClass查询符合的学生ID
LambdaQueryWrapper<StudentClass> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(StudentClass::getClass1, teacherManageClass.getClass1())
.eq(StudentClass::getGrade, teacherManageClass.getGrade());
// 执行查询获取学生ID列表
List<Long> ids = studentClassMapper.selectList(queryWrapper)
.stream()
.map(StudentClass::getStudentid) // 提取学生ID
.collect(Collectors.toList());
return ids.stream();
})
.collect(Collectors.toList()); // 最终返回所有符合条件的学生ID列表
return studentIds;
}
} }

@ -8,7 +8,9 @@ import com.ruoyi.test.seriver.ITeacherManageClassService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
@Service @Service
public class TeacherManageClassServiceImpl extends ServiceImpl<TeacherManageClassMapper, TeacherManageClass> implements ITeacherManageClassService { public class TeacherManageClassServiceImpl extends ServiceImpl<TeacherManageClassMapper, TeacherManageClass> implements ITeacherManageClassService {
@ -40,4 +42,21 @@ public class TeacherManageClassServiceImpl extends ServiceImpl<TeacherManageClas
.eq(TeacherManageClass::getClass1,Class1); .eq(TeacherManageClass::getClass1,Class1);
return teacherManageClassMapper.selectOne(queryWrapper); return teacherManageClassMapper.selectOne(queryWrapper);
} }
@Override
public List<TeacherManageClass> selectById(Long teacherid) {
LambdaQueryWrapper<TeacherManageClass> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TeacherManageClass::getTeacherid,teacherid);
return teacherManageClassMapper.selectList(queryWrapper);
}
@Override
public List<String> selectByTeacherId(Long teacherid) {
LambdaQueryWrapper<TeacherManageClass> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TeacherManageClass::getTeacherid,teacherid);
return teacherManageClassMapper.selectList(queryWrapper)
.stream()
.map(TeacherManageClass::getGrade)
.collect(Collectors.toList());
}
} }

@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
@Service @Service
public class TeacherSubjectServiceImpl extends ServiceImpl<TeacherSubjectMapper, TeacherSubject> implements ITeacherSubjectService { public class TeacherSubjectServiceImpl extends ServiceImpl<TeacherSubjectMapper, TeacherSubject> implements ITeacherSubjectService {
@ -17,9 +18,12 @@ public class TeacherSubjectServiceImpl extends ServiceImpl<TeacherSubjectMapper,
private TeacherSubjectMapper teacherSubjectMapper; private TeacherSubjectMapper teacherSubjectMapper;
@Override @Override
public List<TeacherSubject> select(Long teacherid) { public List<String> select(Long teacherid) {
LambdaQueryWrapper<TeacherSubject> queryWrapper = new LambdaQueryWrapper<>(); LambdaQueryWrapper<TeacherSubject> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(TeacherSubject::getTeacherid,teacherid); queryWrapper.eq(TeacherSubject::getTeacherid,teacherid);
return teacherSubjectMapper.selectList(queryWrapper); return teacherSubjectMapper.selectList(queryWrapper)
.stream()
.map(TeacherSubject::getSubject)
.collect(Collectors.toList());
} }
} }

@ -8,7 +8,6 @@
<insert id="addmarkedtest" parameterType="Markedtest"> <insert id="addmarkedtest" parameterType="Markedtest">
insert into markedtest( insert into markedtest(
sender_id, sender_id,
sender,
testid, testid,
score, score,
totalscore, totalscore,
@ -18,7 +17,6 @@
finishtime finishtime
)values ( )values (
#{markedtest.senderId}, #{markedtest.senderId},
#{markedtest.sender},
#{markedtest.testid}, #{markedtest.testid},
#{markedtest.score}, #{markedtest.score},
#{markedtest.totalscore}, #{markedtest.totalscore},

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--mybatis-3-mapper.dtd:约束文件的名称限制和检查在当前文件中出现的标签和属性符合mybatis的要求-->
<!--namespace命名空间要有唯一的值要求使用dao接口的权限定名称一个dao接口对应一个mappernamespace指明对应哪个dao接口-->
<mapper namespace="com.ruoyi.test.mapper.MessageMapper">
<!-- 所有的数据库操作都要写在mapper标签中可以使用特定的标签表示数据库中的特定操作 -->
<insert id="addMessage" parameterType="Message">
insert into message(
teacher_id,
student_id,
source,
tf
)values (
#{message.teacherId},
#{message.studentId},
#{message.source},
#{message.tf}
)
</insert>
</mapper>

@ -15,15 +15,15 @@
<i class="el-icon-house"></i> <i class="el-icon-house"></i>
<span>主页</span> <span>主页</span>
</el-menu-item> </el-menu-item>
<el-menu-item :index="`/student/exam?userId=${userId}`"> <el-menu-item :index="`/teacher/exam?userId=${userId}`">
<i class="el-icon-message"></i> <i class="el-icon-message"></i>
<span>试卷中心</span> <span>试卷中心</span>
</el-menu-item> </el-menu-item>
<el-menu-item :index="`/student/scoreList?userId=${userId}`"> <el-menu-item :index="`/teacher/scoreList?userId=${userId}`">
<i class="el-icon-s-data"></i> <i class="el-icon-s-data"></i>
<span>分数查询</span> <span>分数查询</span>
</el-menu-item> </el-menu-item>
<el-menu-item :index="`/student/scoreList?userId=${userId}`"> <el-menu-item :index="`/teacher/correct?userId=${userId}`">
<i class="el-icon-edit"></i> <i class="el-icon-edit"></i>
<span>批改中心</span> <span>批改中心</span>
</el-menu-item> </el-menu-item>

@ -1,11 +1,11 @@
import Vue from 'vue';
import App from './App.vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css'; import 'element-ui/lib/theme-chalk/index.css';
import './assets/gloable.css'; import './assets/gloable.css';
import store from './store'; // 确保这个路径是正确的 import store from './store'; // 确保这个路径是正确的
import router from './router'; import router from './router';
import request from "@/utils/request"; import request from "@/utils/request";
import Vue from 'vue';
import App from './App.vue';
import ElementUI from 'element-ui';
// 使用 ElementUI 组件库 // 使用 ElementUI 组件库
Vue.use(ElementUI, { size: 'small' }); Vue.use(ElementUI, { size: 'small' });

@ -8,6 +8,12 @@ import store from '../store'; // 引入 Vuex store
Vue.use(VueRouter); Vue.use(VueRouter);
const routes = [ const routes = [
{
path:'/teacher/viewExamPaper',
name:'ViewExamPaper',
component: () => import(/* webpackChunkName: "about" */ '../views/Teacher/ViewExamPaper.vue'),
meta: { requiresAuth: true }
},
{ {
path: '/teacher/homePage', path: '/teacher/homePage',
name: 'HomePage', name: 'HomePage',
@ -73,7 +79,7 @@ const router = new VueRouter({
// 路由守卫 // 路由守卫
router.beforeEach((to, from, next) => { router.beforeEach((to, from, next) => {
const userId = to.query.userId; const userId = to.query.userId;
console.log('userId:', to); console.log('userId:', store.state.tokens[userId]);
// 判断该路由是否需要登录权限 // 判断该路由是否需要登录权限
if (to.matched.some(record => record.meta.requiresAuth)) { if (to.matched.some(record => record.meta.requiresAuth)) {
// 如果未登录,跳转到登录页 // 如果未登录,跳转到登录页

@ -1,8 +1,6 @@
<template> <template>
<div class="exam-container"> <div class="exam-container">
<!-- 左侧栏 -->
<div class="sidebar"> <div class="sidebar">
<!-- 返回按钮 -->
<div class="back-button"> <div class="back-button">
<button @click="goBack"> <button @click="goBack">
<span>返回</span> <span>返回</span>
@ -25,7 +23,6 @@
</div> </div>
</div> </div>
<!-- 主内容 -->
<div class="main-content" v-if="!loading && questions.length"> <div class="main-content" v-if="!loading && questions.length">
<div <div
v-for="(question, index) in questions" v-for="(question, index) in questions"
@ -35,6 +32,49 @@
:class="{ correct: question.tf === 'true', incorrect: question.tf === 'false', active: currentQuestionIndex === index }" :class="{ correct: question.tf === 'true', incorrect: question.tf === 'false', active: currentQuestionIndex === index }"
> >
<p>{{ index + 1 }}. {{ question.content }}</p> <p>{{ index + 1 }}. {{ question.content }}</p>
<!-- Check and Display Options -->
<div class="options">
<!-- 单选题 (Single Choice) -->
<template v-if="question.type === '单选题'">
<div v-for="(option, optIndex) in question.chance" :key="optIndex"
class="option"
:class="{ selected: answers[question.id] === option.label }">
{{ option.label }}: {{ option.text }}
</div>
</template>
<!-- 多选题 (Multiple Choice) -->
<template v-else-if="question.type === ''">
<div v-for="(option, optIndex) in question.chance" :key="optIndex" class="option">
{{ option.label }}: {{ option.text }}
</div>
</template>
<!-- 判断题 (True/False) -->
<template v-else-if="question.type === ''">
<div>
<input
type="radio"
:name="'question-' + question.id"
value="true"
:checked="answers[question.id] === 'true'"
disabled
/>
T
</div>
<div>
<input
type="radio"
:name="'question-' + question.id"
value="false"
:checked="answers[question.id] === 'false'"
disabled
/>
F
</div>
</template>
</div>
<p>你的答案<span>{{ question.answer }}</span></p> <p>你的答案<span>{{ question.answer }}</span></p>
<p>正确答案<span>{{ question.idanswer }}</span></p> <p>正确答案<span>{{ question.idanswer }}</span></p>
<p>分数{{ question.score }} </p> <p>分数{{ question.score }} </p>
@ -42,18 +82,17 @@
</div> </div>
</div> </div>
<!-- 加载中 -->
<div v-if="loading" class="loading"> <div v-if="loading" class="loading">
正在加载试题请稍候... 正在加载试题请稍候...
</div> </div>
<!-- 空状态 -->
<div v-if="!loading && !questions.length" class="empty"> <div v-if="!loading && !questions.length" class="empty">
未找到试题请联系管理员 未找到试题请联系管理员
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import axios from "axios"; import axios from "axios";
import exam from "@/views/Student/Exam.vue"; import exam from "@/views/Student/Exam.vue";
@ -156,6 +195,7 @@ export default {
this.fetchExamData(); this.fetchExamData();
}, },
created() { created() {
this.userId = this.$route.query.userId;
this.examname = this.$route.query.name; this.examname = this.$route.query.name;
this.id = this.$route.query.id; this.id = this.$route.query.id;
this.getTest(); this.getTest();
@ -190,11 +230,15 @@ export default {
} }
.sidebar { .sidebar {
width: 25%; position: fixed; /* 固定左侧栏 */
top: 0;
left: 0;
width: 20%;
height: 100%;
padding: 20px; padding: 20px;
background-color: #f4f4f4;
overflow-y: auto; /* 允许左侧栏滚动 */
border-right: 1px solid #ddd; border-right: 1px solid #ddd;
display: flex;
flex-direction: column;
} }
.sidebar h2, .sidebar h2,
@ -244,8 +288,11 @@ export default {
} }
.main-content { .main-content {
flex: 1; margin-left: 20%; /* 右侧主内容的宽度根据左侧栏的宽度调整 */
padding: 20px; padding: 20px;
width: 80%;
overflow-y: auto; /* 使右侧内容可滚动 */
height: 100vh;
} }
.question { .question {

@ -15,18 +15,76 @@
<!-- 主内容 --> <!-- 主内容 -->
<el-main> <el-main>
<el-card> <el-card>
<el-table :data="examPapers" border stripe style="width: 100%"> <!-- 搜索框 -->
<el-table-column prop="id" label="试卷ID" width="120" /> <el-form :model="searchQuery" label-width="100px" style="margin-bottom: 20px;">
<el-table-column prop="title" label="试卷名称" /> <el-row :gutter="20">
<el-table-column prop="submitter" label="提交人" width="150" /> <el-col :span="8">
<el-form-item label="试卷名称">
<el-input v-model="searchQuery.name" placeholder="请输入试卷名称" suffix-icon="el-icon-search" @input="filterPapers" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="提交人">
<el-input v-model="searchQuery.submitter" placeholder="请输入提交人" suffix-icon="el-icon-search" @input="filterPapers" />
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="批改状态">
<el-select v-model="searchQuery.status" placeholder="选择批改状态" @change="filterPapers">
<el-option label="全部" value=""></el-option>
<el-option label="已批改" value="0"></el-option>
<el-option label="未批改" value="1"></el-option>
<el-option label="未作答" value="2"></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
<!-- 表格 -->
<el-table :data="filteredExamPapers" border stripe style="width: 100%">
<el-table-column prop="testId" label="试卷ID" width="120" />
<el-table-column prop="name" label="试卷名称" />
<el-table-column prop="subject" label="学科" />
<el-table-column prop="senderName" label="提交人" width="150" />
<el-table-column prop="status" label="批改状态" width="120"> <el-table-column prop="status" label="批改状态" width="120">
<template #default="{ row }"> <template #default="{ row }">
<el-tag :type="row.status === '未批改' ? 'info' : 'success'">{{ row.status }}</el-tag> <el-tag :type="row.status === 0 ? 'success' : (row.status === 1 ? 'warning' : 'info')">
{{ row.status === 0 ? '已批改' : (row.status === 1 ? '未批改' : '未作答') }}
</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column label="操作" width="180"> <el-table-column label="操作" width="180">
<template #default="{ row }"> <template #default="{ row }">
<el-button size="small" type="primary" @click="viewPaper(row)"></el-button> <el-button
v-if="row.status === 0"
size="small"
type="primary"
@click="viewPaper(row)">
查看试卷
</el-button>
<!-- 如果状态是 1显示批改按钮 -->
<el-button
v-else-if="row.status === 1"
size="small"
type="primary"
@click="correctPaper(row)"
style="width: 78px;">
批改
</el-button>
<!-- 如果状态是 2显示提醒按钮 -->
<el-button
v-else
size="small"
type="primary"
@click="remind(row)"
style="width: 78px;">
提醒
</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -53,19 +111,27 @@
<script> <script>
import Header from "@/components/Teacher/Header.vue"; import Header from "@/components/Teacher/Header.vue";
import Aside from "@/components/Teacher/Aside.vue"; import Aside from "@/components/Teacher/Aside.vue";
import axios from "axios";
export default { export default {
name: "CorrectPapers", name: "CorrectPapers",
components: { Aside, Header }, components: { Aside, Header },
data() { data() {
return { return {
userId: "",
collapseBtnClass: "el-icon-s-fold", collapseBtnClass: "el-icon-s-fold",
isCollapse: false, isCollapse: false,
sideWidth: 200, sideWidth: 200,
logoTextShow: true, logoTextShow: true,
examPapers: [], // examPapers: [], //
filteredExamPapers: [], //
dialogVisible: false, // dialogVisible: false, //
selectedPaper: null, // selectedPaper: null, //
searchQuery: {
name: "", //
status: "", //
submitter: "", //
},
}; };
}, },
methods: { methods: {
@ -81,16 +147,73 @@ export default {
this.logoTextShow = true; this.logoTextShow = true;
} }
}, },
fetchExamPapers() { async fetchExamPapers() {
// try {
this.examPapers = [ const token = this.$store.state.tokens[this.userId];
{id: 1, title: "试卷一", submitter: "张三", status: "未批改", answers: "答案内容1"}, if (!token) {
{id: 2, title: "试卷二", submitter: "李四", status: "已批改", answers: "答案内容2"}, alert("用户未登录,请重新登录!");
]; this.$router.push("/login"); //
return;
}
const response = await axios.get('http://localhost:8080/teacher/answerSheet/selectMarkedtestList', {
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
}
});
if (response.data.code == 200) {
this.examPapers = response.data.data;
this.filteredExamPapers = [...this.examPapers]; // Initially, show all exam papers
} else {
alert("数据加载失败");
}
} catch (error) {
console.error('获取数据失败', error);
}
},
filterPapers() {
this.filteredExamPapers = this.examPapers.filter(paper => {
const matchesName = paper.name.toLowerCase().includes(this.searchQuery.name.toLowerCase());
const matchesSubmitter = paper.senderName.toLowerCase().includes(this.searchQuery.submitter.toLowerCase());
const matchesStatus = this.searchQuery.status === "" || paper.status == this.searchQuery.status;
return matchesName && matchesSubmitter && matchesStatus;
});
}, },
viewPaper(paper) { viewPaper(paper) {
this.selectedPaper = paper; console.log('paper', paper);
this.dialogVisible = true; this.$router.push({
name: 'ViewExamPaper',
query: { userId: this.userId,studentId: paper.sendId, testid: paper.testId ,name: paper.name} // ID
});
},
correctPaper(paper){
},
async remind(paper){
const name = paper.name;
const token = this.$store.state.tokens[this.userId];
if (!token) {
alert("用户未登录,请重新登录!");
this.$router.push("/login"); //
return;
}
const res =await axios.post(`http://localhost:8080/teacher/answerSheet/addMessage`,
{teacherId: this.userId,
studentId: paper.sendId,
tf: false,
name: name,
},{
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
}
});
console.log(res);
if(res.data.code == 200){
this.$message.success("提醒成功!");
}else{
this.$message.error("发送失败!");
}
}, },
submitCorrection() { submitCorrection() {
this.dialogVisible = false; this.dialogVisible = false;
@ -100,6 +223,7 @@ export default {
}, },
}, },
mounted() { mounted() {
this.userId = this.$route.query.userId;
this.fetchExamPapers(); this.fetchExamPapers();
}, },
}; };

@ -0,0 +1,328 @@
<template>
<div class="exam-container">
<!-- 左侧栏 -->
<div class="sidebar">
<!-- 返回按钮 -->
<div class="back-button">
<button @click="goBack">
<span>返回</span>
</button>
</div>
<h2>{{ examTitle }}</h2>
<p>答题人{{ sender }}</p>
<p>得分{{ currentScore }} &nbsp; 总分{{ totalScore }}</p>
<p>已答对{{ correctQuestions }} &nbsp; 总题数{{ totalQuestions }}</p>
<div class="question-navigation">
<div
v-for="(question, index) in questions"
:key="question.id"
class="question-box"
:class="{ answered: answers[question.id]?.length > 0, active: currentQuestionIndex === index, correct: question.tf === 'true', incorrect: question.tf === 'false' }"
@click="scrollToQuestion(index)"
>
{{ index + 1 }}
</div>
</div>
</div>
<!-- 主内容 -->
<div class="main-content" v-if="!loading && questions.length">
<div
v-for="(question, index) in questions"
:key="question.id"
class="question"
:ref="'question-' + question.id"
:class="{ correct: question.tf === 'true', incorrect: question.tf === 'false', active: currentQuestionIndex === index }"
>
<p>{{ index + 1 }}. {{ question.content }}</p>
<div class="options">
<!-- 单选题 (Single Choice) -->
<template v-if="question.type === '单选题'">
<div v-for="(option, optIndex) in question.chance" :key="optIndex"
class="option"
:class="{ selected: answers[question.id] === option.label }">
{{ option.label }}: {{ option.text }}
</div>
</template>
<!-- 多选题 (Multiple Choice) -->
<template v-else-if="question.type === ''">
<div v-for="(option, optIndex) in question.chance" :key="optIndex" class="option">
{{ option.label }}: {{ option.text }}
</div>
</template>
<!-- 判断题 (True/False) -->
<template v-else-if="question.type === ''">
<div>
<input
type="radio"
:name="'question-' + question.id"
value="true"
:checked="answers[question.id] === 'true'"
disabled
/>
T
</div>
<div>
<input
type="radio"
:name="'question-' + question.id"
value="false"
:checked="answers[question.id] === 'false'"
disabled
/>
F
</div>
</template>
</div>
<p>你的答案<span>{{ question.answer }}</span></p>
<p>正确答案<span>{{ question.idanswer }}</span></p>
<p>分数{{ question.score }} </p>
<p v-if="question.analysis">{{ question.analysis }}</p>
</div>
</div>
<!-- 加载中 -->
<div v-if="loading" class="loading">
正在加载试题请稍候...
</div>
<!-- 空状态 -->
<div v-if="!loading && !questions.length" class="empty">
未找到试题请联系管理员
</div>
</div>
</template>
<script>
import axios from "axios";
import exam from "@/views/Student/Exam.vue";
export default {
name: "ViewExamPaper",
data() {
return {
examTitle: this.examname, //
sender: "", //
totalScore: 0, //
duration: "", //
questions: [], //
answers: {}, //
correctQuestions: 0, //
currentScore: 0, //
totalQuestions: 0, //
loading: true, //
submitted: false, //
currentQuestionIndex: 0, //
};
},
computed: {
totalQuestions() {
return this.questions.length;
},
},
methods: {
async fetchExamData() {
try {
const token = this.$store.state.tokens[this.userId];
if (!token) {
alert("用户未登录,请重新登录!");
this.$router.push("/login");
return;
}
const response = await axios.get(
"http://localhost:8080/teacher/answerSheet/selectQuestionanswer",
{
params: { senderId: this.studentId,testid: this.testid },
headers: { Authorization: `Bearer ${token}` },
}
);
const { sender, list, testid } = response.data.data;
this.examTitle = this.examname;
this.sender = sender;
this.questions = list;
console.log('list', list);
this.totalScore = list.reduce((sum, q) => sum + q.score, 0);
this.correctQuestions = list.filter((q) => q.tf === "true").length;
this.loading = false;
} catch (error) {
console.error("获取试题失败", error);
this.loading = false;
}
},
async getTest() {
try {
const token = this.$store.state.tokens[this.userId];
if (!token) {
alert("用户未登录,请重新登录!");
this.$router.push("/login");
return;
}
const response = await axios.get(
"http://localhost:8080/teacher/answerSheet/getScoreByTestId",
{
params: { studentId:this.studentId, testId: this.testId },
headers: { Authorization: `Bearer ${token}` },
}
);
const data = response.data.data;
this.sender = data.sender;
this.currentScore = data.score;
this.totalScore = data.totalscore;
this.correctQuestions = data.tquestions;
this.totalQuestions = data.totalquestions;
} catch (error) {
console.error("获取试卷信息失败", error);
this.loading = false;
}
},
scrollToQuestion(index) {
this.$nextTick(() => {
const questionRef = this.$refs[`question-${this.questions[index].id}`];
if (questionRef && questionRef[0]) {
questionRef[0].scrollIntoView({ behavior: "smooth", block: "start" });
this.currentQuestionIndex = index;
}
});
},
//
goBack() {
this.$router.go(-1); //
},
},
mounted() {
this.fetchExamData();
},
created() {
this.userId = this.$route.query.userId;
this.examname = this.$route.query.name;
this.testid = this.$route.query.testid;
this.studentId = this.$route.query.studentId;
this.getTest();
},
};
</script>
<style scoped>
.back-button {
padding-bottom: 10px;
text-align: center;
}
.back-button button {
background-color: #1976d2;
color: white;
padding: 8px 15px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 18px;
display: flex;
align-items: center;
}
.back-button button:hover {
background-color: #1565c0;
}
.exam-container {
display: flex;
}
.sidebar {
position: fixed; /* 固定左侧栏 */
top: 0;
left: 0;
width: 20%;
height: 100%;
padding: 20px;
background-color: #f4f4f4;
overflow-y: auto; /* 允许左侧栏滚动 */
border-right: 1px solid #ddd;
}
.sidebar h2,
.sidebar p {
margin-bottom: 10px;
}
.question-navigation {
display: grid;
grid-template-columns: repeat(5, 1fr); /* Adjust number of columns */
gap: 10px;
margin-top: 20px;
}
.question-box {
padding: 15px;
background-color: #f1f1f1;
text-align: center;
border: 1px solid #ddd;
border-radius: 5px;
font-size: 18px;
cursor: pointer;
transition: background-color 0.3s;
}
.question-box:hover {
background-color: #e0e0e0;
}
.question-box.active {
background-color: #bbdefb; /* Highlight active question */
font-weight: bold;
}
.question-box.answered {
background-color: #c8e6c9; /* Highlight answered question */
}
.question-box.correct {
background-color: #e0f7fa; /* Correct answer color */
color: #00796b; /* Text color for correct answers */
}
.question-box.incorrect {
background-color: #ffebee; /* Incorrect answer color */
color: #d32f2f; /* Text color for incorrect answers */
}
.main-content {
margin-left: 20%; /* 右侧主内容的宽度根据左侧栏的宽度调整 */
padding: 20px;
width: 80%;
overflow-y: auto; /* 使右侧内容可滚动 */
height: 100vh;
}
.question {
padding: 10px;
margin-bottom: 15px;
border: 1px solid #ddd;
border-radius: 5px;
}
.correct {
background-color: #e0f7fa;
color: #00796b;
}
.incorrect {
background-color: #ffebee;
color: #d32f2f;
}
.loading,
.empty {
text-align: center;
margin-top: 50px;
font-size: 18px;
}
.empty {
color: #888;
}
</style>
Loading…
Cancel
Save