|
|
<template>
|
|
|
<el-container style="min-height: 100vh; width: 100%">
|
|
|
<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>
|
|
|
|
|
|
<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-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="grade" 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>
|
|
|
<el-button @click="openDistributionDialog(scope.row)" type="primary" size="small">发布情况</el-button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
|
|
|
<el-pagination
|
|
|
: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>
|
|
|
|
|
|
<!-- 如果题目有选项(chance),则显示选项列 -->
|
|
|
<el-table-column label="选项" width="400">
|
|
|
<template v-slot="scope">
|
|
|
<div v-if="scope.row.chance && scope.row.chance.length > 0">
|
|
|
<el-row v-for="(option, index) in scope.row.chance" :key="index" type="flex" justify="start" align="middle" class="option-row">
|
|
|
<el-col :span="24">
|
|
|
<el-tag :type="'success'" class="option-tag">
|
|
|
{{ option.label }}: {{ option.text }}
|
|
|
</el-tag>
|
|
|
</el-col>
|
|
|
</el-row>
|
|
|
</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">
|
|
|
<el-button @click="isExamDialogVisible = false" type="primary">关闭</el-button>
|
|
|
</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%">
|
|
|
<el-table-column prop="grade" label="年级"></el-table-column>
|
|
|
<el-table-column prop="class1" label="班级"></el-table-column>
|
|
|
<el-table-column label="状态" width="180">
|
|
|
<template slot-scope="scope">
|
|
|
<el-tag :type="scope.row.release === 1 ? 'success' : 'danger'" style="border-radius: 5px; font-size: 14px;">
|
|
|
{{ scope.row.release === 1 ? '已发布' : '未发布' }}
|
|
|
</el-tag>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
<el-table-column label="操作" width="180">
|
|
|
<template slot-scope="scope">
|
|
|
<el-button @click="distributeExam(selectedExam.id, scope.row)" type="success" size="small">发布</el-button>
|
|
|
</template>
|
|
|
</el-table-column>
|
|
|
</el-table>
|
|
|
<span slot="footer" class="dialog-footer">
|
|
|
<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";
|
|
|
import axios from "axios"; // 引入 axios 用于 API 请求
|
|
|
|
|
|
export default {
|
|
|
name: "TeacherExam",
|
|
|
components: { Aside, Header },
|
|
|
data() {
|
|
|
return {
|
|
|
collapseBtnClass: "el-icon-s-fold",
|
|
|
isCollapse: false,
|
|
|
sideWidth: 200,
|
|
|
logoTextShow: true,
|
|
|
exams: [], // 试卷列表
|
|
|
classList: [], // 班级列表
|
|
|
examQuestions: [], //试卷题目
|
|
|
selectedExam: null, // 当前选择的试卷
|
|
|
isDistributionDialogVisible: false, // 分发弹窗显示状态
|
|
|
isExamDialogVisible: false, //试卷题目显示状态
|
|
|
searchQuery: "", // 搜索框的内容
|
|
|
currentPage: 1, // 当前页码
|
|
|
pageSize: 10, // 每页显示的试卷数量
|
|
|
totalExams: 0, // 总试卷数
|
|
|
isAddQuestionDialogVisible: false,//新增题目弹窗
|
|
|
questionBank: [],//题库
|
|
|
isNewExamDialogVisible: false,//新建试卷弹窗
|
|
|
newExamForm: {
|
|
|
name: "",
|
|
|
subject: "",
|
|
|
grade: "",
|
|
|
type: "",
|
|
|
time: ""
|
|
|
},//新建试卷表单
|
|
|
};
|
|
|
},
|
|
|
computed: {
|
|
|
// 计算属性:根据搜索内容过滤试卷列表
|
|
|
filteredExams() {
|
|
|
if (this.searchQuery) {
|
|
|
return this.exams.filter((exam) =>
|
|
|
exam.name.toLowerCase().includes(this.searchQuery.toLowerCase()) // 搜索名称
|
|
|
);
|
|
|
}
|
|
|
return this.exams; // 如果没有输入搜索内容,返回所有试卷
|
|
|
},
|
|
|
},
|
|
|
methods: {
|
|
|
collapse() {
|
|
|
this.isCollapse = !this.isCollapse;
|
|
|
this.sideWidth = this.isCollapse ? 64 : 200;
|
|
|
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){
|
|
|
this.selectedExam = exam;
|
|
|
this.fetchExamQuestions(exam.id);
|
|
|
this.isExamDialogVisible = true;
|
|
|
},
|
|
|
|
|
|
// 获取试卷题目
|
|
|
async fetchExamQuestions(examId) {
|
|
|
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/examPaper/getExamPaperQuestions", {
|
|
|
params: { id: examId },
|
|
|
headers: { Authorization: `Bearer ${token}` },
|
|
|
});
|
|
|
|
|
|
if (response.data.code === 200) {
|
|
|
this.examQuestions = response.data.data; // 获取试卷题目
|
|
|
} else {
|
|
|
this.$message.error("获取试卷题目失败");
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error("获取试卷题目失败:", error);
|
|
|
this.$message.error("获取试卷题目失败");
|
|
|
}
|
|
|
},
|
|
|
|
|
|
// 将题目添加到试卷
|
|
|
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;
|
|
|
this.fetchClassList(exam.id);
|
|
|
this.isDistributionDialogVisible = true;
|
|
|
},
|
|
|
|
|
|
// 获取班级列表
|
|
|
async fetchClassList(testid) {
|
|
|
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/examPaper/selectClassRelease",{
|
|
|
params:{testid:testid},
|
|
|
headers:{Authorization:`Bearer ${token}`}
|
|
|
});
|
|
|
if(response.data.code===200){
|
|
|
this.classList = response.data.data;
|
|
|
}
|
|
|
}catch (error){
|
|
|
alert("用户未登录,请重新登录!");
|
|
|
this.$router.push("/login");
|
|
|
return;
|
|
|
}
|
|
|
},
|
|
|
|
|
|
// 更新班级分发状态
|
|
|
updateStatus(classInfo) {
|
|
|
console.log("更新状态:", classInfo.className, "为", classInfo.status);
|
|
|
},
|
|
|
|
|
|
// 向特定班级分发试卷
|
|
|
async distributeExam(testid,classInfo) {
|
|
|
try {
|
|
|
const token = this.$store.state.tokens[this.userId];
|
|
|
if (!token) {
|
|
|
alert("用户未登录,请重新登录!");
|
|
|
this.$router.push("/login");
|
|
|
return;
|
|
|
}
|
|
|
console.log("class1",classInfo.class1);
|
|
|
const response = await axios.post("http://localhost:8080/teacher/examPaper/addExamPaper", {
|
|
|
id: testid, // 直接在请求体中传递
|
|
|
grade: classInfo.grade,
|
|
|
class1: classInfo.class1
|
|
|
}, {
|
|
|
headers: { Authorization: `Bearer ${token}` }
|
|
|
});
|
|
|
|
|
|
console.log("response",response);
|
|
|
if(response.data.code===200){
|
|
|
this.$message.success("分发成功!");
|
|
|
this.fetchClassList(testid);
|
|
|
}else{
|
|
|
this.$message.error("分发失败!");
|
|
|
}
|
|
|
}catch (error){
|
|
|
console.log("数据异常"+error);
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
// 获取试卷列表
|
|
|
async fetchExams() {
|
|
|
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/examPaper/getExamPaper",{
|
|
|
params: {
|
|
|
pageNum: this.currentPage,
|
|
|
pageSize: this.pageSize,
|
|
|
},
|
|
|
headers: {
|
|
|
Authorization: `Bearer ${token}`,
|
|
|
}
|
|
|
});
|
|
|
if(response.data.code===200){
|
|
|
this.exams = response.data.data.records;
|
|
|
}else{
|
|
|
this.$message.error("获取数据异常");
|
|
|
}
|
|
|
}catch(error) {
|
|
|
console.error("获取试卷列表失败:", error);
|
|
|
}
|
|
|
},
|
|
|
|
|
|
// 处理分页页码变化
|
|
|
handlePageChange(page) {
|
|
|
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;
|
|
|
this.fetchExams(); // 页面加载时获取试卷列表
|
|
|
},
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
<style scoped lang="scss">
|
|
|
.el-table {
|
|
|
margin-top: 20px;
|
|
|
}
|
|
|
/* 对话框的样式 */
|
|
|
.el-dialog {
|
|
|
border-radius: 10px;
|
|
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
|
|
|
.el-dialog__header {
|
|
|
background-color: #409EFF;
|
|
|
color: white;
|
|
|
border-radius: 10px 10px 0 0;
|
|
|
font-weight: bold;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* 表格样式 */
|
|
|
.exam-table-container {
|
|
|
margin-top: 20px;
|
|
|
}
|
|
|
|
|
|
/* 设置选项行的间距 */
|
|
|
.option-row {
|
|
|
margin-bottom: 10px;
|
|
|
}
|
|
|
|
|
|
/* 标签样式 */
|
|
|
.option-tag {
|
|
|
border-radius: 20px;
|
|
|
font-size: 14px;
|
|
|
}
|
|
|
|
|
|
.no-option-tag {
|
|
|
background-color: #f56c6c;
|
|
|
color: white;
|
|
|
font-size: 14px;
|
|
|
}
|
|
|
|
|
|
/* 对话框底部按钮 */
|
|
|
.dialog-footer {
|
|
|
text-align: right;
|
|
|
padding: 15px;
|
|
|
}
|
|
|
</style>
|