|
@@ -0,0 +1,929 @@
|
|
|
+<template>
|
|
|
+ <div class="ev-container component-ev-container" :id="refId" ref="editContainer">
|
|
|
+ <div class="display-flex" v-if="isSchool">
|
|
|
+ <div class="exersices-attr my-radio-style">
|
|
|
+ <IconText :text="'选择学段'" :color="'#00b8ff'" :icon="'md-school'"></IconText>
|
|
|
+ <Select v-model="exercisePeriod" @on-change="onPeriodChange">
|
|
|
+ <Option v-for="(period, index) in schoolInfo.period" :value="index" :key="index">{{ period.name }}</Option>
|
|
|
+ </Select>
|
|
|
+ </div>
|
|
|
+ <div class="my-radio-style exersices-attr">
|
|
|
+ <IconText :text="'选择年级'" :color="'#00b8ff'" :icon="'logo-buffer'"></IconText>
|
|
|
+ <Select v-model="exerciseGrade" multiple>
|
|
|
+ <Option v-for="(grade, index) in gradeList" :value="grade.id" :key="index">{{ grade.name }}</Option>
|
|
|
+ </Select>
|
|
|
+ </div>
|
|
|
+ <div class="exersices-attr my-radio-style">
|
|
|
+ <IconText :text="'选择科目'" :color="'#00b8ff'" :icon="'md-bookmarks'"></IconText>
|
|
|
+ <Select v-model="exerciseSubject" @on-change="onSubjectChange">
|
|
|
+ <Option v-for="(subject, index) in subjectList" :value="index" :key="index">{{ subject.name }}</Option>
|
|
|
+ </Select>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="display-flex">
|
|
|
+ <!-- <div class="exersices-attr my-radio-style">
|
|
|
+ <IconText :text="'题目归属'" :color="'#00b8ff'" :icon="'md-cube'"></IconText>
|
|
|
+ <Select v-model="exerciseScope" disabled>
|
|
|
+ <Option v-for="(item, index) in scopeList" :value="index" :key="index">{{ item }}</Option>
|
|
|
+ </Select>
|
|
|
+ </div> -->
|
|
|
+ <div class="exersices-attr edit-exersices-attr-diff my-radio-style">
|
|
|
+ <IconText :text="'题目难度'" :color="'#00b8ff'" :icon="'md-pulse'"></IconText>
|
|
|
+ <RadioGroup v-model="exersicesDiff" type="button" ref="diffRef">
|
|
|
+ <Radio label="1" @click.native="diffChange($event, '1')">容易</Radio>
|
|
|
+ <Radio label="2" @click.native="diffChange($event, '2')">较易</Radio>
|
|
|
+ <Radio label="3" @click.native="diffChange($event, '3')">一般</Radio>
|
|
|
+ <Radio label="4" @click.native="diffChange($event, '4')">较难</Radio>
|
|
|
+ <Radio label="5" @click.native="diffChange($event, '5')">困难</Radio>
|
|
|
+ </RadioGroup>
|
|
|
+ </div>
|
|
|
+ <div class="exersices-attr my-radio-style">
|
|
|
+ <IconText :text="'关联认知层次'" :color="'#00b8ff'" :icon="'md-planet'"></IconText>
|
|
|
+ <Select v-model="exerciseField">
|
|
|
+ <Option v-for="(item, index) in fieldList" :value="index" :key="index">{{ item }}</Option>
|
|
|
+ </Select>
|
|
|
+ </div>
|
|
|
+ <div class="exersices-attr my-radio-style">
|
|
|
+ <IconText :text="'关联知识点'" :color="'#00b8ff'" :icon="'md-infinite'"></IconText>
|
|
|
+ <Button type="info" style="margin-top: 20px" @click="onSelectPoints" v-if="exercisePoints.length === 0">选择知识点</Button>
|
|
|
+ <div v-else style="margin-top: 10px">
|
|
|
+ <span v-for="(item, index) in exercisePoints" :key="index" class="exercise-item-point">
|
|
|
+ {{ item }}
|
|
|
+ <span class="exercise-item-point-close">
|
|
|
+ <Icon type="md-close" @click="onDeletePoint(index)" /></span>
|
|
|
+ </span>
|
|
|
+ <span class="exercise-item-point-modify" @click="selectPointsModal = true">修改</span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="exersices-attr display-flex">
|
|
|
+ <div class="exersices-attr-diff my-radio-style">
|
|
|
+ <IconText :text="'选择题型'" :color="'#00b8ff'" :icon="'md-pricetags'"></IconText>
|
|
|
+ <RadioGroup v-model="exersicesType" type="button" @on-change="typeChange">
|
|
|
+ <Radio label="single" :disabled="isEdit">单选题</Radio>
|
|
|
+ <Radio label="multiple" :disabled="isEdit">多选题</Radio>
|
|
|
+ <Radio label="judge" :disabled="isEdit">判断题</Radio>
|
|
|
+ <Radio label="complete" :disabled="isEdit">填空题</Radio>
|
|
|
+ <Radio label="subjective" :disabled="isEdit">问答题</Radio>
|
|
|
+ <Radio label="connector" :disabled="isEdit">连线题</Radio>
|
|
|
+ <Radio label="correct" :disabled="isEdit">改错题</Radio>
|
|
|
+ <Radio label="compose" :disabled="isEdit">综合题</Radio>
|
|
|
+ </RadioGroup>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <BaseSingle v-if="exersicesType === 'single'" ref="single" :editInfo="editInfo"></BaseSingle>
|
|
|
+ <BaseMultiple v-else-if="exersicesType === 'multiple'" ref="multiple" :editInfo="editInfo"></BaseMultiple>
|
|
|
+ <BaseJudge v-else-if="exersicesType === 'judge'" ref="judge" :editInfo="editInfo"></BaseJudge>
|
|
|
+ <BaseCompletion v-else-if="exersicesType === 'complete'" ref="complete" :editInfo="editInfo"></BaseCompletion>
|
|
|
+ <BaseSubjective v-else-if="exersicesType === 'subjective'" ref="subjective" :editInfo="editInfo"></BaseSubjective>
|
|
|
+ <BaseConnector v-else-if="exersicesType === 'connector'" ref="connector" :editInfo="editInfo"></BaseConnector>
|
|
|
+ <BaseCorrect v-else-if="exersicesType === 'correct'" ref="correct" :editInfo="editInfo"></BaseCorrect>
|
|
|
+ <BaseCompose v-else-if="exersicesType === 'compose'" ref="compose" :editInfo="editInfo"></BaseCompose>
|
|
|
+
|
|
|
+ <!-- 解析的富文本部分 -->
|
|
|
+ <div class="exersices-analysis" v-show="exersicesType !== 'compose'">
|
|
|
+ <IconText :text="'解析'" :color="'#2892DD'" :icon="'md-list'" style="margin-bottom: 10px"></IconText>
|
|
|
+ <div>
|
|
|
+ <div ref="analysisEditor" style="text-align: left"></div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 补救的富文本部分 -->
|
|
|
+ <div class="exersices-analysis" v-show="exersicesType !== 'compose'">
|
|
|
+ <IconText :text="'补救资源'" :color="'#2892DD'" :icon="'md-link'" style="margin-bottom: 10px"></IconText>
|
|
|
+ <BaseRepair ref="repairRef" :datas="editInfo ? editInfo.repairResource : []"></BaseRepair>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 小题展示区域 -->
|
|
|
+ <div class="child-list-wrap" v-show="exersicesType === 'compose' && childList.length">
|
|
|
+ <IconText :text="'小题列表'" :color="'#00b8ff'" :icon="'md-list'"></IconText>
|
|
|
+ <BaseChildList :childList="childList" @onEditChildFinish="onEditChildFinish" @onDeleteChild="onDeleteChild"></BaseChildList>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="save-wrap display-flex">
|
|
|
+ <Button type="info" @click="addChildModal = true" style="margin-right: 10px" v-show="exersicesType === 'compose'">添加小题</Button>
|
|
|
+ <Button type="success" @click="getContent(exersicesType)" :loading="isLoading">保存</Button>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <Modal v-model="selectPointsModal" title="选择知识点" ref="editPointRef" width="600px" style="z-index: 99999">
|
|
|
+ <BasePoints v-if="selectPointsModal" :period="schoolInfo.period[exercisePeriod].id" :subject="subjectList[exerciseSubject].id"
|
|
|
+ @onCheckChange="onCheckChange" :points="exercisePoints" ref="pointRef" :scope="curScope"></BasePoints>
|
|
|
+ <!--<CreateNewChild v-if="isLoadModal" ref="newChild" :isChildEdit="isChildEdit" :editItem="editChild"></CreateNewChild>-->
|
|
|
+ <div slot="footer">
|
|
|
+ <Button type="text" @click="onConfirm">取消</Button>
|
|
|
+ <Button type="primary" @click="onConfirm">确定</Button>
|
|
|
+ </div>
|
|
|
+ </Modal>
|
|
|
+
|
|
|
+ <!-- 关联内容弹窗 -->
|
|
|
+ <Modal v-model="isRelatedContent" width="880" footer-hide class="relate-modal related-modal">
|
|
|
+ <div class="modal-header" slot="header">内容关联</div>
|
|
|
+ <!-- <ChooseContent :showSyllabus="isFalse" :showOther="isFalse" :showQuestion="isFalse" @on-select-file="onSelectFile"
|
|
|
+ @on-cancel-file="onSelectFile"></ChooseContent> -->
|
|
|
+
|
|
|
+ <Button class="modal-btn" @click="onConfirmRelate">确认</Button>
|
|
|
+ </Modal>
|
|
|
+
|
|
|
+ <!-- 添加小题弹窗 -->
|
|
|
+ <Modal v-model="addChildModal" width="1080" footer-hide class="">
|
|
|
+ <div class="modal-header" slot="header">添加小题</div>
|
|
|
+ <BaseCreateChild @addFinish="onAddChildFinish" v-if="addChildModal" :curPeriodIndex="exercisePeriod"
|
|
|
+ :curSubjectIndex="exerciseSubject"></BaseCreateChild>
|
|
|
+ </Modal>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script>
|
|
|
+ import blobTool from "@/utils/blobTool.js";
|
|
|
+ import "videojs-contrib-hls.js/src/videojs.hlsjs";
|
|
|
+ import IconText from "@/components/evaluation/IconText.vue";
|
|
|
+ import BaseSingle from "@/view/evaluation/types/BaseSingle.vue";
|
|
|
+ import BaseMultiple from "@/view/evaluation/types/BaseMultiple.vue";
|
|
|
+ import BaseCompletion from "@/view/evaluation/types/BaseCompletion.vue";
|
|
|
+ import BaseJudge from "@/view/evaluation/types/BaseJudge.vue";
|
|
|
+ import BaseSubjective from "@/view/evaluation/types/BaseSubjective.vue";
|
|
|
+ import BaseCorrect from "@/view/evaluation/types/BaseCorrect.vue";
|
|
|
+ import BaseConnector from "@/view/evaluation/types/BaseConnector.vue";
|
|
|
+ import BaseCompose from "@/view/evaluation/types/BaseCompose.vue";
|
|
|
+ import E from "wangeditor";
|
|
|
+
|
|
|
+ export default {
|
|
|
+ name:'BaseEditExercise',
|
|
|
+ props: ["exerciseItem", "refId"],
|
|
|
+ components: {
|
|
|
+ IconText,
|
|
|
+ BaseSingle,
|
|
|
+ BaseJudge,
|
|
|
+ BaseMultiple,
|
|
|
+ BaseCompletion,
|
|
|
+ BaseSubjective,
|
|
|
+ BaseCorrect,
|
|
|
+ BaseConnector,
|
|
|
+ BaseCompose,
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ isFalse: false,
|
|
|
+ isLoading: false,
|
|
|
+ addChildModal: false,
|
|
|
+ isRelatedContent: false,
|
|
|
+ selectPointsModal: false,
|
|
|
+ isEdit: false,
|
|
|
+ editInfo: null,
|
|
|
+ schoolInfo: {
|
|
|
+ period: [],
|
|
|
+ },
|
|
|
+ exersicesType: null,
|
|
|
+ exerciseField: 0,
|
|
|
+ exercisePeriod: 0,
|
|
|
+ exerciseGrade: [],
|
|
|
+ exerciseSubject: 0,
|
|
|
+ exerciseScope: 0,
|
|
|
+ exercisePoints: [],
|
|
|
+ childList: [],
|
|
|
+ oldChildList:[],
|
|
|
+ scopeList: ["个人题库", "校本题库"],
|
|
|
+ fieldList: ["知识", "理解", "应用", "分析", "综合", "评鉴"],
|
|
|
+ periodList: [],
|
|
|
+ gradeList: [],
|
|
|
+ subjectList: [],
|
|
|
+ relateFileList: [],
|
|
|
+ exersicesDiff: 0,
|
|
|
+ analysisContent: "",
|
|
|
+ repairContent: "",
|
|
|
+ stemContent: "",
|
|
|
+ analysisEditor: null,
|
|
|
+ repairEditor: null,
|
|
|
+ videoHtml: "",
|
|
|
+ deleteChildrens:[],
|
|
|
+ curId:null
|
|
|
+ };
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ // 初始化区班校信息
|
|
|
+ this.getSchoolInfo();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ getSchoolInfo() {
|
|
|
+ this.$store.dispatch("user/getSchoolProfile").then((res) => {
|
|
|
+ let schoolBaseInfo = res.school_base;
|
|
|
+ if (schoolBaseInfo) {
|
|
|
+ this.schoolInfo = schoolBaseInfo;
|
|
|
+ if (schoolBaseInfo.period.length) {
|
|
|
+ this.gradeList = schoolBaseInfo.period[0].grades;
|
|
|
+ this.subjectList = schoolBaseInfo.period[0].subjects;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ onSelectPoints(){
|
|
|
+ if(this.hasSchool){
|
|
|
+ this.selectPointsModal = true
|
|
|
+ }else{
|
|
|
+ this.$Message.warning('您当前未加入学校,无法选择知识点!')
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ /* 滚回顶部 */
|
|
|
+ backToTop() {
|
|
|
+ this.$refs.editContainer.scrollIntoView();
|
|
|
+ this.exersicesType = ''
|
|
|
+ },
|
|
|
+
|
|
|
+ onSelectFile(val) {
|
|
|
+ this.relateFileList = val.files;
|
|
|
+ },
|
|
|
+
|
|
|
+ onConfirmRelate() {
|
|
|
+ this.isRelatedContent = false;
|
|
|
+ },
|
|
|
+
|
|
|
+ async getContent(type) {
|
|
|
+ let exerciseItem = JSON.parse(JSON.stringify(this.editInfo))
|
|
|
+ this.isLoading = true;
|
|
|
+ switch (type) {
|
|
|
+ case "single":
|
|
|
+ this.$refs.single.doSave()
|
|
|
+ exerciseItem.question = this.$refs.single.stemContent;
|
|
|
+ exerciseItem.option =
|
|
|
+ this.checkOptionNull(this.$refs.single.optionsContent) ?
|
|
|
+ this.$refs.single.optionsContent :
|
|
|
+ null;
|
|
|
+ exerciseItem.type = this.exersicesType;
|
|
|
+ exerciseItem.level = +this.exersicesDiff;
|
|
|
+ exerciseItem.explain = this.analysisContent;
|
|
|
+ exerciseItem.answer = [
|
|
|
+ String.fromCharCode(64 + parseInt(this.$refs.single.trueIndex + 1)),
|
|
|
+ ];
|
|
|
+
|
|
|
+ break;
|
|
|
+ case "multiple":
|
|
|
+ this.$refs.multiple.doSave()
|
|
|
+ exerciseItem.question = this.$refs.multiple.stemContent;
|
|
|
+ exerciseItem.option = this.checkOptionNull(this.$refs.multiple.optionsContent) ?
|
|
|
+ this.$refs.multiple.optionsContent :
|
|
|
+ null;
|
|
|
+ exerciseItem.type = this.exersicesType;
|
|
|
+ exerciseItem.level = +this.exersicesDiff;
|
|
|
+ exerciseItem.explain = this.analysisContent;
|
|
|
+ exerciseItem.answer = this.$refs.multiple.multipleAnswers;
|
|
|
+ break;
|
|
|
+ case "judge":
|
|
|
+ exerciseItem.question = this.$refs.judge._data.stemContent;
|
|
|
+ exerciseItem.option = [];
|
|
|
+ exerciseItem.type = this.exersicesType;
|
|
|
+ exerciseItem.level = +this.exersicesDiff;
|
|
|
+ exerciseItem.answer = [this.$refs.judge._data.trueAnswer];
|
|
|
+ break;
|
|
|
+ case "complete":
|
|
|
+ exerciseItem.question = this.$refs.complete.stemContent;
|
|
|
+ exerciseItem.option = [];
|
|
|
+ exerciseItem.type = this.exersicesType;
|
|
|
+ exerciseItem.level = +this.exersicesDiff;
|
|
|
+ exerciseItem.explain = this.analysisContent;
|
|
|
+ exerciseItem.answer = [this.$refs.complete.answerContent];
|
|
|
+ break;
|
|
|
+ case "connector":
|
|
|
+ exerciseItem.question = this.$refs.connector.stemContent;
|
|
|
+ exerciseItem.option = [];
|
|
|
+ exerciseItem.type = this.exersicesType;
|
|
|
+ exerciseItem.level = +this.exersicesDiff;
|
|
|
+ exerciseItem.explain = this.analysisContent;
|
|
|
+ exerciseItem.answer = [this.$refs.connector.answerContent];
|
|
|
+ break;
|
|
|
+ case "correct":
|
|
|
+ exerciseItem.question = this.$refs.correct.stemContent;
|
|
|
+ exerciseItem.option = [];
|
|
|
+ exerciseItem.type = this.exersicesType;
|
|
|
+ exerciseItem.level = +this.exersicesDiff;
|
|
|
+ exerciseItem.explain = this.analysisContent;
|
|
|
+ exerciseItem.answer = [this.$refs.correct.answerContent];
|
|
|
+ break;
|
|
|
+ case "subjective":
|
|
|
+ exerciseItem.question = this.$refs.subjective.stemContent;
|
|
|
+ exerciseItem.option = [];
|
|
|
+ exerciseItem.type = this.exersicesType;
|
|
|
+ exerciseItem.level = +this.exersicesDiff;
|
|
|
+ exerciseItem.explain = this.analysisContent;
|
|
|
+ exerciseItem.answer = [this.$refs.subjective.answerContent];
|
|
|
+ break;
|
|
|
+ case "compose":
|
|
|
+ exerciseItem.question = this.$refs.compose.stemContent;
|
|
|
+ exerciseItem.option = [];
|
|
|
+ exerciseItem.type = this.exersicesType;
|
|
|
+ exerciseItem.level = +this.exersicesDiff;
|
|
|
+ exerciseItem.explain = this.analysisContent;
|
|
|
+ exerciseItem.children = this.childList;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ exerciseItem.explain = this.analysisContent;
|
|
|
+ exerciseItem.repairResource = this.formatRepairResource(
|
|
|
+ this.$refs.repairRef.datas
|
|
|
+ );
|
|
|
+ exerciseItem.field = this.exerciseField + 1;
|
|
|
+ exerciseItem.points = this.exercisePoints;
|
|
|
+ exerciseItem.periodId = this.isSchool ?
|
|
|
+ this.schoolInfo.period[this.exercisePeriod].id :
|
|
|
+ null;
|
|
|
+ exerciseItem.gradeIds = this.isSchool ?
|
|
|
+ this.exerciseGrade.length ?
|
|
|
+ this.exerciseGrade :
|
|
|
+ this.gradeList.map((i) => i.id) :
|
|
|
+ null;
|
|
|
+ exerciseItem.subjectId = this.isSchool ?
|
|
|
+ this.schoolInfo.period[this.exercisePeriod].subjects[
|
|
|
+ this.exerciseSubject
|
|
|
+ ].id :
|
|
|
+ null;
|
|
|
+ exerciseItem.code =
|
|
|
+ this.editInfo.scope === "school" ?
|
|
|
+ this.$store.state.userInfo.schoolCode :
|
|
|
+ this.$store.state.userInfo.TEAMModelId;
|
|
|
+ exerciseItem.scope = this.exerciseScope === 0 ? "private" : "school";
|
|
|
+
|
|
|
+ // 判断获取的数据是否有空数据以及是否为空字符串
|
|
|
+ if (this.checkContent(exerciseItem)) {
|
|
|
+ exerciseItem = await this.$editorTools.transBase64Src(exerciseItem)
|
|
|
+ if (this.refId !== "paperEdit") {
|
|
|
+ // 生成JSON文件名称以及新增试题的ID
|
|
|
+ const guid = this.editInfo.id ? this.editInfo.id : this.$tools.guid();
|
|
|
+ // 给新增的试题赋值ID
|
|
|
+ exerciseItem.id = guid;
|
|
|
+ if(exerciseItem.children && exerciseItem.children.length && exerciseItem.type === 'compose'){
|
|
|
+ console.log('编辑前的children',this.oldChildList)
|
|
|
+ exerciseItem.children.forEach((child) => {
|
|
|
+ child.periodId = exerciseItem.periodId
|
|
|
+ child.gradeIds = exerciseItem.gradeIds
|
|
|
+ child.subjectId = exerciseItem.subjectId
|
|
|
+ child.scope = exerciseItem.scope
|
|
|
+ child.pid = exerciseItem.id
|
|
|
+ })
|
|
|
+ let modifyChildren = this.checkModifyChildrens(exerciseItem.children)
|
|
|
+ console.log('修改了的children',modifyChildren)
|
|
|
+ exerciseItem.children = await this.saveChildrens(modifyChildren,exerciseItem.children)
|
|
|
+ console.log(exerciseItem)
|
|
|
+ }
|
|
|
+ // 将当前的试题数据转化为BLOB内部的试题JSON格式
|
|
|
+ const itemJsonFile = await this.$evTools.createBlobItem(exerciseItem);
|
|
|
+ // 首先保存新题目的JSON文件到Blob 然后返回URL链接
|
|
|
+ let file = new File([JSON.stringify(itemJsonFile)], guid + ".json", {
|
|
|
+ type: "",
|
|
|
+ });
|
|
|
+ // 获取初始化Blob需要的数据
|
|
|
+ let sasData =
|
|
|
+ this.exerciseScope === 0 ?
|
|
|
+ await this.$tools.getPrivateSas() :
|
|
|
+ await this.$tools.getSchoolSas();
|
|
|
+ //初始化Blob
|
|
|
+ let containerClient = new blobTool(
|
|
|
+ sasData.url,
|
|
|
+ sasData.name,
|
|
|
+ sasData.sas,
|
|
|
+ exerciseItem.scope
|
|
|
+ );
|
|
|
+
|
|
|
+ try {
|
|
|
+ console.log(exerciseItem)
|
|
|
+ // 等待上传blob的返回结果
|
|
|
+ let blobFile = await containerClient.upload(file, "item/" + guid);
|
|
|
+ if (blobFile.blob) {
|
|
|
+ console.log(exerciseItem)
|
|
|
+ // 保存到COSMOS是不含base64图片编码的数据 避免数据量过大
|
|
|
+ exerciseItem.blob = blobFile.blob;
|
|
|
+ let cosmosItem = await this.$evTools.createCosmosItem(
|
|
|
+ exerciseItem
|
|
|
+ );
|
|
|
+ console.log(exerciseItem)
|
|
|
+ this.saveExercise(cosmosItem);
|
|
|
+ } else {
|
|
|
+ this.$Message.error("试题文件上传失败,请稍后重试!");
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ this.$Message.error(e.spaceError);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 如果是试卷内编辑试题 则返回编辑好的数据 再统一进行保存
|
|
|
+ this.saveExercise(exerciseItem);
|
|
|
+ }
|
|
|
+ } else if (exerciseItem.level === 0) {
|
|
|
+ this.$Message.warning("题目难度未设置!");
|
|
|
+ this.isLoading = false;
|
|
|
+ } else {
|
|
|
+ this.$Message.warning("请将题目填写完整!");
|
|
|
+ this.isLoading = false;
|
|
|
+ }
|
|
|
+ console.log(exerciseItem);
|
|
|
+ },
|
|
|
+
|
|
|
+ /* 检查需要更新的子题 */
|
|
|
+ checkModifyChildrens(childrens){
|
|
|
+ if(!this.oldChildList.length){
|
|
|
+ return childrens
|
|
|
+ }
|
|
|
+ let oldChildren = JSON.parse(JSON.stringify(this.oldChildList))
|
|
|
+ let result = childrens.filter((v) => {
|
|
|
+ var str = JSON.stringify(v);
|
|
|
+ return oldChildren.every((v) => JSON.stringify(v) != str);
|
|
|
+ });
|
|
|
+ return result
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ /* 保存综合题的子题 */
|
|
|
+ saveChildrens(modifyChildrens,childrens){
|
|
|
+ return new Promise((resolve,reject) => {
|
|
|
+ let promiseArr = []
|
|
|
+ modifyChildrens.forEach(exerciseItem => {
|
|
|
+ promiseArr.push(new Promise(async (r,j) => {
|
|
|
+ console.log(exerciseItem)
|
|
|
+ // 将当前的试题数据转化为BLOB内部的试题JSON格式
|
|
|
+ const itemJsonFile = await this.$evTools.createBlobItem(exerciseItem);
|
|
|
+ // 首先保存新题目的JSON文件到Blob 然后返回URL链接
|
|
|
+ let file = new File([JSON.stringify(itemJsonFile)], exerciseItem.id + ".json");
|
|
|
+ // 获取初始化Blob需要的数据
|
|
|
+ let sasData =
|
|
|
+ exerciseItem.scope === 'private' ?
|
|
|
+ await this.$tools.getPrivateSas() :
|
|
|
+ await this.$tools.getSchoolSas();
|
|
|
+ //初始化Blob
|
|
|
+ let containerClient = new blobTool(
|
|
|
+ sasData.url,
|
|
|
+ sasData.name,
|
|
|
+ sasData.sas,
|
|
|
+ exerciseItem.scope
|
|
|
+ );
|
|
|
+ try {
|
|
|
+ // 等待上传blob的返回结果
|
|
|
+ let blobFile = await containerClient.upload(file, "item/" + exerciseItem.id);
|
|
|
+ if (blobFile.blob) {
|
|
|
+ // 保存到COSMOS是不含base64图片编码的数据 避免数据量过大
|
|
|
+ exerciseItem.blob = blobFile.blob;
|
|
|
+ let cosmosItem = await this.$evTools.createCosmosItem(exerciseItem)
|
|
|
+ console.log(this.oldChildList.map(i => i.id))
|
|
|
+ console.log(exerciseItem.id)
|
|
|
+ let isNew = this.oldChildList.map(i => i.id).indexOf(exerciseItem.id) === -1
|
|
|
+ this.$api.newEvaluation.SaveSingleExercise({
|
|
|
+ itemInfo: cosmosItem,
|
|
|
+ option: isNew ? "insert" : "update",
|
|
|
+ }).then((res) => {
|
|
|
+ console.log('保存了一个子题',res.itemInfo)
|
|
|
+ r(res.itemInfo)
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ this.$Message.error("试题文件上传失败,请稍后重试!");
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ this.$Message.error(e);
|
|
|
+ }
|
|
|
+ }))
|
|
|
+ })
|
|
|
+
|
|
|
+ /* 如果存在删除的子题 则需要把子题从blob和cosmos中进行删除 */
|
|
|
+ if(this.deleteChildrens.length){
|
|
|
+ this.deleteChildrens.forEach(child => {
|
|
|
+ if(this.oldChildList.map(i => i.id).indexOf(child.id) > -1){
|
|
|
+ promiseArr.push(new Promise((r,j) => {
|
|
|
+ this.onDeleteChildBlob(child).then(res => {
|
|
|
+ if(!res.error){
|
|
|
+ r(200)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }))
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ Promise.all(promiseArr).then(result => {
|
|
|
+ resolve(childrens.map(i => i.id))
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ /* 删除blob和cosmos里面的子题 */
|
|
|
+ onDeleteChildBlob(item){
|
|
|
+ return new Promise((r,j) => {
|
|
|
+ this.$api.newEvaluation
|
|
|
+ .DeleteExamItem({
|
|
|
+ id: item.id,
|
|
|
+ code: item.code,
|
|
|
+ scope: item.scope,
|
|
|
+ })
|
|
|
+ .then(async (res) => {
|
|
|
+ // 获取初始化Blob需要的数据
|
|
|
+ this.deleteBlobPrefix(item).then(status => {
|
|
|
+ r(status)
|
|
|
+ })
|
|
|
+ })
|
|
|
+ .catch((err) => {
|
|
|
+ j(err);
|
|
|
+ this.$Message.warning("删除失败");
|
|
|
+ });
|
|
|
+ })
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ /* 删除blob指定试题目录下所有 */
|
|
|
+ deleteBlobPrefix(item) {
|
|
|
+ return new Promise((resolve,reject) => {
|
|
|
+ this.$api.uploadFile.deletePrefix({
|
|
|
+ "cntr": item.scope === 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,
|
|
|
+ "prefix": "item/" + item.id
|
|
|
+ }).then(
|
|
|
+ (res) => {
|
|
|
+ if (!res.error) {
|
|
|
+ resolve(200)
|
|
|
+ } else {
|
|
|
+ resolve(500)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ (err) => {
|
|
|
+ reject(err)
|
|
|
+ }
|
|
|
+ )
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 保存编辑后的试题
|
|
|
+ * @param item
|
|
|
+ */
|
|
|
+ saveExercise(item) {
|
|
|
+ this.$emit("onEditSuccess", item);
|
|
|
+ },
|
|
|
+
|
|
|
+ /* 检测补救资源超链接 去除无效链接 */
|
|
|
+ formatRepairResource(list) {
|
|
|
+ if (list.length) {
|
|
|
+ let arr = [];
|
|
|
+ list.forEach((i, index) => {
|
|
|
+ if (this.$tools.isURL(i.blobUrl)) {
|
|
|
+ arr.push(i);
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return arr;
|
|
|
+ } else {
|
|
|
+ return [];
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ onEditChildFinish(list,deleteId) {
|
|
|
+ list.forEach((i) => {
|
|
|
+ i.code = this.editInfo.code;
|
|
|
+ });
|
|
|
+ this.childList = list;
|
|
|
+ console.log('编辑完之后的list',list)
|
|
|
+ },
|
|
|
+
|
|
|
+ onDeleteChild(item){
|
|
|
+ this.deleteChildrens.push(item)
|
|
|
+ console.log('需要删除的子题',this.deleteChildrens)
|
|
|
+ },
|
|
|
+
|
|
|
+ onConfirm() {
|
|
|
+ this.selectPointsModal = false;
|
|
|
+ },
|
|
|
+
|
|
|
+ onCheckChange(val, list) {
|
|
|
+ console.log(val);
|
|
|
+ this.exercisePoints = val;
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除选好的关联知识点
|
|
|
+ * @param index
|
|
|
+ */
|
|
|
+ onDeletePoint(index) {
|
|
|
+ this.exercisePoints.splice(index, 1);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 题目类型转换
|
|
|
+ typeChange(val) {
|
|
|
+ if (this.isEdit) {
|
|
|
+ this.$Message.warning("暂不支持更换题型!");
|
|
|
+ }else {
|
|
|
+ this.exersicesType = val;
|
|
|
+ this.analysisEditor.txt.clear();
|
|
|
+ this.repairEditor.txt.clear();
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 难度与背景颜色切换
|
|
|
+ diffChange(e, type) {
|
|
|
+ this.exersicesDiff = +type;
|
|
|
+ e.preventDefault();
|
|
|
+ let colorArr = ["#10abe7", "#E8BE15", "#F19300", "#EB5E00", "#D30000"];
|
|
|
+ /** 通过动态赋予ID 解决多个组件下获取DOM覆盖问题 */
|
|
|
+ let ac = document
|
|
|
+ .getElementById(this.refId)
|
|
|
+ .getElementsByClassName("edit-exersices-attr-diff")[0].children[1]
|
|
|
+ .children;
|
|
|
+ for (let i = 0; i < ac.length; i++) {
|
|
|
+ ac[i].style.background = "#fff";
|
|
|
+ ac[i].style.color = "#515a6e";
|
|
|
+ }
|
|
|
+ e.target.style.background = colorArr[+type - 1];
|
|
|
+ e.target.style.color = "#fff";
|
|
|
+ },
|
|
|
+
|
|
|
+ onPeriodChange(val) {
|
|
|
+ if (!val) return;
|
|
|
+ console.log(this.schoolInfo);
|
|
|
+ console.log(val);
|
|
|
+ this.gradeList = this.schoolInfo.period[val].grades;
|
|
|
+ this.subjectList = this.schoolInfo.period[val].subjects;
|
|
|
+ this.exerciseGrade = 0;
|
|
|
+ this.exerciseSubject = 0;
|
|
|
+ this.exercisePoints = []; // 切换学段后 知识点需要重新选择
|
|
|
+ },
|
|
|
+
|
|
|
+ /* 切换科目 将知识点重置 */
|
|
|
+ onSubjectChange(){
|
|
|
+ this.exercisePoints = []
|
|
|
+ },
|
|
|
+
|
|
|
+ // 提取富文本内容中的文本
|
|
|
+ getSimpleText(html) {
|
|
|
+ var r = /<[^>]*>|/g;
|
|
|
+ return html.replace(r, "");
|
|
|
+ },
|
|
|
+ // 排除对象空属性
|
|
|
+ checkContent(Obj) {
|
|
|
+ let flag = true;
|
|
|
+ let whiteList = this.getWhiteListByType(Obj.type);
|
|
|
+ for (let key in Obj) {
|
|
|
+ if (whiteList.includes(key) && typeof Obj[key] === "string") {
|
|
|
+ if (!this.getSimpleText(Obj[key])) {
|
|
|
+ console.log(key);
|
|
|
+ flag = false;
|
|
|
+ }
|
|
|
+ } else if (whiteList.includes(key) && key === "answer") {
|
|
|
+ if (Obj[key].length === 0) {
|
|
|
+ console.log(key);
|
|
|
+ flag = false;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ if (whiteList.includes(key) && !Obj[key]) {
|
|
|
+ console.log(key);
|
|
|
+ flag = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return flag;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 重置编辑器
|
|
|
+ resetEditor() {
|
|
|
+ this.$router.push({
|
|
|
+ name: "personalBank",
|
|
|
+ params: {
|
|
|
+ tabName: "exercise",
|
|
|
+ },
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ onAddChildFinish(item) {
|
|
|
+ console.log("获取到小题");
|
|
|
+ console.log(item);
|
|
|
+ this.addChildModal = false;
|
|
|
+ this.childList.push(item);
|
|
|
+ },
|
|
|
+
|
|
|
+ // 重置
|
|
|
+ reloadCreate() {
|
|
|
+ location.reload();
|
|
|
+ },
|
|
|
+
|
|
|
+ /* 检测数组是否有空数据 */
|
|
|
+ checkOptionNull(arr) {
|
|
|
+ let flag = true;
|
|
|
+ for (let i = 0; i < arr.length; i++) {
|
|
|
+ if (this.getSimpleText(arr[i].value) === "") {
|
|
|
+ flag = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return flag;
|
|
|
+ },
|
|
|
+
|
|
|
+ // 根据不同题型 给出需要必填选项
|
|
|
+ getWhiteListByType(type) {
|
|
|
+ switch (type) {
|
|
|
+ case "single":
|
|
|
+ return ["question", "option", "answer"];
|
|
|
+ break;
|
|
|
+ case "multiple":
|
|
|
+ return ["question", "option", "answer"];
|
|
|
+ break;
|
|
|
+ case "complete":
|
|
|
+ return ["question", "answer"];
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ return ["question"];
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 渲染编辑习题内容回显
|
|
|
+ async renderExercise(editItem) {
|
|
|
+ this.editInfo = editItem;
|
|
|
+ this.curId = editItem.id
|
|
|
+
|
|
|
+ let schoolProfile = await this.$store.dispatch('user/getSchoolProfile')
|
|
|
+ let schoolInfo = schoolProfile.school_base;
|
|
|
+
|
|
|
+ if (editItem.scope === "school" && schoolInfo) {
|
|
|
+ console.log('进来了')
|
|
|
+ this.schoolInfo = schoolInfo;
|
|
|
+ this.exerciseGrade = editItem.gradeIds;
|
|
|
+ this.exercisePeriod = schoolInfo.period
|
|
|
+ .map((item) => item.id)
|
|
|
+ .indexOf(editItem.periodId);
|
|
|
+ this.subjectList = schoolInfo.period[this.exercisePeriod].subjects;
|
|
|
+ this.gradeList = schoolInfo.period[this.exercisePeriod].grades;
|
|
|
+ this.exerciseSubject = this.subjectList
|
|
|
+ .map((item) => item.id)
|
|
|
+ .indexOf(editItem.subjectId);
|
|
|
+ }
|
|
|
+
|
|
|
+ this.isEdit = true;
|
|
|
+ this.exersicesDiff = editItem.level.toString() || "0";
|
|
|
+ this.exerciseScope = editItem.scope === "private" ? 0 : 1;
|
|
|
+ this.exersicesType = editItem.type;
|
|
|
+ this.exerciseField = editItem.field - 1;
|
|
|
+ this.exercisePoints = editItem.points;
|
|
|
+ if (editItem.level) {
|
|
|
+ let ac = document
|
|
|
+ .getElementById(this.refId)
|
|
|
+ .getElementsByClassName("edit-exersices-attr-diff")[0].children[1]
|
|
|
+ .children;
|
|
|
+ for (let i = 0; i < ac.length; i++) {
|
|
|
+ ac[i].style.background = "#fff";
|
|
|
+ ac[i].style.color = "#515a6e";
|
|
|
+ }
|
|
|
+ // 重新渲染题目难度
|
|
|
+ let diffDom = document
|
|
|
+ .getElementById(this.refId)
|
|
|
+ .getElementsByClassName("edit-exersices-attr-diff")[0].children[1]
|
|
|
+ .children[editItem.level - 1];
|
|
|
+ let colorArr = ["#32CF74", "#E8BE15", "#F19300", "#EB5E00", "#D30000"];
|
|
|
+ diffDom.style.background = colorArr[editItem.level - 1];
|
|
|
+ diffDom.style.color = "#fff";
|
|
|
+ } else {
|
|
|
+ let ac = document
|
|
|
+ .getElementById(this.refId)
|
|
|
+ .getElementsByClassName("edit-exersices-attr-diff")[0].children[1]
|
|
|
+ .children;
|
|
|
+ for (let i = 0; i < ac.length; i++) {
|
|
|
+ ac[i].style.background = "#fff";
|
|
|
+ ac[i].style.color = "#515a6e";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if(editItem.type === 'compose'){
|
|
|
+ this.oldChildList = JSON.parse(JSON.stringify(editItem.children)) || []
|
|
|
+ }
|
|
|
+ this.childList = editItem.children || [];
|
|
|
+ this.stemContent = editItem.question;
|
|
|
+ this.relateFileList = editItem.repairResource || [];
|
|
|
+ this.optionsContent = editItem.option;
|
|
|
+ this.analysisContent = editItem.explain;
|
|
|
+ this.analysisEditor.txt.html(editItem.explain);
|
|
|
+ },
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ let analysisEditor = new E(this.$refs.analysisEditor);
|
|
|
+ analysisEditor.config.uploadImgShowBase64 = true;
|
|
|
+ analysisEditor.config.onchange = (html) => {
|
|
|
+ this.analysisContent = html;
|
|
|
+ },
|
|
|
+ this.$editorTools.addVideoUpload(this, analysisEditor)
|
|
|
+ this.$editorTools.addAudio(this, analysisEditor)
|
|
|
+ this.$editorTools.addCanvas(this, analysisEditor)
|
|
|
+ this.$editorTools.initMyEditor(analysisEditor)
|
|
|
+
|
|
|
+ analysisEditor.create();
|
|
|
+ this.analysisEditor = analysisEditor;
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+ isSchool() {
|
|
|
+ return this.exerciseScope === 1;
|
|
|
+ },
|
|
|
+ curScope(){
|
|
|
+ return this.exerciseScope === 1 ? 'school' : 'private'
|
|
|
+ },
|
|
|
+ hasSchool() {
|
|
|
+ let user = JSON.parse(
|
|
|
+ decodeURIComponent(localStorage.user_profile, "utf-8")
|
|
|
+ );
|
|
|
+ return (
|
|
|
+ user.schools &&
|
|
|
+ user.schools.length &&
|
|
|
+ user.schools.filter((i) => i.status === "join").length > 0
|
|
|
+ );
|
|
|
+ },
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ exerciseItem: {
|
|
|
+ handler(newValue, oldValue) {
|
|
|
+ if (newValue) {
|
|
|
+ console.log("传进来的ITEM");
|
|
|
+ console.log(newValue);
|
|
|
+ this.isLoading = false;
|
|
|
+ this.renderExercise(JSON.parse(JSON.stringify(newValue)));
|
|
|
+ }
|
|
|
+ },
|
|
|
+ //immediate:true
|
|
|
+ },
|
|
|
+ },
|
|
|
+ };
|
|
|
+</script>
|
|
|
+<style src="../index/CreateExercises.less" lang="less" scoped>
|
|
|
+</style>
|
|
|
+
|
|
|
+<style>
|
|
|
+ .exersices-attr .ivu-select-multiple .ivu-tag {
|
|
|
+ height: 32px;
|
|
|
+ line-height: 31px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .exersices-attr .ivu-select-multiple .ivu-tag i {
|
|
|
+ top: 9px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .exersices-attr .ivu-select-multiple .ivu-select-selection .ivu-select-placeholder {
|
|
|
+ line-height: 38px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .component-ev-container .ivu-select-single .ivu-select-selection .ivu-select-placeholder {
|
|
|
+ line-height: 38px;
|
|
|
+ height: 38px;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ .related-point-modal .ivu-modal-header-inner {
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+
|
|
|
+ .exersices-attr .ivu-select-multiple .ivu-tag {
|
|
|
+ height: 32px;
|
|
|
+ line-height: 31px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .exersices-attr .ivu-select-multiple .ivu-tag i {
|
|
|
+ top: 9px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .exersices-attr .ivu-select-multiple .ivu-select-selection .ivu-select-placeholder {
|
|
|
+ line-height: 38px;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* 修改iview Modal样式 */
|
|
|
+
|
|
|
+ .related-modal .ivu-modal-content {
|
|
|
+ background: #3c3c3c;
|
|
|
+ overflow: hidden;
|
|
|
+ color: #fff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .related-modal .ivu-modal-body {
|
|
|
+ height: 400px;
|
|
|
+ padding: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .related-modal .ivu-modal-body {
|
|
|
+ height: 700px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .related-modal .ivu-modal-header {
|
|
|
+ border-bottom: none;
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: bold;
|
|
|
+ padding: 25px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .related-modal .modal-content {
|
|
|
+ padding: 0 35px 30px 35px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .related-modal .modal-btn {
|
|
|
+ margin-left: 2%;
|
|
|
+ width: 96%;
|
|
|
+ height: 40px;
|
|
|
+ background: rgb(11, 151, 117);
|
|
|
+ border: none;
|
|
|
+ color: #fff;
|
|
|
+ margin-top: 30px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .related-modal .choose-content {
|
|
|
+ height: 85%;
|
|
|
+ }
|
|
|
+
|
|
|
+ .btn-relate-content {
|
|
|
+ right: 0;
|
|
|
+ }
|
|
|
+</style>
|