前端:教师端增加批改中心批改功能,分数中心查询;

后端:修改部分数据库字段,补充前端所需的接口
main
yuan 4 months ago
parent 390dd6aa8f
commit 121f74b222

@ -76,7 +76,7 @@ public class StudentExamPaperController {
List<ExamPaperDO1> list1 = new ArrayList<>();
for(ClassExamPaper classExamPaper : list ){
ExamPaper examPaper = iExamPaperService.selectById(classExamPaper.getId());
if(examPaper.getStatus()==0){
if(examPaper.getStatus()==0L){
continue;
}
if(type!=null&&!examPaper.getType().equals(type)){
@ -92,6 +92,7 @@ public class StudentExamPaperController {
examPaperDO1.setSubject(examPaper.getSubject());
examPaperDO1.setStart_time(null);
examPaperDO1.setEnd_time(null);
examPaperDO1.setGlId(examPaper.getGlId());
Long testid = examPaper.getId();
List<Questionbank> list2 = iExamCreateService.selectListByPid(testid);
examPaperDO1.setTotalquestion(list2.size());

@ -6,6 +6,7 @@ import com.ruoyi.common.core.domain.entity.SysUser;
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.ScoreListDO;
import com.ruoyi.test.domain.Markedtest;
import com.ruoyi.test.domain.Message;
import com.ruoyi.test.domain.StudentClass;
@ -50,10 +51,19 @@ public class TeacherAnswerSheetController {
@Autowired
private IMassageService iMassageService;
@ApiOperation("学生成绩列表")
@GetMapping("selectScoreList")
public R<IPage<ScoreListDO>> selectScoreList(int pageNum,int pageSize){
SysUser sysUser = SecurityUtils.getLoginUser().getUser();
Long teacherId = sysUser.getUserId();
List<TeacherManageClass> teacherManageClass = iTeacherManageClassService.selectById(teacherId);
List<StudentClass> studentList = iStudentClassService.getStudentClassByTeacherIdList(teacherManageClass);
return R.ok(iMarkedtestService.selectScoreList(pageNum,pageSize,studentList,teacherId));
}
@ApiOperation("查看学生的考试情况(最新)")
@GetMapping("selectQuestionanswer")
public R<QuestionAnswerDO> selectQuestionanswer(Long senderId, Long testid) {
System.out.println("==============="+senderId+" "+testid);
return R.ok(iQuestionanswerService.selectQuestionanswer(senderId,testid));
}
@ -90,7 +100,7 @@ public class TeacherAnswerSheetController {
@ApiOperation("试卷批改完毕提交")
@PostMapping("addmarkedtest")
public R<String> addmarkedtest(Long senderId,Long testid){
public R<String> addmarkedtest(@RequestParam Long senderId, @RequestParam Long testid){
if(iMarkedtestService.addmarkedtest(senderId,testid)!=0){
return R.ok("提交完成!");
}

@ -1,5 +1,4 @@
package com.ruoyi.test.config;
import com.ruoyi.test.domain.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;

@ -8,6 +8,7 @@ import java.util.List;
public class ExamPaperDO {
private Long id;
private Long glId;
private String subject;
private String grade;
private String name;

@ -5,6 +5,7 @@ import lombok.Data;
@Data
public class ExamPaperDO1 {
private Long id;
private Long glId;
private String name;
private String subject;
private Integer totalquestion;

@ -0,0 +1,20 @@
package com.ruoyi.test.domain.DO;
import lombok.Data;
import java.util.Map;
@Data
public class ScoreListDO {
private Long senderId;
private String senderName;
private String grade;
private String Class1;
private Long testid;
private Double score;
private String examName;
private Integer ranking;//排名
private Long status;
}

@ -1,6 +0,0 @@
package com.ruoyi.test.domain.DO;
public class correctTestsDO {
}

@ -7,6 +7,7 @@ import lombok.Data;
public class ExamPaper {
private Long id;
private Long glId;
private String grade;
private String subject;
private String createtime;

@ -15,5 +15,6 @@ public class Markedtest {
private Integer tquestions;
private Integer time;
private String finishtime;
private Long status;
}

@ -1,27 +0,0 @@
package com.ruoyi.test.domain.Vo;
import lombok.Data;
@Data
public class MarkedtestVo {
private Long id;
// private String grade;
//
// private String subject;
private String name;
private String sender;
private double score;
private double totalscore;
private Integer totalquestions;
private Integer tquestions;
private Integer time;
private String finishtime;
}

@ -40,4 +40,5 @@ public interface IExamPaperService {
IPage<ExamPaper> selectByGrateAndSubjectAndId(int pagenum,int pagesize,String grade,String subject,Long id);
List<ExamPaper> selectByGlId(Long teacherId);
}

@ -2,6 +2,7 @@ package com.ruoyi.test.seriver;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.test.domain.DO.Correct;
import com.ruoyi.test.domain.DO.ScoreListDO;
import com.ruoyi.test.domain.Markedtest;
import com.ruoyi.test.domain.StudentClass;
@ -28,4 +29,6 @@ public interface IMarkedtestService {
Markedtest selectmarkedtestByTestid(Long id,Long testId);
List<Correct> selectByStudentList(Long id,List<Long> list);
IPage<ScoreListDO> selectScoreList(int pageNum,int pageSize,List<StudentClass> studentList,Long teacherId);
}

@ -17,5 +17,6 @@ public interface IStudentClassService {
List<Long> selectByTeacherIdList(List<TeacherManageClass> teacherManageClasses);
List<StudentClass> getStudentClassByTeacherIdList(List<TeacherManageClass> teacherManageClasses);
}

@ -16,6 +16,7 @@ import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
@Service
@ -141,6 +142,13 @@ public class ExamPaperServiceImpl extends ServiceImpl<ExamPaperMapper, ExamPaper
return iPage;
}
@Override
public List<ExamPaper> selectByGlId(Long teacherId) {
LambdaQueryWrapper<ExamPaper> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ExamPaper::getGlId,teacherId);
return examPaperMapper.selectList(queryWrapper);
}
// @Override
// public List<ExamPaper> totalExamPaper(List<TeacherManageClass> list, List<TeacherSubject> list2) {
// List<ExamPaper> list1 = new ArrayList<>();

@ -8,7 +8,7 @@ import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.test.domain.*;
import com.ruoyi.test.domain.DO.Correct;
import com.ruoyi.test.domain.DO.QuestionAnswerDO;
import com.ruoyi.test.domain.Vo.MarkedtestVo;
import com.ruoyi.test.domain.DO.ScoreListDO;
import com.ruoyi.test.domain.Vo.QuestionanswerVo;
import com.ruoyi.test.domain.Vo.QuestionbankVo;
import com.ruoyi.test.mapper.AnswerMapper;
@ -86,6 +86,7 @@ public class MarkedtestServiceImpl extends ServiceImpl<MarkedtestMapper, Markedt
markedtest.setTime(answer.getTime());
markedtest.setTquestions(tquestions);
markedtest.setTotalquestions(totalquestions);
markedtest.setStatus(0L);
return markedtestMapper.addmarkedtest(markedtest);
}
@ -158,7 +159,8 @@ public class MarkedtestServiceImpl extends ServiceImpl<MarkedtestMapper, Markedt
@Override
public List<Markedtest> selectmarkedtestListSenderId(Long senderId) {
LambdaQueryWrapper<Markedtest> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Markedtest::getSenderId,senderId);
queryWrapper.eq(Markedtest::getSenderId,senderId)
.eq(Markedtest::getStatus,1L);
return markedtestMapper.selectList(queryWrapper);
}
@ -181,7 +183,8 @@ public class MarkedtestServiceImpl extends ServiceImpl<MarkedtestMapper, Markedt
public Markedtest selectmarkedtestByTestid(Long id, Long testId) {
LambdaQueryWrapper<Markedtest> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Markedtest::getSenderId,id)
.eq(Markedtest::getTestid,testId);
.eq(Markedtest::getTestid,testId)
.eq(Markedtest::getStatus,1L);
return markedtestMapper.selectOne(queryWrapper);
}
@ -227,4 +230,69 @@ public class MarkedtestServiceImpl extends ServiceImpl<MarkedtestMapper, Markedt
return list1;
}
@Override
public IPage<ScoreListDO> selectScoreList(int pageNum, int pageSize, List<StudentClass> studentList, Long teacherId) {
List<ExamPaper> examPapers = iExamPaperService.selectByGlId(teacherId);
List<ScoreListDO> scoreList = new ArrayList<>();
for(ExamPaper examPaper : examPapers){
for(StudentClass studentClass : studentList){
LambdaQueryWrapper<Markedtest> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Markedtest::getSenderId,studentClass.getStudentid())
.eq(Markedtest::getTestid,examPaper.getId());
Markedtest markedtest = markedtestMapper.selectOne(queryWrapper);
ScoreListDO scoreListDO = new ScoreListDO();
if(markedtest!=null){
scoreListDO.setSenderId(studentClass.getStudentid());
scoreListDO.setTestid(examPaper.getId());
scoreListDO.setSenderName(iSysUserService.selectUserById(studentClass.getStudentid()).getUserName());
scoreListDO.setExamName(examPaper.getName());
scoreListDO.setScore(markedtest.getScore());
scoreListDO.setGrade(studentClass.getGrade());
scoreListDO.setClass1(studentClass.getClass1());
scoreListDO.setStatus(markedtest.getStatus());
scoreList.add(scoreListDO);
}
}
}
System.out.println(scoreList);
// 按年级和班级分组
Map<String, List<ScoreListDO>> groupedByGradeAndClass = scoreList.stream()
.collect(Collectors.groupingBy(score -> score.getGrade() + "-" + score.getClass1()));
// 计算每个组内的排名
for (Map.Entry<String, List<ScoreListDO>> entry : groupedByGradeAndClass.entrySet()) {
List<ScoreListDO> students = entry.getValue();
// 按得分降序排序
students.sort((s1, s2) -> Double.compare(s2.getScore(), s1.getScore()));
// 给每个学生计算排名
int rank = 1;
for (int i = 0; i < students.size(); i++) {
ScoreListDO student = students.get(i);
// 如果与前一个学生分数相同,则排名相同
if (i > 0 && students.get(i).getScore() == students.get(i - 1).getScore()) {
student.setRanking(students.get(i - 1).getRanking());
} else {
student.setRanking(rank);
}
rank++;
}
}
// 把所有学生数据合并回一个列表并返回
List<ScoreListDO> collect = groupedByGradeAndClass.values().stream()
.flatMap(List::stream)
.collect(Collectors.toList());
// 创建 Page 对象,设置当前页和每页大小
IPage<ScoreListDO> page = new Page<>(pageNum, pageSize);
// 将 List 设置为 records
page.setRecords(collect);
return page;
}
}

@ -73,5 +73,24 @@ public class StudentClassServiceImpl extends ServiceImpl<StudentClassMapper, Stu
return studentIds;
}
@Override
public List<StudentClass> getStudentClassByTeacherIdList(List<TeacherManageClass> teacherManageClasses) {
// 用于存储查询结果的学生ID列表
List<StudentClass> 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<StudentClass> ids = studentClassMapper.selectList(queryWrapper);
return ids.stream();
})
.collect(Collectors.toList()); // 最终返回所有符合条件的学生ID列表
return studentIds;
}
}

