前端教师端完善试卷中心试卷的试卷编辑功能,修复学生端教师端的部分bug

main
yuan 4 months ago
parent 2e01100832
commit 1f23ba4798

@ -40,6 +40,18 @@ public class ExamDOController {
@Autowired
private IQuestionbankService iQuestionbankService;
@ApiOperation("试卷中增加题目")
@GetMapping("addQuestionByExamPaper")
public R<Integer> addQuestionByExamPaper(Long id,Long pid){
return R.ok(iExamCreateService.addPaperCreate(id,pid));
}
@ApiOperation("删除试卷中的试题")
@DeleteMapping("deleteQuestionByExamPaper")
public R<Integer> deleteQuestionByExamPaper(Long id,Long pid){
return R.ok(iExamCreateService.deletePaperCreate(id,pid));
}
@ApiOperation("添加题目")
@PostMapping("addQuestion")
public R<Integer> addQuestion(@RequestBody QuestionbankVo2 questionbankVo2){
@ -64,6 +76,12 @@ public class ExamDOController {
return R.ok(iExamDOService.selectExamDoList(pagenum,pagesize,subject,questiontype,difficulty));
}
@ApiOperation("题库列表(不分页)")
@GetMapping("selectListNotPage")
public R<List<QuestionbankVo2>> selectListNotPage(){
return R.ok(iExamDOService.selectListNotPage());
}
@ApiOperation("预览")
@GetMapping("preview")
public R<QuestionbankVo1> preview(Long id){

@ -63,7 +63,7 @@ public class StudentExamPaperController {
@ApiOperation("试卷查询")
@GetMapping("examPaperByTypeAndSubject")
public R<IPage<ExamPaperDO1>> examPaperByTypeAndSubject(int pagenum,int pagesize,String type,String subject){
public R<List<ExamPaperDO1>> examPaperByTypeAndSubject(String type,String subject){
SysUser sysUser = SecurityUtils.getLoginUser().getUser();
Long id = sysUser.getUserId();
StudentClass studentClass = iStudentClassService.selectById(id);
@ -76,9 +76,6 @@ public class StudentExamPaperController {
List<ExamPaperDO1> list1 = new ArrayList<>();
for(ClassExamPaper classExamPaper : list ){
ExamPaper examPaper = iExamPaperService.selectById(classExamPaper.getId());
if(examPaper.getExamPaperStatus()==0L){
continue;
}
if(type!=null&&!examPaper.getType().equals(type)){
continue;
}
@ -103,10 +100,7 @@ public class StudentExamPaperController {
examPaperDO1.setTotalscore(total);
list1.add(examPaperDO1);
}
Page<ExamPaperDO1> page = new Page<>(pagenum,pagesize);
IPage<ExamPaperDO1> iPage = new Page<>(page.getCurrent(),page.getSize(),page.getTotal());
iPage.setRecords(list1);
return R.ok(iPage);
return R.ok(list1);
}

@ -101,6 +101,7 @@ public class TeacherAnswerSheetController {
List<Long> list1 = iStudentClassService.getStudentClassByClassExamPaperList(list)
.stream()
.map(StudentClass::getStudentid)
.distinct()
.collect(Collectors.toList());
return R.ok(iMarkedtestService.selectByStudentList(sysUser.getUserId(),list1));
}

@ -10,6 +10,7 @@ import com.ruoyi.test.domain.ClassExamPaper;
import com.ruoyi.test.domain.DO.*;
import com.ruoyi.test.domain.ExamPaper;
import com.ruoyi.test.domain.TeacherManageClass;
import com.ruoyi.test.domain.Vo.ExamPaperVo;
import com.ruoyi.test.domain.Vo.QuestionbankVo1;
import com.ruoyi.test.seriver.*;
import io.swagger.annotations.Api;
@ -46,6 +47,18 @@ public class TeacherExamPaperController {
@Autowired
private IQuestionbankService iQuestionbankService;
@ApiOperation("创建试卷")
@PostMapping("newExamPaper")
public R<Integer> addExamPaper(@RequestBody ExamPaper examPaper){
System.out.println("============"+examPaper);
SysUser sysUser = SecurityUtils.getLoginUser().getUser();
Long id = sysUser.getUserId();
examPaper.setGlId(id);
examPaper.setStatus(0);
examPaper.setExamPaperStatus(0);
return R.ok(iExamPaperService.newExamPaper(examPaper));
}
@ApiOperation("试卷题目获取")
@GetMapping("getExamPaperQuestions")
public R<List<QuestionbankVo1>> getExamPaperQuestions(Long id){

@ -3,6 +3,7 @@ package com.ruoyi.test.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.test.domain.DO.PaperCreateDO;
import com.ruoyi.test.domain.ExamPaper;
import com.ruoyi.test.domain.Vo.ExamPaperVo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@ -12,4 +13,6 @@ public interface ExamPaperMapper extends BaseMapper<ExamPaper> {
int addPaperExam(@Param("paperCreateDO") PaperCreateDO paperCreateDO);
int updateExamPaper(@Param("testid")Long testid);
int newExamPaper(@Param("examPaper")ExamPaper examPaper);
}

@ -28,4 +28,6 @@ public interface IExamDOService {
int addfrQuestions(Questionbank questionbank);
List<QuestionbankVo2> selectListNotPage();
}

@ -7,6 +7,7 @@ import com.ruoyi.test.domain.TeacherManageClass;
import com.ruoyi.test.domain.TeacherSubject;
import com.ruoyi.test.domain.Vo.ExamPaperVo;
import com.ruoyi.test.domain.Vo.QuestionbankVo1;
import io.swagger.models.auth.In;
//import com.ruoyi.test.domain.Vo.ExamCreateVo;
import java.util.List;
@ -48,4 +49,5 @@ public interface IExamPaperService {
List<QuestionbankVo1> getExamPaperQuestions(Long id);
Integer newExamPaper(ExamPaper examPaper);
}

@ -23,6 +23,7 @@ import org.springframework.stereotype.Service;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@ -135,4 +136,23 @@ public class ExamDOServiceImpl extends ServiceImpl<ExamDOMapper, ExamDO> impleme
return questionbankMapper.addExamCreate(questionbank);
}
@Override
public List<QuestionbankVo2> selectListNotPage() {
LambdaQueryWrapper<Questionbank> queryWrapper = new LambdaQueryWrapper<>();
List<Questionbank> list = questionbankMapper.selectList(queryWrapper);
List<QuestionbankVo2> list1 = new ArrayList<>();
for (Questionbank questionbank : list) {
QuestionbankVo2 questionbankVo2 = new QuestionbankVo2();
BeanUtils.copyProperties(questionbank, questionbankVo2);
Gson gson = new Gson();
// 将 JSON 字符串转换为 List<Map<String, String>>
List<Map<String, String>> listMap = gson.fromJson(questionbank.getChance(), List.class);
questionbankVo2.setChance(listMap);
list1.add(questionbankVo2);
}
return list1;
}
}

@ -223,6 +223,11 @@ public class ExamPaperServiceImpl extends ServiceImpl<ExamPaperMapper, ExamPaper
return questionbankVo1s;
}
@Override
public Integer newExamPaper(ExamPaper examPaper) {
return examPaperMapper.newExamPaper(examPaper);
}
// @Override
// public List<ExamPaper> totalExamPaper(List<TeacherManageClass> list, List<TeacherSubject> list2) {
// List<ExamPaper> list1 = new ArrayList<>();

@ -30,4 +30,28 @@
SET status = 1
WHERE id = #{testid}
</update>
<insert id="newExamPaper" parameterType="ExamPaper">
insert into exam_paper(
gl_id,
grade,
subject,
name,
type,
time,
status,
exam_paper_status,
createtime
)values (
#{examPaper.glId},
#{examPaper.grade},
#{examPaper.subject},
#{examPaper.name},
#{examPaper.type},
#{examPaper.time},
#{examPaper.status},
#{examPaper.examPaperStatus},
Now()
)
</insert>
</mapper>

@ -24,7 +24,7 @@
#{markedtest.tquestions},
#{markedtest.totalquestions},
#{markedtest.time},
#{markedtest.finishtime}
#{markedtest.finishtime},
#{markedtest.status}
)
</insert>

@ -82,7 +82,7 @@ export default {
components: {Aside, Header},
data() {
return {
paperTypes: ["固定试卷","随机试卷"], //
paperTypes: ["固定试卷","班级试卷"], //
subjects: ["语文", "数学"], //
selectedType: "班级试卷", //
selectedSubject: "语文", //
@ -168,7 +168,7 @@ export default {
return false;
}
},
async fetchPapers(page = 1, size = 10) {
async fetchPapers() {
const token = this.$store.state.tokens[this.userId];
if (!token) {
alert("用户未登录,请重新登录!");
@ -177,17 +177,10 @@ export default {
}
try {
this.loading = true;
// page size
const pageNumber = page || 1; // 使 1
const pageSize = size || 10; // 使 10
const response = await axios.get(
`http://localhost:8080/student/examPaper/examPaperByTypeAndSubject`,
{
params: {
pagenum: pageNumber,
pagesize: pageSize, // pagesize
type: this.selectedType, //
subject: this.selectedSubject, //
},
@ -197,13 +190,13 @@ export default {
},
}
);
console.log("responser",response);
console.log("responser",response.data);
if (response.data.code === 200) {
const { records } = response.data.data;
const data = response.data.data;
const updatedRecords = await Promise.all(
records.map(async (record) => {
data.map(async (record) => {
const hasTaken = await this.checkExamStatus(record.id);
return {
id: record.id,
@ -216,6 +209,7 @@ export default {
};
})
);
console.log("updatedRecords",updatedRecords);
this.papers = updatedRecords;
console.log("更新后的试卷数据:", updatedRecords);
} else {

@ -227,7 +227,7 @@ export default {
//
const unanswered = this.questions.filter(
(q) => !this.answers[q.id] || (typeof this.answers[q.id] === 'string' && this.answers[q.id].trim() === "")
(q) => !this.answers[q.id] || (Array.isArray(this.answers[q.id]) && this.answers[q.id].length === 0)
);
if (unanswered.length > 0) {
@ -237,6 +237,13 @@ export default {
}
}
if(this.remainingTime > 0){
const confirmSubmit = confirm(`还有 ${Math.round(this.remainingTime / 60) } 分钟,是否仍然提交试卷?`);
if (!confirmSubmit) {
return; // 退
}
}
const answerList = Object.keys(this.answers).map((questionId) => ({
id: Number(questionId),
answer: Array.isArray(this.answers[questionId])

@ -161,7 +161,8 @@ export default {
'Content-Type': 'application/json',
}
});
if (response.data.code == 200) {
console.log('response', response);
if (response.data.code === 200) {
this.examPapers = response.data.data;
this.filteredExamPapers = [...this.examPapers]; // Initially, show all exam papers
console.log('examPapers', this.filteredExamPapers);

@ -1,33 +1,26 @@
<template>
<el-container style="min-height: 100vh; width: 100%">
<!-- Left sidebar -->
<el-aside :width="sideWidth + 'px'" style="background-color: #f4f7fc; box-shadow: 2px 0 6px rgba(0, 21, 41, 0.15)">
<Aside :isCollapse="isCollapse" :logoTextShow="logoTextShow" />
</el-aside>
<!-- Main content -->
<el-container style="width: calc(100% - 200px);">
<el-header style="border-bottom: 1px solid #e1e4ea; padding: 10px 20px; background: #fff;">
<Header :collapseBtnClass="collapseBtnClass" :collapse="collapse" />
</el-header>
<el-main style="padding: 20px;">
<!-- 搜索框 -->
<el-input
v-model="searchQuery"
placeholder="请输入试卷名称进行搜索"
suffix-icon="el-icon-search"
style="width: 300px; margin-left: auto;"
v-model="searchQuery"
placeholder="请输入试卷名称进行搜索"
suffix-icon="el-icon-search"
style="width: 300px; margin-right: 10px;"
/>
<!-- 试卷列表 -->
<el-button @click="openNewExamDialog" type="primary" size="small">新建试卷</el-button>
<el-table :data="filteredExams" style="width: 100%">
<el-table-column prop="id" label="ID" width="100"></el-table-column>
<el-table-column prop="name" label="名称"></el-table-column>
<el-table-column prop="subject" label="学科"></el-table-column>
<el-table-column prop="type" label="类型"></el-table-column>
<!-- 操作列查看试卷 -->
<el-table-column label="操作" width="200">
<template slot-scope="scope">
<el-button @click="openExamDialog(scope.row)" type="primary" size="small">查看试卷</el-button>
@ -36,21 +29,19 @@
</el-table-column>
</el-table>
<!-- 分页 -->
<el-pagination
:current-page="currentPage"
:page-size="pageSize"
:total="totalExams"
@current-change="handlePageChange"
layout="total, prev, pager, next, jumper"
:current-page="currentPage"
:page-size="pageSize"
:total="totalExams"
@current-change="handlePageChange"
layout="total, prev, pager, next, jumper"
/>
<!-- 查看试卷弹窗 -->
<el-dialog :visible.sync="isExamDialogVisible" title="试卷内容" width="80%" :close-on-click-modal="false">
<!-- 设置对话框的样式 -->
<el-button @click="openAddQuestionDialog" type="primary" size="small" style="margin-bottom: 20px;">新增题目</el-button>
<div v-if="examQuestions.length > 0" class="exam-table-container">
<el-table :data="examQuestions" style="width: 100%">
<!-- 表格列 -->
<el-table-column label="ID" prop="id" width="60"></el-table-column>
<el-table-column label="题目" prop="content" width="300"></el-table-column>
@ -68,6 +59,13 @@
</div>
</template>
</el-table-column>
<!-- 删除题目列 -->
<el-table-column label="操作" width="180">
<template v-slot="scope">
<el-button @click="deleteQuestion(scope.row.id,)" type="danger" size="small">删除</el-button>
</template>
</el-table-column>
</el-table>
</div>
<span slot="footer" class="dialog-footer">
@ -75,6 +73,20 @@
</span>
</el-dialog>
<el-dialog :visible.sync="isAddQuestionDialogVisible" title="选择题目" width="60%">
<el-table :data="questionBank" style="width: 100%">
<el-table-column label="题目" prop="content" width="300"></el-table-column>
<el-table-column label="操作" width="180">
<template v-slot="scope">
<el-button @click="addQuestionToExam(scope.row.id)" type="primary" size="small">添加到试卷</el-button>
</template>
</el-table-column>
</el-table>
<span slot="footer" class="dialog-footer">
<el-button @click="isAddQuestionDialogVisible = false">关闭</el-button>
</span>
</el-dialog>
<!-- 分发弹窗 -->
<el-dialog :visible.sync="isDistributionDialogVisible" title="分发试卷">
<el-table :data="classList" style="width: 100%">
@ -97,11 +109,45 @@
<el-button @click="isDistributionDialogVisible = false">取消</el-button>
</span>
</el-dialog>
<!-- 新建试卷弹窗 -->
<el-dialog :visible.sync="isNewExamDialogVisible" title="新建试卷" width="60%">
<el-form :model="newExamForm" ref="newExamForm" label-width="80px">
<el-form-item label="名称">
<el-input v-model="newExamForm.name" placeholder="请输入试卷名称" style="width: 207.22px"></el-input>
</el-form-item>
<el-form-item label="学科">
<el-select v-model="newExamForm.subject" placeholder="请选择学科">
<el-option label="语文" value="语文"></el-option>
<el-option label="数学" value="数学"></el-option>
<el-option label="英语" value="英语"></el-option>
</el-select>
</el-form-item>
<el-form-item label="年级">
<el-input v-model="newExamForm.grade" placeholder="请输入年级" style="width: 207.22px"></el-input>
</el-form-item>
<el-form-item label="类型">
<el-select v-model="newExamForm.type" placeholder="请选择类型">
<el-option label="班级试卷" value="班级试卷"></el-option>
<el-option label="固定试卷" value="固定试卷"></el-option>
</el-select>
</el-form-item>
<el-form-item label="时间">
<el-input v-model="newExamForm.time" placeholder="请输入考试时间(分钟)" style="width: 207.22px"></el-input>
</el-form-item>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="isNewExamDialogVisible = false">取消</el-button>
<el-button type="primary" @click="createExam"></el-button>
</span>
</el-dialog>
</el-main>
</el-container>
</el-container>
</template>
<script>
import Header from "@/components/Teacher/Header.vue";
import Aside from "@/components/Teacher/Aside.vue";
@ -126,6 +172,16 @@ export default {
currentPage: 1, //
pageSize: 10, //
totalExams: 0, //
isAddQuestionDialogVisible: false,//
questionBank: [],//
isNewExamDialogVisible: false,//
newExamForm: {
name: "",
subject: "",
grade: "",
type: "",
time: ""
},//
};
},
computed: {
@ -146,9 +202,67 @@ export default {
this.collapseBtnClass = this.isCollapse ? "el-icon-s-unfold" : "el-icon-s-fold";
this.logoTextShow = !this.isCollapse;
},
//
openAddQuestionDialog() {
this.fetchQuestionBank(); //
this.isAddQuestionDialogVisible = true;
},
//
async fetchQuestionBank() {
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/examcreate/selectListNotPage", {
headers: { Authorization: `Bearer ${token}` },
});
if (response.data.code === 200) {
this.questionBank = response.data.data; //
} else {
this.$message.error("获取题库失败");
}
} catch (error) {
console.error("获取题库失败:", error);
this.$message.error("获取题库失败");
}
},
//
async deleteQuestion(questionId) {
try {
const token = this.$store.state.tokens[this.userId];
if (!token) {
alert("用户未登录,请重新登录!");
this.$router.push("/login");
return;
}
const response = await axios.delete(`http://localhost:8080/examcreate/deleteQuestionByExamPaper`, {
params:{
id:questionId,
pid:this.selectedExam.id
},
headers: { Authorization: `Bearer ${token}` },
});
if (response.data.code === 200 && response.data.data > 0) {
this.$message.success("题目删除成功");
//
this.fetchExamQuestions(this.selectedExam.id);
} else {
this.$message.error("删除失败");
}
} catch (error) {
console.error("删除题目失败:", error);
this.$message.error("删除题目失败");
}
},
//
openExamDialog(exam){
console.log("22222",exam);
this.selectedExam = exam;
this.fetchExamQuestions(exam.id);
this.isExamDialogVisible = true;
},
@ -169,7 +283,6 @@ export default {
if (response.data.code === 200) {
this.examQuestions = response.data.data; //
console.log("response",this.examQuestions);
} else {
this.$message.error("获取试卷题目失败");
}
@ -179,6 +292,38 @@ export default {
}
},
//
async addQuestionToExam(questionId) {
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/examcreate/addQuestionByExamPaper", {
params:{
pid: this.selectedExam.id,
id: questionId,
},
headers: { Authorization: `Bearer ${token}` },
});
console.log(response.data);
if (response.data.code === 200 && response.data.data > 0) {
this.$message.success("题目已添加到试卷");
this.fetchExamQuestions(this.selectedExam.id); //
this.isAddQuestionDialogVisible = false; //
} else {
this.$message.error("添加失败");
}
} catch (error) {
console.error("添加题目失败:", error);
this.$message.error("添加题目失败");
}
},
//
openDistributionDialog(exam) {
this.selectedExam = exam;
@ -278,6 +423,35 @@ export default {
this.currentPage = page;
this.fetchExams(); //
},
openNewExamDialog() {
this.isNewExamDialogVisible = true;
},
async createExam() {
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/examPaper/newExamPaper", this.newExamForm,{
headers: { Authorization: `Bearer ${token}` },
});
console.log(response.data);
if(response.data.code === 200 && response.data.data > 0){
this.$message.success("试卷创建成功");
this.fetchExams();
this.isNewExamDialogVisible = false;
}else{
this.$message.error("试卷创建失败");
}
} catch (error) {
console.error("Error creating exam:", error);
}
},
},
created() {
this.userId = this.$route.query.userId;

Loading…
Cancel
Save