|
@@ -202,61 +202,97 @@
|
|
|
<Page :total="totalNum" show-sizer show-total :page-size="pageSize" :current="pageNum" @on-page-size-change="pageSizeChange" @on-change="pageChange" :page-size-opts="[10, 20, 30]" />
|
|
|
</div>
|
|
|
<Drawer title="已选择题目" width="40" :mask-closable="false" v-model="showQues" class="select-ques">
|
|
|
- <RadioGroup v-model="saveType" @on-change="saveTypeChange">
|
|
|
+ <!-- <RadioGroup v-model="saveType" @on-change="saveTypeChange">
|
|
|
<Radio label="quesBank">题库</Radio>
|
|
|
<Radio label="paper">试卷</Radio>
|
|
|
- </RadioGroup>
|
|
|
+ </RadioGroup> -->
|
|
|
<div v-if="!selShowList.length">未选择题目</div>
|
|
|
- <div v-else class="content-wrap" style="height: 95%;">
|
|
|
+ <div v-else class="content-wrap" style="height: 90%;">
|
|
|
<vuescroll>
|
|
|
+ <!-- 只在学校题库出现 -->
|
|
|
+ <Form ref="selEvalInfo" :model="selEvalInfo" :rules="evalValidate" label-colon :label-width="100">
|
|
|
+ <template v-if="isSchool">
|
|
|
+ <FormItem :label="$t('evaluation.newExercise.choosePeriod')">
|
|
|
+ <Select v-model="selEvalInfo.paperPeriod" style="width:150px" @on-change="onPeriodChange">
|
|
|
+ <Option v-for="(period, index) in schoolInfo.period" :value="index" :key="index">{{ period.name }}</Option>
|
|
|
+ </Select>
|
|
|
+ </FormItem>
|
|
|
+ <FormItem :label="$t('evaluation.newExercise.chooseGrade')" prop="publish">
|
|
|
+ <Select v-model="selEvalInfo.paperGrade" style="width:150px">
|
|
|
+ <Option v-for="(grade, index) in schGradeList" :value="index" :key="grade">{{ grade }}</Option>
|
|
|
+ </Select>
|
|
|
+ </FormItem>
|
|
|
+ <FormItem :label="$t('evaluation.newExercise.chooseSubject')">
|
|
|
+ <Select v-model="selEvalInfo.paperSubject" style="width:150px">
|
|
|
+ <Option v-for="(subject, index) in schSubjectList" :value="index" :key="index">{{ subject.name }}</Option>
|
|
|
+ </Select>
|
|
|
+ </FormItem>
|
|
|
+ </template>
|
|
|
+ <FormItem label="试卷名称" v-show="selEvalInfo.savetype.includes('paper')" prop="paperName">
|
|
|
+ <Input v-model="selEvalInfo.paperName" placeholder="请输入" />
|
|
|
+ </FormItem>
|
|
|
+ <FormItem label="试卷总分" v-show="selEvalInfo.savetype.includes('paper')" prop="score">
|
|
|
+ <InputNumber :min="1" v-model="totalScore"></InputNumber>
|
|
|
+ </FormItem>
|
|
|
+ </Form>
|
|
|
+ <div style="display: flex; align-items: center; justify-content: space-between; flex-direction: row-reverse; padding-bottom: 15px;">
|
|
|
+ <Button type="info" @click="saveTypeChange(saveType === 'type' ? 'list' : 'type')" style="float: right;">
|
|
|
+ {{ saveType === 'type' ? '题型展示' : '题号展示' }}
|
|
|
+ </Button>
|
|
|
+ <div v-show="selEvalInfo.savetype.includes('paper')">
|
|
|
+ <!-- <span>总分:{{ totalScore }}</span> -->
|
|
|
+ <span>未分配分:
|
|
|
+ <span :style="{'color': surPlusScore === 0 ? '' : 'red'}">{{ surPlusScore }}</span>
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
<div class="list-view" v-for="(quesItem, quesIndex) in selShowList" :key="quesIndex">
|
|
|
- <p v-show="saveType === 'paper' && quesItem.list.length" class="type-name">
|
|
|
+ <p v-show="saveType === 'type' && quesItem.list.length" class="type-name">
|
|
|
{{ $tools.getChineseByNum(getLatestTypeIndex(quesItem.type) + 1) }} : {{ exersicesType[quesItem.type] }}
|
|
|
<span style="font-size: 14px;font-weight: 600;">
|
|
|
({{ `${$t('answerSheet.tip9')} ${quesItem.list.length}${$t('answerSheet.tip17')}${quesItem.score || 0}${$t('evaluation.paperList.score')}` }})
|
|
|
</span>
|
|
|
</p>
|
|
|
- <div class="exercise-item" v-for="(item, index) in quesItem.list" :key="index" @click="onQuestionToggle(index, item.id, $event)">
|
|
|
+ <div class="exercise-item" v-for="(item, index) in quesItem.list" :key="index" @click="onQuestionToggle(index, item.id, $event, true)">
|
|
|
<!-- 工具栏部分 -->
|
|
|
- <div class="item-tools-wrap" v-show="saveType === 'paper'">
|
|
|
- <div class="item-tools-t flex-row-center" @click.stop="handleDelete(quesItem.list,item,index)">
|
|
|
+ <div class="item-tools-wrap" v-show="selEvalInfo.savetype.includes('paper')">
|
|
|
+ <div class="item-tools-t flex-row-center" @click.stop="handleDelete(quesItem.list, item, index)">
|
|
|
<Icon type="ios-archive-outline" />{{$t('evaluation.deleteItem')}}
|
|
|
</div>
|
|
|
- <div class="item-tools-t flex-row-center" v-show="index != 0" @click.stop="handleMoveUp(quesItem.list,index)">
|
|
|
+ <div class="item-tools-t flex-row-center" v-show="index != 0" @click.stop="handleMoveUp(quesItem.list, index)">
|
|
|
<Icon type="md-arrow-up" />{{$t('evaluation.exerciseList.moveUp')}}
|
|
|
</div>
|
|
|
- <div class="item-tools-t flex-row-center" v-show="index != (quesItem.list.length - 1)" @click.stop="handleMoveDown(quesItem.list,index)">
|
|
|
+ <div class="item-tools-t flex-row-center" v-show="index != (quesItem.list.length - 1)" @click.stop="handleMoveDown(quesItem.list, index)">
|
|
|
<Icon type="md-arrow-down" />{{$t('evaluation.exerciseList.moveDown')}}
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="item-question">
|
|
|
- <div>
|
|
|
- <div class="item-question-order">{{ index + 1 }} :</div>
|
|
|
- <div class="item-question-text" v-html="item.question"></div>
|
|
|
+ <div style="max-width: 85%;">
|
|
|
+ <div class="item-question">
|
|
|
+ <div>
|
|
|
+ <div class="item-question-order">{{ index + 1 }} :</div>
|
|
|
+ <div class="item-question-text" v-html="item.question"></div>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <span class="item-btn-toggle" style="justify-content: flex-end;">
|
|
|
- <Icon v-if="item.type !== 'compose'" :type="selcollaList.indexOf(index) > -1 ? 'ios-arrow-dropup' : 'ios-arrow-dropdown'" />
|
|
|
- </span>
|
|
|
- </div>
|
|
|
- <div class="exercise-item-children" v-if="item.children.length">
|
|
|
- <BaseChild ref="childRef" :children="item.children" inBank></BaseChild>
|
|
|
- </div>
|
|
|
- <div v-for="(option, optionIndex) in item.option" :key="optionIndex" class="item-options">
|
|
|
- <div class="item-option-content">
|
|
|
- <div class="item-option-order">
|
|
|
- {{ String.fromCharCode(64 + parseInt(optionIndex + 1)) }} :
|
|
|
+ <div v-for="(option, optionIndex) in item.option" :key="optionIndex" class="item-options">
|
|
|
+ <div class="item-option-content">
|
|
|
+ <div class="item-option-order">
|
|
|
+ {{ String.fromCharCode(64 + parseInt(optionIndex + 1)) }} :
|
|
|
+ </div>
|
|
|
+ <div class="item-option-text" v-html="option.value"></div>
|
|
|
</div>
|
|
|
- <div class="item-option-text" v-html="option.value"></div>
|
|
|
</div>
|
|
|
</div>
|
|
|
- <div class="item-btn-toggle" v-show="saveType === 'paper'">
|
|
|
- <!-- 可调整分数 -->
|
|
|
- <InputNumber v-if="item.type !== 'compose'" :max="item.score + surPlusScore" :min="scoreStep" :step="scoreStep" v-model="item.score" style="display: inline-block ;width: 60px;margin-right: 10px;height: 30px;" @click.stop>
|
|
|
- </InputNumber>
|
|
|
- <span style="margin-right: 10px;" v-if="item.type === 'compose'">{{ getComposeScore(item) }}</span>
|
|
|
- <span style="margin-right: 10px;">{{$t('evaluation.paperList.score')}}</span>
|
|
|
- <!-- <span class="item-score" title="设置题目分数" @click.stop="onSetSingleItem(item,index)" v-else>{{ item.score }} 分</span> -->
|
|
|
- <Icon @click.stop="onQuestionToggle(selectedArr.indexOf(item), item.id, $event, quesItem.list)" :type="selcollaList.indexOf(selectedArr.indexOf(item)) > -1 ? 'ios-arrow-dropup' : 'ios-arrow-dropdown'" v-if="item.type !== 'compose'" />
|
|
|
+ <div class="exercise-item-children" v-if="item.children.length">
|
|
|
+ <BaseChild :children="item.children" :totalScore="item.score" :isShowScore="selEvalInfo.savetype.includes('paper')" :df="true" :scoreChange="scoreChange"></BaseChild>
|
|
|
+ </div>
|
|
|
+ <div class="item-btn-toggle">
|
|
|
+ <template @click.stop v-if="selEvalInfo.savetype.includes('paper')">
|
|
|
+ <!-- 可调整分数 -->
|
|
|
+ <InputNumber v-if="item.type !== 'compose'" :max="item.score + surPlusScore" :min="scoreStep" :step="scoreStep" v-model="item.score" style="display: inline-block ;width: 60px;margin-right: 10px;height: 30px;" @click.stop></InputNumber>
|
|
|
+ <span style="margin-right: 10px;" v-if="item.type === 'compose'">{{ getComposeScore(item) }}</span>
|
|
|
+ <span style="margin-right: 10px;">{{$t('evaluation.paperList.score')}}</span>
|
|
|
+ </template>
|
|
|
+ <Icon @click.stop="onQuestionToggle(selectedArr.indexOf(item), item.id, $event, true)" :type="selcollaList.indexOf(selectedArr.indexOf(item)) > -1 ? 'ios-arrow-dropup' : 'ios-arrow-dropdown'" v-if="item.type !== 'compose'" />
|
|
|
</div>
|
|
|
<transition name="slide" v-if="item.type !== 'compose'">
|
|
|
<div v-show="selcollaList.indexOf(selectedArr.indexOf(item)) > -1" class="toggle-area">
|
|
@@ -318,9 +354,12 @@
|
|
|
</div>
|
|
|
</vuescroll>
|
|
|
</div>
|
|
|
- <div style="display: flex; justify-content: space-between;" v-show="selShowList.length">
|
|
|
- <Button v-show="saveType === 'paper'" @click="saveDFQues('paper')">保存为试卷</Button>
|
|
|
- <Button v-show="saveType != 'paper'" @click="saveDFQues('quesBank')">加入题库</Button>
|
|
|
+ <div style="display: flex; justify-content: space-between; padding-top: 20px;" v-show="selShowList.length">
|
|
|
+ <CheckboxGroup v-model="selEvalInfo.savetype">
|
|
|
+ <Checkbox label="quesBank">同步试题到题库</Checkbox>
|
|
|
+ <Checkbox label="paper">组成试卷</Checkbox>
|
|
|
+ </CheckboxGroup>
|
|
|
+ <Button @click="saveDFQues()">保存</Button>
|
|
|
</div>
|
|
|
</Drawer>
|
|
|
</div>
|
|
@@ -347,7 +386,7 @@ export default {
|
|
|
{id: '历史', name: '历史'},
|
|
|
{id: '生物', name: '生物'},
|
|
|
{id: '政治', name: '政治'},
|
|
|
- ],
|
|
|
+ ], // 多分学科
|
|
|
typeList: [
|
|
|
{id: 'C', name: '选择'},
|
|
|
{id: 'F', name: '填空'},
|
|
@@ -358,8 +397,8 @@ export default {
|
|
|
exersicesDiff: this.$GLOBAL.EXERCISE_DIFFS(),
|
|
|
exersicesType: this.$GLOBAL.EXERCISE_TYPES(),
|
|
|
exersicesField: this.$GLOBAL.EXERCISE_LEVELS(),
|
|
|
- filterGrade: 10,
|
|
|
- filterSubject: '物理',
|
|
|
+ filterGrade: 1,
|
|
|
+ filterSubject: '语文',
|
|
|
filterType: 'all',
|
|
|
filterDiff: 'all',
|
|
|
searchVal: '',
|
|
@@ -368,8 +407,8 @@ export default {
|
|
|
pageNum: 1,
|
|
|
exerciseList: [],
|
|
|
collapseList: [],
|
|
|
- selectedArr: [],
|
|
|
selcollaList: [],
|
|
|
+ selectedArr: [],
|
|
|
orderList: [],
|
|
|
groupList: [],
|
|
|
selShowList: [],
|
|
@@ -377,7 +416,7 @@ export default {
|
|
|
isShowAnswer: true,
|
|
|
isAllOpen: false,
|
|
|
showQues: false,
|
|
|
- saveType: 'quesBank',
|
|
|
+ saveType: 'list',
|
|
|
shoppingCarClass: 'question-shopping-car',
|
|
|
quesTypeList: {
|
|
|
single: 0,
|
|
@@ -388,8 +427,22 @@ export default {
|
|
|
compose: 0
|
|
|
},
|
|
|
scoreStep: 0.5,
|
|
|
- surPlusScore: 0,
|
|
|
needSaveCosmosArr: [],
|
|
|
+ selEvalInfo: {
|
|
|
+ paperPeriod: 0,
|
|
|
+ paperGrade: 0,
|
|
|
+ paperSubject: 0,
|
|
|
+ paperName: '',
|
|
|
+ savetype: ['quesBank'],
|
|
|
+ },
|
|
|
+ evalValidate: {
|
|
|
+ paperName: [{required: true, message: '请输入', trigger: 'blur'}],
|
|
|
+ score: [{required: true, type: Number, message: '请输入', trigger: 'blur'}],
|
|
|
+ },
|
|
|
+ totalScore: 100,
|
|
|
+ schoolInfo: {},
|
|
|
+ schGradeList: [], //当前学校的年级
|
|
|
+ schSubjectList: [], //当前学校的学科
|
|
|
}
|
|
|
},
|
|
|
created() {
|
|
@@ -407,9 +460,21 @@ export default {
|
|
|
isSchool() {
|
|
|
return this.$route.name === 'schoolDf'
|
|
|
},
|
|
|
+ getComposeScore() {
|
|
|
+ return item => {
|
|
|
+ return item.children.length ? item.children.reduce((a, b) => a + b.score, 0) : 0
|
|
|
+ }
|
|
|
+ },
|
|
|
+ surPlusScore() {
|
|
|
+ return this.totalScore - this.selectedArr.reduce((p, e) => Number(p) + Number(e.score), 0)
|
|
|
+ },
|
|
|
},
|
|
|
watch: {
|
|
|
},
|
|
|
+ async mounted () {
|
|
|
+ this.schoolInfo = await this.getSchoolBaseInfo()
|
|
|
+ this.onPeriodChange(0)
|
|
|
+ },
|
|
|
methods: {
|
|
|
getDfList() {
|
|
|
this.isLoading = true
|
|
@@ -481,7 +546,7 @@ export default {
|
|
|
},
|
|
|
});
|
|
|
},
|
|
|
- onQuestionToggle(index, id, e) {
|
|
|
+ onQuestionToggle(index, id, e, isDrawer) {
|
|
|
console.log(e)
|
|
|
this.shoppingCarClass = 'question-shopping-car animated heartBeat'
|
|
|
setTimeout(() => {
|
|
@@ -497,15 +562,29 @@ export default {
|
|
|
)
|
|
|
return
|
|
|
e.stopPropagation()
|
|
|
- let listIndex = this.collapseList.indexOf(index)
|
|
|
- if (listIndex > -1) {
|
|
|
- this.collapseList.splice(listIndex, 1)
|
|
|
+ if(isDrawer) {
|
|
|
+ let listIndex = this.selcollaList.indexOf(index)
|
|
|
+ if (listIndex > -1) {
|
|
|
+ this.selcollaList.splice(listIndex, 1)
|
|
|
+ } else {
|
|
|
+ this.selcollaList.push(index)
|
|
|
+ let path = this.$tools.composedPath(e)
|
|
|
+ let exerciseItemDom = path.filter((i) => i.className === "exercise-item")
|
|
|
+ if (exerciseItemDom.length) {
|
|
|
+ // this.pageScrollTo(exerciseItemDom[0].offsetTop + 180)
|
|
|
+ }
|
|
|
+ }
|
|
|
} else {
|
|
|
- this.collapseList.push(index)
|
|
|
- let path = this.$tools.composedPath(e)
|
|
|
- let exerciseItemDom = path.filter((i) => i.className === "exercise-item")
|
|
|
- if (exerciseItemDom.length) {
|
|
|
- this.pageScrollTo(exerciseItemDom[0].offsetTop + 180)
|
|
|
+ let listIndex = this.collapseList.indexOf(index)
|
|
|
+ if (listIndex > -1) {
|
|
|
+ this.collapseList.splice(listIndex, 1)
|
|
|
+ } else {
|
|
|
+ this.collapseList.push(index)
|
|
|
+ let path = this.$tools.composedPath(e)
|
|
|
+ let exerciseItemDom = path.filter((i) => i.className === "exercise-item")
|
|
|
+ if (exerciseItemDom.length) {
|
|
|
+ this.pageScrollTo(exerciseItemDom[0].offsetTop + 180)
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
},
|
|
@@ -524,6 +603,7 @@ export default {
|
|
|
this.shoppingCarClass = 'question-shopping-car'
|
|
|
},
|
|
|
goToPreview() {
|
|
|
+ if(!this.selectedArr.length) return
|
|
|
this.orderList = []
|
|
|
this.groupList = []
|
|
|
let that = this
|
|
@@ -539,14 +619,23 @@ export default {
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
- this.orderList.push({list: this._.cloneDeep(this.selectedArr)})
|
|
|
- this.selShowList = this._.cloneDeep(this.orderList)
|
|
|
- // 总分默认100
|
|
|
- this.surPlusScore = 100 - this.selectedArr.reduce((p, e) => Number(p) + Number(e.score), 0);
|
|
|
+ this.orderList.push({list: this.selectedArr})
|
|
|
+ this.selShowList = this.saveType === 'list' ? this.orderList : this.groupList
|
|
|
this.showQues = true
|
|
|
- // this.$emit('goToPreview')
|
|
|
// 使用弹出框展示已选题目,再选择加入题库/组成试卷
|
|
|
},
|
|
|
+ scoreChange(val, pid, id) {
|
|
|
+ let parent = this.selectedArr.find(item => item.id === pid)
|
|
|
+ parent.score = 0
|
|
|
+ parent.children.forEach(child => {
|
|
|
+ if(child.id === id) {
|
|
|
+ child.score = val
|
|
|
+ }
|
|
|
+ parent.score += child.score
|
|
|
+ })
|
|
|
+ // 总分默认100
|
|
|
+ // this.surPlusScore = this.totalScore - this.selectedArr.reduce((p, e) => Number(p) + Number(e.score), 0)
|
|
|
+ },
|
|
|
async onSelectAll() {
|
|
|
this.selectedArr = this.isSelectAll ? this._.cloneDeep(this.exerciseList) : []
|
|
|
let groupResult = await this.$jsFn.groupBy(this.selectedArr, 'type')
|
|
@@ -569,11 +658,8 @@ export default {
|
|
|
}
|
|
|
},
|
|
|
saveTypeChange(val) {
|
|
|
- if(val === 'quesBank') {
|
|
|
- this.selShowList = this._.cloneDeep(this.orderList)
|
|
|
- } else {
|
|
|
- this.selShowList = this._.cloneDeep(this.groupList)
|
|
|
- }
|
|
|
+ this.saveType = val
|
|
|
+ this.selShowList = val === 'list' ? this.orderList : this.groupList
|
|
|
},
|
|
|
getLatestTypeIndex(type) {
|
|
|
let arr = []
|
|
@@ -584,11 +670,6 @@ export default {
|
|
|
})
|
|
|
return arr.indexOf(type)
|
|
|
},
|
|
|
- getComposeScore() {
|
|
|
- return item => {
|
|
|
- return item.children.length ? item.children.reduce((a, b) => a + b.score, 0) : 0
|
|
|
- }
|
|
|
- },
|
|
|
// 子题顺序操作
|
|
|
moveItems(arr, index1, index2) {
|
|
|
arr[index1] = arr.splice(index2, 1, arr[index1])[0]
|
|
@@ -611,31 +692,60 @@ export default {
|
|
|
title: this.$t('evaluation.newExercise.modalTip'),
|
|
|
content: this.$t('evaluation.exerciseList.confirmDelete'),
|
|
|
onOk: () => {
|
|
|
- this.surPlusScore += item.score
|
|
|
- arr.splice(index, 1)
|
|
|
+ // this.surPlusScore += item.score
|
|
|
+ // arr.splice(index, 1)
|
|
|
this.selectedArr.splice(this.selectedArr.indexOf(item), 1)
|
|
|
this.$Message.success(this.$t('evaluation.deleteSuc'))
|
|
|
}
|
|
|
})
|
|
|
},
|
|
|
- saveDFQues(type) {
|
|
|
- if(type === 'paper') {
|
|
|
-
|
|
|
+ /** 获取当前学校基础数据 */
|
|
|
+ getSchoolBaseInfo() {
|
|
|
+ return new Promise((r, j) => {
|
|
|
+ this.$store.dispatch("user/getSchoolProfile").then((res) => {
|
|
|
+ let schoolBaseInfo = res.school_base;
|
|
|
+ if (schoolBaseInfo) {
|
|
|
+ this.schoolInfo = schoolBaseInfo
|
|
|
+ r(schoolBaseInfo)
|
|
|
+ } else {
|
|
|
+ r(null)
|
|
|
+ }
|
|
|
+ });
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /* 学段切换 */
|
|
|
+ onPeriodChange(val) {
|
|
|
+ this.schGradeList = this.schoolInfo.period[val].grades
|
|
|
+ this.schSubjectList = this.schoolInfo.period[val].subjects
|
|
|
+ },
|
|
|
+ saveDFQues() {
|
|
|
+ if(!this.selectedArr.length) {
|
|
|
+ this.$Message.warning('请先选择题目')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if(!this.selEvalInfo.savetype.length) {
|
|
|
+ this.$Message.warning('请选择导入题库或组成试卷')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if(this.selEvalInfo.savetype.includes('paper') && (!this.selEvalInfo.paperName || !this.totalScore)) {
|
|
|
+ this.$Message.warning('请完善信息')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ // 弹出框让用户选择学段、年级、学科,以及试卷名称
|
|
|
+ if(this.isSchool) {
|
|
|
+ this.selectedArr.forEach(item => {
|
|
|
+ item.periodId = this.schoolInfo.period[this.selEvalInfo.paperPeriod].id
|
|
|
+ item.gradeIds = [String(this.selEvalInfo.paperGrade)]
|
|
|
+ item.subjectId = this.schSubjectList[this.selEvalInfo.paperSubject].id
|
|
|
+ })
|
|
|
+ }
|
|
|
+ console.log('开始保存');
|
|
|
+ // 组成试卷,必要将题目保存在blob
|
|
|
+ if(this.selEvalInfo.savetype.includes('paper')) {
|
|
|
+ this.savePaper(this.selectedArr)
|
|
|
} else {
|
|
|
- this.saveQuesBank(this.selShowList[0].list, true).then(async res => {
|
|
|
- console.log(res);
|
|
|
- // 校本组卷情况下 同步知识点数据
|
|
|
- /* if (this.isSchool && this.isSavePoints && this.evaluationInfo.createType === 'import') {
|
|
|
- if (this.importKnowledges.length) {
|
|
|
- let paperItem = {
|
|
|
- code: this.editPaper ? this.editPaper.code.replace('Paper-', '') : (this.isSchool ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId),
|
|
|
- subjectId: this.isSchool ? this.subjectList[this.evaluationInfo.paperSubject].id : null,
|
|
|
- periodId: this.isSchool ? this.schoolInfo.period[this.evaluationInfo.paperPeriod].id : null,
|
|
|
- }
|
|
|
- this.importKnowledges.push(...refreshList.map(i => i.knowledge).flat(1))
|
|
|
- await this.saveImportPoints([...new Set(this.importKnowledges)], paperItem)
|
|
|
- }
|
|
|
- } */
|
|
|
+ // 同步到题库
|
|
|
+ this.saveQuesBank(this.selectedArr, true).then(async res => {
|
|
|
this.$Spin.hide()
|
|
|
this.$Message.success(this.$t('evaluation.paperList.saveSuc'))
|
|
|
this.isLoading = false
|
|
@@ -725,7 +835,6 @@ export default {
|
|
|
// 首先保存新题目的JSON文件到Blob 然后返回URL链接
|
|
|
let file = new File([JSON.stringify(itemJsonFile)], item.id + ".json")
|
|
|
blobFiles.push(file)
|
|
|
- console.log(isToItemBank);
|
|
|
try {
|
|
|
if (!isToItemBank) {
|
|
|
r({
|
|
@@ -779,7 +888,6 @@ export default {
|
|
|
// 主观题的answer为空数组
|
|
|
let nullType = ['complete', 'subjective', 'compose', 'correct', 'connector']
|
|
|
result.map(i => i.cosmosItem).forEach(item => {
|
|
|
- console.log(item)
|
|
|
let o = {
|
|
|
url: item.id + '.json',
|
|
|
type: item.type,
|
|
@@ -806,7 +914,360 @@ export default {
|
|
|
})
|
|
|
},
|
|
|
async savePaper(list) {
|
|
|
-
|
|
|
+ let noScoreList = this.selectedArr.filter(item => item.score === 0) // 判断是否有未配分的题目
|
|
|
+ let groupTypeList = this.groupList
|
|
|
+ let paperName = this.selEvalInfo.paperName.trim()
|
|
|
+ if (paperName === '') {
|
|
|
+ this.$Message.warning(this.$t('evaluation.paperList.emptyNameTip'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (this.surPlusScore === 0) {
|
|
|
+ if (!noScoreList.length) {
|
|
|
+ let isPaperExist = await this.isPaperExist(this.selEvalInfo.paperName)
|
|
|
+ let isContainerFull = await this.isContainerFull()
|
|
|
+ if (!isPaperExist) {
|
|
|
+ if (list.length) {
|
|
|
+ // 拿到题型顺序的试题数组进行拼接
|
|
|
+ let arr = []
|
|
|
+ groupTypeList.forEach(i => {
|
|
|
+ arr = arr.concat(i.list)
|
|
|
+ })
|
|
|
+ if (!this.checkComposeScore(arr)) return
|
|
|
+ if (isContainerFull) {
|
|
|
+ this.$Message.warning(this.$t('evaluation.paperList.noSpaceTip'))
|
|
|
+ } else {
|
|
|
+ // 只按照默认顺序保存
|
|
|
+ let saveArr = this.saveType === 'type' ? arr : list
|
|
|
+ this.doSavePaper(saveArr)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.isLoading = false
|
|
|
+ this.$Message.warning(this.$t('evaluation.paperList.noItemTip'))
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 处理已存在同名称的试卷
|
|
|
+ this.$Modal.confirm({
|
|
|
+ title: this.$t('evaluation.newExercise.modalTip'),
|
|
|
+ content: this.$t('evaluation.paperList.isExistPaperTip'),
|
|
|
+ onOk: async () => {
|
|
|
+ // 拿到题型顺序的试题数组进行拼接
|
|
|
+ let arr = []
|
|
|
+ groupTypeList.forEach(i => {
|
|
|
+ arr = arr.concat(i.list)
|
|
|
+ })
|
|
|
+ if (!this.checkComposeScore(arr)) return
|
|
|
+ try {
|
|
|
+ // 如果是已存在相同名称的试卷,则进行覆盖,先删除原来的目录再进行保存
|
|
|
+ let blobList = await this.getPaperFiles('paper/' + this.selEvalInfo.paperName + '/')
|
|
|
+ let files = blobList.blobList.map(i => {
|
|
|
+ return {
|
|
|
+ blob: i.blob,
|
|
|
+ size: i.size
|
|
|
+ }
|
|
|
+ })
|
|
|
+ this.deleteNoUseItem(files, arr).then(r => {
|
|
|
+ if (isContainerFull) {
|
|
|
+ this.$Message.warning(this.$t('evaluation.paperList.noSpaceTip'))
|
|
|
+ } else {
|
|
|
+ // 只按照默认顺序保存 arr代表题型排序 list代表的是顺序排序
|
|
|
+ let saveArr = this.saveType === 'type' ? arr : list
|
|
|
+ this.doSavePaper(saveArr)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } catch (e) {
|
|
|
+ this.$Message.error(e)
|
|
|
+ this.isLoading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onCancel: () => {
|
|
|
+ this.isLoading = false
|
|
|
+ this.$Message.warning(this.$t('evaluation.paperList.cancelSaveTip'))
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.$Message.warning(this.$t('evaluation.paperList.hasNoScoreTip'))
|
|
|
+ this.isLoading = false
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.$Message.warning(this.$t('evaluation.paperList.noCompleteScoreTip'))
|
|
|
+ this.isLoading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /* 保存试卷业务 */
|
|
|
+ async doSavePaper(list) {
|
|
|
+ this.$Modal.remove()
|
|
|
+ // 将传进来的试题 如果是导入的试题 则需要补充年级学段等信息
|
|
|
+ let isToItemBank = this.selEvalInfo.savetype.includes('quesBank')
|
|
|
+ // 初始化试卷数据
|
|
|
+ let guid = this.$tools.guid()
|
|
|
+ let paperItem = {
|
|
|
+ id: guid,
|
|
|
+ code: this.isSchool ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId,
|
|
|
+ scope: this.isSchool ? 'school' : 'private',
|
|
|
+ itemSort: this.saveType === 'list' ? 1 : 0,
|
|
|
+ gradeIds: this.isSchool ? [String(this.selEvalInfo.paperGrade)] : [],
|
|
|
+ subjectId: this.isSchool ? this.schSubjectList[this.selEvalInfo.paperSubject].id : null,
|
|
|
+ subjectName: this.isSchool ? this.schSubjectList[this.selEvalInfo.paperSubject].name : '',
|
|
|
+ periodId: this.isSchool ? this.schoolInfo.period[this.selEvalInfo.paperPeriod].id : null,
|
|
|
+ name: this.selEvalInfo.paperName,
|
|
|
+ points: this.getPaperPoints(list),
|
|
|
+ scoring: this.getAnswers(list),
|
|
|
+ score: this.totalScore,
|
|
|
+ sheet: null, //答题卡
|
|
|
+ tags: [],
|
|
|
+ multipleRule: 1, //阅卷规则
|
|
|
+ typeSummaryInfo: {}, //说明文本
|
|
|
+ orderTemp: this.orderTempIndex //题号模板
|
|
|
+ }
|
|
|
+ this.isLoading = true
|
|
|
+ // 保存导入的试题到BLOB以及COSMOS
|
|
|
+ this.saveQuesBank(list, isToItemBank).then(async res => {
|
|
|
+ console.error(res)
|
|
|
+ let blobPaper = await this.$evTools.createBlobPaper(paperItem, res.slides)
|
|
|
+ // 首先保存新题目的JSON文件到Blob 然后返回URL链接
|
|
|
+ let paperFile = new File([JSON.stringify(blobPaper)], "index.json");
|
|
|
+ // 获取初始化Blob需要的数据
|
|
|
+ let sasData = this.isSchool ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
|
|
|
+ //初始化Blob
|
|
|
+ let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, this.isSchool ? 'school' : 'private')
|
|
|
+ try {
|
|
|
+ let promiseArr = []
|
|
|
+ let blobFile = null
|
|
|
+ // 放入试题json文件
|
|
|
+ for (let i = 0; i < res.files.length; i++) {
|
|
|
+ promiseArr.push(new Promise(async (r, j) => {
|
|
|
+ try {
|
|
|
+ let item = res.files[i]
|
|
|
+ const itemJsonFile = await this.$evTools.createBlobItem(item)
|
|
|
+ let file = new File([JSON.stringify(itemJsonFile)], item.id + ".json");
|
|
|
+ containerClient.upload(file, {
|
|
|
+ path: 'paper/' + paperItem.name,
|
|
|
+ checkSize: false
|
|
|
+ }).then(res => {
|
|
|
+ r(200)
|
|
|
+ })
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e)
|
|
|
+ }
|
|
|
+ }))
|
|
|
+ }
|
|
|
+ // 放入index.json文件
|
|
|
+ promiseArr.push(new Promise(async (r, j) => {
|
|
|
+ try {
|
|
|
+ blobFile = await containerClient.upload(paperFile, {
|
|
|
+ path: 'paper/' + paperItem.name,
|
|
|
+ checkSize: false
|
|
|
+ })
|
|
|
+ console.log('上传到试卷目录下', blobFile)
|
|
|
+ r(blobFile)
|
|
|
+ } catch (e) {
|
|
|
+ j(e)
|
|
|
+ this.$Message.error(e.spaceError)
|
|
|
+ this.isLoading = false
|
|
|
+ }
|
|
|
+ }))
|
|
|
+ // 不存在多媒体
|
|
|
+
|
|
|
+ // 进行试卷文件上传Blob 先上传所有题目 再上传index.json文件
|
|
|
+ Promise.all(promiseArr).then(async result => {
|
|
|
+ try {
|
|
|
+ // 检查试卷目录下是否有 已被移除的试题 有则进行删除操作
|
|
|
+ let blobList = await this.getPaperFiles('paper/' + paperItem.name + '/')
|
|
|
+ let files = blobList.blobList.map(i => {
|
|
|
+ return {
|
|
|
+ blob: i.blob,
|
|
|
+ size: i.size
|
|
|
+ }
|
|
|
+ })
|
|
|
+ await this.deleteNoUseItem(files, res.files)
|
|
|
+
|
|
|
+ if (blobFile.blob) {
|
|
|
+ // 试卷保存更新后需要重新生成答题卡
|
|
|
+ paperItem.blob = blobFile.blob.split('/index.json')[0]
|
|
|
+
|
|
|
+ let params = {
|
|
|
+ paper: await this.$evTools.createCosmosPaper(paperItem),
|
|
|
+ option: this.isEditPaper ? 'update' : 'insert'
|
|
|
+ }
|
|
|
+ // 保存试卷到cosmos
|
|
|
+ this.$api.learnActivity.SaveExamPaper(params).then(res => {
|
|
|
+ if (res.error == null) {
|
|
|
+ this.$Message.success(this.$t('evaluation.paperList.saveSuc'))
|
|
|
+ this.isLoading = false
|
|
|
+ this.$Spin.hide()
|
|
|
+ // this.savePeriodInfos()
|
|
|
+ // 清空已选试题
|
|
|
+ this.showQues = false
|
|
|
+ this.selectedArr = []
|
|
|
+ this.groupList = []
|
|
|
+ this.orderList = []
|
|
|
+ this.selShowList = []
|
|
|
+ } else {
|
|
|
+ this.$Message.error(this.$t('evaluation.paperList.saveFail'))
|
|
|
+ this.$Spin.hide()
|
|
|
+ this.isLoading = false
|
|
|
+ }
|
|
|
+ },err => {
|
|
|
+ this.$Message.error(this.$t('evaluation.paperList.saveFail'))
|
|
|
+ this.isLoading = false
|
|
|
+ this.$Spin.hide()
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ console.error(blobFile)
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } catch (e) {
|
|
|
+ console.log(e)
|
|
|
+ this.$Message.error(this.$t('evaluation.paperList.saveItemsFailTip'))
|
|
|
+ this.isLoading = false
|
|
|
+ }
|
|
|
+ }).catch(e => {
|
|
|
+ this.$Message.error(this.$t('evaluation.paperList.saveItemsFailTip'))
|
|
|
+ this.isLoading = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /* 获取整张试卷的知识点集合 */
|
|
|
+ getPaperPoints(items) {
|
|
|
+ let arr = []
|
|
|
+ items.forEach((i, index) => {
|
|
|
+ if (i.knowledge) {
|
|
|
+ arr = arr.concat(i.knowledge)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return arr
|
|
|
+ },
|
|
|
+ /* 获取整张试卷的答案合计Answers */
|
|
|
+ getAnswers(items) {
|
|
|
+ let arr = []
|
|
|
+ // 主观题的answer为空数组
|
|
|
+ let nullType = ['complete', 'subjective', 'compose', 'correct', 'connector']
|
|
|
+ items.forEach((i, index) => {
|
|
|
+ arr.push({
|
|
|
+ type: i.type,
|
|
|
+ ans: nullType.includes(i.type) ? [] : i.answer,
|
|
|
+ score: i.score
|
|
|
+ })
|
|
|
+ })
|
|
|
+ return arr
|
|
|
+ },
|
|
|
+ // 判断空间状态
|
|
|
+ isContainerFull() {
|
|
|
+ return new Promise(async (r, j) => {
|
|
|
+ let scope = this.isSchool ? 'school' : 'private'
|
|
|
+ // 获取初始化Blob需要的数据
|
|
|
+ let sasData = this.isSchool ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
|
|
|
+ //初始化Blob
|
|
|
+ let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, scope)
|
|
|
+ containerClient.isContainerFull(scope).then((res) => {
|
|
|
+ r(res)
|
|
|
+ },(err) => {
|
|
|
+ j(err)
|
|
|
+ this.$Message.error('API Error')
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 判断试卷是否存在于Blob中
|
|
|
+ isPaperExist(paperName) {
|
|
|
+ return new Promise(async (r, j) => {
|
|
|
+ // 获取初始化Blob需要的数据
|
|
|
+ let sasData = this.isSchool ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
|
|
|
+ //初始化Blob
|
|
|
+ let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, this.isSchool ? 'school' : 'private')
|
|
|
+ containerClient.exists('paper/' + paperName + '/index.json').then((res) => {
|
|
|
+ r(res)
|
|
|
+ },(err) => {
|
|
|
+ j(err)
|
|
|
+ this.$Message.error('API Error')
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /* 检查综合题配分是否正确 */
|
|
|
+ checkComposeScore(arr) {
|
|
|
+ let flag = true
|
|
|
+ for (let index = 0; index < arr.length; index++) {
|
|
|
+ let i = arr[index]
|
|
|
+ if (i.type === 'compose' && i.children.length) {
|
|
|
+ let childTotalScore = i.children.reduce((p, e) => p + e.score, 0)
|
|
|
+ let hasNoScoreChild = i.children.filter(j => !j.score).length > 0
|
|
|
+ if (i.score !== childTotalScore || hasNoScoreChild) {
|
|
|
+ console.log(i.score)
|
|
|
+ console.log(childTotalScore)
|
|
|
+ console.log(index)
|
|
|
+ /* let exList = this.$refs.testPaper.$refs.exList
|
|
|
+ let exerciseDom = Array.from(exList.$el.getElementsByClassName('exercise-item')).filter(item => item.dataset.id === i.id)[0]
|
|
|
+ exerciseDom.style.backgroundColor = '#ffa7a7'
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$refs.paperRef) {
|
|
|
+ this.$refs['paperRef'].scrollTo({y: exerciseDom.offsetTop}, 500)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ setTimeout(() => {
|
|
|
+ exerciseDom.style.backgroundColor = '#fff'
|
|
|
+ }, 2000) */
|
|
|
+ this.$Message.warning(`${this.$t('evaluation.createPaper.tip1')} ${index + 1} ${this.$t('evaluation.createPaper.tip2')}${i.score > childTotalScore ? this.$t('evaluation.createPaper.tip3') : this.$t('evaluation.createPaper.tip4')},${this.$t('evaluation.createPaper.tip5')}`)
|
|
|
+ flag = false
|
|
|
+ this.isLoading = false
|
|
|
+ break
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ flag = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return flag
|
|
|
+ },
|
|
|
+ /* 获取指定路径试卷下的所有文件 */
|
|
|
+ getPaperFiles(path) {
|
|
|
+ return new Promise(async (r, j) => {
|
|
|
+ // 获取初始化Blob需要的数据
|
|
|
+ let sasData = this.isSchool ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
|
|
|
+ //初始化Blob
|
|
|
+ let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, this.isSchool ? 'school' : 'private')
|
|
|
+ // 等待blob的返回结果
|
|
|
+ containerClient.listBlob({prefix: path}).then((res) => {
|
|
|
+ r(res)
|
|
|
+ },(err) => {
|
|
|
+ this.$Message.error('API Error')
|
|
|
+ })
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /* 删除同名试卷覆盖情况下 已被移除的试题 */
|
|
|
+ deleteNoUseItem(blobList, arr) {
|
|
|
+ return new Promise(async (resolve, reject) => {
|
|
|
+ let needDeleteUrlArr = []
|
|
|
+ blobList.forEach(s => {
|
|
|
+ if (s.blob.includes('.json')) {
|
|
|
+ let id = s.blob.split('/')[s.blob.split('/').length - 1].replace('.json', '')
|
|
|
+ if (id !== 'index' && arr.map(i => i.id).indexOf(id) === -1) {
|
|
|
+ needDeleteUrlArr.push(s)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+ if (!needDeleteUrlArr.length) {
|
|
|
+ resolve(200)
|
|
|
+ } else {
|
|
|
+ let promiseArr = []
|
|
|
+ let sas = this.isSchool ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
|
|
|
+ let blobClient = new blobTool(sas.url, sas.name, sas.sas, this.isSchool ? 'school' : 'private')
|
|
|
+ needDeleteUrlArr.forEach(item => {
|
|
|
+ promiseArr.push(new Promise((r, j) => {
|
|
|
+ blobClient.deleteBlob(item.blob, item.size).then((res) => {
|
|
|
+ r(200)
|
|
|
+ },(err) => {
|
|
|
+ j(err)
|
|
|
+ })
|
|
|
+ }))
|
|
|
+ })
|
|
|
+ Promise.all(promiseArr).then(result => {
|
|
|
+ resolve(200)
|
|
|
+ }).catch(e => {
|
|
|
+ reject(e)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
},
|
|
|
},
|
|
|
}
|
|
@@ -818,5 +1279,50 @@ export default {
|
|
|
<style lang="less">
|
|
|
.select-ques {
|
|
|
background-color: #f6f6f6;
|
|
|
+ .list-view {
|
|
|
+ margin-top: 20px;
|
|
|
+ }
|
|
|
+ .exercise-item {
|
|
|
+ &:hover {
|
|
|
+ .item-tools-wrap{
|
|
|
+ display: block;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .item-tools-wrap {
|
|
|
+ position: absolute;
|
|
|
+ right: -2px;
|
|
|
+ top: -32px;
|
|
|
+ width: auto;
|
|
|
+ height: 30px;
|
|
|
+ margin: 0;
|
|
|
+ padding: 0;
|
|
|
+ background: #01b4ef;
|
|
|
+ display: none;
|
|
|
+ }
|
|
|
+ .flex-row-center {
|
|
|
+ display: flex;
|
|
|
+ flex-direction: row;
|
|
|
+ justify-content: center;
|
|
|
+ align-items: center;
|
|
|
+ }
|
|
|
+ .item-tools-t {
|
|
|
+ height: 100%;
|
|
|
+ padding: 0 15px;
|
|
|
+ float: left;
|
|
|
+ color: white;
|
|
|
+ cursor: pointer;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-question .item-question-text {
|
|
|
+ display: inline-block;
|
|
|
+ width: calc(90% - 30px);
|
|
|
+ }
|
|
|
+ .exercise-item-children {
|
|
|
+ .child-tools-wrap {
|
|
|
+ display: none !important;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
</style>
|