@ -7,6 +7,7 @@
<insert id="addPaperExam" parameterType="ExamPaper">
insert into exam_paper(
gl_id,
grade,
subject,
name,
@ -14,6 +15,7 @@
time,
createtime
)values (
#{paperCreateDO.glId}
#{paperCreateDO.grade},
#{paperCreateDO.subject},
#{paperCreateDO.name},

@ -14,7 +14,8 @@
tquestions,
totalquestions,
time,
finishtime
finishtime,
status
)values (
#{markedtest.senderId},
#{markedtest.testid},
@ -24,6 +25,7 @@
#{markedtest.totalquestions},
#{markedtest.time},
#{markedtest.finishtime}
#{markedtest.status}
)
</insert>

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

@ -8,6 +8,18 @@ import store from '../store'; // 引入 Vuex store
Vue.use(VueRouter);
const routes = [
{
path:'/teacher/score',
name:'Score',
component: () => import(/* webpackChunkName: "about" */ '../views/Teacher/Score.vue'),
meta: { requiresAuth: true }
},
{
path:'/teacher/correctExamPaper',
name:'CorrectExamPaper',
component: () => import(/* webpackChunkName: "about" */ '../views/Teacher/CorrectExamPaper.vue'),
meta: { requiresAuth: true }
},
{
path:'/teacher/viewExamPaper',
name:'ViewExamPaper',

@ -212,8 +212,6 @@ export default {
questionCount: record.totalquestion,
totalScore: record.totalscore,
time: record.time,
startTime: record.start_time || "未设置",
endTime: record.end_time || "未设置",
hasTaken: hasTaken,
};
})

