소스 검색

Merge branch 'develop-rc' into hhb/develop-course

CrazyIter_Bin 2 년 전
부모
커밋
48a15bb7ff

+ 83 - 21
TEAMModelOS/ClientApp/src/view/assessment/ArtAssessment.less

@@ -1,9 +1,22 @@
+@level1Color: #085fec;
+@level2Color: #4398e3;
+@level3Color: #a6a6a6;
+
 .art-assessment-container {
     padding: 15px;
 
     .table-box {
         margin-top: 10px;
 
+        /deep/ .ivu-table td {
+            padding-top: 10px;
+            vertical-align: top;
+        }
+
+        .icon-edit {
+            cursor: pointer;
+        }
+
         .user-info-wrap {
             display: flex;
             align-items: center;
@@ -29,6 +42,25 @@
             }
         }
 
+        .level1-score {
+            display: flex;
+            justify-content: space-between;
+            align-items: center;
+            margin: 10px 0;
+        }
+
+        .icon-total {
+            display: inline-flex;
+            justify-content: center;
+            align-items: center;
+            border-radius: 100%;
+            padding: 0 5px;
+            background: @level2Color;
+            color: #fff;
+        }
+
+
+
         .quota-item {
             display: flex;
             flex-direction: column;
@@ -36,19 +68,21 @@
             .quota-name {
                 font-weight: bold;
                 margin: 10px 0;
-                color: #129cff;
+                color: @level2Color;
 
                 &::before {
                     content: '';
                     display: inline-block;
-                    border: 2px solid #129cff;
-                    height: 8px;
+                    border: 1px solid @level2Color;
+                    width: 8px;
+                    height: 2px;
+                    margin-bottom: 5px;
                     margin-right: 6px;
                 }
             }
 
             .quota-score {
-                color: #129cff;
+                color: @level2Color;
                 font-weight: bold;
             }
 
@@ -60,37 +94,65 @@
             }
         }
 
+        .first-level-score {
+
+            .quota-name {
+                color: @level1Color  !important;
+
+                &::before {
+                    content: '';
+                    display: inline-block;
+                    height: 6px;
+                    width: 6px;
+                    border: none;
+                    background: @level1Color;
+                    margin-bottom: 3px;
+                    margin-right: 6px;
+                }
+            }
+
+            .quota-score {
+                color: @level1Color  !important;
+            }
+        }
+
         .total-score {
-            font-size: 20px;
+            font-size: 16px;
+            color: red;
+            font-weight: bold;
+        }
+
+        .total-level {
+            font-size: 16px;
             color: red;
             font-weight: bold;
         }
 
+        .child-files {
+            display: flex;
+            flex-direction: column;
+            font-size: 14px;
+            color: @level3Color;
+
+            .file-item {
+                margin: 5px 0 5px 5px;
+                padding: 5px 0;
+                text-decoration: underline;
+                cursor: pointer;
+            }
+        }
+
         .child-item {
             display: flex;
             flex-direction: column;
             margin: 3px 0 10px 8px;
 
-            .child-files {
-                display: flex;
-                flex-direction: column;
-                font-size: 14px;
-                color: #838383;
-
-                .file-item {
-                    margin: 5px 0 5px 5px;
-                    padding: 5px 0;
-                    text-decoration: underline;
-                    cursor: pointer;
-                }
-            }
-
             .child-name {
-                color: rgb(154, 154, 154);
+                color: @level3Color;
             }
 
             .child-score {
-                color: rgb(154, 154, 154);
+                color: @level3Color;
             }
         }
     }

+ 209 - 83
TEAMModelOS/ClientApp/src/view/assessment/ArtAssessment.vue

@@ -20,10 +20,10 @@
         </Option>
       </Select>
       <!-- 搜索框 -->
-      <Input v-special-char v-model="searchVal" search :placeholder="$t('ability.place1')" style="width: 180px;margin-left: 15px;" @on-search="doFilter" @on-enter="doFilter" />
+      <Input v-special-char v-model="searchVal" search :placeholder="$t('ability.place1')" style="width: 180px;margin-left: 15px;" @on-search="doFilter" />
     </div>
     <div class="table-box">
