瀏覽代碼

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

CrazyIter_Bin 3 月之前
父節點
當前提交
bb5ca98ca6

+ 8 - 0
TEAMModelBI/ClientApp/src/language/lang/zh-cn.js

@@ -821,6 +821,14 @@ const zh_cn = {
         view: '查看',
         view: '查看',
         message1_1: '当前查询人数仅支持小于或等于',
         message1_1: '当前查询人数仅支持小于或等于',
         message1_2: '名用户',
         message1_2: '名用户',
+        teacherData: '教师数据',
+        tmid: '醍摩豆Id',
+        schoolName: '学校',
+        stuLessonLengMin: '学生参与总时数',
+        lessonRecord: '课堂总数',
+        lessonLengMin: '课堂总时数',
+        item: '题目数',
+        interact: '互动次数',
     },
     },
     userInquire: {
     userInquire: {
         index: {
         index: {

+ 8 - 0
TEAMModelBI/ClientApp/src/language/lang/zh-tw.js

@@ -814,6 +814,14 @@ const zh_tw = {
         view: '查看',
         view: '查看',
         message1_1: '當前查詢人數僅支持小於或等於',
         message1_1: '當前查詢人數僅支持小於或等於',
         message1_2: '名用戶',
         message1_2: '名用戶',
+        teacherData: '教師數據',
+        tmid: '醍摩豆Id',
+        schoolName: '學校',
+        stuLessonLengMin: '學生參與總時數',
+        lessonRecord: '課堂總數',
+        lessonLengMin: '課堂總時數',
+        item: '題目數',
+        interact: '互動次數',        
     },
     },
     userInquire: {
     userInquire: {
         index: {
         index: {

+ 107 - 21
TEAMModelBI/ClientApp/src/view/product/details.vue

@@ -153,10 +153,12 @@
             </div>
             </div>
           </div>
           </div>
         </div>
         </div>
-        <!--学区or城市样式内容-->
-        <div class="data-tables" style="height: 700px;width: 100%;" v-loading="searchLoading"  :element-loading-text="$t(`product.prepareData`)+'...'">
-          <el-auto-resizer>
-            <template #default="{ height, width }">
+        
+        <!--老師個人資料列表-->        
+        <div class="data-tables-teacher" style="height: 700px;width: 100%;" v-loading="searchLoading"  :element-loading-text="$t(`product.prepareData`)+'...'">          
+          <el-button type="primary" @click="exportExcel()" style="display: block;margin-top: 10px;">匯出</el-button>
+          <el-auto-resizer>            
+            <template #default="{ height, width }">              
               <el-table-v2 v-if="filterdata.length > 0" v-model:sort-state="sortState" :columns="columns" :data="filterdata" :width="width" :height="height" @column-sort="onSort" fixed  :row-class="rowClassName" />
               <el-table-v2 v-if="filterdata.length > 0" v-model:sort-state="sortState" :columns="columns" :data="filterdata" :width="width" :height="height" @column-sort="onSort" fixed  :row-class="rowClassName" />
             </template>
             </template>
           </el-auto-resizer>
           </el-auto-resizer>
@@ -333,6 +335,8 @@ import { ref, reactive, getCurrentInstance, defineEmits, computed, onMounted } f
 import { ElMessage, TableV2SortOrder, ElLoading, ElCheckbox,HeaderCellSlotProps,ElPopover,Column, RowClassNameGetter} from 'element-plus'
 import { ElMessage, TableV2SortOrder, ElLoading, ElCheckbox,HeaderCellSlotProps,ElPopover,Column, RowClassNameGetter} from 'element-plus'
 import Xlines from '@/components/echarts/Xline.vue'
 import Xlines from '@/components/echarts/Xline.vue'
 import * as echarts from 'echarts'
 import * as echarts from 'echarts'
+import excel from "../../until/excel"
+
 let props = defineProps({
 let props = defineProps({
   detailsData: Object,
   detailsData: Object,
   pattern:Object,
   pattern:Object,
@@ -357,7 +361,21 @@ const sortState = ref({
 })
 })
 let searchLoading=ref(false)
 let searchLoading=ref(false)
 let sortValue = reactive({})
 let sortValue = reactive({})
-let columns = ref([
+let columns = ref([  
+  {
+    key: "schoolName",
+    dataKey: "schoolName",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+    title: proxy.$t(`product.schoolName`),//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    headerClass: 'general',
+  },  
+  {
+    key: "schoolId",
+    dataKey: "schoolId",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+    title: proxy.$t(`product.simpleCode`),//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    headerClass: 'general',
+  },  
   {
   {
     key: "name",
     key: "name",
     dataKey: "name",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
     dataKey: "name",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
@@ -368,21 +386,24 @@ let columns = ref([
     headerClass: 'general',
     headerClass: 'general',
   },
   },
   {
   {
-    key: "date",
-    dataKey: "date",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
-    title: proxy.$t(`product.time`),//显示在单元格表头的文本
+    key: "tmid",
+    dataKey: "tmid",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+    title: proxy.$t(`product.tmid`),//显示在单元格表头的文本
     width: 100,//当前列的宽度,必须设置
     width: 100,//当前列的宽度,必须设置
     fixed: false,//是否固定列
     fixed: false,//是否固定列
-     sortable: true,
+    // sortable: true,
     headerClass: 'general',
     headerClass: 'general',
   },
   },
   {
   {
-    key: "schoolId",
-    dataKey: "schoolId",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
-    title: proxy.$t(`product.simpleCode`),//显示在单元格表头的文本
+    key: "date",
+    dataKey: "date",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
+    title: proxy.$t(`product.time`),//显示在单元格表头的文本
     width: 100,//当前列的宽度,必须设置
     width: 100,//当前列的宽度,必须设置
+    fixed: false,//是否固定列
+     sortable: true,
     headerClass: 'general',
     headerClass: 'general',
   },
   },
+  
   {
   {
     key: "deviceCnt",
     key: "deviceCnt",
     dataKey: "deviceCnt",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
     dataKey: "deviceCnt",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
@@ -402,7 +423,7 @@ let columns = ref([
   {
   {
     key: "stuShow",
     key: "stuShow",
     dataKey: "stuShow",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
     dataKey: "stuShow",//需要渲染当前列的数据字段,如{id:9527,name:'Mike'},则填id
-    title: proxy.$t(`product.studentNumber`),//显示在单元格表头的文本
+    title: proxy.$t(`product.studentNumberUnique`),//显示在单元格表头的文本
     width: 100,//当前列的宽度,必须设置
     width: 100,//当前列的宽度,必须设置
     headerClass: 'general',
     headerClass: 'general',
     sortable:true
     sortable:true
@@ -439,6 +460,46 @@ let columns = ref([
     headerClass: 'general',
     headerClass: 'general',
     sortable:true
     sortable:true
   },
   },
+  {
+    key: "stuLessonLengMin",
+    dataKey: "stuLessonLengMin",
+    title: proxy.$t(`product.stuLessonLengMin`),//显示在单元格表头的文本
+    width: 150,//当前列的宽度,必须设置
+    headerClass: 'general',
+    sortable:true
+  },
+  {
+    key: "lessonRecord",
+    dataKey: "lessonRecord",
+    title: proxy.$t(`product.lessonRecord`),//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    headerClass: 'general',
+    sortable:true
+  },
+  {
+    key: "lessonLengMin",
+    dataKey: "lessonLengMin",
+    title: proxy.$t(`product.lessonLengMin`),//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    headerClass: 'general',
+    sortable:true
+  },
+  {
+    key: "item",
+    dataKey: "item",
+    title: proxy.$t(`product.item`),//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    headerClass: 'general',
+    sortable:true
+  },
+  {
+    key: "interact",
+    dataKey: "interact",
+    title: proxy.$t(`product.interact`),//显示在单元格表头的文本
+    width: 100,//当前列的宽度,必须设置
+    headerClass: 'general',
+    sortable:true
+  },
   // {
   // {
   //   key: "date",
   //   key: "date",
   //   dataKey: "date",
   //   dataKey: "date",
@@ -1345,7 +1406,9 @@ function serachToresult() {
     if (res.state === 200) {
     if (res.state === 200) {
         res.data.forEach((item) => { 
         res.data.forEach((item) => { 
           item.name = item.tmidInfo.name ? item.tmidInfo.name : proxy.$t(`product.noneYet`) 
           item.name = item.tmidInfo.name ? item.tmidInfo.name : proxy.$t(`product.noneYet`) 
-          item.schoolId = item.tmid
+          // 把學校名稱
+          item.schoolName = item.school.name
+          //item.schoolId = item.tmid
           });
           });
         res.geo.forEach((item) => {
         res.geo.forEach((item) => {
           if (item.school.name || (item.school.name === "")) {
           if (item.school.name || (item.school.name === "")) {
@@ -1363,6 +1426,29 @@ function serachToresult() {
     ElMessage.error(proxy.$t(`product.apiErrpr`) + ',' + proxy.$t(`product.getDataError`))
     ElMessage.error(proxy.$t(`product.apiErrpr`) + ',' + proxy.$t(`product.getDataError`))
   })
   })
 }
 }
+//匯出各縣市的統購資料
+function exportExcel() {    
+  let title = [proxy.$t(`product.schoolName`), proxy.$t(`product.simpleCode`), proxy.$t(`product.name`), proxy.$t(`product.tmid`), proxy.$t(`product.time`), proxy.$t(`product.classroomNumber`), proxy.$t(`product.teacherNumber`)
+  , proxy.$t(`product.studentNumber`), proxy.$t(`product.lessonNumber`), proxy.$t(`product.lessonHours`), proxy.$t(`product.tGreen`), proxy.$t(`product.tLesson`)
+  , proxy.$t(`product.stuLessonLengMin`), proxy.$t(`product.lessonRecord`), proxy.$t(`product.lessonLengMin`), proxy.$t(`product.item`), proxy.$t(`product.interact`)];
+  let key = ['schoolName', 'schoolId', 'name', 'tmid', 'date', 'deviceCnt', 'tmidCnt', 'stuShow', 'lessonRecord', 'lessonLengMin', 'tGreen', 'tLesson',
+    'stuLessonLengMin','lessonRecord','lessonLengMin','item','interact'];
+
+  let arr = excel.export_json_to_array(key, filterdata.value);
+  arr.unshift(title);
+  let ws = XLSX.utils.aoa_to_sheet(arr);
+  ws = excel.export_auto_width(ws, arr);
+  let wb = XLSX.utils.book_new();
+  let sheetName ='Data';
+  XLSX.utils.book_append_sheet(wb, ws, sheetName);
+  //檔案做成
+  let filename = schoolData.value.name + '_' + proxy.$t(`product.teacherData`);
+  XLSX.writeFile(wb, filename + '.xlsx', {
+      bookType: 'xlsx',
+      bookSST: true,
+      type: 'array'
+  });           
+  }
 init()
 init()
 </script>
 </script>
 <style  scoped>
 <style  scoped>
@@ -1922,16 +2008,17 @@ init()
 .contentbox .el-divider {
 .contentbox .el-divider {
   margin: 10px 0;
   margin: 10px 0;
 }
 }
-.data-tables .header-class,
-  .data-tables 
+.data-tables-teacher .header-class,
+  .data-tables-teacher
   .el-table-v2__row-cell 
   .el-table-v2__row-cell 
   {
   {
-    /* width: v-bind(cellWidth + "%") !important; */
+    max-width: 15% !important;   
     justify-content: center;
     justify-content: center;
     text-align: center;
     text-align: center;
+    white-space:nowrap;
   }
   }
-  .data-tables .general {
-    /* width: v-bind(cellWidth + "%") !important; */
+  .data-tables-teacher .general {
+    max-width: 15% !important;   
     justify-content: center;
     justify-content: center;
     text-align: center;
     text-align: center;
   }
   }
@@ -1939,8 +2026,7 @@ init()
     justify-content: left;
     justify-content: left;
     text-align: left;
     text-align: left;
   }
   }
-  .data-tables .btn-class {
-    /* width: v-bind(cellWidth + "%") !important; */
+  .data-tables .btn-class {    
     justify-content: center;
     justify-content: center;
     text-align: center;
     text-align: center;
   }
   }

文件差異過大導致無法顯示
+ 83 - 12
TEAMModelBI/Controllers/BIProductAnalysis/ProductAnalysisController.cs


+ 14 - 14
TEAMModelOS/ClientApp/src/common/BaseLayout.vue

@@ -1462,6 +1462,20 @@
 										menuName: "manageHomeWork",
 										menuName: "manageHomeWork",
 										isShow: true
 										isShow: true
 									},
 									},
+									// 活动报名
+									{
+										icon: "iconfont icon-yishu",
+										name: this.$t("system.menu.activity"),
+										router: "#",
+										tag: "",
+										role: "admin|teacher",
+										permission: "",
+										child: [],
+										menuName: "privActivity",
+										// menuName: 'myCourse',
+										isShow: this.isShowActi || this.isWenJiangArea,
+										to: "privActivity"
+									},
 									{
 									{
 										icon: "iconfont icon-vote",
 										icon: "iconfont icon-vote",
 										name: this.$t("system.menu.prtVote"),
 										name: this.$t("system.menu.prtVote"),
@@ -1482,20 +1496,6 @@
 										menuName: "personalSurvey",
 										menuName: "personalSurvey",
 										isShow: true
 										isShow: true
 									},
 									},
-									// 活动报名
-									{
-										icon: "iconfont icon-yishu",
-										name: this.$t("system.menu.activity"),
-										router: "#",
-										tag: "",
-										role: "admin|teacher",
-										permission: "",
-										child: [],
-										menuName: "privActivity",
-										// menuName: 'myCourse',
-										isShow: this.isShowActi || this.isWenJiangArea,
-										to: "privActivity"
-									},
 									// 自主学习和作业活动暂时隐藏
 									// 自主学习和作业活动暂时隐藏
 									// {
 									// {
 									//     icon: 'iconfont icon-learning-self',
 									//     icon: 'iconfont icon-learning-self',

+ 1 - 1
TEAMModelOS/ClientApp/src/common/BaseSelectSchool.vue

@@ -30,7 +30,7 @@
 				<DropdownMenu slot="list">
 				<DropdownMenu slot="list">
 					<div v-for="(item, index) in periods" :key="index">
 					<div v-for="(item, index) in periods" :key="index">
 						<DropdownItem :name="index">
 						<DropdownItem :name="index">
-							<div class="school-item">
+							<div class="school-item" v-if="!item.status">
 								<span>{{ item.name }}</span>
 								<span>{{ item.name }}</span>
 							</div>
 							</div>
 						</DropdownItem>
 						</DropdownItem>

+ 2 - 2
TEAMModelOS/ClientApp/src/view/areaMgmt/AreaLayout.vue

@@ -401,7 +401,7 @@
 					// 研修平台
 					// 研修平台
 					{
 					{
 						icon: "iconfont icon-basic-setting",
 						icon: "iconfont icon-basic-setting",
-						name: this.$t("system.menu.trainSystem"),
+						name: '培训平台',
 						router: "",
 						router: "",
 						tag: "",
 						tag: "",
 						subName: "trainCenter",
 						subName: "trainCenter",
@@ -504,7 +504,7 @@
 					},
 					},
 					{
 					{
 						icon: "iconfont icon-resource",
 						icon: "iconfont icon-resource",
-						name: `培训平台`,
+						name: `教师发展`,
 						router: "#",
 						router: "#",
 						tag: "",
 						tag: "",
 						role: "",
 						role: "",

+ 1 - 0
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseImport.vue

@@ -427,6 +427,7 @@ export default {
 
 
     /* 上传异常处理 */
     /* 上传异常处理 */
     onUploadError(e) {
     onUploadError(e) {
+      return
       console.log(e)
       console.log(e)
       this.$Message.error(this.$t('evaluation.importFile.warningTips4'))
       this.$Message.error(this.$t('evaluation.importFile.warningTips4'))
       this.isBtnLoading = false
       this.isBtnLoading = false

+ 241 - 0
TEAMModelOS/Controllers/Common/ExamController.cs

@@ -1597,6 +1597,247 @@ namespace TEAMModelOS.Controllers
             }
             }
         }
         }
 
 
+        /// <summary>
+        /// 离线版本学生作答接口
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [Authorize(Roles = "IES")]
+        [AuthToken(Roles = "student,teacher")]
+        [HttpPost("upsert-new-record")]
+        public async Task<IActionResult> upsertNewRecord(JsonElement request)
+        {
+
+            //评测活动Id
+            if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
+            //学生作答结果
+            if (!request.TryGetProperty("answer", out JsonElement answer)) return BadRequest();
+            //科目ID
+            if (!request.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
+            //班级ID
+            if (!request.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
+            //活动code
+            if (!request.TryGetProperty("ownerId", out JsonElement ownerId)) return BadRequest();
+            if (!request.TryGetProperty("paperId", out JsonElement paperId)) return BadRequest();
+            if (!request.TryGetProperty("studentId", out JsonElement studentId)) return BadRequest();
+
+            var (userId, name, picture, school) = HttpContext.GetAuthTokenInfo();
+            try
+            {
+                var client = _azureCosmos.GetCosmosClient();
+                ExamInfo info = new();
+                var response = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(id.ToString(), new PartitionKey($"Exam-{ownerId}"));
+                if (response.StatusCode == System.Net.HttpStatusCode.OK)
+                {
+                    using var cJson = await JsonDocument.ParseAsync(response.Content);
+                    info = cJson.ToObject<ExamInfo>();
+                }
+                else
+                {
+                    return Ok(new { code = 404, msg = "该活动未被找到" });
+                }
+                string code = string.Empty;
+                if (info.scope.Equals("school"))
+                {
+                    code = info.school;
+                }
+                else {
+                    code = info.creatorId;
+                }
+
+                List<ExamClassResult> examClassResults = new List<ExamClassResult>();
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryStreamIteratorSql(
+                    queryText: $"select value(c) from c where c.examId = '{id}' and c.subjectId = '{subjectId}' and c.info.id = '{classId}' ",
+                    requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ExamClassResult-{code}") }))
+                {
+                    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())
+                        {
+                            examClassResults.Add(obj.ToObject<ExamClassResult>());
+                        }
+                    }
+                }
+                //获取试卷详情
+                PaperSimple paper = info.papers.Where(c => c.id.Equals(paperId.GetString())).FirstOrDefault();
+                examClassResults = examClassResults.Where(c => c.studentIds.Contains(studentId.GetString())).ToList();
+                ExamClassResult classResult = new ExamClassResult();
+              
+                List<List<string>> ans = answer.ToObject<List<List<string>>>();
+                List<List<string>> standard = paper.answers;
+                List<double> points = paper.point;
+                int rule = paper.multipleRule;
+                List<Task<string>> tasks = new List<Task<string>>();
+                foreach (ExamClassResult result in examClassResults)
+                {
+                    
+                    int newIndex = result.studentIds.IndexOf(studentId.ToString());
+                    StringBuilder builder = new();
+                    builder.Append(result.examId).Append('/');
+                    builder.Append(result.subjectId).Append('/');
+                    builder.Append(studentId.GetString()).Append('/');
+                    builder.Append("ans.json");
+                    tasks.Add(_azureStorage.GetBlobContainerClient(code.ToString()).UploadFileByContainer(ans.ToJsonString(), "exam", builder.ToString(), false));
+                    result.studentAnswers[newIndex].Add(builder.ToString());
+                    result.status[newIndex] = 0;
+                    for (int i = 0; i < ans.Count; i++)
+                    {
+
+                        var sc = standard[i].Count;
+                        var ac = ans[i].Where(a => a.Trim().Length > 0).ToList().Count;
+                        //算分处理
+                        if (sc > 0)
+                        {
+                            /*                         if (ans[i].Count == 0)
+                                                     {
+                                                         continue;
+                                                     }*/
+                            result.ans[newIndex][i] = ans[i];
+                            if (ac == sc && sc == 1)
+                            {
+                                foreach (string right in ans[i])
+                                {
+                                    if (standard[i].Contains(right.Trim()))
+                                    {
+                                        result.studentScores[newIndex][i] = points[i];
+                                    }
+                                    else
+                                    {
+                                        result.studentScores[newIndex][i] = 0;
+                                    }
+                                }
+
+                            }
+                            else
+                            {
+                                if (rule > 0)
+                                {
+                                    int falseCount = 0;
+                                    if (ac > 0)
+                                    {
+                                        foreach (string obj in ans[i])
+                                        {
+                                            if (!standard[i].Contains(obj))
+                                            {
+                                                falseCount++;
+                                            }
+                                        }
+                                        switch (rule)
+                                        {
+                                            case 1:
+                                                if (ac == sc)
+                                                {
+                                                    if (falseCount == 0)
+                                                    {
+                                                        result.studentScores[newIndex][i] = points[i];
+                                                    }
+                                                    else
+                                                    {
+                                                        result.studentScores[newIndex][i] = 0;
+                                                    }
+                                                }
+                                                else
+                                                {
+                                                    result.studentScores[newIndex][i] = 0;
+                                                }
+                                                break;
+                                            case 2:
+                                                if (falseCount > 0)
+                                                {
+                                                    result.studentScores[newIndex][i] = 0;
+                                                }
+                                                else
+                                                {
+                                                    if (ac == sc)
+                                                    {
+                                                        result.studentScores[newIndex][i] = points[i];
+                                                    }
+                                                    else
+                                                    {
+                                                        result.studentScores[newIndex][i] = points[i] / 2;
+                                                    }
+
+                                                }
+                                                break;
+                                            case 3:
+                                                if (falseCount > 0)
+                                                {
+                                                    result.studentScores[newIndex][i] = 0;
+                                                }
+                                                else
+                                                {
+                                                    if (ac == sc)
+                                                    {
+                                                        result.studentScores[newIndex][i] = points[i];
+                                                    }
+                                                    else
+                                                    {
+                                                        result.studentScores[newIndex][i] = System.Math.Round((double)ac / sc * points[i], 1);
+                                                    }
+
+                                                }
+                                                break;
+                                            case 4:
+                                                if (ac == sc)
+                                                {
+                                                    result.studentScores[newIndex][i] = points[i];
+                                                }
+                                                else
+                                                {
+                                                    double persent = (double)(sc - 2 * falseCount) / sc;
+                                                    if (persent <= 0)
+                                                    {
+                                                        result.studentScores[newIndex][i] = 0;
+                                                    }
+                                                    else
+                                                    {
+                                                        result.studentScores[newIndex][i] = System.Math.Round(persent * points[i], 1);
+                                                    }
+                                                }
+                                                break;
+                                        }
+                                    }
+                                    else
+                                    {
+                                        result.studentScores[newIndex][i] = 0;
+                                    }
+
+                                }
+                            }
+                        }
+                    }
+                    bool isAns = result.studentScores[newIndex].Exists(s => s == -1);
+                    HttpContext.Items.TryGetValue("Scope", out object type);
+                    int userType = $"{type}".Equals(Constant.ScopeStudent) ? 2 : 1;
+                    result.sum[newIndex] = result.studentScores[newIndex].Sum();
+                    classResult = await client.GetContainer(Constant.TEAMModelOS, "Common").ReplaceItemAsync(result, result.id, new PartitionKey($"{result.code}"));
+                    var target = info.scope.Equals("school") ? info.school : info.creatorId;
+                    string _client = "web";
+                    if (info.source.Equals("1"))
+                    {
+                        _client = "hiteach";
+                    }
+                    await SystemService.RecordAccumulateData(_azureRedis, _dingDing, new SDK.Models.Dtos.Accumulate { client = _client, count = 1, id = info.id, key = "exam-submit", name = info.name, scope = info.scope, target = target });
+                    if (!isAns) {
+                        if (request.TryGetProperty("artId", out JsonElement artId) && request.TryGetProperty("quotaId", out JsonElement quotaId))
+                        {
+                            await getArtInfoAsync(client, artId.GetString(), school, result.sum[newIndex], id.GetString(), subjectId.GetString(), quotaId.GetString(), userId, picture, name, userType, new List<string> { classId.GetString()});
+                        };                  
+                    }
+                }
+                await Task.WhenAll(tasks);
+                return Ok(new { classResult });
+            }
+            catch (Exception e)
+            {
+                await _dingDing.SendBotMsg($"OS,{_option.Location},exam/upsertNewRecord()\n{e.Message}\n{e.StackTrace}\n\n{id.GetString()}\n{request.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
+                return BadRequest();
+            }
+        }
+
+
 
 
 
 
         [ProducesDefaultResponseType]
         [ProducesDefaultResponseType]