Bladeren bron

处理创建评测学段问题

liqk 4 jaren geleden
bovenliggende
commit
cc9de2499d

+ 1 - 0
TEAMModelOS/ClientApp/src/view/evaluation/index/CreatePaper.vue

@@ -214,6 +214,7 @@
 				let importList = await this.refreshImportItems(list)
 				this.evaluationInfo.item = importList
 				this.activeTab = 'preview'
+				console.log(this.evaluationInfo)
 				if (this.errorList.length) {
 					this.$EventBus.$emit('importFinish', this.errorList)
 				}

+ 7 - 5
TEAMModelOS/ClientApp/src/view/learnactivity/CreatePrivEva.vue

@@ -61,11 +61,9 @@
                         </TabPane>
                         <TabPane label="试卷预览" name="preview" :index="2" tab="createTest">
                             <TeacherPreview :testPaper="evaluationInfo.paperInfo[0]"></TeacherPreview>
-                            <!-- <TestPaper :paper="evaluationInfo.paperInfo[0]" isExamPaper></TestPaper> -->
                         </TabPane>
-
                         <TabPane label="导入说明" name="import" v-if="createType == 'import'" :index="4" tab="createTest">
-                            <BaseImport @importedQuestions="getImportQuestions" @goToPreview="goToPreview"></BaseImport>
+                            <ImportCreate></ImportCreate>
                         </TabPane>
                         <TabPane label="作答预览" name="student" :index="6" tab="createTest">
                             <StudentPreview></StudentPreview>
@@ -80,23 +78,26 @@
                 </div>
             </div>
         </div>
+        
     </div>
 </template>
 <script>
 import BlobTool from '@/utils/blobTool.js'
 import ManualPaper from './ManualPaper.vue'
-import BaseImport from '@/view/evaluation/components/BaseImport.vue'
+import ImportCreate from './ImportCreate.vue'
 import TeacherPreview from './TeacherPreview.vue'
 import StudentPreview from './StudentPreview.vue'
+
 export default {
     components: {
         TeacherPreview,
         StudentPreview,
-        BaseImport,
+        ImportCreate,
         ManualPaper
     },
     data() {
         return {
+            
             props: {
                 multiple: true,
             },
@@ -200,6 +201,7 @@ export default {
         }
     },
     methods: {
+        
         //重置课程类型
         resetCourse() {
             this.evaluationInfo.targets = []

+ 11 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/ImportCreate.less

@@ -0,0 +1,11 @@
+@main-bgColor: rgb(40,40,40);
+@borderColor: #424242;
+@primary-textColor: #fff; 
+@second-textColor: #a5a5a5; 
+@primary-fontSize: 14px;
+@second-fontSize: 16px;
+
+.import-create-wrap {
+    width: 100%;
+    height: 100%;
+}

+ 380 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/ImportCreate.vue

@@ -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>

+ 3 - 1
TEAMModelOS/ClientApp/src/view/learnactivity/ManualPaper.vue

@@ -252,8 +252,10 @@ export default {
         periodId: {
             handler() {
                 this.searchPeriod = this.periodId
+                console.log('---',this.searchPeriod)
                 this.getPaperList()
-            }
+            },
+            immediate:true
         },
         subjectId: {
             handler() {

+ 1 - 1
TEAMModelOS/ClientApp/src/view/learnactivity/Scoring.less

@@ -49,7 +49,7 @@
 }
 
 .ev-target-box {
-    margin-top: 20px;
+    // margin-top: 20px;
     width: ~"calc(100% - 10px)";
     color: #ffffff;
     background: rgba(50, 50, 50, 1);

+ 3 - 3
TEAMModelOS/ClientApp/src/view/learnactivity/Scoring.vue

@@ -4,11 +4,11 @@
             <SimpleAnalysis :examInfo="examInfo" v-show="!showTest"></SimpleAnalysis>
             <div class="ev-target-box dark-iview-select">
                 <span class="filter-label" v-show="examInfo.scope == 'school'">学科:</span>
-                <Select filterable v-model="chooseSubject" class="filter-select" size="small" @on-change="getCurPaper" v-show="examInfo.scope == 'school'">
+                <Select filterable v-model="chooseSubject" class="filter-select" size="small" @on-change="getCurPaper" v-show="examInfo.scope == 'school'" transfer>
                     <Option v-for="(item,index) in examInfo.subjects" :value="item.id" :key="index">{{ item.name }}</Option>
                 </Select>
                 <span class="filter-label" v-show="examInfo.scope == 'school'">年级:</span>
-                <Select filterable v-model="chooseGrade" class="filter-select" size="small" v-show="examInfo.scope == 'school'" style="margin-right:5px">
+                <Select filterable v-model="chooseGrade" class="filter-select" size="small" v-show="examInfo.scope == 'school'" style="margin-right:5px" transfer>
                     <Option v-for="(item,index) in examInfo.grades" :value="item.id" :key="index">{{ item.name }}</Option>
                 </Select>
                 <span>班级:</span>
@@ -16,7 +16,7 @@
                     <Option v-for="(item,index) in classList" :value="item.id" :key="index">{{ item.name }}</Option>
                 </Select>
                 <span style="margin-left:5px" v-show="showTest">学生:</span>
-                <Select filterable v-model="chooseStudent.id" label-in-value class="filter-select" style="width:140px;" size="small" clearable @on-change="setStuInfo" v-show="showTest">
+                <Select filterable v-model="chooseStudent.id" label-in-value class="filter-select" style="width:140px;" size="small" clearable @on-change="setStuInfo" v-show="showTest" transfer>
                     <Option v-for="(item,index) in students" :value="item.id" :key="index">
                         <span class="select-status-tag" :style="{'background':item.status == 1 ? '#ed4014' : item.status == 2 ? '#ff9900' : '#19be6b'}"></span>
                         {{ item.name }}