Sfoglia il codice sorgente

Merge branch 'develop' of http://163.228.141.122:3000/TEAMMODEL/TEAMModelOS into develop

CrazyIter_Bin 9 mesi fa
parent
commit
9f72a3f791

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

@@ -1987,7 +1987,9 @@ const LANG_EN_US = {
             addSuc: 'Added successfully!',
             addFail: 'Failed to add!',
             numMax1: 'Maximum linking of ',
-            numMax2: 'key concept'
+            numMax2: 'key concept',
+            addLevel: 'Add to the current level',
+            addLevelOne: 'Add to the outermost level',
         },
         echarts: {
             pointPie: 'Key Concept Distribution',

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

@@ -1986,7 +1986,9 @@ const LANG_ZH_CN = {
             addSuc: '添加成功!',
             addFail: '添加失败!',
             numMax1: '最多绑定',
-            numMax2: '个知识点'
+            numMax2: '个知识点',
+            addLevelOne: '添加到最外层',
+            addLevel: '添加到当前层级下'
         },
         echarts: {
             pointPie: '试卷知识点分析图',

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

@@ -1989,7 +1989,9 @@ const LANG_ZH_TW = {
             addSuc: '新增成功!',
             addFail: '新增失敗!',
             numMax1: '最多關聯',
-            numMax2: '個知識點'
+            numMax2: '個知識點',
+            addLevel: '新增到目前層級下',
+            addLevelOne: '新增到最外層',
         },
         echarts: {
             pointPie: '試卷知識點分佈圖',

+ 180 - 44
TEAMModelOS/ClientApp/src/view/evaluation/components/BasePoints.vue

@@ -2,7 +2,18 @@
   <div class="points-container">
     <!-- <Button type="info" class="btn-add-point" @click="addPointsModal = true"
 			v-show="curScope === 'school'">{{$t('evaluation.points.addPoint')}}</Button> -->
-    <div class="filter-wrap">
+    <div v-if="curScope != 'school'" style="margin-bottom: 10px;">
+      <span class="manual-filter-label">{{ $t('evaluation.filter.origin') }}:</span>
+      <RadioGroup v-model="radioCode" @on-change="onCodeChange">
+            <Radio label="private">
+                <span>{{ $t('cusMgt.private') }}</span>
+            </Radio>
+            <Radio label="school">
+                <span>{{ $t('cusMgt.school') }}</span>
+            </Radio>
+      </RadioGroup>
+    </div>
+    <div class="filter-wrap" v-if="radioCode === 'school'">
       <Select v-model="selectPeriod" @on-change="onPeriodChange" :disabled="curScope === 'school'">
         <Option v-for="(item, index) in periodList" :value="item.id" :key="index">{{ item.name }}</Option>
       </Select>
@@ -11,6 +22,12 @@
         <Option v-for="(item, index) in subjectList" :value="item.id" :key="index">{{ item.name }}</Option>
       </Select>
     </div>
+    <div class="filter-wrap" v-else>
+      <Select v-model="selectTree" @on-change="getPoints">
+        <Option v-for="(item, index) in treeList" :value="item.id" :key="index">{{ item.name }}</Option>
+      </Select>
+      <Icon type="md-add-circle" color="#40A8F0" size="16" :title="$t('knowledge.addPoint')" style="cursor:pointer; margin-left: 5px;" @click="getKnowledgeTree()" />
+    </div>
 
     <div style="margin-top: 20px;">
       <Loading hideMask v-show="isLoading"></Loading>
@@ -33,10 +50,23 @@
 
     <Modal v-model="addPointsModal" :title="$t('evaluation.points.addPoint')" ref="pointRef" width="400px" class="related-point-modal" style="z-index:99999">
       <span>{{$t('evaluation.points.pointName')}}</span>
-      <Input v-special-char v-model="newPointName" :placeholder="$t('evaluation.points.inputNewPoint')" style="margin:10px 0" />
+      <span style="display: flex; align-items: center;">
+        <Input v-special-char v-model="newPointName" :placeholder="$t('evaluation.points.inputNewPoint')" style="margin:10px 0" />
+        <Button type="primary" @click="onAddNewPoint" style="margin-left: 10px;">{{ $t('evaluation.points.addLevelOne') }}</Button>
+      </span>
+      <el-tree :data="knowledgeTree" :props="defaultProps" class="tree" node-key="id" :expand-on-click-node="false" check-on-click-node highlight-current accordion ref="pointTree">
+          <span class="custom-tree-node" slot-scope="{ node, data }">
+              <span class="tree-node-lable">
+                  <span class="text-cut" style="max-width: 60%;display: inline-block;vertical-align: bottom;" :title="data.name">{{ data.name }}</span>
+              </span>
+              <span class="custom-tree-tools">
+                  <Icon type="md-add" :title="$t('evaluation.points.addLevel')" v-if="node.level < 4" @click.stop="onAddPoint(node, data)" />
+              </span>
+          </span>
+      </el-tree>
       <div slot="footer">
         <Button type="text" @click="addPointsModal = false">{{$t('evaluation.cancel')}}</Button>
-        <Button type="primary" @click="onAddNewPoint" :loading="isAddLoading">{{$t('evaluation.confirm')}}</Button>
+        <Button type="primary" @click="onSureAdd" :loading="isAddLoading">{{ $t('cusMgt.save') }}</Button>
       </div>
     </Modal>
   </div>
@@ -88,23 +118,33 @@ export default {
         id: '0',
         name: '0'
       }],
+      treeList: [],
+      selectTree: 0,
       pointList: [],
-      schoolPointList: [],
+      schoolPointList: [], //展示的知识点
       checkedList: [],
-      originPointList: [],
-      originSchoolList: [],
+      originPointList: [], //所有的知识点
+      originSchoolList: [], //所有的知识点
       originList: [],
       defaultParams: {
         code: '',
         periodId: null,
         subjectId: null,
         school_code: null,
-        type: 1
+        type: 1 
+      },
+      curPointResponse: null,
+      radioCode: '',
+      knowledgeTree: [],
+      defaultProps: {
+          children: 'children',
+          label: 'name'
       },
-      curPointResponse: null
     }
   },
   created() {
+    // this.radioCode = this.scope === 'school' ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId
+    this.radioCode = this.scope
     console.log('period-' + this.period)
     console.log('subject-' + this.subject)
     console.log('scope-' + this.scope)
@@ -113,7 +153,12 @@ export default {
       this.selectSubject = this.subject
     }
     this.initSchoolData()
-    this.getPoints()
+    // 个人需先获取到知识点树列表,再获取相关的知识点
+    if(this.scope === 'private') {
+      this.getPointList()
+    } else {
+      this.getPoints()
+    }
   },
   methods: {
     // 获取当前学校学段学科等基本信息
@@ -146,67 +191,125 @@ export default {
     onSubjectChange(val) {
       this.getPoints()
     },
+    onCodeChange(val) {
+      this.searchSchoolPoint = ''
+      this.checkedList = []
+      this.getPoints()
+    },
 
     doReset() {
       this.getPoints()
       this.checkedList = []
     },
+    /**
+     * 获取个人知识点树列表
+     */
+    getPointList() {
+        this.isLoading = true
+        let params = {
+            scope: 'private' 
+        }
+        this.$api.knowledge.getPointList(params).then(res => {
+            if(res.datas && res.datas.length) {
+                this.selectTree = res.datas[0].id
+                this.treeList = res.datas
+                if(res.datas.length) this.getPoints()
+            }
+        }).finally(() => {
+            this.isLoading = false
+        })
+    },
 
     /**
      * 获取知识点仓库数据
      */
     getPoints() {
+      this.isLoading = true
       if (this.periodList.length && this.subjectList.length) {
-        this.isLoading = true
         // if (this.pointList.length && this.schoolPointList.length) return
         this.defaultParams.code = this.$store.state.userInfo.schoolCode
         this.defaultParams.school_code = this.$store.state.userInfo.schoolCode
         this.defaultParams.periodId = this.selectPeriod
         this.defaultParams.subjectId = this.selectSubject
+      }
+      let params = this.radioCode === 'school' ? this.defaultParams : {
+        scope: 'private',
+        kid: this.selectTree,//不填,则返回该教师的所有知识点树的信息
+        owner: this.$store.state.userInfo.TEAMModelId,
+      }
 
-        if (this.defaultParams.periodId && this.defaultParams.subjectId) {
-          this.$api.knowledge.GetSchoolPoints(this.defaultParams).then(res => {
-            if (!res.error && res.length) {
-              this.curPointResponse = res[0]
-              this.schoolPointList = res[0].points
-              this.originSchoolList = res[0].points
-              this.originPointList = this.originPointList.concat(res[0].points)
-            } else {
-              this.$Message.warning(this.$t('evaluation.noData'),)
-              this.uuid = Math.uuid()
-              this.schoolPointList = []
-              this.originSchoolList = []
-              this.originPointList = []
-              this.curPointResponse = {
-                blocks: [],
-                code: `Knowledge-${this.$store.state.userInfo.schoolCode}-${this.uuid}`,
-                id: this.uuid,
-                owner: this.$store.state.userInfo.schoolCode,
-                periodId: this.defaultParams.periodId,
-                pk: 'Knowledge',
-                points: [],
-                scope: 'school',
-                subjectId: this.defaultParams.subjectId
-              }
+      if (this.radioCode === 'school' ? this.defaultParams.periodId && this.defaultParams.subjectId : true) {
+        this.$api.knowledge.GetSchoolPoints(params).then(res => {
+          if (!res.error && res.length) {
+            this.curPointResponse = res[0]
+            this.schoolPointList = res[0].points
+            this.originSchoolList = res[0].points
+            this.originPointList = this.originPointList.concat(res[0].points)
+          } else {
+            this.$Message.warning(this.$t('evaluation.noData'),)
+            this.uuid = Math.uuid()
+            this.schoolPointList = []
+            this.originSchoolList = []
+            this.originPointList = []
+            this.curPointResponse = {
+              blocks: [],
+              code: `Knowledge-${this.$store.state.userInfo.schoolCode}-${this.uuid}`,
+              id: this.uuid,
+              owner: this.$store.state.userInfo.schoolCode,
+              periodId: this.defaultParams.periodId,
+              pk: 'Knowledge',
+              points: [],
+              scope: 'school',
+              subjectId: this.defaultParams.subjectId
             }
-            this.isLoading = false
-          })
-        }
-        this.isLoading = true
+          }
+          this.isLoading = false
+        })
       }
+      this.isLoading = true
 
 
     },
 
     /** 添加新知识点 */
     onAddNewPoint() {
-      let newName = this.newPointName
-      if (newName) {
-        this.curPointResponse.points.push(newName)
-        this.savePoint()
-      } else {
-        this.$Message.warning(this.$t('evaluation.points.noNameTips'))
+      this.knowledgeTree.push({
+        allcids: [],
+        children: [],
+        id: this.knowledgeTree.length ? (Number(this.knowledgeTree[this.knowledgeTree.length - 1].id) + 1).toString() : '1',
+        level: 1,
+        link: 0,
+        name: this.newPointName,
+        pid: this.selectTree,
+        subcids: [],
+        tid: null,
+        used: 0
+      })
+      this.newPointName = ''
+    },
+    onSureAdd() {
+      let params = {
+          knowledgeTree: {
+              id: this.selectTree,
+              owner: this.$store.state.userInfo.TEAMModelId,
+              scope: 'private',
+              periodId: '',
+              subjectId: '',
+              name: this.treeList.find(item => item.id === this.selectTree).name,
+              tree: this.knowledgeTree || [],
+          }
       }
+      this.$api.knowledge.upsertPoint(params).then(res => {
+          if(res.knowledgeTree) {
+              this.$Message.success(this.$t('knowledge.saveSuccess'))
+              this.getPoints()
+              this.addPointsModal = false
+          } else {
+              this.$Message.warning(this.$t('knowledge.saveFail'))
+          }
+      }).catch(err => {
+          this.$Message.error(this.$t('knowledge.saveFail'))
+      })
     },
 
     /**
@@ -258,10 +361,43 @@ export default {
     onSearchSchoolChange() {
       this.schoolPointList = this.originSchoolList.filter(item => item.toUpperCase().indexOf(this.searchSchoolPoint.toUpperCase()) > -1 || item.toLowerCase().indexOf(this.searchSchoolPoint.toLowerCase()) > -1 || item.indexOf(this.searchSchoolPoint) > -1)
     },
+    getKnowledgeTree() {
+      let params = {
+          periodId: '',
+          scope: 'private',
+          school_code: '',
+          id: this.selectTree
+      }
+      this.$api.knowledge.getPointInfo(params).then(res => {
+        if(res.knowledgeTrees) {
+          this.knowledgeTree = res.knowledgeTrees.length ? res.knowledgeTrees[0]?.tree : []
+          this.addPointsModal = true
+        }
+      })
+    },
+    // 新增知识点事件
+    onAddPoint(node, data) {
+        let idLast2 = data.children.length ? data.children[data.children.length - 1].id : '-0'
+        let id2 = idLast2.split(`-`)
+        data.children.push({
+          allcids: [],
+          children: [],
+          id: `${data.id}-${Number(id2[id2.length - 1]) + 1}`,
+          level: 1,
+          link: 0,
+          name: this.newPointName,
+          pid: data.id,
+          subcids: [],
+          tid: null,
+          used: 0
+        })
+        this.newPointName = ''
+    },
   },
   mounted() {
     if (this.points.length) {
       this.checkedList = this.points
+      // this.radioCode = this.radioCode === 'private' && this.schoolPointList.includes(this.checkedList[0]) ? 'private' : 'school'
     }
     this.curScope = this.scope
   },

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

@@ -177,6 +177,7 @@
                 <el-table-column prop="creatorId" :label="this.$t('htcommunity.tmid')" min-width="50"></el-table-column>
                 <el-table-column prop="courseName" :label="this.$t('htcommunity.course')" min-width="50"></el-table-column>
                 <el-table-column prop="groupName" :label="this.$t('htcommunity.courseGroup')" min-width="50"></el-table-column>
+                <el-table-column prop="createTime" :label="this.$t('htcommunity.jointTime')" min-width="50"></el-table-column>
             </el-table>
         </el-dialog>
     </div>
@@ -466,6 +467,7 @@ export default {
                                   c.groupLists.forEach((g) => {
                                       courseGroupId = g.id;
                                       courseGroupName = g.name;
+                                      let createTimeYmd = new Date(item.createTime).toLocaleString('en-US', { hour12: false }).split(" ");
                                       //資料生成
                                       let jointCourseRow = {
                                           id: item.id,
@@ -480,6 +482,7 @@ export default {
                                           courseName: courseName,
                                           groupId: courseGroupId,
                                           groupName: courseGroupName,
+                                          createTime: this.timeCycle(createTimeYmd),
                                       }
                                       this.joinTeacherCourseArr.push(jointCourseRow);
                                       index++;
@@ -502,8 +505,8 @@ export default {
       exportExcel(type) {
         //老師報名資料
           if (type == 'teacherCourse') {
-              let titles = [this.$t('htcommunity.jointGroup'), this.$t('htcommunity.schoolName'), this.$t('htcommunity.teacherName'), this.$t('htcommunity.tmid'), this.$t('htcommunity.course'), this.$t('htcommunity.courseGroup')];
-              let keys = ['jointGroupName', 'schoolName', 'creatorName', 'creatorId', 'courseName', 'groupName'];
+              let titles = [this.$t('htcommunity.jointGroup'), this.$t('htcommunity.schoolName'), this.$t('htcommunity.teacherName'), this.$t('htcommunity.tmid'), this.$t('htcommunity.course'), this.$t('htcommunity.courseGroup'), this.$t('htcommunity.jointTime')];
+              let keys = ['jointGroupName', 'schoolName', 'creatorName', 'creatorId', 'courseName', 'groupName', 'createTime'];
               const params = {
                   title: titles,
                   key: keys,
@@ -803,6 +806,21 @@ export default {
                 break
         }
     },
+    //时间转换
+    timeCycle(times) {
+        let time = times[1]
+        let mdy = times[0]
+        mdy = mdy.split('/')
+        let month = parseInt(mdy[0]);
+        let day = parseInt(mdy[1]);
+        let year = parseInt(mdy[2])
+        if (year == 1970 && month == 1 && day == 1) {
+            return '--'
+        }
+        else {
+            return year + '-' + month + '-' + day + ' ' + time
+        }
+    },
   },
   created () {
     this.twCityArr = option_gl[0].children;      

+ 5 - 4
TEAMModelOS/ClientApp/src/view/learnactivity/ByQuMark.vue

@@ -3,7 +3,7 @@
         <Loading :top="200" type="1" style="text-align:center" v-show="dataLoading"></Loading>
         <div class="scoring-paper-header">
             <!-- 保存分数 -->
-            <span :class="['base-info-btn',isUpd ? 'base-info-btn-active' : '']" type="success" @click="saveScore" style="margin-right:25px">
+            <span v-if="!examInfo.isJointExam || examInfo.jointExamType!='custom'" :class="['base-info-btn',isUpd ? 'base-info-btn-active' : '']" type="success" @click="saveScore" style="margin-right:25px">
                 <Icon type="ios-albums-outline" />
                 {{$t('learnActivity.score.saveScore')}}
             </span>
@@ -18,12 +18,12 @@
                 {{ showQu ? $t('learnActivity.score.hideQu') : $t('learnActivity.score.showQu')}}
             </span>
             <!-- 全部满分 -->
-            <span class="base-info-btn" @click="batchScore(questionInfo.score)">
+            <span v-if="!examInfo.isJointExam || examInfo.jointExamType!='custom'" class="base-info-btn" @click="batchScore(questionInfo.score)">
                 <Icon type="ios-create" />
                 {{$t('learnActivity.score.fastScore1')}}
             </span>
             <!-- 全部零分 -->
-            <span class="base-info-btn" @click="batchScore(0)">
+            <span v-if="!examInfo.isJointExam || examInfo.jointExamType!='custom'" class="base-info-btn" @click="batchScore(0)">
                 <Icon type="ios-create" />
                 {{$t('learnActivity.score.fastScore2')}}
             </span>
@@ -98,7 +98,8 @@
         <div class="answer-wrap">
             <div @click="stuIndex = index" :class="['stu-ans-item',stuIndex === index ? 'stu-ans-item-active':'']" v-for="(item,index) in studentsData" :key="item.id+index">
                 <!-- 打分区域 -->
-                <div class="set-score-box">
+                <div v-if="examInfo.isJointExam && examInfo.jointExamType=='custom'" class="set-score-box"></div>
+                <div v-else class="set-score-box">
                     <template v-if="item.data">
                         <InputNumber @on-change="setUpdStatus(item)" v-model="item.data[quIndex]" :formatter="value => value < 0 ? '' : `${value}${$t('learnActivity.score.scoreUnit')}`" :parser="value => value.replace($t('learnActivity.score.scoreUnit'), '')" :min="0" :max="questionInfo.score" :placeholder="$t('learnActivity.score.zeroScore1')" style="width:60px" />
                     </template>

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

@@ -14,17 +14,17 @@
           </span>
         </span>
         <!-- 保存分数 -->
-        <span :class="['base-info-btn', isUpd ? 'base-info-btn-active' : '']" type="success" @click="saveScore">
+        <span v-if="!examInfo.isJointExam || examInfo.jointExamType!='custom'" :class="['base-info-btn', isUpd ? 'base-info-btn-active' : '']" type="success" @click="saveScore">
           <Icon type="ios-albums-outline" />
           {{$t('learnActivity.score.saveScore')}}
         </span>
         <!-- 未阅满分 -->
-        <span class="base-info-btn" @click="batchScore('zero')">
+        <span v-if="!examInfo.isJointExam || examInfo.jointExamType!='custom'" class="base-info-btn" @click="batchScore('zero')">
           <Icon type="ios-create" />
           {{$t('learnActivity.score.fastScore4')}}
         </span>
         <!-- 未阅零分 -->
-        <span class="base-info-btn" @click="batchScore('full')">
+        <span v-if="!examInfo.isJointExam || examInfo.jointExamType!='custom'" class="base-info-btn" @click="batchScore('full')">
           <Icon type="ios-create" />
           {{$t('learnActivity.score.fastScore5')}}
         </span>
@@ -32,10 +32,12 @@
           <Icon type="md-eye" />
           {{$t('learnActivity.score.viewOrigin')}}
         </span>
+        <!-- 显示答案 -->
         <span class="base-info-btn" @click="config.showAnswer = !config.showAnswer">
           <Icon :type="config.showAnswer ? 'md-eye-off':'md-eye'" />
           {{ config.showAnswer ? $t('learnActivity.score.hideAns') : $t('learnActivity.score.showAns')}}
         </span>
+        <!-- 显示题目 -->
         <span class="base-info-btn" @click="config.showQu = !config.showQu">
           <Icon :type="config.showQu ? 'md-eye-off':'md-eye'" />
           {{ config.showQu ? $t('learnActivity.score.hideQu') : $t('learnActivity.score.showQu')}}
@@ -73,10 +75,10 @@
             </p>
             <div v-for="(quItem) in typeItem.list" :key="quItem.quNo">
               <template v-if="quItem.children && quItem.children.length">
-                <QuAndScore :ref="'QuAndScore'+ child.index" :stuMark="studentAnswer.mark[child.index]" @click.native="config.activeIndex = child.index" v-model="studentAnswer.scores[child.index]" v-for="(child) in quItem.children" :key="child.quNo" :stuAnswer="studentAnswer.stuAnswers[child.index]" :questionItem="child" :config="config" @on-save-mark="saveMark" @on-del-mark="delMark"></QuAndScore>
+                <QuAndScore :ref="'QuAndScore'+ child.index" :stuMark="studentAnswer.mark[child.index]" :examInfo="examInfo" @click.native="config.activeIndex = child.index" v-model="studentAnswer.scores[child.index]" v-for="(child) in quItem.children" :key="child.quNo" :stuAnswer="studentAnswer.stuAnswers[child.index]" :questionItem="child" :config="config" @on-save-mark="saveMark" @on-del-mark="delMark"></QuAndScore>
               </template>
               <template v-else>
-                <QuAndScore :ref="'QuAndScore'+ quItem.index" :stuMark="studentAnswer.mark[quItem.index]" @click.native="config.activeIndex = quItem.index" v-model="studentAnswer.scores[quItem.index]" :questionItem="quItem" :config="config" :stuAnswer="studentAnswer.stuAnswers[quItem.index]" @on-save-mark="saveMark" @on-del-mark="delMark"></QuAndScore>
+                <QuAndScore :ref="'QuAndScore'+ quItem.index" :stuMark="studentAnswer.mark[quItem.index]" :examInfo="examInfo" @click.native="config.activeIndex = quItem.index" v-model="studentAnswer.scores[quItem.index]" :questionItem="quItem" :config="config" :stuAnswer="studentAnswer.stuAnswers[quItem.index]" @on-save-mark="saveMark" @on-del-mark="delMark"></QuAndScore>
               </template>
             </div>
           </div>

+ 9 - 1
TEAMModelOS/ClientApp/src/view/learnactivity/byStu/QuAndScore.vue

@@ -1,7 +1,8 @@
 <template>
     <!-- 非综合题-->
     <div :class="['qu-score-item', config.activeIndex == questionItem.index ? 'active-qu-wrap':''] " :id="questionItem.quNo">
-        <div class="scoring-input-box" @click.stop>
+        <div v-if="examInfo.isJointExam && examInfo.jointExamType=='custom'" class="scoring-input-box" @click.stop></div>
+        <div v-else class="scoring-input-box" @click.stop>
             <InputNumber @on-change="updScore" v-model="score" size="small" :formatter="value => value < 0 ? '' : `${value}${$t('learnActivity.score.scoreUnit')}`" :parser="value => value.replace($t('learnActivity.score.scoreUnit'), '')" :min="0" :max="questionItem.score" :placeholder="$t('learnActivity.score.zeroScore1')" class="score-input" />
             <!-- 快速打分 满分 零分 -->
             <div style="display:flex;justify-content: space-evenly;margin-top:5px;">
@@ -194,6 +195,13 @@ export default {
                 }
             }
         },
+        //評量資訊
+        examInfo: {
+            type: Object,
+            default: () => {
+                return {}
+            }
+        },
         //学生分数
         value: {
             type: Number,

+ 6 - 6
TEAMModelOS/ClientApp/src/view/learnactivity/tabs/AnswerTable.vue

@@ -91,9 +91,7 @@
 					</template>
 					<!-- 1: 未作答 2:未评分 3:已评分 4:缺考 5:补考中 -->
 					<template slot-scope="{ row, index }" slot="status">
-						<span class="stu-status-tag" @click="getStuScore(row, 0)" :style="{ background: row.statusColor }">
-							{{ row.statusText }}
-						</span>
+						<span class="stu-status-tag" @click="getStuScore(row, 0)" :style="{ background: row.statusColor }">{{ row.statusText }}</span>
 					</template>
 					<Loading slot="loading" :top="-50"></Loading>
 				</Table>
@@ -339,8 +337,9 @@
 				paperInfo: {},
 				students: [],
 				routerScope: "",
-				isJointExam: false,
-                jointVisiable: false,
+				isJointExam: false, //是統測評量
+				jointVisiable: false, //統測評量是否可見
+                jointExamType: "", //統測評量類型
 			};
 		},
 		computed: {
@@ -496,7 +495,8 @@
 						}
 					);
                     this.isJointExam = (n.jointExamId && typeof n.jointExamId === "string" && n.jointExamId.length > 0) ? true : false
-                    this.jointVisiable = n.jointVisiable
+					this.jointVisiable = n.jointVisiable
+                    this.jointExamType = n.jointExamType
 				},
 				deep: true,
 				immediate: true

+ 35 - 3
TEAMModelOS/Controllers/Common/ExamController.cs

@@ -864,7 +864,6 @@ namespace TEAMModelOS.Controllers
                 List<ExamInfo> examInfo = new List<ExamInfo>();
                 await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIteratorSql(queryText: stringBuilder.ToString(), continuationToken: token, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout }))
                 {
-
                     using var json = await JsonDocument.ParseAsync(item.Content);
                     if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                     {
@@ -1087,7 +1086,8 @@ namespace TEAMModelOS.Controllers
                 if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
 
                 var client = _azureCosmos.GetCosmosClient();
-                List<ExamInfo> examInfo = new List<ExamInfo>();
+                List<ExamInfoEx> examInfo = new List<ExamInfoEx>();
+                List<string> jointExamIds = new List<string>();
                 //var query = $"select value(c) from c ";
                 await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIteratorSql(queryText: $"select value(c) from c where c.id = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
                 {
@@ -1097,10 +1097,37 @@ namespace TEAMModelOS.Controllers
                         foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                         {
                             //obj.TryGetProperty("progress", out JsonElement progress);
-                            examInfo.Add(obj.ToObject<ExamInfo>());
+                            ExamInfoEx exInfo = obj.ToObject<ExamInfoEx>();
+                            examInfo.Add(exInfo);
+                            if (!string.IsNullOrWhiteSpace(exInfo.jointExamId) && !jointExamIds.Contains(exInfo.jointExamId)) jointExamIds.Add(exInfo.jointExamId);
+                        }
+                    }
+                }
+                //加入統測資訊
+                List<JointExam> jointExams = new List<JointExam>();
+                if (jointExamIds.Count > 0)
+                {
+                    StringBuilder stringBuilderJointEx = new($"SELECT c.id, c.name, c.code, c.jointEventId, c.jointScheduleId, c.jointGroupId, c.creatorId, c.examType, c.progress FROM c WHERE ARRAY_CONTAINS({JsonSerializer.Serialize(jointExamIds)}, c.id, true) ");
+                    await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIteratorSql(queryText: stringBuilderJointEx.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"JointExam") }))
+                    {
+                        using var json = await JsonDocument.ParseAsync(item.Content);
+                        if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                        {
+                            foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                            {
+                                jointExams.Add(obj.ToObject<JointExam>());
+                            }
                         }
                     }
                 }
+                foreach (ExamInfoEx exinfo in examInfo)
+                {
+                    JointExam jointExamNow = jointExams.Where(j => !string.IsNullOrWhiteSpace(exinfo.jointExamId) && j.id.Equals(exinfo.jointExamId)).FirstOrDefault();
+                    if (jointExamNow != null)
+                    {
+                        exinfo.jointExamType = jointExamNow.examType;
+                    }
+                }
                 return Ok(new { examInfo });
             }
             catch (Exception e)
@@ -4879,4 +4906,9 @@ namespace TEAMModelOS.Controllers
         public string qId { get; set; }
         public string unitId { get; set; }
     }
+    //延伸ExamInfo 追加額外顯示欄位 (目前只有find使用)
+    public class ExamInfoEx : ExamInfo
+    {
+        public string jointExamType { get; set; }
+    }
 }

+ 1 - 0
TEAMModelOS/Controllers/Teacher/JointEventController.cs

@@ -1351,6 +1351,7 @@ namespace TEAMModelOS.Controllers.Common
             public string schoolName { get; set; } //老師教育雲綁定的學校名稱
             public string periodId { get; set; } //老師個人課程時為null
             public List<JointEventGroupCourseDto> courseLists { get; set; } = new();
+            public long createTime { get; set; }
             public class JointEventGroupCourseDto
             {
                 public string subjectId { get; set; } //老師個人課程時為null