@ -75,8 +75,8 @@
</div>
</template>
</div>
<p>你的答案<span>{{ question.answer }}</span></p>
<p>正确答案<span>{{ question.idanswer }}</span></p>
<p>你的答案<span>{{ question.idanswer }}</span></p>
<p>正确答案<span>{{ question.answer }}</span></p>
<p>分数{{ question.score }} </p>
<p v-if="question.analysis">{{ question.analysis }}</p>
</div>

@ -164,6 +164,7 @@ export default {
if (response.data.code == 200) {
this.examPapers = response.data.data;
this.filteredExamPapers = [...this.examPapers]; // Initially, show all exam papers
console.log('examPapers', this.filteredExamPapers);
} else {
alert("数据加载失败");
}
@ -187,7 +188,11 @@ export default {
});
},
correctPaper(paper){
console.log('paper', paper);
this.$router.push({
name: 'CorrectExamPaper',
query: { userId: this.userId,studentId: paper.sendId, testid: paper.testId ,name: paper.name} // ID
});
},
async remind(paper){
const name = paper.name;

@ -0,0 +1,481 @@
<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',
// completed: question.tf !== null
}"
@click="scrollToQuestion(index)"
>
{{ index + 1 }}
<span v-if="question.tf !== null" class="status-label"></span>
<span v-else class="status-label">待批改</span>
</div>
</div>
<div>
<button @click="submitGrading(answers)" class="grading-complete">批改完成</button>
</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.idanswer }}</span></p>
<p>正确答案<span>{{ question.answer }}</span></p>
<p>分数{{ question.score }} </p>
<p v-if="question.analysis">{{ question.analysis }}</p>
<!-- 批改未批改题目 -->
<div class="grade-buttons">
<button @click="gradeQuestion(question.id, 'true')" class="grade-button correct">批改为正确</button>
<button @click="gradeQuestion(question.id, 'false')" class="grade-button incorrect">批改为错误</button>
</div>
</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";
export default {
name: "ViewExamPaper",
data() {
return {
examTitle: this.examname, //
sender: "", //
totalScore: 0, //
questions: [], //
answers: {}, //
correctQuestions: 0, //
currentScore: 0, //
totalQuestions: 0, //
loading: true, //
submitted: false, //
currentQuestionIndex: 0, //
};
},
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} = response.data.data;
this.examTitle = this.examname;
this.sender = sender;
this.questions = list;
this.totalQuestions = this.questions.length;
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;
}
},
goBack() {
this.$router.go(-1); //
},
gradeQuestion(questionId, result) {
const question = this.questions.find(q => q.id === questionId);
// `tf`
if (question.tf !== result) {
//
question.tf = result; //
this.answers[questionId] = result; //
//
this.correctQuestions = this.questions.filter(q => q.tf === "true").length;
this.currentScore = this.questions.reduce((sum, q) => sum + (q.tf === "true" ? q.score : 0), 0);
}
console.log(`题目 ID: ${questionId} | 批改结果: ${result} | 正确答案: ${question.answer}`);
},
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;
}
});
},
async submitGrading() {
//
const updatedQuestions = this.questions.map(question => {
return {
...question,
//
tf: this.answers[question.id] || question.tf, // 使
userAnswer: this.answers[question.id] || question.idanswer //
};
});
try {
const token = this.$store.state.tokens[this.userId];
if (!token) {
alert("用户未登录,请重新登录!");
this.$router.push("/login");
return;
}
//
const response = await axios.post(
"http://localhost:8080/teacher/answerSheet/markObjectiveQuestions", //
{
senderId: this.studentId,
testid: this.testid,
list: updatedQuestions, //
},
{
headers: {Authorization: `Bearer ${token}`},
}
);
if(response.data.code === 200){
const res = await axios.post(
`http://localhost:8080/teacher/answerSheet/addmarkedtest`, //
null, // null
{
params: {
senderId: this.studentId, //
testid: this.testid, //
},
headers: {
Authorization: `Bearer ${token}`, // Authorization
},
}
);
if(res.data.code === 200){
this.$message.success("批改成功!");
this.$router.go(-1);
}else{
this.$message.error("批改失败!");
}
}else{
this.$message.error("数据提交异常!");
this.fetchExamData();
}
} catch (error) {
console.error("提交批改失败", error);
alert("提交批改失败,请稍后再试!");
}
},
},
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;
console.log("222222222",this.studentId);
},
};
</script>
<style scoped>
.grading-complete {
border: none; /* 去掉边框 */
display: flex;
align-items: center;
justify-content: center; /* 居中对齐按钮 */
background-color: #388e3c;
color: white;
padding: 10px 15px;
border-radius: 5px;
font-size: 18px;
font-weight: bold;
text-align: center;
margin-top: 15px; /* 控制按钮距离题目的间距 */
width: 100%; /* 让按钮占满容器宽度 */
}
.grade-completed-button {
margin-top: 20px;
text-align: center;
}
.grade-completed-button button {
background-color: #388e3c;
color: white;
padding: 8px 15px;
border: none;
border-radius: 5px;
cursor: pointer;
font-size: 16px;
display: inline-flex;
align-items: center;
transition: background-color 0.3s ease;
}
.grade-completed-button button:hover {
background-color: #2c6b32;
}
.grade-completed-button button:disabled {
background-color: #bdbdbd;
cursor: not-allowed;
}
.grade-buttons {
display: flex;
gap: 15px; /* 按钮之间的间距 */
margin-top: 15px; /* 控制按钮距离题目的间距 */
}
.grade-button {
padding: 10px 20px;
font-size: 16px;
font-weight: bold;
border: none;
border-radius: 30px;
cursor: pointer;
transition: all 0.3s ease;
min-width: 120px;
}
.grade-button:hover {
transform: scale(1.05); /* 悬停时稍微放大按钮 */
}
.grade-button.correct {
background: linear-gradient(145deg, #81c784, #66bb6a); /* 绿色渐变背景 */
color: white;
}
.grade-button.correct:hover {
background: linear-gradient(145deg, #66bb6a, #81c784); /* 悬停时反转颜色 */
}
.grade-button.incorrect {
background: linear-gradient(145deg, #e57373, #f44336); /* 红色渐变背景 */
color: white;
}
.grade-button.incorrect:hover {
background: linear-gradient(145deg, #f44336, #e57373); /* 悬停时反转颜色 */
}
.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;
}
.question-box.incorrect {
background-color: #ffebee;
}
.question-box.completed {
background-color: #fce4ec;
font-weight: bold;
}
.status-label {
font-size: 12px;
color: #555;
margin-left: 5px;
font-style: italic;
}
.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>

@ -0,0 +1,191 @@
<template>
<el-container style="min-height: 100vh; width: 100%">
<!-- 左侧导航 -->
<el-aside :width="sideWidth + 'px'" style="background-color: rgb(238, 241, 246); box-shadow: 2px 0 6px rgb(0 21 41 / 35%)">
<Aside :isCollapse="isCollapse" :logoTextShow="logoTextShow" />
</el-aside>
<!-- 右侧内容 -->
<el-container style="width: calc(100% - 200px);"> <!-- Adjust width based on aside -->
<!-- 顶部导航 -->
<el-header style="border-bottom: 1px solid #ccc;">
<Header :collapseBtnClass="collapseBtnClass" :collapse="collapse" />
</el-header>
<el-main style="padding: 20px;">
<el-row>
<!-- 搜索框 -->
<el-col :span="8">
<el-input
v-model="searchQuery.name"
placeholder="请输入试卷名称"
clearable
@input="fetchScores"
style="width: 100%; margin-bottom: 20px;"
/>
</el-col>
<el-col :span="8">
<el-input
v-model="searchQuery.testID"
placeholder="请输入试卷ID"
clearable
@input="fetchScores"
style="width: 100%; margin-bottom: 20px;"
/>
</el-col>
</el-row>
<!-- 试卷成绩列表 -->
<el-table :data="papers" style="width: 100%" border>
<el-table-column prop="testid" label="试卷ID" width="100" />
<el-table-column prop="senderName" label="学生姓名" width="150" />
<el-table-column prop="examName" label="试卷名称" width="150" />
<el-table-column prop="grade" label="年级" width="100" />
<el-table-column prop="class1" label="班级" width="100" />
<el-table-column prop="score" label="得分" width="180" />
<el-table-column prop="ranking" label="排名" width="180" />
<!-- 状态列已发布为绿色未发布为红色 -->
<el-table-column label="状态" width="160">
<template slot-scope="scope">
<el-tag :type="scope.row.status === 1 ? 'success' : 'danger'">
{{ scope.row.status === 1 ? '已发布' : '未发布' }}
</el-tag>
</template>
</el-table-column>
<!-- 操作列 -->
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<el-button type="primary" size="small" @click="viewDetail(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
:current-page="pageNum"
:page-size="pageSize"
:total="total"
@current-change="handlePageChange"
layout="total, prev, pager, next, jumper"
style="text-align: right; margin-top: 20px;"
/>
</el-main>
</el-container>
</el-container>
</template>
<script>
import Header from "@/components/Teacher/Header.vue";
import Aside from "@/components/Teacher/Aside.vue";
import axios from "axios";
export default {
name: "Score",
components: { Aside, Header },
data() {
return {
userId: "", // ID
collapseBtnClass: "el-icon-s-fold",
isCollapse: false,
sideWidth: 200,
logoTextShow: true,
searchQuery: {
name: "",
testID: "",
}, //
papers: [], //
pageNum: 1, //
pageSize: 10, //
total: 0, //
};
},
created() {
this.userId = this.$route.query.userId;
this.fetchScores(); //
},
methods: {
collapse() {
this.isCollapse = !this.isCollapse;
if (this.isCollapse) {
this.sideWidth = 64;
this.collapseBtnClass = "el-icon-s-unfold";
this.logoTextShow = false;
} else {
this.sideWidth = 200;
this.collapseBtnClass = "el-icon-s-fold";
this.logoTextShow = true;
}
},
//
async fetchScores() {
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/selectScoreList", //
{
params: {
pageNum: this.pageNum, //
pageSize: this.pageSize, //
name: this.searchQuery.name, //
testID: this.searchQuery.testID, //
},
headers: {
Authorization: `Bearer ${token}`,
},
}
);
if (response.data.code === 200) {
console.log(response.data);
// papers
this.papers = response.data.data.records || [];
this.total = response.data.data.total || 0; //
this.pageNum = response.data.data.current || 1; //
} else {
this.$message.error("查询异常!");
}
} catch (error) {
console.error("获取试卷数据失败", error);
}
},
//
viewDetail(paper) {
this.$router.push({
path: "/teacher/paper/detail",
query: {
testID: paper.testid, //
name: paper.examName,
},
});
},
//
handlePageChange(pageNum) {
this.pageNum = pageNum;
this.fetchScores(); //
},
},
};
</script>
<style scoped lang="scss">
/* 你可以在这里加入你的样式 */
.el-container {
margin: 0;
padding: 0;
height: 100%;
width: 100%;
}
.el-main {
padding: 20px;
}
</style>

@ -17,7 +17,11 @@
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' }"
:class="{ answered: answers[question.id]?.length > 0,
active: currentQuestionIndex === index,
correct: question.tf === 'true',
incorrect: question.tf === 'false'
}"
@click="scrollToQuestion(index)"
>
{{ index + 1 }}
@ -76,8 +80,8 @@
</div>
</template>
</div>
<p>你的答案<span>{{ question.answer }}</span></p>
<p>正确答案<span>{{ question.idanswer }}</span></p>
<p>你的答案<span>{{ question.idanswer }}</span></p>
<p>正确答案<span>{{ question.answer }}</span></p>
<p>分数{{ question.score }} </p>
<p v-if="question.analysis">{{ question.analysis }}</p>
</div>

Loading…
Cancel
Save