|
@@ -0,0 +1,380 @@
|
|
|
+<template>
|
|
|
+ <div class="import-create-wrap">
|
|
|
+ <BaseImport @importFinish="onImportFinish"></BaseImport>
|
|
|
+ <Modal v-model="importStatus" title="导入试卷" width="1200" @on-ok="saveTestPaper">
|
|
|
+ <TestPaper ref="testPaper" :paper="evaluationInfo"></TestPaper>
|
|
|
+ </Modal>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<script>
|
|
|
+import blobTool from '@/utils/blobTool.js'
|
|
|
+import BaseImport from '@/view/evaluation/components/BaseImport.vue'
|
|
|
+import TestPaper from '@/view/evaluation/index/TestPaper.vue'
|
|
|
+export default {
|
|
|
+ components: {
|
|
|
+ BaseImport, TestPaper
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ routerScope: '',
|
|
|
+ importStatus: false,
|
|
|
+ errorList: [],
|
|
|
+ evaluationInfo: {
|
|
|
+ name: '测试创建评测导入试卷',
|
|
|
+ target: [],
|
|
|
+ type: 'private',
|
|
|
+ publish: '',
|
|
|
+ paperPeriod: 0,
|
|
|
+ paperGrade: [],
|
|
|
+ paperSubject: 0,
|
|
|
+ score: 100,
|
|
|
+ item: [],
|
|
|
+ startTime: 0,
|
|
|
+ endTime: 0,
|
|
|
+ createType: 'auto'
|
|
|
+ },
|
|
|
+ }
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ //导入试卷解析完成
|
|
|
+ async onImportFinish(list) {
|
|
|
+ this.errorList = []
|
|
|
+ this.evaluationInfo.item = []
|
|
|
+ let importList = await this.refreshImportItems(list)
|
|
|
+ this.evaluationInfo.item = importList
|
|
|
+ console.log(this.evaluationInfo)
|
|
|
+ console.log('error', this.errorList)
|
|
|
+ if (this.errorList.length) {
|
|
|
+ this.$EventBus.$emit('importFinish', this.errorList)
|
|
|
+ } else {
|
|
|
+ this.importStatus = true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /* 给导入的试题 补充最新的试卷学段年级以及科目信息 */
|
|
|
+ refreshImportItems(list) {
|
|
|
+ return new Promise((r, j) => {
|
|
|
+ let objectiveTypes = ['single', 'multiple']
|
|
|
+ let code = this.routerScope == 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId
|
|
|
+ let gradeIds = []
|
|
|
+ let subjectId = ''
|
|
|
+ let periodId = ''
|
|
|
+ for (let j = 0; j < list.length; j++) {
|
|
|
+ let i = list[j]
|
|
|
+ if (i.blob && i.id) {
|
|
|
+ console.log('题目已存在不需要刷新基础信息')
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ /* 如果是导入的试题 没有ID 则试题的信息和当前试卷的学段信息保持一致 */
|
|
|
+ i.id = this.$tools.guid()
|
|
|
+ i.code = code
|
|
|
+ i.level = 3
|
|
|
+ i.field = 1
|
|
|
+ i.scope = this.isSchool ? 'school' : 'private'
|
|
|
+ i.gradeIds = gradeIds
|
|
|
+ i.subjectId = ''
|
|
|
+ i.periodId = ''
|
|
|
+ if (i.children.length) {
|
|
|
+ i.children.forEach(j => {
|
|
|
+ j.id = this.$tools.guid()
|
|
|
+ j.pid = i.id
|
|
|
+ j.scope = i.scope
|
|
|
+ j.code = code
|
|
|
+ j.level = 3
|
|
|
+ j.field = 1
|
|
|
+ j.gradeIds = []
|
|
|
+ j.subjectId = []
|
|
|
+ j.periodId = []
|
|
|
+ })
|
|
|
+ }
|
|
|
+ // 如果导入的是客观题 则需要检测答案与选项是否为空
|
|
|
+ if (objectiveTypes.includes(i.type) && (!i.question.replace(/\s*/g, "") || !i.option.length || !i.answer.length)) {
|
|
|
+ this.errorList.push(i)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ r(list)
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /** 保存当前试卷数据 */
|
|
|
+ async saveTestPaper() {
|
|
|
+ let exListVm = this.$refs.testPaper.$refs.exList
|
|
|
+ let hasSurplus = exListVm.surPlusScore // 判断是否有剩余分数未分配
|
|
|
+ let noScoreList = exListVm.exerciseList.filter(item => item.score === 0) // 判断是否有未配分的题目
|
|
|
+ let hasErrorItem = exListVm.errorList.length > 0
|
|
|
+ let groupTypeList = exListVm.groupTypeList
|
|
|
+ let list = this.evaluationInfo.item
|
|
|
+ this.$refs.testPaper.isShowAnalysis = false
|
|
|
+ if (this.evaluationInfo.name.trim() === '') {
|
|
|
+ this.$Message.warning('试卷名称不能为空!')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if (!hasErrorItem) {
|
|
|
+ if (hasSurplus === 0) {
|
|
|
+ if (!noScoreList.length) {
|
|
|
+ this.isLoading = true
|
|
|
+ let isPaperExist = await this.isPaperExist(this.evaluationInfo.name)
|
|
|
+ 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('空间已满!')
|
|
|
+ } else {
|
|
|
+ this.doSavePaper(arr)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.$Message.warning('未选择任何试题!')
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.$Modal.confirm({
|
|
|
+ title: '温馨提示',
|
|
|
+ content: '<p>试卷库已存在重复名称试卷,是否继续保存覆盖原试卷?</p>',
|
|
|
+ okText: '确认',
|
|
|
+ cancelText: '取消',
|
|
|
+ onOk: async () => {
|
|
|
+ // 拿到题型顺序的试题数组进行拼接
|
|
|
+ let arr = []
|
|
|
+ groupTypeList.forEach(i => {
|
|
|
+ arr = arr.concat(i.list)
|
|
|
+ })
|
|
|
+ this.isLoading = true
|
|
|
+ if (!this.checkComposeScore(arr)) return
|
|
|
+ let blobList = await this.getPaperFiles('paper/' + this.evaluationInfo.name)
|
|
|
+ let files = blobList.blobList.map(i => i.blob)
|
|
|
+ this.onDeleteBlobPaper(files).then(r => {
|
|
|
+ if (isContainerFull) {
|
|
|
+ this.$Message.warning('空间已满!')
|
|
|
+ } else {
|
|
|
+ this.doSavePaper(arr)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ onCancel: () => {
|
|
|
+ this.isLoading = false
|
|
|
+ this.$Message.warning('取消保存试卷')
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.$Message.warning(`存在未配分的题目,请配分后再保存!`)
|
|
|
+ this.isLoading = false
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.$Message.warning(`保存前请确认试卷配分是否与试卷总分一致!`)
|
|
|
+ this.isLoading = false
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.$Message.warning(`存在异常试题,请修改或者重新导入!`)
|
|
|
+ this.isLoading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 判断试卷是否存在于Blob中
|
|
|
+ isPaperExist(paperName) {
|
|
|
+ return new Promise(async (r, j) => {
|
|
|
+ // 获取初始化Blob需要的数据
|
|
|
+ let sasData = this.routerScope == 'school' ? 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')
|
|
|
+ }
|
|
|
+ )
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 判断空间是否已满
|
|
|
+ isContainerFull() {
|
|
|
+ return new Promise(async (r, j) => {
|
|
|
+ let scope = this.routerScope
|
|
|
+ // 获取初始化Blob需要的数据
|
|
|
+ let sasData = this.routerScope == 'school' ? 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')
|
|
|
+ }
|
|
|
+ )
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /* 检查综合题配分是否正确 */
|
|
|
+ checkComposeScore(arr) {
|
|
|
+ let flag = true
|
|
|
+ arr.forEach((i, index) => {
|
|
|
+ if (i.type === 'compose' && i.children.length) {
|
|
|
+ let childTotalScore = i.children.reduce((p, e) => parseInt(p) + parseInt(e.score), 0)
|
|
|
+ let hasNoScoreChild = i.children.filter(j => !j.score).length > 0
|
|
|
+ if (i.score !== childTotalScore || hasNoScoreChild) {
|
|
|
+ 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(`第 ${index + 1} 题综合题的配分${i.score > childTotalScore ? '不足' : '溢出'},请检查后重试!`)
|
|
|
+ flag = false
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ flag = true
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return flag
|
|
|
+ },
|
|
|
+ /* 保存试卷业务 */
|
|
|
+ async doSavePaper(list) {
|
|
|
+ console.log('保存的试卷题目集合', list)
|
|
|
+ this.isLoading = true
|
|
|
+ let multipleRule = this.$refs.testPaper.$refs.exList.multipleRule
|
|
|
+ let modifyItems = this.$refs.testPaper.$refs.exList.modifyItems
|
|
|
+ // 将传进来的试题 如果是导入的试题 则需要补充年级学段等信息
|
|
|
+ let refreshList = await this.refreshImportItems(list)
|
|
|
+ // 保存导入的试题到BLOB以及COSMOS
|
|
|
+ this.savePaperItems(refreshList, modifyItems, this.isEditPaper).then(async res => {
|
|
|
+ let guid = this.$tools.guid()
|
|
|
+ let paperItem = {
|
|
|
+ id: this.evaluationInfo.id || guid,
|
|
|
+ code: this.editPaper ? this.editPaper.code : (this.isSchool ? this.$store.state.userInfo.schoolCode : this.$store
|
|
|
+ .state.userInfo.TEAMModelId),
|
|
|
+ scope: this.isSchool ? 'school' : 'private',
|
|
|
+ gradeIds: this.isSchool ? (this.evaluationInfo.paperGrade.length ? this.evaluationInfo.paperGrade : this.gradeList
|
|
|
+ .map(i => i.id)) : [],
|
|
|
+ subjectId: this.isSchool ? this.subjectList[this.evaluationInfo.paperSubject].id : null,
|
|
|
+ subjectName: this.isSchool ? this.subjectList[this.evaluationInfo.paperSubject].name : '',
|
|
|
+ periodId: this.isSchool ? this.schoolInfo.period[this.evaluationInfo.paperPeriod].id : null,
|
|
|
+ name: this.evaluationInfo.name,
|
|
|
+ points: this.getPaperPoints(this.evaluationInfo.item),
|
|
|
+ scoring: this.getAnswers(list),
|
|
|
+ score: this.evaluationInfo.score,
|
|
|
+ multipleRule: multipleRule || 1
|
|
|
+ }
|
|
|
+ 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.evaluationInfo.type === 'private' ? await this.$tools.getPrivateSas() : await this.$tools.getSchoolSas()
|
|
|
+ //初始化Blob
|
|
|
+ let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, this.evaluationInfo.type)
|
|
|
+ try {
|
|
|
+ let promiseArr = []
|
|
|
+ let blobFile = null
|
|
|
+
|
|
|
+ console.log('试卷题目的ID集合', res.files)
|
|
|
+ console.log('试卷ITEM', paperItem)
|
|
|
+ // return
|
|
|
+ let privateSas = await this.$tools.getPrivateSas()
|
|
|
+ let privateBlob = new blobTool(privateSas.url, privateSas.name, privateSas.sas, 'private')
|
|
|
+ let schoolSas = await this.$tools.getSchoolSas()
|
|
|
+ let schoolBlob = new blobTool(schoolSas.url, schoolSas.name, schoolSas.sas, 'school')
|
|
|
+
|
|
|
+ // 放入试题json文件以及index.json文件
|
|
|
+ for (let i = 0; i < res.files.length; i++) {
|
|
|
+ promiseArr.push(new Promise(async (r, j) => {
|
|
|
+ // let result = await containerClient.upload(res.files[i], 'paper/' + paperItem.name, undefined, false)
|
|
|
+ // r(result)
|
|
|
+
|
|
|
+ let item = res.files[i]
|
|
|
+ if (item.scope == 'school') {
|
|
|
+ containerClient.copyFolder('paper/' + paperItem.name + '/', 'item/' + item.id, schoolBlob)
|
|
|
+ } else {
|
|
|
+ containerClient.copyFolder('paper/' + paperItem.name + '/', 'item/' + item.id, privateBlob)
|
|
|
+ }
|
|
|
+ r(200)
|
|
|
+ }))
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+ promiseArr.push(new Promise(async (r, j) => {
|
|
|
+ try {
|
|
|
+ blobFile = await containerClient.upload(paperFile, 'paper/' + paperItem.name, undefined, false)
|
|
|
+ console.log('上传到试卷目录下', blobFile)
|
|
|
+ r(blobFile)
|
|
|
+ } catch (e) {
|
|
|
+ j(e)
|
|
|
+ this.$Message.error(e.spaceError)
|
|
|
+ this.isLoading = false
|
|
|
+ }
|
|
|
+
|
|
|
+ }))
|
|
|
+ // 进行试卷文件上传Blob
|
|
|
+ Promise.all(promiseArr).then(async result => {
|
|
|
+ console.log('试卷上传文件的promise结果', result)
|
|
|
+ if (blobFile.blob) {
|
|
|
+ // 保存到COSMOS是不含base64图片编码的数据 避免数据量过大
|
|
|
+ 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.isEditPaper ? '编辑成功' : '保存成功')
|
|
|
+ this.isLoading = false
|
|
|
+ this.$router.push({
|
|
|
+ name: this.evaluationInfo.type === 'private' ? 'personalBank' : 'schoolBank',
|
|
|
+ params: {
|
|
|
+ tabName: 'paper'
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ this.$Message.error('保存试卷失败')
|
|
|
+ this.isLoading = false
|
|
|
+ }
|
|
|
+ },
|
|
|
+ err => {
|
|
|
+ this.$Message.error('保存试卷失败')
|
|
|
+ this.isLoading = false
|
|
|
+ }
|
|
|
+ )
|
|
|
+ }
|
|
|
+ })
|
|
|
+ } catch (e) {
|
|
|
+ this.$Message.error('上传失败!')
|
|
|
+ console.log(e)
|
|
|
+ this.isLoading = false
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ },
|
|
|
+ computed: {
|
|
|
+
|
|
|
+ },
|
|
|
+ created() {
|
|
|
+ //判断创建个人还是校本评测
|
|
|
+ if (this.$route.name == 'createSchoolEva') {
|
|
|
+ this.routerScope = 'school'
|
|
|
+ } else {
|
|
|
+ this.routerScope = 'private'
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+<style lang="less">
|
|
|
+@import "./ImportCreate.less";
|
|
|
+</style>
|
|
|
+<style>
|
|
|
+</style>
|