Преглед на файлове

Merge branch 'develop6.0-tmd' of http://52.130.252.100:10000/TEAMMODEL/TEAMModelOS into develop6.0-tmd

zhouj1203@hotmail.com преди 3 години
родител
ревизия
ba1730efc7
променени са 32 файла, в които са добавени 1611 реда и са изтрити 80 реда
  1. 1 1
      TEAMModelBI/Controllers/DingDingStruc/TableDingDingInfoController.cs
  2. 32 6
      TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs
  3. 1 1
      TEAMModelOS.SDK/Models/Cosmos/Common/Bloblog.cs
  4. 1 1
      TEAMModelOS.SDK/Models/Cosmos/Common/LessonRecord.cs
  5. 4 0
      TEAMModelOS.SDK/Models/Service/GroupListService.cs
  6. 8 7
      TEAMModelOS/ClientApp/src/boot-app.js
  7. 1 1
      TEAMModelOS/ClientApp/src/common/BasePreviewFile.vue
  8. 52 31
      TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/ClassRecord.vue
  9. 1 1
      TEAMModelOS/ClientApp/src/components/student-web/HomeView/CourseListView.vue
  10. 3 3
      TEAMModelOS/ClientApp/src/components/student-web/SettingView/Setting.vue
  11. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/en-US/schoolBaseInfo.js
  12. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/en-US/survey.js
  13. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/schoolBaseInfo.js
  14. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/survey.js
  15. 1 0
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/schoolBaseInfo.js
  16. 1 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-TW/survey.js
  17. 1 1
      TEAMModelOS/ClientApp/src/router/routes.js
  18. 41 2
      TEAMModelOS/ClientApp/src/utils/directive.js
  19. 6 5
      TEAMModelOS/ClientApp/src/view/ability/Review.vue
  20. 28 6
      TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue
  21. 1 1
      TEAMModelOS/ClientApp/src/view/classrecord/eventchart/PopQues.vue
  22. 3 1
      TEAMModelOS/ClientApp/src/view/evaluation/bank/PaperDownload.vue
  23. 1 0
      TEAMModelOS/ClientApp/src/view/evaluation/index/CreatePaper.vue
  24. 1 1
      TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue
  25. 2 0
      TEAMModelOS/ClientApp/src/view/schoolmgmt/SystemSetting/SystemSetting.less
  26. 7 5
      TEAMModelOS/ClientApp/src/view/schoolmgmt/SystemSetting/SystemSetting.vue
  27. 1 1
      TEAMModelOS/ClientApp/src/view/student-account/class/ClassMgt.vue
  28. 1 1
      TEAMModelOS/ClientApp/src/view/student-account/stulist/MgtStuList.vue
  29. 1184 0
      TEAMModelOS/ClientApp/src/view/teachCenter/TeaResCenterNew.vue
  30. 1 1
      TEAMModelOS/ClientApp/src/view/teachermgmt/components/userList/Index.vue
  31. 1 0
      TEAMModelOS/Controllers/Client/HiTeachController.cs
  32. 222 0
      TEAMModelOS/Controllers/XTest/FixDataController.cs

+ 1 - 1
TEAMModelBI/Controllers/DingDingStruc/TableDingDingInfoController.cs

@@ -375,7 +375,7 @@ namespace TEAMModelBI.Controllers.DingDingStruc
         /// <param name="jsonElement"></param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
-        [AuthToken(Roles = "assist")]
+        [AuthToken(Roles = "admin")]
         [HttpPost("set-permissions")]
         public async Task<IActionResult> SetPermissions(JsonElement jsonElement)
         {

+ 32 - 6
TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs

@@ -967,6 +967,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                 //如果有更新 则去读取/{_lessonId}/IES/base.json
                                 try
                                 {
+                                    await _dingDing.SendBotMsg($"{_option.Location},课堂id:{_lessonId} 收到更新", GroupNames.成都开发測試群組);
                                     BlobDownloadResult baseblobDownload = await _azureStorage.GetBlobContainerClient(blobname).GetBlobClient($"/records/{_lessonId}/IES/base.json").DownloadContentAsync();
                                     LessonBase lessonBase = baseblobDownload.Content.ToObjectFromJson<LessonBase>();
                                     if (lessonBase != null  && lessonBase.summary!=null)
@@ -987,6 +988,26 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                         lessonRecord.examCount = lessonBase.summary.examCount;
                                         lessonRecord.totalInteractPoint = lessonBase.summary.totalInteractPoint;
                                     }
+                                    long? size = await  _azureStorage.GetBlobContainerClient(blobname).GetBlobsSize($"records/{_lessonId}");
+                                    Bloblog bloblog = new Bloblog
+                                    {
+                                        id = lessonRecord.id,
+                                        code = $"Bloblog-{blobname}",
+                                        name = lessonRecord.name,
+                                        pk = "Bloblog",
+                                        time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                                        type = "records",
+                                        url = $"records/{_lessonId}",
+                                        subjectId = new List<string> { lessonRecord.subjectId },
+                                        periodId = new List<string> { lessonRecord.periodId },
+                                        size = size.HasValue ? size.Value : 0,
+                                    };
+                                    await client.GetContainer(Constant.TEAMModelOS,tbname).UpsertItemAsync(bloblog);
+                                    var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = "records", name = $"{blobname}" }.ToJsonString()); ;
+                                    messageBlob.ApplicationProperties.Add("name", "BlobRoot");
+                                    var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
+                                    await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
+                                    await _dingDing.SendBotMsg($"{_option.Location},课堂id:{_lessonId} 更新完成", GroupNames.成都开发測試群組);
                                     msgs.Add(update);
                                 }
                                 catch (RequestFailedException ex) when (ex.Status == 404)
@@ -1027,6 +1048,12 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                 try
                                 {
                                     await client.GetContainer(Constant.TEAMModelOS, tbname).DeleteItemAsync<LessonRecord>(lessonId, new PartitionKey(code));
+                                    await _azureStorage.GetBlobServiceClient().DeleteBlobs(_dingDing, blobname, new List<string> { $"records/{_lessonId}" });
+                                    await client.GetContainer(Constant.TEAMModelOS, tbname).DeleteItemStreamAsync(lessonRecord.id,new PartitionKey ($"Bloblog-{blobname}"));
+                                    var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = "records", name = $"{blobname}" }.ToJsonString()); ;
+                                    messageBlob.ApplicationProperties.Add("name", "BlobRoot");
+                                    var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
+                                    await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
                                     msgs.Add(update);
                                 }
                                 catch (CosmosException)
