Bladeren bron

Merge branch 'develop' of http://52.130.252.100:10000/TEAMMODEL/TEAMModelOS into develop

CrazyIter_Bin 1 jaar geleden
bovenliggende
commit
45dfe17ffc

+ 0 - 1
TEAMModelOS/ClientApp/package.json

@@ -51,7 +51,6 @@
     "lodash": "^4.17.21",
     "node-fetch": "^2.6.1",
     "oidc-client": "^1.9.1",
-    "pdfjs-dist": "^4.1.392",
     "primeicons": "^6.0.1",
     "primevue": "^2.10.1",
     "qrcodejs2": "0.0.2",

+ 29 - 32
TEAMModelOS/ClientApp/public/lang/en-US.js

@@ -1089,7 +1089,7 @@ const LANG_EN_US = {
         copyUrl: 'Copy Link',
         joinMessage1: "Allowed to join the course",
         joinMessage2: "Prohibited to join the course",
-        defaultDesc: 'Personal Course on the IES TEAM Model Cloud',
+        defaultDesc:'Personal Course on the IES TEAM Model Cloud',
         inviteInfo1: 'Invite to join the IES Teacher Personal Course on the TEAM Model Cloud',
         inviteInfo2: 'Course Name:',
         inviteInfo3: 'Course List:',
@@ -1585,37 +1585,34 @@ const LANG_EN_US = {
     // 试题试卷
     evaluation: {
         quickPaper: {
-            title: 'Rapid Exam Paper Creation',
-            mode1: 'Switch to custom arrangement mode',
-            mode2: 'Switch to question type arrangement mode',
-            info: 'Exam paper information',
-            tip1: 'Enter exam paper name',
-            attachments: 'Attachments',
-            upload: 'Upload attachment',
+            title: 'Quick Design',
+            mode1: 'Switch to flexible quick design',
+            mode2: 'Switch to quick design by question type',
+            info: 'Exam File Name',
+            tip1: 'Please enter the name',
+            attachments: 'Attachment',
+            upload: 'Upload Attachment',
             empty: 'No attachment yet',
             preview: 'Preview',
             del: 'Delete',
             setItem: 'Set Question',
-            count: 'Number of questions',
-            itemOptions: 'Number of options',
-            setAns: 'Set answer',
-            number: 'Numeric',
+            count: 'No.',
+            itemOptions: 'Option No.',
+            setAns: 'Set Answer',
+            number: 'Number',
             code: 'Alphabet',
-            inputMode: 'Option input mode',
-            tip2: 'Enter the answers to the multiple choice questions, please set them in the order of the questions',
-            tip3: 'Enter the answer to the multiple answer question',
-            tip4: 'Enter the answer to the cloze question',
-            tip5: 'There are no questions yet, click the button above to quickly add a question',
-            options: 'Number of options',
-            ansType: 'Answer type',
-            ans: 'Reference answer',
+            inputMode: 'Option Display',
+            tip2: 'Enter the answers for the single answer questions, and set them in the order of the questions.',
+            tip3: 'Enter the answer for the multiple answers question',
+            tip4: 'Enter the answer for the cloze question',
+            tip5: 'There are no questions at the moment, click the button above to add questions.',
+            options: 'Option No.',
+            ansType: 'Answer Type',
+            ans: 'Answer',
             tip6: 'Enter the answer',
-            tip7: 'Switching mode will clear all question data. Do you confirm to switch? ',
-            tip8: 'Up to 20 questions',
-            tip9: 'Enter the text prompt for the audio question',
-            tip10: '题目数量不能为0',
-            tip11: '单选题答案数与题目数不一致,请检查后重试!',
-            tip12: '多选题答案数与题目数不一致,请检查后重试!',
+            tip7: 'Switching will clear the current question data, do you confirm to switch?',
+            tip8: 'Maximum 20 questions!',
+            tip9: 'Enter the speaking prompt',
         },
         cpTip1: 'Pick from the question bank',
         cpTip2: 'Pick from the exam paper',
@@ -1742,12 +1739,12 @@ const LANG_EN_US = {
         cancelSuc: 'Cancel successfully',
         addSuc: 'Add successfully',
         newExercise: {
-            answerType: {
-                types: 'Answer Type',
-                text: 'Text',
-                textImage: 'Draw Notes',
-                image: 'Picture',
-                file: 'File',
+            answerType:{
+                types:'Answer Type',
+                text:'Text',
+                textImage:'Draw Notes',
+                image:'Picture',
+                file:'File',
                 audio: 'Audio',
                 autoScore: 'Automatic Rating',
                 answerLang: 'Language',

+ 0 - 3
TEAMModelOS/ClientApp/public/lang/zh-CN.js

@@ -1612,9 +1612,6 @@ const LANG_ZH_CN = {
             tip7:'切换模式将会清空当前试题数据,是否确认切换?',
             tip8:'最多添加20道试题',
             tip9:'输入音频题正确答案',
-            tip10:'题目数量不能为0',
-            tip11:'单选题答案数与题目数不一致,请检查后重试!',
-            tip12:'多选题答案数与题目数不一致,请检查后重试!',
         },
         cpTip1: '从题库挑选',
         cpTip2: '从试卷挑选',

+ 0 - 3
TEAMModelOS/ClientApp/public/lang/zh-TW.js

@@ -1615,9 +1615,6 @@ const LANG_ZH_TW = {
             tip7: '切換模式將會清除目前試題資料,是否確認切換? ',
             tip8: '最多增加20個試題',
             tip9: '輸入錄音題文字提示',
-            tip10: '题目数量不能为0',
-            tip11: '单选题答案数与题目数不一致,请检查后重试!',
-            tip12: '多选题答案数与题目数不一致,请检查后重试!',
         },
         cpTip1: '從題庫挑選',
         cpTip2: '從試卷挑選',

+ 4 - 1
TEAMModelOS/ClientApp/src/api/newEvaluation.js

@@ -51,6 +51,9 @@ export default {
 	checkPaperName: function(data) {
         return post('/paper/check-paper-name', data)
     },
-	
 
+    // 获取多分题库
+    dfQuesList: function(data) {
+        return post('/moofen/question', data)
+    },
 }

+ 18 - 0
TEAMModelOS/ClientApp/src/router/routes.js

@@ -502,6 +502,24 @@ export const routes = [{
                 activeName: 'schoolBank'
             },
         },
+        {
+            path: 'schoolDf',
+            name: 'schoolDf',
+            // component: () => import('@/view/answersheet/index.vue'),
+            component: () => import('@/view/evaluation/index/DfPage.vue'),
+            meta: {
+                activeName: 'schoolBank'
+            },
+        },
+        {
+            path: 'privateDf',
+            name: 'privateDf',
+            // component: () => import('@/view/answersheet/index.vue'),
+            component: () => import('@/view/evaluation/index/DfPage.vue'),
+            meta: {
+                activeName: 'personalBank'
+            },
+        },
         {
             path: 'wxtPage',
             name: 'wxtPage',

+ 134 - 0
TEAMModelOS/ClientApp/src/view/evaluation/index/DfPage.less

@@ -0,0 +1,134 @@
+@main-bgColor: rgb(40, 40, 40); //主背景颜色
+@borderColor: var(--border-color);
+@primary-textColor: var(--primary-text-color); //文本主颜色
+@second-textColor: #a5a5a5; //文本副级颜色
+@primary-fontSize: 14px;
+@second-fontSize: 16px;
+
+.df-container {
+    width: 100%;
+    height: 100%;
+    position: relative;
+
+    .new-exercise-header {
+        width: 100%;
+        height: 45px;
+        border-bottom: 1px solid @borderColor;
+        margin-bottom: 15px;
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+
+        .ev-title {
+            height: 45px;
+            line-height: 45px;
+            color: @primary-textColor;
+            padding-left: 20px;
+            font-size: 16px;
+            display: inline-flex;
+        }
+
+        .btn-save {
+            margin-top: 6px;
+            margin-right: 20px;
+            height: 28px;
+            line-height: 28px;
+        }
+    }
+
+    .create-body {
+        width: 98%;
+        margin: 0px auto;
+        height: ~"calc(100% - 45px)";
+        // display: flex;
+
+        .ivu-page {
+            display: flex;
+            flex-direction: row;
+            justify-content: center;
+            margin: 20px 0;
+        }
+
+        .filter-wrap {
+            margin-bottom: 15px;
+        }
+
+        .content-wrap {
+            position: relative;
+            width: 100%;
+            height: auto;
+            display: flex;
+            flex-direction: column;
+
+            .exercise-item {
+                position: relative;
+                width: 100%;
+                height: auto;
+                padding: 10px 20px 10px 20px;
+                margin-bottom: 10px;
+                font-size: 14px;
+                background: #fff;
+                border: 2px solid transparent;
+                cursor: pointer;
+
+                &:hover {
+                    .item-tools-bind {
+                        display: unset;
+                    }
+                }
+
+                .item-tools-wrap {
+                    position: absolute;
+                    right: -2px;
+                    top: -32px;
+                    width: auto;
+                    height: 30px;
+                    margin: 0;
+                    padding: 0;
+                    background: #01b4ef;
+                    display: none;
+                }
+
+                .item-tools-t {
+                    height: 100%;
+                    padding: 0 15px;
+                    float: left;
+                    color: white;
+                    cursor: pointer;
+                    font-size: 14px;
+                }
+            }
+        }
+
+        .no-data-text {
+            width: 100%;
+            padding: 30px;
+            background: #fff;
+            display: flex;
+            flex-direction: column;
+            justify-content: center;
+            align-items: center;
+            margin-top: 10px;
+            font-size: 16px;
+        }
+    }
+
+    .question-shopping-car {
+        position: fixed;
+        right: 50px;
+        bottom: 27px;
+        z-index: 9999;
+
+        .ivu-poptip-popper {
+            width: 360px !important;
+        }
+    }
+
+    /*横向垂直水平居中*/
+    .flex-row-center {
+        display: flex;
+        flex-direction: row;
+        justify-content: center;
+        align-items: center;
+    }
+}

+ 822 - 0
TEAMModelOS/ClientApp/src/view/evaluation/index/DfPage.vue

@@ -0,0 +1,822 @@
+<template>
+    <div class="df-container">
+        <Loading :top="200" v-show="isLoading" hideMask type="1"></Loading>
+        <Poptip padding="0px 0px" offset="10" placement="top-end" width="300" trigger="hover" :class="shoppingCarClass">
+            <Badge type="primary" :count="selectedArr.length" show-zero :offset="[-3,-3]" @mouseenter.native="changeActive($event)" @mouseleave.native="removeActive($event)">
+                <Icon custom="iconfont icon-sp-car" color="#05C19C" size="50" />
+            </Badge>
+            <div slot="content">
+                <div class="shopping-car-detail">
+                    <p class="shopping-car-detail-title">{{$t('evaluation.createPaper.total')}}<span style="margin:0px 5px;">{{selectedArr.length}}</span>{{$t('evaluation.createPaper.nums')}}</p>
+                    <div class="shopping-car-detail-item">
+                        <span class="question-type">{{$t('evaluation.single')}}:</span>
+                        <Progress stroke-color="#6bdfc3" :percent="getPercent('single')" :stroke-width="15" style="width:165px;vertical-align:top;padding-top:2px;" hide-info />
+                        <span class="question-num">{{quesTypeList.single}}{{$t('evaluation.createPaper.spc')}}</span>
+                    </div>
+                    <div class="shopping-car-detail-item">
+                        <span class="question-type">{{$t('evaluation.multiple')}}:</span>
+                        <Progress stroke-color="#6bdfc3" :percent="getPercent('multiple')" :stroke-width="15" style="width:165px;vertical-align:top;padding-top:2px;" hide-info />
+                        <span class="question-num">{{quesTypeList.multiple}}{{$t('evaluation.createPaper.spc')}}</span>
+                    </div>
+                    <!-- <div class="shopping-car-detail-item">
+                        <span class="question-type">{{$t('evaluation.judge')}}:</span>
+                        <Progress stroke-color="#6bdfc3" :percent="getPercent('judge')" :stroke-width="15" style="width:165px;vertical-align:top;padding-top:2px;" hide-info />
+                        <span class="question-num">{{quesTypeList.judge}}{{$t('evaluation.createPaper.spc')}}</span>
+                    </div> -->
+                    <div class="shopping-car-detail-item">
+                        <span class="question-type">{{$t('evaluation.complete')}}:</span>
+                        <Progress stroke-color="#6bdfc3" :percent="getPercent('complete')" :stroke-width="15" style="width:165px;vertical-align:top;padding-top:2px;" hide-info />
+                        <span class="question-num">{{quesTypeList.complete}}{{$t('evaluation.createPaper.spc')}}</span>
+                    </div>
+                    <div class="shopping-car-detail-item">
+                        <span class="question-type">{{$t('evaluation.subjective')}}:</span>
+                        <Progress stroke-color="#6bdfc3" :percent="getPercent('subjective')" :stroke-width="15" style="width:165px;vertical-align:top;padding-top:2px;" hide-info />
+                        <span class="question-num">{{quesTypeList.subjective}}{{$t('evaluation.createPaper.spc')}}</span>
+                    </div>
+                    <div class="shopping-car-detail-item">
+                        <span class="question-type">{{$t('evaluation.compose')}}:</span>
+                        <Progress stroke-color="#6bdfc3" :percent="getPercent('compose')" :stroke-width="15" style="width:165px;vertical-align:top;padding-top:2px;" hide-info />
+                        <span class="question-num">{{quesTypeList.compose}}{{$t('evaluation.createPaper.spc')}}</span>
+                    </div>
+                    <p class="shopping-car-detail-bottom" @click="goToPreview">{{$t('evaluation.createPaper.goDetails')}}</p>
+                </div>
+            </div>
+        </Poptip>
+        <div class="new-exercise-header">
+            <span class="ev-title">
+                多分题库
+            </span>
+            <div>
+                <Button @click="backToBank" class="btn-back-to-bank" icon="md-arrow-round-back" style="margin-left: 10px">{{ $t('evaluation.newExercise.backToBank')}}</Button>
+            </div>
+        </div>
+        <div class="create-body">
+            <div class="filter-wrap">
+                <div class="filter-item">
+                    <span class="filter-title">{{$t('evaluation.filter.grade')}}:</span>
+                    <RadioGroup v-model="filterGrade" type="button" @on-change="getDfList()">
+                        <Radio v-for="(item, index) in gradeList" :key="index" :label="index + 1" style="margin-bottom: 5px;">{{ item }}</Radio>
+                    </RadioGroup>
+                </div>
+                <div class="filter-item">
+                    <span class="filter-title">{{$t('evaluation.filter.subject')}}:</span>
+                    <RadioGroup v-model="filterSubject" type="button" @on-change="getDfList()">
+                        <Radio v-for="(item, index) in subjectList" :key="index" :label="item.id" style="margin-bottom: 5px;">{{ item.name }}</Radio>
+                    </RadioGroup>
+                </div>
+                <div class="filter-item">
+                    <span class="filter-title">{{$t('evaluation.filter.type')}}:</span>
+                    <RadioGroup v-model="filterType" type="button" @on-change="getDfList()">
+                        <Radio label="all" style="margin-bottom: 5px;">全部</Radio>
+                        <Radio v-for="(item, index) in typeList" :key="index" :label="item.id" style="margin-bottom: 5px;">{{ item.name }}</Radio>
+                    </RadioGroup>
+                </div>
+                <div class="filter-item">
+                    <span class="filter-title">{{$t('evaluation.filter.diff')}}:</span>
+                    <RadioGroup v-model="filterDiff" type="button" @on-change="getDfList()">
+                        <Radio label="all" style="margin-bottom: 5px;">全部</Radio>
+                        <Radio v-for="(item, index) in exersicesDiff" :key="index" :label="index + 1" style="margin-bottom: 5px;">{{ item }}</Radio>
+                    </RadioGroup>
+                </div>
+            </div>
+            <div class="bank-action-bar">
+                <div class="action-tools">
+                    <div class="action-tool">
+                        <Input v-model="searchVal" placeholder="输入关键词搜索试题..." style="width: 300px;" clearable search @on-search="getDfList()"></Input>
+                    </div>
+                    <div class="action-tool">
+                        <Checkbox v-model="isAllOpen" @on-change="onHandleToggle">{{ $t('evaluation.exerciseList.showAllAnswer') }}</Checkbox>
+                    </div>
+                </div>
+                <div class="action-tools" style="display:flex;align-items: center;">
+                    <Checkbox v-model="isSelectAll" @on-change="onSelectAll" v-if="($access.can('admin.*||exercise-upd'))">{{ $t('evaluation.choosePageItems') }}</Checkbox>
+                    <span style="margin-left:20px">
+                        {{ $t('evaluation.exerciseList.totalTip1') }}
+                        <span style="font-size: 18px;color: #ff0206;margin: 0 10px;font-weight: bold;">{{ totalNum }}</span>
+                        {{ $t('evaluation.exerciseList.unit') }}
+                    </span>
+                </div>
+            </div>
+            <div v-if="!exerciseList.length" class="no-data-text">
+                <img src="@/assets/icon/no_data_evaluation.png" width="120" />
+                <span style="margin-top: 15px; color: #808080">{{$t('evaluation.noData')}}</span>
+            </div>
+            <div v-else class="content-wrap" ref="mathJaxContainer">
+                <div class="exercise-item" v-for="(item, index) of exerciseList" :key="index" @click="onQuestionToggle(index, item.id, $event)">
+                    <!-- 题干部分 -->
+                    <div class="item-question">
+                        <div>
+                            <div class="item-question-order">{{ pageSize * (pageNum - 1) + index + 1 }} :</div>
+                            <div class="item-question-text" v-html="item.question"></div>
+                        </div>
+                        <span class="item-btn-toggle" style="justify-content: flex-end;">
+                            <Icon v-if="item.type !== 'compose'" :type="collapseList.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>
+                            <div class="item-option-text" v-html="option.value"></div>
+                        </div>
+                    </div>
+                    <transition name="slide" v-if="item.type !== 'compose'">
+                        <div v-show="collapseList.indexOf(exerciseList.indexOf(item)) > -1" class="toggle-area">
+                            <div>
+                                <!-- 答案展示部分 -->
+                                <div class="item-explain">
+                                    <span class="explain-title">【{{$t('evaluation.answer')}}】</span>
+                                    <div class="item-explain-details">
+                                        <!-- 问答题答案 -->
+                                        <div v-if="item.type === 'subjective' || item.type === 'complete' || item.type === 'connector' || item.type === 'correct' ">
+                                            <span v-for="(answer, index) in item.answer" :key="index" v-html="item.answer.length ? answer : $t('evaluation.noAnswer')"></span>
+                                        </div>
+                                        <!-- 判断题答案 -->
+                                        <div v-else-if="item.type === 'judge'">
+                                            <span>{{ item.answer.length ? (item.answer[0] === 'A' ? $t('evaluation.isTrue') : $t('evaluation.isFalse')) : $t('utils.noData') }}</span>
+                                        </div>
+                                        <!-- 其余题型答案 -->
+                                        <div v-else>
+                                            <span :class="[ item.type === 'complete' ? 'item-answer-item' : '']" v-for="(answer, index) in item.answer" :key="index">{{ answer }}</span>
+                                        </div>
+                                    </div>
+                                </div>
+                                <!-- 解析部分 -->
+                                <div class="item-explain">
+                                    <span class="explain-title">【{{$t('evaluation.explain')}}】</span>
+                                    <div class="item-explain-details">
+                                        <span v-html="item.explain ||$t('utils.noData')"></span>
+                                    </div>
+                                </div>
+                                <!-- 知识点部分 -->
+                                <div class="item-explain">
+                                    <span class="explain-title">【{{$t('evaluation.knowledgePoints')}}】</span>
+                                    <div class="item-explain-details">
+                                        <span v-if="!item.knowledge || !item.knowledge.length">{{ $t('utils.noData') }}</span>
+                                        <div v-else>
+                                            <span v-for="(point, index) in item.knowledge" class="item-point-tag" :key="index">
+                                                {{ point }}
+                                            </span>
+                                        </div>
+                                    </div>
+                                </div>
+                                <!-- 补救资源部分 -->
+                                <div class="item-explain" v-show="isShowAnswer">
+                                    <span class="explain-title">【{{ $t('evaluation.newExercise.repair') }}】</span>
+                                    <div class="item-explain-details">
+                                        <div v-if="item.repair && item.repair.length" style="display: flex; flex-wrap: wrap;">
+                                            <div class="repair-item" v-for="(link, index) in item.repair" :key="index">
+                                                <img :src="$tools.getFileThum(link.type, link.name)" width="20" />
+                                                <span class="repair-item-link" @click.stop="onRepairLinkClick(link)">{{ link.name }}</span>
+                                            </div>
+                                        </div>
+                                        <span v-else>{{ $t('utils.noData') }}</span>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </transition>
+                    <!-- 底部题目操作栏 -->
+                    <div class="item-tools">
+                        <span class="item-tools-info">{{$t('evaluation.filter.grade')}}:{{ gradeList[parseInt(item.grade) - 1] }}</span>
+                        <span class="item-tools-info">{{$t('evaluation.filter.subject')}}:{{ item.subject }}</span>
+                        <span class="item-tools-info">{{$t('evaluation.filter.type')}}:{{ exersicesType[item.type] }}</span>
+                        <span class="item-tools-info">{{$t('evaluation.filter.diff')}}:{{ exersicesDiff[item.level - 1] }}</span>
+
+                        <div class="buttons" style="float:right;display:flex;flex-direction:row-reverse;align-items:center">
+                            <Button type="info" :style="{backgroundColor: selectedArr.map((i) => i.id).indexOf(item.id) > -1 ? '#bbbbbb' : '#2db7f5'}" @click.stop="handleChoose(item)">
+                                {{ids.indexOf(item.id) > -1 ? $t('evaluation.removeItem') : $t('evaluation.selectItem')}}
+                            </Button>
+                            <!-- <Button type="text" @click.stop="handleDelete(item)" v-if="($access.can('admin.*||exercise-upd') ||  (filterOrigin !== schoolCode)) && !isComponent" icon="md-trash">{{$t('evaluation.deleteItem')}}</Button> -->
+                            <!-- <Button type="text" @click.stop="handleEdit(item)" v-if="($access.can('admin.*||exercise-upd') ||  (filterOrigin !== schoolCode)) && !isComponent" icon="md-create">{{$t('evaluation.editItem')}}</Button> -->
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <!-- 底部分页区域 -->
+            <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">
+                <Radio label="quesBank">题库</Radio>
+                <Radio label="paper">试卷</Radio>
+            </RadioGroup>
+            <div v-if="!selShowList.length">未选择题目</div>
+            <div v-else class="content-wrap" style="height: 95%;">
+                <vuescroll>
+                    <div class="list-view" v-for="(quesItem, quesIndex) in selShowList" :key="quesIndex">
+                        <p v-show="saveType === 'paper' && 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="item-tools-wrap" v-show="saveType === '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)">
+                                    <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)">
+                                    <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>
+                                <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>
+                                    <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>
+                            <transition name="slide" v-if="item.type !== 'compose'">
+                                <div v-show="selcollaList.indexOf(selectedArr.indexOf(item)) > -1" class="toggle-area">
+                                    <div>
+                                        <!-- 答案展示部分 -->
+                                        <div class="item-explain">
+                                            <span class="explain-title">【{{$t('evaluation.answer')}}】</span>
+                                            <div class="item-explain-details">
+                                                <!-- 问答题答案 -->
+                                                <div v-if="item.type === 'subjective' || item.type === 'complete' || item.type === 'connector' || item.type === 'correct' ">
+                                                    <span v-for="(answer, index) in item.answer" :key="index" v-html="item.answer.length ? answer : $t('evaluation.noAnswer')"></span>
+                                                </div>
+                                                <!-- 判断题答案 -->
+                                                <div v-else-if="item.type === 'judge'">
+                                                    <span>{{ item.answer.length ? (item.answer[0] === 'A' ? $t('evaluation.isTrue') : $t('evaluation.isFalse')) : $t('utils.noData') }}</span>
+                                                </div>
+                                                <!-- 其余题型答案 -->
+                                                <div v-else>
+                                                    <span :class="[ item.type === 'complete' ? 'item-answer-item' : '']" v-for="(answer, index) in item.answer" :key="index">{{ answer }}</span>
+                                                </div>
+                                            </div>
+                                        </div>
+                                        <!-- 解析部分 -->
+                                        <div class="item-explain">
+                                            <span class="explain-title">【{{$t('evaluation.explain')}}】</span>
+                                            <div class="item-explain-details">
+                                                <span v-html="item.explain ||$t('utils.noData')"></span>
+                                            </div>
+                                        </div>
+                                        <!-- 知识点部分 -->
+                                        <div class="item-explain">
+                                            <span class="explain-title">【{{$t('evaluation.knowledgePoints')}}】</span>
+                                            <div class="item-explain-details">
+                                                <span v-if="!item.knowledge || !item.knowledge.length">{{ $t('utils.noData') }}</span>
+                                                <div v-else>
+                                                    <span v-for="(point, index) in item.knowledge" class="item-point-tag" :key="index">
+                                                        {{ point }}
+                                                    </span>
+                                                </div>
+                                            </div>
+                                        </div>
+                                        <!-- 补救资源部分 -->
+                                        <div class="item-explain" v-show="isShowAnswer">
+                                            <span class="explain-title">【{{ $t('evaluation.newExercise.repair') }}】</span>
+                                            <div class="item-explain-details">
+                                                <div v-if="item.repair && item.repair.length" style="display: flex; flex-wrap: wrap;">
+                                                    <div class="repair-item" v-for="(link, index) in item.repair" :key="index">
+                                                        <img :src="$tools.getFileThum(link.type, link.name)" width="20" />
+                                                        <span class="repair-item-link" @click.stop="onRepairLinkClick(link)">{{ link.name }}</span>
+                                                    </div>
+                                                </div>
+                                                <span v-else>{{ $t('utils.noData') }}</span>
+                                            </div>
+                                        </div>
+                                    </div>
+                                </div>
+                            </transition>
+                        </div>
+                    </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>
+        </Drawer>
+    </div>
+</template>
+
+<script>
+import blobTool from '@/utils/blobTool.js'
+import ExerciseList from '@/components/evaluation/ExerciseList.vue'
+export default {
+    components: {
+        ExerciseList
+    },
+    data() {
+        return {
+            isLoading: false,
+            gradeList: ['一年级', '二年级', '三年级', '四年级', '五年级', '六年级', '七年级', '八年级', '九年级', '十年级', '十一年级', '十二年级'],
+            subjectList: [
+                {id: '语文', name: '语文'},
+                {id: '数学', name: '数学'},
+                {id: '英语', name: '英语'},
+                {id: '物理', name: '物理'},
+                {id: '化学', name: '化学'},
+                {id: '地理', name: '地理'},
+                {id: '历史', name: '历史'},
+                {id: '生物', name: '生物'},
+                {id: '政治', name: '政治'},
+            ],
+            typeList: [
+                {id: 'C', name: '选择'},
+                {id: 'F', name: '填空'},
+                {id: 'Q', name: '问答'},
+                {id: 'W', name: '写作'},
+                {id: 'S', name: '综合'},
+            ],
+            exersicesDiff: this.$GLOBAL.EXERCISE_DIFFS(),
+            exersicesType: this.$GLOBAL.EXERCISE_TYPES(),
+            exersicesField: this.$GLOBAL.EXERCISE_LEVELS(),
+            filterGrade: 10,
+            filterSubject: '物理',
+            filterType: 'all',
+            filterDiff: 'all',
+            searchVal: '',
+            totalNum: 0,
+            pageSize: 5,
+            pageNum: 1,
+            exerciseList: [],
+            collapseList: [],
+            selectedArr: [],
+            selcollaList: [],
+            orderList: [],
+            groupList: [],
+            selShowList: [],
+            isSelectAll: false,
+            isShowAnswer: true,
+            isAllOpen: false,
+            showQues: false,
+            saveType: 'quesBank',
+            shoppingCarClass: 'question-shopping-car',
+            quesTypeList: {
+                single: 0,
+                multiple: 0,
+                judge: 0,
+                complete: 0,
+                subjective: 0,
+                compose: 0
+            },
+            scoreStep: 0.5,
+            surPlusScore: 0,
+            needSaveCosmosArr: [],
+        }
+    },
+    created() {
+        this.getDfList()
+    },
+    computed: {
+        ids() {
+            return this.selectedArr.map(i => i.id)
+        },
+        getPercent(type) {
+            return type => {
+                return this.selectedArr.length ? ((this.quesTypeList[type] * 100) / this.selectedArr.length) : 0
+            }
+        },
+        isSchool() {
+            return this.$route.name === 'schoolDf'
+        },
+    },
+    watch: {
+    },
+    methods: {
+        getDfList() {
+            this.isLoading = true
+            let param = {
+                subject: this.filterSubject,
+                grades: this.filterGrade,
+                // type: this.filterType,
+                // difficulty: this.filterDiff,
+                pageSize: this.pageSize,
+                currentPage: this.pageNum,
+            }
+            if(this.filterDiff != 'all') param.difficulty = this.filterDiff
+            if(this.filterType != 'all') param.type = this.filterType
+            if(this.searchVal) param.search = this.searchVal
+            this.$api.newEvaluation.dfQuesList(param).then(res => {
+                if(res.code === 200) {
+                    this.exerciseList = res.items
+                    this.totalNum = res.count
+                }
+            }).finally(() => {
+                this.isLoading = false
+            })
+        },
+        async handleChoose(item) {
+            if (this.ids.indexOf(item.id) === -1) {
+                this.selectedArr.push(item) //添加题目
+            } else {
+                for (let i = 0; i < this.selectedArr.length; i++) {
+                    if (this.selectedArr[i].id === item.id) {
+                        this.selectedArr.splice(i, 1) //移除
+                        break
+                    }
+                }
+            }
+            let groupResult = await this.$jsFn.groupBy(this.selectedArr, 'type')
+            for (let i = 0; i < groupResult.length; i++) {
+                this.quesTypeList[groupResult[i][0].type] = groupResult[i].length
+            }
+            this.isSelectAll = this.selectedArr.length === this.exerciseList.length
+            // this.$emit('chooseQuChange', this.selectedArr)
+        },
+        async pageChange(page) {
+            this.pageNum = page;
+            /* let start = this.pageSize * (page - 1);
+            let end = this.pageSize * page;
+            // 拿到当前页码需要展示的数据
+            let simpleList = this.originData.slice(start, end);
+            try {
+                // 执行试题换取完整JSON数据
+                this.exerciseList = await this.$evTools.getFullItem(simpleList);
+                // this.totalNum = this.exerciseList.length
+                this.pageScrollTo(0);
+                this.onHandleToggle(false)
+                this.$refs.childRef && this.$refs.childRef[0] && (this.$refs.childRef[0].collapseList = [])
+            } catch (e) {
+                this.$Message.error('Blob Error : ' + e)
+            } */
+            this.getDfList()
+        },
+        pageSizeChange(val) {
+            this.pageSize = val;
+            this.pageChange(1);
+        },
+        backToBank() {
+            this.$router.push({
+                name: "schoolBank",
+                params: {
+                    tabName: "exercise",
+                },
+            });
+        },
+        onQuestionToggle(index, id, e) {
+            console.log(e)
+            this.shoppingCarClass = 'question-shopping-car animated heartBeat'
+            setTimeout(() => {
+                this.shoppingCarClass = 'question-shopping-car'
+            }, 1000)
+            let curClassName = e.target.className
+            if (
+                curClassName === "item-tools" ||
+                curClassName === "richText-video" ||
+                curClassName === "richText-audio" ||
+                curClassName === "ivu-checkbox-input" ||
+                curClassName === "ivu-checkbox-wrapper ivu-checkbox-default"
+            )
+                return
+            e.stopPropagation()
+            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)
+                }
+            }
+        },
+        pageScrollTo(scrollDistance) {
+            this.$nextTick(() => {
+                let parentVm = this.$parent.$parent.$parent
+                if (parentVm.$refs["evScroll"]) {
+                    parentVm.$refs["evScroll"].scrollTo({y: scrollDistance}, 500, "easeInQuad")
+                }
+            })
+        },
+        changeActive(e) {
+            this.shoppingCarClass = 'question-shopping-car animated pulse'
+        },
+        removeActive() {
+            this.shoppingCarClass = 'question-shopping-car'
+        },
+        goToPreview() {
+            this.orderList = []
+            this.groupList = []
+            let that = this
+            let typesList = this._.cloneDeep(this.exersicesType)
+            for (const types in typesList) {
+                this._.mapKeys(this._.groupBy(this.selectedArr, 'type'), function (value, key) {
+                    if (key === types) { /* 按照题型排序,并且计算每种题型的总分 */
+                        that.groupList.push({
+                            type: key,
+                            list: value,
+                            score: 0
+                        })
+                    }
+                })
+            }
+            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.showQues = true
+            // this.$emit('goToPreview')
+            // 使用弹出框展示已选题目,再选择加入题库/组成试卷
+        },
+        async onSelectAll() {
+            this.selectedArr = this.isSelectAll ? this._.cloneDeep(this.exerciseList) : []
+            let groupResult = await this.$jsFn.groupBy(this.selectedArr, 'type')
+            if(groupResult.length) {
+                for (let i = 0; i < groupResult.length; i++) {
+                    this.quesTypeList[groupResult[i][0].type] = groupResult[i].length
+                }
+            } else {
+                for (const key in this.quesTypeList) {
+                    this.quesTypeList[key] = 0
+                }
+            }
+        },
+        /* 全部展开与全部折叠 */
+        onHandleToggle(isAllClose) {
+            if (!isAllClose) {
+                this.collapseList = [];
+            } else {
+                this.collapseList = [...this.exerciseList.keys()];
+            }
+        },
+        saveTypeChange(val) {
+            if(val === 'quesBank') {
+                this.selShowList = this._.cloneDeep(this.orderList)
+            } else {
+                this.selShowList = this._.cloneDeep(this.groupList)
+            }
+        },
+        getLatestTypeIndex(type) {
+            let arr = []
+            this.groupList.forEach(i => {
+                if (i.list.length) {
+                    arr.push(i.type)
+                }
+            })
+            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]
+            return arr
+        },
+        // 子题上移操作
+        handleMoveUp(arr, index) {
+            this.moveItems(arr, index, index - 1)
+        },
+        // 子题下移操作
+        handleMoveDown(arr, index) {
+            this.moveItems(arr, index, index + 1)
+        },
+        /**
+         * 删除试卷中的单个试题
+         * @param index
+         */
+        handleDelete(arr, item, index) {
+            this.$Modal.confirm({
+                title: this.$t('evaluation.newExercise.modalTip'),
+                content: this.$t('evaluation.exerciseList.confirmDelete'),
+                onOk: () => {
+                    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') {
+
+            } 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.$Spin.hide()
+                    this.$Message.success(this.$t('evaluation.paperList.saveSuc'))
+                    this.isLoading = false
+                    // 清空已选试题
+                    this.showQues = false
+                    this.selectedArr = []
+                    this.groupList = []
+                    this.orderList = []
+                    this.selShowList = []
+                }).catch(err => {
+                    console.log(err);
+                    this.$Message.error(this.$t('evaluation.paperList.saveFail'))
+                })
+            }
+        },
+        async saveQuesBank(list, isToItemBank) {
+            // 试题id 使用本身的id
+            let that = this
+            this.isLoading = true
+            // 获取初始化Blob需要的数据
+            let sasData = this.isSchool ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
+            let itemJsonFiles = []
+            let blobFiles = []
+            //初始化Blob
+            let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, this.isSchool ? 'school' : 'private')
+            return new Promise((resolve, reject) => {
+                let promiseArr = []
+                list.forEach(item => {
+                    if(item.children.length) {
+                        // 如果是没有保存Blob的综合题 则需要把题干和小题都进行保存操作
+                        let composeArr = [item, ...item.children]
+                        composeArr.forEach(composeItem => {
+                            promiseArr.push(new Promise(async (r, j) => {
+                                /* if (composeItem.children.length && composeItem.children[0].id) {
+                                    composeItem.children = composeItem.children.map(i => i.id)
+                                } */
+                                // 将当前的试题数据转化为BLOB内部的试题JSON格式
+                                let removeItem = await this.$editorTools.doRemoveMideaHost(composeItem)
+                                const itemJsonFile = await this.$evTools.createBlobItem(removeItem)
+                                const cosmosItem = await this.$evTools.createCosmosItem(composeItem)
+                                // 首先保存新题目的JSON文件到Blob 然后返回URL链接
+                                let file = new File([JSON.stringify(itemJsonFile)], composeItem.id + ".json")
+                                blobFiles.push(file)
+                                if (!isToItemBank) {
+                                    // 只保存试题
+                                    itemJsonFiles.push(composeItem)
+                                    r({
+                                        cosmosItem: composeItem,
+                                        blobItem: itemJsonFile
+                                    })
+                                } else {
+                                    // 保存试卷时,需要题目id
+                                    try {
+                                        // 等待上传blob的返回结果
+                                        let blobFile = await containerClient.upload(file, {
+                                            path: 'item/' + composeItem.id,
+                                            checkSize: false
+                                        })
+                                        if (blobFile.blob) {
+                                            // 保存试题JSON文件到试卷文件夹需要
+                                            itemJsonFiles.push(composeItem)
+                                            // 保存到COSMOS是不含base64图片编码的数据 避免数据量过大
+                                            cosmosItem.blob = blobFile.blob
+                                            // 保存当前试题到数据库
+                                            that.needSaveCosmosArr.push(cosmosItem)
+                                            r({
+                                                cosmosItem: cosmosItem,
+                                                blobItem: blobFile
+                                            })
+                                        } else {
+                                            j(500)
+                                        }
+                                    } catch (e) {
+                                        this.$Message.error(e.spaceError)
+                                        this.isLoading = false
+                                    }
+                                }
+                            }))
+                        })
+                    } else {
+                        // 如果没有blob字段 说明试题还没有保存到item目录下 则需要进行保存item文件夹后再保存到paper文件夹(导入试题情况)
+                        promiseArr.push(new Promise(async (r, j) => {
+                            // 将当前的试题数据转化为BLOB内部的试题JSON格式
+                            let removeItem = await this.$editorTools.doRemoveMideaHost(item)
+                            const itemJsonFile = await this.$evTools.createBlobItem(removeItem)
+                            const cosmosItem = await this.$evTools.createCosmosItem(item)
+                            // 首先保存新题目的JSON文件到Blob 然后返回URL链接
+                            let file = new File([JSON.stringify(itemJsonFile)], item.id + ".json")
+                            blobFiles.push(file)
+                            console.log(isToItemBank);
+                            try {
+                                if (!isToItemBank) {
+                                    r({
+                                        cosmosItem: item,
+                                        blobItem: itemJsonFile
+                                    })
+                                } else {
+                                    // 等待上传blob的返回结果
+                                    let blobFile = await containerClient.upload(file, {
+                                        path: 'item/' + item.id,
+                                        checkSize: false
+                                    })
+                                    if (blobFile.blob) {
+                                        // 保存试题JSON文件到试卷文件夹需要
+                                        // 保存到COSMOS是不含base64图片编码的数据 避免数据量过大
+                                        cosmosItem.blob = blobFile.blob
+                                        // 保存当前试题到数据库
+                                        that.needSaveCosmosArr.push(cosmosItem)
+                                        r({
+                                            cosmosItem: cosmosItem,
+                                            blobItem: blobFile
+                                        })
+                                    } else {
+                                        j(500)
+                                    }
+                                }
+                                itemJsonFiles.push(item)
+                            } catch (e) {
+                                this.$Message.error(e.spaceError)
+                                this.isLoading = false
+                            }
+                        }))
+                    }
+                })
+                Promise.all(promiseArr).then(async result => {
+                    // 如果是入库 则批量保存所有试题
+                    if (isToItemBank) {
+                        try {
+                            await this.$api.evaluation.upsertAll({
+                                option: 'insert',
+                                itemInfos: this.needSaveCosmosArr
+                            })
+                        } catch (e) {
+                            this.isLoading = false
+                            console.error(e)
+                            this.$Message.error(this.$t('evaluation.paperList.saveItemsFailTip'))
+                        }
+                    }
+                    console.log(result)
+                    let slides = []
+                    // 主观题的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,
+                            scoring: {
+                                score: item.score || 0,
+                                knowledge: item.knowledge || [],
+                                field: item.field || 1,
+                                ans: nullType.includes(item.type) ? [] : (item.answer || [])
+                            }
+                        }
+                        item.type === 'compose' && delete o.scoring
+                        slides.push(o)
+                    })
+                    // this.isLoading = false
+                    resolve({
+                        slides: slides,
+                        files: itemJsonFiles
+                    })
+                }).catch(err => {
+                    reject(err)
+                    this.isLoading = false
+                    this.$Message.error(this.$t('evaluation.paperList.saveItemsFailTip'))
+                })
+            })
+        },
+        async savePaper(list) {
+            
+        },
+    },
+}
+</script>
+
+<style lang="less" scoped>
+@import "./DfPage.less";
+</style>
+<style lang="less">
+.select-ques {
+    background-color: #f6f6f6;
+}
+</style>