-      <Table :columns="assessmentCol" :data="assessmentList" stripe border ellipsis :loading="tableLoading" ref="table" :max-height="tableHeight" :no-data-text="`当前条件下未匹配到学生数据`" @on-row-click="onRowClick">
+      <Table :columns="filterCols" :data="assessmentList" stripe border ellipsis :loading="tableLoading" ref="table" :max-height="tableHeight" :no-data-text="`当前条件下未匹配到学生数据`" @on-row-click="onRowClick">
         <!-- 学生基础信息 -->
         <template slot-scope="{ row,index }" slot="userInfo">
           <div class="user-info-wrap">
@@ -36,26 +36,27 @@
         </template>
         <!-- 基础指标 -->
         <template slot-scope="{ row,index }" slot="quota_1">
-          <!-- <p class="total-score">
-            <span class="title"></span>
-            <span class="score"></span>
-          </p> -->
           <div class="quota-item">
-            <div class="quota">
+            <div class="quota first-level-score">
               <span class="quota-name">指标总分</span>
-              <span class="quota-score">99分</span>
+              <span class="quota-score">{{ getQuotaScore('quota_1',row) }}</span>
             </div>
           </div>
-          <div class="quota-item" v-for="(quota,quotaIndex) in artSettings.quotas[0].children" :key="quotaIndex">
+          <div class="quota-item" v-for="(quota,quotaIndex) in artSettings.quotas[0].children" :key="quotaIndex" v-if="checkQuotaIdArr.includes(quota.id)">
             <div class="quota">
               <span class="quota-name">{{ quota.name }}</span>
-              <span class="quota-score">{{ getQuotaScore(quota.id,row) }}</span>
+              <span class="quota-score">{{ getQuotaScore(quota.id,row) }}
+                <Icon type="md-create" size="12" v-if="[0,2].includes(quota.type)" @click="onEdit(quota,row)" />
+              </span>
+
             </div>
             <div v-if="quota.children.length && expandedArr.includes(index)">
-              <div class="child-item" v-for="(child,childIndex) in quota.children" :key="childIndex">
+              <div class="child-item" v-for="(child,childIndex) in quota.children" :key="childIndex" v-if="checkQuotaIdArr.includes(child.id)">
                 <div class="child-info">
                   <span class="child-name">{{ child.name }}</span>
-                  <span class="child-score">{{ getQuotaScore(child.id,row) }}</span>
+                  <span class="child-score">{{ getQuotaScore(child.id,row) }}
+                    <BaseArtScore :quota="child" :row="row" @onConfirmEdit="onConfirmEdit"></BaseArtScore>
+                  </span>
                 </div>
                 <div class="child-files" v-if="child.type === 2">
                   <p class="file-item" v-for="(file,fileIndex) in getSubmitFiles(child.id,row)" @click.stop="onPreviewFile(file)">
@@ -69,22 +70,32 @@
         </template>
         <!-- 学业指标 -->
         <template slot-scope="{ row,index }" slot="quota_2">
-          <div class="quota-item">
+          <div class="quota-item first-level-score">
             <div class="quota">
               <span class="quota-name">指标总分</span>
-              <span class="quota-score">99分</span>
+              <span class="quota-score">{{ getQuotaScore('quota_2',row) }}</span>
             </div>
           </div>
-          <div class="quota-item" v-for="(quota,quotaIndex) in artSettings.quotas[1].children" :key="quotaIndex">
+          <div class="quota-item" v-for="(quota,quotaIndex) in artSettings.quotas[1].children" :key="quotaIndex" v-if="checkQuotaIdArr.includes(quota.id)">
             <div class="quota">
               <span class="quota-name">{{ quota.name }}</span>