@@ -1094,6 +1121,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                     if (groupLists.IsNotEmpty() && !string.IsNullOrWhiteSpace(lessonRecord.periodId))
                                     {
                                         try {
+                                            var gplist = groupLists.FindAll(x => lessonRecord.groupIds.Contains(x.id));
                                             School schoolObj = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>(lessonRecord.school, new PartitionKey("Base"));
                                             //年级算法
                                             var period = schoolObj.period.Find(x => x.id.Equals(lessonRecord.periodId));
@@ -1102,16 +1130,16 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                             {
                                                 int Month = DateTimeOffset.UtcNow.Month;
                                                 int Year = DateTimeOffset.UtcNow.Year;
-                                                foreach (int year in groupLists.Select(x => x.year))
+                                                foreach (int year in gplist.Select(x => x.year))
                                                 {
                                                     int grade;
                                                     if (Month >= 1 && Month <= 6)
                                                     {
-                                                        grade = (Year - year + 1) / Count.Value;
+                                                        grade = (Year - year -1) % Count.Value;
                                                     }
                                                     else
                                                     {
-                                                        grade = (Year - year) / Count.Value;
+                                                        grade = (Year - year) % Count.Value;
                                                     }
                                                     grades.Add($"{grade}");
                                                 }
@@ -1120,12 +1148,10 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
                                             
                                         }
                                     }
-                                    lessonRecord.grade.AddRange(grades);
+                                    lessonRecord.grade= grades.ToList();
                                 }
                                 msgs.Add(update);
                                 break;
-                           
-                                
                             default:
                                 break;
                         }

+ 1 - 1
TEAMModelOS.SDK/Models/Cosmos/Common/Bloblog.cs

@@ -18,7 +18,7 @@ namespace TEAMModelOS.SDK.Models
         public List<string> subjectId { get; set; } = new List<string>() { "" };
         public List<string> gradeId { get; set; } = new List<string>() { "" };
         /// <summary>
-        /// audio 音频,video 视频 ,doc文档,image图片,other 其他,res教材,thum缩略图,avatar 头像
+        /// audio 音频,video 视频 ,doc文档,image图片,other 其他,res教材,thum缩略图,avatar 头像,课堂记录records
         /// </summary>
         public string type { get; set; }
 

+ 1 - 1
TEAMModelOS.SDK/Models/Cosmos/Common/LessonRecord.cs

@@ -354,7 +354,7 @@ namespace TEAMModelOS.SDK.Models
         /// <summary>
         /// 
         /// </summary>
-        public double attendState { get; set; }
+        //public double attendState { get; set; }
         /// <summary>
         /// 
         /// </summary>

+ 4 - 0
TEAMModelOS.SDK/Models/Service/GroupListService.cs

