Browse Source

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

upon 1 year ago
parent
commit
c14e34d0aa

+ 48 - 4
TEAMModelOS.SDK/Models/Cosmos/School/ExamImport.cs

@@ -9,6 +9,50 @@ using System.Threading.Tasks;
 namespace TEAMModelOS.SDK.Models.Cosmos.School
 {
 
+    public class VirtueImport : CosmosEntity {
+        /// <summary>
+        /// id:根据名称不重复的前台生成UUID,
+        /// code:ExamImport-hbcn
+        /// pk:ExamImport
+        /// 评测名称
+        /// </summary>
+        public string name { get; set; }
+
+        /// <summary>
+        /// 评测类型 期末,期中,季考,月考,周考,测验,练习,作业,日常,课中
+        /// </summary>
+        public string type { get; set; }
+        /// <summary>
+        /// 学校id
+        /// </summary>
+        public string school { get; set; }
+        /// <summary>
+        /// 考试时间
+        /// </summary>
+        public long time { get; set; }
+        /// <summary>
+        /// 学年
+        /// </summary>
+        public int year { get; set; }
+        /// <summary>
+        /// 学期
+        /// </summary>
+        public string semesterId { get; set; }
+        /// <summary>
+        /// 学段
+        /// </summary>
+        public string periodId { get; set; }
+        /// <summary>
+        /// 班级id
+        /// </summary>
+        public string classId { get;set; }
+        /// <summary>
+        /// 学生成绩
+        /// </summary>
+        public List<ResultImportStudent> students { get; set; } = new List<ResultImportStudent>();
+    }
+
+
     /// <summary>
     /// 双向细目表导入
     /// </summary>
@@ -75,11 +119,11 @@ namespace TEAMModelOS.SDK.Models.Cosmos.School
         /// <summary>
         /// 学生成绩
         /// </summary>
-        public List<ExamImportStudent> students { get; set; }= new List<ExamImportStudent> ();
+        public List<ResultImportStudent> students { get; set; }= new List<ResultImportStudent> ();
 
     }
 
