Browse Source

Merge branch 'develop' into PL/develop-BI

Li 2 years ago
parent
commit
d5edf190b8
32 changed files with 2043 additions and 1439 deletions
  1. 48 16
      TEAMModelBI/ClientApp/src/view/areaServe/thirdparty.vue
  2. 15 15
      TEAMModelBI/ClientApp/src/view/areamanage/statistics.vue
  3. 63 2
      TEAMModelOS.FunctionV4/HttpTrigger/IESHttpTrigger.cs
  4. 9 1
      TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs
  5. 1 1
      TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj
  6. 1 1
      TEAMModelOS.SDK/Models/Cosmos/School/Knowledge.cs
  7. 3 3
      TEAMModelOS.SDK/Models/Service/StatisticsService.cs
  8. 1 1
      TEAMModelOS.SDK/TEAMModelOS.SDK.csproj
  9. 313 298
      TEAMModelOS/ClientApp/public/lang/en-US.js
  10. 225 210
      TEAMModelOS/ClientApp/public/lang/zh-CN.js
  11. 245 230
      TEAMModelOS/ClientApp/public/lang/zh-TW.js
  12. 102 11
      TEAMModelOS/ClientApp/src/components/evaluation/ExerciseList.less
  13. 453 453
      TEAMModelOS/ClientApp/src/view/Home.vue
  14. 9 0
      TEAMModelOS/ClientApp/src/view/areaMgmt/AreaData.vue
  15. 0 2
      TEAMModelOS/ClientApp/src/view/dashboard/StudentAll.less
  16. 1 0
      TEAMModelOS/ClientApp/src/view/dashboard/StudentAll.vue
  17. 193 67
      TEAMModelOS/ClientApp/src/view/evaluation/index/CommonExercise.less
  18. 14 7
      TEAMModelOS/ClientApp/src/view/jyzx/index.vue
  19. 1 1
      TEAMModelOS/ClientApp/src/view/jyzx/offline.vue
  20. 29 6
      TEAMModelOS/ClientApp/src/view/mgtPlatform/MgtPlatform.vue
  21. 34 24
      TEAMModelOS/ClientApp/src/view/mycourse/exam/CreatePrivExam.vue
  22. 92 6
      TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.vue
  23. 2 2
      TEAMModelOS/ClientApp/src/view/schoolmgmt/SystemSetting/SystemSetting.vue
  24. 1 1
      TEAMModelOS/ClientApp/src/view/student-account/import/StuImport.vue
  25. 10 23
      TEAMModelOS/Controllers/Analysis/AnalysisController.cs
  26. 30 29
      TEAMModelOS/Controllers/Client/HiTeachController.cs
  27. 70 0
      TEAMModelOS/Controllers/Client/HiTeachccControlller.cs
  28. 25 17
      TEAMModelOS/Controllers/Normal/AbilityStatisticsController.cs
  29. 2 2
      TEAMModelOS/Controllers/School/KnowledgesController.cs
  30. 24 3
      TEAMModelOS/Controllers/School/SchoolSettingController.cs
  31. 12 4
      TEAMModelOS/Controllers/Third/Xkw/XkwServiceController.cs
  32. 15 3
      TEAMModelOS/Controllers/XTest/FixDataController.cs

+ 48 - 16
TEAMModelBI/ClientApp/src/view/areaServe/thirdparty.vue

@@ -13,18 +13,11 @@
     </div>
     <div class="searchbox" v-show="displayMode ==='list'">
       <div class="searchbox-input">
-        <el-input v-model="input3" placeholder="搜索企业名称/统一社会信用代码" class="input-with-select" size="small">
-          <template #prepend>
-            <el-select v-model="select" placeholder="所有" style="width: 100px">
-              <el-option label="Restaurant" value="1" />
-              <el-option label="Order No." value="2" />
-              <el-option label="Tel" value="3" />
-            </el-select>
-          </template>
+        <el-input v-model="serachkeys" placeholder="搜索企业名称/统一社会信用代码" class="input-with-select" size="small" :prefix-icon="Search" clearable="true">
         </el-input>
       </div>
     </div>
-    <div class="application-list" v-show="displayMode ==='list'">
+    <div class="application-list" v-show="displayMode ==='list' && thirdpartyArr.length !==0">
       <div class="application-item" v-for="item in thirdpartyArr" :key="item.rowKey" @click="viewDetails(item)">
         <div class="application-item-left">
           <div class="left-img">
@@ -46,6 +39,9 @@
         </div>
       </div>
     </div>
+    <div class="application-list" v-show="thirdpartyArr.length ===0">
+      <div class="notdata">暂无数据</div>
+    </div>
     <div class="created-thirdparty" v-show="displayMode ==='list'">
       <el-dialog v-model="createdShow" title="创建第三方企业" width="35%" :before-close="closeCreated">
         <div class="created-content">
@@ -104,14 +100,15 @@
   </div>
 </template>
 <script>
