|
@@ -0,0 +1,199 @@
|
|
|
+<template>
|
|
|
+ <div class="build-paper-auto">
|
|
|
+ <div class="build-step-title">
|
|
|
+ <h3><span>试卷结构设置</span></h3>
|
|
|
+ <div>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ size="small"
|
|
|
+ icon="el-icon-circle-plus-outline"
|
|
|
+ @click="addDetail"
|
|
|
+ >新增大题</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <el-collapse v-model="activeNames" accordion>
|
|
|
+ <el-collapse-item
|
|
|
+ v-for="(detail, index) in details"
|
|
|
+ :key="detail.id"
|
|
|
+ :name="detail.id"
|
|
|
+ >
|
|
|
+ <div slot="title" class="detail-header">
|
|
|
+ <h3>{{ index + 1 }}、{{ detail.detailName }}</h3>
|
|
|
+ <div>
|
|
|
+ <el-button
|
|
|
+ size="mini"
|
|
|
+ type="text"
|
|
|
+ icon="el-icon-edit"
|
|
|
+ title="编辑"
|
|
|
+ @click.stop="editDetail(detail)"
|
|
|
+ ></el-button>
|
|
|
+ <el-button
|
|
|
+ class="btn-danger"
|
|
|
+ size="mini"
|
|
|
+ type="text"
|
|
|
+ icon="el-icon-delete"
|
|
|
+ title="删除"
|
|
|
+ @click.stop="removeDetail(index)"
|
|
|
+ ></el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div v-if="!isAnEmptyRichText(detail.description)" class="detail-desc">
|
|
|
+ <rich-text :text-json="detail.description"></rich-text>
|
|
|
+ </div>
|
|
|
+ <div class="detail-info">
|
|
|
+ <div>
|
|
|
+ <p>
|
|
|
+ <span>题型:</span>
|
|
|
+ <span>{{ detail.sourceDetailName }}</span>
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ <div>
|
|
|
+ <p>
|
|
|
+ <span>小题数:</span>
|
|
|
+ <span>{{ detail.questionCount }}</span>
|
|
|
+ </p>
|
|
|
+ <p>
|
|
|
+ <span>总分:</span>
|
|
|
+ <span>{{ detail.questionCount * detail.scorePerQuestion }}</span>
|
|
|
+ </p>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <question-group-struct
|
|
|
+ :ref="`QuestionStruct${detail.id}`"
|
|
|
+ :filter-data="{
|
|
|
+ courseId,
|
|
|
+ sourceDetailId: detail.sourceDetailId,
|
|
|
+ }"
|
|
|
+ :data-source="detail"
|
|
|
+ @count-change="(val) => structCountChange(val, detail)"
|
|
|
+ ></question-group-struct>
|
|
|
+ </el-collapse-item>
|
|
|
+ </el-collapse>
|
|
|
+
|
|
|
+ <!-- ModifyDetailStruct -->
|
|
|
+ <modify-detail-struct
|
|
|
+ ref="ModifyDetailStruct"
|
|
|
+ :detail="curDetail"
|
|
|
+ @modified="detailModified"
|
|
|
+ ></modify-detail-struct>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import ModifyDetailStruct from "./ModifyDetailStruct.vue";
|
|
|
+import QuestionGroupStruct from "./QuestionGroupStruct.vue";
|
|
|
+import { isAnEmptyRichText } from "@/utils/utils";
|
|
|
+import { deepCopy } from "@/plugins/utils";
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: "BuildPaperAutoStruct",
|
|
|
+ components: {
|
|
|
+ ModifyDetailStruct,
|
|
|
+ QuestionGroupStruct,
|
|
|
+ },
|
|
|
+ props: {
|
|
|
+ courseId: {
|
|
|
+ type: [String, Number],
|
|
|
+ default: "",
|
|
|
+ },
|
|
|
+ detailSource: {
|
|
|
+ type: Array,
|
|
|
+ default() {
|
|
|
+ return [];
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ details: [],
|
|
|
+ curDetail: {},
|
|
|
+ activeNames: [],
|
|
|
+ };
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ isEdit() {
|
|
|
+ return !!(this.detailSource && this.detailSource.length);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ if (this.detailSource) {
|
|
|
+ this.details = deepCopy(this.detailSource);
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ isAnEmptyRichText,
|
|
|
+ toSelectStruct() {
|
|
|
+ this.$refs.AutoBuildPaperStructManage.open();
|
|
|
+ },
|
|
|
+ addDetail() {
|
|
|
+ this.curDetail = { courseId: this.courseId };
|
|
|
+ this.$refs.ModifyDetailStruct.open();
|
|
|
+ },
|
|
|
+ editDetail(curDetail) {
|
|
|
+ this.curDetail = curDetail;
|
|
|
+ this.$refs.ModifyDetailStruct.open();
|
|
|
+ },
|
|
|
+ async removeDetail(index) {
|
|
|
+ const confirm = await this.$confirm(`确定要删除当前大题吗?`, "提示", {
|
|
|
+ type: "warning",
|
|
|
+ }).catch(() => {});
|
|
|
+ if (confirm !== "confirm") return;
|
|
|
+
|
|
|
+ this.details.splice(index, 1);
|
|
|
+ },
|
|
|
+ detailModified(data) {
|
|
|
+ const index = this.details.findIndex((item) => item.id === data.id);
|
|
|
+ if (index === -1) {
|
|
|
+ this.details.push({ ...data, questionCount: 0 });
|
|
|
+ if (!this.activeNames.includes(data.id)) this.activeNames.push(data.id);
|
|
|
+ } else {
|
|
|
+ this.$set(
|
|
|
+ this.details,
|
|
|
+ index,
|
|
|
+ Object.assign({}, this.details[index], data)
|
|
|
+ );
|
|
|
+ }
|
|
|
+ },
|
|
|
+ structCountChange(val, detail) {
|
|
|
+ const index = this.details.findIndex((item) => item.id === detail.id);
|
|
|
+ if (index === -1) return;
|
|
|
+ this.details[index].questionCount = val;
|
|
|
+ },
|
|
|
+ getData() {
|
|
|
+ let detailInfo = this.details.map((item) => {
|
|
|
+ const structData =
|
|
|
+ this.$refs[`QuestionStruct${item.id}`][0].getDataList();
|
|
|
+ return {
|
|
|
+ questionType: item.questionType,
|
|
|
+ description: item.description,
|
|
|
+ detailName: item.detailName,
|
|
|
+ sourceDetailId: item.sourceDetailId,
|
|
|
+ courseId: item.courseId,
|
|
|
+ score: structData.questionCount * item.scorePerQuestion,
|
|
|
+ ...structData,
|
|
|
+ };
|
|
|
+ });
|
|
|
+
|
|
|
+ return { detailInfo };
|
|
|
+ },
|
|
|
+ validate() {
|
|
|
+ if (!this.details.length) {
|
|
|
+ this.$message.error("请设置大题!");
|
|
|
+ return Promise.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ let hasNoQuestionDetail = this.details.some(
|
|
|
+ (detail) => !detail.questionCount
|
|
|
+ );
|
|
|
+ if (hasNoQuestionDetail) {
|
|
|
+ this.$message.error("有大题未设置小题!");
|
|
|
+ return Promise.reject();
|
|
|
+ }
|
|
|
+
|
|
|
+ return Promise.resolve(true);
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|