-    public class ExamImportStudent {
+    public class ResultImportStudent {
     
         /// <summary>
         /// 学生id
@@ -161,11 +205,11 @@ namespace TEAMModelOS.SDK.Models.Cosmos.School
     {
         public string subject        { get; set; }
         public List<ImportExamItem> items { get; set; } = new List<ImportExamItem>();
-        public List<ImportExamStudent> students { get; set; } = new List<ImportExamStudent>();
+        public List<ImportResultStudent> students { get; set; } = new List<ImportResultStudent>();
     }
 
 
-    public class ImportExamStudent
+    public class ImportResultStudent
     {
 
         /// <summary>

+ 38 - 5
TEAMModelOS.SDK/Models/Cosmos/School/SchoolSetting.cs

@@ -35,17 +35,50 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         public HashSet<string> lessonTag { get; set; } = new HashSet<string>();
         public LessonSetting lessonSetting { get; set; }= new LessonSetting();
+        /// <summary>
+        /// 五育数据统计规则
+        /// </summary>
         public OverallEducationSetting overallEducationSetting { get; set; } = new OverallEducationSetting();
-        public List<ReviewLevel> reviewLevel { get; set; } = new List<ReviewLevel>();
+       
     }
+
+  
     public class OverallEducationSetting
     {
-        // newest avg sum 
+        // newest最新 avg平均 sum总和 
         public string sports { get; set; } = "newest";
         public string art { get; set; } = "newest";
-        public string labour { get; set; } = "newest";
-        public string intelligence { get; set; } = "newest";
-        public string virtue { get; set; } = "newest";  
+        public string labour { get; set; } = "sum";
+        public string intelligence { get; set; } = "avg";
+        public string virtue { get; set; } = "sum";
+        public List<ReviewLevel> reviewLevel { get; set; } = new List<ReviewLevel>() { 
+            new ReviewLevel { code="A", value = new List<double> { 85,100 } },
+            new ReviewLevel { code="B", value = new List<double> { 75,85 } },
+            new ReviewLevel { code="C", value = new List<double> { 60,75 } } ,
+            new ReviewLevel { code="D", value = new List<double> { 0,60 } } ,
+        };
+        /// <summary>
+        /// 五育默认初始值
+        /// </summary>
+        public double overallEducationInit { get; set; } = 60;
+        /// <summary>
+        /// 推送到五育数据的评测类型
+        /// </summary>
+        public List<string> examTypes { get; set; } = new List<string>();
+        public List<CodeDouble> intelligenceWeight { get; set; } = new List<CodeDouble>() {
+            new CodeDouble { code = "attitude", value = 0.25 },//态度
+            new CodeDouble { code = "cooperate", value = 0.25 },//合作
+            new CodeDouble { code = "ability", value = 0.25 },//能力
+            new CodeDouble { code = "standard", value = 0.25 },//水平
+        };
+    }
+
+    public class CodeDouble
+    {
+        //attitude cooperate  ability  standard
+        public double value { get; set; }
+        public string code { get; set; }
+
     }
     public class LessonSetting
     {

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

@@ -5654,7 +5654,7 @@ const LANG_ZH_CN = {
             noSchool1: '学校暂未购买服务',
             noSchool2: '暂未加入学校',
             copyright: '©2021 HABOOK Group',
-            studentDash: '学生看板',
+            studentDash: '五育看板',
             techDash: '教学看板',
             log: '操作日志',
             elegant: '德育风采',

File diff suppressed because it is too large
+ 1173 - 870
TEAMModelOS/ClientApp/src/common/BaseLayout.vue


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

@@ -1162,6 +1162,16 @@ export const routes = [{
         }
     },
     {
+            name: 'dashSetting',
+            path: '/dashSetting',
+            // component: () => import('@/view/dashboard/StudentAll.vue'),
+            component: () => import('@/view/dashboard/Setting.vue'),
+            meta: {
+                activeName: 'dashSetting',
+                middleware: ['login', 'ability:admin,dashboard-read'],
+            }
+        },
+        {
         name: 'artDashboard',
         path: '/artDashboard',
         component: () => import('@/view/dashboard/Art.vue'),

+ 304 - 0
TEAMModelOS/ClientApp/src/view/dashboard/Setting.vue

@@ -0,0 +1,304 @@
+<template>
+  <div class="dash-setting-container">
+    <div class="box">
+      <p class="title">评价等级分数设置</p>
+      <div class="content art-setting-wrap">
+        <div
+          class="level-item"
+          v-for="(item, index) in schoolSetting.reviewLevel"
+          :key="index"
+        >
+          <span
+            ><span
+              style="
+                color: rgb(25, 185, 224);
+                font-size: 18px;
+                font-weight: bold;
+                margin-right: 10px;
+              "
+              >{{ item.code }}</span
+            >
+            等级分数范围</span
+          >
+          <br />
+          <p
+            style="
+              color: rgb(25, 185, 224);
+              font-weight: bold;
+              margin: 10px 0;
+              font-size: 20px;
+              display: inline-block;
+            "
+          >
+            {{ item.value.join(" ~ ") }} 分
+          </p>
+          <span>
+            <Icon
+              type="md-create"
+              size="16"
+              style="margin-left: 20px; cursor: pointer; display: inline-block"
+              color="#ccc"
+              @click.stop="onLevelClick(item)"
+            ></Icon>
+          </span>
+        </div>
+      </div>
+      <p style="margin-left: 20px; color: #8a8a8a">
+        *
+        评价看板的等级判定根据分数所在区间进行判定,可通过点击编辑按钮进行分数范围调整。
+      </p>
+    </div>
+    <div class="box">
+      <p class="title">智育维度占比设置</p>
+      <div class="art-setting-wrap" style="margin-top: 20px; margin-left: 20px">
+        <p style="margin: 20px 0">
+          学习态度
+          <InputNumber
+            v-model="schoolSetting.percents[0]"
+            :min="0"
+            :max="100"
+            :step="1"
+          ></InputNumber>
+          %
+        </p>
+        <p style="margin: 20px 0">
+          学习合作
+          <InputNumber
+            v-model="schoolSetting.percents[1]"
+            :min="0"
+            :max="100"
+            :step="1"
+          ></InputNumber>
+          %
+        </p>
+        <p style="margin: 20px 0">
+          学习能力
+          <InputNumber
+            v-model="schoolSetting.percents[2]"
+            :min="0"
+            :max="100"
+            :step="1"
+          ></InputNumber>
+          %
+        </p>
+        <p style="margin: 20px 0">
+          学习成效
+          <InputNumber
+            v-model="schoolSetting.percents[3]"
+            :min="0"
+            :max="100"
+            :step="1"
+          ></InputNumber>
+          %
+        </p>
+        <br />
+        <p style="color: #8a8a8a">* 确保四个维度的占比总和为100%。</p>
+      </div>
+    </div>
+    <div class="box">
+      <p class="title">智育评测数据采集设置</p>
+      <div class="art-setting-wrap" style="margin-top: 20px; margin-left: 20px">
+        <CheckboxGroup v-model="chooseTypes">
+          <Checkbox
+            :label="type.name"
+            border
+            v-for="(type, index) in allTypes"
+            :key="index"
+          ></Checkbox>
+        </CheckboxGroup>
+        <br />
+        <p style="color: #8a8a8a">
+          *
+          以上所勾选的类型的评测活动将会被纳入智育数据计算,可通过勾选与取消勾选进行设置。
+        </p>
+      </div>
+    </div>
+    <div class="box">
+      <p class="title">评价初始值设置</p>
+      <p style="margin: 20px">
+        德智体美劳各评价初始分数
+        <InputNumber
+          v-model="schoolSetting.overallEducationInit"
+          :min="0"
+          :max="100"
+          :step="1"
+        ></InputNumber>
+        分
+      </p>
+      <p style="margin-left: 20px; color: #8a8a8a">
+        * 设置例如新学期等场景下学生的五育评价初始分数
+      </p>
+    </div>
+    <Button type="info" @click="updateSetting">保 存</Button>
+    <Modal
+      v-model="setLevelModal"
+      :title="`等级设置`"
+      width="400px"
+      v-if="curLevel"
+    >
+      <p style="margin-bottom: 10px">名称</p>
+      <Input type="text" v-model="curLevel.code"></Input>
+      <p style="margin-top: 20px">分数范围</p>
+      <Slider v-model="curLevel.value" range></Slider>
+      <div slot="footer">
+        <Button type="text" @click="setLevelModal = false">{{
+          $t("knowledge.cancel")
+        }}</Button>
+        <Button type="primary" @click="confirmSetLevel">{{
+          $t("knowledge.confirm")
+        }}</Button>
+      </div>
+    </Modal>
+  </div>
+</template>
+
+<script>
+export default {
+  data() {
+    return {
+      schoolSetting: {
+        reviewLevel: [],
+        examTypes: [],
+        overallEducationInit: 0,
+        percents: [0, 0, 0, 0]
+      },
+      allTypes:[],
+      chooseTypes: [],
+      setLevelModal: false,
+      curLevel: null,
+    };
+  },
+  created() {
+    this.findSchoolSetting();
+  },
+  methods: {
+    findSchoolSetting() {
+      let params = {
+        schoolId: this.$store.state.userInfo.schoolCode,
+      };
+      this.$api.schoolSetting.getSchoolSetting(params).then((res) => {
+        console.log(res);
+        this.schoolSetting = res.setting.overallEducationSetting;
+        this.schoolSetting.percents =
+          res.setting.overallEducationSetting.intelligenceWeight.map(
+            (i) => i.value * 100
+          );
+        let curPeriod = this.$store.state.user.curPeriod;
+        this.allTypes = curPeriod.analysis.type;
+        console.log(res.setting.overallEducationSetting.examTypes);
+        console.log(curPeriod.analysis.type.find(k => k.id === res.setting.overallEducationSetting.examTypes[0]));
+        this.chooseTypes = res.setting.overallEducationSetting.examTypes.map(i => curPeriod.analysis.type.find(k => k.id === i).name)
+        console.log(this.chooseTypes);
+      });
+    },
+    updateSetting() {
+        let settingConfig = this._.cloneDeep(this.schoolSetting)
+        settingConfig.intelligenceWeight.forEach((i,index) => {
+            i.value = Number((this.schoolSetting.percents[index] * 0.01).toFixed(2))
+        })
+        settingConfig.examTypes = this.chooseTypes.map(i => this.allTypes.find(k => k.name === i).id)
+        delete settingConfig.percents
+        this.$api.schoolSetting
+        .upsertSchoolSetting({
+          schoolId: this.$store.state.userInfo.schoolCode,
+          opt: "UpsertOverallEducationSetting",
+          overallEducationSetting: settingConfig,
+        })
+        .then((res) => {
+          if (!res.error) {
+            this.$Message.success(this.$t("knowledge.success"));
+            this.findSchoolSetting()
+          } else {
+            this.$Message.error("Fail");
+          }
+        })
+        .catch((e) => {
+          this.$Message.error("Fail");
+        });
+    },
+    /* 点击等级 */
+    onLevelClick(item) {
+      this.setLevelModal = true;
+      this.curLevel = item;
+    },
+    confirmSetLevel() {
+      this.setLevelModal = false;
+        this.$Message.warning('修改成功,请确认保存您的修改。')
+    },
+  },
+};
+</script>
+
+<style lang="less" scoped>
+.dash-setting-container {
+  display: flex;
+  flex-direction: column;
+  background: #f0f0f0;
+  padding: 0 20px;
+  padding-bottom: 120px;
+  max-height: 99vh;
+  overflow: auto;
+
+  .box {
+    width: 100%;
+    padding: 20px;
+    background: #fff;
+    border-radius: 10px;
+    margin: 20px 0;
+
+    .title {
+      font-size: 14px;
+      font-weight: bold;
+      &::before {
+        content: "";
+        display: inline-block;
+        border: 4px solid #0fa4c1;
+        border-radius: 50%;
+        margin-right: 10px;
+        margin-bottom: 2px;
+      }
+    }
+
+    .content {
+      display: flex;
+      font-size: 14px;
+      margin: 18px;
+
+      .level-item {
+        // background: #ededed;
+        border: 2px solid #ececec;
+        border-radius: 10px;
+        width: 220px;
+        margin: 10px 30px 0 0;
+        padding: 10px 20px;
+      }
+
+      .setting-item {
+        display: flex;
+        align-items: center;
+        margin: 15px 0;
+
+        .ivu-input-number,
+        .ivu-select {
+          margin: 0 10px;
+        }
+      }
+    }
+
+    .ivu-checkbox {
+      margin: 0 10px;
+    }
+
+    .ivu-input-number {
+      margin: 0 10px;
+    }
+  }
+
+  .ivu-btn {
+    height: 40px;
+    padding: 10px 0;
+    width: 200px;
+    border-radius: 50px;
+  }
+}
+</style>

+ 1 - 1
TEAMModelOS/ClientApp/src/view/dashboard/Student.vue

@@ -37,7 +37,7 @@
           <div class="d-flex jc-center">
             <dv-decoration-8 class="dv-dec-8" :color="['#568aea', '#000000']" />
             <div class="title">
-              <span class="dash-title-text">学生五育发展大数据画像</span>
+              <span class="dash-title-text">学生全面发展大数据画像</span>
               <dv-decoration-6
                 class="dv-dec-6"
                 :reverse="true"

+ 38 - 22
TEAMModelOS/ClientApp/src/view/dashboard/fiveEdu/FiveEdu.less

@@ -10,32 +10,46 @@
         "Microsoft JhengHei UI",
         "Microsoft JhengHei";
 
-        .bg {
-            width: 100%;
-            height: 100%;
-            padding: 16px 16px 0 16px;
-            background-image: url("../../../assets/image/pageBg.png");
-            background-size: cover;
-            background-position: center center;
-        }
+    .bg {
+        width: 100%;
+        height: 100%;
+        padding: 16px 16px 0 16px;
+        background-image: url("../../../assets/image/pageBg.png");
+        background-size: cover;
+        background-position: center center;
+    }
 
-        .dv-decoration-8,
-        .dv-decoration-10,
-        .dv-decoration-6 {
-            opacity: 0;
-        }
+    .dv-decoration-8,
+    .dv-decoration-10,
+    .dv-decoration-6 {
+        opacity: 0;
+    }
 
-        .dash-header {
-            position: fixed;
-            top: 0;
-            left: 0;
-            width: 100vw;
-            height: 70px;
-            background: url('https://ydzt.cdwalker.com/health/static/img/header.d55c582c.png') no-repeat;
-            background-size: 100% 100%;
-            z-index: 0;
+    .dash-header {
+        position: absolute;
+        top: 0;
+        left: 0;
+        width: 100vw;
+        height: 70px;
+        background: url('https://ydztshow.cdwalker.com/health/static/img/header.d55c582c.png') no-repeat;
+        background-size: 100% 100%;
+        z-index: 0;
         }
 
+    .period-tag {
+        position: absolute;
+        top: 3px;
+        right: 10px;
+        font-size: 14px;
+        display: flex;
+        align-items: center;
+        font-weight: 700;
+        color: #64a4db;
+        padding: 2px 10px;
+        border-radius: 4px;
+        z-index: 1;
+    }
+
     .border-box-content {
         padding: 15px;
     }
@@ -131,6 +145,8 @@
         }
     }
 
+
+
     .ivu-cascader .ivu-cascader-menu-item {
         color: rgb(255, 255, 255) !important;
     }

+ 6 - 5
TEAMModelOS/ClientApp/src/view/dashboard/fiveEdu/FiveEdu.vue

@@ -29,6 +29,7 @@
             @click="goBack"
           ></span>
         </div>
+       <span class="period-tag">{{ schoolInfo.schoolName + '-' + schoolInfo.periodName }}</span>
         <div class="school-info">
           <div class="dash-menus" style="display: flex">
             <div
@@ -58,8 +59,8 @@
                 style="position: absolute; right: 10%; top: 5px"
               >
                 <template slot="content">
-                  <p style="color: #fff">目标:立德树人,五育融合</p>
-                  <p style="color: #fff">标准:素养导向,课标准</p>
+                  <p style="color: #fff">目标:立德树人,科学评价</p>
+                  <p style="color: #fff">标准:素养导向,课标准</p>
                   <p style="color: #fff">方法:工具赋能,自动采集</p>
                 </template>
                 <!-- <Icon type="md-help-circle" class="icon-tip" /> -->
@@ -194,7 +195,7 @@
                           "
                         ></BaseDashTip>
                         <BaseDashTab
-                          :tabs="['学业成效表现', '学习过程表现']"
+                          :tabs="['学习过程表现','学业成效表现']"
                           @tab-change="onLineBarTabChange"
                         ></BaseDashTab>
                       </div>
@@ -359,7 +360,7 @@ import BaseCarousel from "../moral/BaseCarousel";
 export default {
   data() {
     return {
-      lineBarType: "exam",
+      lineBarType: "study",
       noAuthName: "劳动教育",
       noAuthModal: false,
       curStuIndex: -1,
@@ -601,7 +602,7 @@ export default {
         val === 0 ? parseInt(stuCount * 0.96) : parseInt(stuCount * 0.88);
     },
     onLineBarTabChange(val) {
-      this.lineBarType = val === 0 ? "exam" : "study";
+      this.lineBarType = val === 1 ? "exam" : "study";
     },
     onStuRankChange(index) {
       this.$nextTick(() => {

+ 2 - 4
TEAMModelOS/ClientApp/src/view/research-center/ReportPreview.vue

@@ -301,12 +301,10 @@ export default {
       this.staticArr = new Array(8).fill(0)
     }
 
-
-
-    // 计算获灯情况
+    // 计算获灯情况 双灰色的灯代表未收集到数据 暂不处理
     let greenCount = list.filter(i => i.pLevel === 2 && i.tLevel === 2).length
     let redCount = list.filter(i => i.pLevel === 0 && i.tLevel === 0).length
-    let singleCount = list.length - greenCount - redCount
+    let singleCount = list.filter(i => (i.pLevel === 2 && i.tLevel !== 2) || (i.pLevel !== 2 && i.tLevel === 2)).length
     this.lightCountArr = [
       greenCount,
       singleCount,

+ 339 - 171
TEAMModelOS/Controllers/School/ImportExamController.cs

@@ -6,12 +6,15 @@ using Microsoft.AspNetCore.Mvc;
 using Microsoft.Azure.Amqp.Framing;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Options;
+using NUnit.Framework;
 using OfficeOpenXml;
+using OpenXmlPowerTools;
 using StackExchange.Redis;
 using System;
 using System.Collections.Generic;
 using System.ComponentModel;
 using System.Linq;
+using System.Runtime.Intrinsics.Arm;
 using System.Text.Json;
 using System.Threading.Tasks;
 using TEAMModelOS.Filter;
@@ -19,6 +22,7 @@ using TEAMModelOS.Models;
 using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Helper.Security.ShaHash;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.School;
 
@@ -59,15 +63,81 @@ namespace TEAMModelOS.Controllers
             _configuration = configuration;
             _httpTrigger = httpTrigger;
         }
+        // [AuthToken(Roles = "teacher,admin")]
+        [HttpPost("read-excel-virtue")]
+        //[Authorize(Roles = "IES")]
+        [AuthToken(Roles = "teacher,admin,business")]
+        [RequestSizeLimit(102_400_000_00)] //最大10000m左右
+        public async Task<IActionResult> ReadExcelVirtue([FromForm] IFormFile file, [FromForm] string periodId) {
+            List<KeyValuePair<string, List<string>>> error = new List<KeyValuePair<string, List<string>>>();
+            List<KeyValuePair<string, List<string>>> warn = new List<KeyValuePair<string, List<string>>>();
+            var (id, _, _, school) = HttpContext.GetAuthTokenInfo();
+            ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
+            List<VirtueImport> virtueImports = new List<VirtueImport> {  };
+            using (ExcelPackage package = new ExcelPackage(file.OpenReadStream())) {
+                ExcelWorksheets sheet = package.Workbook.Worksheets;
+                //德育数据导入
+                School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new Azure.Cosmos.PartitionKey("Base"));
+                Period period = schoolBase.period.Find(x => x.id.Equals(periodId));
+                var daily_sheets = sheet.Where(z => !z.Name.Equals("栏位说明"));
+                HashSet<IdNameCode> rightStudents = new HashSet<IdNameCode>();
+                List<Class> classes = new List<Class>();
+                foreach (var daily_sheet in daily_sheets)
+                {
+                    if (DateTimeOffset.TryParse(daily_sheet.Name, out DateTimeOffset sheetNameTime))
+                    {
 
+                        var data = GetSubSheetData(daily_sheet, error);
+                        Dictionary<string, object> dailyData = new Dictionary<string, object> { { "subject", "德育" }, { "students", data.students } };
+                        ImportExamSubject importExamDaily = dailyData.ToJsonString().ToObject<ImportExamSubject>();
+                        var subject = period.subjects.Find(z => z.name.Equals(importExamDaily.subject));
+                        if (subject != null)
+                        {
+                            List<ResultImportStudent> examImportStudents = new List<ResultImportStudent>();
+                            //学生
+                            await ExamImportStudent(importExamDaily.students, rightStudents, school, period, examImportStudents, error, warn, classes, daily_sheet.Name);
+                            var semesterData=  SchoolService.GetSemester(period, sheetNameTime.ToUnixTimeMilliseconds());
+                            var group = examImportStudents.GroupBy(x => x.classId).Select(y => new { key = y.Key,list= y.ToList()} );
+                            foreach (var groupData in group) {
+                                VirtueImport virtueImport = new VirtueImport
+                                {
+                                    time = sheetNameTime.ToUnixTimeMilliseconds(),
+                                    id = $"{semesterData.studyYear}-{semesterData.currSemester.id}-{groupData.key}",
+                                    code = $"VirtueImport-{school}",
+                                    pk = "VirtueImport",
+                                    ttl = -1,
+                                    semesterId = semesterData.currSemester.id,
+                                    periodId = period.id,
+                                    type = "日常",
+                                    school = school,
+                                    year = semesterData.studyYear,
+                                    classId=groupData.key,
+                                    students = groupData.list,
+                                    name=$"{semesterData.studyYear}-{semesterData.currSemester.name}"
+                                };
+                                virtueImports.Add(virtueImport);
+                            }
+                        }
+                        else
+                        {
+                            error.Add(new KeyValuePair<string, List<string>>("subject_invalid", new List<string> { importExamDaily.subject }));// 科目不存在
+                        }
+                    }
+                    else { 
+                     
+                    }
+                }
+            }
+            return Ok(new { virtueImports, error,warn});
+        }
         // [AuthToken(Roles = "teacher,admin")]
-        [HttpPost("read-excel")]
+        [HttpPost("read-excel-exam")]
         //[Authorize(Roles = "IES")]
         [AuthToken(Roles = "teacher,admin,business")]
         [RequestSizeLimit(102_400_000_00)] //最大10000m左右
         public async Task<IActionResult> ReadExcel([FromForm] IFormFile file,[FromForm] string periodId) {
-            List<string> error = new List<string>();
-            List<string> warn = new List<string>();
+            List<KeyValuePair<string, List<string>>> error = new List<KeyValuePair<string, List<string>>>();
+            List<KeyValuePair<string, List<string>>> warn = new List<KeyValuePair<string, List<string>>>();
             var (id, _, _, school) = HttpContext.GetAuthTokenInfo();
             ExcelPackage.LicenseContext = OfficeOpenXml.LicenseContext.NonCommercial;
             using (ExcelPackage package = new ExcelPackage(file.OpenReadStream()))
@@ -166,8 +236,8 @@ namespace TEAMModelOS.Controllers
                                     item.Add(itemTitle[j], index);
                                 }
                                 else {
-                                    error.Add("index_invalid");// 题目序列只能是正整数
-                                    return Ok(new { code = 400, error, data = itemDatas[i][j] });
+
+                                    error.Add(new KeyValuePair<string, List<string>>("index_invalid",new List<string> { itemDatas[i][j] } ));// 题目序列只能是正整数
                                 }
                                 
                             }
@@ -182,8 +252,7 @@ namespace TEAMModelOS.Controllers
                                 }
                                 else
                                 {
-                                    error.Add("score_invalid");// 配分只能是数字
-                                    return Ok(new { code = 400, error, data = itemDatas[i][j] });
+                                    error.Add(new KeyValuePair<string, List<string>>("score_invalid", new List<string> { itemDatas[i][j] }));//  配分只能是数字
                                 }
 
                             }
@@ -201,198 +270,300 @@ namespace TEAMModelOS.Controllers
                     foreach (var subject in subjects) {
                       
                         var subject_sheet = sheet.Where(z => z.Name.StartsWith($"Sub_{subject}")).FirstOrDefault();
-                        var data = GetSubSheetData(subject_sheet);
+                        var data = GetSubSheetData(subject_sheet,error);
                         var items = itemInfo.FindAll(x => x["subject"].Equals(subject));
-                        if (data.error.Any()) {
-                            return Ok(new { code = 400, error= data.error, data = data.errorData});
-                        }
+                       
                         Dictionary<string, object> subjectData = new Dictionary<string, object> { { "subject", subject } ,{ "items",items },{ "students", data.students } };
                         subjectDatas.Add(subjectData);
                     }
                 }
-                //德育数据导入
-                {
-                    var subject_sheet = sheet.Where(z => z.Name.StartsWith($"Sub_德育")).FirstOrDefault();
-                    var data = GetSubSheetData(subject_sheet);
-                    if (data.error.Any())
-                    {
-                        return Ok(new { code = 400, error= data.error, data = data.errorData });
-                    }
-                    Dictionary<string, object> subjectData = new Dictionary<string, object> { { "subject", "德育" },  { "students", data.students } };
-                    subjectDatas.Add(subjectData);
-                }
+               
                 baseInfo.Add("periodId", periodId);
                 baseInfo.Add("school", school);
                 baseInfo.Add("subjects", subjectDatas);
                 var importExam  =baseInfo.ToJsonString().ToObject<ImportExam>();
                 var validData = importExam.Valid();
-                if (!validData.isVaild)
+                ExamImport examImport = null;
+                School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(importExam.school, new Azure.Cosmos.PartitionKey("Base"));
+                Period period = schoolBase.period.Find(x => x.id.Equals(importExam.periodId));
+                if (validData.isVaild)
                 {
-                    return Ok(new { code = 400, error = validData.errors.SelectMany(z => z.Value).ToList() });
+                    string sql = $"select value c from c where c.name ='{importExam.name}'";
+                    var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Common).GetList<ExamImport>(sql, $"ExamImport-{importExam.school}", pageSize: 1);
+                   
+                    if (string.IsNullOrEmpty(result.continuationToken))
+                    {
+                        warn.Add(new KeyValuePair<string, List<string>>("name_duplicate", new List<string> { importExam.name }));//评测名称重复
+                    }
+                    if (result.list.IsNotEmpty())
+                    {
+                        examImport = result.list[0];
+                        warn.Add(new KeyValuePair<string, List<string>>("name_update", new List<string> { importExam.name }));//同名评测数据更新
+
+                    }
+                    if (examImport == null)
+                    {
+                        examImport = new ExamImport { name = importExam.name, type = importExam.type, school = importExam.school,periodId=period.id,code= $"ExamImport-{importExam.school}",pk= "ExamImport", };
+                        if (DateTimeOffset.TryParse(importExam.time, out DateTimeOffset dateTime))
+                        {
+                            examImport.time = dateTime.ToUnixTimeMilliseconds();
+                            var semesterData= SchoolService.GetSemester(period, examImport.time);
+                            examImport.semesterId = semesterData.currSemester.id;
+                            examImport.id = $"{semesterData.studyYear}-{ShaHashHelper.GetSHA1(examImport.name)}";
+                        }
+                        else
+                        {
+                            error.Add(new KeyValuePair<string, List<string>>("time_format", new List<string> { importExam.time }));//  时间格式错误
+                        }
+                    }
+
+                  
+
+                    if (period != null)
+                    {
+                        //用于处理多学科,不需要重复查询学习基础信息
+                        //id  学生id  code 行政班id  name  学生姓名
+                        HashSet<IdNameCode> rightStudents = new HashSet<IdNameCode>();
+                        List<Class> classes = new List<Class>();
+                        foreach (var item in importExam.subjects)
+                        {
+                            var subject = period.subjects.Find(z => z.name.Equals(item.subject));
+                            if (subject != null)
+                            {
+                                List<ResultImportStudent> examImportStudents = new List<ResultImportStudent>();
+                                //学生
+                               await  ExamImportStudent(item.students, rightStudents, school, period, examImportStudents, error, warn, classes, item.subject);
+
+                                examImport.subjects.Add(new ExamImportSubject { id = subject.id, name = subject.name, students = examImportStudents, }) ;
+                            }
+                            else
+                            {
+                                error.Add(new KeyValuePair<string, List<string>>("subject_invalid", new List<string> { item.subject }));// 科目不存在
+                            }
+                        }
+                    }
+                    else
+                    {
+                        error.Add(new KeyValuePair<string, List<string>>("period_invalid",new List<string> { importExam.periodId }));// 学段不存在
+                    }
                 }
-              
-                string sql = $"select value c from c where c.name ='{importExam.name}'";
-                var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<ExamImport>(sql, $"ExamImport-{importExam.school}", pageSize: 1);
-                ExamImport examImport = null;
-                if (string.IsNullOrEmpty(result.continuationToken))
+                else {
+                    validData.errors.SelectMany(z => z.Value).ToList().ForEach(x => {
+                        error.Add(new KeyValuePair<string, List<string>>(x, new List<string> { }));
+                    });
+                }
+                List<KeyValuePair<string, HashSet<string>>> errorData = new List<KeyValuePair<string, HashSet<string>>>();
+                error.ForEach(x => {
+                    var value = errorData.Find(z => z.Key.Equals(x.Key));
+                    if (!string.IsNullOrWhiteSpace(value.Key))
+                    {
+                        x.Value.ForEach(z => { value.Value.Add(z); });
+                    }
+                    else {
+                        errorData.Add(new KeyValuePair<string, HashSet<string>>(x.Key,x.Value.ToHashSet()));
+                    }
+                });
+                return Ok(new { code = 400, error = errorData, examImport });
+            } 
+        }
+
+        private async Task ExamImportStudent(List<ImportResultStudent> importExamStudents, HashSet<IdNameCode> rightStudents,string  school,
+            Period period, List<ResultImportStudent> examImportStudents, List<KeyValuePair<string, List<string>>> error,
+            List<KeyValuePair<string, List<string>>> warn, List<Class> classes, string sheetName)
+        {
+            // 学号确定的学生
+            var hasIdStudents = importExamStudents.Where(z => !string.IsNullOrWhiteSpace(z.id));
+            var needSearch = hasIdStudents.ExceptBy(rightStudents.Select(x => x.id), hasId => hasId.id).ToList();
+            List<ImportResultStudent> notExistIds = new List<ImportResultStudent>();
+            //通过id在数据库和rightStudents 都找不到的学生
+            List<ImportResultStudent> evenNotExistIds = new List<ImportResultStudent>();
+            if (needSearch.Any())
+            {
+                ///在rightStudents找不到的学生需要查询数据库。
+                string stuidsql = $"select c.id,c.classId as code , c.name  from  c where c.id in ({string.Join(",", needSearch.Select(x => $"'{x.id}'"))}) and c.periodId='{period.id}' ";
+                var sturesult = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<IdNameCode>(stuidsql, $"Base-{school}");
+                if (sturesult.list.IsNotEmpty())
+                {
+                    sturesult.list.ForEach(x => {
+                        var exist = rightStudents.Where(y => y.id.Equals(x.id));
+                        if (!exist.Any())
+                        {
+                            rightStudents.Add(x);
+                        }
+                    });
+                    //needSearch与  sturesult.list(数据库)查找的对比,仍然没有找到的学生。
+                    var notInDb = needSearch.ExceptBy(sturesult.list.Select(x => x.id), y => y.id);
+                    if (notInDb.Any())
+                    {
+                        evenNotExistIds.AddRange(notInDb);
+                    }
+                }
+                else
                 {
-                    warn.Add("name_duplicate");//评测名称重复
+                    evenNotExistIds.AddRange(needSearch);
                 }
-                if (result.list.IsNotEmpty())
+            }
+            foreach (var item in hasIdStudents) 
+            {
+                var existStudent = rightStudents.Where(n => n.id.Equals(item.id));
+                if (existStudent .Any())
                 {
-                    examImport = result.list[0];
-                    warn.Add("name_update");//同名评测数据更新
+                    long time = 0;
+                    if (DateTimeOffset.TryParse(item.time, out DateTimeOffset dateTime))
+                    {
+                        time = dateTime.ToUnixTimeMilliseconds();
+                    }
+                    examImportStudents.Add(new ResultImportStudent
+                    {
+                        id = item.id,
+                        name = existStudent.First().name,
+                        classId = existStudent.First().code,
+                        score = item.score,
+                        scores = item.scores,
+                        time = time,
+                        items = item.items,
+                    });
                 }
-                if (examImport == null)
+            }
+            //id信息在数据库找不到的 且班级和姓名不全,
+            var hasNameClassid = evenNotExistIds.Where(x => !string.IsNullOrWhiteSpace(x.name) && !string.IsNullOrWhiteSpace(x.classId));
+            var notexistStudent = evenNotExistIds.Except(hasNameClassid);
+            if (notexistStudent.Any())
+            {
+                error.Add(new KeyValuePair<string, List<string>>("student_notexist", notexistStudent.Select(x => $"id:{x.id}_name:{x.name}_classId:{x.classId}").ToList()));//没有班级和姓名不全,且id信息在数据库找不到的
+            }
+            //没有学号 ,且姓名和班级信息不全的
+            var studentInvalid = importExamStudents.Where(z => string.IsNullOrWhiteSpace(z.id) && (string.IsNullOrWhiteSpace(z.name) || string.IsNullOrWhiteSpace(z.classId)));
+            if (studentInvalid.Any())
+            {
+                error.Add(new KeyValuePair<string, List<string>>("student_invalid", studentInvalid.Select(x => $"id:{x.id}_name:{x.name}_classId:{x.classId}").ToList()));// 学生信息不全
+            }
+            //没有id ,但是存在姓名和班级信息
+            var classesStu = importExamStudents.Where(z => !string.IsNullOrWhiteSpace(z.classId) && !string.IsNullOrWhiteSpace(z.name) && string.IsNullOrWhiteSpace(z.id)).ToHashSet();
+            if (hasNameClassid.Any())
+            {
+                hasNameClassid.ToList().ForEach(x => classesStu.Add(x));
+            }
+            var group = classesStu.GroupBy(x => x.classId);
+
+            //不能被拆分的以班级名称查找。
+            foreach (var classGroupStudents in group)
+            {
+                Class clzz = null;
+                bool isClassName = false;
+                string className = string.Empty;
+                var cls = classGroupStudents.Key.Split("-");
+                var classStudents = classGroupStudents.ToList();
+                var duplicateStudents = new List<ImportResultStudent>();
+                classStudents.GroupBy(z => z.name).Select(z => new { key = z.Key, list = z.ToList() }).ToList().ForEach(y => {
+                    if (y.list.Count > 1)
+                    {
+                        duplicateStudents.AddRange(y.list);
+                        error.Add(new KeyValuePair<string, List<string>>("stuname_duplicate", y.list.Select(z => $"{sheetName}-{z.name}").ToList()));
+                    }
+                });
+                if (duplicateStudents.IsNotEmpty())
+                {
+                    duplicateStudents.ForEach(z => { classStudents.Remove(z); });
+                }
+                if (cls.Length == 2 && int.TryParse(cls[0], out int year) && year > 2000 && int.TryParse(cls[1], out int no) && no > 0)
                 {
-                    examImport = new ExamImport { name = importExam.name, type = importExam.type, school = importExam.school };
-                    if (DateTimeOffset.TryParse(importExam.time, out DateTimeOffset dateTime))
+
+                    var existInTemp = classes.FindAll(z => z.year == year && z.no.Equals(cls[1]));
+                    if (existInTemp.Any())
                     {
-                        examImport.time = dateTime.ToUnixTimeMilliseconds();
+                        clzz = existInTemp.First();
                     }
                     else
                     {
-                        error.Add("time_format");// 时间格式错误
-                        return Ok(new { code = 400, error,data=new List<string>() { importExam.time } });
+                        string sqlClazz = $"select value c from c where c.year={year} and c.no ='{cls[1]}' and c.periodId='{period.id}' ";
+                        var classresult = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Class>(sqlClazz, $"Class-{school}", pageSize: 1);
+                        if (classresult.list.IsNotEmpty())
+                        {
+                            clzz = classresult.list[0];
+                            classes.Add(clzz);
+                        }
+                        else
+                        {
+                            className = classGroupStudents.Key;
+                            isClassName = true;
+                        }
                     }
                 }
-
-                School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(importExam.school, new Azure.Cosmos.PartitionKey("Base"));
-                Period period = schoolBase.period.Find(x => x.id.Equals(importExam.periodId));
-               
-                if (period != null)
-                { 
-                    //用于处理多学科,不需要重复查询学习基础信息
-                    //id  学生id  code 行政班id  name  学生姓名
-                    HashSet<IdNameCode> rightStudents = new HashSet<IdNameCode>();
-                    foreach (var item in importExam.subjects)
+                else
+                {
+                    className = classGroupStudents.Key;
+                    isClassName = true;
+                }
+                if (isClassName)
+                {
+                    var existInTemp = classes.FindAll(z => z.name.Equals(className));
+                    if (existInTemp.Any())
                     {
-                        var subject = period.subjects.Find(z => z.name.Equals(item.subject));
-                        if (subject != null)
+                        clzz = existInTemp.First();
+                    }
+                    else
+                    {
+                        string sqlClazz = $"select value c from c where c.name ='{className}' and c.periodId='{period.id}' ";
+                        var classresult = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Class>(sqlClazz, $"Class-{school}", pageSize: 1);
+                        if (classresult.list.IsNotEmpty())
                         {
-                            List<ExamImportStudent> examImportStudents = new List<ExamImportStudent>();
-                            //学生
+                            clzz = classresult.list[0];
+                            classes.Add(clzz);
+                        }
+                        else
+                        {
+                            error.Add(new KeyValuePair<string, List<string>>("class_invalid", new List<string> { $"{sheetName}-{className}" }));// 班级错误
+                        }
+                    }
+                }
+                if (clzz != null)
+                {
+                    string stuClassIdsql = $"select c.id,c.classId as code , c.name  from  c where c.name  in ({string.Join(",", classStudents.Select(x => $"'{x.name}'"))}) and c.classId ='{clzz.id}' and c.periodId='{period.id}' ";
+                    var sturesult = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<IdNameCode>(stuClassIdsql, $"Base-{school}");
+                    //检查重名
+                    if (sturesult.list.IsNotEmpty())
+                    {
+                        var groupNames = sturesult.list.GroupBy(x => x.name).Select(x => new { key = x.Key, list = x.ToList() }).Where(y => y.list.Count > 1);
+                        if (groupNames.Any())
+                        {
+                            warn.Add(new KeyValuePair<string, List<string>>("stuname_duplicate", groupNames.Select(x => $"{sheetName}-{x.key}").ToList()));//学生姓名重复
+                        }
+                        foreach (var stu in classesStu)
+                        {
+                            var student = sturesult.list.FindAll(x => x.name.Equals(stu.name));
+                            if (student.Any())
                             {
-                                // 学号确定的学生
-                                var hasIdStudents = item.students.Where(z => !string.IsNullOrWhiteSpace(z.id));
-                                var needSearch = hasIdStudents.ExceptBy(rightStudents.Select(x => x.id), hasId => hasId.id);
-                                List<ImportExamStudent> notExistIds = new List<ImportExamStudent>();
-                                //通过id在数据库和rightStudents 都找不到的学生
-                                List<ImportExamStudent> evenNotExistIds = new List<ImportExamStudent>();
-                                if (needSearch.Any())
-                                {
-                                    ///在rightStudents找不到的学生需要查询数据库。
-                                    string stuidsql = $"select c.id,c.classId as code , c.name  from  c where c.id in ({needSearch.Select(x => $"'{x.id}'")}) and c.periodId='{period.id}' ";
-                                    var sturesult = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<IdNameCode>(stuidsql, $"Base-{school}");
-                                    if (sturesult.list.IsNotEmpty())
-                                    {
-                                        sturesult.list.ForEach(x => {
-                                            var exist = rightStudents.Where(x => x.id.Equals(x.id));
-                                            if (!exist.Any())
-                                            {
-                                                rightStudents.Add(x);
-                                            }
-                                            else
-                                            {
-                                                var existStudent = needSearch.Where(n => n.id.Equals(x.id)).FirstOrDefault();
-                                                if (existStudent!=null) {
-                                                    long time = 0;
-                                                    if (DateTimeOffset.TryParse(existStudent.time, out DateTimeOffset dateTime))
-                                                    {
-                                                        time = dateTime.ToUnixTimeMilliseconds();
-                                                    }
-                                                    examImportStudents.Add(new ExamImportStudent {
-                                                        id = existStudent.id,
-                                                        name = x.name,
-                                                        classId = x.code,
-                                                        score = existStudent.score,
-                                                        scores = existStudent.scores,
-                                                        time = time
-                                                    });
-                                                }
-                                            }
-                                        });
-                                        //needSearch与  sturesult.list(数据库)查找的对比,仍然没有找到的学生。
-                                        var notInDb = needSearch.ExceptBy(sturesult.list.Select(x => x.id), y => y.id);
-                                        if (notInDb.Any())
-                                        {
-                                            evenNotExistIds.AddRange(notInDb);
-                                        }
-                                    }
-                                    else
-                                    {
-                                        evenNotExistIds.AddRange(needSearch);
-                                    }
-                                }
-                                //id信息在数据库找不到的 且班级和姓名不全,
-                                var hasNameClassid = evenNotExistIds.Where(x => !string.IsNullOrWhiteSpace(x.name) && !string.IsNullOrWhiteSpace(x.classId));
-                                var notexistStudent = evenNotExistIds.Except(hasNameClassid);
-                                if (notexistStudent.Any())
-                                {
-                                    error.Add("student_notexist");//没有班级和姓名不全,且id信息在数据库找不到的
-                                    return Ok(new { code = 400, error, data = notexistStudent.Select(x => $"id:{x.id}_name:{x.name}_classId:{x.classId}") });
-                                }
-                                //没有学号 ,且姓名和班级信息不全的
-                                var studentInvalid = item.students.Where(z => string.IsNullOrWhiteSpace(z.id) && (string.IsNullOrWhiteSpace(z.name) || string.IsNullOrWhiteSpace(z.classId)));
-                                if (studentInvalid.Any())
-                                {
-                                    error.Add("student_invalid");// 学生信息不全
-                                    return Ok(new { code = 400, error, data = studentInvalid.Select(x => $"id:{x.id}_name:{x.name}_classId:{x.classId}") });
-                                }
-                                //没有id ,但是存在姓名和班级信息
-                                var classesStu = item.students.Where(z => !string.IsNullOrWhiteSpace(z.classId) && !string.IsNullOrWhiteSpace(z.name) && string.IsNullOrWhiteSpace(z.id)).ToHashSet();
-                                if (hasNameClassid.Any())
-                                {
-                                    hasNameClassid.ToList().ForEach(x => classesStu.Add(x));
-                                }
-                                var group = classesStu.GroupBy(x => x.classId);
 
-                                //不能被拆分的以班级名称查找。
-                                HashSet<string> classNames = new HashSet<string>();
-                                foreach (var clazz in group)
+                                long time = 0;
+                                if (DateTimeOffset.TryParse(stu.time, out DateTimeOffset dateTime))
                                 {
-                                    var cls = clazz.Key.Split("-");
-                                    if (cls.Length == 2 && int.TryParse(cls[0], out int year) && year > 2000 && int.TryParse(cls[1], out int no) && no > 0)
-                                    {
-                                        string sqlClazz = $"select value c from c where c.year={year} and c.no ='{cls[1]}' and c.periodId='{period.id}' ";
-                                        var classresult = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Class>(sqlClazz, $"Class-{school}");
-                                        if (classresult.list.IsNotEmpty())
-                                        {
-                                            Class clzz = classresult.list[0];
-                                            string stuClassIdsql = $"select c.id,c.classId as code , c.name  from  c where c.name  in ({clazz.ToList().Select(x => $"'{x.name}'")}) and c.classId ='{clzz.id}' and c.periodId='{period.id}' ";
-                                            var sturesult = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).GetList<IdNameCode>(stuClassIdsql, $"Base-{school}");
-                                            //检查重名
-                                        }
-                                        else
-                                        {
-                                            classNames.Add(clazz.Key);
-                                        }
-                                    }
-                                    else
-                                    {
-                                        classNames.Add(clazz.Key);
-                                    }
+                                    time = dateTime.ToUnixTimeMilliseconds();
                                 }
+                                examImportStudents.Add(new ResultImportStudent
+                                {
+                                    id = student[0].id,
+                                    name = student[0].name,
+                                    classId = student[0].code,
+                                    score = stu.score,
+                                    scores = stu.scores,
+                                    time = time,
+                                    items = stu.items
+                                });
                             }
                         }
-                        else
-                        {
-                            error.Add("subject_invalid");// 科目不存在
-                            return Ok(new { code = 400, error, data =new List<string>() { item.subject } });
-                        }
+                    }
+                    else
+                    {
+                        error.Add(new KeyValuePair<string, List<string>>("student_invalid", classGroupStudents.ToList().Select(x => $"{sheetName}-{x.name}").ToList()));
                     }
                 }
-                else {
-                    error.Add("period_invalid");// 学段不存在
-                    return Ok(new { code = 400, error, data = new List<string>() { importExam.periodId } });
-                }
-                return Ok(new {baseInfo });
-            } 
+            }
+
         }
 
-        private (List<Dictionary<string, object>> students, HashSet<string> error, HashSet<string> errorData) GetSubSheetData(ExcelWorksheet subject_sheet) {
-            HashSet<string> error = new HashSet<string>();
-            HashSet<string> errorData = new HashSet<string>();
+
+        private (List<Dictionary<string, object>> students, List<KeyValuePair<string, List<string>>> error) GetSubSheetData(ExcelWorksheet subject_sheet, List<KeyValuePair<string, List<string>>> error) {
             List<Dictionary<string, object>> students = new List<Dictionary<string, object>>();
             List<string> titles = new List<string>();
             List<List<string>> datas = new List<List<string>>();
@@ -461,8 +632,7 @@ namespace TEAMModelOS.Controllers
                             items.Add(new ItemVlaue() { code = titles[j].Replace("item_", ""), value = score });
                         }
                         else {
-                            error.Add("score_invalid");// 得分只能是数字
-                            errorData.Add(datas[i][j]);
+                            error.Add(new KeyValuePair<string, List<string>>("score_invalid",new List<string> { datas[i][j] }));// 得分只能是数字
                         }
                         
                     }
@@ -479,8 +649,7 @@ namespace TEAMModelOS.Controllers
                                 item.Add(titles[j], 0);
                             }
                             else {
-                                error.Add("score_invalid");// 得分只能是数字
-                                errorData.Add(datas[i][j]);
+                                error.Add(new KeyValuePair<string, List<string>>("score_invalid", new List<string> { datas[i][j] }));// 得分只能是数字
                             }
                         }
                         else {
@@ -504,8 +673,7 @@ namespace TEAMModelOS.Controllers
                     }
                     else
                     {
-                        error.Add("score_invalid");// 得分只能是数字
-                        errorData.Add(datas[i][orders[j].Value]);
+                        error.Add(new KeyValuePair<string, List<string>>("score_invalid", new List<string> { datas[i][orders[j].Value] }));// 得分只能是数字
                     }
                    
                 }