-              <span class="quota-score">{{ getQuotaScore(quota.id,row) }}</span>
+              <span class="quota-score">{{ getQuotaScore(quota.id,row) }}
+                <BaseArtScore :quota="quota" :row="row" @onConfirmEdit="onConfirmEdit"></BaseArtScore>
+              </span>
+            </div>
+            <div class="child-files" v-if="quota.type === 2 && expandedArr.includes(index)">
+              <p class="file-item" v-for="(file,fileIndex) in getSubmitFiles(quota.id,row)" @click.stop="onPreviewFile(file)">
+                <Icon type="ios-link" />
+                {{ file.name }}
+              </p>
             </div>
             <div v-if="quota.children.length && expandedArr.includes(index)">
               <div class="child-item" v-for="(child,childIndex) in quota.children" :key="childIndex">
                 <div class="child-info">
                   <span class="child-name">{{ child.name }}</span>
-                  <span class="child-score">{{ getQuotaScore(child.id,row) }}</span>
+                  <span class="child-score">{{ getQuotaScore(child.id,row) }}
+                    <BaseArtScore :quota="child" :row="row" @onConfirmEdit="onConfirmEdit"></BaseArtScore>
+                  </span>
                 </div>
                 <div class="child-files" v-if="child.type === 2">
                   <p class="file-item" v-for="(file,fileIndex) in getSubmitFiles(child.id,row)" @click.stop="onPreviewFile(file)">
@@ -98,22 +109,24 @@
         </template>
         <!-- 发展指标 -->
         <template slot-scope="{ row,index }" slot="quota_3">
-          <div class="quota-item">
+          <div class="quota-item first-level-score">
             <div class="quota">
               <span class="quota-name">指标总分</span>
-              <span class="quota-score">99分</span>
+              <span class="quota-score">{{ getQuotaScore('quota_3',row) }}</span>
             </div>
           </div>
-          <div class="quota-item" v-for="(quota,quotaIndex) in artSettings.quotas[2].children" :key="quotaIndex">
+          <div class="quota-item" v-for="(quota,quotaIndex) in artSettings.quotas[2].children" :key="quotaIndex" v-if="checkQuotaIdArr.includes(quota.id)">
             <div class="quota">
               <span class="quota-name">{{ quota.name }}</span>
               <span class="quota-score">{{ getQuotaScore(quota.id,row) }}</span>
             </div>
             <div v-if="quota.children.length && expandedArr.includes(index)">
-              <div class="child-item" v-for="(child,childIndex) in quota.children" :key="childIndex">
+              <div class="child-item" v-for="(child,childIndex) in quota.children" :key="childIndex" v-if="checkQuotaIdArr.includes(child.id)">
                 <div class="child-info">
                   <span class="child-name">{{ child.name }}</span>
-                  <span class="child-score">{{ getQuotaScore(child.id,row) }}</span>
+                  <span class="child-score">{{ getQuotaScore(child.id,row) }}
+                    <BaseArtScore :quota="child" :row="row" @onConfirmEdit="onConfirmEdit"></BaseArtScore>
+                  </span>
                 </div>
                 <div class="child-files" v-if="child.type === 2">
                   <p class="file-item" v-for="(file,fileIndex) in getSubmitFiles(child.id,row)" @click.stop="onPreviewFile(file)">
@@ -127,17 +140,44 @@
         </template>
         <!-- 总分 -->
         <template slot-scope="{ row,index }" slot="finalResult">
-          <!-- <span class="total-score"> {{ getFinalScore }} </span> <span>分</span> -->
+          <p v-for="(level1,levelIndex) in filterCols.filter((i,index) => index !== 0 && index !== filterCols.length - 1)" class="level1-score">
+            <span>{{ level1.title }}</span>
+            <span style="color: #085fec;">{{ row.level1Score.find(i => i.id === level1.slot) ? row.level1Score.find(i => i.id === level1.slot).score : 0 }}</span>
+          </p>
+          <div class="level1-score">
+            <span class="icon-total">总</span>
+            <span class="total-score" :style="{color:colorList[row.finalLevelIndex]}"> {{ row.totalScore }} <span>分</span></span>
+            <span class="total-level" :style="{color:colorList[row.finalLevelIndex]}"> {{ artSettings.reviewLevel[row.finalLevelIndex].code }} </span>
+          </div>
         </template>
       </Table>
     </div>
