<template>
|
<div class="notice">
|
<el-dialog
|
v-model="dialogVisible"
|
width="800px"
|
:before-close="handleClose"
|
destroy-on-close
|
:close-on-press-escape="false"
|
:close-on-click-modal="false"
|
>
|
<el-form :model="state.form" size="default" ref="busRef" :rules="state.formRules" label-width="150px" >
|
<span style="font-size: 20px;font-weight: 800;margin-left: 20px">考试配置</span>
|
<div style="margin: 20px 20px">
|
<el-form-item label="考试名称:" prop="name">
|
<el-input v-model.trim="state.form.name" placeholder="请输入考试名称"></el-input>
|
</el-form-item>
|
<el-form-item label="课程分类:" prop="categoryId" >
|
<el-cascader
|
style="width: 100%"
|
ref="classifyRef"
|
v-model="state.form.categoryId"
|
:options="state.classifyList"
|
:props="state.props"
|
clearable
|
:show-all-levels="false"
|
@change="handleChange"
|
/>
|
</el-form-item>
|
</div>
|
<span style="font-size: 20px;font-weight: 800;margin-left: 20px">组卷信息</span>
|
<div style="display: flex">
|
<div class="group">
|
<div>
|
单选:<el-input style="max-width: 40px" v-model.trim="state.form.singleNum"></el-input> 题
|
</div>
|
<div style="margin-left: 20px">
|
每题:<el-input style="max-width: 40px" v-model.trim="state.form.singleScore"></el-input> 分
|
</div>
|
</div>
|
<div class="group" >
|
<div>
|
共
|
<span style="max-width: 30px" v-show="state.form.singleNum && state.form.singleScore">{{state.form.singleNum * state.form.singleScore}}</span>
|
<!-- <span v-else></span>-->
|
分
|
</div>
|
<el-select
|
clearable
|
v-model="state.form.singleBankId"
|
style="width: 160px;margin: 0 20px"
|
v-loadMoreNew:[reselectSingle]="handleScroll"
|
:popper-class="reselectSingle.name"
|
class="item-width"
|
placeholder="请选择单选题题库"
|
>
|
<el-option
|
v-for="item in state.bankListSingle"
|
:key="item.id"
|
:label="item.name"
|
:value="item.id"
|
/>
|
</el-select>
|
<el-radio-group v-model="state.form.singleMethod" >
|
<el-radio :label="1" style="max-width: 30px">随机</el-radio>
|
<el-radio :label="2" style="max-width: 30px">顺序</el-radio>
|
</el-radio-group >
|
<el-radio-group v-model="state.form.singleRebuild" style="margin-left: 30px" >
|
<el-radio :label="1" v-if="title === '编辑'" style="max-width: 30px">重新出题</el-radio>
|
</el-radio-group>
|
</div>
|
</div>
|
<div style="display: flex">
|
<div class="group">
|
<div>
|
多选:<el-input style="max-width: 40px" v-model="state.form.multiNum"></el-input> 题
|
</div>
|
<div style="margin-left: 20px">
|
每题:<el-input style="max-width: 40px" v-model="state.form.multiScore"></el-input> 分
|
</div>
|
</div>
|
<div class="group" >
|
<div >
|
共
|
<span style="max-width: 30px" v-show="state.form.multiNum && state.form.multiScore">{{state.form.multiNum * state.form.multiScore}}</span>
|
<!-- <span v-else></span>-->
|
分
|
</div>
|
<el-select
|
clearable
|
v-model="state.form.multiBankId"
|
style="width: 160px;margin: 0 20px"
|
v-loadMoreNew:[reselectSingle]="handleScroll"
|
:popper-class="reselectSingle.name"
|
class="item-width"
|
placeholder="请选择多选题题库"
|
>
|
<el-option
|
v-for="item in state.bankListSingle"
|
:key="item.id"
|
:label="item.name"
|
:value="item.id"
|
/>
|
</el-select>
|
<el-radio-group v-model="state.form.multiMethod" >
|
<el-radio :label="1" style="max-width: 30px">随机</el-radio>
|
<el-radio :label="2" style="max-width: 30px">顺序</el-radio>
|
</el-radio-group>
|
<el-radio-group v-model="state.form.multiRebuild" style="margin-left: 30px" >
|
<el-radio :label="1" v-if="title === '编辑'" style="max-width: 30px">重新出题</el-radio>
|
</el-radio-group>
|
</div>
|
</div>
|
<div style="display: flex">
|
<div class="group">
|
<div>
|
判断:<el-input style="max-width: 40px" v-model="state.form.judgeNum"></el-input> 题
|
</div>
|
<div style="margin-left: 20px">
|
每题:<el-input style="max-width: 40px" v-model="state.form.judgeScore"></el-input> 分
|
</div>
|
</div>
|
<div class="group" >
|
<div>
|
共
|
<span style="max-width: 30px" v-show="state.form.judgeNum && state.form.judgeScore">{{state.form.judgeNum * state.form.judgeScore}}</span>
|
<!-- <span v-else></span>-->
|
分
|
</div>
|
<el-select
|
clearable
|
v-model="state.form.judgeBankId"
|
style="width: 160px;margin: 0 20px"
|
v-loadMoreNew:[reselectSingle]="handleScroll"
|
:popper-class="reselectSingle.name"
|
class="item-width"
|
placeholder="请选择判断题题库"
|
>
|
<el-option
|
v-for="item in state.bankListSingle"
|
:key="item.id"
|
:label="item.name"
|
:value="item.id"
|
/>
|
</el-select>
|
<el-radio-group v-model="state.form.judgeMethod" >
|
<el-radio :label="1" style="max-width: 30px">随机</el-radio>
|
<el-radio :label="2" style="max-width: 30px">顺序</el-radio>
|
</el-radio-group>
|
<el-radio-group v-model="state.form.judgeRebuild" style="margin-left: 30px" >
|
<el-radio :label="1" v-if="title === '编辑'" style="max-width: 30px">重新出题</el-radio>
|
</el-radio-group>
|
</div>
|
</div>
|
<div style="display: flex">
|
<div class="group">
|
<div>
|
简答:<el-input style="max-width: 40px" v-model="state.form.easyNum"></el-input> 题
|
</div>
|
<div style="margin-left: 20px">
|
每题:<el-input style="max-width: 40px" v-model="state.form.easyScore"></el-input> 分
|
</div>
|
</div>
|
<div class="group" >
|
<div>
|
共
|
<span style="max-width: 30px" v-show="state.form.easyNum && state.form.easyScore">{{state.form.easyNum * state.form.easyScore}}</span>
|
<!-- <span v-else></span>-->
|
分
|
</div>
|
<el-select
|
clearable
|
v-model="state.form.easyBankId"
|
style="width: 160px;margin: 0 20px"
|
v-loadMoreNew:[reselectSingle]="handleScroll"
|
:popper-class="reselectSingle.name"
|
class="item-width"
|
placeholder="请选择简答题题库"
|
>
|
<el-option
|
v-for="item in state.bankListSingle"
|
:key="item.id"
|
:label="item.name"
|
:value="item.id"
|
/>
|
</el-select>
|
<el-radio-group v-model="state.form.easyMethod" >
|
<el-radio :label="1" style="max-width: 30px">随机</el-radio>
|
<el-radio :label="2" style="max-width: 30px">顺序</el-radio>
|
</el-radio-group>
|
<el-radio-group v-model="state.form.easyRebuild" style="margin-left: 30px" >
|
<el-radio :label="1" v-if="title === '编辑'" style="max-width: 30px">重新出题</el-radio>
|
</el-radio-group>
|
</div>
|
</div>
|
<span class="group" style="margin-bottom: 20px">共计:
|
{{state.form.judgeNum * state.form.judgeScore+state.form.multiNum * state.form.multiScore+state.form.singleNum * state.form.singleScore+state.form.easyNum * state.form.easyScore}}
|
分</span>
|
<div style="display: flex;justify-content: space-between;align-items: center">
|
<el-form-item label="合格分数:" prop="passScore">
|
<el-input-number v-model="state.form.passScore" :min="1" :max="1000" style="margin-right: 10px" /> (大于等于)
|
</el-form-item>
|
<el-form-item label="限制时长:" prop="limitTime">
|
<el-input v-model="state.form.limitTime" style="max-width: 200px" :disabled="state.form.limited === 0">
|
<template #append>分钟</template>
|
</el-input>
|
|
</el-form-item>
|
|
</div>
|
<div style="display: flex;justify-content: space-between;align-items: center">
|
<el-form-item label="是否限制考试时长:" prop="limited" style="margin-left: 60px">
|
<el-radio-group v-model="state.form.limited" @change="changeLimit" >
|
<el-radio :label="0" style="max-width: 30px">否</el-radio>
|
<el-radio :label="1">是</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
<el-form-item label="考试截止时间:" prop="deadline" style="margin-left: 60px">
|
<el-date-picker
|
v-model="state.form.deadline"
|
type="date"
|
placeholder="请选择截止时间"
|
format="YYYY-MM-DD"
|
value-format="YYYY-MM-DD 23:59:59"
|
/>
|
</el-form-item>
|
</div>
|
|
</el-form>
|
<template #footer>
|
<span class="dialog-footer">
|
<el-button @click="handleClose" size="default">取 消</el-button>
|
<el-button type="primary" @click="onSubmit" size="default" v-preReClick>确认</el-button>
|
</span>
|
</template>
|
</el-dialog>
|
</div>
|
</template>
|
<script setup>
|
import {reactive, ref, toRefs} from 'vue'
|
import {ElMessage} from "element-plus";
|
|
import {
|
getClassification
|
} from "@/api/onlineEducation/courseClass";
|
import {addCourse, checkCourseName, editCourse, getCourseById} from "@/api/onlineEducation/courseManage";
|
import {getToken} from "@/utils/auth";
|
import {delPic, getBannerById} from "@/api/onlineEducation/banner";
|
import Cookies from "js-cookie";
|
import {
|
addQuestionBank,
|
checkQuestionBankName,
|
editQuestionBank,
|
getQuestionBank
|
} from "@/api/onlineEducation/questionBank";
|
import {addExam, checkExamName, editExam} from "@/api/onlineEducation/exam";
|
import Student from "@/views/onlineEducation/groupExams/components/student.vue";
|
|
const dialogVisible = ref(false);
|
const title = ref("");
|
const busRef = ref();
|
const length = ref()
|
const emit = defineEmits(["getList"]);
|
const startUsername = ref('');
|
const classifyRef = ref(null)
|
|
const validateName = (rule, value, callback)=>{
|
if(value === ''){
|
callback(new Error('请输入考试名称'))
|
}else if(title.value === '编辑' && value === startUsername.value){
|
callback()
|
}else{
|
let param = {}
|
if(title.value === '新增') {
|
param = {
|
name:value
|
}
|
}else if(title.value === '编辑'){
|
param = {
|
name:value,
|
id: state.form.id
|
}
|
}
|
checkExamName(param).then((res)=>{
|
if(res.data == false){
|
callback(new Error('考试名称已被占用,请更换其他名称'))
|
}else{
|
callback()
|
}
|
})
|
}
|
}
|
const reselectSingle = reactive({
|
name: 'Single'
|
})
|
const state = reactive({
|
form: {
|
id: '',
|
name: '',
|
categoryId: null,
|
companyName: '',
|
companyId: null,
|
judgeBankId: null,
|
judgeMethod: 1,
|
judgeNum: null,
|
judgeScore: null,
|
multiBankId: null,
|
multiMethod: 1,
|
multiNum: null,
|
multiScore: null,
|
singleBankId: null,
|
singleMethod: 1,
|
singleNum: null,
|
singleScore: null,
|
limited: 1,
|
limitTime: null,
|
passScore: null,
|
judgeRebuild: null,
|
multiRebuild: null,
|
singleRebuild: null,
|
easyRebuild: null,
|
deadline: '',
|
easyNum: null,
|
easyScore: null,
|
easyBankId: null,
|
easyMethod: 1,
|
|
},
|
formRules: {
|
name: [{required: true, trigger: "blur", validator: validateName}],
|
categoryId: [{required: true, message: '请选择课程分类', trigger: 'blur'}],
|
limited: [{required: true, message: '请选择是否限制考试时长', trigger: 'blur'}],
|
limitTime: [{required: true, message: '请输入考试限制时长', trigger: 'blur'}],
|
passScore: [{required: true, message: '请输入合格分数', trigger: 'blur'}],
|
deadline: [{required: true, message: '请选择考试截止时间', trigger: 'blur'}]
|
},
|
classifyList: [],
|
isAdmin: false,
|
props: {
|
checkStrictly: true,
|
},
|
bankListSingle: [],
|
bankSinglePageNum: 1, // 当前页码
|
bankSinglePageSize: 10, // 每页显示的数量
|
hasMoreItemsSingle: null, // 是否还有更多选项
|
})
|
|
const openDialog = async (type, value) => {
|
await getClassifyList();
|
await loadMoreBankData()
|
const userInfo = JSON.parse(Cookies.get('userInfo'))
|
console.log("userInfo",userInfo)
|
if(userInfo.userType === 0){
|
state.isAdmin = true;
|
state.form.companyName = ''
|
state.form.companyId = null
|
}else {
|
state.isAdmin = false;
|
state.form.companyName = userInfo.companyName
|
state.form.companyId = userInfo.companyId
|
}
|
title.value = type === 'addFirst' || type === 'add' ? '新增' : type ==='edit' ? '编辑' : '' ;
|
if(type === 'edit') {
|
state.form = value
|
state.form.easyNum = state.form.easyNum ? state.form.easyNum: null
|
state.form.easyScore = state.form.easyScore ? state.form.easyScore: null
|
state.form.singleNum = state.form.singleNum ? state.form.singleNum: null
|
state.form.singleScore = state.form.singleScore ? state.form.singleScore: null
|
state.form.multiNum = state.form.multiNum ? state.form.multiNum: null
|
state.form.multiScore = state.form.multiScore ? state.form.multiScore: null
|
state.form.judgeNum = state.form.judgeNum ? state.form.judgeNum: null
|
state.form.judgeScore = state.form.judgeScore ? state.form.judgeScore: null
|
startUsername.value = value.name;
|
}else if(type === 'add' && value ){
|
state.form.parentId = value.id
|
}
|
dialogVisible.value = true;
|
}
|
|
const onSubmit = async () => {
|
// if(state.isAdmin){
|
// ElMessage({
|
// type: 'warning',
|
// message: '管理员暂无权限'
|
// });
|
// return;
|
// }
|
const total = state.form.judgeNum * state.form.judgeScore+state.form.multiNum * state.form.multiScore+state.form.singleNum * state.form.singleScore+state.form.easyNum * state.form.easyScore
|
if(state.form.passScore > total){
|
ElMessage({
|
type: 'warning',
|
message: '合格分数不能大于总分'
|
});
|
return;
|
}
|
// if(!(state.form.judgeBankId || state.form.multiBankId || state.form.singleBankId)){
|
// ElMessage({
|
// type: 'warning',
|
// message: '请选择题库'
|
// });
|
// return;
|
// }
|
const valid = await busRef.value.validate();
|
if(valid){
|
if(title.value === '新增'){
|
const {id, ...data} = JSON.parse(JSON.stringify(state.form))
|
const res = await addExam(data)
|
if(res.code === 200){
|
ElMessage({
|
type: 'success',
|
message: '新增成功'
|
});
|
}else{
|
ElMessage.warning(res.message)
|
}
|
emit("getList")
|
busRef.value.clearValidate();
|
reset();
|
dialogVisible.value = false;
|
}else if(title.value === '编辑'){
|
const {...data} = JSON.parse(JSON.stringify(state.form))
|
const res = await editExam(data)
|
if(res.code === 200){
|
ElMessage({
|
type: 'success',
|
message: '编辑成功'
|
});
|
}else{
|
ElMessage.warning(res.message)
|
}
|
emit("getList")
|
busRef.value.clearValidate();
|
reset();
|
dialogVisible.value = false;
|
}
|
}
|
}
|
const getClassifyList = async () => {
|
const res = await getClassification();
|
if(res.code === 200){
|
state.classifyList = recursion(res.data)
|
}else{
|
ElMessage.warning(res.message)
|
}
|
}
|
const recursion = (data) => {
|
let tmp = []
|
for (let i = 0; i < data.length; i++) {
|
let item = data[i]
|
// children为空
|
if (item.children&& item.children.length==0) {
|
tmp.push({
|
value: item.id,
|
label: item.name
|
})
|
// 有children
|
} else {
|
tmp.push({
|
value: item.id,
|
label: item.name,
|
children:recursion(item.children)
|
})
|
}
|
}
|
return tmp;
|
}
|
const handleChange = ()=> {
|
console.log("label====",classifyRef.value.getCheckedNodes()[0].value)
|
state.form.categoryId = classifyRef.value.getCheckedNodes()[0].value
|
// 我这里只是打印了一下label的值哦,需要赋值的话自己去赋值哦
|
if (classifyRef.value.popperVisible) {
|
classifyRef.value.togglePopperVisible()
|
}
|
}
|
|
const handleClose = () => {
|
busRef.value.clearValidate();
|
reset();
|
dialogVisible.value = false;
|
emit("getList")
|
|
}
|
const reset = () => {
|
state.form = {
|
id: '',
|
name: '',
|
categoryId: null,
|
companyName: '',
|
companyId: null,
|
judgeBankId: null,
|
judgeMethod: 1,
|
judgeNum: null,
|
judgeScore: null,
|
multiBankId: null,
|
multiMethod: 1,
|
multiNum: null,
|
multiScore: null,
|
singleBankId: null,
|
singleMethod: 1,
|
singleNum: null,
|
singleScore: null,
|
limited: 1,
|
limitTime: null,
|
passScore: null,
|
judgeRebuild: null,
|
multiRebuild: null,
|
singleRebuild: null,
|
easyRebuild: null,
|
easyNum: null,
|
easyScore: null,
|
easyBankId: null,
|
easyMethod: 1,
|
deadline: ''
|
}
|
state.bankListSingle = [];
|
state.bankSinglePageNum = 1;
|
state.bankSinglePageSize = 10;
|
}
|
const handleScroll = () => {
|
if(state.bankSinglePageNum >= state.hasMoreItemsSingle) return
|
state.bankSinglePageNum++;
|
loadMoreBankData()
|
|
}
|
const loadMoreBankData = async () => {
|
console.log(' Bank');
|
const queryParams = {
|
pageNum: state.bankSinglePageNum,
|
pageSize: state.bankSinglePageSize,
|
}
|
const res = await getQuestionBank(queryParams)
|
if (res.code == 200) {
|
state.hasMoreItemsSingle = res.data.totalPage
|
const data = res.data
|
state.bankListSingle = state.bankListSingle.concat(data.list)
|
}else{
|
ElMessage.warning(res.message)
|
}
|
}
|
|
const changeLimit = (val) => {
|
state.form.limitTime = null
|
if(val === 0) {
|
state.form.limitTime = 0
|
}
|
|
}
|
defineExpose({
|
openDialog
|
});
|
|
</script>
|
|
<style scoped lang="scss">
|
.notice{
|
:deep(.el-form .el-form-item__label) {
|
font-size: 15px;
|
}
|
.file {
|
display: flex;
|
flex-direction: column;
|
align-items: flex-start;
|
}
|
.group{
|
display: flex;
|
align-items:center;
|
font-size: 15px;
|
font-weight: 700;
|
margin: 20px 0 0 35px;
|
}
|
}
|
|
</style>
|