@@ -520,7 +688,7 @@ namespace TEAMModelOS.Controllers
                 students.Add(item);
             }
            
-            return (students,error,errorData);
+            return (students,  error);
         }
 
       

+ 4 - 4
TEAMModelOS/Controllers/School/SchoolSettingController.cs

@@ -164,12 +164,12 @@ namespace TEAMModelOS.Controllers
                     LessonSetting lessonSetting = _lessonSetting.ToObject<LessonSetting>();
                     setting.lessonSetting = lessonSetting;
                     break;
-                case bool when $"{_opt}".Equals("UpsertReviewLevel", StringComparison.OrdinalIgnoreCase) && (json.TryGetProperty("reviewLevel", out JsonElement _reviewLevel)):
-                    List<ReviewLevel> reviewLevel = _reviewLevel.ToObject<List<ReviewLevel>>();
+                case bool when $"{_opt}".Equals("UpsertOverallEducationSetting", StringComparison.OrdinalIgnoreCase) && (json.TryGetProperty("overallEducationSetting", out JsonElement _overallEducationSetting)):
+                    OverallEducationSetting overallEducationSetting = _overallEducationSetting.ToObject<OverallEducationSetting>();
 
-                    if (reviewLevel.IsNotEmpty())
+                    if (overallEducationSetting!=null)
                     {
-                        setting.reviewLevel = reviewLevel;
+                        setting.overallEducationSetting = overallEducationSetting;
                     }
                     break;
                 default: break;