+    <Modal v-model="previewModal" width="500" footer-hide class="tree-modal add-volume-modal">
+      <div v-if="previewFile">
+        <p style="margin-bottom:20px;font-weight:bold;font-size:16px">预览文件 - {{ previewFile.name }}</p>
+        <video v-if="previewFile.type == 'video'" id="previewVideo" :src="previewFile.url" controls="controls" style="max-width: 100%">
+          {{$t('teachContent.tips8')}}
+        </video>
+        <audio v-else-if="previewFile.type == 'audio'" controls>
+          <source :src="previewFile.url">
+          {{$t('teachContent.notAudio')}}
+        </audio>
+      </div>
+    </Modal>
   </div>
 </template>
 
 <script>
+import BaseArtScore from './BaseArtScore.vue'
 export default {
+  components: {
+    BaseArtScore
+  },
   data(vm) {
     return {
+      colorList: ['#23c466', '#c47c18', '#c49258', '#ff0000'],
+      previewModal: false,
+      previewFile: null,
       defaultAvatarSrc: '',
       tableLoading: false,
       tableHeight: document.documentElement.clientHeight * 0.86,
@@ -286,7 +326,9 @@ export default {
           width: 240
         },
       ],
+      filterCols: [],
       assessmentList: [],
+      originList: [],
       artSettings: {
         quotas: [
           {
@@ -309,7 +351,8 @@ export default {
       flatQuotasArr: [],
       expandedArr: [],
       rateTips: [],
-      scoreArr: []
+      scoreArr: [],
+      checkQuotaIdArr: [],
     }
   },
   created() {
@@ -392,10 +435,17 @@ export default {
       this.$api.areaArt.findArtSummary(params).then(
         (res) => {
           if (!res.error) {
+            // 查找勾选的指标ID集合
+            this.checkQuotaIdArr = [...new Set(res.art.settings.map(i => i.path).flat(1))]
+            // 根据勾选的指标 展示表格的列 其中用户信息列和总分列是固定展示
+            let originCols = this._.cloneDeep(this.assessmentCol)
+            this.filterCols = originCols.filter(i => ['userInfo', 'finalResult', ...this.checkQuotaIdArr].includes(i.slot))
             this.classList = [{ name: '全部班级', id: 'all' }].concat(res.classes)
+            // 修改活动科目信息
             this.subjectList = res.art.subjects
             this.curSubjectIndex = 0
             this.curClassId = 'all'
+            // 查询初始化数据
             this.onClassChange()
           }
         },
@@ -419,16 +469,19 @@ export default {
     },
     /* 查询操作 */
     doFilter() {
+      this.expandedArr = []
       this.tableLoading = true
       this.$api.areaArt.findArtResults({
         "opt": "find",
         "artId": this.acList[this.curAcIndex].id,
         "subjects": [this.subjectList[this.curSubjectIndex].id],
-        "classIds": this.curClassId === 'all' ? [] : [this.curClassId]
+        "classIds": this.curClassId === 'all' ? [] : [this.curClassId],
+        "studentName": this.searchVal
       }).then(res => {
         if (!res.error) {
           this.tableLoading = false
           this.assessmentList = res.results
+          this.originList = this._.cloneDeep(this.assessmentList)
           this.calcQuotaScores(res.results)
         } else {
           this.$Message.error('Fail')
@@ -440,40 +493,61 @@ export default {
     /* 计算每个学生各指标分数 */
     calcQuotaScores(list) {
       list.forEach(stu => {
-        let allQuatas = this._.cloneDeep(this.flatQuotasArr)
-        allQuatas.forEach(quota => {
-          let hasQuota = stu.results.find(i => i.quotaId === quota.id)
-          // 直接找到 代表是第三级指标或者学业的第二级
-          if (hasQuota) {
-            quota.score = hasQuota.score
-          } else {
-            // 如果没有找到则代表没有勾选(默认score为-1可以不管) 或者是 一二级指标
-            if (quota.level === 1) {
-              let finalScore = 0
-              quota.children.forEach(second => {
-                let findSecond = stu.results.find(i => i.quotaId === second.id)
-                finalScore += findSecond ? (findSecond.score === -1 ? 0 : findSecond.score * findSecond.percent * 0.01) : 0
-                if (second.children.length) {
-                  finalScore += stu.results.filter(i => second.children.map(k => k.id).includes(i.quotaId)).reduce((a, b) => a + (b.score === -1 ? 0 : b.score * b.percent * 0.01), 0)
-                }
-              })
-              quota.score = finalScore
-            } else if (quota.level === 2) {
-              // 如果是二级指标的话 分数就只提取子指标的分数 进行计算
-              let children = stu.results.filter(i => quota.children.map(k => k.id).includes(i.quotaId))
-              quota.score = children.length && children.some(i => i.score !== -1) ? children.reduce((a, b) => a + (b.score === -1 ? 0 : b.score * b.percent * 0.01), 0) : -1
+        this.refreshStuScore(stu)
+      })
+    },
+    /* 重新计算学生各指标分数统计 */
+    refreshStuScore(stu) {
+      let allQuatas = this._.cloneDeep(this.flatQuotasArr)
+      stu.level1Score = []
+      allQuatas.forEach(quota => {
+        let hasQuota = stu.results.find(i => i.quotaId === quota.id)
+        // 直接找到 代表是第三级指标或者学业的第二级
+        if (hasQuota) {
+          quota.score = hasQuota.score
+        } else {
+          // 如果没有找到则代表没有勾选(默认score为-1可以不管) 或者是 一二级指标
+          if (quota.level === 1) {
+            // 找到一级指标下的任务
+            let relativeTask = stu.results.filter(i => i.quotaId.includes(quota.id))
+            let hasQuotaTask = relativeTask.length > 0
+            // 如果没有找到 或者 找到的任务都是未评分 则直接一级指标也是未评分
+            if (!hasQuotaTask || (hasQuotaTask && relativeTask.every(i => i.score === -1))) {
+              quota.score = -1
+              return
             }
+            // 计算一级指标的总分
+            let finalScore = 0
+            quota.children.forEach(second => {
+              let findSecond = stu.results.find(i => i.quotaId === second.id)
+              // 看二级指标是否有勾选 如果有则默认加上分数
+              finalScore += findSecond ? (findSecond.score === -1 ? 0 : findSecond.score * second.percent * 0.01) : 0
+              if ((!findSecond || (findSecond && findSecond.score === -1)) && second.children.length) {
+                let secondScore = stu.results.filter(i => second.children.map(k => k.id).includes(i.quotaId)).reduce((a, b) => a + (b.score === -1 ? 0 : b.score * this.getChildPercent(b.quotaId, quota) * 0.01), 0)
+                finalScore += secondScore * second.percent * 0.01
+              }
+            })
+            quota.score = finalScore
+            stu.level1Score.push({
+              id: quota.id,
+              name: quota.name,
+              score: quota.score
+            })
+          } else if (quota.level === 2) {
+            // 如果是二级指标的话 分数就只提取子指标的分数 进行计算
+            let children = stu.results.filter(i => quota.children.map(k => k.id).includes(i.quotaId))
+            quota.score = children.length && children.some(i => i.score !== -1) ? children.reduce((a, b) => a + (b.score === -1 ? 0 : b.score * this.getChildPercent(b.quotaId, quota) * 0.01), 0) : -1
           }
-        })
-        stu.flatScoreArr = allQuatas
-      })
-      console.error('计算后', list[0].flatScoreArr.map(i => {
-        return {
-          name: i.name,
-          level: i.level,
-          score: i.score
         }
-      }))
+      })
+      stu.flatScoreArr = allQuatas
+      stu.totalScore = this.getFinalScore(stu)
+      stu.finalLevelIndex = this.getTotalLevel(stu.totalScore)
+      return stu.totalScore
+    },
+    /* 获取子指标在父指标下对应的占比 */
+    getChildPercent(childId) {
+      return this.flatQuotasArr.find(i => i.id === childId).percent
     },
     /* 点击表格某条数据 */
     onRowClick(item, index) {
@@ -494,10 +568,70 @@ export default {
       let fileFullLink = await this.$tools.getFileSas(file.url)
       if (file.type === 'image') {
         this.$hevueImgPreview(fileFullLink.url)
+      } else if (file.type === 'doc') {
+        if (this.getSuffix(file.name) === 'pdf') {
+          this.openPdf(fileFullLink.url, file.name)
+        } else {
+          this.openDoc(escape(fileFullLink.url))
+        }
+      } else if (['video', 'audio'].includes(file.type)) {
+        file.url = fileFullLink.url
+        this.previewFile = file
+        this.previewModal = true
+      } else {
+        this.$tools.doDownloadByUrl(fileFullLink.url, file.name)
       }
+    },
+    /* 打开PDF文件进行预览 */
+    openPdf(url) {
+      window.open('/web/viewer.html?file=' + encodeURIComponent(url));
+    },
+    /* 预览文档 */
+    openDoc(url) {
+      window.open('https://view.officeapps.live.com/op/view.aspx?src=' + url);
+    },
+    /* 编辑分数 */
+    onConfirmEdit(val) {
+      let { quota, row, score } = val
+      this.$api.areaArt.findArtResults({
+        "opt": "saveScore",
+        "artId": this.acList[this.curAcIndex].id,
+        "studentScore": [{
+          "studentId": row.studentId,
+          "results": [
+            {
+              "taskId": row.results.find(i => i.quotaId === quota.id).taskId,
+              "subjectId": this.subjectList[this.curSubjectIndex].id,
+              "quotaId": quota.id,
+              "score": score
+            }
+          ]
+        }]
+      }).then(res => {
+        console.log(res)
+        if (!res.error) {
+          row.results.find(i => i.quotaId === quota.id).score = score
+          this.refreshStuScore(row)
+          this.$Message.success('修改成功')
+        } else {
+          this.$Message.error('修改失败')
+        }
+      }).catch(e => {
+        this.$Message.error('修改失败')
+      })
+    },
+    onInputEvent(e) {
+      e.stopPropagation()
     }
   },
   computed: {
+    /* 获取文件后缀名 */
+    getSuffix() {
+      return name => {
+        return name.substr(name.lastIndexOf(".") + 1)
+      }
+    },
+    /* 获取指标对应上传的文件 */
     getSubmitFiles() {
       return (quotaId, row) => {
         let findQuota = row.results.find(i => i.quotaId === quotaId)
@@ -507,40 +641,32 @@ export default {
     /* 获取每个任务得分情况 -1代表未评分 如果是一级或者二级指标 则需要根据下级指标分数按照占比来计算得分 */
     getQuotaScore() {
       return (quotaId, row) => {
-        let findQuota = row.results.find(i => i.quotaId === quotaId)
-        let quotaScore = findQuota ? (findQuota.score === -1 ? '未评分' : findQuota.score + '分') : this.calcParentScore(quotaId, row)
-        let isExistScore = this.scoreArr.find(i => i.quotaId === quotaId)
-        if (isExistScore) {
-          isExistScore.score = quotaScore
-        } else {
-          this.scoreArr.push({
-            quotaId: quotaId,
-            level: findQuota ? 3 : 2,
-            score: quotaScore
-          })
-        }
-        return quotaScore
+        let score = row.flatScoreArr.find(i => i.id === quotaId).score
+        return score === -1 ? '未评分' : score + '分'
       }
     },
+    /* 获取最终分数 */
     getFinalScore() {
-      console.error(this.scoreArr)
-      return 0
+      return row => {
+        let level1ScoreArr = row.flatScoreArr.filter(i => i.level === 1 && i.score > -1)
+        let totalScore = level1ScoreArr.length ? level1ScoreArr.reduce((a, b) => a + b.score * b.percent * 0.01, 0) : 0
+        return `${totalScore}`
+      }
     },
-    calcParentScore() {
-      return (quotaId, row) => {
-        // 先拿到作答数据里面 所属子指标的分数
-        let children = row.results.filter(i => i.quotaId.includes(quotaId))
-        // 如果查不到 或者 子指标都是未评分状态 则父指标也是未评分
-        if (!children.length || children.every(i => i.score === -1)) {
-          return '未评分'
-        }
-        // 然后按照区级设置的子指标分数占比来进行计算父级分数
-        let totalScore = children.map(b => this.flatQuotasArr.find(i => i.id === b.quotaId).percent * 0.01 * (b.score === -1 ? 0 : b.score)).reduce((a, b) => a + b, 0)
-        return totalScore + '分'
+    /* 获取最终等级 */
+    getTotalLevel() {
+      return totalScore => {
+        let levelIndex = this.artSettings.reviewLevel.findIndex(i => i.value[0] <= totalScore && i.value[1] > totalScore)
+        return levelIndex
       }
     }
   }
 }
 </script>
 
-<style lang="less" src="./ArtAssessment.less" scoped></style>
+<style lang="less" src="./ArtAssessment.less" scoped></style>
+<style>
+.art-edit-tooltip .ivu-tooltip-inner {
+  padding: 20px !important;
+}
+</style>

+ 62 - 0
TEAMModelOS/ClientApp/src/view/assessment/BaseArtScore.vue

@@ -0,0 +1,62 @@
+<template>
+  <Tooltip placement="bottom" theme="light" width="400" transfer-class-name="art-edit-tooltip" transfer>
+    <Icon type="md-create" size="14" v-if="[0,2].includes(quota.type)" class="icon-edit" @click.stop.native />
+    <template #content>
+      <div style="display: flex;align-items: center">
+        <InputNumber v-model="quota.score" :min="0" :max="100" @click.stop.native></InputNumber>
+        <span style="margin-left:10px;color:#085fec;cursor: pointer;" @click.stop="onConfirmEdit()">确认修改</span>
+      </div>
+      <p style="margin:5px 0">快速给分</p>
+      <div style="display: flex;">
+        <span v-for="(item,index) in quickScoreArr" :key="index" @click="doQuickScore(item)" style="display:inline-block;padding:2px 5px;margin-right:6px; border:1px solid #ccc;cursor: pointer;">{{ item }}</span>
+      </div>
+    </template>
+  </Tooltip>
+</template>
+
+<script>
+export default {
+  props: {
+    quota: {
+      type: Object,
+      default: () => { }
+    },
+    row: {
+      type: Object,
+      default: () => { }
+    }
+  },
+  data() {
+    return {
+      quickScoreArr: [20, 40, 60, 80, 100]
+    }
+  },
+  created() {
+    if (this.quota.score === -1) {
+      this.quota.score = 0
+    }
+  },
+  methods: {
+    doQuickScore(score) {
+      console.log(score)
+      this.$set(this.quota, 'score', score)
+      this.$forceUpdate()
+    },
+    onConfirmEdit() {
+      this.$emit('onConfirmEdit', {
+        quota: this.quota,
+        row: this.row,
+        score: this.quota.score
+      })
+    }
+  },
+  mounted() {
+  }
+}
+</script>
+
+<style>
+.art-edit-tooltip .ivu-tooltip-inner {
+  padding: 20px !important;
+}
+</style>

+ 1 - 0
TEAMModelOS/ClientApp/src/view/syllabus/Syllabus.vue

@@ -1386,6 +1386,7 @@ export default {
         source.creatorName = myName
         if (source.rnodes.length) {
           source.rnodes.forEach(i => {
+            if (i.type === 'link') return
             i.cntr = myId
             i.code = i.code.split('-').length > 1 ? i.code.split('-')[0] + '-' + myId : myId
             i.link = i.link.replace(i.link.split('/')[2], source.id) // 链接地址的nodeId也要变成newNodeId

+ 27 - 23
TEAMModelOS/Controllers/School/ArtReviewController.cs

@@ -88,8 +88,10 @@ namespace TEAMModelOS.Controllers
                         {
                             string results_join = "";
                             string results_where = "";
+                            //string results_filed = "c.results";
                             string classIds_join = "";
                             string classIds_where = "";
+                            //string classIds_filed = "c.classIds";
                             request.TryGetProperty("studentName", out JsonElement studentName); 
                             request.TryGetProperty("studentId", out JsonElement studentId);
                             request.TryGetProperty("classIds", out JsonElement _classIds);
@@ -109,6 +111,7 @@ namespace TEAMModelOS.Controllers
                             if (_classIds.ValueKind.Equals(JsonValueKind.Array)) {
                                 var classIds = _classIds.Deserialize<List<string>>();
                                 if (classIds.IsNotEmpty()) {
+                                    //classIds_filed = " ARRAY_CONCAT([classIds],[])  as   classIds ";
                                     classIds_join = " join classIds in  c.classIds ";
                                     classIds_where = $" and classIds in({string.Join(",", classIds.Select(x => $"'{x}'"))}) ";
                                 }
@@ -119,8 +122,9 @@ namespace TEAMModelOS.Controllers
                                 subjects = _subjects.Deserialize<List<string>>();
                                 if (subjects.IsNotEmpty())
                                 {
+                                    //results_filed = " ARRAY_CONCAT([results],[])  as results  ";
                                     results_join = " join results in c.results ";
-                                    results_where = $" and results.subjectId in({string.Join(",", subjects.Select(x => $"'{x}'"))}) or results.subjectId = null";
+                                    results_where = $" and ( results.subjectId in({string.Join(",", subjects.Select(x => $"'{x}'"))}) or  results.subjectId= null )";
                                 }
                             }
                             string studentNameWhere = "";
@@ -132,36 +136,36 @@ namespace TEAMModelOS.Controllers
                             {
                                 studentIdWhere = $" and  c.id = '{school}-{studentId}' ";
                             }
-                            string sql = $"SELECT value c FROM c {classIds_join}  {results_join} where  c.pk='ArtResult'  {classIds_where} {results_where} {studentIdWhere} {studentNameWhere} ";
+                            //string sql = $"SELECT  c.id,c.code,c.pk,c.studentId,c.studentName,c.picture,c.userType,c.school,c.artId,c.totalScore ,{results_filed},{classIds_filed}" +
+                            string sql = $"SELECT  distinct value( c.id ) " +
+                                $" FROM c {classIds_join}  {results_join} where  c.pk='ArtResult'  {classIds_where} {results_where} {studentIdWhere} {studentNameWhere} ";
+                            List<string> ids = new List<string>();
+                            await  foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryIterator<string> 
+                                (queryText: sql , requestOptions: new QueryRequestOptions {  PartitionKey = new PartitionKey($"ArtResult-{_artId}") })) {
+                                ids.Add(item);
+                            }
                             List<StudentArtResult> results = new List<StudentArtResult>();
-                            await  foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryStreamIterator 
-                                (queryText: sql,continuationToken: continuationToken, requestOptions: new QueryRequestOptions { MaxItemCount = pageCount, PartitionKey = new PartitionKey($"ArtResult-{_artId}") })) {
-                                using var json = await JsonDocument.ParseAsync(item.ContentStream);
-                                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                            if (ids.Any()) {
+                                string query = $" select value c from c where c.id in({string.Join(",",ids.Select(x=>$"'{x}'"))}) ";
+                                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Student).GetItemQueryStreamIterator
+                                    (queryText: query, continuationToken: continuationToken, requestOptions: new QueryRequestOptions { MaxItemCount = pageCount, PartitionKey = new PartitionKey($"ArtResult-{_artId}") }))
                                 {
-                                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
                                     {
-                                        StudentArtResult student = obj.ToObject<StudentArtResult>();
-                                        if (results.Any())
-                                        {
-                                            if (!results.Exists(x => x.id.Equals(student.id)))
-                                            {
-                                                results.Add(student);
-                                            }
-                                        }
-                                        else
+                                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                                         {
+                                            StudentArtResult student = obj.ToObject<StudentArtResult>();
                                             results.Add(student);
                                         }
-                                     
                                     }
+                                    continuationToken = item.GetContinuationToken();
+                                    break;
+                                }
+                                if (subjects.IsNotEmpty())
+                                {
+                                    results.ForEach(x => x.results.RemoveAll(z => !string.IsNullOrWhiteSpace(z.subjectId) && !subjects.Contains(z.subjectId)));
                                 }
-                                continuationToken = item.GetContinuationToken();
-                                break;
-                            }
-                            if (subjects.IsNotEmpty())
-                            {
-                                results.ForEach(x => x.results.RemoveAll(z => !string.IsNullOrWhiteSpace(z.subjectId) && !subjects.Contains(z.subjectId)));
                             }
                             return Ok(new { results= results, status = 1 , continuationToken });
                         }