@@ -450,6 +450,10 @@ namespace TEAMModelOS.SDK
         public static async Task<List<GroupListDto>> GetGroupListListids(CosmosClient client, DingDing _dingDing, List<string> classes, string school,
             string SummarySql = " c.id,c.code,c.name,c.no,c.periodId,c.scope,c.school,c.creatorId,c.type,c.year,c.tcount,c.scount,c.leader ")
         {
+            classes.RemoveAll(x => x == null);
+            if (!classes.IsNotEmpty()) {
+                return null;
+            }
             List<GroupListDto> groupLists = null;
             if (classes.Count == 1 && classes.First().Equals("TeacherAll") && !string.IsNullOrEmpty(school))
             {

+ 8 - 7
TEAMModelOS/ClientApp/src/boot-app.js

@@ -11,7 +11,7 @@ import tools from '@/utils/public.js'
 import evTools from '@/utils/evTools.js'
 import editorTools from '@/utils/editorTools.js'
 import jsFn from '@/utils/js-fn.js'
-import specialChar from '@/utils/directive.js'
+import { specialChar, fileName } from '@/utils/directive.js'
 import apiTools from '@/api'
 import loginTools from '@/access/login'
 import mockTools from '@/mock'
@@ -57,11 +57,12 @@ Vue.use(hevueImgPreview)
 Vue.use(dataV)
 // 设置全局自定义指令
 Vue.directive('special-char', specialChar)
+Vue.directive('file-name', fileName)
 // 设置图片懒加载
 Vue.use(VueLazyload, {
- error: require('@/assets/image/img_err.png'),
- loading: require('@/assets/loading/loading.gif'),
- attempt: 1,//尝试加载的次数
+    error: require('@/assets/image/img_err.png'),
+    loading: require('@/assets/loading/loading.gif'),
+    attempt: 1,//尝试加载的次数
 })
 Vue.use(htmlToPdf)
 Vue.use(VueClipBoard)
@@ -85,9 +86,9 @@ Vue.use(VueLogger, {
     showConsoleColors: true
 })
 // 定义vuescroll全局滚动条组件
-Vue.component('vuescroll',vuescroll)
-Vue.component('NewChooseContent',NewChooseContent)
-Vue.prototype.$vuescrollConfig =  tools.vueScrollOpt
+Vue.component('vuescroll', vuescroll)
+Vue.component('NewChooseContent', NewChooseContent)
+Vue.prototype.$vuescrollConfig = tools.vueScrollOpt
 // 定义全局中央数据总线通信
 Vue.prototype.$EventBus = new Vue()
 // 全局API请求

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

@@ -11,7 +11,7 @@
 			<iframe v-else-if="previewFile.type == 'doc' && previewFile.extension != 'PDF'"
 				:src="'https://view.officeapps.live.com/op/view.aspx?src=' + encodeURIComponent(previewFile.url)"
 				width="100%" height="100%" frameborder="1" />
-			<div class="preview-fail" v-else>文件暂不支持预览</div>
+			<div class="preview-fail" v-else>{{ $t('jyzx.online.noSee') }}</div>
 		</div>
 	</div>
 </template>

+ 52 - 31
TEAMModelOS/ClientApp/src/components/student-web/ClassRecord/ClassRecord.vue

@@ -126,7 +126,7 @@
                                                         <Icon type="ios-search" @click="openViewer(items.img)" />
                                                     </p>
                                                 </div>
-                                                
+
                                                 <!-- <div v-for="(rtItem, rtIndex) in items.pageData" :key="rtIndex + '' + index" class="record-data-item">
                                                     <span class="event-tag">{{ rtItem.Event }}</span>
                                                 </div> -->
@@ -202,7 +202,7 @@ export default {
         Receive,
         DataCount,
     },
-    data () {
+    data() {
         return {
             isLoad: false,
             player: undefined,
@@ -216,10 +216,10 @@ export default {
                 height: "450px",
                 controlBar: {
                     children: [// 写在这里,会在播放条上显示出来,并且是按照写的顺序显示位置。
-                        {name: "playToggle"}, //播放暂停按钮
-                        {name: "currentTimeDisplay"}, //当前播放时间
-                        {name: "progressControl"}, //播放进度条
-                        {name: "durationDisplay"}, //总时间
+                        { name: "playToggle" }, //播放暂停按钮
+                        { name: "currentTimeDisplay" }, //当前播放时间
+                        { name: "progressControl" }, //播放进度条
+                        { name: "durationDisplay" }, //总时间
                         {
                             name: "playbackRateMenuButton",
                             playbackRates: [0.5, 1, 1.5, 2, 2.5]
@@ -228,8 +228,8 @@ export default {
                             name: "volumePanel", //音量控制
                             inline: false, //不使用水平方式
                         },
-                        {name: "FullscreenToggle"}, //全屏
-                        {name: "DashBoardEchart"}
+                        { name: "FullscreenToggle" }, //全屏
+                        { name: "DashBoardEchart" }
                     ],
                 },
                 /* html5: {
@@ -266,13 +266,13 @@ export default {
             courseNow: undefined,
         }
     },
-    created () {
+    created() {
         this.hiTeachEvent = this.$GLOBAL.HI_TEACH_EVENT()
         this.events = Object.keys(this.hiTeachEvent)
         this.fnEvents = this.events.filter(key => this.hiTeachEvent[key].type === 'fn')
         this.recordInfo = this.$route.params.record
         this.courseNow = this.$route.params.courseNow
-        if(!this.recordInfo) {
+        if (!this.recordInfo) {
             this.$router.go(-1)
         } else {
             this.recordInfo.startTime = this.dateFormat(this.recordInfo.startTime)
@@ -284,13 +284,13 @@ export default {
             this.getPageList()
         }
     },
-    mounted () {
+    mounted() {
         // this.getVideo()
     },
     methods: {
         getVideo() {
             var that = this
-            this.player = videojs(document.getElementById("recordVideo"), this.playerOptions, function() {
+            this.player = videojs(document.getElementById("recordVideo"), this.playerOptions, function () {
                 this.on('error', (e) => {
                     that.hasVideo = false
                     that.isShowVd = false
@@ -298,7 +298,7 @@ export default {
             })
             //时间切片
             this.player.markers({
-                    markerStyle: {
+                markerStyle: {
                     width: "16px",
                     height: "16px",
                     top: "-22px",
@@ -333,7 +333,7 @@ export default {
 
                 //标记点击事件
                 onMarkerClick: function (marker) {
-                    
+
                 },
                 //视频播放到标记点触发的时间
                 onMarkerReached: function (marker) {
@@ -353,7 +353,7 @@ export default {
                     that.getCurPage(marker.page)
                 },
             });
-            
+
             this.isLoad = false
         },
         // 根据SokratesRecords.json处理page数据
@@ -395,7 +395,7 @@ export default {
                         let baseUrl = `${sas.url}/${sas.name}/records/${this.recordInfo.id}/IES/base.json?${sas.sas}`
                         this.baseData = JSON.parse(await this.$tools.getFile(baseUrl) || '{}')
                         this.baseData.student.forEach((item, index) => {
-                            if(item.name === this.$store.state.userInfo.name) {
+                            if (item.name === this.$store.state.userInfo.name) {
                                 this.nowStuInfo = item
                                 this.nowStuInfo.index = index
                             }
@@ -405,6 +405,16 @@ export default {
                     }
                     let r = this.sokratesRecords.find(item => item.Event === 'PgidList')
                     let pgids = r ? r.PgIdList : []
+
+                    //这里需要判断录制开始的pageid
+                    let startInfo = this.sokratesRecords.find(item => item.Event === 'EzsStartRecord')
+                    let startId = startInfo ? startInfo.Pgid : ''
+                    let startIndex = 0
+                    if (startId) {
+                        startIndex = pgids.findIndex(item => item === startId)
+                    }
+                    pgids = pgids.slice(startIndex)
+
                     let havePage = 0
                     pgids.forEach((item, index) => {
                         let page = {}
@@ -479,7 +489,7 @@ export default {
             let pageInfo = this.markers.find(item => {
                 return item.page === page
             })
-            if(pageInfo) {
+            if (pageInfo) {
                 this.player.currentTime(pageInfo.time)
             }
         },
@@ -491,7 +501,7 @@ export default {
             let pageInfo = this.markers.find(item => {
                 return item.page === page
             })
-            if(pageInfo) {
+            if (pageInfo) {
                 this.player.currentTime(pageInfo.time)
                 if (!this.openHtexViewer) {
                     this.player.play()
@@ -511,16 +521,29 @@ export default {
             this.player.play()
         },
         //查看电子笔记
-        viewENote() {
+        async viewENote() {
+            let eNote
             if (this.recordInfo.eNote) {
-                window.open('/web/viewer.html?file=' + encodeURIComponent(this.recordInfo.eNote))
+                eNote = this.recordInfo.eNote
             } else {
-                this.$Message.warning(this.$t('cusMgt.rcd.noNote'))
+                // let sasInfo = {}
+                // let blobInfo = this.recordInfo.scope === 'school' ? this.$store.state.user.schoolProfile : this.$store.state.user.userProfile
+                // sasInfo.sas = '?' + blobInfo.blob_sas
+                // sasInfo.name = this.recordInfo.scope ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId
+                // sasInfo.url = blobInfo.blob_uri.slice(0, blobInfo.blob_uri.lastIndexOf(sasInfo.name) - 1)
+                let sasInfo = await this.$tools.getBlobSas(this.recordInfo.scope === 'school' ? this.recordInfo.school : this.recordInfo.tmdid)
+                eNote = `${sasInfo.url}/${sasInfo.name}/records/${this.recordInfo.id}/Note.pdf${sasInfo.sas}`
             }
+            window.open('/web/viewer.html?file=' + encodeURIComponent(eNote))
+            // if (this.recordInfo.eNote) {
+            //     window.open('/web/viewer.html?file=' + encodeURIComponent(this.recordInfo.eNote))
+            // } else {
+            //     this.$Message.warning(this.$t('cusMgt.rcd.noNote'))
+            // }
         },
         //下载电子笔记
         async loadNote() {
-            if(this.recordInfo.eNote) {
+            if (this.recordInfo.eNote) {
                 // 已经有授权,在查看文件时不需要再次获取授权
                 let blobData = this.recordInfo.eNote
                 const downloadRes = async () => {
@@ -538,7 +561,7 @@ export default {
                 this.$Message.warning("暂无电子笔记")
             }
         },
-        openViewer(item){
+        openViewer(item) {
             this.$hevueImgPreview(item)
         },
         // 筛选
@@ -568,7 +591,7 @@ export default {
     },
     computed: {
         curImg() {
-            if (this.pageList[this.curPage]) {
+            if (this.pageList[this.curPage - 1]) {
                 return this.pageList[this.curPage - 1].img
             } else {
                 return ""
@@ -583,8 +606,7 @@ export default {
 </style>
 <style lang="less">
 .class-content {
-
-    .video-js .vjs-big-play-button{
+    .video-js .vjs-big-play-button {
         top: 50%;
         left: 50%;
         margin-left: -20px;
@@ -592,20 +614,19 @@ export default {
         display: none;
     }
 
-    .video-js .vjs-control-bar{
+    .video-js .vjs-control-bar {
         display: flex;
     }
 
-    
     .vjs-marker::after {
-        content: '';
+        content: "";
         height: 0px;
         width: 0px;
         border: 3px transparent solid;
         display: block;
         position: absolute;
         bottom: -10px;
-        z-index:-1;
+        z-index: -1;
         border-right: 8px solid transparent;
         border-top: 15px solid orange;
         border-left: 8px solid transparent;
@@ -620,7 +641,7 @@ export default {
         z-index: 101;
     }
 }
-.owner-student-client-icon{
+.owner-student-client-icon {
     font-size: 30px;
     padding: 5px;
     color: #ffffff;

+ 1 - 1
TEAMModelOS/ClientApp/src/components/student-web/HomeView/CourseListView.vue

@@ -1002,7 +1002,7 @@ export default {
         getRecordList() {
             this.recordList = []
             let param = {
-                tmdid: "",
+                tmdid: this.courseNow.teaId,
                 scope: this.courseNow.scope, //school:传school,private:传tmdid
                 school: "",
                 category: [],

+ 3 - 3
TEAMModelOS/ClientApp/src/components/student-web/SettingView/Setting.vue

@@ -315,7 +315,7 @@ export default {
             let srvAdr = this.config.srvAdr
             let host = srvAdr == 'Global' ? this.config.Global.coreAPIUrl : this.config.China.coreAPIUrl
             let clientId = srvAdr == 'Global' ? this.config.Global.clientID : this.config.China.clientID
-            let idToken = localStorage.getItem('id_token')
+            let idToken = localStorage.getItem('stu_id_token')
             let params = {
                 "grant_type": "get",
                 "nonce": "habook",
@@ -485,7 +485,7 @@ export default {
                 let srvAdr = this.config.srvAdr
                 let host = srvAdr == 'Global' ? this.config.Global.coreAPIUrl : this.config.China.coreAPIUrl
                 let clientId = srvAdr == 'Global' ? this.config.Gloabl.clientID : this.config.China.clientID
-                let idToken = localStorage.getItem('id_token')
+                let idToken = localStorage.getItem('stu_id_token')
 
                 let params = {
                     "nonce": "habook",
@@ -653,7 +653,7 @@ export default {
                     let srvAdr = _this.config.srvAdr
                     let host = srvAdr == 'Global' ? _this.config.Global.coreAPIUrl : _this.config.China.coreAPIUrl
                     let clientId = srvAdr == 'Global' ? _this.config.Gloabl.clientID : _this.config.China.clientID
-                    let idToken = localStorage.getItem('id_token')
+                    let idToken = localStorage.getItem('stu_id_token')
                     let params = {
                         "nonce": "habook", //任意字符串
                         "client_id": clientId,

+ 1 - 0
TEAMModelOS/ClientApp/src/locale/lang/en-US/schoolBaseInfo.js

@@ -115,6 +115,7 @@ export default {
   delTimeContent:'Are you sure you want to delete the current schedule?',
   setStartTitps:'Set as enrollment semester',
   periodCountTips:'The number of school systems is allocated based on school purchases, and schools can only edit school system names, not add or delete school system.',
+  cgCountTips:'學院數量根據學校購買進行分配,學校只能進行編輯學院名稱,不能新增和刪除學院。',
 
   // ClassroomSetting.vue
   classroomList: 'Classroom List',

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/en-US/survey.js

@@ -104,6 +104,6 @@ export default {
 	noMatchData:'No matching data',
 	getFileFailTip:'Failed to read data',
 	backToRecord:'Back to Activity Record',
-	noFoundAc:'Specified ID activity not found, please select again!'
+	noFoundAc:'Activity not found, please select again!'
 	
 }

+ 1 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/schoolBaseInfo.js

@@ -115,6 +115,7 @@ export default {
   delTimeContent: '是否确认删除当前时段?',
   setStartTitps:'设置为入学期',
   periodCountTips:'学段数量根据学校购买进行分配,学校只能进行编辑学段名称,不能新增和删除学段。',
+  cgCountTips:'学院数量根据学校购买进行分配,学校只能进行编辑学院名称,不能新增和删除学院。',
 
   // ClassroomSetting.vue
   classroomList: '教室列表',

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-CN/survey.js

@@ -104,6 +104,6 @@ export default {
 	noMatchData:'未匹配数据',
 	getFileFailTip:'数据读取失败',
 	backToRecord:'返回活动记录',
-	noFoundAc:'未查找到指定ID活动,请重新选择!'
+	noFoundAc:'该活动已被删除或丢失,请返回重新选择!'
 	
 }

+ 1 - 0
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/schoolBaseInfo.js

@@ -115,6 +115,7 @@ export default {
   delTimeContent:'是否確認刪除當前時段? ',
   setStartTitps:'設置為入學期',
   periodCountTips:'學段數量根據學校購買進行分配,學校只能進行編輯學段名稱,不能新增和刪除學段。',
+  cgCountTips:'學院數量根據學校購買進行分配,學校只能進行編輯學院名稱,不能新增和刪除學院。',
 
   // ClassroomSetting.vue
   classroomList: '教室清單',

+ 1 - 1
TEAMModelOS/ClientApp/src/locale/lang/zh-TW/survey.js

@@ -104,5 +104,5 @@ export default {
 	noMatchData:'未配對到數據',
 	getFileFailTip:'資料讀取失敗',
 	backToRecord:'返回活動記錄',
-	noFoundAc:'未找到指定ID的活動,請重新選擇!'
+	noFoundAc:'該活動已被刪除或丟失,請返回重新選擇!'
 }

+ 1 - 1
TEAMModelOS/ClientApp/src/router/routes.js

@@ -1009,7 +1009,7 @@ export const routes = [{
 	{
 		path: 'teachCenter',
 		name: 'teachCenter',
-		component: resolve => require(['@/view/teachCenter/TeaResCenter.vue'], resolve),
+		component: resolve => require(['@/view/teachCenter/TeaResCenterNew.vue'], resolve),
 		// meta: {
 		// 	activeName: 'teachCenter'
 		// }

+ 41 - 2
TEAMModelOS/ClientApp/src/utils/directive.js

@@ -8,7 +8,7 @@ const trigger = (el, type) => {
     el.dispatchEvent(e)
 }
 
-
+//普通特殊字符过滤
 const specialChar = {
     bind: function (el, binding, vnode) {
         // 正则规则可根据需求自定义
@@ -44,4 +44,43 @@ const specialChar = {
     },
 }
 
-export default specialChar
+//文件名特殊字符过滤
+const fileName = {
+    bind: function (el, binding, vnode) {
+        // 正则规则可根据需求自定义
+        // var regRule = /[`~!@#$%^&*()\-+=<>?:"{}|,.\/;'\\[\]·~!@#¥%……&*()——\-+={}|《》?:“”【】、;‘’,。、]/g
+        let regRule = /[`~?$^&*\|\/\\:"<>]/g
+        let isChinese = false
+        let $inp = findEle(el, 'input')
+        el.$inp = $inp
+        if ($inp) {
+            $inp.handle = function () {
+                if (!isChinese) {
+                    let val = $inp.value
+                    $inp.value = val.replace(regRule, '')
+                    trigger($inp, 'input')
+                }
+            }
+            $inp.chineseStart = function () {
+                isChinese = true
+            }
+            $inp.chineseEnd = function () {
+                isChinese = false
+            }
+            $inp.addEventListener('keyup', $inp.handle)
+            $inp.addEventListener('compositionstart', $inp.chineseStart)
+            $inp.addEventListener('compositionend', $inp.chineseEnd)
+        }
+    },
+    unbind: function (el) {
+        el.$inp && el.$inp.removeEventListener('keyup', el.$inp.handle)
+        el.$inp && el.$inp.removeEventListener('compositionend', el.$inp.chineseStart)
+        el.$inp && el.$inp.removeEventListener('compositionstart', el.$inp.chineseStart)
+        // el.$inp && el.$inp.removeEventListener('keydown', el.$inp.handle)
+    },
+}
+
+
+export {
+    specialChar, fileName
+}

+ 6 - 5
TEAMModelOS/ClientApp/src/view/ability/Review.vue

@@ -39,8 +39,8 @@
                 </div>
               </div>
             </div>
-            <p class="appraise-title" v-if="mode !== 'edit'"><span style="font-size: 16px;font-weight: bold;">{{ mode === 'self' ? $t('ability.review.tip1') : $t('ability.review.tip2')}}</span> {{ $t('ability.review.tip3') }}</p>
-            <div class="unit-item-appraise" v-if="mode !== 'edit'">
+            <p class="appraise-title"><span style="font-size: 16px;font-weight: bold;">{{ mode === 'self' ? $t('ability.review.tip1') : $t('ability.review.tip2')}}</span> {{ $t('ability.review.tip3') }}</p>
+            <div class="unit-item-appraise">
               <!-- 优秀 -->
               <div class="appraise-block" v-if="task.titles.length">
                 <p class="title">
@@ -73,7 +73,7 @@
                 </RadioGroup>
               </div>
             </div>
-            <div class="appraise-result" v-if="mode !== 'edit'">
+            <div class="appraise-result">
               <span>{{ isSelfMode ? '自评结果' : $t('ability.result') }}:</span>
               <span class="good" v-if="appraiseResultArr[index] === 'good'">
                 <Icon type="md-happy" size="22" />{{ $t('ability.good') }}
@@ -217,7 +217,7 @@ export default {
       if (this.finalUpload.some(i => i.urls.length === 0)) {
         this.$Message.warning(this.$t('ability.review.tip4'))
         this.isBtnLoading = false
-      } else if (this.mode === 'self' && this.finalResult === 0) {
+      } else if (this.isSelfMode && this.finalResult === 0) {
         this.$Message.warning(this.$t('ability.review.tip5'))
         this.isBtnLoading = false
       } else {
@@ -446,7 +446,8 @@ export default {
       console.log(abilityDetail)
 	  // 如果是编辑状态 则需要把自评的结果回显
       this.appraiseResultArr = this.mode === 'edit' ? this.reviewData.uploads.map(i => ['bad','normal','good'][i.score]) : abilityDetail.stds.map(i => 'bad')
-	  this.finalResult = this.mode === 'edit' ? this.reviewData.self : 0
+	  // this.finalResult = this.mode === 'edit' ? this.reviewData.self : 0
+	  this.finalResult = 0
       this.appraiseList = abilityDetail.stds.map(i => [])
       this.isAllNormalArr = abilityDetail.stds.map(i => false)
       this.stdFileArr = abilityDetail.stds.map(i => [])

+ 28 - 6
TEAMModelOS/ClientApp/src/view/classrecord/ClassRecord.vue

@@ -81,7 +81,7 @@
                         </div> -->
                         <vuescroll ref="datawrap">
                             <template v-for="(item,index) in pageList">
-                                <div v-if="item.pageData.length" class="page-item" :key="index" :id="'page'+(item.page)">
+                                <div v-if="item.pageData" class="page-item" :key="index" :id="'page'+(item.page)">
                                     <div class="page-info-wrap">
                                         <span class="page-tag" @click="toVideo(index+1,$event)" :ref="'page'+(index+1)">
                                             {{`${$t('cusMgt.rcd.cw')}${item.page}${$t('cusMgt.rcd.page')}`}}
@@ -96,7 +96,7 @@
                                         </Timeline> -->
                                     </div>
                                     <div class="record-data-wrap">
-                                        <!-- <EmptyData v-if="!" :textContent="$t('cusMgt.rcd.pageNoRcd')"></EmptyData> -->
+                                        <EmptyData v-if="!item.pageData.length" :textContent="$t('cusMgt.rcd.pageNoRcd')"></EmptyData>
                                         <!-- <template v-else> -->
                                         <!-- 互动数据 -->
                                         <div v-for="event in item.pageData" :key="event.Time">
@@ -145,7 +145,7 @@ export default {
     },
     data() {
         return {
-            baseData:{}, //base.json
+            baseData: {}, //base.json
             pushData: [],//push.json
             irsData: [],//irs.json
             taskData: [],//task.json
@@ -277,6 +277,16 @@ export default {
                     console.log(this.pushData)
                     let r = this.sokratesRecords.find(item => item.Event === 'PgidList')
                     let pgids = r ? r.PgIdList : []
+
+                    //这里需要判断录制开始的pageid
+                    let startInfo = this.sokratesRecords.find(item => item.Event === 'EzsStartRecord')
+                    let startId = startInfo ? startInfo.Pgid : ''
+                    let startIndex = 0
+                    if (startId) {
+                        startIndex = pgids.findIndex(item => item === startId)
+                    }
+                    pgids = pgids.slice(startIndex)
+
                     pgids.forEach((item, index) => {
                         let page = {}
                         page.id = item
@@ -331,11 +341,23 @@ export default {
         },
         //查看电子笔记
         viewENote() {
+            let eNote
             if (this.recordInfo.eNote) {
-                window.open('/web/viewer.html?file=' + encodeURIComponent(this.recordInfo.eNote))
+                eNote = this.recordInfo.eNote
             } else {
-                this.$Message.warning(this.$t('cusMgt.rcd.noNote'))
+                let sasInfo = {}
+                let blobInfo = this.recordInfo.scope === 'school' ? this.$store.state.user.schoolProfile : this.$store.state.user.userProfile
+                sasInfo.sas = '?' + blobInfo.blob_sas
+                sasInfo.name = this.recordInfo.scope ? this.$store.state.userInfo.schoolCode : this.$store.state.userInfo.TEAMModelId
+                sasInfo.url = blobInfo.blob_uri.slice(0, blobInfo.blob_uri.lastIndexOf(sasInfo.name) - 1)
+
+                eNote = `${sasInfo.url}/${sasInfo.name}/records/${this.recordInfo.id}/Note.pdf${sasInfo.sas}`
             }
+            window.open('/web/viewer.html?file=' + encodeURIComponent(eNote))
+            // if (this.recordInfo.eNote) {
+            // } else {
+            //     this.$Message.warning(this.$t('cusMgt.rcd.noNote'))
+            // }
         },
         //点击视频切片
         getCurPage(page) {
@@ -404,7 +426,7 @@ export default {
     },
     computed: {
         curImg() {
-            if (this.pageList[this.curPage]) {
+            if (this.pageList[this.curPage - 1]) {
                 return this.pageList[this.curPage - 1].img
             } else {
                 return ""

+ 1 - 1
TEAMModelOS/ClientApp/src/view/classrecord/eventchart/PopQues.vue

@@ -1,7 +1,7 @@
 <template>
     <div class="pop-ques-wrap">
         <TeacherClient></TeacherClient>
-        <p class="event-type">{{evtType == 'PopQuesLoad' ? '即问即答' : '二次作答'}}</p>
+        <p class="event-type">{{evtType == 'PopQuesLoad' ? $t('studentWeb.hiteachNote.qA') : $t('studentWeb.hiteachNote.qaAgain')}}</p>
         <OptionCount :optionCount="optionData" :answer="answer"></OptionCount>
         <CorrectRate :correctData="correctData"></CorrectRate>
     </div>

+ 3 - 1
TEAMModelOS/ClientApp/src/view/evaluation/bank/PaperDownload.vue

@@ -383,7 +383,9 @@
 							that.isDownloading = false
 							that.printMode = 'A4'
 						}
-
+					}).catch(e => {
+						this.$Message.warning('试卷数据异常,无法生成!')
+						this.isDownloading = false
 					})
 			},
 			/* 对试卷题目进行题型分组 */

+ 1 - 0
TEAMModelOS/ClientApp/src/view/evaluation/index/CreatePaper.vue

@@ -851,6 +851,7 @@
 								await this.saveImportPoints([...new Set(this.importKnowledges)], paperItem)
 							}
 						}
+						this.$Spin.hide()
 						this.$Message.success(this.$t('evaluation.paperList.saveSuc'))
 						this.isLoading = false
 						this.$router.push({

+ 1 - 1
TEAMModelOS/ClientApp/src/view/newcourse/MyCourse.vue

@@ -358,7 +358,7 @@
                         </RadioGroup>
                     </FormItem>
                     <FormItem :label="$t('cusMgt.name')" v-if="type == 'create'">
-                        <Input v-special-char v-model="listName" :placeholder="$t('cusMgt.nameHolder')" style="width: 300px" />
+                        <Input v-file-name v-model="listName" :placeholder="$t('cusMgt.nameHolder')" style="width: 300px" />
                     </FormItem>
                     <FormItem :label="$t('cusMgt.listLabel')" v-else>
                         <Select v-model="listId" style="width:300px">

+ 2 - 0
TEAMModelOS/ClientApp/src/view/schoolmgmt/SystemSetting/SystemSetting.less

@@ -171,6 +171,7 @@
 }
 .period-wrap {
     height: 100%;
+    background: white;
     // padding-left: 15px;
 }
 
@@ -307,6 +308,7 @@
         overflow: hidden;
         display: inline-block;
         border: 1px solid var(--border-color);
+        background: white;
         &:hover{
             box-shadow: 0 0px 8px 1px var(--card-shadow);
         }

+ 7 - 5
TEAMModelOS/ClientApp/src/view/schoolmgmt/SystemSetting/SystemSetting.vue

@@ -58,18 +58,20 @@
             </div>
 
         </div>
-        <!-- 学段管理 -->
+        <!-- 学段/学院管理 -->
         <div class="sm-system-body custom-iview-split disabled-iview-select text-cursor-disabled" v-show="tab == 'period'">
             <Split v-model="split1">
                 <!--学段列表-->
                 <div slot="left" class="period-wrap">
                     <div class="col-title">
-                        <span>{{$t('schoolBaseInfo.periodSettingLabel')}}</span>
+                        <span>
+                            {{schoolSetting.type == 1 ? $t('schoolBaseInfo.periodSettingLabel') : $t('schoolBaseInfo.cgMgt')}}
+                        </span>
                         <Tooltip :max-width="180" transfer>
                             <p slot="content">
-                                {{$t('schoolBaseInfo.periodCountTips')}}
+                                {{schoolSetting.type == 1 ? $t('schoolBaseInfo.periodCountTips') : $t('schoolBaseInfo.cgCountTips')}}
                             </p>
-                            <Icon type="md-information-circle" style="margin-left:5px" />
+                            <Icon type="md-information-circle" style="margin-left:0px" />
                         </Tooltip>
 
                         <div class="action-btx-box">
@@ -168,7 +170,7 @@
                                     <p class="block-title bf-color3">
                                         {{$t('schoolBaseInfo.gradeSetting')}}
                                         <Tooltip :content="$t('schoolBaseInfo.gradeTips')" max-width="200">
-                                            <Icon type="ios-information-circle-outline" color="#1cc0f3" size="16" style="margin-right:5px;cursor:pointer;"/>
+                                            <Icon type="ios-information-circle-outline" color="#1cc0f3" size="16" style="margin-right:5px;cursor:pointer;" />
                                         </Tooltip>
                                         <span class="block-action-box">
                                             <Icon type="md-add" @click.stop="addGrade" class="action-btn-icon" v-if="$access.ability('admin','schoolSetting-upd').validateAll" />

+ 1 - 1
TEAMModelOS/ClientApp/src/view/student-account/class/ClassMgt.vue

@@ -91,7 +91,7 @@
                             <Form v-if="classListShow[curClassIndex]" ref="edClassInfo" :model="classListShow[curClassIndex]" :rules="classValidate" style="padding-top:20px;">
                                 <FormItem prop="name" @click.native.stop class="requird-color">
                                     <span slot="label" class="class-attr-wrap-label">{{$t('schoolBaseInfo.className')}}</span>
-                                    <Input v-special-char @on-change="watchUpdate" :disabled="editStatus" v-model="classListShow[curClassIndex].name" clearable :placeholder="$t('schoolBaseInfo.classroomNameHolder')" />
+                                    <Input v-file-name @on-change="watchUpdate" :disabled="editStatus" v-model="classListShow[curClassIndex].name" clearable :placeholder="$t('schoolBaseInfo.classroomNameHolder')" />
                                 </FormItem>
 
                                 <FormItem prop="year" @click.native.stop class="requird-color">

+ 1 - 1
TEAMModelOS/ClientApp/src/view/student-account/stulist/MgtStuList.vue

@@ -92,7 +92,7 @@
                     </Select>
                 </FormItem>
                 <FormItem :label="$t('cusMgt.name')" prop="listName">
-                    <Input v-special-char v-model="listInfo.listName" :placeholder="$t('cusMgt.nameHolder')"></Input>
+                    <Input v-file-name v-model="listInfo.listName" :placeholder="$t('cusMgt.nameHolder')"></Input>
                 </FormItem>
             </Form>
         </Modal>

Файловите разлики са ограничени, защото са твърде много
+ 1184 - 0
TEAMModelOS/ClientApp/src/view/teachCenter/TeaResCenterNew.vue


+ 1 - 1
TEAMModelOS/ClientApp/src/view/teachermgmt/components/userList/Index.vue

@@ -118,7 +118,7 @@
 </style>
 <template>
     <div class="userList">
-        <Loading v-if="isloading == true"></Loading>
+        <Loading v-if="isloading"></Loading>
         <!-- 使用者列表 -->
         <div class="userLists" :class="{ isSetting: authMulti || isOpenSpaceAuth == true }">
             <div class="serch-box">

+ 1 - 0
TEAMModelOS/Controllers/Client/HiTeachController.cs

@@ -130,6 +130,7 @@ namespace TEAMModelOS.Controllers.Client
                 }
                 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 });
             }

+ 222 - 0
TEAMModelOS/Controllers/XTest/FixDataController.cs

@@ -30,6 +30,7 @@ using Microsoft.Extensions.Configuration;
 using TEAMModelOS.Models;
 using System.Text.RegularExpressions;
 using TEAMModelOS.SDK.Services;
+using Azure.Messaging.ServiceBus;
 
 namespace TEAMModelOS.Controllers
 {
@@ -1825,6 +1826,227 @@ namespace TEAMModelOS.Controllers
             }
             return Ok(schools);
         }
+
+        /// <summary>
+        /// 给学校空间设置1024T,按区域。
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [HttpPost("fix-school-subjects-type")]
+        public async Task<IActionResult> FixSchoolSubjectsType(JsonElement json)
+        {
+            string sql = " SELECT distinct value(c)  FROM c join p in  c. period join s in p.subjects where s.type=0 ";
+            List<School> schools = new List<School>();
+            await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIterator<School>(queryText: sql, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
+            {
+                schools.Add(item);
+            }
+            schools.ForEach(x => {
+                x.period.ForEach(p => {
+                    p.subjects.ForEach(s => {
+                        if (s.type == 0)
+                        {
+                            s.type = 1;
+                        }
+                    });
+                });
+            });
+            foreach (var item in schools)
+            {
+                await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReplaceItemAsync(item, item.id, new PartitionKey(item.code));
+            }
+            return Ok(schools);
+        }
+
+
+        /// <summary>
+        /// 给学校空间设置1024T,按区域。
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [HttpPost("fix-school-lesson-record")]
+        public async Task<IActionResult> FixSchoolLessonRecord(JsonElement json)
+        {
+            var client = _azureCosmos.GetCosmosClient();
+            string sql = " SELECT distinct value(c)  FROM c  where c.pk='LessonRecord' and  c.code<>'LessonRecord-ydzt' ";
+            List<LessonRecord> lessonRecords = new List<LessonRecord>();
+            await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIterator<LessonRecord>(queryText: sql,requestOptions:new QueryRequestOptions {/* PartitionKey = new PartitionKey("LessonRecord-ydzt")*/ }))
+            {
+                lessonRecords.Add(item);
+            }
+            //await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetItemQueryIterator<LessonRecord>(queryText: sql, requestOptions: new QueryRequestOptions { }))
+            //{
+            //    lessonRecords.Add(item);
+            //}
+            HashSet<string> courseIds = new HashSet<string>();
+            lessonRecords.ForEach(item => {
+                if (!string.IsNullOrWhiteSpace(item.courseId)) {
+                    courseIds.Add(item.courseId);
+                }
+            });
+            List<Course> courses = new List<Course>();
+            if (courseIds.Any()) {
+                string sqlCourse = $" SELECT distinct value(c)  FROM c  where c.pk='Course' and c.id in ({string.Join(",", courseIds.Select(x => $"'{x}'"))}) ";
+                await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIterator<Course>(queryText: sqlCourse, requestOptions: new QueryRequestOptions { }))
+                {
+                    courses.Add(item);
+                }
+                await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetItemQueryIterator<Course>(queryText: sqlCourse, requestOptions: new QueryRequestOptions { }))
+                {
+                    courses.Add(item);
+                }
+            }
+
+            HashSet<string> schoolIds = new HashSet<string>();
+            lessonRecords.ForEach(item => {
+                if (!string.IsNullOrWhiteSpace(item.school))
+                {
+                    schoolIds.Add(item.school);
+                }
+            });
+            string sqlSchool = $" SELECT distinct value(c)  FROM c  where  c.id in ({string.Join(",", schoolIds.Select(x => $"'{x}'"))})   ";
+            List<School> schools = new List<School>();
+            await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetItemQueryIterator<School>(queryText: sqlSchool, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") }))
+            {
+                schools.Add(item);
+            }
+            var lists =  lessonRecords.Where(x => !string.IsNullOrWhiteSpace(x.school)).GroupBy(y => y.school).Select(a => new { key = a.Key, list = a.ToList() });
+            Dictionary<string, List<GroupListDto>> dict = new Dictionary<string, List<GroupListDto>>();
+            foreach (var item in lists) {
+                var gids= item.list.SelectMany(x => x.groupIds).Where(y=>!string.IsNullOrWhiteSpace(y));
+                HashSet<string> grades = new HashSet<string>();
+                List<GroupListDto> groups = await GroupListService.GetGroupListListids(client, _dingDing, gids.ToList(), item.key);
+                List<GroupListDto> groupLists = groups?.FindAll(x => !string.IsNullOrEmpty(x.periodId)  && !string.IsNullOrEmpty(x.school));
+                dict.Add(item.key, groupLists);
+            }
+            foreach (var lessonRecord in lessonRecords) {
+                LessonRecord old = lessonRecord.ToJsonString().ToObject<LessonRecord>();
+                if (string.IsNullOrWhiteSpace(lessonRecord.courseId)) {
+                    var course = courses.Find(x => x.id.Equals(lessonRecord.courseId));
+                    if (course != null)
+                    {
+                        lessonRecord.periodId = course.period?.id;
+                        lessonRecord.subjectId = course.subject?.id;
+                    }
+                }
+                //处理课堂选用的名单
+                if (lessonRecord.groupIds.IsNotEmpty()  && !string.IsNullOrWhiteSpace(lessonRecord.school) && !string.IsNullOrWhiteSpace(lessonRecord.periodId))
+                {
+                    HashSet<string> grades = new HashSet<string>();
+                    List<GroupListDto> groupLists = null;
+                    dict.TryGetValue(lessonRecord.school, out groupLists);
+                    if (groupLists.IsNotEmpty())
+                    {
+                        var gplist =  groupLists.FindAll(x=>lessonRecord.groupIds.Contains(x.id));
+                        School schoolObj = schools.Find(x => x.id.Equals(lessonRecord.school));
+                        if (schoolObj != null)
+                        {
+                            //年级算法
+                            var period = schoolObj.period.Find(x => x.id.Equals(lessonRecord.periodId));
+                            int? Count = period?.grades?.Count;
+                            if (Count.HasValue)
+                            {
+                                int Month = DateTimeOffset.UtcNow.Month;
+                                int Year = DateTimeOffset.UtcNow.Year;
+                                int dis = 0;
+                                int index = -1;
+                                
+                                foreach (int year in gplist.Select(x => x.year))
+                                {
+                                    int grade;
+                                    if (Month >= 1 && Month <= 6)
+                                    {
+                                        grade = (Year - year - 1) % Count.Value;
+                                    }
+                                    else
+                                    {
+                                        grade = (Year - year) % Count.Value;
+                                    }
+                                    grades.Add($"{grade}");
+                                }
+                            }
+                        }
+                    }
+                    lessonRecord.grade= grades.ToList();
+                }
+                string scope = lessonRecord.scope;
+                string tmdid =lessonRecord.tmdid;
+                string lessonId=lessonRecord.id;
+                string school=lessonRecord.school;
+                string tbname="";
+                string code;
+                string blobname="";
+                   
+                if ($"{scope}".Equals("school") && !string.IsNullOrEmpty($"{school}"))
+                {
+                    blobname = $"{school}";
+                    code = $"LessonRecord-{school}";
+                    tbname = "School";
+                }
+                else if ($"{scope}".Equals("private"))
+                {
+                    blobname = $"{tmdid}";
+                    code = $"LessonRecord-{tmdid}";
+                    tbname = "Teacher";
+                }
+                //如果有更新 则去读取/{_lessonId}/IES/base.json
+                try
+                {
+                    BlobDownloadResult baseblobDownload = await _azureStorage.GetBlobContainerClient(blobname).GetBlobClient($"/records/{lessonId}/IES/base.json").DownloadContentAsync();
+                    LessonBase lessonBase = baseblobDownload.Content.ToObjectFromJson<LessonBase>();
+                    if (lessonBase != null && lessonBase.summary != null)
+                    {
+                        lessonRecord.attendCount = lessonBase.summary.attendCount;
+                        lessonRecord.clientCount = lessonBase.summary.clientCount;
+                        lessonRecord.attendRate = lessonBase.summary.attendRate;
+                        lessonRecord.groupCount = lessonBase.summary.groupCount;
+                        lessonRecord.collateTaskCount = lessonBase.summary.collateTaskCount;
+                        lessonRecord.collateCount = lessonBase.summary.collateCount;
+                        lessonRecord.pushCount = lessonBase.summary.pushCount;
+                        lessonRecord.totalPoint = lessonBase.summary.totalPoint;
+                        lessonRecord.examQuizCount = lessonBase.summary.examQuizCount;
+                        lessonRecord.interactionCount = lessonBase.summary.interactionCount;
+                        lessonRecord.examPointRate = lessonBase.summary.examPointRate;
+                        lessonRecord.clientInteractionCount = lessonBase.summary.clientInteractionCount;
+                        lessonRecord.clientInteractionAverge = lessonBase.summary.clientInteractionAverge;
+                        lessonRecord.examCount = lessonBase.summary.examCount;
+                        lessonRecord.totalInteractPoint = lessonBase.summary.totalInteractPoint;
+                    }
+                    long? size = await _azureStorage.GetBlobContainerClient(blobname).GetBlobsSize($"records/{lessonId}");
+                    Bloblog bloblog = new Bloblog
+                    {
+                        id = lessonRecord.id,
+                        code = $"Bloblog-{blobname}",
+                        name = lessonRecord.name,
+                        pk = "Bloblog",
+                        time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                        type = "records",
+                        url = $"records/{lessonId}",
+                        subjectId = new List<string> { lessonRecord.subjectId },
+                        periodId = new List<string> { lessonRecord.periodId },
+                        size = size.HasValue ? size.Value : 0,
+                    };
+                    await client.GetContainer(Constant.TEAMModelOS, tbname).UpsertItemAsync(bloblog);
+                    var messageBlob = new ServiceBusMessage(new { id = Guid.NewGuid().ToString(), progress = "update", root = "records", name = $"{blobname}" }.ToJsonString()); ;
+                    messageBlob.ApplicationProperties.Add("name", "BlobRoot");
+                    var ActiveTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");
+                    await _serviceBus.GetServiceBusClient().SendMessageAsync(ActiveTask, messageBlob);
+                }
+                catch (RequestFailedException ex) when (ex.Status == 404)
+                {
+                }
+                catch (Exception ex)
+                {
+                    await _dingDing.SendBotMsg($"{Environment.GetEnvironmentVariable("Option:Location")}课程读取base.json,{lessonId}\n{ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                }
+                await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, tbname).ReplaceItemAsync<LessonRecord>(lessonRecord, lessonId, new PartitionKey(lessonRecord.code));
+                LessonDis lessonDis = new LessonDis();
+                //计算课堂更新前后的差值
+                lessonDis = LessonService.DisLessonCount(old, lessonRecord, lessonDis);
+                await LessonService.FixLessonCount(client, _dingDing, lessonRecord, old, lessonDis);
+            }
+            return Ok(new { lessonRecords });
+        }
         public record CorrectStu
         {
             public string id { get; set; }