ソースを参照

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

CrazyIter_Bin 9 ヶ月 前
コミット
cbf696085b

+ 3 - 1
TEAMModelOS/ClientApp/public/lang/en-US.js

@@ -8009,7 +8009,9 @@ const LANG_EN_US = {
         signup: 'Sign up',
         exam: 'Exam',
         other: 'Other',
-        activityPlace:'Place',        
+        activityPlace:'Place',                
+        teacher:'teacher',        
+        class:'class',
         fileUrl: 'FileUrl',
         joinStatus: 'Registration status',
         tmid: 'TEAM Model ID',

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

@@ -8010,7 +8010,9 @@ const LANG_ZH_CN = {
         signup: '报名',
         exam: '评量',
         other: '其他',
-        activityPlace:'地点',        
+        activityPlace:'地点',                
+        teacher:'老师',        
+        class:'班级',
         fileUrl: '档案连结',
         joinStatus: '报名状况',
         tmid: '醍摩豆帐号',

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

@@ -8010,7 +8010,9 @@ const LANG_ZH_TW = {
         signup: '報名',
         exam: '評量',
         other: '其他',
-        activityPlace:'地點',        
+        activityPlace:'地點',                
+        teacher:'老師',        
+        class:'班級',
         fileUrl: '檔案連結',
         joinStatus: '報名狀況',
         tmid: '醍摩豆帳號',

+ 8 - 0
TEAMModelOS/ClientApp/src/api/htcommunity.js

@@ -28,6 +28,14 @@ export default {
     jointExamFind: function(data) {
         return post('/joint/exam/find', data)
     },
+    // 取得學生評量結果
+    commonExamFindSummaryRecord: function(data) {
+        return post('/common/exam/find-summary-record', data)
+    },
+    // 新建變更統測評量
+    jointExamUpsert: function(data) {
+        return post('/joint/exam/upsert', data)
+    },    
     // 取得報名教師課程
     jointCourseFind: function (data) {
         return post('/joint/course/find', data)

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

@@ -759,6 +759,15 @@ export const routes = [{
             isKeep: true
         }
     },
+    {
+        path: 'htCreateEva',
+        name: 'htCreateEva',
+        component: () => import('@/view/learnactivity/htCreateEva.vue'),
+        meta: {
+            activeName: '',
+            isKeep: true
+        }
+    },    
     // 创建个人评测
     {
         path: 'createPrivExam',

+ 1 - 0
TEAMModelOS/ClientApp/src/store/module/config.js

@@ -103,6 +103,7 @@ export default {
                 stationSetting = {}
                 stationSetting.station = 'test'
                 stationSetting.srvAdr = 'China'
+                //stationSetting.srvAdr = 'Global'
                 //这里异常如果本地为 null 本地测试会重复设置为null
                 // if (localStorage.getItem('srvAdr')) stationSetting.srvAdr = localStorage.getItem('srvAdr')
             }

+ 1 - 1
TEAMModelOS/ClientApp/src/utils/blobTool.js

@@ -6,7 +6,7 @@ import store from '@/store'
 import FileSaver from "file-saver";
 import JSZip from "jszip";
 
-const BLOB_PATH = ['avatar', 'audio', 'doc', 'exam', 'image', 'elegant', 'item', 'notice', 'other', 'paper', 'syllabus', 'res', 'records', 'student', 'survey', 'temp', 'thum', 'video', 'vote', 'jyzx', 'train', 'yxpt', 'homework', 'policy', 'public', 'art', 'activity', 'banner']
+const BLOB_PATH = ['jointexam', 'avatar', 'audio', 'doc', 'exam', 'image', 'elegant', 'item', 'notice', 'other', 'paper', 'syllabus', 'res', 'records', 'student', 'survey', 'temp', 'thum', 'video', 'vote', 'jyzx', 'train', 'yxpt', 'homework', 'policy', 'public', 'art', 'activity', 'banner']
 const { BlobServiceClient } = require("@azure/storage-blob")
 
 //获取文件后缀和类型

+ 1 - 1
TEAMModelOS/ClientApp/src/view/Home.vue

@@ -455,7 +455,7 @@
 					if (this.teacherRoutes.includes(val.path)) {						
 						this.isBaseMgtExpire = false;
 					}
-					console.error("路由切换", val);
+					console.log("路由切换", val);
 					/* 判断学校管理模块是否到期 */
 					let schoolVersions = JSON.parse(decodeURIComponent(localStorage.school_profile || "{}", "utf-8"));
 					let isSchoolRoute = !this.teacherRoutes.includes(this.$route.path)									

+ 782 - 0
TEAMModelOS/ClientApp/src/view/evaluation/index/htTestPaper.vue

@@ -0,0 +1,782 @@
+<template>
+  <div class="paper-container">
+    <div class="back-to-top flex-col-center" :title="$t('evaluation.backToTop')" v-if="isShowBackToTop" @click="handleBackToTop">
+      <Icon type="ios-arrow-up" />
+    </div>
+    <div class="paper-main-wrap">
+      <!-- 试卷内容 -->
+      <div class="paper-content">
+        <div class="paper-body">
+          <!-- 试卷基础信息 -->
+          <div class="paper-base-info" v-show="!isPreview &&  !isPreviewItems">
+            <div style="display: flex;">
+              <div class="paper-info-items">
+                <span class="base-info-item">{{$t('evaluation.paperList.paperScore')}}:<span class="analysis-info" style="cursor: pointer;">{{ paperInfo.score }}</span>{{$t('evaluation.paperList.score')}}</span>
+                <span class="base-info-item" @click="onShowScoreTable" style="cursor: pointer;">{{$t('evaluation.paperList.alreadyScore')}}:<span class="analysis-info">{{ allocatedScore || 0 }}</span>{{$t('evaluation.paperList.score')}}</span>
+              </div>
+              <div class="paper-info-items">
+                <span class="base-info-item">{{$t('evaluation.filter.diff')}}:
+                  <Rate allow-half v-model="paperInfo.item.length ? +paperDiff : 0" disabled />
+                </span>
+                <span class="base-info-item">{{$t('evaluation.paperList.itemCount')}}:<span class="analysis-info">{{ paperInfo.item ? paperInfo.item.length : 0 }}</span></span>
+              </div>
+            </div>
+            <div v-if="isShowBaseInfo && !isExamPaper && !isPreviewItems">
+              <Button class="base-info-btn" type="info" @click="showPaperAttachments" v-if="isHiteachPaper">{{ $t('evaluation.quickPaper.attachments') }}</Button>
+              <Button class="base-info-btn" type="info" @click="addNewModal = true" v-show="!isShowAnalysis">{{ $t('evaluation.index.addExercise') }}</Button>
+              <Button class="base-info-btn" type="info" @click="onHandleToggle" v-show="paperInfo.item.length && !isShowAnalysis">{{ isAllOpen ? $t('evaluation.index.collapseAll') : $t('evaluation.index.openAll')}}</Button>
+              <Button class="base-info-btn" type="info" @click="onSetScoreByType" v-show="paperInfo.item.length && !isShowAnalysis">{{$t('evaluation.exerciseList.typeScore')}}</Button>
+              <Button class="base-info-btn" type="info" @click="onViewModelChange" v-show="paperInfo.item.length && !isShowAnalysis">{{ `${ viewModel === 'type' ? this.$t('evaluation.paperList.sortByOrder') : this.$t('evaluation.paperList.sortByType') }` }}</Button>
+              <Button class="base-info-btn" type="info" @click="isShowAnalysis = !isShowAnalysis" v-show="paperInfo.item.length">{{ isShowAnalysis ? this.$t('evaluation.paperList.paperDetails') : this.$t('evaluation.paperList.paperAnalysis')}}</Button>
+              <Button class="base-info-btn" type="info" v-show="paperInfo.item.length && paperInfo.id" @click="onChooseOrderTemp">{{ $t('evaluation.orderTemp') }}</Button>
+              <Button class="base-info-btn" type="info" @click="downloadSheet" :loading="downLoading" v-show="isMarkModel && paperInfo.item.length && paperInfo.id && paper.sheetNo">{{ $t('evaluation.paperList.goAnswerSheet') }}<span v-if="paperInfo.mode">-{{ paperInfo.mode }}</span></Button>
+              <Button class="base-info-btn" type="info" @click="goAnswerSheet" v-show="isMarkModel && paperInfo.item.length && paperInfo.id">{{ paper.sheetNo ?  $t('evaluation.paperList.reCreateSheet') : $t('evaluation.paperList.createSheet') }}</Button>
+            </div>
+            <div v-if="isExamPaper && !isPreviewItems && paperInfo.item.length">
+              <Button class="base-info-btn" type="info" @click="showPaperAttachments" v-show="!isChangePaper" v-if="isHiteachPaper">{{ $t('evaluation.quickPaper.attachments') }}</Button>
+              <!-- <Button class="base-info-btn" type="info" @click="showChangePaper" v-show="isExamInfoPaper && !isChangePaper">{{ $t('evaluation.quickPaper.modifyPaper') }}</Button> -->
+              <Button class="base-info-btn" type="info" @click="onHandleToggle" v-show="!isShowAnalysis && !isChangePaper">{{ isAllOpen ? $t('evaluation.index.collapseAll') : $t('evaluation.index.openAll')}}</Button>
+              <Button class="base-info-btn" type="info" @click="onViewModelChange" v-show="!isShowAnalysis && !isChangePaper">{{ `${ viewModel === 'type' ? this.$t('evaluation.paperList.sortByOrder') : this.$t('evaluation.paperList.sortByType') }` }}</Button>
+              <Button class="base-info-btn" type="info" @click="isShowAnalysis = !isShowAnalysis" v-show="!isHideAnalysis && !isChangePaper">{{ isShowAnalysis ? this.$t('evaluation.paperList.paperDetails') : this.$t('evaluation.paperList.paperAnalysis')}}</Button>
+              <Button class="base-info-btn" type="info" @click="downloadSheet" :loading="downLoading" v-show="isMarkModel && paperInfo.id && paper.sheetNo && !hideSheet && !isSharePreview && !isChangePaper">{{ $t('evaluation.paperList.goAnswerSheet') }}<span v-if="paperInfo.mode">-{{ paperInfo.mode }}</span></Button>
+              <Button class="base-info-btn" type="info" @click="goAnswerSheet" v-show="isMarkModel && paperInfo.id && !hideSheet && !isSharePreview && !isChangePaper">{{ paper.sheetNo ?  $t('evaluation.paperList.reCreateSheet') : $t('evaluation.paperList.createSheet') }}</Button>
+              <Button class="base-info-btn" type="info" @click="exitPreview" v-show="paperInfo.id && isSharePreview && !isChangePaper">{{ $t('evaluation.index.backList') }}</Button>
+              <Button class="base-info-btn" type="success" @click="showChangePaper(1)" v-show="isChangePaper">{{ $t('cusMgt.save') }}</Button>
+              <Button class="base-info-btn" @click="showChangePaper" v-show="isChangePaper">{{ $t('evaluation.cancel') }}</Button>
+            </div>
+          </div>
+          <!-- 试卷头部信息 -->
+          <div class="paper-header flex-col-center">
+            <p class="paper-title">{{paperInfo.name}}</p>
+          </div>
+          <!-- 试卷分析部分 -->
+          <ExamPaperAnalysis :testPaper="paperInfo" v-if="isShowAnalysis" :hidePie="hidePie">
+          </ExamPaperAnalysis>
+          <!-- 题目类型及列表 -->
+          <BaseExerciseList :paper="paperInfo" @dataUpdate="onListUpdate" v-show="!isShowAnalysis" ref="exList" :isChangePaper="isChangePaper" :isShowTools="!isPreview" :canFix="canFix" :isExamPaper="isExamPaper || isPreviewItems" @toggleChange="onToggleChange" @scoreUpdate="scoreUpdate"></BaseExerciseList>
+        </div>
+        <!-- <BaseHiteachPaper v-if="isHiteachPaper" :paper="paperInfo"></BaseHiteachPaper> -->
+      </div>
+    </div>
+
+    <!-- 新建试题 -->
+    <Modal v-model="addNewModal" @on-visible-change="onAddNewModalChange" :mask-closable="false" :title="$t('evaluation.index.addExercise')" width="1000px" class="related-point-modal edit-exercise-modal">
+      <Tabs value="name1" name="newExerciseTab" @on-click="onTabChange" :animated="false">
+        <TabPane :label="$t('evaluation.autoCreate')" name="name1" tab="newExerciseTab">
+          <BaseCreateChild @addFinish="onAddNewFinish" ref="newEdit" v-if="addNewModal" :curPeriodIndex="paperInfo.paperPeriod" :curSubjectIndex="paperInfo.paperSubject">
+          </BaseCreateChild>
+        </TabPane>
+        <!-- <TabPane :label="$t('evaluation.quickCreate')" name="name2" tab="newExerciseTab" v-if="isDevEnv">
+          <BasePasteTool v-if="addNewModal" @addFinish="onAddNewFinish"></BasePasteTool>
+        </TabPane> -->
+        <TabPane :label="$t('evaluation.cpTip1')" name="name3" tab="newExerciseTab">
+          <ManualCreate ref="bankPicker" :subjectCode="subjectCode" :periodCode="periodCode" :gradeCode="gradeCode" :isMarkModel="isMarkMode"></ManualCreate>
+        </TabPane>
+        <TabPane :label="$t('evaluation.cpTip2')" name="name4" tab="newExerciseTab">
+          <BasePaperItemPicker v-if="curModalTab === 'name4'" ref='paperPicker' :subjectCode="subjectCode" :periodCode="periodCode" :gradeCode="gradeCode"></BasePaperItemPicker>
+        </TabPane>
+      </Tabs>
+      <div slot="footer">
+        <Button @click="addNewModal = false">{{$t('evaluation.cancel')}}</Button>
+        <Button type="success" :loading="editLoading" @click="doSaveEdit">{{$t('evaluation.confirm')}}</Button>
+      </div>
+    </Modal>
+
+    <!-- 选择题号模板 -->
+    <Modal v-model="orderTempModal" :title="$t('evaluation.orderTempChoos')" width="600px" class="related-point-modal order-temp-modal" @on-ok="onConfirmOrderTemp">
+      <div :class="['order-temp-item',curOrderTempIndex === 0 ? 'order-temp-item-active' : '']" @click="onClickOrderTemp(0)">
+        <p>{{ $t('evaluation.order1') }} <span class="order-temp-item-info">({{ $t('evaluation.orderTip1') }})</span> </p>
+      </div>
+      <div :class="['order-temp-item',curOrderTempIndex === 1 ? 'order-temp-item-active' : '']" @click="onClickOrderTemp(1)">
+        <p>{{ $t('evaluation.order2') }} <span class="order-temp-item-info">({{ $t('evaluation.orderTip2') }})</span></p>
+      </div>
+      <div :class="['order-temp-item',curOrderTempIndex === 2 ? 'order-temp-item-active' : '']" @click="onClickOrderTemp(2)">
+        <p>{{ $t('evaluation.order3') }} <span class="order-temp-item-info">({{ $t('evaluation.orderTip3') }})</span></p>
+      </div>
+      <!-- <div :class="['order-temp-item',curOrderTempIndex === 3 ? 'order-temp-item-active' : '']" @click="onClickOrderTemp(3)">
+				<p>中文大写 <span class="order-temp-item-info">(例:壹、贰、叁、肆、伍......)</span></p>
+			</div> -->
+    </Modal>
+  </div>
+</template>
+<script>
+import blobTool from '@/utils/blobTool.js'
+import ExamPaperAnalysis from '@/view/learnactivity/ExamPaperAnalysis.vue'
+import ManualCreate from '@/view/learnactivity/ManualCreate.vue'
+
+export default {
+  components: {
+    ManualCreate,
+    ExamPaperAnalysis,
+  },
+  props: {    
+    jointGroupId: {
+      type: String,
+      default: ''
+    },
+    jointScheduleId: {
+      type: String,
+      default: ''
+    },
+    paper: {
+      type: Object,
+      default: null
+    },
+    /* 是否阅卷专用 */
+    isMarkMode: {
+      type: Boolean,
+      default: false
+    },
+    isShowTools: {
+      type: Boolean,
+      default: true
+    },
+    isPreview: {
+      type: Boolean,
+      default: false
+    },
+    isShowBaseInfo: {
+      type: Boolean,
+      default: true
+    },
+    isExamPaper: {
+      type: Boolean,
+      default: false
+    },
+    isExamInfoPaper: { //评测页面下的试卷,需调整答案、配分等
+      type: Boolean,
+      default: false
+    },
+    hidePie: {
+      type: Boolean,
+      default: false
+    },
+    isHideAnalysis: {
+      type: Boolean,
+      default: false
+    },
+    isPreviewItems: {
+      type: Boolean,
+      default: false
+    },
+    hideSheet: {
+      type: Boolean,
+      default: false
+    },
+    isSharePreview: {
+      type: Boolean,
+      default: false
+    },
+    canFix: {
+      type: Boolean,
+      default: false
+    },
+    gradeCode: {
+      type: Array,
+      default: () => []
+    },
+    subjectCode: {
+      type: String,
+      default: ''
+    },
+    periodCode: {
+      type: String,
+      default: ''
+    },
+    activityIndex: {
+        type: Number,
+        default: 0
+    },
+    subjectIndex: {
+        type: Number,
+        default: 0
+    },
+    refreshExam: {
+        type: Function,
+        require: true,
+        default: null
+    },
+  },
+  data() {
+    return {
+      isHiteachPaper: false,
+      isMarkModel:false,
+      editLoading: false,
+      hasModify: false,
+      curOrderTempIndex: 0,
+      orderTempModal: false,
+      isShowPasteTool: false,
+      addNewModal: false,
+      scoreTableModal: false,
+      isShowAnswerSheet: false,
+      isShowBackToTop: false,
+      isAllOpen: false,
+      isShowAnalysis: false,
+      isSetPaperName: false,
+      isSetScore: false,
+      isSetRules: false,
+      isShowSave: false,
+      exersicesList: [],
+      allocatedScore: 0,
+      list: [],
+      schoolInfo: {},
+      paperInfo: {
+        name: "",
+        score: 100,
+        answers: [],
+        multipleRule: 1,
+        item: [],
+        paperSubject: 0,
+        paperPeriod: 0
+      },
+      paperInfoOld: {},
+      exersicesType: this.$GLOBAL.EXERCISE_TYPES(),
+      exersicesDiff: this.$GLOBAL.EXERCISE_DIFFS(),
+      exersicesField: this.$GLOBAL.EXERCISE_LEVELS(),
+      diffColors: ['#32CF74', '#E8BE15', '#F19300', '#EB5E00', '#D30000'],
+      filterType: '0',
+      filterDiff: '0',
+      filterSort: '0',
+      pageSize: 5,
+      pageNum: 1,
+      totalNum: 100,
+      allList: [],
+      isShowAnswer: false,
+      isShowPart: false,
+      isShowConcept: false,
+      isShowTitle: true,
+      isShowInfo: false,
+      downLoading: false,
+      analysisTableData: [],
+      viewModel: 'type',
+      paperDiff: 0,
+      curModalTab: '',
+      isChangePaper: false,
+    }
+  },
+  methods: {
+    getSelectedQuestion(val) {
+      // this.onAddNewFinish(val.item)
+      // this.paperInfo.item = this._.cloneDeep(val.item)
+
+    },
+    onAddNewModalChange(val) {
+      if (val) {
+        this.$refs.bankPicker && (this.$refs.bankPicker.shoppingQuestionList = [])
+        this.$refs.bankPicker && (this.$refs.bankPicker.$refs.exList.selectList = [])
+        this.$refs.paperPicker && (this.$refs.paperPicker.checkList = [])
+      }
+    },
+    /* 退出预览 */
+    exitPreview() {
+      this.$emit('exitPreview')
+    },
+    async showPaperAttachments(){
+      let paper = this.paperInfo
+      if(!paper.attachments.length){
+        this.$Message.warning(this.$t('homework.noAttachments'))
+        return
+      }
+      console.error(paper)
+      // let curScope = paper.examScope || paper.scope
+      let curScope = paper.scope // 个人评测使用校本试卷 examScope会是 private 所以改为直接读取 scope
+      let blobHost = curScope === 'school' ? JSON.parse(decodeURIComponent(localStorage.school_profile, "utf-8")).blob_uri : JSON.parse(decodeURIComponent(localStorage.user_profile, "utf-8")).blob_uri
+      let sasString = curScope === 'school' ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
+      let fullImgArr = paper.attachments?.map(imgName => blobHost + paper.blob + '/' + imgName + sasString.sas)
+      this.$hevueImgPreview({
+					multiple: true,
+					keyboard: true,
+					nowImgIndex: 0,
+					imgList: fullImgArr
+				});
+    },
+    /* 手动保存 */
+    doSaveEdit() {
+      this.editLoading = true
+      if (this.curModalTab === 'name4') {
+        let newItems = this.$refs.paperPicker.checkList
+        this.onAddNewFinish(newItems)
+      } else if (this.curModalTab === 'name3') {
+        let newItems = this.$refs.bankPicker.shoppingQuestionList
+        this.onAddNewFinish(newItems)
+      } else {
+        this.$refs.newEdit.getContent(this.$refs.newEdit.exersicesType)
+      }
+    },
+    onTabChange(val) {
+      this.curModalTab = val
+      // if (val === 'name1') {
+      // 	this.isShowPasteTool = true
+      // }
+    },
+    onClickOrderTemp(val) {
+      this.curOrderTempIndex = val
+    },
+    onChooseOrderTemp() {
+      this.orderTempModal = true
+    },
+    onConfirmOrderTemp() {
+      this.$refs.exList.onConfirmOrderTemp(this.curOrderTempIndex)
+    },
+    /* 下载Blob答题卡 */
+    async downloadSheet() {
+      this.downLoading = true
+      let examId = this.paperInfo.examId
+      console.error(this.paperInfo)
+      let sheetMode = this.paperInfo.mode ? `(${this.paperInfo.mode})` : ``
+      let fileName = `${this.paperInfo.name}-${this.paperInfo.sheetNo}${sheetMode}.pdf`
+      // let pdfName = `${this.paperInfo.name}-${this.paperInfo.sheetNo}.pdf`
+      let path = examId ? `exam/${examId}/paper/${this.paperInfo.subjectId}/` : `paper/${this.paperInfo.name}/`
+      let curScope = examId ? this.paperInfo.examScope : this.paperInfo.scope
+      let cntr = curScope === 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId
+      let sasData = curScope === 'school' ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
+      let blobHost = this.$evTools.getBlobHost()
+      let fullPath = blobHost + '/' + cntr + '/' + path + fileName + sasData.sas
+      const downloadRes = async () => {
+        let response = await fetch(fullPath); // 内容转变成blob地址
+        if (response.status !== 200) {
+          this.$Message.warning(this.$t('answerSheet.sheetTip5'))
+        } else {
+          let blob = await response.blob();  // 创建隐藏的可下载链接
+          let objectUrl = window.URL.createObjectURL(blob);
+          let a = document.createElement('a');
+          a.href = objectUrl;
+          a.download = fileName;
+          a.click()
+          a.remove();
+        }
+        this.downLoading = false
+      }
+      downloadRes();
+      console.log(fullPath);
+    },
+    goAnswerSheet() {
+      console.log(this.paperInfo)
+
+      if (this.paperInfo.itemSort === 1) {
+        this.$Message.warning(this.$t('answerSheet.noCreateTip'))
+        return
+      }
+      if (!this.isExamPaper) {
+        localStorage.setItem('c_edit_paper', JSON.stringify(this.paperInfo))
+      }
+      this.$store.commit('clearAllConfig')
+      this.$router.push({
+        name: 'answerSheet',
+        params: {
+          paper: this.paperInfo
+        }
+      })
+    },
+    onShowScoreTable() {
+      this.$refs.exList.scoreTableModal = true
+    },
+    /* 新增题目回调 */
+    onAddNewFinish(item) {
+      sessionStorage.setItem('isSave', 0)
+      if (Array.isArray(item)) {
+        if(this.isMarkMode && item.some(i => i.type === 'compose')){
+          this.$Message.warning(this.$t('evaluation.markMode.tip2'))
+        }
+        let noComposeItems = item.filter(o => o.type !== 'compose')
+        this.paperInfo.item.push(...noComposeItems)
+      } else {
+        if(this.isMarkMode && item.type === 'compose'){
+          this.$Message.warning(this.$t('evaluation.markMode.tip2'))
+        }else{
+          this.paperInfo.item.push(item)
+        }
+      }
+      this.addNewModal = false
+      this.editLoading = false
+    },
+    /**
+     * 标题切换
+     * @param e
+     */
+    titleChange(e) {
+      this.paperInfo.name = e.target.innerHTML
+    },
+
+    handleBackToTop() {
+      console.log(this)
+      this.$EventBus.$emit('onBackToTop')
+    },
+
+    onSetMarkingRules() {
+      this.isSetRules = false
+    },
+
+    onShowAnalysis() {
+      this.isShowAnalysis = true
+    },
+
+    /** 切换全部展开与折叠 */
+    onHandleToggle() {
+      this.$refs.exList.onHandleToggle(this.isAllOpen)
+      this.isAllOpen = !this.isAllOpen
+    },
+
+    /**
+     * exList的collapseList变化
+     * @param list
+     */
+    onToggleChange(list) {
+      this.isAllOpen = list.length !== 0
+    },
+
+    /** 返回试卷库 */
+    onBackToBank() {
+      this.$router.push({
+        name: 'testPaperList',
+        params: {
+          tabName: 'paper'
+        }
+      })
+    },
+
+    /* 清空试卷试题 */
+    onCleanPaper() {
+      this.paperInfo.item = []
+      this.$refs.exList.errorList = []
+      this.$refs.exList.noAnswerList = []
+      this.$EventBus.$emit('onPaperItemChange', [])
+    },
+
+    onSetScore() {
+      this.isSetScore = false
+      this.$refs.exList.exerciseList.map(item => item.score = 0)
+    },
+
+    /**
+     * 组件更新删除题目时的处理
+     * @param list
+     */
+    onListUpdate(list) {
+      this.paperInfo.item = list
+      this.hasModify = true
+      console.log(list);
+    },
+    /** 重新挑题 */
+    goToPickExercise() {
+      this.$router.push({
+        name: 'exercisesList',
+        params: {
+          paperInfo: this.paperInfo
+        }
+      })
+    },
+
+    /** 点击题型配分 */
+    onSetScoreByType() {
+      this.$refs.exList.onSetScoreByType()
+    },
+
+
+    /**
+     * 试卷的视图模式切换
+     * @param val
+     */
+    onViewModelChange(val) {
+      if(this.isMarkMode){
+        this.$Message.warning(this.$t('evaluation.markMode.tip3'))
+        return
+      }
+      this.viewModel = this.viewModel === 'type' ? 'list' : 'type'
+      this.$refs.exList.viewModel = this.viewModel
+      this.$refs.exList.collapseList = []
+      // this.$refs.exList.doRenderMathJax()
+      this.$emit('onViewModelChange', this.viewModel)
+    },
+
+    /**
+     * 计算试卷题目平均难度
+     * @param arr 试题集合
+     */
+    handleDiffCalc(arr) {
+      let levelArr = arr.map(i => i.level)
+      return this._.meanBy(levelArr).toFixed(1)
+    },
+
+    scoreUpdate(score) {
+      this.allocatedScore = this.paperInfo.score - score
+    },
+    async showChangePaper(type) {
+        if(type === 1) {// 修改試卷 > 儲存按鈕
+            if(this.allocatedScore != this.paperInfo.score) {
+                this.$Message.warning(this.$t('evaluation.paperList.noCompleteScoreTip'))
+                return
+            }
+            
+            // 活動板修改試卷 先暫停
+            // let params1 = {
+            //     jointEventId: this.$route.params.data.id,
+            //     jointGroupId: this.jointGroupId,
+            //     jointScheduleId: this.jointScheduleId,
+            //     jointExamId: this.paperInfo.examId,                                            
+            //     papers: this.paperInfo
+            // }
+            // 重新保存试卷 && 调接口保存答案、配分
+            let params = {
+                id: this.paperInfo.examId, //活动ID
+                code: this.paperInfo.examScope === 'school' ? this.paperInfo.examSchool : this.paperInfo.creatorId, //个人ID或者学校编码
+                scode: this.paperInfo.examCode, //原本评测活动的完整code:'Exam-hbcn'
+                paperId: this.paperInfo.id, //试卷ID
+                //subjectId: this.paperInfo.examSubject[this.subjectIndex]?.id, //科目ID
+                paperAns: [], //作答记录的完整数组
+                point: [], //完整配分的数组
+                kno: [], //知识点
+                multipleRule: this.paperInfo.multipleRule, //评分规则
+            }
+            this.paperInfo.item.forEach(item => {
+              if(item.type === 'compose') {
+                item.children.forEach(child => {
+                  if(child.type === 'single' || child.type === 'multiple' || child.type === 'judge') {
+                    params.paperAns.push(child.answer)
+                  } else {
+                    params.paperAns.push([])
+                  }
+                  params.point.push(child.score)
+                  params.kno.push(child.knowledge)
+                })
+              } else {
+                if(item.type === 'single' || item.type === 'multiple' || item.type === 'judge') {
+                  params.paperAns.push(item.answer)
+                } else {
+                  params.paperAns.push([])
+                }
+                params.point.push(item.score)
+                params.kno.push(item.knowledge)
+              }
+            })            
+            //this.paperInfo.slides 分數是未更新前的   this.paperInfo.item 分數是更新後的
+            const itemJsonFile111 = await this.$evTools.createBlobPaper(this.paperInfo, this.paperInfo.slides);
+           
+            this.$api.htcommunity.jointExamUpsert(params).then(async res => {
+              if(res.code === 200) {
+                const itemJsonFile = await this.$evTools.createBlobPaper(this.paperInfo, this.paperInfo.slides);
+                // let blobPaper = await this.$evTools.createBlobPaper(paperItem, res.slides)
+                // 首先保存新题目的JSON文件到Blob 然后返回URL链接
+                let paperFile = new File([JSON.stringify(itemJsonFile)], "index.json");
+                // 获取初始化Blob需要的数据
+                let sasData = this.paperInfo.scope === 'school' ? await this.$tools.getSchoolSas() : await this.$tools.getPrivateSas()
+                //初始化Blob
+                let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, this.paperInfo.scope)
+                try {
+                    let promiseArr = []
+                    let blobFile = null
+                    let blobUrl = this.paperInfo.blob.slice(1)
+                    // 放入试题json文件
+                    for (let i = 0; i < this.paperInfo.item.length; i++) {
+                        promiseArr.push(new Promise(async (r, j) => {
+                            try {
+                                let item = this.paperInfo.item[i]
+                                const itemJsonFile = await this.$evTools.createBlobItem(item)
+                                let file = new File([JSON.stringify(itemJsonFile)], item.id + ".json");
+                                containerClient.upload(file, {
+                                    path: blobUrl,
+                                    checkSize: false
+                                }).then(res => {
+                                    r(200)
+                                })
+                            } catch (e) {
+                                console.log(e)
+                            }
+                        }))
+                        if(this.paperInfo.item[i].type === 'compose') {
+                          this.paperInfo.item[i].children.forEach(child => {
+                            promiseArr.push(new Promise(async (r, j) => {
+                              try {
+                                  let item = child
+                                  const itemJsonFile = await this.$evTools.createBlobItem(item)
+                                  let file = new File([JSON.stringify(itemJsonFile)], item.id + ".json");
+                                  containerClient.upload(file, {
+                                      path: blobUrl,
+                                      checkSize: false
+                                  }).then(res => {
+                                      r(200)
+                                  })
+                              } catch (e) {
+                                  console.log(e)
+                              }
+                          }))
+                          })
+                        }
+                    }
+                    // 放入index.json文件
+                    promiseArr.push(new Promise(async (r, j) => {
+                        try {
+                            blobFile = await containerClient.upload(paperFile, {
+                                path: blobUrl,
+                                checkSize: false
+                            })
+                            console.log('上传到试卷目录下', blobFile)
+                            r(blobFile)
+                        } catch (e) {
+                            j(e)
+                            this.$Message.error(e.spaceError)
+                            this.isLoading = false
+                        }
+                    }))
+                    // 不存在多媒体
+
+                    // 进行试卷文件上传Blob 先上传所有题目 再上传index.json文件
+                    Promise.all(promiseArr).then(async result => {
+                        try {
+                            this.refreshExam(this.paperInfo, this.subjectIndex)
+                            if (blobFile.blob) {
+                                // 试卷保存更新后需要重新生成答题卡
+                                /* paperItem.blob = blobFile.blob.split('/index.json')[0]
+
+                                let params = {
+                                    paper: await this.$evTools.createCosmosPaper(paperItem),
+                                    option: this.isEditPaper ? 'update' : 'insert'
+                                }
+                                //  保存试卷到cosmos
+                                this.$api.learnActivity.SaveExamPaper(params).then(res => {
+                                    if (res.error == null) {
+                                        this.$Message.success(this.$t('evaluation.paperList.saveSuc'))
+                                        this.isLoading = false
+                                        this.$Spin.hide()
+                                        // this.savePeriodInfos()
+                                        // 清空已选试题
+                                        this.showQues = false
+                                        this.selectedArr = []
+                                        this.groupList = []
+                                        this.orderList = []
+                                        this.selShowList = []
+                                    } else {
+                                        this.$Message.error(this.$t('evaluation.paperList.saveFail'))
+                                        this.$Spin.hide()
+                                        this.isLoading = false
+                                    }
+                                },err => {
+                                    this.$Message.error(this.$t('evaluation.paperList.saveFail'))
+                                    this.isLoading = false
+                                    this.$Spin.hide()
+                                }) */
+                            } else {
+                                console.error(blobFile)
+                            }
+                        } catch (e) {
+                            console.log(e)
+                        }
+                        this.$Message.success(this.$t("evaluation.editSuc"))
+                        this.isChangePaper = !this.isChangePaper
+                    })
+                } catch (e) {
+                    console.log(e)
+                    this.$Message.error(this.$t('evaluation.paperList.saveItemsFailTip'))
+                    this.isLoading = false
+                    this.isChangePaper = !this.isChangePaper
+                }
+              } else {
+                this.$t('learnActivity.mgtScEv.updErr')
+              }
+            })
+        } else {
+            this.isChangePaper = !this.isChangePaper
+            if(!this.isChangePaper) {
+              this.paperInfo = JSON.parse(JSON.stringify(this.paperInfoOld))
+              this.paper.item = this.paperInfo.item
+              this.$forceUpdate()
+            }
+        }
+    },
+
+
+  },
+  mounted() {
+    // this.isShowSave = window.location.pathname === '/home/evaluation/testPaper'
+    this.$Spin.hide()
+    let paper = this.paper || this.$route.params.paper || JSON.parse(localStorage.getItem('c_edit_paper'))
+    if (!paper || !paper.item) return
+    this.paperInfoOld = JSON.parse(JSON.stringify(paper))
+    console.log('xxxx', paper)
+    this.$EventBus.$emit('getNewPaper', paper)
+    // localStorage.setItem('_paperInfo', JSON.stringify(paper))
+    this.viewModel = paper.itemSort === 1 ? 'list' : 'type'
+    this.paperInfo = paper // 自己页面的值
+    this.paperDiff = paper.item ? this.handleDiffCalc(paper.item) : 0
+    this.curOrderTempIndex = paper.orderTemp || 0
+  },
+  computed: {
+    isAuto() {
+      return this.paperInfo.markConfig ? this.paperInfo.markConfig.auto : false
+    },
+    ruleType() {
+      return this.paperInfo.markConfig ? this.paperInfo.markConfig.type : 0
+    },
+    isSchool() {
+      return this.$route.name === 'newSchoolPaper'
+    },
+    isDevEnv() {
+      return process.env.NODE_ENV === 'development'
+    }
+  },
+  watch: {
+    paper: {
+      handler(newValue, oldValue) {
+        if (newValue.item && newValue.item.length) {
+          this.$nextTick(() => {            
+            this.isHiteachPaper = newValue.qamode === 1 // 是否是快速组卷或者Hiteach的课中试卷
+            this.isMarkModel = newValue.markModel === 1 // 是否是阅卷专用
+            if (!this.isHiteachPaper) {
+              this.$EventBus.$emit('getNewPaper', newValue)
+            }
+            this.viewModel = newValue.itemSort === 1 ? 'list' : 'type'
+            console.log('TestPaper > paper', newValue)
+          })
+          this.curOrderTempIndex = newValue.orderTemp || 0          
+          this.paperInfo = newValue
+        }
+        this.paperDiff = newValue.item ? this.handleDiffCalc(newValue.item) : 4
+      },
+      immediate: true,
+      deep: true
+    },
+    activityIndex: {
+      handler(n, o) {
+        if(this.isExamInfoPaper) this.isChangePaper = false
+        this.paperInfoOld = JSON.parse(JSON.stringify(this.paper))
+      }
+    },
+    subjectIndex: {
+      handler(n, o) {
+        if(this.isExamInfoPaper) this.isChangePaper = false
+        this.paperInfoOld = JSON.parse(JSON.stringify(this.paper))
+      }
+    }
+  }
+}
+</script>
+<style src="../index/TestPaper.less" lang="less" scoped>
+</style>
+<style lang="less">
+.complete-line {
+  padding: 0 45px;
+  border-bottom: 2px solid rgb(128, 128, 128);
+}
+
+.order-temp-modal {
+  .order-temp-item {
+    margin: 10px 0;
+    border: 1px solid #dddddd;
+    padding: 20px 15px;
+    border-radius: 5px;
+    font-size: 16px;
+    font-weight: bold;
+    cursor: pointer;
+    &-info {
+      font-size: 14px;
+      font-weight: 400;
+      margin-left: 15px;
+    }
+
+    &-active {
+      background-color: #72cbff;
+      color: #fff;
+    }
+  }
+}
+</style>

+ 7 - 0
TEAMModelOS/ClientApp/src/view/htcommunity/htMgtExam.less

@@ -176,4 +176,11 @@
     &:hover{
         color: #2d8cf0;
     }
+}
+.selected,
+.fistTag:first-child {
+  background: white;
+  color: #606266;
+  font-weight: bolder;
+  border: white 2px solid;
 }

ファイルの差分が大きいため隠しています
+ 862 - 846
TEAMModelOS/ClientApp/src/view/htcommunity/htMgtExam.vue


+ 2 - 2
TEAMModelOS/ClientApp/src/view/htcommunity/htMgtHome.vue

@@ -18,8 +18,8 @@
             </el-table-column>
             <el-table-column :label="this.$t('htcommunity.eventExam')">
                 <template slot-scope="scope">
-                    <!-- <el-button type="text" @click="viewExams(scope.row)">{{$t("htcommunity.view")}}</el-button> -->
-                    <el-button type="text" @click="return false">{{$t("htcommunity.view")}}</el-button>
+                    <el-button type="text" @click="viewExams(scope.row)">{{$t("htcommunity.view")}}</el-button>
+                    <!-- <el-button type="text" @click="return false">{{$t("htcommunity.view")}}</el-button> -->
                 </template>
             </el-table-column>
         </el-table>

+ 1 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/CreatePrivEva.vue

@@ -483,6 +483,7 @@
 								}
 								return;
 							}
+							debugger
 							// 挑选的是校本试卷
 							if (item.scope == "school") {
 								if (!schoolBlob) schoolBlob = new BlobTool(schoolSas.url, schoolSas.name, schoolSas.sas, "school");

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

@@ -300,7 +300,11 @@ export default {
                 if (this.source) {
                     this.scope = this.source
                 } else {
-                    this.scope = this.$route.name == 'createPrivEva' ? this.$store.state.userInfo.TEAMModelId : this.$store.state.userInfo.schoolCode
+                    if(this.$route.name == 'createPrivEva' || this.$route.name == 'htCreateEva'){
+                        this.scope = this.$store.state.userInfo.TEAMModelId;
+                    } else {
+                        this.scope = this.$store.state.userInfo.schoolCode;
+                    }                    
                 }
             },
             immediate: true

+ 704 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/htCreateEva.vue

@@ -0,0 +1,704 @@
+<template>
+	<div class="create-priv-container">
+		<div class="create-header">
+			<p class="create-header-title" @click="consData">{{ $t("learnActivity.createEv.createLabel") }}</p>
+			<Button class="btn-save" type="text" :loading="isLoading" ghost icon="ios-albums-outline" @click="saveEvaluation" style="margin-right: 30px">
+				{{ $t("learnActivity.createEv.publishEv") }}
+			</Button>
+			<Button class="btn-save" type="text" ghost icon="md-arrow-back" @click="confirmToManage">
+				{{ $t("learnActivity.createEv.return") }}
+			</Button>
+		</div>
+		<div class="create-body">
+			<div class="evaluation-attr-wrap">
+				<p class="wrap-label">{{ $t("learnActivity.createEv.baseInfo") }}</p>
+				<div style="width: 100%; height: calc(100% - 45px); padding-top: 15px" class="ivu-select-nochoose light-iview-form light-el-input">
+					<vuescroll>
+						<Form ref="evaForm" :model="evaluationInfo" label-position="top" class="evaluation-attr-form" label-colon :rules="ruleValidate">
+							<FormItem :label="$t('learnActivity.createEv.evName')" prop="name">
+								<Input v-special-char v-model="evaluationInfo.name" :placeholder="$t('learnActivity.createEv.evName')"></Input>
+							</FormItem>
+							<FormItem prop="source">
+								<label slot="label" style="width:200px">
+									<span>{{ $t("learnActivity.createEv.evMode") }}</span>
+									<Tooltip :content="$t('tip.examMode')" transfer theme="light" max-width="300">
+										<Icon type="ios-information-circle-outline" color="#1cc0f3" style="margin-left: 5px" />
+									</Tooltip>
+								</label>
+								<Select v-model="evaluationInfo.source" @on-change="checkItemSort">
+									<!-- 暂时取消创建课中评量 -->
+									<!-- 20230105課中評測放回 -->
+									<Option v-for="(item, index) in $GLOBAL.EV_MODE()" v-show="true" :label="item.label" :value="item.value" :key="index" :disabled="index > 1 && (!$store.state.userInfo.hasSchool || !$store.state.user.schoolProfile.svcStatus.VABAJ6NV)">
+										<div>
+											<span>
+												{{ item.label }}
+											</span>
+											<span @click.stop="toProduct" v-show="index > 1 && scaleStatusText()" class="no-auth-tag">
+												{{ scaleStatusText() }}
+											</span>
+										</div>
+									</Option>
+								</Select>
+							</FormItem>
+							<!-- 去掉系统预设考试类型 20220413 -->
+							<!-- <FormItem :label="$t('learnActivity.createEv.evType')" prop="type">
+                                <Select v-model="evaluationInfo.type">
+                                    <Option v-for="(item,index) in $GLOBAL.EV_TYPE()" :value="item.value" :key="index">{{ item.label }}</Option>
+                                </Select>
+                            </FormItem> -->
+							<!-- 使用级联选择 课程--》班级 -->
+							<!-- <FormItem :label="$t('learnActivity.createEv.evTarget')" prop="targets">
+								<label slot="label">
+									<span>{{ $t("learnActivity.createEv.evTarget") }}</span>
+									<Tooltip :content="$t('tip.targetTips')" transfer theme="light" max-width="300">
+										<Icon type="ios-information-circle-outline" color="#1cc0f3" style="margin-left: 5px" />
+									</Tooltip>
+								</label>
+								<PrivateTargetSingle :defaultScope="defaultScope" :defTargets="defTargets" @on-scope-change="getScope" @on-target-change="treeChange"></PrivateTargetSingle>
+							</FormItem> -->
+							<!-- <FormItem :label="$t('learnActivity.createEv.publishType')" prop="publish">
+                                <Checkbox v-model="evaluationInfo.publish" :true-value="$GLOBAL.PUBLISH_TYPE()[0].value" :false-value="$GLOBAL.PUBLISH_TYPE()[1].value" @on-change="publishChange">
+                                    <span style="margin-left:5px;user-select: none;">{{$GLOBAL.PUBLISH_TYPE()[0].label}}</span>
+                                </Checkbox>
+                            </FormItem> -->
+							<FormItem :label="$t('learnActivity.createEv.startTime') + '(' + $t('learnActivity.noStartTimeTip') + ')'">
+								<DatePicker :options="dateOpt" type="datetime" format="yyyy/MM/dd HH:mm" v-model="startTime" split-panels :placeholder="$t('learnActivity.createEv.sTimeHolder')" style="width: 100%" @on-change="getDate($event, 0)"></DatePicker>
+							</FormItem>
+							<FormItem :label="$t('learnActivity.createEv.endTime')" prop="endTime">
+								<DatePicker :options="dateOpt1" type="datetime" format="yyyy/MM/dd HH:mm" v-model="endTime" split-panels :placeholder="$t('learnActivity.createEv.eTimeHolder')" style="width: 100%" @on-change="getDate($event, 1)"></DatePicker>
+							</FormItem>
+							<FormItem>
+								<Checkbox v-model="evaluationInfo.isCompletion">{{ $t("learnActivity.createEv.completeScore") }}</Checkbox>
+							</FormItem>
+						</Form>
+					</vuescroll>
+				</div>
+			</div>
+			<div class="evaluation-question-wrap">
+				<div class="evaluation-question-main">
+					<Tabs v-model="activeTab" type="card" class="question-main-tabs" name="createTest">
+						<TabPane :label="$t('learnActivity.createEv.papersLabel')" name="manualPaper" v-if="createType == 'manualPaper'" :index="1" tab="createTest">
+							<ManualPaper ref="manualPaper" @selectPaper="selectPaper" :selectedId="evaluationInfo.paperInfo[0] ? evaluationInfo.paperInfo[0].id : ''"></ManualPaper>
+						</TabPane>
+						<TabPane :label="$t('learnActivity.createEv.perviewLabel')" name="preview" :index="2" tab="createTest">
+							<div class="teacher-preview-container">
+								<!--返回顶部-->
+								<!-- <div class="back-to-top" :title="$t('learnActivity.mgtScEv.returnTop')" v-show="showBack" @click="handleBackToTop">
+                                    <Icon type="ios-arrow-up" />
+                                </div> -->
+								<BackToTop @on-to-top="handleBackToTop"></BackToTop>
+								<vuescroll ref="paper-preview" @handle-scroll="checkBackTop">
+									<TestPaper v-if="activeTab == 'preview'" :paper="evaluationInfo.paperInfo.length ? evaluationInfo.paperInfo[0] : { item: [] }" isExamPaper hideSheet></TestPaper>
+								</vuescroll>
+							</div>
+						</TabPane>
+					</Tabs>
+				</div>
+			</div>
+		</div>
+	</div>
+</template>
+<script>
+	import BlobTool from "@/utils/blobTool.js";
+	import TestPaper from "@/view/evaluation/index/TestPaper.vue";
+	import ManualPaper from "./ManualPaper.vue";
+	export default {
+		components: {
+			TestPaper,
+			ManualPaper
+		},
+		data() {
+			const _this = this;
+			return {
+				dateOpt: {
+					disabledDate(date) {
+						return date && date.valueOf() < Date.now() - 86400000;
+					}
+				},
+				dateOpt1: {
+					disabledDate(date) {
+						let d = _this.evaluationInfo.startTime ? _this.evaluationInfo.startTime : Date.now();
+						return d && d > date.valueOf();
+					}
+				},
+				defaultScope: "",
+				defTargets: [],
+				createType: "manualPaper",
+				startTime: "",
+				endTime: "",
+				isLoading: false,
+				ruleValidate: {
+					name: [{ required: true, message: this.$t("learnActivity.createEv.errTips1"), trigger: "change" }],
+					"type.id": [{ required: true, message: this.$t("learnActivity.createEv.errTips2"), trigger: "change" }],
+					source: [{ required: true, message: this.$t("learnActivity.createEv.errTips3"), trigger: "change" }],
+					type: [{ required: true, message: this.$t("learnActivity.createEv.errTips4"), trigger: "change" }],
+					"examType.id": [{ required: true, message: this.$t("learnActivity.createEv.errTips5"), trigger: "change" }],
+					targets: [{ required: true, message: this.$t("learnActivity.createEv.errTips6"), type: "array", trigger: "change" }],
+					classes: [{ required: true, message: this.$t("learnActivity.createEv.errTips6"), type: "array", trigger: "change" }],
+					publish: [{ required: true, message: this.$t("learnActivity.createEv.errTips7"), trigger: "change" }],
+					startTime: [{ required: true, type: "number", message: this.$t("learnActivity.createEv.errTips8"), trigger: "change" }],
+					endTime: [{ required: true, type: "number", message: this.$t("learnActivity.createEv.errTips9"), trigger: "change" }]
+				},
+				activeTab: "manualPaper",
+				isMarkMode: false,
+				evaluationInfo: {
+					name: "",
+					targets: [],
+					classes: [],
+					scope: "",
+					type: "", //测试类别
+					source: "",
+					publish: "0",
+					examType: null, //测试类型
+					startTime: undefined,
+					endTime: undefined,
+					paperInfo: [],
+					papers: [],
+					isCompletion: 0
+				},
+				mode: "",
+				selectBefore: [],
+				stuList: [],
+				showBack: false,
+				isComplete: false
+			};
+		},
+		methods: {
+			scaleStatusText() {
+				if (!this.$store.state.userInfo.hasSchool) {
+					return this.$t("learnActivity.createEv.noSchool");
+				}
+				if (this.$store.state.user.schoolProfile.svcStatus.VABAJ6NV) {
+					return "";
+				} else {
+					return this.$t("learnActivity.createEv.noAuth");
+				}
+			},
+			toProduct() {
+				if (this.$store.state.userInfo.hasSchool) {
+					this.$router.push({
+						name: "product"
+					});
+				}
+			},
+			getScope(data) {
+				this.evaluationInfo.scope = data;
+			},
+			/**vuescroll回到顶部 */
+			handleBackToTop() {
+				this.$refs["paper-preview"].scrollTo(
+					{
+						y: "0"
+					},
+					300
+				);
+			},
+			/**
+			 * 判断是否显示回到顶部按钮
+			 * @param vertical
+			 * @param horizontal
+			 * @param nativeEvent
+			 */
+			checkBackTop(vertical, horizontal, nativeEvent) {
+				if (vertical.scrollTop > 100) {
+					this.showBack = true;
+				} else {
+					this.showBack = false;
+				}
+			},
+			publishChange(data) {
+				if (data == 0) {
+					this.startTime = new Date();
+					this.evaluationInfo.startTime = Date.now();
+				}
+			},
+			treeChange(data) {
+				this.evaluationInfo.targets = data.targets;
+				this.$refs["evaForm"]?.validate();
+				// 1、设置发布对象
+				//个人课程
+				if (this.evaluationInfo.scope == "private") {
+					this.evaluationInfo.stuLists = this.evaluationInfo.targets.map((item) => {
+						return item[1];
+					});
+					this.evaluationInfo.classes = [];
+				}
+				//学校课程教学班
+				else if (this.evaluationInfo.scope == "school" && this.evaluationInfo.targets.length && this.evaluationInfo.targets[0][1] == "teach") {
+					this.evaluationInfo.stuLists = this.evaluationInfo.targets.map((item) => {
+						return item[2];
+					});
+					this.evaluationInfo.classes = [];
+					this.evaluationInfo.grades = [];
+				}
+				// 学校课程行政班
+				else {
+					this.evaluationInfo.classes = this.evaluationInfo.targets.map((item) => {
+						return item[2];
+					});
+					this.evaluationInfo.stuLists = [];
+					//补充年级信息
+					this.evaluationInfo.grades = [];
+					let courseClassList = data.course?.children?.find((item) => item.id == "class")?.children;
+					if (courseClassList && courseClassList.length) {
+						let sltClass = courseClassList.filter((item) => this.evaluationInfo.classes.includes(item.id));
+						let grades = Array.from(new Set(sltClass?.map((item) => item.year)));
+
+						let gradesInfo = grades.map((item) => {
+							return this.$jsFn.getGradeInfoByYear(item, data.course.periodId);
+						});
+						gradesInfo = gradesInfo.filter((item) => !!item);
+						gradesInfo.forEach((item) => {
+							item.id = item.id.toString();
+						});
+						this.evaluationInfo.grades = gradesInfo;
+					}
+				}
+
+				//2、设置评测“学科”
+				this.evaluationInfo.subjects = [];
+				// 个人课程用课程名称代替学科
+				if (this.evaluationInfo.scope == "private") {
+					if (data.targets.length && data.course) {
+						this.evaluationInfo.subjects.push({
+							id: data.course.id,
+							name: data.course.name
+						});
+					}
+					this.evaluationInfo.period = undefined;
+				}
+				//校本课程用课程关联的学生,并补充学段信息
+				else {
+					if (data.targets.length && data.course) {
+						this.evaluationInfo.subjects.push({
+							id: data.course.subjectId,
+							name: data.course.subject
+						});
+						this.evaluationInfo.period = {
+							id: data.course.periodId,
+							name: data.course.period
+						};
+					}
+				}
+			},
+			/*
+			 * 返回上一级
+			 */
+			confirmToManage() {
+				this.$router.go(-1);
+				// if (this.mode == 'private') {
+				//     this.$router.push({
+				//         name: 'privExam'
+				//     })
+				// } else {
+				//     this.$router.push({
+				//         name: 'schoolExam'
+				//     })
+				// }
+			},
+			//设置评测模式后检查试卷itemSort
+			checkItemSort() {
+				this.evaluationInfo.paperInfo = [];
+				this.evaluationInfo.papers = [];
+				this.activeTab = "manualPaper";
+				this.$Message.warning(this.$t('evaluation.markMode.tip5'));
+				this.isMarkMode = this.evaluationInfo.source == "2";
+				this.$refs.manualPaper.getPaperList();
+			},
+			/**
+			 * 处理挑选试卷事件
+			 * @param data
+			 */
+			selectPaper(data) {				
+				if (this.evaluationInfo.source == "2" && data.itemSort == 1) {
+					return this.$Message.warning(this.$t("learnActivity.createEv.sort3"));
+				}
+				let simplePaper = data;
+				this.$Modal.confirm({
+					title: this.$t("learnActivity.createEv.stPaperTitle"),
+					content: `${this.$t("learnActivity.createEv.stPaperContent")}${data.name}?`,
+					onOk: async () => {
+						let fullPaper = await this.$evTools.getFullPaper(simplePaper);
+						this.comfirmSelectPaper(simplePaper, fullPaper);
+					}
+				});
+			},
+			comfirmSelectPaper(simplePaper, fullPaper) {
+				if (!this.evaluationInfo.name) {
+					this.evaluationInfo.name = simplePaper.name;
+				}
+				fullPaper.examId = "";
+				fullPaper.examScope = this.mode;
+				fullPaper.examCode = this.$store.state.userInfo.schoolCode;
+				this.evaluationInfo.paperInfo[0] = fullPaper;
+				this.evaluationInfo.papers[0] = simplePaper;
+				this.goToPreview();
+			},
+
+			/**
+			 * 将日期控件时间格式转成时间戳
+			 * @param value
+			 * @param date
+			 */
+			getDate(value, flag) {
+				if (flag == 0) {
+					this.startTime = value;
+					this.evaluationInfo.startTime = new Date(value).getTime();
+					if (this.evaluationInfo.startTime >= this.evaluationInfo.endTime) {
+						this.endTime = undefined;
+						this.evaluationInfo.endTime = undefined;
+					}
+				} else if (flag == 1) {
+					if (value.indexOf("00:00") > 0) {
+						value = value.replace("00:00", "23:59:59");
+					}
+					this.endTime = value;
+					this.evaluationInfo.endTime = new Date(value).getTime();
+				}
+			},
+			goToPreview() {
+				this.activeTab = "preview";
+			},
+			consData() {
+				console.log("evaluationInfo", this.evaluationInfo);
+			},			
+			async saveEvaluation() {
+				//表单验证
+				let flag = true;
+				this.$refs["evaForm"].validate((valid) => {
+					if (!valid) {
+						this.$Message.warning(this.$t("learnActivity.createEv.formWarning"));
+						flag = false;
+					}
+				});
+				if (!flag) {
+					return;
+				}
+				//检查试卷是否添加
+				if (this.evaluationInfo.papers.length < 1) {
+					this.$Message.warning({
+						content: this.$t("learnActivity.createEv.paperWarning"),
+						duration: 2
+					});
+					flag = false;
+				}
+				if (!flag) {
+					return;
+				}
+				let examId = this.$tools.guid();
+				let apiPapers = this.getPaperInfo(examId);
+				let requestData = {
+					jointEventId: this.$route.params.data.id,
+					jointGroupId: this.$route.params.jointGroupId,
+					jointScheduleId: this.$route.params.jointScheduleId,
+					jointExamId: "",
+					creatorId: this.$route.params.data.creatorId,
+					name: this.evaluationInfo.name,
+					source: this.evaluationInfo.source,
+					papers: apiPapers
+				}
+				//发布成功需要备份试卷数据
+				
+				let privateSas = {};
+				if (this.$store.state.user.userProfile) {
+					let blobInfo = this.$store.state.user.userProfile;
+					privateSas.sas = "?" + blobInfo.blob_sas;
+					privateSas.url = blobInfo.blob_uri.slice(0, blobInfo.blob_uri.lastIndexOf(this.$store.state.userInfo.TEAMModelId) - 1);
+					privateSas.name = this.$store.state.userInfo.TEAMModelId;
+				}
+
+				let schoolSas = {};
+				if (this.$store.state.userInfo.hasSchool) {
+					schoolSas = {
+						sas: "?" + this.$store.state.user.schoolProfile.blob_sas,
+						//url: this.$store.state.user.schoolProfile.blob_uri.slice(0, this.$store.state.user.schoolProfile.blob_uri.lastIndexOf(this.$store.state.userInfo.schoolCode) - 1),
+						url: this.$store.state.user.schoolProfile.blob_uri.slice(0, this.$store.state.user.schoolProfile.blob_uri.lastIndexOf("/")),
+						name: this.$store.state.userInfo.schoolCode
+					};
+				}
+				//校本课程复制到学校容器 个人课程复制到个人容器
+				let targetBlob = undefined;
+				if (this.evaluationInfo.scope == "school") {
+					targetBlob = new BlobTool(schoolSas.url, schoolSas.name, schoolSas.sas, "school");
+				} else {
+					targetBlob = new BlobTool(privateSas.url, privateSas.name, privateSas.sas, "private");
+				}
+				let privateBlob = new BlobTool(privateSas.url, privateSas.name, privateSas.sas, "private");
+				let schoolBlob = undefined;
+				let targetFolder = "jointexam/" + examId + "/paper/";
+				let count = 0;
+				requestData.papers.forEach(async (item, index) => {
+					if (item.blobUrl.indexOf("/exam/") == 0) {
+						if (++count == requestData.papers.length) {
+							this.$Message.success(this.$t("learnActivity.createEv.publishOk"));
+							this.isLoading = false;
+							// let route = this.mode + 'Evaluation'
+							this.$router.push({
+								name: "htMgtExam",
+								params: {
+									data: this.$route.params.data
+								}
+							});
+						}
+						return;
+					}
+					// 挑选的是校本试卷
+					if (item.scope == "school") {
+						if (!schoolBlob) schoolBlob = new BlobTool(schoolSas.url, schoolSas.name, schoolSas.sas, "school");
+						// 將公用試卷複製一份到該評量的位置
+						targetBlob
+							.copyFolder(targetFolder + requestData.papers[0].id + "/", item.blobUrl.substring(1), schoolBlob)
+							.then()
+							.finally(() => {
+								if (++count == requestData.papers.length) {
+									requestData.jointExamId = examId;
+									this.upsertData(requestData);
+								}
+							});
+					}
+					//挑选的是个人试卷
+					else if (item.scope == "private") {
+						if (!privateBlob) privateBlob = new BlobTool(privateSas.url, privateSas.name, privateSas.sas, "private");
+						// 將公用試卷複製一份到該評量的位置
+						targetBlob
+							.copyFolder(targetFolder + requestData.papers[0].id + "/", item.blobUrl.substring(1), privateBlob)
+							.then()
+							.finally(() => {
+								if (++count == requestData.papers.length) {// 上傳blob成功
+									requestData.jointExamId = examId;
+									this.upsertData(requestData);
+								}
+							});
+					}
+				});
+
+			},
+			// 呼叫寫入API 
+			upsertData(requestData){
+				this.$api.htcommunity.jointExamUpsert(requestData).then(// 呼叫API寫入評量
+					(res) => {
+						this.isComplete = true;
+						if (res.err === "") {
+							this.$Message.success(this.$t("learnActivity.createEv.publishOk"));
+							this.isLoading = false;
+							let route = this.mode + 'Evaluation'
+							this.$router.push({
+								name: "htMgtExam",
+								params: {
+									data: this.$route.params.data
+								}
+							});							
+						} else {						
+							// this.$Message.error('API ERROR!')
+							this.$Message.error(this.$t("learnActivity.mark.saveErr"));
+							this.isLoading = false;
+							return;
+						}
+					},
+					(err) => {
+						this.$Message.error(this.$t("learnActivity.mgtScEv.updErr"));
+					})		
+			},
+			//拼接API需要的paper数据
+			getPaperInfo(examId) {				
+				let data = this.evaluationInfo.papers;
+				let rule = this.evaluationInfo.paperInfo;
+				if (data) {
+					let paperDto = [];
+					let typeArr = ["single", "multiple", "judge"];
+					if (this.evaluationInfo.isCompletion) {
+						typeArr.push("complete");
+					}
+					for (let i = 0; i < data.length; i++) {
+						if (data[i].blob.indexOf("/exam/") == 0) {
+							paperDto.push(data[i]);
+						} else {
+							let paper = {};
+							paper.id = data[i].id;
+							paper.code = data[i].code;
+							paper.name = data[i].name;
+							paper.blob = "/jointexam/" + examId + "/paper/" + data[i].id;// 公用試卷庫的blob位置							
+							paper.blobUrl = data[i].blob;// 新增評量試卷放的blob位置
+							paper.scope = data[i].scope;
+							paper.sheet = data[i].sheet;
+							paper.periodId = data[i].periodId;
+							paper.multipleRule = rule[i].multipleRule;
+							paper.answers = [];
+							paper.point = [];
+							paper.knowledge = [];
+							paper.field = [];
+							paper.type = []; //后面新增字段, 保存每个题目类型
+							for (let k = 0; k < rule[i].item.length; k++) {
+								// scoring中只有客观题答案,这里改为从题目中获取客观题和填空题的答案
+								if (rule[i].item[k].children.length) {
+									for (let m = 0; m < rule[i].item[k].children.length; m++) {
+										paper.answers.push(typeArr.includes(rule[i].item[k].children[m].type) ? (rule[i].item[k].children[m].answer ? rule[i].item[k].children[m].answer : []) : []);
+										paper.point.push(rule[i].item[k].children[m].score);
+										paper.knowledge.push(rule[i].item[k].children[m].knowledge ? rule[i].item[k].children[m].knowledge : []);
+										paper.field.push(rule[i].item[k].children[m].field ? rule[i].item[k].children[m].field : []);
+										paper.type.push(rule[i].item[k].children[m].type); //后面新增字段, 保存每个题目类型
+									}
+								} else {
+									paper.answers.push(typeArr.includes(rule[i].item[k].type) ? (rule[i].item[k].answer ? rule[i].item[k].answer : []) : []);
+									paper.point.push(rule[i].item[k].score);
+									paper.knowledge.push(rule[i].item[k].knowledge ? rule[i].item[k].knowledge : []);
+									paper.field.push(rule[i].item[k].field ? rule[i].item[k].field : []);
+									paper.type.push(rule[i].item[k].type); //后面新增字段, 保存每个题目类型
+								}
+							}
+							/* for (let k = 0; k < rule[i].slides.length; k++) {
+                if (rule[i].slides[k].type !== 'compose') {
+                    paper.answers.push(rule[i].slides[k].scoring.ans ? rule[i].slides[k].scoring.ans : [])
+                    paper.point.push(rule[i].slides[k].scoring.score)
+                    paper.knowledge.push(rule[i].slides[k].scoring.knowledge ? rule[i].slides[k].scoring.knowledge : [])
+                    paper.field.push(rule[i].slides[k].scoring.field ? rule[i].slides[k].scoring.field : [])
+                    paper.type.push(rule[i].slides[k].type) //后面新增字段, 保存每个题目类型
+                }
+            } */
+							paper.subjectName = this.evaluationInfo.subjects && this.evaluationInfo.subjects.length ? this.evaluationInfo.subjects[0].name : "";
+							paper.subjectId = this.evaluationInfo.subjects && this.evaluationInfo.subjects.length ? this.evaluationInfo.subjects[0].id : "";
+							paperDto.push(paper);
+						}
+					}
+					return paperDto;
+				} else {
+					return [];
+				}
+			},
+			//复制或编辑评测初始化数据
+			async initData(data) {
+				let subjects = this._.cloneDeep(data.subjects);
+				data.id = "";
+				data.name = `${data.name}(${this.$t("learnActivity.mgtScEv.copy")})`;
+				this.startTime = new Date(data.startTime);
+				this.endTime = new Date(data.endTime);
+				let pp = {
+					"@DESC": "createTime",
+					code: data.papers[0].code?.replace("Paper-", ""),
+					scope: data.papers[0].scope,
+					id: data.papers.map((item) => item.id)
+				};
+				data.paperInfo = [];
+				data.papers = [];
+				this.defTargets = data.targets;
+				this.defaultScope = data.scope;
+				data.publish = "0";				
+				this.evaluationInfo = data;
+				console.log(JSON.stringify(this.evaluationInfo));
+				try {
+					let paperInfo = await this.$api.learnActivity.FindExamPaper(pp);
+					if (!paperInfo.length) {
+						// pp.sc
+						paperInfo = await this.$api.learnActivity.FindExamPaper(pp);
+					}
+					for (let i = 0; i < paperInfo.papers.length; i++) {
+						let fullPaper = await this.$evTools.getFullPaper(paperInfo.papers[i]);
+						this.comfirmSelectPaper(paperInfo.papers[i], fullPaper);
+					}
+					this.evaluationInfo.subjects = subjects;
+				} catch (e) {}
+				this.activeTab = "preview";
+				this.endTime = new Date(new Date(new Date().toLocaleDateString()).getTime() + 2 * 24 * 60 * 60 * 1000 - 1);
+				this.evaluationInfo.endTime = new Date(new Date().toLocaleDateString()).getTime() + 2 * 24 * 60 * 60 * 1000 - 1;
+				// data.id = ''
+				// data.name = `${data.name}(${this.$t('learnActivity.mgtScEv.copy')})`
+				// this.startTime = new Date(data.startTime)
+				// this.endTime = new Date(data.endTime)
+				// data.paperInfo = []
+				// this.defTargets = data.targets
+				// for (let i = 0; i < data.papers.length; i++) {
+				//     let paper = this._.cloneDeep(data.papers[i])
+				//     data.paperInfo.push(paper)
+				//     data.paperInfo[i].subjectId = data.subjects[i].id
+				//     data.paperInfo[i].subjectName = data.subjects[i].name
+				// }
+				// data.publish = '0'
+				// this.evaluationInfo = data
+				// this.activeTab = 'preview'
+			}
+		},
+		mounted(){
+			// 如果取不到活動資料則返回活動列表頁
+			if(!this.$route.params.data){
+				this.$router.push({
+						name: "htMgtHome"
+					});
+			}
+		},
+		created() {
+			// 处理默认时间
+			// this.startTime = new Date()
+			// this.evaluationInfo.startTime = new Date().getTime()
+			this.endTime = new Date(new Date(new Date().toLocaleDateString()).getTime() + 2 * 24 * 60 * 60 * 1000 - 1);
+			this.evaluationInfo.endTime = new Date(new Date().toLocaleDateString()).getTime() + 2 * 24 * 60 * 60 * 1000 - 1;
+			//判断创建个人还是校本评测
+			this.mode = "private";
+			//编辑评测逻辑
+			let routerData = this.$route.params.evaluationInfo;
+			if (routerData) {
+				// console.log(JSON.stringify(routerData))
+				console.log(routerData.subjects);
+				this.initData(routerData);
+			}
+		},
+		beforeRouteLeave(to, from, next) {
+			if (this.isComplete) {
+				if (to.name == "answerSheet") {
+					from.meta.isKeep = true;
+				} else {
+					from.meta.isKeep = false;
+				}
+				next();
+			} else {
+				this.$Modal.confirm({
+					title: this.$t("evaluation.newExercise.modalTip"),
+					content: this.$t("learnActivity.createEv.unSaveTip"),
+					cancelText: this.$t("auth.cancel"),
+					onOk: () => {
+						if (to.name == "answerSheet") {
+							from.meta.isKeep = true;
+						} else {
+							from.meta.isKeep = false;
+						}
+						next();
+					}
+				});
+			}
+		}
+	};
+</script>
+<style scoped lang="less">
+	@import "./CreatePrivEva.less";
+</style>
+<style lang="less">
+	.one-hidden-check-box {
+		.el-cascader-menu:nth-child(1) .el-checkbox {
+			display: none;
+		}
+	}
+	.teacher-preview-container .paper-main-wrap {
+		padding: 0px;
+		margin-top: 0px;
+	}
+	.evaluation-attr-wrap .ivu-form .ivu-form-item-label {
+		color: var(--second-text-color);
+	}
+
+	.evaluation-question-main .ivu-tabs-tab-active {
+		font-weight: 600;
+	}
+
+	.evaluation-question-main .ivu-tabs .ivu-tabs-content-animated {
+		height: 100%;
+		margin-bottom: 10px;
+	}
+
+	.evaluation-question-main .ivu-tabs-bar {
+		border-color: #404040;
+		margin-bottom: 0px;
+		border-bottom: none;
+	}
+	.evaluation-question-main .ivu-tabs.ivu-tabs-card .ivu-tabs-bar .ivu-tabs-tab {
+		margin-right: 2px;
+	}
+</style>

+ 145 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/tabs/htAnswerTable.less

@@ -0,0 +1,145 @@
+.data-count-wrap {
+    padding: 20px 0px;
+    display: flex;
+    background: white;
+    justify-content: space-between;
+    box-shadow: 0 0 10px 2px var(--card-shadow);
+}
+
+.data-count-item {
+    width: 150px;
+    text-align: center;
+
+    .data-value {
+        font-size: 30px;
+        font-weight: 600;
+        color: #17233d;
+    }
+}
+
+.table-data-wrap {
+    width: 100%;
+    box-shadow: 0 0 10px 2px var(--card-shadow);
+    margin-top: 10px;
+    // min-height: 600px;
+    min-height: ~"calc(100% - 118px)";
+    background: white;
+    padding: 10px 10px 60px 10px;
+}
+
+.ev-target-box {
+    color: var(--label-text-color);
+    padding: 10px 10px 10px 0;
+    position: sticky;
+    top: 0px;
+    background: white;
+    overflow: hidden;
+
+    .filter-select {
+        display: inline-block;
+        width: 120px;
+        margin-right: 25px;
+    }
+}
+
+.export-btn {
+    float: right;
+    margin-left: 20px;
+    margin-top: 5px;
+}
+
+.header-tips {
+    color: #515a6e;
+    float: right;
+    margin-top: 5px;
+}
+
+.stu-status-tag {
+    cursor: pointer;
+    background: #ed4014;
+    font-size: 12px;
+    padding: 3px 8px;
+    font-weight: 800;
+    border-radius: 4px;
+    color: white;
+}
+
+.score-box {
+    margin-top: 10px;
+}
+
+.page-wrap {
+    float: right;
+    margin-top: 15px;
+}
+
+.common-icon-text {
+    color: var(--primary-text-color);
+    cursor: pointer;
+    user-select: none;
+    float: right;
+    margin-right: 11px;
+}
+
+.mark-view-header {
+    top: 0px;
+    z-index: 9;
+    padding: 15px;
+    color: var(--label-text-color);
+    position: sticky;
+    top: 0px;
+    background: white;
+    overflow:visible;
+
+    .filter-select {
+        display: inline-block;
+        width: 120px;
+        margin-right: 25px;
+    }
+}
+
+.select-status-tag {
+    display: inline-block;
+    width: 7px;
+    height: 7px;
+    border-radius: 50%;
+    margin-right: 5px;
+}
+
+.qu-type-tag {
+    background: #2db7f5;
+    padding: 0px 4px;
+    color: white;
+    border-radius: 2px;
+    width: fit-content;
+    word-break: keep-all;
+    height: fit-content;
+}
+
+.correct-tips {
+    width: 300px;
+}
+
+.chart-wrap {
+    display: flex;
+    // align-items: center;
+}
+
+.correct-tips-label {
+    color: black;
+    margin-bottom: 15px;
+    font-weight: 600;
+}
+
+.stu-info {
+    margin-right: 30px;
+    font-size: 16px;
+}
+
+.stu-value {
+    font-weight: 600;
+}
+
+.stu-label {
+    color: #808695;
+}

ファイルの差分が大きいため隠しています
+ 1490 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/tabs/htAnswerTable.vue


+ 106 - 0
TEAMModelOS/ClientApp/src/view/learnactivity/tabs/htExamPaper.vue

@@ -0,0 +1,106 @@
+<template>
+    <div class="exam-paper-container">        
+        <vuescroll ref="exam-paper-wrap" @handle-scroll="checkBackTop">
+            <div class="subjects-wrap" v-if="examInfo && examInfo.subjects && examInfo.owner == 'school' && !examInfo.examPaperErr">
+                <span>{{$t('learnActivity.mgtScEv.evSubject')}}</span>
+                <RadioGroup v-model="curSubIndex" type="button" button-style="solid">
+                    <Radio :label="index" :key="item.id" v-for="(item,index) in examInfo.subjects">
+                        {{item.name}}
+                    </Radio>
+                </RadioGroup>
+            </div>            
+            <div class="paper-wrap" v-if="!examInfo.examPaperErr">                
+                <TestPaper v-if="examInfo && examInfo.papers && examInfo.papers[curSubIndex] && examInfo.papers[curSubIndex].item" 
+                :paper="examInfo.papers[curSubIndex]" style="color:#515a6e;" :isShowTools="false" isExamPaper isExamInfoPaper :examId="examInfo.id" :activityIndex="activityIndex" :subjectIndex="curSubIndex" :refreshExam="refreshExam" canFix
+                :jointGroupId="examInfo.jointGroupId" :jointScheduleId="examInfo.jointScheduleId"
+                ></TestPaper>                
+                <EmptyData v-else style="padding-top:60px;" :textContent="$t('learnActivity.simple.paperErr')"></EmptyData>                
+            </div>
+            <div v-else class="paper-err-wrap">                
+                <EmptyData :top="0" style="padding-top:60px;" :textContent="$t('learnActivity.simple.paperErr')"></EmptyData>                
+            </div>
+        </vuescroll>
+        <BackToTop @on-to-top="handleToTop" v-show="showBack"></BackToTop>
+    </div>
+</template>
+<script>
+import TestPaper from '@/view/evaluation/index/htTestPaper.vue'
+export default {
+    components: {
+        TestPaper
+    },
+    props: {
+        examInfo: {
+            type: Object,
+            default: () => {
+                return {}
+            }
+        },
+        activityIndex: {
+            type: Number,
+            default: 0
+        },
+        refreshExam: {
+            type: Function,
+            require: true,
+            default: null
+        },
+    },
+    data() {
+        return {
+            showBack: false,
+            curSubIndex: 0,
+            curSubject: '',
+            subjects: [
+                {
+                    name: '语文',
+                    id: '1'
+                },
+                {
+                    name: '数学',
+                    id: '2'
+                }
+            ]
+        }
+    },
+    created(){
+        //debugger
+        console.log('ssss', this.examInfo)
+    },
+    methods: {
+        //返回顶部
+        handleToTop() {
+            this.$refs['exam-paper-wrap'].scrollTo(
+                {
+                    y: '0'
+                },
+                300
+            )
+        },
+        /**
+         * 判断是否显示回到顶部按钮
+         * @param vertical
+         * @param horizontal
+         * @param nativeEvent
+         */
+        checkBackTop(vertical, horizontal, nativeEvent) {
+            if (vertical.scrollTop > 100) {
+                this.showBack = true
+            } else {
+                this.showBack = false
+            }
+        },
+    }
+}
+</script>
+<style lang="less" scoped>
+@import "./ExamPaper.less";
+</style>
+<style lang="less">
+.exam-paper-container .__view {
+    padding: 10px;
+}
+.exam-paper-container .paper-main-wrap {
+    margin-top: 0px;
+}
+</style>