+ 32 - 32
TEAMModelOS/appsettings.Development.json

@@ -22,48 +22,48 @@
   },
   "Azure": {
     //测试站数据库
-    //"Storage": {
-    //  "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodeltest;AccountKey=O2W2vadCqexDxWO+px+QK7y1sHwsYj8f/WwKLdOdG5RwHgW/Dupz9dDUb4c1gi6ojzQaRpFUeAAmOu4N9E+37A==;EndpointSuffix=core.chinacloudapi.cn"
-    //},
-    //"Cosmos": {
-    //  "ConnectionString": "AccountEndpoint=https://cdhabookdep-free.documents.azure.cn:443/;AccountKey=JTUVk92Gjsx17L0xqxn0X4wX2thDPMKiw4daeTyV1HzPb6JmBeHdtFY1MF1jdctW1ofgzqkDMFOtcqS46by31A==;"
-    //},
-    //"Redis": {
-    //  "ConnectionString": "52.130.252.100:6379,password=habook,ssl=false,abortConnect=False,writeBuffer=10240"
-    //},
-    //"ServiceBus": {
-    //  "ConnectionString": "Endpoint=sb://teammodelos.servicebus.chinacloudapi.cn/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=Sy4h4EQ8zP+7w/lOLi1X3tGord/7ShFHimHs1vC50Dc=",
-    //  "ActiveTask": "dep-active-task",
-    //  "ItemCondQueue": "dep-itemcond",
-    //  "GenPdfQueue": "dep-genpdf"
-    //},
-    //"SignalR": {
-    //  "ConnectionString": "Endpoint=https://channel.service.signalr.net;AccessKey=KrblW06tuA4a/GyqRPDU0ynFFmAWxbAvyJihHclSXbQ=;Version=1.0;"
-    //}
-    // 正式站数据库
     "Storage": {
-      "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodelos;AccountKey=Dl04mfZ9hE9cdPVO1UtqTUQYN/kz/dD/p1nGvSq4tUu/4WhiKcNRVdY9tbe8620nPXo/RaXxs+1F9sVrWRo0bg==;EndpointSuffix=core.chinacloudapi.cn"
+      "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodeltest;AccountKey=O2W2vadCqexDxWO+px+QK7y1sHwsYj8f/WwKLdOdG5RwHgW/Dupz9dDUb4c1gi6ojzQaRpFUeAAmOu4N9E+37A==;EndpointSuffix=core.chinacloudapi.cn"
     },
     "Cosmos": {
-      "ConnectionString": "AccountEndpoint=https://teammodelos.documents.azure.cn:443/;AccountKey=clF73GwPECfP1lKZTCvs8gLMMyCZig1HODFbhDUsarsAURO7TcOjVz6ZFfPqr1HzYrfjCXpMuVD5TlEG5bFGGg==;"
+      "ConnectionString": "AccountEndpoint=https://cdhabookdep-free.documents.azure.cn:443/;AccountKey=JTUVk92Gjsx17L0xqxn0X4wX2thDPMKiw4daeTyV1HzPb6JmBeHdtFY1MF1jdctW1ofgzqkDMFOtcqS46by31A==;"
     },
     "Redis": {
-      "ConnectionString": "CoreRedisCN.redis.cache.chinacloudapi.cn:6380,password=LyJWP1ORJdv+poXWofAF97lhCEQPg1wXWqvtzXGXQuE=,ssl=True,abortConnect=False"
+      "ConnectionString": "52.130.252.100:6379,password=habook,ssl=false,abortConnect=False,writeBuffer=10240"
     },
     "ServiceBus": {
-      "ConnectionString": "Endpoint=sb://coreiotservicebuscnpro.servicebus.chinacloudapi.cn/;SharedAccessKeyName=TEAMModelOS;SharedAccessKey=llRPBMDJG9w1Nnifj+pGhV0g4H2REcq0PjvX2qqpcOg=",
-      "ActiveTask": "active-task",
-      "ItemCondQueue": "itemcond",
-      "GenPdfQueue": "genpdf"
+      "ConnectionString": "Endpoint=sb://teammodelos.servicebus.chinacloudapi.cn/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=Sy4h4EQ8zP+7w/lOLi1X3tGord/7ShFHimHs1vC50Dc=",
+      "ActiveTask": "dep-active-task",
+      "ItemCondQueue": "dep-itemcond",
+      "GenPdfQueue": "dep-genpdf"
     },
     "SignalR": {
-      "ConnectionString": "Endpoint=https://channel.signalr.azure.cn;AccessKey=AtcB7JYFNUbUXb1rGxa3PVksQ2X5YSv3JOHZR9J88tw=;Version=1.0;"
-    },
-    "Speech": {
-      "SubscriptionKey": "a4f5f4e2e2e54c6e8b0a4a0b4a0a4a0b",
-      "Region": "chinanorth3",
-      "Endpoint": "https://chinanorth3.api.cognitive.azure.cn/sts/v1.0/issuetoken"
+      "ConnectionString": "Endpoint=https://channel.service.signalr.net;AccessKey=KrblW06tuA4a/GyqRPDU0ynFFmAWxbAvyJihHclSXbQ=;Version=1.0;"
     }
+    // 正式站数据库
+    //"Storage": {
+    //  "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodelos;AccountKey=Dl04mfZ9hE9cdPVO1UtqTUQYN/kz/dD/p1nGvSq4tUu/4WhiKcNRVdY9tbe8620nPXo/RaXxs+1F9sVrWRo0bg==;EndpointSuffix=core.chinacloudapi.cn"
+    //},
+    //"Cosmos": {
+    //  "ConnectionString": "AccountEndpoint=https://teammodelos.documents.azure.cn:443/;AccountKey=clF73GwPECfP1lKZTCvs8gLMMyCZig1HODFbhDUsarsAURO7TcOjVz6ZFfPqr1HzYrfjCXpMuVD5TlEG5bFGGg==;"
+    //},
+    //"Redis": {
+    //  "ConnectionString": "CoreRedisCN.redis.cache.chinacloudapi.cn:6380,password=LyJWP1ORJdv+poXWofAF97lhCEQPg1wXWqvtzXGXQuE=,ssl=True,abortConnect=False"
+    //},
+    //"ServiceBus": {
+    //  "ConnectionString": "Endpoint=sb://coreiotservicebuscnpro.servicebus.chinacloudapi.cn/;SharedAccessKeyName=TEAMModelOS;SharedAccessKey=llRPBMDJG9w1Nnifj+pGhV0g4H2REcq0PjvX2qqpcOg=",
+    //  "ActiveTask": "active-task",
+    //  "ItemCondQueue": "itemcond",
+    //  "GenPdfQueue": "genpdf"
+    //},
+    //"SignalR": {
+    //  "ConnectionString": "Endpoint=https://channel.signalr.azure.cn;AccessKey=AtcB7JYFNUbUXb1rGxa3PVksQ2X5YSv3JOHZR9J88tw=;Version=1.0;"
+    //},
+    //"Speech": {
+    //  "SubscriptionKey": "a4f5f4e2e2e54c6e8b0a4a0b4a0a4a0b",
+    //  "Region": "chinanorth3",
+    //  "Endpoint": "https://chinanorth3.api.cognitive.azure.cn/sts/v1.0/issuetoken"
+    //}
   },
   "HaBookAuth": {
     "CoreId": {