-import { ref, reactive, getCurrentInstance } from 'vue'
-import { Plus } from '@element-plus/icons-vue'
+import { ref, reactive, getCurrentInstance, watch } from 'vue'
+import { Plus, Search } from '@element-plus/icons-vue'
 import { ElMessage } from 'element-plus'
 import SetThird from './setthird.vue'
 export default {
   components: {
     Plus,
-    SetThird
+    SetThird,
+    Search
   },
   setup () {
     let { proxy } = getCurrentInstance()
@@ -120,6 +117,7 @@ export default {
     let createdShow = ref(false)
     let displayMode = ref('list')
     let thirdpartyArr = ref([])
+    let original = ref([])
     let form = ref({
       name: '',
       code: '',
@@ -149,6 +147,8 @@ export default {
     let imageUrl = ref('')
     let uploadState = ref(false)
     let clickDetails = ref('')
+    let serachkeys = ref('')
+    let timer = ref('')
     let user_token = JSON.parse(localStorage.getItem('id_token'))
     function uploadInt () {
       let token = JSON.parse(localStorage.getItem('id_token'))
@@ -227,7 +227,7 @@ export default {
     function getAlls () {
       proxy.$api.getAllthirdparty({}).then((res) => {
         console.log(res, '企业信息')
-        res.state === 200 ? thirdpartyArr.value = res.companys : ''
+        res.state === 200 ? (thirdpartyArr.value = res.companys, original.value = res.companys) : ''
       }).catch((error) => {
         ElMessage.error('获取企业信息失败')
       })
@@ -242,6 +242,28 @@ export default {
     function backChangeState (value) {
       displayMode.value = value
     }
+    function debounce (fn, wait) {
+      if (timer.value !== null) {
+        clearTimeout(timer.value)
+      }
+      timer.value = setTimeout(fn, wait)
+    }
+    function personnelSearch () {
+      let arr = thirdpartyArr.value
+      let newArr = arr.filter((item) => {
+        // return (item.name && item.name.includes(filterText.value)) || (item.mobile && item.mobile.includes(filterText.value)) || (item.mobile && item.mobile.tmdId.includes(filterText.value))
+        return item.name.includes(serachkeys.value)
+      })
+      thirdpartyArr.value = newArr
+    }
+    watch(serachkeys, (newdata) => {
+      console.log(newdata, '数据变化')
+      if (newdata.trim().length !== 0) {
+        debounce(personnelSearch, 500)
+      } else {
+        thirdpartyArr.value = original.value
+      }
+    })
     uploadInt()
     getAlls()
     return {
@@ -268,7 +290,10 @@ export default {
       viewDetails,
       clickDetails,
       backChangeState,
-      PowerShow
+      PowerShow,
+      serachkeys,
+      backChangeState,
+      personnelSearch
     }
   },
 }
@@ -305,7 +330,7 @@ export default {
   height: 40px;
 }
 .searchbox-input {
-  width: 25%;
+  width: 22%;
   float: right;
 }
 .application-list {
@@ -316,12 +341,13 @@ export default {
   margin-top: 1%;
 }
 .application-item {
-  width: 25%;
+  width: 23%;
   padding: 1% 1%;
   border: 1px solid #ccc;
   border-radius: 10px;
   margin-right: 2%;
   cursor: pointer;
+  margin-top: 1%;
 }
 .application-item-left {
   width: 30%;
@@ -445,6 +471,12 @@ export default {
   width: 100%;
   padding: 1%;
 }
+.notdata {
+  margin: 30vh auto 0 auto;
+  font-size: 22px;
+  font-weight: bold;
+  color: #bdc3c7;
+}
 </style>
 <style>
 .searchbox .el-input__suffix {

+ 15 - 15
TEAMModelBI/ClientApp/src/view/areamanage/statistics.vue

@@ -124,13 +124,13 @@
           <div class="right-top-text">
             <p class="right-top-num">{{item.num}}<span v-if="item.classname ==='size'">GB</span></p>
             <!-- <p class="right-top-title">{{item.title}}</p> -->
-            <div class="right-top-bottombox">
+            <div class="right-top-bottombox" :class="[item.classname ==='school' || item.classname ==='teach' || item.classname ==='datas'? '':'right-all','right-top-bottombox-title']">
               <div class="right-top-bottombox-title">
                 <p class="right-top-title">{{item.title}}</p>
               </div>
-              <div class="right-top-bottombox-comparison">
-                <p>周新增:<span class="week-comparison">3</span></p>
-                <p>月新增:<span class="months-comparison">15</span></p>
+              <div class="right-top-bottombox-comparison" v-if="item.classname ==='school' || item.classname ==='teach' || item.classname ==='datas'">
+                <p>周新增:<span class="week-comparison">0</span></p>
+                <p>月新增:<span class="months-comparison">0</span></p>
               </div>
             </div>
           </div>
@@ -263,10 +263,10 @@ export default {
     const store = useStore()
     let showPattern = ref('all')
     let aspectsData = ref([
-      { id: 1, title: '区内学校', num: 0, icon: '#icon-renshixuexiao', classname: 'school' },
-      { id: 2, title: '区内老师', num: 0, icon: '#icon-schoollaoshi', classname: 'teach' },
+      { id: 1, title: '区内学校', num: 0, icon: '#icon-renshixuexiao', classname: 'school', addweek: 0, addmonth: 0, },
+      { id: 2, title: '区内老师', num: 0, icon: '#icon-schoollaoshi', classname: 'teach', addweek: 0, addmonth: 0, },
       { id: 3, title: '本周数据', num: 0, icon: '#icon-benzhou', classname: 'months' },
-      { id: 4, title: '产出总数据', num: 0, icon: '#icon-ziyuan1', classname: 'datas' },
+      { id: 4, title: '产出总数据', num: 0, icon: '#icon-ziyuan1', classname: 'datas', addweek: 0, addmonth: 0, },
       { id: 5, title: '空间总容量', num: 0, icon: '#icon-kongjian', classname: 'size' },
     ])
     let aspectsLoading = ref({
@@ -1197,9 +1197,9 @@ export default {
       schedule: {
         color: ['#3fb1e3', '#6be6c1', '#626c91', '#a0a7e6', '#c4ebad', '#96dee8'],
         data: [
-          { value: 9, name: '已完成' },
-          { value: 33, name: '进行中' },
-          { value: 82, name: '未完成' },
+          { value: 0, name: '已完成' },
+          { value: 0, name: '进行中' },
+          { value: 0, name: '未完成' },
         ],
         legend: {
           orient: 'vertical',
@@ -1566,7 +1566,7 @@ export default {
             //基础数据
             activityData.value.oneself[0].num = res.weekLess
             activityData.value.oneself[1].num = res.termLess
-            activityData.value.oneself[2].num = res.weekActivity
+            activityData.value.oneself[2].num = res.weekActivity + res.weekLess
             activityData.value.oneself[3].num = res.termActivity
             activityData.value.oneself[4].num = res.totalTime
             activityData.value.oneself[5].num = res.allLess
@@ -1682,9 +1682,9 @@ export default {
             { value: 0, name: '课堂实录' },
           ]
           let within = [
-            { value: 9, name: '已完成' },
-            { value: 33, name: '进行中' },
-            { value: 82, name: '未完成' },
+            { value: 0, name: '已完成' },
+            { value: 0, name: '进行中' },
+            { value: 0, name: '未完成' },
           ]
           if (res.state === 200) {
             outer[0].value = res.onLineCount
@@ -1865,7 +1865,7 @@ export default {
   font-size: 16px;
 }
 .right-top-bottombox-title {
-  width: 45%;
+  width: 100%;
 }
 .right-top-bottombox-comparison {
   width: 55%;

+ 63 - 2
TEAMModelOS.FunctionV4/HttpTrigger/IESHttpTrigger.cs

@@ -70,6 +70,67 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
             return response;
 
 
+        }
+        /// <summary>
+        /// 数据推送接口
+        /// </summary>
+        /// <param name="req"></param>
+        /// <param name="log"></param>
+        /// <returns></returns>
+        [Function("lesson-tag-change")]
+        public async Task<HttpResponseData> LessonTagChange([HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestData req) {
+            var response = req.CreateResponse(HttpStatusCode.OK);
+            string data = await new StreamReader(req.Body).ReadToEndAsync();
+            var json = JsonDocument.Parse(data).RootElement;
+            List<TagOldNew> old_new = null;
+            string school = null;
+            if (json.TryGetProperty("school", out JsonElement _school))
+            {
+                school = _school.GetString();
+            }
+            if (json.TryGetProperty("old_new", out JsonElement _old_new))
+            {
+                old_new = _old_new.ToObject<List<TagOldNew>>();
+            }
+            if (old_new.IsNotEmpty() && !string.IsNullOrWhiteSpace(school))
+            {
+                foreach (var on in old_new)
+                {
+                    List<LessonRecord> lessonRecords = new List<LessonRecord>();
+                    string sql = $"select value(c) from c    where array_contains(c.category,'{on._old}') ";
+                    await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<LessonRecord>
+                        (queryText: sql.ToString(), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"LessonRecord-{_school}") }))
+                    {
+                        lessonRecords.Add(item);
+                    }
+
+                    lessonRecords.ForEach(item =>
+                    {
+                        //修改标签
+                        if (!string.IsNullOrWhiteSpace(on._new))
+                        {
+                            for (int i = 0; i < item.category.Count; i++)
+                            {
+                                if (item.category[i].Equals(on._old))
+                                {
+                                    item.category[i] = on._new;
+                                }
+                            }
+                        }
+                        else
+                        {
+                            //表示删除标签
+                            item.category.RemoveAll(x => x.Equals(on._old));
+                        }
+                    });
+                    foreach (var item in lessonRecords)
+                    {
+                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync(item, item.id, new PartitionKey(item.code));
+                    }
+                }
+            }
+            await response.WriteAsJsonAsync(new { data = json });
+            return response;
         }
         /// <summary>
         /// 数据推送接口
@@ -83,7 +144,7 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
             var response = req.CreateResponse(HttpStatusCode.OK);
             string data = await new StreamReader(req.Body).ReadToEndAsync();
             var json = JsonDocument.Parse(data).RootElement;
-            List<OldNew> old_new = null;
+            List<TagOldNew> old_new = null;
             string school = null;
             if (json.TryGetProperty("school", out JsonElement _school))
             {
@@ -91,7 +152,7 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
             }
             if (json.TryGetProperty("old_new", out JsonElement _old_new))
             {
-                old_new = _old_new.ToObject<List<OldNew>>();
+                old_new = _old_new.ToObject<List<TagOldNew>>();
             }
             if (old_new.IsNotEmpty() && !string.IsNullOrWhiteSpace(school))
             {

+ 9 - 1
TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs

@@ -407,10 +407,18 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                 {
                     List<Study> studies = new List<Study>();
                     await foreach (var item in client.GetContainer("TEAMModelOS", "Common")
-                       .GetItemQueryIterator<Study>(queryText: $"select value(c) from c    where c.owner<>'area'  ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{school}") }))
+                       .GetItemQueryIterator<Study>(queryText: $"select value(c) from c    where c.owner<>'area'  ", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Study-{school.school}") }))
                     {
                         studies.Add(item);
                     }
+                    if (school.teachers.Any()) {
+                        string trainSql = $"select value(c) from c where c.id in ({string.Join(",", school.teachers.Select(x =>$"'{x}'"))}) ";
+                        await foreach (var item in client.GetContainer("TEAMModelOS", Constant.Teacher)
+                      .GetItemQueryIterator<TeacherTrain>(queryText: trainSql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{school.school}") }))
+                        {
+                            trains.Add(item);
+                        }
+                    }
                     await StatisticsService.GetStatisticsTeacher(trains, setting, area, client, studies);
                 }
                 area.updateTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();

+ 1 - 1
TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj

@@ -12,7 +12,7 @@
 		<Authors>teammodel</Authors>
 		<Company>醍摩豆(成都)信息技术有限公司</Company>
 		<Product>IES5</Product>
-		<Description>事件触发中心</Description>
+		<Description>事件触发中心 </Description>
 		<PackageProjectUrl>https://www.teammodel.cn/</PackageProjectUrl>
 	</PropertyGroup>
 	<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">

+ 1 - 1
TEAMModelOS.SDK/Models/Cosmos/School/Knowledge.cs

@@ -39,7 +39,7 @@ namespace TEAMModelOS.SDK.Models
         public List<Block> blocks { get; set; } = new List<Block>();
 
     }
-    public class OldNew
+    public class TagOldNew
     {
         [Required(ErrorMessage = "_old 必须设置")]
         public string _old { get; set; }

+ 3 - 3
TEAMModelOS.SDK/Models/Service/StatisticsService.cs

@@ -51,11 +51,11 @@ namespace TEAMModelOS.SDK
         public class TeacherTrainChangeMsg {
 
             public string areaId { get; set; }
-            public List<TeacherTrainChangeMsgSchoolTeachers> schools{ get; set; }
+            public List<TeacherTrainChangeMsgSchoolTeachers> schools { get; set; } = new List<TeacherTrainChangeMsgSchoolTeachers>();
         }
         public class TeacherTrainChangeMsgSchoolTeachers { 
             public string school { get; set; }
-            public List<string> teachers { get; set; }
+            public List<string> teachers { get; set; } = new List<string>();
         }
         public static async Task DoChange(TeacherTrainChange change, AzureCosmosFactory _azureCosmos)
         {
@@ -252,7 +252,7 @@ namespace TEAMModelOS.SDK
             //}
  
 
-            returnTrains = updateTeacherTrains;
+            returnTrains .AddRange(updateTeacherTrains) ;
             // await GetStatisticsTeacher(teacherTrains, setting, area, client, studies);
             //await foreach (var tarain in GetStatisticsTeacher(teacherTrains, setting, area, client))
             //{

+ 1 - 1
TEAMModelOS.SDK/TEAMModelOS.SDK.csproj

@@ -19,7 +19,7 @@
     <PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.2.0" />
     <PackageReference Include="Azure.Storage.Blobs.Batch" Version="12.8.0" />
     <PackageReference Include="Azure.Storage.Queues" Version="12.9.0" />
-    <PackageReference Include="ClouDASLibx" Version="1.3.1" />
+    <PackageReference Include="ClouDASLibx" Version="1.3.2" />
     <PackageReference Include="DinkToPdf" Version="1.0.8" />
     <PackageReference Include="DocumentFormat.OpenXml" Version="2.15.0" />
     <PackageReference Include="HTEXLib" Version="5.2203.232" />

+ 313 - 298
TEAMModelOS/ClientApp/public/lang/en-US.js

@@ -16,13 +16,13 @@ const LANG_EN_US = {
         toProvince: '推送省平臺',
         noData: '當前條件下未匹配到教師數據',
         noGroup: '未分組',
-        offline: '校本研修',
-        online: '線上研修',
-        ability: '認證材料',
-        video: '課堂實錄',
-        hour: '學時',
-        noOnline: '暫無線上研修記錄',
-        minute: '分鐘',
+        offline: 'School Study',
+        online: 'Online Study',
+        ability: 'Certified Material',
+        video: 'Lesson Recording',
+        hour: 'Study Length',
+        noOnline: 'No online study records yet',
+        minute: 'minutes',
         noSubmitNum: '未提交數',
         noAbility: '暫無認證材料記錄',
         selfAppraise: '自評',
@@ -34,7 +34,7 @@ const LANG_EN_US = {
         tip1: '教師未提交認證材料,無法評審',
         tip2: '前往評審教師提交的認證材料',
         goAppraise: '去評審',
-        noOffline: '暫無校本研修記錄',
+        noOffline: 'No school study records yet',
         hasPdf: '已提交PDF',
         noPdf: '未提交PDF',
         hasUpload: '已上傳',
@@ -46,7 +46,7 @@ const LANG_EN_US = {
         no: '暫無',
         allStatus: '全部狀態',
         noSubmit1: '認證材料未提交',
-        noSubmit2: '校本研修作業未提交',
+        noSubmit2: 'School study homework not submitted',
         noSubmit3: '課堂實錄未提交',
         teacherInfo: '教師信息',
         tip3: '教師在線上研修觀看能力點所關聯的視頻資源總時長,1學時=45分鐘',
@@ -54,7 +54,7 @@ const LANG_EN_US = {
         tip5: '個能力點的認證材料合格即可獲得學時',
         tip6: '認證材料必須全部通過才能獲得學時',
         allNormal: '全部合格',
-        tip7: '根據省平臺要求,教師必須滿足以下條件才可獲得校本研修活動學時: 1.10學時中至少有一次需提交作業的校本研修活動 2.在活動中成功提交PDF作業',
+        tip7: 'According to the requirements of the provincial platform, teachers must meet the following conditions to receive Study Length for school study activities: 1. At least one school study activity in ten Study Length requires submission of homework. 2. Successful submission of PDF homework in the activity',
         allPass: '全部通過',
         tip8: '教師提交課堂實錄併且考核通過後即可獲得5學時',
         atName: '被評價人',
@@ -108,11 +108,11 @@ const LANG_EN_US = {
         appraiseTip2: '請優先對互評次數為0的老師進行互評!',
         check: {
             isCheck: '是否为考核人员',
-            tip1: '确认修改当前教师的核人员身份吗?',
+            tip1: '确认修改当前教师的核人员身份吗?',
             tip2: '已添加',
-            tip3: '为核人员',
+            tip3: '为核人员',
             tip4: '已取消',
-            tip5: '的核人员身份!',
+            tip5: '的核人员身份!',
         },
         points: {
             doc: '文檔類',
@@ -246,22 +246,22 @@ const LANG_EN_US = {
             import: '導入試題',
             resource: '關聯資源',
             chapter: '章節',
-            edit: '編輯微能力點',
-            addAbility: '新增微能力點',
-            no: '編號',
-            name: '名稱',
-            desc: '描述',
-            env: '環境',
-            sug: '建議',
+            edit: 'Edit Competency',
+            addAbility: 'Add Competency',
+            no: 'No.',
+            name: 'Name',
+            desc: 'Description',
+            env: 'Environment',
+            sug: 'Suggestion',
             isCompulsory: 'Elective/Required',
             noCompulsory: 'Elective',
-            place2: '填寫微能力點編號...',
-            place3: '填寫微能力點名稱...',
-            place4: '填寫微能力點描述資訊...',
-            place5: '填寫微能力點環境...',
-            place6: '填寫微能力點建議...',
-            tip1: '編號不能為空',
-            tip2: '名稱不能為空',
+            place2: 'Please enter competency No. ...',
+            place3: 'Please enter competency name...',
+            place4: 'Please enter competency description...',
+            place5: 'Please enter competency environment...',
+            place6: 'Please enter competency suggestion...',
+            tip1: 'Number cannot be empty',
+            tip2: 'Name cannot be empty',
         },
         upload: {
             label1: '整校實施方案上傳',
@@ -1273,7 +1273,7 @@ const LANG_EN_US = {
             gCount: 'Group No.',
             taskCount: 'Task No.',
             colctCount: 'Work No.',
-            pushCount: 'Push No.',
+            pushCount: 'Pushed No.',
             totalScore: 'Total Points',
             examCount: 'No. of Test',
             quCount: 'IRS Question No.',
@@ -2095,13 +2095,13 @@ const LANG_EN_US = {
             abilyMes: "After each competency has finished the required number of Study Length, the extra Study Length will not be counted as part of the total Study Length.",
             fromArea: "來源省平臺",
             fromArea1: "來源:省平臺",
-            noStuTime: "不計學時",
+            noStuTime: "Doesn't count as Study Length",
             loadLook: "可下載查看",
-            allEnvir: "全部環境",
-            envirMix: "混合學習環境",
-            multiMedia: "多媒體教學環境",
-            studyEnvir: "智慧學習環境",
-            allDimension: "全部維度",
+            allEnvir: "All ",
+            envirMix: "Hybrid Learning",
+            multiMedia: "Multimedia Teaching",
+            studyEnvir: "Smart Learning",
+            allDimension: "All Type",
             keepRecords: "保存記錄",
             close: "關閉提示",
             autoSave: "已經自動保存",
@@ -2170,7 +2170,7 @@ const LANG_EN_US = {
             message4: "Please select a file first!",
             uploadSuccess: 'Upload successfully',
             uploadError: 'Failed to upload',
-            message5: "You do not need to submit the homework, it will be submitted together by the group leader",
+            message5: "You do not need to submit the homework, it will be submitted together by the team leader",
             message6: "You have not uploaded a main file in the required format",
             video: "Video",
             activityData: "Information",
@@ -2178,15 +2178,15 @@ const LANG_EN_US = {
             noFile: "No file yet",
             sendActivity: "Submit",
             main: "Main",
-            message7: "根據省平臺要求,教師必須滿足以下條件才可獲得校本研修活動學時",
-            message8: "1. 10學時中至少有一次需提交作業的校本研修活動。",
-            message9: "2. 在活動中成功提交PDF作業。",
+            message7: "According to the requirements of the provincial platform, teachers must meet the following conditions to receive Study Length for school study activities",
+            message8: "1. At least one school study activity in ten Study Length requires submission of homework.",
+            message9: "2. Successful submission of PDF homework in the activity",
             noActivity: "暫無活動",
-            tips: "重要提示",
-            tips1: "根據省平臺要求,教師上傳的作業必須選擇一個",
-            tips2: "檔案,作為本次活動的主要檔案提交到省平臺。",
-            mainFile: "主要檔案",
-            tips3: "提交前,點擊檔名,即可切換主要檔案",
+            tips: "Note",
+            tips1: "According to the requirements of the provincial platform, teachers must select a",
+            tips2: "file of their uploaded homework and submit it to the provincial platform as the main file for this activity.",
+            mainFile: "Main File",
+            tips3: "Before submitting, you can click on the file name to switch the main files",
         },
         // 应用考核
         application: {
@@ -2595,17 +2595,17 @@ const LANG_EN_US = {
             isZeroTips: 'It is already zero point',
             saveScoreOk: 'Results saved successfully!',
             saveSocreErr: 'Failed to save results!',
-            zero: '0.',
-            one: '1.',
-            two: '2.',
-            three: '3.',
-            four: '4.',
-            five: '5.',
-            six: '6.',
-            seven: '7.',
-            eight: '8.',
-            nine: '9.',
-            ten: '10.',
+            zero: '0',
+            one: '1',
+            two: '2',
+            three: '3',
+            four: '4',
+            five: '5',
+            six: '6',
+            seven: '7',
+            eight: '8',
+            nine: '9',
+            ten: '10',
             hundred: 'Hundred',
             thousand: 'Thousand',
             tenThd: 'Ten thousand',
@@ -2628,7 +2628,7 @@ const LANG_EN_US = {
             status3: 'View Score',
             status4: 'Absent',
             status5: 'Make-up Test',
-            status6: '未開始',
+            status6: 'Not Started',
             column1: 'Name',
             column2: 'Total Score',
             column3: 'Status',
@@ -2717,7 +2717,7 @@ const LANG_EN_US = {
             noKn: 'No key concept data in the exam file',
             dataErr: 'Assessment data has anomalies',
             goingNoData: 'Assessment is in progress, statistics cannot be viewed',
-            pendingNoData: '評測暫未發布,無法查看統計數據',
+            pendingNoData: 'The assessment has not started yet, so cannot check the statistics',
             paperErr: 'Exam file data has anomalies'
         },
 
@@ -2905,6 +2905,18 @@ const LANG_EN_US = {
     },
     // 课堂记录
     lessonRecord: {
+        export: {
+            order: '序號',
+            tchName: '教師姓名',
+            tmdid: '醍摩豆ID',
+            recordCount: '課堂記錄總數',
+            recordName: '課程名稱',
+            time: '授課時間',
+            sheet1: '教師課堂記錄數量統計',
+            sheet2: '學校課堂記錄總錶',
+            fileName: '課堂記錄統計錶',
+            noData: '暫無數據導出'
+        },
         noRecordTip: 'No lesson records are available under the current school system!',
         delStatusTip: 'Lesson records have been cleared',
         overdue: 'expired',
@@ -2951,7 +2963,7 @@ const LANG_EN_US = {
         count5: 'Accumulated Test Question',
         count6: 'Accumulated Interaction',
         count7: 'New lesson records this semester',
-        export: 'Export Data',
+        exportData: 'Export Data',
         tagMg: 'Category',
         tchName: 'Teacher',
         lessonName: 'Lesson Name',
@@ -2976,7 +2988,7 @@ const LANG_EN_US = {
         totalPoint: 'Total Points',
         collateTaskCount: 'Task No.',
         collateCount: 'Work No.',
-        pushCount: 'Push No.',
+        pushCount: 'Pushed No.',
         score: 'Interactive Score',
         interactionCount: 'Interactive Qs',
         clientInteractionCount: 'Response',
@@ -3979,10 +3991,10 @@ const LANG_EN_US = {
         setNoErr1: "Please set the student's class",
         setNoErr2: 'The seat number is repeated in the class',
         sltStuTips: 'Please select student first',
-        imeiErr1:'電子學生證只能為數字',
-        imeiErr2:'電子學生證為15位數字',
-        imeiErr3:'請輸入學生ID',
-        imeiErr4:'已經綁定此編號,如果當前學生綁定此編號,原來學生的將會自動取消綁定。',
+        imeiErr1:'E-Student ID Number can only be numbers',
+        imeiErr2:'E-Student ID Number is 15 digits',
+        imeiErr3:'Please enter student ID',
+        imeiErr4:" has bound this number, if the current student binds this number, the original student's binding will be cancelled automatically.",
         addOk: 'Added successfully',
         updOk: 'Modified successfully',
         addErr: 'Failed to add',
@@ -4050,17 +4062,17 @@ const LANG_EN_US = {
         sit13: 'guardian: Optional. Guardian-Student Relationship',
         sit14: 'gName: Optional. Guardian Name',
         sit15: 'gPhone: Optional. Guardian Phone Number',
-        sit16: 'imei: 選填,電子學生證編號,由15位數字組成',
+        sit16: 'imei: Optional. E-Student ID Number, consists of 15 digits',
         sit17: 'Repeated seat No. (with existing students)',
-        sit18: '電子學生證編號重復',
-        sit19: '電子學生證格式錯誤',
-        sit20: '電子學生證編號為15位數字組成',
-        sit21: 'M(男)或F(女)代表學生性別',
-        sit22: '性別格式錯誤',
-        sit23: '性別',
-        sit24: '',
-        sit25: '',
-        sit26: 'gender: 選填,學生性別,"M"代表男,"F"代表女',
+        sit18: 'The same E-Student ID Number already exists',
+        sit19: 'Incorrect E-Student ID Number format',
+        sit20: 'The E-Student ID Number consists of 15 digits',
+        sit21: "M (male) or F (female) represents the student's gender",
+        sit22: 'Incorrect gender format',
+        sit23: 'Gender',
+        sit24: 'Male',
+        sit25: 'Female',
+        sit26: "gender: Optional. Student's Gender, M for male, F for female",
 
         // Authorization.vue
         authTitle: 'Service Authorization Management',
@@ -5560,8 +5572,8 @@ const LANG_EN_US = {
         table: {
             text1: 'Basic',
             text2: 'Advance',
-            text3: '校級管理員',
-            text4: '區級管理員',
+            text3: 'School Administrator',
+            text4: 'District Administrator',
             th1: 'ID',
             th2: 'Name',
             th3: 'Title',
@@ -5674,7 +5686,7 @@ const LANG_EN_US = {
             'research': 'Lesson Management',
             'research-read': 'View Lesson Management',
             'research-upd': 'Manage Lesson Management',
-            'link': '資源平臺',
+            'link': 'Resource Platform',
             'link-read': 'View Resource Platform',
             'link-upd': 'Manage Resource Platform'
         },
@@ -6331,26 +6343,26 @@ const LANG_EN_US = {
             school: 'School:'
         },
         mgt: {
-            all: '全部',
-            trainTypeLabel: '活動類型:',
-            search: '搜索',
-            toCreate: '新建研修',
-            areaLabel: '區級',
-            schoolLabel: '校級',
-            presenter: '主講人:',
-            topic: '主題:',
-            address: '地點:',
-            time: '時間:',
-            noTrain: '暫無校本研修活動',
+            all: 'All',
+            trainTypeLabel: 'Type:',
+            search: 'Search',
+            toCreate: 'Create Study',
+            areaLabel: 'District',
+            schoolLabel: 'School',
+            presenter: 'Speaker:',
+            topic: 'Theme:',
+            address: 'Venue:',
+            time: 'Time:',
+            noTrain: 'No school study activities yet',
         },
         detail: {
             back: '返回研修總覽',
-            hour: '學時',
-            presenter: '主講人:',
-            topic: '主題:',
-            address: '地點:',
-            time: '時間:',
-            delete: '刪除',
+            hour: 'Study Length',
+            presenter: 'Speaker:',
+            topic: 'Theme:',
+            address: 'Venue:',
+            time: 'Time:',
+            delete: 'Delete',
             checkHour: '學時審核',
             pass: '通過',
             fail: '不通過',
@@ -6362,7 +6374,7 @@ const LANG_EN_US = {
             signStatus2: '遲到',
             signStatus3: '未簽到',
             hwLabel: '作業詳情',
-            hwView: '查看',
+            hwView: 'View',
             hwDownload: 'Download',
             quLabel: '問卷反饋',
             viewDetail: '查看詳情',
@@ -6421,211 +6433,214 @@ const LANG_EN_US = {
         }
     },
     //研修
-    td:{
-        td1:'研修統計',
-        td2:'學時統計',
-        td3:'總學時:',
-        td4:'分鐘',
-        td5:'學時',
-        td6:'未開始:',
-        td7:'進行中:',
-        td8:'已完成:',
-        td9:'合格率',
-        td10:'學校概覽',
-        td11:'學校列表',
-        td12:'導出學校數據',
-        td13:'導出教師數據',
-        td14:'搜索學校',
-        td15:'參訓人數',
-        td16:'詳情>>>',
-        td17:'未搜索到學校',
-        td18:'暫無學校數據',
-        td19:'學校數量',
-        td20:'總學時',
-        td21:'合格人數',
-        td22:'線上研修',
-        td23:'校本研修',
-        td24:'認證材料',
-        td25:'課堂實錄',
-        td26:'未修滿',
-        td27:'能力點',
-        td28:'學校',
-        td29:'姓名',
-        td30:'線上研修學時',
-        td31:'所選微能力點',
-        td32:'已修滿的能力點數量',
-        td33:'認證材料學時',
-        td34:'校本研修學時',
-        td35:'課堂實錄學時',
-        td36:'認證材料需提交數',
-        td37:'已提交認證材料數',
-        td38:'已提交認證材料能力點',
-        td39:'未提交認證材料數',
-        td40:'未提交認證材料能力點',
-        td41:'作業未提交數',
-        td42:'課堂實錄是否提交',
-        td43:'已提交',
-        td44:'未提交',
-        td45:'研修情況統計表',
-        td46:'未開始人數',
-        td47:'進行中人數',
-        td48:'已完成人數',
-        td49:'參訓總人數',
-        td50:'學校數據統計',
-        td51:'資源列表',
-        td52:'添加資源',
-        td53:'完成率:',
-        td54:'返回區級',
-        td55:'所有學校',
-        td56:'共建',
-        td57:'個試點校,參訓人數',
-        td58:'重新上傳',
-        td59:'主題',
-        td60:'時間',
-        td61:'地點',
-        td62:'描述',
-        td63:'請選擇作業附件上傳類型',
-        td64:'簽到成功',
-        td65:'數據概覽',
-        td66:'的',
-        td67:'查詢簽到數據失敗',
-        td68:'獲取作業提交數據失敗',
-        td69:'合格率統計',
-        td70:'能力維度選修占比',
-        td71:'能力點選修占比',
-        td72:'研修小組統計',
-        td73:'暫無小組數據',
-        td74:'未分組',
-        td75:'查看成員',
-        td76:'完成線上研修',
-        td77:'完成認證材料',
-        td78:'完成校本研修',
-        td79:'完成課堂記錄',
-        td80:'全部完成',
-        td81:'完成率',
-        td82:'優秀',
-        td83:'合格',
-        td84:'不合格',
-        td85:'獲取統計數據失敗',
-        td86:'數據總覽',
-        td87:'詳細數據',
-        td88:'搜索',
-        td89:'數據導出',
-        td90:'未完成',
-        td91:'已完成',
-        td92:'教師姓名',
-        td93:'小組',
-        td94:'完成狀態',
-        td95:'姓名',
-        td96:'組別',
-        td97:'獲取統計數據失敗',
-        td98:'根據省平臺要求,教師必須滿足以下條件才可獲得校本研修活動學時:',
-        td99:'1、10學時中至少有一次需提交作業的校本研修活動',
-        td100:'2、在活動中成功提交PDF作業',
-        td101:'提交方式',
-        td102:'所有老師提交',
-        td103:'由組長統一提交',
-        td104:'請設置作業類型',
-        td105:'請設置提交方式',
-        td106:'未分組老師',
-        td107:'創建研修問卷失敗',
-        td108:'創建研修評測失敗',
-        td109:'輸入手機號',
-        td110:'未查詢到對應賬號!請檢查後重試!',
-        td111:'已簽到成功,請勿重復操作!',
-        td112:'請輸入正確手機號!',
-        td113:'簽到失敗,請重新簽到',
-        td114:'簽到成功',
-        td115:'簽到失敗',
-        td116:'溫馨提示:區級活動不計入校本研修學時',
-        td117:'未發布',
-        td118:'進行中',
-        td119:'已結束',
-        td120:'活動視頻:',
-        td121:'播放',
-        td122:'刪除',
-        td123:'上傳',
-        td124:'(視頻只能上傳一個)',
-        td125:'活動資料:',
-        td126:'繼續上傳',
-        td127:'(資料可以上傳多份)',
-        td128:'根據省平臺要求,教師必須滿足以下條件才可獲得校本研修活動學時: 1、10學時中至少有一次需提交作業的校本研修活動 2、在活動中成功提交PDF作業',
-        td129:'批量合格',
-        td130:'請選擇學校老師參加並發布活動',
-        td131:'選擇老師',
-        td132:'繼續挑選(已選',
-        td133:'位)',
-        td134:'發布活動',
-        td135:'上傳中',
-        td136:'上傳完成',
-        td137:'添加教師',
-        td138:'教研組',
-        td139:'教研組篩選',
-        td140:'未設置',
-        td141:'查詢教研組失敗',
-        td142:'請勾選參加活動的老師',
-        td143:'刪除文件',
-        td144:'是否確認刪除',
-        td145:'刪除成功',
-        td146:'刪除失敗',
-        td147:'文件上傳中,請等待文件上傳完成',
-        td148:'活動視頻只支持mp4文件格式',
-        td149:'學校空間已滿',
-        td150:'上傳失敗',
-        td151:'請選擇需要批量處理',
-        td152:'合格',
-        td153:'不合格',
-        td154:'的老師',
-        td155:'批量處理',
-        td156:'確認將所選老師全部設置為合格嗎?',
-        td157:'問卷作答數據獲取失敗',
-        td158:'獲取作業提交數據失敗',
-        td159:'獲取名單列表失敗',
-        td160:'獲取簽到數據失敗',
-        td161:'學校',
-        td162:'查詢教師列表失敗',
-        td163:'對象:',
-        td164:'暫無',
-        td165:'查詢研修列表失敗',
-        td166:'人數:',
-        td167:'(已同步省平臺名單)',
-        td168:'溫馨提示:空白分組(分組內沒有添加教師)不會被保存。',
-        td169:'保存分組',
-        td170:'分組視圖',
-        td171:'列表視圖',
-        td172:'移除教師',
-        td173:'添加教師',
-        td174:'組長',
-        td175:'組員',
-        td176:'已綁定',
-        td177:'未綁定',
-        td178:'添加成員',
-        td179:'設為組長',
-        td180:'取消組長',
-        td181:'身份',
-        td182:'狀態',
-        td183:'設置成功',
-        td184:'設置失敗',
-        td185:'刪除組別',
-        td186:'刪除組別後,當前組的老師將默認被分配到相鄰組別,確認刪除嗎?',
-        td187:'確認刪除所有分組嗎?',
-        td188:'請設置所有組名',
-        td189:'保存成功',
-        td190:'保存失敗',
-        td191:'請輸入組名再添加組別',
-        td192:'組名重復',
-        td193:'請選擇需要移除的老師',
-        td194:'批量移除',
-        td195:'確認批量移除',
-        td196:'個參訓老師嗎?',
-        td197:'移除成功',
-        td198:'移除失敗',
-        td199:'移除參訓老師',
-        td200:'是否確認移除',
-        td201:'研修名單',
-        td202:'添加成功',
-        td203:'保存研修名單失敗',
-        td204:'查詢研修名單失敗'
+    td: {
+        td1: '研修統計',
+        td2: '學時統計',
+        td3: 'Total Study Length:',
+        td4: 'minutes',
+        td5: 'Study Length',
+        td6: '未開始:',
+        td7: '進行中:',
+        td8: '已完成:',
+        td9: '合格率',
+        td10: '學校概覽',
+        td11: '學校列表',
+        td12: '導出學校數據',
+        td13: '導出教師數據',
+        td14: '搜索學校',
+        td15: '參訓人數',
+        td16: '詳情>>>',
+        td17: '未搜索到學校',
+        td18: '暫無學校數據',
+        td19: '學校數量',
+        td20: 'Total Study Length',
+        td21: '合格人數',
+        td22: '線上研修',
+        td23: '校本研修',
+        td24: '認證材料',
+        td25: '課堂實錄',
+        td26: '未修滿',
+        td27: '能力點',
+        td28: '學校',
+        td29: '姓名',
+        td30: '線上研修學時',
+        td31: '所選微能力點',
+        td32: '已修滿的能力點數量',
+        td33: '認證材料學時',
+        td34: '校本研修學時',
+        td35: '課堂實錄學時',
+        td36: '認證材料需提交數',
+        td37: '已提交認證材料數',
+        td38: '已提交認證材料能力點',
+        td39: '未提交認證材料數',
+        td40: '未提交認證材料能力點',
+        td41: '作業未提交數',
+        td42: '課堂實錄是否提交',
+        td43: '已提交',
+        td44: '未提交',
+        td45: '研修情況統計表',
+        td46: '未開始人數',
+        td47: '進行中人數',
+        td48: '已完成人數',
+        td49: '參訓總人數',
+        td50: '學校數據統計',
+        td51: '資源列表',
+        td52: '添加資源',
+        td53: '完成率:',
+        td54: '返回區級',
+        td55: '所有學校',
+        td56: '共建',
+        td57: '個試點校,參訓人數',
+        td58: 'Re-upload',
+        td59: 'Theme',
+        td60: 'Time',
+        td61: 'Venue',
+        td62: 'Description',
+        td63: '請選擇作業附件上傳類型',
+        td64: '簽到成功',
+        td65: '數據概覽',
+        td66: '的',
+        td67: '查詢簽到數據失敗',
+        td68: '獲取作業提交數據失敗',
+        td69: '合格率統計',
+        td70: '能力維度選修占比',
+        td71: '能力點選修占比',
+        td72: '研修小組統計',
+        td73: '暫無小組數據',
+        td74: '未分組',
+        td75: '查看成員',
+        td76: '完成線上研修',
+        td77: '完成認證材料',
+        td78: '完成校本研修',
+        td79: '完成課堂記錄',
+        td80: '全部完成',
+        td81: '完成率',
+        td82: '優秀',
+        td83: '合格',
+        td84: '不合格',
+        td85: '獲取統計數據失敗',
+        td86: '數據總覽',
+        td87: '詳細數據',
+        td88: '搜索',
+        td89: '數據導出',
+        td90: '未完成',
+        td91: '已完成',
+        td92: '教師姓名',
+        td93: '小組',
+        td94: '完成狀態',
+        td95: '姓名',
+        td96: '組別',
+        td97: '獲取統計數據失敗',
+        td98: '根據省平臺要求,教師必須滿足以下條件才可獲得校本研修活動學時:',
+        td99: '1、10學時中至少有一次需提交作業的校本研修活動',
+        td100: '2、在活動中成功提交PDF作業',
+        td101: 'Submit Method',
+        td102: 'All teachers must submit',
+        td103: 'The team leader will submit on behalf of the team',
+        td104: 'Please set the homework type',
+        td105: 'Please set submit method',
+        td106: '未分組老師',
+        td107: '創建研修問卷失敗',
+        td108: '創建研修評測失敗',
+        td109: '輸入手機號',
+        td110: '未查詢到對應賬號!請檢查後重試!',
+        td111: '已簽到成功,請勿重復操作!',
+        td112: '請輸入正確手機號!',
+        td113: '簽到失敗,請重新簽到',
+        td114: '簽到成功',
+        td115: '簽到失敗',
+        td116: '溫馨提示:區級活動不計入校本研修學時',
+        td117: '未發布',
+        td118: '進行中',
+        td119: '已結束',
+        td120: '活動視頻:',
+        td121: '播放',
+        td122: '刪除',
+        td123: '上傳',
+        td124: '(視頻只能上傳一個)',
+        td125: '活動資料:',
+        td126: '繼續上傳',
+        td127: '(資料可以上傳多份)',
+        td128: '根據省平臺要求,教師必須滿足以下條件才可獲得校本研修活動學時: 1、10學時中至少有一次需提交作業的校本研修活動 2、在活動中成功提交PDF作業',
+        td129: 'Batch Pass',
+        td130: '請選擇學校老師參加並發布活動',
+        td131: '選擇老師',
+        td132: '繼續挑選(已選',
+        td133: '位)',
+        td134: '發布活動',
+        td135: '上傳中',
+        td136: '上傳完成',
+        td137: '添加教師',
+        td138: '教研組',
+        td139: '教研組篩選',
+        td140: '未設置',
+        td141: '查詢教研組失敗',
+        td142: '請勾選參加活動的老師',
+        td143: '刪除文件',
+        td144: '是否確認刪除',
+        td145: '刪除成功',
+        td146: '刪除失敗',
+        td147: '文件上傳中,請等待文件上傳完成',
+        td148: '活動視頻只支持mp4文件格式',
+        td149: '學校空間已滿',
+        td150: '上傳失敗',
+        td151: '請選擇需要批量處理',
+        td152: '合格',
+        td153: '不合格',
+        td154: '的老師',
+        td155: '批量處理',
+        td156: '確認將所選老師全部設置為合格嗎?',
+        td157: '問卷作答數據獲取失敗',
+        td158: '獲取作業提交數據失敗',
+        td159: '獲取名單列表失敗',
+        td160: '獲取簽到數據失敗',
+        td161: '學校',
+        td162: '查詢教師列表失敗',
+        td163: '對象:',
+        td164: '暫無',
+        td165: '查詢研修列表失敗',
+        td166: '人數:',
+        td167: '(已同步省平臺名單)',
+        td168: '溫馨提示:空白分組(分組內沒有添加教師)不會被保存。',
+        td169: '保存分組',
+        td170: '分組視圖',
+        td171: '列表視圖',
+        td172: '移除教師',
+        td173: '添加教師',
+        td174: '組長',
+        td175: '組員',
+        td176: '已綁定',
+        td177: '未綁定',
+        td178: '添加成員',
+        td179: '設為組長',
+        td180: '取消組長',
+        td181: '身份',
+        td182: '狀態',
+        td183: '設置成功',
+        td184: '設置失敗',
+        td185: '刪除組別',
+        td186: '刪除組別後,當前組的老師將默認被分配到相鄰組別,確認刪除嗎?',
+        td187: '確認刪除所有分組嗎?',
+        td188: '請設置所有組名',
+        td189: '保存成功',
+        td190: '保存失敗',
+        td191: '請輸入組名再添加組別',
+        td192: '組名重復',
+        td193: '請選擇需要移除的老師',
+        td194: '批量移除',
+        td195: '確認批量移除',
+        td196: '個參訓老師嗎?',
+        td197: '移除成功',
+        td198: '移除失敗',
+        td199: '移除參訓老師',
+        td200: '是否確認移除',
+        td201: '研修名單',
+        td202: '添加成功',
+        td203: '保存研修名單失敗',
+        td204: '查詢研修名單失敗',
+        td205: '數據更新中,當前數據更新於',
+        td206: ',如需查看最新數據請稍後。',
+        td207: '當前已是最新數據,更新於'
     },
     // 单位管理
     unit: {

+ 225 - 210
TEAMModelOS/ClientApp/public/lang/zh-CN.js

@@ -2905,6 +2905,18 @@ const LANG_ZH_CN = {
     },
     // 课堂记录
     lessonRecord: {
+        export: {
+            order: '序号',
+            tchName: '教师姓名',
+            tmdid: '醍摩豆ID',
+            recordCount: '课堂记录总数',
+            recordName: '课程名称',
+            time: '授课时间',
+            sheet1: '教师课堂记录数量统计',
+            sheet2: '学校课堂记录总表',
+            fileName: '课堂记录统计表',
+            noData: '暂无数据导出'
+        },
         delStatusTip: '课堂记录已被清理',
         noRecordTip: '当前学段下未查询到课堂记录!',
         overdue: '到期',
@@ -2951,7 +2963,7 @@ const LANG_ZH_CN = {
         count5: '累计测验总题数',
         count6: '累计互动总数',
         count7: '本学期新增课堂记录数',
-        export: '导出数据',
+        exportData: '导出数据',
         tagMg: '类别管理',
         tchName: '教师',
         lessonName: '课堂名称',
@@ -3979,10 +3991,10 @@ const LANG_ZH_CN = {
         setNoErr1: '请设置学生班级',
         setNoErr2: '座号在班级中重复',
         sltStuTips: '请先选择学生',
-        imeiErr1:'电子学生证只能为数字',
-        imeiErr2:'电子学生证为15位数字',
-        imeiErr3:'请输入学生ID',
-        imeiErr4:'已经绑定此编号,如果当前学生绑定此编号,原来学生的将会自动取消绑定。',
+        imeiErr1: '电子学生证只能为数字',
+        imeiErr2: '电子学生证为15位数字',
+        imeiErr3: '请输入学生ID',
+        imeiErr4: '已经绑定此编号,如果当前学生绑定此编号,原来学生的将会自动取消绑定。',
         addOk: '添加成功',
         updOk: '修改成功',
         addErr: '添加失败',
@@ -6332,211 +6344,214 @@ const LANG_ZH_CN = {
         }
     },
     //研修
-    td:{
-        td1:'研修统计',
-        td2:'学时统计',
-        td3:'总学时:',
-        td4:'分钟',
-        td5:'学时',
-        td6:'未开始:',
-        td7:'进行中:',
-        td8:'已完成:',
-        td9:'合格率',
-        td10:'学校概览',
-        td11:'学校列表',
-        td12:'导出学校数据',
-        td13:'导出教师数据',
-        td14:'搜索学校',
-        td15:'参训人数',
-        td16:'详情>>>',
-        td17:'未搜索到学校',
-        td18:'暂无学校数据',
-        td19:'学校数量',
-        td20:'总学时',
-        td21:'合格人数',
-        td22:'线上研修',
-        td23:'校本研修',
-        td24:'认证材料',
-        td25:'课堂实录',
-        td26:'未修满',
-        td27:'能力点',
-        td28:'学校',
-        td29:'姓名',
-        td30:'线上研修学时',
-        td31:'所选微能力点',
-        td32:'已修满的能力点数量',
-        td33:'认证材料学时',
-        td34:'校本研修学时',
-        td35:'课堂实录学时',
-        td36:'认证材料需提交数',
-        td37:'已提交认证材料数',
-        td38:'已提交认证材料能力点',
-        td39:'未提交认证材料数',
-        td40:'未提交认证材料能力点',
-        td41:'作业未提交数',
-        td42:'课堂实录是否提交',
-        td43:'已提交',
-        td44:'未提交',
-        td45:'研修情况统计表',
-        td46:'未开始人数',
-        td47:'进行中人数',
-        td48:'已完成人数',
-        td49:'参训总人数',
-        td50:'学校数据统计',
-        td51:'资源列表',
-        td52:'添加资源',
-        td53:'完成率:',
-        td54:'返回区级',
-        td55:'所有学校',
-        td56:'共建',
-        td57:'个试点校,参训人数',
-        td58:'重新上传',
-        td59:'主题',
-        td60:'时间',
-        td61:'地点',
-        td62:'描述',
-        td63:'请选择作业附件上传类型',
-        td64:'签到成功',
-        td65:'数据概览',
-        td66:'的',
-        td67:'查询签到数据失败',
-        td68:'获取作业提交数据失败',
-        td69:'合格率统计',
-        td70:'能力维度选修占比',
-        td71:'能力点选修占比',
-        td72:'研修小组统计',
-        td73:'暂无小组数据',
-        td74:'未分组',
-        td75:'查看成员',
-        td76:'完成线上研修',
-        td77:'完成认证材料',
-        td78:'完成校本研修',
-        td79:'完成课堂记录',
-        td80:'全部完成',
-        td81:'完成率',
-        td82:'优秀',
-        td83:'合格',
-        td84:'不合格',
-        td85:'获取统计数据失败',
-        td86:'数据总览',
-        td87:'详细数据',
-        td88:'搜索',
-        td89:'数据导出',
-        td90:'未完成',
-        td91:'已完成',
-        td92:'教师姓名',
-        td93:'小组',
-        td94:'完成状态',
-        td95:'姓名',
-        td96:'组别',
-        td97:'获取统计数据失败',
-        td98:'根据省平台要求,教师必须满足以下条件才可获得校本研修活动学时:',
-        td99:'1、10学时中至少有一次需提交作业的校本研修活动',
-        td100:'2、在活动中成功提交PDF作业',
-        td101:'提交方式',
-        td102:'所有老师提交',
-        td103:'由组长统一提交',
-        td104:'请设置作业类型',
-        td105:'请设置提交方式',
-        td106:'未分组老师',
-        td107:'创建研修问卷失败',
-        td108:'创建研修评测失败',
-        td109:'输入手机号',
-        td110:'未查询到对应账号!请检查后重试!',
-        td111:'已签到成功,请勿重复操作!',
-        td112:'请输入正确手机号!',
-        td113:'签到失败,请重新签到',
-        td114:'签到成功',
-        td115:'签到失败',
-        td116:'温馨提示:区级活动不计入校本研修学时',
-        td117:'未发布',
-        td118:'进行中',
-        td119:'已结束',
-        td120:'活动视频:',
-        td121:'播放',
-        td122:'删除',
-        td123:'上传',
-        td124:'(视频只能上传一个)',
-        td125:'活动资料:',
-        td126:'继续上传',
-        td127:'(资料可以上传多份)',
-        td128:'根据省平台要求,教师必须满足以下条件才可获得校本研修活动学时: 1、10学时中至少有一次需提交作业的校本研修活动 2、在活动中成功提交PDF作业',
-        td129:'批量合格',
-        td130:'请选择学校老师参加并发布活动',
-        td131:'选择老师',
-        td132:'继续挑选(已选',
-        td133:'位)',
-        td134:'发布活动',
-        td135:'上传中',
-        td136:'上传完成',
-        td137:'添加教师',
-        td138:'教研组',
-        td139:'教研组筛选',
-        td140:'未设置',
-        td141:'查询教研组失败',
-        td142:'请勾选参加活动的老师',
-        td143:'删除文件',
-        td144:'是否确认删除',
-        td145:'删除成功',
-        td146:'删除失败',
-        td147:'文件上传中,请等待文件上传完成',
-        td148:'活动视频只支持mp4文件格式',
-        td149:'学校空间已满',
-        td150:'上传失败',
-        td151:'请选择需要批量处理',
-        td152:'合格',
-        td153:'不合格',
-        td154:'的老师',
-        td155:'批量处理',
-        td156:'确认将所选老师全部设置为合格吗?',
-        td157:'问卷作答数据获取失败',
-        td158:'获取作业提交数据失败',
-        td159:'获取名单列表失败',
-        td160:'获取签到数据失败',
-        td161:'学校',
-        td162:'查询教师列表失败',
-        td163:'对象:',
-        td164:'暂无',
-        td165:'查询研修列表失败',
-        td166:'人数:',
-        td167:'(已同步省平台名单)',
-        td168:'温馨提示:空白分组(分组内没有添加教师)不会被保存。',
-        td169:'保存分组',
-        td170:'分组视图',
-        td171:'列表视图',
-        td172:'移除教师',
-        td173:'添加教师',
-        td174:'组长',
-        td175:'组员',
-        td176:'已绑定',
-        td177:'未绑定',
-        td178:'添加成员',
-        td179:'设为组长',
-        td180:'取消组长',
-        td181:'身份',
-        td182:'状态',
-        td183:'设置成功',
-        td184:'设置失败',
-        td185:'删除组别',
-        td186:'删除组别后,当前组的老师将默认被分配到相邻组别,确认删除吗?',
-        td187:'确认删除所有分组吗?',
-        td188:'请设置所有组名',
-        td189:'保存成功',
-        td190:'保存失败',
-        td191:'请输入组名再添加组别',
-        td192:'组名重复',
-        td193:'请选择需要移除的老师',
-        td194:'批量移除',
-        td195:'确认批量移除',
-        td196:'个参训老师吗?',
-        td197:'移除成功',
-        td198:'移除失败',
-        td199:'移除参训老师',
-        td200:'是否确认移除',
-        td201:'研修名单',
-        td202:'添加成功',
-        td203:'保存研修名单失败',
-        td204:'查询研修名单失败'
+    td: {
+        td1: '研修统计',
+        td2: '学时统计',
+        td3: '总学时:',
+        td4: '分钟',
+        td5: '学时',
+        td6: '未开始:',
+        td7: '进行中:',
+        td8: '已完成:',
+        td9: '合格率',
+        td10: '学校概览',
+        td11: '学校列表',
+        td12: '导出学校数据',
+        td13: '导出教师数据',
+        td14: '搜索学校',
+        td15: '参训人数',
+        td16: '详情>>>',
+        td17: '未搜索到学校',
+        td18: '暂无学校数据',
+        td19: '学校数量',
+        td20: '总学时',
+        td21: '合格人数',
+        td22: '线上研修',
+        td23: '校本研修',
+        td24: '认证材料',
+        td25: '课堂实录',
+        td26: '未修满',
+        td27: '能力点',
+        td28: '学校',
+        td29: '姓名',
+        td30: '线上研修学时',
+        td31: '所选微能力点',
+        td32: '已修满的能力点数量',
+        td33: '认证材料学时',
+        td34: '校本研修学时',
+        td35: '课堂实录学时',
+        td36: '认证材料需提交数',
+        td37: '已提交认证材料数',
+        td38: '已提交认证材料能力点',
+        td39: '未提交认证材料数',
+        td40: '未提交认证材料能力点',
+        td41: '作业未提交数',
+        td42: '课堂实录是否提交',
+        td43: '已提交',
+        td44: '未提交',
+        td45: '研修情况统计表',
+        td46: '未开始人数',
+        td47: '进行中人数',
+        td48: '已完成人数',
+        td49: '参训总人数',
+        td50: '学校数据统计',
+        td51: '资源列表',
+        td52: '添加资源',
+        td53: '完成率:',
+        td54: '返回区级',
+        td55: '所有学校',
+        td56: '共建',
+        td57: '个试点校,参训人数',
+        td58: '重新上传',
+        td59: '主题',
+        td60: '时间',
+        td61: '地点',
+        td62: '描述',
+        td63: '请选择作业附件上传类型',
+        td64: '签到成功',
+        td65: '数据概览',
+        td66: '的',
+        td67: '查询签到数据失败',
+        td68: '获取作业提交数据失败',
+        td69: '合格率统计',
+        td70: '能力维度选修占比',
+        td71: '能力点选修占比',
+        td72: '研修小组统计',
+        td73: '暂无小组数据',
+        td74: '未分组',
+        td75: '查看成员',
+        td76: '完成线上研修',
+        td77: '完成认证材料',
+        td78: '完成校本研修',
+        td79: '完成课堂记录',
+        td80: '全部完成',
+        td81: '完成率',
+        td82: '优秀',
+        td83: '合格',
+        td84: '不合格',
+        td85: '获取统计数据失败',
+        td86: '数据总览',
+        td87: '详细数据',
+        td88: '搜索',
+        td89: '数据导出',
+        td90: '未完成',
+        td91: '已完成',
+        td92: '教师姓名',
+        td93: '小组',
+        td94: '完成状态',
+        td95: '姓名',
+        td96: '组别',
+        td97: '获取统计数据失败',
+        td98: '根据省平台要求,教师必须满足以下条件才可获得校本研修活动学时:',
+        td99: '1、10学时中至少有一次需提交作业的校本研修活动',
+        td100: '2、在活动中成功提交PDF作业',
+        td101: '提交方式',
+        td102: '所有老师提交',
+        td103: '由组长统一提交',
+        td104: '请设置作业类型',
+        td105: '请设置提交方式',
+        td106: '未分组老师',
+        td107: '创建研修问卷失败',
+        td108: '创建研修评测失败',
+        td109: '输入手机号',
+        td110: '未查询到对应账号!请检查后重试!',
+        td111: '已签到成功,请勿重复操作!',
+        td112: '请输入正确手机号!',
+        td113: '签到失败,请重新签到',
+        td114: '签到成功',
+        td115: '签到失败',
+        td116: '温馨提示:区级活动不计入校本研修学时',
+        td117: '未发布',
+        td118: '进行中',
+        td119: '已结束',
+        td120: '活动视频:',
+        td121: '播放',
+        td122: '删除',
+        td123: '上传',
+        td124: '(视频只能上传一个)',
+        td125: '活动资料:',
+        td126: '继续上传',
+        td127: '(资料可以上传多份)',
+        td128: '根据省平台要求,教师必须满足以下条件才可获得校本研修活动学时: 1、10学时中至少有一次需提交作业的校本研修活动 2、在活动中成功提交PDF作业',
+        td129: '批量合格',
+        td130: '请选择学校老师参加并发布活动',
+        td131: '选择老师',
+        td132: '继续挑选(已选',
+        td133: '位)',
+        td134: '发布活动',
+        td135: '上传中',
+        td136: '上传完成',
+        td137: '添加教师',
+        td138: '教研组',
+        td139: '教研组筛选',
+        td140: '未设置',
+        td141: '查询教研组失败',
+        td142: '请勾选参加活动的老师',
+        td143: '删除文件',
+        td144: '是否确认删除',
+        td145: '删除成功',
+        td146: '删除失败',
+        td147: '文件上传中,请等待文件上传完成',
+        td148: '活动视频只支持mp4文件格式',
+        td149: '学校空间已满',
+        td150: '上传失败',
+        td151: '请选择需要批量处理',
+        td152: '合格',
+        td153: '不合格',
+        td154: '的老师',
+        td155: '批量处理',
+        td156: '确认将所选老师全部设置为合格吗?',
+        td157: '问卷作答数据获取失败',
+        td158: '获取作业提交数据失败',
+        td159: '获取名单列表失败',
+        td160: '获取签到数据失败',
+        td161: '学校',
+        td162: '查询教师列表失败',
+        td163: '对象:',
+        td164: '暂无',
+        td165: '查询研修列表失败',
+        td166: '人数:',
+        td167: '(已同步省平台名单)',
+        td168: '温馨提示:空白分组(分组内没有添加教师)不会被保存。',
+        td169: '保存分组',
+        td170: '分组视图',
+        td171: '列表视图',
+        td172: '移除教师',
+        td173: '添加教师',
+        td174: '组长',
+        td175: '组员',
+        td176: '已绑定',
+        td177: '未绑定',
+        td178: '添加成员',
+        td179: '设为组长',
+        td180: '取消组长',
+        td181: '身份',
+        td182: '状态',
+        td183: '设置成功',
+        td184: '设置失败',
+        td185: '删除组别',
+        td186: '删除组别后,当前组的老师将默认被分配到相邻组别,确认删除吗?',
+        td187: '确认删除所有分组吗?',
+        td188: '请设置所有组名',
+        td189: '保存成功',
+        td190: '保存失败',
+        td191: '请输入组名再添加组别',
+        td192: '组名重复',
+        td193: '请选择需要移除的老师',
+        td194: '批量移除',
+        td195: '确认批量移除',
+        td196: '个参训老师吗?',
+        td197: '移除成功',
+        td198: '移除失败',
+        td199: '移除参训老师',
+        td200: '是否确认移除',
+        td201: '研修名单',
+        td202: '添加成功',
+        td203: '保存研修名单失败',
+        td204: '查询研修名单失败',
+        td205: '数据更新中,当前数据更新于',
+        td206: ',如需查看最新数据请稍后。',
+        td207: '当前已是最新数据,更新于'
     },
     // 单位管理
     unit: {

+ 245 - 230
TEAMModelOS/ClientApp/public/lang/zh-TW.js

@@ -48,8 +48,8 @@ const LANG_ZH_TW = {
         noSubmit1: '認證材料未提交',
         noSubmit2: '校本研習作業未提交',
         noSubmit3: '課堂實錄未提交',
-        teacherInfo: '教師信息',
-        tip3: '教師在線上研習觀看增能項目所關聯的視頻資源總時長,1學時=45分鐘',
+        teacherInfo: '教師資訊',
+        tip3: '教師在線上研習觀看增能項目所關聯的影片資源總時長,1學時=45分鐘',
         tip4: '最少有',
         tip5: '個增能項目的認證材料合格即可獲得學時',
         tip6: '認證材料必須全部通過才能獲得學時',
@@ -84,17 +84,17 @@ const LANG_ZH_TW = {
         noComment: '無評價內容',
         tip11: '確定',
         tip12: '互評嗎',
-        tip13: '設成功!當前互評狀態為:',
-        tip14: '設失敗!',
+        tip13: '設成功!當前互評狀態為:',
+        tip14: '設失敗!',
         tip15: '當前教師暫未上傳活動pdf作業,無法通過!',
         tip16: '操作成功!',
-        tip17: '確認將所有教師參與的 不需要提交的 以及 需要併且已經提交PDF 的研習活動全部設為通過嗎?',
-        tip18: '確認將所有教師已經自評過的增能項目全部設為合格嗎?',
+        tip17: '確認將所有教師參與的 不需要提交的 以及 需要併且已經提交PDF 的研習活動全部設為通過嗎?',
+        tip18: '確認將所有教師已經自評過的增能項目全部設為合格嗎?',
         tip19: '操作失敗!',
-        tip20: '確認將所有教師已提交的課堂實錄全部設為合格嗎?',
+        tip20: '確認將所有教師已提交的課堂實錄全部設為合格嗎?',
         tip21: '確認將當前所有教師的校本研習評定為合格嗎?',
         tip22: '批量操作',
-        tip23: '設成功!',
+        tip23: '設成功!',
         noProvince: '暫未對接省平臺',
     },
     // 研習模块
@@ -109,7 +109,7 @@ const LANG_ZH_TW = {
         check: {
             isCheck: '是否為考核人員',
             tip1: '確認修改當前教師的審核人員身份嗎?',
-            tip2: '已添加',
+            tip2: '已新增',
             tip3: '為審核人員',
             tip4: '已取消',
             tip5: '的審核人員身份!',
@@ -191,7 +191,7 @@ const LANG_ZH_TW = {
             scoreUp: '分以上',
             self: '自評結果',
             tip6: '溫馨提示',
-            tip7: '您未確認“提交評審結果”,無法存修改內容,是否確認離開?',
+            tip7: '您未確認“提交評審結果”,無法存修改內容,是否確認離開?',
             tip8: '等',
             tip9: '個文件已更新!',
             tip10: '刪除認證材料',
@@ -571,8 +571,8 @@ const LANG_ZH_TW = {
         ctFmText15: '其他',
         ctFmText16: '請選擇所在地區',
         ctFmText17: '請選擇諮詢內容',
-        ctFmText18: '存成功,稍後我們將與您聯繫',
-        ctFmText19: '存失敗',
+        ctFmText18: '存成功,稍後我們將與您聯繫',
+        ctFmText19: '存失敗',
         ctFmText20: '智慧教室',
         ctFmText21: '研習中心',
         ctFmText22: '顧問服務',
@@ -1293,8 +1293,8 @@ const LANG_ZH_TW = {
             evt3: '挑人:',
             evt4: '收集:',
             evt5: '收集的作品',
-            oldHT: '舊版HiTeach上傳的數據,無法查看課中評',
-            wrkCmp: '作品回',
+            oldHT: '舊版HiTeach上傳的數據,無法查看課中評',
+            wrkCmp: '作品回',
             dlStuWrk: '下載學生作品',
             stuWrk: '學生作品'
         }
@@ -2102,15 +2102,15 @@ const LANG_ZH_TW = {
             multiMedia: "多媒體教學環境",
             studyEnvir: "智慧學習環境",
             allDimension: "全部維度",
-            keepRecords: "存記錄",
+            keepRecords: "存記錄",
             close: "關閉提示",
-            autoSave: "已經自動存",
-            autoSaving: "自動存中",
-            addtoAbility: "添加增能項目",
+            autoSave: "已經自動存",
+            autoSaving: "自動存中",
+            addtoAbility: "新增增能項目",
             addtoContent: "請到省平臺挑選您想學習的增能項目",
-            message4: "該檔案缺少資訊,無法存學習記錄",
+            message4: "該檔案缺少資訊,無法存學習記錄",
             had: "已獲得",
-            submitExam: "提交評",
+            submitExam: "提交評",
             timehave: "學時獲得",
         },
         // 校本研習
@@ -2717,7 +2717,7 @@ const LANG_ZH_TW = {
             noKn: '試卷沒有知識點數據',
             dataErr: '評量數據異常',
             goingNoData: '評量進行中,無法查看統計數據',
-            pendingNoData: '評暫未發布,無法查看統計數據',
+            pendingNoData: '評暫未發布,無法查看統計數據',
             paperErr: '試卷數據異常'
         },
 
@@ -2905,6 +2905,18 @@ const LANG_ZH_TW = {
     },
     // 课堂记录
     lessonRecord: {
+        export: {
+            order: '序號',
+            tchName: '教師姓名',
+            tmdid: '醍摩豆ID',
+            recordCount: '課堂記錄總數',
+            recordName: '課程名稱',
+            time: '授課時間',
+            sheet1: '教師課堂記錄數量統計',
+            sheet2: '學校課堂記錄總表',
+            fileName: '課堂記錄統計表',
+            noData: '暫無數據匯出'
+        },
         delStatusTip: '課堂記錄已被清理',
         noRecordTip: '當前學段下未查詢到課堂記錄!',
         overdue: '到期',
@@ -2951,7 +2963,7 @@ const LANG_ZH_TW = {
         count5: '累計測驗總題數',
         count6: '累計互動總數',
         count7: '本學期新增課堂記錄數',
-        export: '匯出數據',
+        exportData: '匯出數據',
         tagMg: '類別管理',
         tchName: '教師',
         lessonName: '課堂名稱',
@@ -3350,7 +3362,7 @@ const LANG_ZH_TW = {
             noVideo: "暫沒有影片資源",
         }
     },
-    // 基础信息
+    // 基础資訊
     schoolBaseInfo: {
         commonset: '通用設定',
         pdMgt: '學制管理',
@@ -4052,7 +4064,7 @@ const LANG_ZH_TW = {
         sit15: 'gPhone: 選填,監護人手機號碼',
         sit16: 'imei: 選填,電子學生證編號,由15位數字組成',
         sit17: '座號重複(與已有學生)',
-        sit18: '電子學生證編號重',
+        sit18: '電子學生證編號重',
         sit19: '電子學生證格式錯誤',
         sit20: '電子學生證編號為15位數字組成',
         sit21: 'M(男)或F(女)代表學生性別',
@@ -5855,7 +5867,7 @@ const LANG_ZH_TW = {
         teacherList: '教師名單',
         noIpmtData: '暫無可匯入數據'
     },
-    // 提示信息
+    // 提示資訊
     tip: {
         typeScoreTip: '每道題的最低配分為0.5分',
         importPaper: '您可將設定好的試卷 Word 檔案透過此功能轉換成系統試卷運用於課堂測驗、學生線上測驗或是閱卷考試運用',
@@ -6332,211 +6344,214 @@ const LANG_ZH_TW = {
         }
     },
     //研習
-    td:{
-        td1:'研習統計',
-        td2:'學時統計',
-        td3:'總學時:',
-        td4:'分鐘',
-        td5:'學時',
-        td6:'未開始:',
-        td7:'進行中:',
-        td8:'已完成:',
-        td9:'合格率',
-        td10:'學校概覽',
-        td11:'學校列表',
-        td12:'導出學校數據',
-        td13:'導出教師數據',
-        td14:'搜索學校',
-        td15:'參訓人數',
-        td16:'詳情>>>',
-        td17:'未搜索到學校',
-        td18:'暫無學校數據',
-        td19:'學校數量',
-        td20:'總學時',
-        td21:'合格人數',
-        td22:'線上研習',
-        td23:'校本研習',
-        td24:'認證材料',
-        td25:'課堂實錄',
-        td26:'未修滿',
-        td27:'增能項目',
-        td28:'學校',
-        td29:'姓名',
-        td30:'線上研習學時',
-        td31:'所選增能項目',
-        td32:'已修滿的增能項目數量',
-        td33:'認證材料學時',
-        td34:'校本研習學時',
-        td35:'課堂實錄學時',
-        td36:'認證材料需提交數',
-        td37:'已提交認證材料數',
-        td38:'已提交認證材料增能項目',
-        td39:'未提交認證材料數',
-        td40:'未提交認證材料增能項目',
-        td41:'作業未提交數',
-        td42:'課堂實錄是否提交',
-        td43:'已提交',
-        td44:'未提交',
-        td45:'研習情況統計表',
-        td46:'未開始人數',
-        td47:'進行中人數',
-        td48:'已完成人數',
-        td49:'參訓總人數',
-        td50:'學校數據統計',
-        td51:'資源列表',
-        td52:'添加資源',
-        td53:'完成率:',
-        td54:'返回區級',
-        td55:'所有學校',
-        td56:'共建',
-        td57:'個試點校,參訓人數',
-        td58:'重新上傳',
-        td59:'主題',
-        td60:'時間',
-        td61:'地點',
-        td62:'描述',
-        td63:'請選擇作業附件上傳類型',
-        td64:'簽到成功',
-        td65:'數據概覽',
-        td66:'的',
-        td67:'查詢簽到數據失敗',
-        td68:'獲取作業提交數據失敗',
-        td69:'合格率統計',
-        td70:'能力維度選修占比',
-        td71:'增能項目選修占比',
-        td72:'研習小組統計',
-        td73:'暫無小組數據',
-        td74:'未分組',
-        td75:'查看成員',
-        td76:'完成線上研習',
-        td77:'完成認證材料',
-        td78:'完成校本研習',
-        td79:'完成課堂記錄',
-        td80:'全部完成',
-        td81:'完成率',
-        td82:'優秀',
-        td83:'合格',
-        td84:'不合格',
-        td85:'獲取統計數據失敗',
-        td86:'數據總覽',
-        td87:'詳細數據',
-        td88:'搜索',
-        td89:'數據導出',
-        td90:'未完成',
-        td91:'已完成',
-        td92:'教師姓名',
-        td93:'小組',
-        td94:'完成狀態',
-        td95:'姓名',
-        td96:'組別',
-        td97:'獲取統計數據失敗',
-        td98:'根據省平臺要求,教師必須滿足以下條件才可獲得校本研習活動學時:',
-        td99:'1、10學時中至少有一次需提交作業的校本研習活動',
-        td100:'2、在活動中成功提交PDF作業',
-        td101:'提交方式',
-        td102:'所有老師提交',
-        td103:'由組長統一提交',
-        td104:'請設置作業類型',
-        td105:'請設置提交方式',
-        td106:'未分組老師',
-        td107:'創建研習問卷失敗',
-        td108:'創建研習評測失敗',
-        td109:'輸入手機號',
-        td110:'未查詢到對應賬號!請檢查後重試!',
-        td111:'已簽到成功,請勿重復操作!',
-        td112:'請輸入正確手機號!',
-        td113:'簽到失敗,請重新簽到',
-        td114:'簽到成功',
-        td115:'簽到失敗',
-        td116:'溫馨提示:區級活動不計入校本研習學時',
-        td117:'未發布',
-        td118:'進行中',
-        td119:'已結束',
-        td120:'活動視頻:',
-        td121:'播放',
-        td122:'刪除',
-        td123:'上傳',
-        td124:'(視頻只能上傳一個)',
-        td125:'活動資料:',
-        td126:'繼續上傳',
-        td127:'(資料可以上傳多份)',
-        td128:'根據省平臺要求,教師必須滿足以下條件才可獲得校本研習活動學時: 1、10學時中至少有一次需提交作業的校本研習活動 2、在活動中成功提交PDF作業',
-        td129:'批量合格',
-        td130:'請選擇學校老師參加並發布活動',
-        td131:'選擇老師',
-        td132:'繼續挑選(已選',
-        td133:'位)',
-        td134:'發布活動',
-        td135:'上傳中',
-        td136:'上傳完成',
-        td137:'添加教師',
-        td138:'教研組',
-        td139:'教研組篩選',
-        td140:'未設置',
-        td141:'查詢教研組失敗',
-        td142:'請勾選參加活動的老師',
-        td143:'刪除文件',
-        td144:'是否確認刪除',
-        td145:'刪除成功',
-        td146:'刪除失敗',
-        td147:'文件上傳中,請等待文件上傳完成',
-        td148:'活動視頻只支持mp4文件格式',
-        td149:'學校空間已滿',
-        td150:'上傳失敗',
-        td151:'請選擇需要批量處理',
-        td152:'合格',
-        td153:'不合格',
-        td154:'的老師',
-        td155:'批量處理',
-        td156:'確認將所選老師全部設置為合格嗎?',
-        td157:'問卷作答數據獲取失敗',
-        td158:'獲取作業提交數據失敗',
-        td159:'獲取名單列表失敗',
-        td160:'獲取簽到數據失敗',
-        td161:'學校',
-        td162:'查詢教師列表失敗',
-        td163:'對象:',
-        td164:'暫無',
-        td165:'查詢研習列表失敗',
-        td166:'人數:',
-        td167:'(已同步省平臺名單)',
-        td168:'溫馨提示:空白分組(分組內沒有添加教師)不會被保存。',
-        td169:'保存分組',
-        td170:'分組視圖',
-        td171:'列表視圖',
-        td172:'移除教師',
-        td173:'添加教師',
-        td174:'組長',
-        td175:'組員',
-        td176:'已綁定',
-        td177:'未綁定',
-        td178:'添加成員',
-        td179:'設為組長',
-        td180:'取消組長',
-        td181:'身份',
-        td182:'狀態',
-        td183:'設置成功',
-        td184:'設置失敗',
-        td185:'刪除組別',
-        td186:'刪除組別後,當前組的老師將默認被分配到相鄰組別,確認刪除嗎?',
-        td187:'確認刪除所有分組嗎?',
-        td188:'請設置所有組名',
-        td189:'保存成功',
-        td190:'保存失敗',
-        td191:'請輸入組名再添加組別',
-        td192:'組名重復',
-        td193:'請選擇需要移除的老師',
-        td194:'批量移除',
-        td195:'確認批量移除',
-        td196:'個參訓老師嗎?',
-        td197:'移除成功',
-        td198:'移除失敗',
-        td199:'移除參訓老師',
-        td200:'是否確認移除',
-        td201:'研習名單',
-        td202:'添加成功',
-        td203:'保存研習名單失敗',
-        td204:'查詢研習名單失敗'
+    td: {
+        td1: '研習統計',
+        td2: '學時統計',
+        td3: '總學時:',
+        td4: '分鐘',
+        td5: '學時',
+        td6: '未開始:',
+        td7: '進行中:',
+        td8: '已完成:',
+        td9: '合格率',
+        td10: '學校概覽',
+        td11: '學校列表',
+        td12: '導出學校數據',
+        td13: '導出教師數據',
+        td14: '搜索學校',
+        td15: '參訓人數',
+        td16: '詳情>>>',
+        td17: '未搜索到學校',
+        td18: '暫無學校數據',
+        td19: '學校數量',
+        td20: '總學時',
+        td21: '合格人數',
+        td22: '線上研習',
+        td23: '校本研習',
+        td24: '認證材料',
+        td25: '課堂實錄',
+        td26: '未修滿',
+        td27: '增能項目',
+        td28: '學校',
+        td29: '姓名',
+        td30: '線上研習學時',
+        td31: '所選增能項目',
+        td32: '已修滿的增能項目數量',
+        td33: '認證材料學時',
+        td34: '校本研習學時',
+        td35: '課堂實錄學時',
+        td36: '認證材料需提交數',
+        td37: '已提交認證材料數',
+        td38: '已提交認證材料增能項目',
+        td39: '未提交認證材料數',
+        td40: '未提交認證材料增能項目',
+        td41: '作業未提交數',
+        td42: '課堂實錄是否提交',
+        td43: '已提交',
+        td44: '未提交',
+        td45: '研習情況統計表',
+        td46: '未開始人數',
+        td47: '進行中人數',
+        td48: '已完成人數',
+        td49: '參訓總人數',
+        td50: '學校數據統計',
+        td51: '資源列表',
+        td52: '新增資源',
+        td53: '完成率:',
+        td54: '返回區級',
+        td55: '所有學校',
+        td56: '共建',
+        td57: '個試點校,參訓人數',
+        td58: '重新上傳',
+        td59: '主題',
+        td60: '時間',
+        td61: '地點',
+        td62: '描述',
+        td63: '請選擇作業附件上傳類型',
+        td64: '簽到成功',
+        td65: '數據概覽',
+        td66: '的',
+        td67: '查詢簽到數據失敗',
+        td68: '獲取作業提交數據失敗',
+        td69: '合格率統計',
+        td70: '能力維度選修占比',
+        td71: '增能項目選修占比',
+        td72: '研習小組統計',
+        td73: '暫無小組數據',
+        td74: '未分組',
+        td75: '查看成員',
+        td76: '完成線上研習',
+        td77: '完成認證材料',
+        td78: '完成校本研習',
+        td79: '完成課堂記錄',
+        td80: '全部完成',
+        td81: '完成率',
+        td82: '優秀',
+        td83: '合格',
+        td84: '不合格',
+        td85: '獲取統計數據失敗',
+        td86: '數據總覽',
+        td87: '詳細數據',
+        td88: '搜索',
+        td89: '數據導出',
+        td90: '未完成',
+        td91: '已完成',
+        td92: '教師姓名',
+        td93: '小組',
+        td94: '完成狀態',
+        td95: '姓名',
+        td96: '組別',
+        td97: '獲取統計數據失敗',
+        td98: '根據省平臺要求,教師必須滿足以下條件才可獲得校本研習活動學時:',
+        td99: '1、10學時中至少有一次需提交作業的校本研習活動',
+        td100: '2、在活動中成功提交PDF作業',
+        td101: '提交方式',
+        td102: '所有老師提交',
+        td103: '由組長統一提交',
+        td104: '請設定作業類型',
+        td105: '請設定提交方式',
+        td106: '未分組老師',
+        td107: '建立研習問卷失敗',
+        td108: '建立研習評量失敗',
+        td109: '輸入手機號',
+        td110: '未查詢到對應賬號!請檢查後重試!',
+        td111: '已簽到成功,請勿重複操作!',
+        td112: '請輸入正確手機號碼!',
+        td113: '簽到失敗,請重新簽到',
+        td114: '簽到成功',
+        td115: '簽到失敗',
+        td116: '溫馨提示:區級活動不計入校本研習學時',
+        td117: '未發布',
+        td118: '進行中',
+        td119: '已結束',
+        td120: '活動影片:',
+        td121: '播放',
+        td122: '刪除',
+        td123: '上傳',
+        td124: '(影片只能上傳一個)',
+        td125: '活動資料:',
+        td126: '繼續上傳',
+        td127: '(資料可以上傳多份)',
+        td128: '根據省平臺要求,教師必須滿足以下條件才可獲得校本研習活動學時: 1、10學時中至少有一次需提交作業的校本研習活動 2、在活動中成功提交PDF作業',
+        td129: '批量合格',
+        td130: '請選擇學校老師參加並發布活動',
+        td131: '選擇老師',
+        td132: '繼續挑選(已選',
+        td133: '位)',
+        td134: '發布活動',
+        td135: '上傳中',
+        td136: '上傳完成',
+        td137: '新增教師',
+        td138: '教研組',
+        td139: '教研組篩選',
+        td140: '未設定',
+        td141: '查詢教研組失敗',
+        td142: '請勾選參加活動的老師',
+        td143: '刪除文件',
+        td144: '是否確認刪除',
+        td145: '刪除成功',
+        td146: '刪除失敗',
+        td147: '文件上傳中,請等待文件上傳完成',
+        td148: '活動影片只支持mp4文件格式',
+        td149: '學校空間已滿',
+        td150: '上傳失敗',
+        td151: '請選擇需要批量處理',
+        td152: '合格',
+        td153: '不合格',
+        td154: '的老師',
+        td155: '批量處理',
+        td156: '確認將所選老師全部設定為合格嗎?',
+        td157: '問卷作答數據獲取失敗',
+        td158: '獲取作業提交數據失敗',
+        td159: '獲取名單列表失敗',
+        td160: '獲取簽到數據失敗',
+        td161: '學校',
+        td162: '查詢教師列表失敗',
+        td163: '對象:',
+        td164: '暫無',
+        td165: '查詢研習列表失敗',
+        td166: '人數:',
+        td167: '(已同步省平臺名單)',
+        td168: '溫馨提示:空白分組(分組內沒有新增教師)不會被儲存。',
+        td169: '儲存分組',
+        td170: '分組視圖',
+        td171: '列表視圖',
+        td172: '移除教師',
+        td173: '新增教師',
+        td174: '組長',
+        td175: '組員',
+        td176: '已綁定',
+        td177: '未綁定',
+        td178: '新增成員',
+        td179: '設為組長',
+        td180: '取消組長',
+        td181: '身份',
+        td182: '狀態',
+        td183: '設定成功',
+        td184: '設定失敗',
+        td185: '刪除組別',
+        td186: '刪除組別後,當前組的老師將默認被分配到相鄰組別,確認刪除嗎?',
+        td187: '確認刪除所有分組嗎?',
+        td188: '請設定所有組名',
+        td189: '儲存成功',
+        td190: '儲存失敗',
+        td191: '請輸入組名再新增組別',
+        td192: '組名重複',
+        td193: '請選擇需要移除的老師',
+        td194: '批量移除',
+        td195: '確認批量移除',
+        td196: '個參訓老師嗎?',
+        td197: '移除成功',
+        td198: '移除失敗',
+        td199: '移除參訓老師',
+        td200: '是否確認移除',
+        td201: '研習名單',
+        td202: '新增成功',
+        td203: '儲存研習名單失敗',
+        td204: '查詢研習名單失敗',
+        td205: '數據更新中,當前數據更新於',
+        td206: ',如需查看最新數據請稍後。',
+        td207: '當前已是最新數據,更新於'
     },
     // 单位管理
     unit: {

+ 102 - 11
TEAMModelOS/ClientApp/src/components/evaluation/ExerciseList.less

@@ -1,18 +1,21 @@
 .ev-cp-list-container {
   user-select: none !important;
   position: relative;
+
   .ev-header {
     background: #fff;
     padding: 10px;
     display: flex;
     align-items: center;
   }
+
   .ev-title {
     font-size: 20px;
     font-weight: bold;
     margin-left: 5px;
     vertical-align: middle;
   }
+
   .ev-length {
     font-size: 12px;
     font-weight: bold;
@@ -21,9 +24,11 @@
     margin-top: 5px;
     vertical-align: text-top;
   }
+
   .ivu-divider-horizontal {
     margin: 15px 0;
   }
+
   .no-data-text {
     width: 100%;
     padding: 30px;
@@ -34,8 +39,9 @@
     align-items: center;
     margin-top: 10px;
     font-size: 16px;
-	min-height: 55vh;
+    min-height: 55vh;
   }
+
   .ivu-page {
     display: flex;
     flex-direction: row;
@@ -48,6 +54,7 @@
     padding: 10px;
   }
 }
+
 .ev-list-operation {
   position: absolute;
   top: -65px;
@@ -57,31 +64,38 @@
   flex-direction: row;
   align-items: center;
   justify-content: space-between;
+
   .ivu-checkbox-wrapper {
     font-size: 14px;
   }
+
   .ivu-checkbox {
     margin: 10px;
   }
+
   .import-exercise {
     font-weight: bold;
     color: rgb(16, 171, 231);
     font-size: 16px;
     display: flex;
+
     .ivu-btn {
       margin-right: 10px;
       border: none !important;
     }
   }
+
   .ivu-icon {
     font-size: 16px;
     margin-right: 6px;
     cursor: pointer;
     vertical-align: initial;
   }
+
   .ivu-badge-count {
     right: 12px;
   }
+
   .ivu-checkbox-checked {
     .ivu-checkbox-inner {
       background: #01b4ef;
@@ -89,15 +103,18 @@
     }
   }
 }
+
 .exercise-backet-wrap {
   .ivu-btn {
     border: none !important;
   }
+
   .exercise-backet-item {
     &:not(:first-child) {
       margin-left: 10px;
     }
   }
+
   .exercise-backet-num {
     font-weight: bold;
     margin: 0 5px;
@@ -105,9 +122,11 @@
     color: rgb(16, 171, 231);
   }
 }
+
 .ev-content {
   background: none;
 }
+
 .cp-content-wrap {
   position: relative;
   width: 100%;
@@ -115,6 +134,7 @@
   display: flex;
   flex-direction: column;
   padding: 15px;
+
   .cp-exercise-item {
     position: relative;
     width: 100%;
@@ -125,6 +145,7 @@
     background: #fff;
     border: 2px solid #7e6c6c0f;
     cursor: pointer;
+
     &:hover {
       .item-tools-bind {
         display: unset;
@@ -132,45 +153,60 @@
     }
   }
 }
-.cp-content-wrap .cp-exercise-item table, .cp-content-wrap .cp-exercise-item td {
+
+.cp-content-wrap .cp-exercise-item table,
+.cp-content-wrap .cp-exercise-item td {
   border: 1px solid rgb(128, 128, 128);
   border-collapse: collapse;
   text-align: center;
   padding: 5px 10px;
 }
+
 .complete-line {
   margin: 0 5px;
   padding: 0 45px;
   border-bottom: 2px solid rgb(128, 128, 128);
 }
+
 .cp-exercise-item {
-	color: #565656;
+  color: #565656;
+
   .item-question {
     position: relative;
     cursor: pointer;
+
     .item-question-order {
       display: inline-block;
       vertical-align: top;
       width: 30px;
     }
+
     .item-question-text {
       display: inline-block;
       width: calc(90% - 30px);
     }
   }
+
   img {
     vertical-align: middle;
     max-width: 100%;
   }
+
+  video {
+    max-width: 100%;
+  }
+
   .item-btn-toggle {
     position: absolute;
     right: 20px;
     top: 8px;
+
     .ivu-icon {
       font-size: 22px;
       cursor: pointer;
     }
   }
+
   .item-difficulty {
     display: inline-block;
     padding: 2px 10px;
@@ -179,6 +215,7 @@
     color: #fff;
     font-size: 12px;
   }
+
   .item-type {
     display: inline-block;
     padding: 1px 9px;
@@ -188,69 +225,85 @@
     margin-left: 5px;
     background: rgb(16, 171, 231);
   }
+
   .item-relevant-points {
     display: inline-block;
     padding: 1px 9px;
     font-size: 13px;
   }
+
   .item-options {
     margin-top: 10px;
+
     .item-option-content {
       margin: 7px 0;
     }
+
     .item-option-order {
       display: inline-block;
       vertical-align: top;
       width: 30px;
     }
+
     .item-option-text {
       display: inline-block;
       width: calc(100% - 30px);
     }
   }
+
   .toggle-area {
     border-top: 1px #c3c3c34d dashed;
     padding-top: 10px;
     margin-top: 10px;
   }
+
   .item-answer {
     display: inline-block;
     cursor: pointer;
     margin-top: 12px;
     font-size: 14px;
+
     .answer-title-line {
       background: rgb(0, 173, 37);
       padding: 0 3px;
       border-radius: 5px;
     }
+
     .answer-title {
       margin-left: 10px;
       color: rgb(0, 173, 37);
     }
   }
+
   .item-answer-item {
     margin-left: 25px;
     padding: 0 25px;
     border-bottom: 2px solid rgb(128, 128, 128);
+
     p {
       display: inline-block;
     }
+
     &:first-child {
       margin-left: 0;
     }
   }
+
   .item-answer-details {
     margin: 10px 20px;
   }
+
   .item-explain {
     margin-top: 10px;
     cursor: pointer;
     font-size: 14px;
+
     .explain-title-line {
       background: rgb(16, 171, 231);
       padding: 0 3px;
       border-radius: 5px;
     }
+
     .explain-title {
       width: 12%;
       max-width: 85px;
@@ -258,37 +311,44 @@
       color: rgb(16, 171, 231);
     }
   }
+
   .repair-item {
-  	display: inline-block;
-  	margin-right: 10px;
-  	color: #21b1ff;
-  	text-decoration: underline;
+    display: inline-block;
+    margin-right: 10px;
+    color: #21b1ff;
+    text-decoration: underline;
   }
+
   .item-explain-item {
     margin-left: 25px;
     padding: 0 25px;
     border-bottom: 2px solid rgb(128, 128, 128);
   }
+
   .item-explain-details {
     vertical-align: top;
     display: inline-block;
     width: calc(100% - 90px);
+
     .item-point-tag {
       padding: 0 10px;
       border: 1px solid #d6d6d6;
       margin-left: 10px;
       border-radius: 4px;
+
       &:first-child {
         margin-left: 0;
       }
     }
   }
+
   .item-tools {
     width: 100%;
     padding: 10px 0;
     margin-top: 20px;
     font-size: 14px;
     border-top: 1px #c3c3c34d dashed;
+
     .item-tools-action {
       float: right;
       color: #01b4ef;
@@ -298,79 +358,102 @@
       display: flex;
       align-items: center;
       cursor: pointer;
+
       .ivu-icon {
         font-size: 18px;
       }
     }
+
     .ivu-icon {
       font-size: 16px;
       margin-right: 5px;
       font-weight: bold;
     }
+
     .ivu-btn {
       float: right;
       border-color: transparent;
       box-shadow: none;
     }
+
     .item-tools-info {
       vertical-align: sub;
       color: #868686;
       border-right: 2px solid #d2d2d2;
       font-size: 12px;
       padding: 0 10px;
+
       &:first-child {
         padding-left: 0;
       }
     }
+
     span {
       &:nth-child(2) {
         border-right-width: 0;
       }
     }
   }
+
   .item-tools-tool {
     margin-left: 10px;
     font-weight: bold;
     cursor: pointer;
     color: rgb(16, 171, 231);
     font-size: 14px;
+
     .ivu-icon {
       margin-left: 15px;
       vertical-align: top;
     }
+
     .item-bind-point {
       color: rgb(128, 128, 128);
       margin-left: 5px;
     }
+
     .ivu-tag {
       margin-top: -2px;
     }
+
     .ivu-tag-border {
       line-height: 22px;
     }
   }
 }
-.ev-list-container h1, h2, h3, h4, h5, h6 {
+
+.ev-list-container h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
   display: inline-block;
 }
+
 .filter-wrap {
   width: 100%;
   padding: 20px;
   background: #fff;
+
   .filter-item {
     margin-top: 10px;
+
     &:first-child {
       margin-top: 0px;
     }
   }
+
   .filter-title {
     font-size: 16px;
     font-weight: bold;
     margin-right: 10px;
   }
+
   .ivu-radio-group {
     padding-bottom: 4px;
   }
+
   .ivu-radio-wrapper {
     padding: 0 10px;
     margin-left: 15px;
@@ -380,18 +463,22 @@
     border: none !important;
     font-size: 14px;
     border-radius: 0 !important;
+
     .ivu-icon {
       margin-bottom: 2px;
     }
   }
+
   .ivu-radio-group-item {
     border-radius: 5px !important;
   }
+
   .ivu-radio-wrapper-checked {
     background: rgb(16, 171, 231);
     box-shadow: none !important;
     color: white;
   }
+
   .ivu-radio-group-button {
     .ivu-radio-wrapper-checked {
       &:hover {
@@ -399,10 +486,12 @@
       }
     }
   }
+
   .ivu-checkbox-group {
     padding-bottom: 4px;
     display: inline-block;
   }
+
   .ivu-checkbox-wrapper {
     padding: 0 10px;
     margin-left: 15px;
@@ -412,18 +501,22 @@
     border: none !important;
     font-size: 14px;
     border-radius: 0 !important;
+
     .ivu-icon {
       margin-bottom: 2px;
     }
   }
+
   .ivu-checkbox-group-item {
     border-radius: 5px !important;
   }
+
   .ivu-checkbox-wrapper-checked {
     background: rgb(16, 171, 231);
     box-shadow: none !important;
     color: white;
   }
+
   .ivu-checkbox-group-button {
     .ivu-checkbox-wrapper-checked {
       &:hover {
@@ -431,6 +524,4 @@
       }
     }
   }
-}
-
-
+}

File diff suppressed because it is too large
+ 453 - 453
TEAMModelOS/ClientApp/src/view/Home.vue


+ 9 - 0
TEAMModelOS/ClientApp/src/view/areaMgmt/AreaData.vue

@@ -2,6 +2,8 @@
     <div class="area-data-container">
         <Loading v-show="isLoading"></Loading>
         <vuescroll>
+            <Alert show-icon v-if="isnew" style="width:calc(100% - 40px);margin-left:20px;margin-bottom:15px" closable type="success">{{`${$t('td.td207')}${$jsFn.timeFormat(updateTime)}`}}</Alert>
+            <Alert show-icon v-else style="width:calc(100% - 40px);margin-left:20px;margin-bottom:15px" closable type="warning">{{`${$t('td.td205')}${$jsFn.timeFormat(updateTime)}${$t('td.td206')}`}}</Alert>
             <!-- 头部统计 -->
             <div class="top-block-wrap">
                 <div class="content-con-item border-style" v-for="(item,index) in topData" :key="index">
@@ -148,6 +150,8 @@ export default {
     data() {
         const _this = this
         return {
+            isnew: true,
+            updateTime: 0,
             settingHours: {},
             onlineTime: 20,
             offlineTime: 10,
@@ -434,6 +438,8 @@ export default {
             this.$api.ability.getAreaDataSimple(params).then(
                 res => {
                     if (!res.error) {
+                        this.isnew = res.isnew
+                        this.updateTime = res.updateTime
                         this.settingHours = res.setting || {}
                         //设置的学时
                         this.onlineTime = res.setting.onlineTime || this.onlineTime
@@ -581,6 +587,9 @@ export default {
         this.defImg = require('@/assets/image/def-school-img.png')
         this.schoolInfo = {}
         this.trainType = this.$GLOBAL.TRAIN_TYPE()
+        this.$Notice.config({
+            top: 50
+        })
         this.getAreaData()
     },
     mounted() {

+ 0 - 2
TEAMModelOS/ClientApp/src/view/dashboard/StudentAll.less

@@ -143,8 +143,6 @@
         }
     }
 
-
-
     .tools {
         position: absolute;
         right: 30px;

+ 1 - 0
TEAMModelOS/ClientApp/src/view/dashboard/StudentAll.vue

@@ -17,6 +17,7 @@
           <dv-decoration-10 class="dv-dec-10" />
           <div class="d-flex jc-center">
             <dv-decoration-8 class="dv-dec-8" :color="['#568aea', '#000000']" />
+            <!-- <img src="https://ydzt.cdwalker.com/health/static/img/header.d55c582c.png" alt="" style="position:absolute;left:0;top:-20px;"> -->
             <div class="title">
               <span class="title-text">学生大数据画像看板</span>
               <dv-decoration-6 class="dv-dec-6" :reverse="true" :color="['#50e3c2', '#67a1e5']" />

+ 193 - 67
TEAMModelOS/ClientApp/src/view/evaluation/index/CommonExercise.less

@@ -1,17 +1,20 @@
 .ev-list-container {
   position: relative;
+
   .ev-header {
     background: #fff;
     padding: 10px;
     display: flex;
     align-items: center;
   }
+
   .ev-title {
     font-size: 20px;
     font-weight: bold;
     margin-left: 5px;
     vertical-align: middle;
   }
+
   .ev-length {
     font-size: 12px;
     font-weight: bold;
@@ -20,9 +23,11 @@
     margin-top: 5px;
     vertical-align: text-top;
   }
+
   .ivu-divider-horizontal {
     margin: 15px 0;
   }
+
   .no-data-text {
     width: 100%;
     padding: 30px;
@@ -34,6 +39,7 @@
     margin-top: 10px;
     font-size: 16px;
   }
+
   .ivu-page {
     display: flex;
     flex-direction: row;
@@ -41,6 +47,7 @@
     margin: 20px 0;
   }
 }
+
 .ev-list-operation {
   position: absolute;
   top: -65px;
@@ -50,31 +57,38 @@
   flex-direction: row;
   align-items: center;
   justify-content: space-between;
+
   .ivu-checkbox-wrapper {
     font-size: 14px;
   }
+
   .ivu-checkbox {
     margin: 10px;
   }
+
   .import-exercise {
     font-weight: bold;
     color: rgb(16, 171, 231);
     font-size: 16px;
     display: flex;
+
     .ivu-btn {
       margin-right: 10px;
       border: none !important;
     }
   }
+
   .ivu-icon {
     font-size: 16px;
     margin-right: 6px;
     cursor: pointer;
     vertical-align: initial;
   }
+
   .ivu-badge-count {
     right: 12px;
   }
+
   .ivu-checkbox-checked {
     .ivu-checkbox-inner {
       background: #01b4ef;
@@ -82,15 +96,18 @@
     }
   }
 }
+
 .exercise-backet-wrap {
   .ivu-btn {
     border: none !important;
   }
+
   .exercise-backet-item {
     &:not(:first-child) {
       margin-left: 10px;
     }
   }
+
   .exercise-backet-num {
     font-weight: bold;
     margin: 0 5px;
@@ -98,15 +115,18 @@
     color: rgb(16, 171, 231);
   }
 }
+
 .ev-content {
   background: none;
 }
+
 .content-wrap {
   position: relative;
   width: 100%;
   height: auto;
   display: flex;
   flex-direction: column;
+
   .exercise-item {
     position: relative;
     width: 100%;
@@ -117,6 +137,7 @@
     background: #fff;
     border: 2px solid transparent;
     cursor: pointer;
+
     &:hover {
       .item-tools-bind {
         display: unset;
@@ -124,51 +145,67 @@
     }
   }
 }
-.content-wrap .exercise-item table, .content-wrap .exercise-item td {
+
+.content-wrap .exercise-item table,
+.content-wrap .exercise-item td {
   border: 1px solid rgb(128, 128, 128);
   border-collapse: collapse;
   text-align: center;
   padding: 5px 10px;
 }
+
 .complete-line {
   margin: 0 5px;
   padding: 0 45px;
   border-bottom: 2px solid rgb(128, 128, 128);
 }
+
 .exercise-item {
   .item-question {
     position: relative;
     cursor: pointer;
+
     .item-question-order {
       display: inline-block;
       vertical-align: top;
       width: 30px;
     }
+
     .item-question-text {
       display: inline-block;
       width: calc(90% - 30px);
     }
   }
+
   img {
     vertical-align: middle;
-	max-width: 100%;
+    max-width: 100%;
   }
+
+  video {
+    max-width: 100%;
+  }
+
   .item-btn-toggle {
     position: absolute;
     right: 10px;
     top: 8px;
-	width: 15%;
-	display: flex;
-	justify-content: center;
-	align-items: center;
+    width: 15%;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+
     .ivu-icon {
       font-size: 22px;
       cursor: pointer;
     }
-	.ivu-input-number-handler-down-inner,.ivu-input-number-handler-up-inner{
-		width: 17px;
-	}
+
+    .ivu-input-number-handler-down-inner,
+    .ivu-input-number-handler-up-inner {
+      width: 17px;
+    }
   }
+
   .item-difficulty {
     display: inline-block;
     padding: 2px 10px;
@@ -177,6 +214,7 @@
     color: #fff;
     font-size: 12px;
   }
+
   .item-type {
     display: inline-block;
     padding: 1px 9px;
@@ -186,69 +224,85 @@
     margin-left: 5px;
     background: rgb(16, 171, 231);
   }
+
   .item-relevant-points {
     display: inline-block;
     padding: 1px 9px;
     font-size: 13px;
   }
+
   .item-options {
     margin-top: 10px;
+
     .item-option-content {
       margin: 7px 0;
     }
+
     .item-option-order {
       display: inline-block;
       vertical-align: top;
       width: 30px;
     }
+
     .item-option-text {
       display: inline-block;
       width: calc(100% - 30px);
     }
   }
+
   .toggle-area {
     border-top: 1px #c3c3c34d dashed;
     padding-top: 10px;
     margin-top: 10px;
   }
+
   .item-answer {
     display: inline-block;
     cursor: pointer;
     margin-top: 12px;
     font-size: 14px;
+
     .answer-title-line {
       background: rgb(0, 173, 37);
       padding: 0 3px;
       border-radius: 5px;
     }
+
     .answer-title {
       margin-left: 10px;
       color: rgb(0, 173, 37);
     }
   }
+
   .item-answer-item {
     margin-left: 25px;
     padding: 0 25px;
     border-bottom: 2px solid rgb(128, 128, 128);
+
     p {
       display: inline-block;
     }
+
     &:first-child {
       margin-left: 0;
     }
   }
+
   .item-answer-details {
     margin: 10px 20px;
   }
+
   .item-explain {
     margin-top: 10px;
     cursor: pointer;
     font-size: 14px;
+
     .explain-title-line {
       background: rgb(16, 171, 231);
       padding: 0 3px;
       border-radius: 5px;
     }
+
     .explain-title {
       width: 12%;
       max-width: 100px;
@@ -256,45 +310,51 @@
       color: rgb(16, 171, 231);
     }
   }
-  
+
   .repair-item {
-  	display: inline-flex;
-	margin-right: 20px;
-	color: #21b1ff;
-	text-decoration: underline;
-	align-items: flex-end;
-	
-	&-link{
-		margin-left: 5px;
-	}
-	
+    display: inline-flex;
+    margin-right: 20px;
+    color: #21b1ff;
+    text-decoration: underline;
+    align-items: flex-end;
+
+    &-link {
+      margin-left: 5px;
+    }
+
   }
+
   .item-explain-item {
     margin-left: 25px;
     padding: 0 25px;
     border-bottom: 2px solid rgb(128, 128, 128);
   }
+
   .item-explain-details {
     vertical-align: top;
     display: inline-block;
     width: calc(100% - 100px);
+
     // width: 90%;
     .item-point-tag {
       padding: 0 10px;
       border: 1px solid #d6d6d6;
       margin-left: 10px;
       border-radius: 4px;
+
       &:first-child {
         margin-left: 0;
       }
     }
   }
+
   .item-tools {
     width: 100%;
     padding: 10px 0;
     margin-top: 20px;
     font-size: 14px;
     border-top: 1px #c3c3c34d dashed;
+
     .item-tools-action {
       float: right;
       color: #01b4ef;
@@ -304,87 +364,110 @@
       display: flex;
       align-items: center;
       cursor: pointer;
+
       .ivu-icon {
         font-size: 18px;
       }
     }
+
     .ivu-icon {
-	  font-size: 14px;
+      font-size: 14px;
       font-weight: bold;
     }
+
     .ivu-btn {
       float: right;
       border-color: transparent;
       box-shadow: none;
     }
+
     .item-tools-info {
       vertical-align: sub;
       color: #868686;
       border-right: 2px solid #d2d2d2;
       font-size: 12px;
       padding: 0 10px;
+
       &:first-child {
         padding-left: 0;
       }
     }
+
     span {
       &:nth-child(4) {
         border-right-width: 0;
       }
     }
   }
+
   .item-tools-tool {
     margin-left: 10px;
     font-weight: bold;
     cursor: pointer;
     color: rgb(16, 171, 231);
     font-size: 14px;
+
     .ivu-icon {
       margin-left: 15px;
       vertical-align: top;
     }
+
     .item-bind-point {
       color: rgb(128, 128, 128);
       margin-left: 5px;
     }
+
     .ivu-tag {
       margin-top: -2px;
     }
+
     .ivu-tag-border {
       line-height: 22px;
     }
   }
 }
-.ev-list-container h1, h2, h3, h4, h5, h6 {
+
+.ev-list-container h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
   display: inline-block;
 }
+
 .filter-wrap {
   width: 100%;
   padding: 10px 20px;
   padding-bottom: 20px;
   background: #fff;
+
   .filter-item {
     margin-top: 10px;
-	display: flex;
+    display: flex;
+
     &:first-child {
       margin-top: 0px;
     }
-	
-	.filter-count{
-		color: red;
-	}
+
+    .filter-count {
+      color: red;
+    }
   }
+
   .filter-title {
     font-size: 16px;
     font-weight: bold;
     margin-right: 10px;
-	min-width: 45px;
-	// display: inline-block;
-	// text-align: end;
+    min-width: 45px;
+    // display: inline-block;
+    // text-align: end;
   }
+
   .ivu-radio-group {
     padding-bottom: 4px;
   }
+
   .ivu-radio-wrapper {
     padding: 0 10px;
     margin-left: 15px;
@@ -394,21 +477,26 @@
     border: none !important;
     font-size: 14px;
     border-radius: 0 !important;
+
     .ivu-icon {
       margin-bottom: 2px;
     }
   }
+
   .ivu-radio-group-item {
     border-radius: 5px !important;
   }
+
   .ivu-radio-wrapper-checked {
     background: rgb(16, 171, 231);
     box-shadow: none !important;
     color: white;
-	.filter-count{
-		color: #fff;
-	}
+
+    .filter-count {
+      color: #fff;
+    }
   }
+
   .ivu-radio-group-button {
     .ivu-radio-wrapper-checked {
       &:hover {
@@ -416,10 +504,12 @@
       }
     }
   }
+
   .ivu-checkbox-group {
     padding-bottom: 4px;
     display: inline-block;
   }
+
   .ivu-checkbox-wrapper {
     padding: 0 10px;
     margin-left: 15px;
@@ -429,21 +519,26 @@
     border: none !important;
     font-size: 14px;
     border-radius: 0 !important;
+
     .ivu-icon {
       margin-bottom: 2px;
     }
   }
+
   .ivu-checkbox-group-item {
     border-radius: 5px !important;
   }
+
   .ivu-checkbox-wrapper-checked {
     background: rgb(16, 171, 231);
     box-shadow: none !important;
     color: white;
-	.filter-count{
-		color: #fff;
-	}
+
+    .filter-count {
+      color: #fff;
+    }
   }
+
   .ivu-checkbox-group-button {
     .ivu-checkbox-wrapper-checked {
       &:hover {
@@ -452,41 +547,49 @@
     }
   }
 }
-.filter-wrap .ivu-radio-wrapper:after, .ivu-radio-group-button .ivu-radio-wrapper:before {
+
+.filter-wrap .ivu-radio-wrapper:after,
+.ivu-radio-group-button .ivu-radio-wrapper:before {
   content: none;
 }
+
 .filter-wrap .ivu-checkbox-inner,
-    .filter-wrap .ivu-checkbox-checked,
-    .filter-wrap .ivu-checkbox {
+.filter-wrap .ivu-checkbox-checked,
+.filter-wrap .ivu-checkbox {
   display: none;
 }
-.filter-wrap .ivu-checkbox-wrapper:after, .ivu-checkbox-group-button .ivu-checkbox-wrapper:before {
+
+.filter-wrap .ivu-checkbox-wrapper:after,
+.ivu-checkbox-group-button .ivu-checkbox-wrapper:before {
   content: none;
 }
 
-.bank-action-bar{
-	background-color: #fff;
-	padding: 15px 15px;
-	margin: 10px 0;
-	display: flex;
-	align-items: center;
-	justify-content: space-between;
-	
-	.action-tools{
-		display: flex;
-		.action-tool{
-			display: flex;
-			align-items: center;
-			margin-right: 15px;
-			a{
-				color: #333333;
-			}
-			.action-title{
-				display: inline-block;
-				min-width: 50px;
-			}
-		}
-	}
+.bank-action-bar {
+  background-color: #fff;
+  padding: 15px 15px;
+  margin: 10px 0;
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+
+  .action-tools {
+    display: flex;
+
+    .action-tool {
+      display: flex;
+      align-items: center;
+      margin-right: 15px;
+
+      a {
+        color: #333333;
+      }
+
+      .action-title {
+        display: inline-block;
+        min-width: 50px;
+      }
+    }
+  }
 }
 
 /*绑定知识点部分树形结构样式*/
@@ -495,27 +598,33 @@
   font-size: 14px;
   margin: 10px;
 }
+
 .transferModal {
   overflow: hidden;
+
   .point-list {
     max-height: 400px;
     overflow: auto;
+
     .ivu-input-wrapper {
       width: 90%;
       margin-bottom: 10px;
     }
   }
+
   .selected-point-list {
     padding: 10px;
     width: 100%;
-    border-top: 1px solid rgba(128, 128, 128,.3);
+    border-top: 1px solid rgba(128, 128, 128, .3);
     margin-top: 15px;
   }
+
   .bind-title {
     margin: 10px 0;
     font-weight: bold;
     font-size: 14px;
   }
+
   .checked-point {
     margin: 5px 10px;
     background: rgb(16, 171, 231);
@@ -524,15 +633,18 @@
     border-radius: 5px;
     display: inline-block;
   }
+
   .ivu-checkbox-checked {
     .ivu-checkbox-inner {
       background: rgb(16, 171, 231);
       border-color: rgb(16, 171, 231);
     }
   }
+
   .ivu-icon {
     color: rgb(16, 171, 231);
   }
+
   .btn-clear {
     float: right;
     font-weight: 500;
@@ -541,6 +653,7 @@
     cursor: pointer;
     letter-spacing: 1px;
   }
+
   .point-checkbox {
     margin-left: 10px;
     border-radius: 2px;
@@ -551,26 +664,31 @@
     box-sizing: border-box;
     border: 1px solid #dcdee2;
   }
+
   .point-checked {
     background: rgb(16, 171, 231);
     background-clip: content-box;
   }
+
   .ivu-tabs-nav-scroll {
     display: flex;
     flex-direction: row;
     justify-content: center;
   }
+
   .ivu-tree-empty {
     text-align: center;
     margin: 15px;
     color: rgb(128, 128, 128);
   }
 }
+
 .point-list {
   &::-webkit-scrollbar {
     width: 5px;
     height: 1px;
   }
+
   &:hover {
     .ztree_box {
       &::-webkit-scrollbar {
@@ -578,20 +696,24 @@
       }
     }
   }
+
   &::-webkit-scrollbar-thumb {
     border-radius: 10px;
-    box-shadow: inset 0 0 5px rgba(0,0,0,0.2);
+    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.2);
     background: #70707026;
   }
+
   &::-webkit-scrollbar-track {
     background: #f4f4f400;
   }
 }
+
 .shop {
   position: fixed;
   top: 300px;
   left: 400px;
 }
+
 .ball {
   position: fixed;
   right: 128px;
@@ -599,16 +721,19 @@
   z-index: 200;
   transition: all 0.4s cubic-bezier(0.49, -0.29, 0.75, 0.41);
 }
+
 .inner {
   width: 16px;
   height: 16px;
   border-radius: 50%;
   transition: all 0.4s linear;
+
   img {
     width: 26px;
     height: 26px;
   }
 }
+
 .cart {
   position: fixed;
   bottom: 22px;
@@ -618,6 +743,7 @@
   background-color: rgb(0, 160, 220);
   color: rgb(255, 255, 255);
 }
-.hevue-imgpreview-wrap{
-	z-index: 1999;
+
+.hevue-imgpreview-wrap {
+  z-index: 1999;
 }

+ 14 - 7
TEAMModelOS/ClientApp/src/view/jyzx/index.vue

@@ -8,7 +8,7 @@
                         {{ $t('jyzx.online.checkedPoint') }}
                         <span style="margin-right: 10px">({{ $t("jyzx.online.studyTime") }}:{{ totalShow }})</span>
                         <Checkbox v-model="single" v-if="hasAbilityAuth">{{ $t("jyzx.online.fromArea") }}</Checkbox>
-                        <Tooltip placement="right-start" max-width="200">
+                        <Tooltip :placement="lang === 'en-us' ? 'bottom' : 'right-start'" max-width="200">
                             <Icon type="ios-alert-outline" />
                             <div slot="content">
                                 <p>{{ $t("jyzx.online.abilyMes") }}</p>
@@ -166,7 +166,7 @@
                     {{ $t('jyzx.online.study') }}<span>{{ studyTim }}</span>/{{ setting.onlineTime }}{{ $t('jyzx.online.time') }}
                 </p>
                 <Select v-model="selDimen" style="width: 200px; margin-right: 10px" label-in-value @on-change="selAllPoint">
-                    <Option v-for="(item, index) in dimension" :value="item.code" :key="index">{{ item.val }}</Option>
+                    <Option v-for="(item, index) in dimension" :value="item.code" :key="index">{{ item.name }}</Option>
                 </Select>
                 <Select v-model="selEnvi" style="width: 200px" label-in-value @on-change="selAllPoint">
                     <Option v-for="(item, index) in environment" :value="item" :key="index">{{ item }}</Option>
@@ -260,15 +260,15 @@ export default {
             dimension: [
                 {
                     code: 0,
-                    val: this.$t('jyzx.online.allDimension'),
+                    name: this.$t('jyzx.online.allDimension'),
                 },
             ], //维度
             selDimen: 0, //选择的维度
             environment: [
                 this.$t('jyzx.online.allEnvir'),
-                this.$t('jyzx.online.envirMix'),
+               /*  this.$t('jyzx.online.envirMix'),
                 this.$t('jyzx.online.multiMedia'),
-                this.$t('jyzx.online.studyEnvir'),
+                this.$t('jyzx.online.studyEnvir'), */
             ], //环境
             selEnvi: this.$t('jyzx.online.allEnvir'), //选择的环境
             abliltyId: undefined, //能力点id
@@ -303,6 +303,7 @@ export default {
                 nodeId: 0
             },
             totalShow: 0,
+            lang: localStorage.getItem('local'),
         };
     },
     created() {
@@ -544,6 +545,11 @@ export default {
                     } else {
                         this.studyTim = res.teacherTrain.onlineTime;
                     }
+                    if(res.setting.dimensions.length) {
+                        res.setting.dimensions.map(item => {
+                            this.dimension.push(item);
+                        })
+                    }
                     this.getAbility()
                 }
             });
@@ -827,9 +833,9 @@ export default {
         // 获取所有能力点
         async getAllpoint() {
             let dimenArr = await this.$GLOBAL.DIMENSIONS();
-            dimenArr.forEach((item) => {
+            /* dimenArr.forEach((item) => {
                 this.dimension.push(item);
-            });
+            }); */
             // let standard = sessionStorage.getItem('standard') ? sessionStorage.getItem('standard') : this.$sotre.state.user.schoolProfile.school_base.standard
             let req = {
                 scope: "school",
@@ -854,6 +860,7 @@ export default {
                                 this.noStudy.push(ids)
                             })
                         }
+                        if(item.env && !this.environment.includes(item.env)) this.environment.push(item.env)
                     })
                     /* 
                         currency:3 -> 选修,1 -> 必修,2 -> 通识

+ 1 - 1
TEAMModelOS/ClientApp/src/view/jyzx/offline.vue

@@ -1060,7 +1060,7 @@ export default {
         },
         deleteFile() {
             if(!this.selectionFile.length) {
-                this.$Message.warning("请先选择文件!")
+                this.$Message.warning(this.$t("jyzx.offline.message4"))
             } else {
                 this.isLoading = true
                 let blobUrl = JSON.parse(

+ 29 - 6
TEAMModelOS/ClientApp/src/view/mgtPlatform/MgtPlatform.vue

@@ -30,8 +30,7 @@
                             </p>
                             <!-- 操作区域 -->
                             <div class="platform-action-wrap" v-if="!isArea && $access.can('admin.*|link-upd')">
-                                <!-- 等待对接设置顺序API -->
-                                <span class="pf-action-btn" @click.stop>
+                                <span class="pf-action-btn" @click.stop="editPlatform(item,index)">
                                     <Icon type="md-create" />
                                     {{$t('common.edit')}}
                                 </span>
@@ -42,13 +41,13 @@
                             </div>
                         </div>
                     </div>
-                    <div class="add-platform-box" @click="addStatus = true" v-show="areaPlatform.links.length || schoolPlatform.links.length" v-if="$access.can('admin.*|link-upd')">
+                    <div class="add-platform-box" @click="toAddPlatform" v-show="areaPlatform.links.length || schoolPlatform.links.length" v-if="$access.can('admin.*|link-upd')">
                         <Icon type="md-add-circle" class="add-platform-icon" />
                         <p class="add-platform-text">{{$t('platform.addPlatform')}}</p>
                     </div>
                     <div v-show="!areaPlatform.links.length && !schoolPlatform.links.length" style="margin:auto">
                         <EmptyData :textContent="$t('platform.noPlatform')" :top="120"></EmptyData>
-                        <p class="add-platform" @click="addStatus = true">
+                        <p class="add-platform" @click="toAddPlatform">
                             <Icon type="md-add" />
                             {{$t('platform.addPlatform')}}
                         </p>
@@ -104,6 +103,7 @@ export default {
             }
         }
         return {
+            editIndex: -1,
             areaSas: '',
             schoolSas: '',
             fullData: {},
@@ -137,6 +137,15 @@ export default {
         }
     },
     methods: {
+        toAddPlatform() {
+            this.editIndex = -1
+            this.addStatus = true
+        },
+        editPlatform(platform, index) {
+            this.editIndex = index
+            this.platform = this._.cloneDeep(platform)
+            this.addStatus = true
+        },
         handleDragEnd() {
             let params = {
                 schoolId: this.$store.state.userInfo.schoolCode,
@@ -276,7 +285,14 @@ export default {
                 if (valid) {
                     //区级管理
                     if (this.isArea) {
-                        this.areaPlatform.links.push(this._.cloneDeep(this.platform))
+                        // 修改
+                        if (this.editIndex >= 0) {
+                            this.areaPlatform.links.splice(this.editIndex, 1, this._.cloneDeep(this.platform))
+                        }
+                        // 新增
+                        else {
+                            this.areaPlatform.links.push(this._.cloneDeep(this.platform))
+                        }
                         this.fullData.third = [this.areaPlatform]
                         this.$api.ability.upsertResAndPolicy(this.fullData).then(
                             res => {
@@ -293,7 +309,14 @@ export default {
                     }
                     //校级管理
                     else {
-                        this.schoolPlatform.links.push(this._.cloneDeep(this.platform))
+                        // 修改
+                        if (this.editIndex >= 0) {
+                            this.schoolPlatform.links.splice(this.editIndex, 1, this._.cloneDeep(this.platform))
+                        }
+                        // 新增
+                        else {
+                            this.schoolPlatform.links.push(this._.cloneDeep(this.platform))
+                        }
                         let params = {
                             schoolId: this.$store.state.userInfo.schoolCode,
                             opt: 'UpsertThird',

+ 34 - 24
TEAMModelOS/ClientApp/src/view/mycourse/exam/CreatePrivExam.vue

@@ -273,29 +273,29 @@ export default {
                 this.evaluationInfo.grades = gradesInfo
             }
 
-            //2、设置评测“学科”
-            this.evaluationInfo.subjects = []
-            // 个人课程用课程名称代替学科
-            if (this.evaluationInfo.scope == 'private') {
-                if (data.targets.length && data.course) {
-                    this.evaluationInfo.subjects.push({
-                        id: this.courseInfo.id,
-                        name: this.courseInfo.name
-                    })
-                }
-                this.evaluationInfo.period = undefined
-            }
-            //校本课程用课程关联的学生,并补充学段信息
-            else {
-                this.evaluationInfo.subjects.push({
-                    id: this.courseInfo?.subject?.id,
-                    name: this.courseInfo?.subject?.name
-                })
-                this.evaluationInfo.period = {
-                    id: this.courseInfo?.period?.id,
-                    name: this.courseInfo?.period?.name
-                }
-            }
+            //2、设置评测“学科” 我的课程页面已经是从课程页面进来,不需要挑选课程了
+            // this.evaluationInfo.subjects = []
+            // // 个人课程用课程名称代替学科
+            // if (this.evaluationInfo.scope == 'private') {
+            //     if (data.targets.length && data.course) {
+            //         this.evaluationInfo.subjects.push({
+            //             id: this.courseInfo.id,
+            //             name: this.courseInfo.name
+            //         })
+            //     }
+            //     this.evaluationInfo.period = undefined
+            // }
+            // //校本课程用课程关联的学生,并补充学段信息
+            // else {
+            //     this.evaluationInfo.subjects.push({
+            //         id: this.courseInfo?.subject?.id,
+            //         name: this.courseInfo?.subject?.name
+            //     })
+            //     this.evaluationInfo.period = {
+            //         id: this.courseInfo?.period?.id,
+            //         name: this.courseInfo?.period?.name
+            //     }
+            // }
         },
         scaleStatusText() {
             if (!this.$store.state.userInfo.hasSchool) {
@@ -640,7 +640,6 @@ export default {
             this.$router.go(-1)
             return
         }
-        console.log(courseData)
         this.courseInfo = course
         this.evaluationInfo.scope = this.courseInfo.scope
         this.classList = classList.map(item => {
@@ -661,6 +660,17 @@ export default {
                 this.targets = [defaultClass]
             }
             this.evaluationInfo.targets = this.targets
+            this.evaluationInfo.subjects = []
+            if (courseData.course?.scope == 'school') {
+                this.evaluationInfo.subjects.push(this._.cloneDeep(courseData.course.subject))
+            } else {
+                this.evaluationInfo.subjects = [
+                    {
+                        id: courseData.course.id,
+                        name: courseData.course.name
+                    }
+                ]
+            }
             this.treeChangeToSetInfo()
         }
     },

+ 92 - 6
TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.vue

@@ -76,6 +76,9 @@
         <span style="cursor: pointer;margin-right: 10px;color: #04abc8;" @click="onClickAdFilter">
           <Icon type="ios-funnel" color="#04abc8" style="margin-right: 5px;" />{{ hideAdFilter ? $t('lessonRecord.more') : $t('lessonRecord.close') }}
         </span>
+        <span style="cursor: pointer;margin-right: 10px;color: #04abc8;" @click="exportTable">
+          <Icon type="md-download" color="#04abc8" style="margin:5px;" />{{ $t('assessment.export') }}
+        </span>
         <span>{{ $t('lessonRecord.resultTip1') }} <span style="font-size: 24px;font-weight: bold;color: #FF0000;">{{ totalNum.count }}
           </span>{{ $t('lessonRecord.resultTip2') }}</span>
       </div>
@@ -129,7 +132,7 @@
               </div>
             </div>
           </template>
-          <template slot-scope="{ row }" slot="category">
+          <!-- <template slot-scope="{ row }" slot="category">
             <span>{{ row.category.length ? row.category.join(',') : '-' }}</span>
           </template>
           <template slot-scope="{ row }" slot="subject">
@@ -143,7 +146,7 @@
           </template>
           <template slot-scope="{ row }" slot="startTime">
             <span>{{ $tools.formatTime(row.startTime,'yyyy-MM-dd') }}</span>
-          </template>
+          </template> -->
           <template slot-scope="{ row }" slot="action">
             <div v-if="row.status !== 404">
               <Icon type="md-download" class="action-icon" color="#34cf97" @click="downloadTable(row)" :title="$t('lessonRecord.action1')" />
@@ -209,6 +212,7 @@
 import BaseTypeMgmt from './BaseTypeMgmt.vue'
 import BaseForm from './BaseForm.vue'
 import BaseCleanCond from './BaseCleanCond.vue'
+import excel from '@/utils/excel.js'
 export default {
   components: {
     BaseTypeMgmt,
@@ -395,9 +399,12 @@ export default {
         },
         {
           title: vm.$t('lessonRecord.attendCount'),
-          key: 'attendCount',
+          key: 'attendRate',
           sortable: true,
           ellipsis: true,
+          render: function (h, params) {
+            return h('span', (Number(params.row.attendRate)).toFixed(2) + '%')
+          },
         },
         {
           title: vm.$t('lessonRecord.groupCount'),
@@ -458,6 +465,9 @@ export default {
           key: 'examPointRate',
           sortable: true,
           ellipsis: true,
+          render: function (h, params) {
+            return h('span', (Number(params.row.examPointRate)).toFixed(2) + '%')
+          },
         },
         {
           title: vm.$t('lessonRecord.action'),
@@ -480,9 +490,85 @@ export default {
     },
     /* 导出表格 */
     exportTable() {
-      this.$refs.tableRef.exportCsv({
-        filename: this.$t('lessonRecord.allTable')
-      });
+      if (this.totalNum) {
+        this.filterParams.pageCount = this.totalNum.count
+        this.$Spin.show()
+        this.$api.lessonRecord.getLessonList(this.filterParams).then(async res => {
+          if (!res.error && res.lessonRecords) {
+            let origin = res.lessonRecords
+            let sheets = []
+            // 导出教师角度的统计
+            let teacherIds = [...new Set(origin.map(i => i.tmdid))]
+            let teacherHeaders = [this.$t('lessonRecord.export.order'), this.$t('lessonRecord.export.tchName'), this.$t('lessonRecord.export.tmdid'), this.$t('lessonRecord.subject'), this.$t('lessonRecord.export.recordCount')]
+            let teacherKeys = ['index', 'name', 'tmdid', 'subject', 'count']
+            let teacherDatas = teacherIds.map((tchId, index) => {
+              let tchRecords = origin.filter(i => i.tmdid === tchId)
+              return {
+                index: index + 1,
+                name: tchRecords[0].tmdname,
+                tmdid: tchId,
+                subject: [...new Set(tchRecords.map(i => i.subjectId))].map(i => this.curPeriod.subjects.find(j => j.id === i) ? this.curPeriod.subjects.find(j => j.id === i).name : '-').join(','),
+                count: tchRecords.length
+              }
+            })
+            const teacherSheet = {
+              title: teacherHeaders,
+              key: teacherKeys,
+              data: teacherDatas,
+              autoWidth: true,
+              filename: this.$t('lessonRecord.export.sheet1')
+            }
+            sheets.push(teacherSheet)
+            // 导出所有课堂记录清单
+            let conds = this.conds.map(i => i.name)
+            let keys = this.conds.map(i => i.key)
+            console.error(this.$t('lessonRecord.export.order'))
+            let recordHeaders = [this.$t('lessonRecord.export.order'), this.$t('lessonRecord.export.recordName'), this.$t('lessonRecord.export.tchName'), this.$t('lessonRecord.export.tmdid'), this.$t('lessonRecord.subject'), this.$t('lessonRecord.grade'), this.$t('lessonRecord.className'), this.$t('lessonRecord.cate'), ...conds, this.$t('lessonRecord.export.time')]
+            let recordKeys = ['index', 'name', 'tmdname', 'tmdid', 'subject', 'grade', 'className', 'category', ...keys, 'time']
+            let recordDatas = origin.map((record, index) => {
+              return {
+                index: index + 1,
+                name: record.name,
+                tmdname: record.tmdname,
+                tmdid: record.tmdid,
+                subject: this.curPeriod.subjects.find(j => j.id === record.subjectId) ? this.curPeriod.subjects.find(j => j.id === record.subjectId).name : '-',
+                grade: record.grade.map(i => this.curPeriod.grades[+i]).join(','),
+                className: record.groupNames.join(','),
+                category: record.category.length ? record.category.join(',') : '-',
+                attendRate: record.attendRate.toFixed(2) + '%',
+                groupCount: record.groupCount,
+                totalPoint: record.totalPoint,
+                collateTaskCount: record.collateTaskCount,
+                collateCount: record.collateCount,
+                pushCount: record.pushCount,
+                totalInteractPoint: record.totalInteractPoint,
+                interactionCount: record.interactionCount,
+                clientInteractionCount: record.clientInteractionCount,
+                examQuizCount: record.examQuizCount,
+                examPointRate: record.examPointRate.toFixed(2) + '%',
+                time: this.$tools.formatTime(record.startTime, 'yyyy-MM-dd')
+              }
+            })
+            const recordSheet = {
+              title: recordHeaders,
+              key: recordKeys,
+              data: recordDatas,
+              autoWidth: true,
+              filename: this.$t('lessonRecord.export.sheet2')
+            }
+            sheets.push(recordSheet)
+            // 一起导出
+            excel.export_array_to_sheet(sheets, this.$store.state.user.schoolProfile.school_base.name + this.$t('lessonRecord.export.fileName'))
+            this.$Spin.hide()
+          } else {
+            this.$Spin.hide()
+            this.$Message.warning(this.$t('lessonRecord.export.noData'))
+          }
+        })
+      } else {
+        this.$Message.warning(this.$t('lessonRecord.export.noData'))
+      }
+
     },
     /* 下载课例总表 */
     downloadTable(row) {

+ 2 - 2
TEAMModelOS/ClientApp/src/view/schoolmgmt/SystemSetting/SystemSetting.vue

@@ -10,9 +10,9 @@
                     {{schoolSetting.type == 1 ? $t('schoolBaseInfo.pdMgt') : $t('schoolBaseInfo.cgMgt')}}
                 </span>
                 <!-- 接口未配置完整,先隐藏 -->
-                <!-- <span class="pane" @click="tab = 'third'" :class="{ active: tab === 'third' }">
+                <span class="pane" @click="tab = 'third'" :class="{ active: tab === 'third' }">
                     {{this.$t('settings.setting_title3')}}
-                </span> -->
+                </span>
             </div>
             <Button v-show="tab != 'third'" v-if="$access.ability('admin','schoolSetting-upd').validateAll" class="school-tools" :loading="isLoading" :disabled="!updated" icon="ios-albums-outline" @click.stop="saveData()">{{$t('schoolBaseInfo.saveInfo')}}</Button>
         </div>

+ 1 - 1
TEAMModelOS/ClientApp/src/view/student-account/import/StuImport.vue

@@ -152,7 +152,7 @@
                         <p>{{(row.pw == '' || row.pw == null)? '— —' : row.pw+''}}</p>
                     </template>
                     <template slot-scope="{ row,index }" slot="gender">
-                        <p>{{row.gender == 'F' ? $t('stuAccount.sit25') : row.gender == 'M' ? $t('stuAccount.sit26') : row.gender || '-'}}</p>
+                        <p>{{row.gender == 'F' ? $t('stuAccount.sit25') : row.gender == 'M' ? $t('stuAccount.sit24') : row.gender || '-'}}</p>
                     </template>
                     <template slot-scope="{ row }" slot="classYear">
                         <p>{{ `${$jsFn.getGradeNameByYear(row.classYear)}(${row.classYear}${$t('unit.gradeYear')})` }}</p>

+ 10 - 23
TEAMModelOS/Controllers/Analysis/AnalysisController.cs

@@ -1071,18 +1071,12 @@ namespace TEAMModelOS.Controllers.Analysis
                 resultSum.Add(data.Sum());
             }
             //确定高分组 最低分数
-            double rhw = 0;
-            double rhl = 0;
-            int rhwCount = 0;
-            int rhlCount = 0;
-            if (resultSum.Count >= 20) {
-                resultSum.Sort((s1, s2) => { return s2.CompareTo(s1); });
-                rhwCount = Convert.ToInt32(Math.Floor(resultSum.Count * 0.27));
-                 rhw = rhwCount > 0 ? resultSum[rhwCount] : 0;
-                 rhlCount = Convert.ToInt32(Math.Ceiling(resultSum.Count * 0.73));
-                 rhl = rhlCount > 0 ? resultSum[rhlCount] : 0;
-            }
-           
+            resultSum.Sort((s1, s2) => { return s2.CompareTo(s1); });
+            int rhwCount = Convert.ToInt32(Math.Floor(resultSum.Count * 0.27));
+            double rhw = rhwCount > 0 ? resultSum[rhwCount] : 0;
+            int rhlCount = Convert.ToInt32(Math.Ceiling(resultSum.Count * 0.73));
+            double rhl = rhlCount > 0 ? resultSum[rhlCount - 1] : 0;
+
 
 
             List<string> knowledgeName = new List<string>();
@@ -1299,18 +1293,11 @@ namespace TEAMModelOS.Controllers.Analysis
                 resultSum.Add(data.Sum());
             }
             //确定高分组 最低分数
-            double rhw = 0;
-            double rhl = 0;
-            int rhwCount = 0;
-            int rhlCount = 0;
-            if (resultSum.Count >= 20)
-            {
                 resultSum.Sort((s1, s2) => { return s2.CompareTo(s1); });
-                rhwCount = Convert.ToInt32(Math.Floor(resultSum.Count * 0.27));
-                rhw = rhwCount > 0 ? resultSum[rhwCount] : 0;
-                rhlCount = Convert.ToInt32(Math.Ceiling(resultSum.Count * 0.73));
-                rhl = rhlCount > 0 ? resultSum[rhlCount] : 0;
-            }
+                int rhwCount = Convert.ToInt32(Math.Floor(resultSum.Count * 0.27));
+                double rhw = rhwCount > 0 ? resultSum[rhwCount] : 0;
+                int rhlCount = Convert.ToInt32(Math.Ceiling(resultSum.Count * 0.73));
+                double rhl = rhlCount > 0 ? resultSum[rhlCount-1] : 0;
 
             //初始化年级总分
             double total = 0;

+ 30 - 29
TEAMModelOS/Controllers/Client/HiTeachController.cs

@@ -1241,7 +1241,7 @@ namespace TEAMModelOS.Controllers.Client
             //參數驗證
             if (!request.TryGetProperty("grant_type", out JsonElement grant_type)) return BadRequest();
             string grantType = (grant_type.GetString().Equals("school")) ? "school" : "private";
-            JsonElement school_code = new JsonElement();
+            JsonElement school_code = new();
             if (grantType == "school" && !request.TryGetProperty("school_code", out school_code)) return BadRequest();
             string dataId = (grantType.Equals("school")) ? school_code.GetString() : id;
             string container = (grantType.Equals("school")) ? "School" : "Teacher";
@@ -1263,15 +1263,15 @@ namespace TEAMModelOS.Controllers.Client
             }
 
             //取得卷
-            List<object> volumes = new List<object>();
-            List<Volume> volumeList = new List<Volume>();
-            List<string> volumeIdList = new List<string>();
-            string queryTextVol = String.Empty;
-            List<string> WhereVol = new List<string>();
-            if (!String.IsNullOrWhiteSpace(periodId)) WhereVol.Add($" c.periodId = '{periodId}' ");
-            if (!String.IsNullOrWhiteSpace(subjectId)) WhereVol.Add($" c.subjectId = '{subjectId}' ");
-            if (!String.IsNullOrWhiteSpace(volumeId)) WhereVol.Add($" c.id = '{volumeId}' ");
-            if (!String.IsNullOrWhiteSpace(volumeIdFromSyllabusId)) WhereVol.Add($" c.id = '{volumeIdFromSyllabusId}' ");
+            List<object> volumes = new();
+            List<Volume> volumeList = new();
+            List<string> volumeIdList = new();
+            string queryTextVol = string.Empty;
+            List<string> WhereVol = new();
+            if (!string.IsNullOrWhiteSpace(periodId)) WhereVol.Add($" c.periodId = '{periodId}' ");
+            if (!string.IsNullOrWhiteSpace(subjectId)) WhereVol.Add($" c.subjectId = '{subjectId}' ");
+            if (!string.IsNullOrWhiteSpace(volumeId)) WhereVol.Add($" c.id = '{volumeId}' ");
+            if (!string.IsNullOrWhiteSpace(volumeIdFromSyllabusId)) WhereVol.Add($" c.id = '{volumeIdFromSyllabusId}' ");
             foreach (string Where in WhereVol)
             {
                 queryTextVol += (String.IsNullOrWhiteSpace(queryTextVol)) ? $" WHERE {Where} " : $" AND {Where} ";
@@ -1291,7 +1291,7 @@ namespace TEAMModelOS.Controllers.Client
                 }
             }
             //取得課綱 ※display=1時不取任何課綱
-            List<SyllabusTreeNode> treeNodes = new List<SyllabusTreeNode>();
+            List<SyllabusTreeNode> treeNodes = new();
             if (!display.Equals(1))
             {
                 string queryTextSyl = $"SELECT value(c) FROM c WHERE ARRAY_CONTAINS({JsonSerializer.Serialize(volumeIdList)}, c.volumeId, true)";
@@ -1299,30 +1299,31 @@ namespace TEAMModelOS.Controllers.Client
                 await foreach (Syllabus items in client.GetContainer(Constant.TEAMModelOS, container).GetItemQueryIterator<Syllabus>(queryText: queryTextSyl, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{dataId}") }))
                 {
                     List<SyllabusTree> trees = SyllabusService.ListToTree(items.children);
-                    SyllabusTreeNode tree = new SyllabusTreeNode() { id = items.id, scope = items.scope, trees = trees, volumeId = items.volumeId, auth = items.auth, codeval = $"{id}" };
+                    SyllabusTreeNode tree = new() { id = items.id, scope = items.scope, trees = trees, volumeId = items.volumeId, auth = items.auth, codeval = $"{id}" };
                     treeNodes.Add(tree);
                 }
             }
 
             //輸出結果
-            foreach (Volume volumeRow in volumeList)
+            foreach (Volume vr in volumeList)
             {
-                dynamic volumeExtobj = new ExpandoObject();
-                volumeExtobj.periodId = volumeRow.periodId;
-                volumeExtobj.subjectId = volumeRow.subjectId;
-                volumeExtobj.volumeId = volumeRow.id;
-                volumeExtobj.gradeId = volumeRow.gradeId;
-                volumeExtobj.semesterId = volumeRow.semesterId;
-                volumeExtobj.name = volumeRow.name;
-                volumeExtobj.creatorId = volumeRow.creatorId;
-                volumeExtobj.creatorName = volumeRow.creatorName;
-                volumeExtobj.school = volumeRow.school;
-                volumeExtobj.scope = volumeRow.scope;
-                volumeExtobj.syllabusIds = volumeRow.syllabusIds; //課綱內容ID
-                volumeExtobj.auth = volumeRow.auth;     //授權教師
-                List<SyllabusTreeNode> treesInVol = treeNodes.Where(t => t.volumeId == volumeRow.id).ToList();
-                volumeExtobj.syllabus = treesInVol;
-                volumes.Add(volumeExtobj);
+                volumes.Add(new
+                {
+                    vr.periodId,
+                    vr.subjectId,
+                    vr.id,
+                    vr.gradeId,
+                    vr.semesterId,
+                    vr.name,
+                    vr.creatorId,
+                    vr.creatorName,
+                    vr.school,
+                    vr.scope,
+                    vr.syllabusIds,
+                    vr.auth,
+                    vr.order,
+                    syllabus = treeNodes.Where(t => t.volumeId == vr.id).ToList()
+                });
             }
 
             return Ok(volumes);

+ 70 - 0
TEAMModelOS/Controllers/Client/HiTeachccControlller.cs

@@ -245,6 +245,76 @@ namespace TEAMModelOS.Controllers.Client
             }
         }
 
+        /// <summary>
+        /// 更新课堂记录
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("update-lesson-record")]
+        public async Task<IActionResult> UpdateLessonRecord(JsonElement request)
+        {
+            var client = _azureCosmos.GetCosmosClient();
+            if (!request.TryGetProperty("lesson_id", out JsonElement _lessonId)) return BadRequest();
+            if (!request.TryGetProperty("tmdid", out JsonElement _tmdid)) return BadRequest();
+            request.TryGetProperty("name", out JsonElement name);
+            request.TryGetProperty("school", out JsonElement _school);
+            if (!request.TryGetProperty("scope", out JsonElement _scope)) return BadRequest();
+            request.TryGetProperty("grant_types", out JsonElement _grant_types);
+            string tbname;
+            string code;
+
+            if (_scope.GetString().Equals("school") && !string.IsNullOrWhiteSpace(_school.GetString()))
+            {
+                code = $"LessonRecord-{_school}";
+                tbname = "School";
+            }
+            else if ($"{_scope}".Equals("private"))
+            {
+
+                code = $"LessonRecord";
+                tbname = "Teacher";
+            }
+            else
+            {
+                return BadRequest();
+            }
+            try
+            {
+                LessonRecord lessonRecord = await client.GetContainer(Constant.TEAMModelOS, tbname).ReadItemAsync<LessonRecord>($"{_lessonId}", new PartitionKey(code));
+                List<LessonUpdate> updates = new() { new LessonUpdate { grant_type = "up-base" } };
+                if (_grant_types.ValueKind.Equals(JsonValueKind.Array))
+                {
+                    updates = _grant_types.ToObject<List<LessonUpdate>>();
+                    if (!updates.Select(x => x.grant_type).Contains("up-base"))
+                    {
+                        updates.Add(new LessonUpdate { grant_type = "up-base" });
+                    }
+                }
+                if (!string.IsNullOrWhiteSpace($"{name}"))
+                {
+                    lessonRecord.name = $"{name}";
+                    await client.GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<LessonRecord>(lessonRecord, $"{_lessonId}", new PartitionKey(code));
+                }
+                var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
+                string msg = null;
+                msg = new { lesson_id = $"{_lessonId}", tmdid = $"{_tmdid}", grant_types = updates, school = $"{_school}", scope = $"{_scope}" }.ToJsonString();
+                var messageChange = new ServiceBusMessage(msg);
+                messageChange.ApplicationProperties.Add("name", "LessonRecordEvent");
+                //await _dingDing.SendBotMsg($"{_option.Location},课堂id:{_lessonId} 更新事件,{msg}", GroupNames.醍摩豆服務運維群組);
+                await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageChange);
+                return Ok(new { status = 200 });
+            }
+            catch (CosmosException ex) when (ex.Status == 404)
+            {
+                return BadRequest("课堂记录不存在");
+            }
+            catch (Exception ex)
+            {
+                return BadRequest();
+            }
+        }
+
         //取得老師資訊
         [ProducesResponseType(StatusCodes.Status200OK)]
         [ProducesResponseType(StatusCodes.Status400BadRequest)]

+ 25 - 17
TEAMModelOS/Controllers/Normal/AbilityStatisticsController.cs

@@ -377,30 +377,38 @@ namespace TEAMModelOS.Controllers
                 List<School> schools = new List<School>();
                 await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<School>(queryText: $"select value(c) from c where c.areaId='{area.id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base") }))
                 {
-
                     schools.Add(item);
                 }
-              
                 int countArea = 0;
                 int appraiseArea = 0;
                 List<SchoolInfos> schoolInfos = new List<SchoolInfos>();
                 TeacherTrainChangeMsg msg  = new TeacherTrainChangeMsg() { areaId=area.id};
-                foreach (var school in schools)
+                List<Task> tasks = new List<Task>();
+                List<string> updateTeach = new List<string>();
+                schools.ForEach(  school =>
                 {
-                    schoolInfos.Add(new SchoolInfos { schoolId = school.id, schoolName = school.name, picture = school.picture });
-                    (List<TeacherTrain> trains, List<RGroupList> yxtrain, List < TeacherTrain >   updateTeacherTrains)= await StatisticsService.StatisticsSchoolQuik(_coreAPIHttpService, school.id, setting, area, client, _dingDing, null);
-                    teacherTrains.AddRange( trains);
-                    schoolInfos.ForEach(y => {
-                        var list =yxtrain.Find(z => z.school.Equals(y.schoolId));
-                        if (list != null)
+                    tasks.Add(Task.Run(async () =>
+                    {
+                        schoolInfos.Add(new SchoolInfos { schoolId = school.id, schoolName = school.name, picture = school.picture });
+                        (List<TeacherTrain> trains, List<RGroupList> yxtrain, List<TeacherTrain> updateTeacherTrains) = 
+                        await StatisticsService.StatisticsSchoolQuik(_coreAPIHttpService, school.id, setting, area, client, _dingDing, null);
+                        teacherTrains.AddRange(trains);
+                        schoolInfos.ForEach(y =>
                         {
-                            y.trainCount = list.members.Count;
+                            var list = yxtrain.Find(z => z.school.Equals(y.schoolId));
+                            if (list != null)
+                            {
+                                y.trainCount = list.members.Count;
+                            }
+                        });
+                        if (updateTeacherTrains.IsNotEmpty())
+                        {
+                            updateTeach.AddRange(updateTeacherTrains.Select(z => z.id));
+                            msg.schools.Add(new TeacherTrainChangeMsgSchoolTeachers { school = school.id, teachers = updateTeacherTrains.Select(z => z.id).ToList() });
                         }
-                    });
-                    if (updateTeacherTrains.IsNotEmpty()) {
-                        msg.schools.Add(  new TeacherTrainChangeMsgSchoolTeachers { school = school.id, teachers = updateTeacherTrains.Select(z => z.id).ToList() });
-                    }
-                }
+                    }));
+                });
+                await Task.WhenAll(tasks);
                 bool isnew=false;
                 if (msg.schools.IsNotEmpty())
                 {
@@ -475,11 +483,11 @@ namespace TEAMModelOS.Controllers
                         isnew= true;
                     }
                 }
-                return Ok(new { teacherTrains = dynamics, setting, schools = schoolInfos, totalTime, hgcount, teacherCount = countArea, appraiseCount = appraiseArea, isnew ,area.updateTime});
+                return Ok(new { teacherTrains = dynamics, setting, schools = schoolInfos, totalTime, hgcount, teacherCount = countArea, appraiseCount = appraiseArea, isnew ,area.updateTime, updateTeach });
             }
             catch (Exception ex)
             {
-                await _dingDing.SendBotMsg($"OS,{_option.Location},UpsertSubmitScore/UpsertSubmitScore()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
+                await _dingDing.SendBotMsg($"OS,{_option.Location},StatisticsAreaQuick()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
                 return BadRequest(new { ex.Message, ex.StackTrace });
 
             }

+ 2 - 2
TEAMModelOS/Controllers/School/KnowledgesController.cs

@@ -122,10 +122,10 @@ namespace TEAMModelOS.Controllers
         {
             if (!json.TryGetProperty("school", out JsonElement school)) return BadRequest();
             Knowledge knowledge = json.GetProperty("knowledge").ToObject<Knowledge>();
-            List<OldNew> old_new = null;
+            List<TagOldNew> old_new = null;
             if (json.TryGetProperty("old_new", out JsonElement _old_new))
             {
-                old_new = _old_new.ToObject<List<OldNew>>();
+                old_new = _old_new.ToObject<List<TagOldNew>>();
             }
             ValidResult validResult = knowledge.Valid();
             if (!validResult.isVaild)

+ 24 - 3
TEAMModelOS/Controllers/School/SchoolSettingController.cs

@@ -15,6 +15,8 @@ using Microsoft.Extensions.Options;
 using Microsoft.Extensions.Configuration;
 using TEAMModelOS.Filter;
 using Microsoft.AspNetCore.Authorization;
+using HTEXLib.COMM.Helpers;
+using System.Linq;
 
 namespace TEAMModelOS.Controllers
 {
@@ -30,8 +32,9 @@ namespace TEAMModelOS.Controllers
         private readonly AzureRedisFactory _azureRedis;
         private readonly DingDing _dingDing;
         private readonly Option _option;
-        private readonly IConfiguration _configuration;
-        public SchoolSettingController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration)
+        private readonly IConfiguration _configuration; 
+        private readonly HttpTrigger _httpTrigger;
+        public SchoolSettingController(HttpTrigger httpTrigger, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, DingDing dingDing, IOptionsSnapshot<Option> option, IConfiguration configuration)
         {
             _azureCosmos = azureCosmos;
             _azureStorage = azureStorage;
@@ -39,6 +42,7 @@ namespace TEAMModelOS.Controllers
             _dingDing = dingDing;
             _option = option?.Value;
             _configuration = configuration;
+            _httpTrigger = httpTrigger;
         }
 
         /*
@@ -138,6 +142,23 @@ namespace TEAMModelOS.Controllers
                 case bool when $"{_opt}".Equals("UpsertLessonTag", StringComparison.OrdinalIgnoreCase) && (json.TryGetProperty("lessonTag", out JsonElement _lessonTag)):
                     HashSet <string> lessonTag = _lessonTag.ToObject<HashSet<string>>();
                     setting.lessonTag = lessonTag;
+                    List<TagOldNew> old_new = null;
+                    if (json.TryGetProperty("old_new", out JsonElement _old_new))
+                    {
+                        old_new = _old_new.ToObject<List<TagOldNew>>();
+                    }
+                    //处理标签删除的问题。
+                    if (old_new.IsNotEmpty()  && lessonTag != null)
+                    {
+                        try
+                        {
+                            _ = _httpTrigger.RequestHttpTrigger(new { old_new = old_new, school = $"{_school}" }, _option.Location, "lesson-tag-change");
+                        }
+                        catch (Exception ex)
+                        {
+                            //暂不处理
+                        }
+                    }
                     break;
                 case bool when $"{_opt}".Equals("UpsertLessonSetting", StringComparison.OrdinalIgnoreCase) && (json.TryGetProperty("lessonSetting", out JsonElement _lessonSetting)):
                     LessonSetting lessonSetting = _lessonSetting.ToObject<LessonSetting>();
@@ -145,7 +166,7 @@ namespace TEAMModelOS.Controllers
                     break;
                 default: break;
             }
-            await client.GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync<SchoolSetting>(setting, partitionKey: new Azure.Cosmos.PartitionKey("SchoolSetting"));
+            await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolSetting>(setting,setting.id, partitionKey: new Azure.Cosmos.PartitionKey("SchoolSetting"));
             return Ok(new { setting });
         }
     }

+ 12 - 4
TEAMModelOS/Controllers/Third/Xkw/XkwServiceController.cs

@@ -279,7 +279,9 @@ namespace TEAMModelOS.Controllers.Third.Xkw
                                 child_itemInfo.objective = true;
                                 string shtml = questiones[i];
                                 //去除class 以及span标签"
-                                shtml = Regex.Replace(shtml, table_pattern, "").Replace("</table>", "").Replace("<tr>", "").Replace("<td>", "").Replace("</td>", "").Replace("</tr>", "");
+                               // shtml = Regex.Replace(shtml, table_pattern, "").Replace("</table>", "").Replace("<tr>", "").Replace("<td>", "").Replace("</td>", "").Replace("</tr>", "");
+                                
+                                
                                 //shtml = Regex.Replace(shtml, classpattern, "");
                                 //shtml = Regex.Replace(shtml, pattern, "");
                                 //shtml = Regex.Replace(shtml, apattern, "");
@@ -383,7 +385,10 @@ namespace TEAMModelOS.Controllers.Third.Xkw
 
                             string shtml = x.stem;
                             //去除class 以及span标签"
-                            shtml = Regex.Replace(shtml, table_pattern, "").Replace("</table>", "").Replace("<tr>", "").Replace("<td>", "").Replace("</td>", "").Replace("</tr>", "");
+                           // shtml = Regex.Replace(shtml, table_pattern, "").Replace("</table>", "").Replace("<tr>", "").Replace("<td>", "").Replace("</td>", "").Replace("</tr>", "");
+                            
+                            
+                            
                             //shtml = Regex.Replace(shtml, classpattern, "");
                             //shtml = Regex.Replace(shtml, pattern, "");
                             //shtml = Regex.Replace(shtml, apattern, "");
@@ -496,15 +501,18 @@ namespace TEAMModelOS.Controllers.Third.Xkw
                     optHtml = HtmlHelper.DoUselessTag(optHtml);
                     optHtml = optHtml.TrimStart().TrimEnd();
                     textImg.Append(HtmlHelper.DoTextImg(optHtml));
+                    string table_pattern = "<table([^>]{0,})>";
+                    optHtml = Regex.Replace(optHtml, table_pattern, "").Replace("</table>", "").Replace("<tr>", "").Replace("<td>", "").Replace("</td>", "").Replace("</tr>", "");
                     options.Add(new CodeValue { code = optionsKeys[i], value = optHtml });
                 }
             }
             if (!string.IsNullOrWhiteSpace(optsHtml))
-            {
-                return (options, question.Replace(optsHtml, ""));
+            { question = question.Replace(optsHtml, "").Replace("<table class=\"qml-og\" style=\"width:100%\"><tr><td>", "");
+                return (options, question);
             }
             else
             {
+                question= question.Replace("<table class=\"qml-og\" style=\"width:100%\"><tr><td>","");
                 return (new List<CodeValue>(), question);
             }
         }

+ 15 - 3
TEAMModelOS/Controllers/XTest/FixDataController.cs

@@ -1754,16 +1754,28 @@ namespace TEAMModelOS.Controllers
 
             if (!request.TryGetProperty("userkeys", out JsonElement _userkeys)) { return BadRequest(); }
             List<string> userkeys = _userkeys.ToObject<List<string>>();
-
+            List<string> nokey = new List<string>();
             var content = new StringContent(userkeys.Select(x => x).ToJsonString(), Encoding.UTF8, "application/json");
             string json = await _coreAPIHttpService.GetUserInfos(content);
-            List<TmdInfo> tmdInfos = json.ToObject<List<TmdInfo>>();
+            List<CoreUser> tmdInfos = json.ToObject<List<CoreUser>>();
+            List<string> noreg = new List<string>();
+            var notin = userkeys.Except(tmdInfos.Select(x => x.searchKey));
+            if (notin.Any())
+            {
+                noreg.AddRange(notin);
+
+            }
             string sql = $"select value(c) from c where c.pk='Teacher' and  c.id in ({string.Join(",", tmdInfos.Select(x => $"'{x.id}'"))})";
             List<SchoolTeacher> schoolTeachers = new List<SchoolTeacher>();
             await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIterator<SchoolTeacher>(queryText: sql))
             {
                 schoolTeachers.Add(item);
             }
+            var noid= tmdInfos.Select(x => x.id).Except(schoolTeachers.Select(z => z.id));
+            if (noid.Any()) {
+               var a = tmdInfos.FindAll(x => noid.Contains(x.id));
+                nokey.AddRange(a.Select(x=>x.searchKey));
+            }
             var groups = schoolTeachers.GroupBy(x => x.id).Select(y => new { key = y.Key, list = y.ToList() });
             var countMore1 = groups.Where(x => x.list.Count > 1).SelectMany(x => x.list);
             var countEqual1 = groups.Where(x => x.list.Count == 1).SelectMany(x => x.list);
@@ -1775,7 +1787,7 @@ namespace TEAMModelOS.Controllers
             foreach (var item in countEqual1) {
                 await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(item, item.id, new PartitionKey(item.code));
             }
-            return Ok(new { countMore1, countEqual1 });
+            return Ok(new { countMore1, countEqual1 , nokey,noreg});
 
         }
         /// <summary>