<!-- 试卷管理 -->
|
<template>
|
<div class="c">
|
<div class="bg">
|
<div class="main">
|
<!-- 带返回的标题 -->
|
<TitleIndex title='试卷管理'/>
|
<div class="content">
|
<div
|
style="padding-bottom:20px; border-bottom: 3px solid #409EFF;margin-bottom: 20px;display: flex; align-items: center;">
|
<el-page-header @back="goBack()">
|
</el-page-header>
|
<el-button
|
type="primary"
|
@click="addTemplate"
|
>新增模板
|
</el-button>
|
</div>
|
<!-- 搜索 -->
|
<div>
|
<el-form
|
:inline="true"
|
:model="queryParam"
|
label-width="80px"
|
>
|
<el-form-item>
|
<el-input v-model="queryParam.name" placeholder="模板名" clearable></el-input>
|
</el-form-item>
|
<el-form-item>
|
<el-select
|
v-model="queryParam.subjectId"
|
placeholder="全部科目"
|
clearable
|
>
|
<el-option v-for="item in subjects" :key="item.id" :label="item.name" :value="item.id"/>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="">
|
<el-button
|
style="width:100px;"
|
type="primary"
|
size="small"
|
@click="getPage"
|
>查询
|
</el-button>
|
</el-form-item>
|
</el-form>
|
</div>
|
<!-- 表格 -->
|
<el-table
|
:header-cell-style="getRowClass"
|
:data="tableData"
|
border
|
style="width: 100%;"
|
:row-style="{height:'40px'}"
|
:cell-style="{padding: '0'}"
|
>
|
<el-table-column
|
align="center"
|
prop="name"
|
label="模板名"
|
>
|
</el-table-column>
|
<el-table-column
|
align="center"
|
prop="subjectId"
|
label="科目"
|
>
|
<template slot-scope="scope">
|
{{ translate(scope.row.subjectId) }}
|
</template>
|
</el-table-column>
|
<el-table-column
|
align="center"
|
prop="suggestTime"
|
label="建议时长(分钟)"
|
>
|
</el-table-column>
|
<el-table-column
|
align="center"
|
prop="score"
|
label="分值"
|
>
|
</el-table-column>
|
<el-table-column
|
label="操作"
|
align="center"
|
>
|
<template slot-scope="scope">
|
<el-button type="text">预览</el-button>
|
<el-button type="text">编辑</el-button>
|
<el-button type="text" @click="deletePaper(scope.row)" class="link-left">删除</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
|
<div
|
class="flex"
|
style="justify-content:center;margin-top:20px;"
|
>
|
<pagination v-show="total>0" :total="total" :page.sync="queryParam.currentPage"
|
:limit.sync="queryParam.pageSize"
|
@pagination="getPage"/>
|
</div>
|
</div>
|
|
<!-- 添加试卷模板对话框 -->
|
<el-dialog :title="title" :visible.sync="open" width="600px" append-to-body>
|
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
<el-form-item label="模板名称" prop="name">
|
<el-input v-model="form.name" placeholder="请输入模板名称" style="width: 300px"/>
|
</el-form-item>
|
<el-form-item label="科目" prop="subjectId">
|
<el-select v-model="form.subjectId" placeholder="请选择科目" style="width: 300px">
|
<el-option
|
v-for="item in subjects"
|
:key="item.id"
|
:label="item.name"
|
:value="item.id"
|
/>
|
</el-select>
|
</el-form-item>
|
<el-form-item label="考试时长(分钟)" prop="suggestTime">
|
<el-input-number v-model="form.suggestTime" placeholder="请输入考试时长"/>
|
</el-form-item>
|
<el-form-item label="权限" prop="visibility">
|
<el-radio v-model="form.visibility" :label="1">私有</el-radio>
|
<el-radio v-model="form.visibility" :label="2">公开</el-radio>
|
</el-form-item>
|
<el-form-item label="多选题得分类型" prop="deductType" v-show="addedQuestionTypes.includes(2)"><!-- 有多选才出现 -->
|
<div>
|
<el-select v-model="form.deductType" placeholder="请选择多选题得分类型" style="width: 200px;margin-right: 30px">
|
<el-option
|
v-for="item in deductTypeList"
|
:key="item.value"
|
:label="item.name"
|
:value="item.value"
|
/>
|
</el-select>
|
<el-input-number v-model="form.score" placeholder="请输入多选得分分数"
|
v-show="form.deductType === 2 || form.deductType === 3"/>
|
</div>
|
</el-form-item>
|
<el-form-item prop="questionList" label-width="0">
|
<el-table
|
:summary-method="getSummaries"
|
show-summary
|
:data="questionList"
|
style="width: 100%;">
|
<el-table-column
|
prop="questionType"
|
label="题目类型"
|
width="180"
|
>
|
<template slot-scope="scope">
|
<div> {{ translateQuestionType(scope.row.questionType) }}</div>
|
</template>
|
</el-table-column>
|
<el-table-column
|
prop="num"
|
label="题目数量"
|
width="180">
|
</el-table-column>
|
<el-table-column
|
prop="score"
|
label="每题分数">
|
</el-table-column>
|
<el-table-column
|
fixed="right"
|
width="100">
|
<template slot-scope="scope">
|
<el-button
|
type="text"
|
size="small"
|
@click="editQuestion(scope.row)">
|
编辑
|
</el-button>
|
<el-button
|
type="text"
|
size="small"
|
@click="removeQuestion(scope.row)">
|
移除
|
</el-button>
|
</template>
|
</el-table-column>
|
</el-table>
|
<el-button type="success" @click="nextAdd()" size="mini" plain>添加</el-button>
|
</el-form-item>
|
</el-form>
|
<div slot="footer" class="dialog-footer">
|
<el-button type="primary" @click="submitForm">确 定</el-button>
|
<el-button @click="cancel">取 消</el-button>
|
</div>
|
</el-dialog>
|
|
<!-- 添加题目对话框 -->
|
<el-dialog :title="questionTitle" :visible.sync="questionOpen" width="400px" append-to-body>
|
<el-form ref="questionForm" :model="questionForm" :rules="questionRules">
|
<el-form-item label="题目类型" prop="questionType">
|
<el-select v-model="questionForm.questionType" placeholder="请选择题目类型">
|
<el-option
|
v-for="item in questionTypeList"
|
:key="item.value"
|
:label="item.name"
|
:value="item.value"
|
:disabled="addedQuestionTypes.includes(item.value)"/><!-- 禁用已添加的选项 -->
|
</el-select>
|
</el-form-item>
|
<el-form-item label="题目数量" prop="num" style="margin-left: 10px">
|
<el-input-number v-model="questionForm.num" placeholder="请输入题目数量" :precision="0"/>
|
</el-form-item>
|
<el-form-item label="每题分数" prop="score" style="margin-left: 10px">
|
<el-input-number v-model="questionForm.score" placeholder="请输入每题分数" :precision="1"/>
|
</el-form-item>
|
</el-form>
|
<div slot="footer" class="dialog-footer">
|
<el-button type="primary" @click="addQuestion">确 定</el-button>
|
<el-button @click="questionCancel">取 消</el-button>
|
</div>
|
</el-dialog>
|
</div>
|
</div>
|
</div>
|
|
</template>
|
<script>
|
import {
|
getExamTemplates,
|
getExamTemplateById,
|
deleteExamTemplateById,
|
editExamTemplate,
|
addExamTemplate
|
} from '@/api/examTemplate'
|
import subjectApi from '@/api/subject'
|
import Pagination from "@/components/Pagination"
|
|
export default {
|
components: {Pagination},
|
data() {
|
var validateDeductType = (rule, value, callback) => {
|
const index = this.addedQuestionTypes.findIndex(item => item.questionType === 2)
|
if (index !== -1 && (!value || value === '')) {
|
callback(new Error('请选择多选题得分方式'));
|
} else {
|
callback();
|
}
|
}
|
return {
|
// 弹出层标题
|
title: "",
|
questionTitle: "",
|
// 是否显示弹出层
|
open: false,
|
questionOpen: false,
|
// 总条数
|
total: 0,
|
queryParam: {
|
name: null,
|
subjectId: null,
|
currentPage: 1,
|
pageSize: 10
|
},
|
form: {
|
visibility: 1
|
},
|
questionForm: {},
|
tableData: [],
|
subjects: [],
|
deductTypeList: [
|
{name: '答错不得分', value: 1},
|
{name: '漏选得固定分值,包含错误选项不得分', value: 2},
|
{name: '每对一题得相应分值,包含错误选项不得分', value: 3},
|
],
|
questionTypeList: [
|
{name: '单选题', value: 1},
|
{name: '多选题', value: 2},
|
{name: '填空题', value: 3},
|
{name: '判断题', value: 4},
|
{name: '简答题', value: 5},
|
{name: '计算题', value: 6},
|
],
|
questionList: [],
|
addedQuestionTypes: [],// 已添加的题目类型
|
// 表单校验
|
rules: {
|
name: [
|
{required: true, message: "试卷名称不能为空", trigger: "blur"}
|
],
|
subjectId: [
|
{required: true, message: "科目不能为空", trigger: "change"}
|
],
|
paperType: [
|
{required: true, message: "试卷类型不能为空", trigger: "change"}
|
],
|
suggestTime: [
|
{required: true, message: "考试时长不能为空", trigger: "blur"}
|
],
|
deductType: [
|
{validator: validateDeductType, trigger: 'change'}
|
],
|
},
|
questionRules: {
|
questionType: [
|
{required: true, message: "题目类型不能为空", trigger: "change"}
|
],
|
}
|
};
|
|
},
|
created() {
|
this.getSubjects();
|
this.getPage()
|
},
|
methods: {
|
//移除题目
|
removeQuestion(row) {
|
let index = this.questionList.findIndex(item => item.questionType === row.questionType && item.num === row.num && item.score === row.score);
|
this.questionList.splice(index, 1);
|
index = this.addedQuestionTypes.findIndex(item => item.questionType === row.questionType)
|
this.addedQuestionTypes.splice(index, 1);
|
},
|
//编辑题目
|
editQuestion(row) {
|
this.questionReset();
|
this.questionForm.questionType = row.questionType
|
this.questionForm.num = row.num
|
this.questionForm.score = row.score
|
this.questionTitle = "编辑题目"
|
this.questionOpen = true;
|
},
|
//题目列表合计方法
|
getSummaries(param) {
|
const {columns, data} = param;
|
const sums = [];
|
columns.forEach((column, index) => {
|
if (index === 0) {
|
sums[index] = '合计';
|
return;
|
}
|
if (index === 3) {
|
sums[index] = '';
|
return;
|
}
|
if (index === 2) { // 第三列是分数列
|
const values = data.map(item => Number(item.score) * Number(item.num) || 0);
|
if (!values.every(value => isNaN(value))) {
|
sums[index] = values.reduce((prev, curr) => {
|
const value = Number(curr);
|
if (!isNaN(value)) {
|
return prev + curr;
|
} else {
|
return prev;
|
}
|
}, 0);
|
sums[index] = sums[index].toFixed(2); // 格式化合计值,保留两位小数
|
sums[index] += ' 分';
|
}
|
} else if (index === 1) { // 第二列是题目数量列,在这里展示总数
|
const values = data.map(item => Number(item.num) || 0);
|
if (!values.every(value => isNaN(value))) {
|
sums[index] = values.reduce((prev, curr) => {
|
const value = Number(curr);
|
if (!isNaN(value)) {
|
return prev + curr;
|
} else {
|
return prev;
|
}
|
}, 0);
|
sums[index] += ' 题';
|
} else {
|
sums[index] = 'N/A';
|
}
|
} else {
|
sums[index] = 'N/A';
|
}
|
});
|
return sums;
|
},
|
translate(subjectId) {
|
const subject = this.subjects.find(subject => subject.id == subjectId);
|
return subject ? subject.name : '未知';
|
},
|
translateQuestionType(questionTypeId) {
|
const questionType = this.questionTypeList.find(questionType => questionType.value == questionTypeId);
|
return questionType ? questionType.name : '未知';
|
},
|
// 返回上一个页面
|
goBack() {
|
this.$router.back();
|
},
|
cancel() {
|
this.open = false;
|
},
|
questionCancel() {
|
this.questionOpen = false;
|
},
|
// 模板表单重置
|
reset() {
|
this.form = {
|
name: null,
|
subjectId: null,
|
suggestTime: null,
|
visibility: 1
|
};
|
this.addedQuestionTypes = []
|
this.questionList = []
|
},
|
// 问题表单重置
|
questionReset() {
|
this.questionForm = {
|
questionType: null,
|
num: null,
|
score: null,
|
};
|
},
|
// 修改表单头部的颜色
|
getRowClass() {
|
return "background:#d2d3d6";
|
},
|
//新增模板
|
addTemplate() {
|
this.reset();
|
this.title = "新增模板"
|
this.open = true;
|
},
|
//新增题目
|
nextAdd() {
|
this.questionReset();
|
this.questionTitle = "添加题目"
|
this.questionOpen = true;
|
},
|
deletePaper(row) {
|
deleteExamTemplateById(row.id).then(re => {
|
if (re.code === 1) {
|
this.getPage()
|
this.$message.success("删除成功")
|
} else {
|
this.$message.error(re.message)
|
}
|
})
|
},
|
getPage() {
|
this.listLoading = true
|
getExamTemplates(this.queryParam).then(re => {
|
const data = re.data
|
this.tableData = data.data
|
this.total = data.total
|
this.listLoading = false
|
})
|
},
|
// 获取科目
|
getSubjects() {
|
subjectApi.list().then(re => {
|
this.subjects = re.data
|
})
|
},
|
//添加或修改题目
|
addQuestion() {
|
this.$refs['questionForm'].validate(valid => {
|
if (valid) {
|
//新增
|
if (this.questionTitle === "添加题目") {
|
// 将题目类型添加到已添加列表中
|
if (!this.addedQuestionTypes.includes(this.questionForm.questionType)) {
|
this.addedQuestionTypes.push(this.questionForm.questionType);
|
}
|
this.questionList.push({
|
"questionType": this.questionForm.questionType,
|
"num": this.questionForm.num,
|
"score": this.questionForm.score
|
});
|
this.questionOpen = false;
|
} else if (this.questionTitle === "编辑题目") {
|
let index = this.questionList.findIndex(item => item.questionType === this.questionForm.questionType)
|
this.questionList.splice(index, 1, this.questionForm);
|
this.questionOpen = false;
|
}
|
}
|
})
|
},
|
//添加或修改模板
|
submitForm() {
|
this.$refs['form'].validate(valid => {
|
if (valid) {
|
let temp = {
|
...this.form,
|
};
|
temp.questionList = this.questionList
|
if (temp.id != null) {
|
editExamTemplate(temp).then(response => {
|
this.$message("修改成功");
|
this.open = false;
|
this.getPage();
|
});
|
} else {
|
addExamTemplate(temp).then(response => {
|
this.$message("新增成功");
|
this.open = false;
|
this.reset()
|
this.getPage();
|
});
|
}
|
} else {
|
console.log("error")
|
}
|
})
|
},
|
},
|
};
|
</script>
|
<style scoped lang="scss">
|
.flex {
|
display: flex;
|
}
|
|
// 内容
|
.content {
|
width: 1262px;
|
margin-bottom: 80px;
|
background-color: #fff;
|
padding: 20px 40px;
|
border-radius: 10px;
|
}
|
|
</style>
|