Files
fe-manage/src/components/growthpath/GrowthExa.vue

847 lines
23 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div @click="openDrawer()">
<slot></slot>
</div>
<a-drawer
:visible="visible"
class="drawerStyle growth-exa"
width="1500"
placement="right"
>
<div class="drawerMain">
<div class="header">
<div class="headerTitle">
{{ title }}
</div>
<img
style="width: 29px; height: 29px; cursor: pointer"
src="../../assets/images/basicinfo/close.png"
@click="closeDrawer"
/>
</div>
<template v-if="step == 1">
<div
style="
display: flex;
flex-direction: row;
padding-top: 0px;
margin-top: 20px;
margin-left: 32px;
"
>
<div>
<button
v-show="formData.info.examType === 1 || !formData.id"
@click="changeExamType(1)"
style="width: 100px; cursor: pointer"
:class="formData.info.examType === 1 ? 'outer' : 'notOuter'"
>
系统考试
</button>
<button
v-show="formData.info.examType === 2 || !formData.id"
@click="changeExamType(2)"
style="width: 100px; cursor: pointer"
:class="formData.info.examType === 2 ? 'outer' : 'notOuter'"
>
外部考试
</button>
</div>
</div>
<div v-if="formData.info.examType === 1" class="contentMain">
<div class="main_left">
<div class="main_item">
<div class="signbox">
<div class="sign">
<img
src="@/assets/images/coursewareManage/asterisk.png"
alt=""
/>
</div>
<span style="margin-right: 3px">考试名称</span>
</div>
<div class="btnbox">
<a-input
v-model:value="formData.info.examinationName"
style="width: 400px; height: 40px; border-radius: 8px"
placeholder="请输入考试名称"
:maxlength="20"
showCount
/>
</div>
</div>
<div class="main_item">
<div class="signbox">
<div class="sign">
<img
src="@/assets/images/coursewareManage/asterisk.png"
alt=""
/>
</div>
<span style="margin-right: 3px">选择试卷</span>
</div>
<div v-if="formData.info.examinationPaperId">
<a-tag
closable
color="processing"
@close="delTag"
:closeIcon="true"
>
<span style="font-size: 14px; line-height: 33px">{{
formData.info.examinationTestName
}}</span>
</a-tag>
</div>
<div class="btnbox" @click="selectTest">
<button class="xkbtn" style="margin: 0">
{{ formData.info.examinationPaperId ? "重选" : "选择" }}试卷
</button>
</div>
<!-- <GrowthSelectTest
v-if="taskIndex < 0 || (taskIndex >= 0 && isEdit == false)"
v-model:id="formData.examinationPaperId"
v-model:name="formData.examinationTestName"
>
<div class="btnbox">
<button class="xkbtn" style="margin: 0">
{{ formData.examinationPaperId ? "重选" : "选择" }}试卷
</button>
</div>
</GrowthSelectTest> -->
</div>
<div class="main_item">
<div class="signbox">
<div class="sign">
<img
src="@/assets/images/coursewareManage/asterisk.png"
alt=""
/>
</div>
<span style="margin-right: 3px">考试时间</span>
</div>
<div class="btnbox">
<a-range-picker
style="width: 400px; height: 40px; border-radius: 8px"
:show-time="{ format: 'hh:mm' }"
format="YYYY-MM-DD HH:mm"
valueFormat="YYYY-MM-DD HH:mm"
v-model:value="dateTime"
@change="timeChange"
:placeholder="[' 开始时间', ' 结束时间']"
/>
</div>
</div>
<div class="main_item">
<div class="signbox">
<div class="sign">
<img
src="@/assets/images/coursewareManage/asterisk.png"
alt=""
/>
</div>
<span style="margin-right: 3px">考试时长</span>
</div>
<div class="select">
<a-input-number
:min="0"
:max="999999"
:precision="0"
style="width: 400px; height: 40px; border-radius: 8px"
v-model:value="formData.info.examinationDuration"
></a-input-number>
<span style="color: #999999; margin-left: 8px">分钟</span>
</div>
</div>
<div class="main_item">
<div class="signbox">
<div class="sign">
<img
src="@/assets/images/coursewareManage/asterisk.png"
alt=""
/>
</div>
<span style="margin-right: 3px">及格线</span>
</div>
<div class="btnbox">
<a-input-number
min="0"
v-model:value="formData.info.passLine"
style="width: 400px; height: 40px; border-radius: 8px"
/>
<span style="color: #999999; margin-left: 8px"></span>
</div>
</div>
<div class="main_item2">
<div class="signbox">
<span style="margin-right: 3px">考试说明</span>
</div>
<div class="textarea">
<a-textarea
v-model:value="formData.info.examinationExplain"
placeholder="请输入考试说明"
show-count
:maxlength="200"
:rows="6"
/>
</div>
</div>
<div class="main_item2">
<div class="signbox">
<span style="margin-right: 3px; margin-top: 10px"
>考试限制</span
>
</div>
<div class="kqszbox">
<div class="setbox">
<div class="timerbox">
<span>允许重复考试</span>
<a-input-number
:min="-1"
:max="999999"
:precision="0"
style="
width: 100px;
height: 32px;
border-radius: 8px;
overflow: hidden;
"
v-model:value="formData.info.examinationLimit"
></a-input-number>
<span style="color: #999999; margin-left: 8px"
>,-1表示无限制</span
>
</div>
</div>
</div>
</div>
<div class="main_item">
<div class="signbox">
<span style="margin-right: 3px">显示答案</span>
</div>
<div class="btnbox">
<a-radio-group
style="margin-right: 12px"
v-model:value="formData.info.showAnswers"
>
<a-radio :value="'1'">允许查看</a-radio>
<a-radio :value="'2'">不允许查看</a-radio>
</a-radio-group>
</div>
</div>
<div class="main_item">
<div class="signbox">
<span style="margin-right: 3px">显示解析</span>
</div>
<div class="btnbox">
<a-radio-group
style="margin-right: 12px"
v-model:value="formData.info.showAnalysis"
>
<a-radio :value="'1'">允许查看</a-radio>
<a-radio :value="'2'">不允许查看</a-radio>
</a-radio-group>
</div>
</div>
<div class="main_item">
<div class="signbox">
<span style="margin-right: 3px">评分模式</span>
</div>
<div class="btnbox">
<a-radio-group
style="margin-right: 12px"
v-model:value="formData.info.scoringModel"
>
<a-radio :value="'1'">最高一次</a-radio>
<a-radio :value="'2'">最后一次</a-radio>
</a-radio-group>
</div>
</div>
<div class="main_item">
<div class="signbox">
<span style="margin-right: 3px">试题排列</span>
</div>
<div class="btnbox">
<a-radio-group
style="margin-right: 12px"
v-model:value="formData.info.questionArrangement"
>
<a-radio :value="'1'">试题乱序</a-radio>
<a-radio :value="'2'">选项乱序</a-radio>
<a-radio :value="'3'">全部乱序</a-radio>
<a-radio :value="'4'">不乱序</a-radio>
</a-radio-group>
</div>
</div>
<div class="main_item" style="height: 20px"></div>
</div>
</div>
<div v-else class="contentMain">
<div class="main_left">
<div class="main_item">
<div class="signbox">
<div class="sign">
<img
src="@/assets/images/coursewareManage/asterisk.png"
alt=""
/>
</div>
<span style="margin-right: 3px">考试名称</span>
</div>
<div class="btnbox">
<a-input
v-model:value="formData.info.examinationName"
style="width: 400px; height: 40px; border-radius: 8px"
placeholder="请输入考试名称"
:maxlength="20"
showCount
/>
</div>
</div>
<div class="main_item">
<div class="signbox">
<div class="sign">
<img
src="@/assets/images/coursewareManage/asterisk.png"
alt=""
/>
</div>
<span style="margin-right: 3px">数据来源</span>
</div>
<div class="btnbox">
<a-input
v-model:value="formData.info.source"
style="width: 400px; height: 40px; border-radius: 8px"
placeholder="请输入数据来源"
show-count
:maxlength="420"
/>
</div>
</div>
<div class="main_item2">
<div class="signbox">
<span style="margin-right: 3px">考试说明</span>
</div>
<div class="textarea">
<a-textarea
v-model:value="formData.info.examinationExplain"
placeholder="请输入考试说明"
show-count
:maxlength="200"
:rows="6"
/>
</div>
</div>
</div>
</div>
<div class="main_btns">
<a-button class="btn2" @click="closeDrawer">取消</a-button>
<a-button class="btn2" @click="confirm">确定</a-button>
</div>
</template>
<div v-show="step == 2">
<GrowthSelectTest
ref="GrowthSelectTestRef"
:selectId="formData.info.examinationPaperId"
@confirm="selectTestConfirm"
@addTest="addTest"
>
</GrowthSelectTest>
</div>
<!-- 新建考试 -->
<div class="iframe-container" v-if="step == 3">
<iframe
id="iframe"
style="width: 100%; height: 100%; border: none"
:src="iframeUrl + '/exam/papers?addnew=true'"
name="myframe"
sandbox="allow-forms allow-downloads allow-scripts allow-same-origin allow-popups"
></iframe>
</div>
</div>
</a-drawer>
</template>
<script setup>
import { defineEmits, defineProps, ref, watch, computed } from "vue";
import GrowthSelectTest from "./GrowthSelectTest.vue";
import dayjs from "dayjs";
import { Form, message } from "ant-design-vue";
import { useResetRef } from "@/utils/useCommon";
import { saveTask } from "@/api/growthpath";
import { iframeUrl } from "@/api/method";
const props = defineProps({
type: Number,
// 选秀2 必修1
activeKey: String,
growId: String,
});
// 步骤数
const step = ref(1);
const GrowthSelectTestRef = ref(null);
// 选择试卷
const selectTest = () => {
// if (formData.value.examinationPaperId) {
// GrowthSelectTestRef.value.initData({
// id: formData.value.examinationPaperId,
// });
// }
step.value = 2;
};
//新增试卷
const addTest = () => {
step.value = 3;
};
// 选择试卷完毕
const selectTestConfirm = (data) => {
step.value = step.value - 1;
formData.value.info.examinationPaperId = data.id;
formData.value.info.examinationTestName = data.testName;
};
const title = computed(() => {
if (step.value == 1) {
return formData.value.id ? "编辑考试" : "添加考试";
} else if (step.value == 2) {
return "选择试卷";
} else if (step.value == 3) {
return "新建试卷";
}
});
const visible = ref(false);
const initValue = {
info: {
examinationName: "",
examinationPaperId: "",
examinationStartTime: "",
examinationEndTime: "",
examinationDuration: null,
passLine: "",
examType: 1,
source: "",
showAnswers: "2",
showAnalysis: "2",
scoringModel: "2",
questionArrangement: "4",
externalExplain: "",
examinationExplain: "",
type: 14,
targetId: props.growId,
},
};
const formData = useResetRef(initValue);
const innerRule = {
examinationName: [
{
required: true,
message: "请输入考试名称",
},
],
examinationPaperId: [
{
required: true,
message: "请输入选择试卷",
},
],
examinationStartTime: [
{
required: true,
message: "请输入考试时间",
},
],
examinationEndTime: [
{
required: true,
message: "请输入考试时间",
},
],
examinationDuration: [
{
required: true,
message: "请输入考试时长",
},
],
passLine: [
{
required: true,
message: "请输入及格线",
},
],
};
const outerRule = {
examinationName: [
{
required: true,
message: "请输入考试名称",
},
],
source: [
{
required: true,
message: "请输入数据来源",
},
],
};
const rulesRef = ref(innerRule);
const emit = defineEmits({});
const dateTime = ref([]);
const { resetFields, validate } = Form.useForm(formData.value.info, rulesRef);
watch(
() => formData.value.info.examType,
() => {
formData.value.info.examType === 1
? (rulesRef.value = innerRule)
: (rulesRef.value = outerRule);
}
);
const closeDrawer = () => {
// 新增完试卷需要更新数据
if (step.value == 3) {
GrowthSelectTestRef.value.fetch();
}
if (step.value > 1) {
step.value = step.value - 1;
} else {
formData.value.info = {};
visible.value = false;
formData.reset();
dateTime.value = [];
}
};
function timeChange(time, timeStr) {
formData.value.info.examinationStartTime = timeStr[0];
formData.value.info.examinationEndTime = timeStr[1];
}
// 系统考试
async function confirm() {
console.log(formData.value)
if (formData.value.info.examinationName.trim() == "") {
message.warning("请输入考试名称");
return;
}
if (
formData.value.info.source.trim() == "" &&
formData.value.info.examType != 1
) {
message.warning("请输入数据来源");
return;
}
await validate().catch(({ errorFields }) => {
message.warning(errorFields[0].errors.join());
throw Error("数据校验不通过");
});
// 专业力ID
formData.value.growthId = props.growId;
// 任务类型
formData.value.taskType = props.type;
// 必修/选修
formData.value.type = props.activeKey;
// 任务名称
formData.value.taskName = formData.value.info.examinationName;
// 任务时长
formData.value.duration = formData.value.info.examinationDuration
saveTask(formData.value).then((res) => {
if (res.data.code == 200) {
if (formData.value.id) {
message.success("编辑成功");
} else {
message.success("添加成功");
}
emit("refresh");
} else {
message.error(res.msg);
}
closeDrawer();
});
}
function openDrawer(row) {
console.log(row, "irow");
row && resetFields(row.info);
row &&
(dateTime.value = [
row.info.examinationStartTime,
row.info.examinationEndTime,
]);
row && (formData.value = row);
visible.value = true;
}
const delTag = () => {
formData.value.examinationPaperId = "";
formData.value.examinationTestName = "";
};
// 切换考试类型
function changeExamType(v) {
// formData.reset()
formData.value.info.examType = v;
}
defineExpose({ openDrawer });
</script>
<style lang="scss">
.ant-table-striped :deep(.table-striped) td {
background-color: #fafafa !important;
}
.outer {
background-color: #4ea6ff;
color: #fff;
border-radius: 5px;
border: 1px solid #a09292;
height: 36px;
margin-right: 10px;
}
.notOuter {
color: #000;
border-radius: 5px;
border: 1px solid #a09292;
background: #fff;
margin-right: 10px;
padding: 3px;
}
.tag-style {
color: rgb(113, 113, 237);
background-color: #d7d1f7;
}
.growth-exa {
.ant-input-number-input-wrap > .ant-input-number-input {
height: 40px !important;
}
.drawerMain {
.header {
height: 73px;
border-bottom: 1px solid #e8e8e8;
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
.headerTitle {
font-size: 18px;
font-weight: 600;
color: #333333;
line-height: 25px;
margin-left: 24px;
}
}
.contentMain {
display: flex;
justify-content: space-between;
.main_left {
padding-right: 30px;
margin-top: 0px;
flex: 1;
border-right: 1px solid #e8e8e8;
.main_item {
display: flex;
align-items: center;
margin-top: 32px;
margin-bottom: 32px;
.signbox {
width: 120px;
display: flex;
justify-content: end;
align-items: center;
.sign {
margin-right: 5px;
}
}
.btnbox {
display: flex;
flex: 1;
align-items: center;
.xkbtn {
cursor: pointer;
width: 130px;
height: 40px;
background: #4ea6ff;
border-radius: 8px;
border: 0;
margin-right: 8px;
color: #fff;
}
}
}
.main_item2 {
display: flex;
align-items: flex-start;
margin-bottom: 32px;
.textarea {
width: 400px;
.ant-input {
width: 100%;
}
.ant-input-textarea-show-count {
position: relative;
}
.ant-input-textarea-show-count::after {
position: absolute;
right: 10px;
bottom: 0px;
}
.ant-input {
border-radius: 8px;
}
}
.signbox {
width: 120px;
display: flex;
justify-content: end;
align-items: center;
.sign {
margin-right: 5px;
}
}
.kqszbox {
.qdqtbox {
margin-left: 56px;
}
.setbox {
display: flex;
flex-wrap: wrap;
.timerbox {
margin-top: 6px;
margin-right: 32px;
display: flex;
align-items: center;
flex-wrap: nowrap;
}
}
}
.btnbox2 {
display: flex;
flex-direction: column;
justify-content: flex-start;
.xkbtn {
cursor: pointer;
width: 130px;
height: 40px;
background: #4ea6ff;
border-radius: 8px;
border: 0;
margin-right: 16px 8px 32px 0;
color: #fff;
margin-top: 16px;
margin-bottom: 60px;
}
}
}
}
}
.main_table {
position: relative;
padding-bottom: 80px;
.ant-checkbox-wrapper {
align-items: center;
margin-top: -2px;
}
.ant-table-selection-column {
padding: 0px !important;
padding-left: 5px !important;
}
.ant-table-thead > tr > th {
background-color: rgba(239, 244, 252, 1);
}
th.h {
background-color: #eff4fc !important;
}
.ant-table-tbody
> tr:hover:not(.ant-table-expanded-row):not(.ant-table-row-selected)
> td {
background: #f6f9fd;
}
.pa {
left: 0;
width: 100%;
display: flex;
justify-content: center;
position: absolute;
bottom: 20px;
}
}
.main_btns {
height: 72px;
width: 100%;
bottom: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0px 1px 35px 0px rgba(118, 136, 166, 0.16);
.btn1 {
width: 100px;
height: 40px;
border: 1px solid #4ea6ff;
border-radius: 8px;
color: #4ea6ff;
background-color: #fff;
cursor: pointer;
}
.btn2 {
cursor: pointer;
width: 100px;
height: 40px;
background: #4ea6ff;
border-radius: 8px;
border: 0;
margin-left: 15px;
color: #fff;
}
}
}
.iframe-container {
width: 100%;
height: calc(100% - 100px);
}
}
</style>