ソースを参照

Merge branch 'develop5.0-tmd' of http://106.12.23.251:10000/TEAMMODEL/TEAMModelOS into develop5.0-tmd

liqk 4 年 前
コミット
b1f480cfd5
30 ファイル変更671 行追加376 行削除
  1. 21 1
      TEAMModelFunction/TriggerCorrect.cs
  2. 2 2
      TEAMModelFunction/TriggerExam.cs
  3. 8 0
      TEAMModelOS.SDK/Models/Cosmos/Api/OpenApi.cs
  4. 4 1
      TEAMModelOS.SDK/Models/Cosmos/Common/Inner/SyllabusTree.cs
  5. 61 0
      TEAMModelOS.SDK/Models/Cosmos/Common/Scoring.cs
  6. 1 0
      TEAMModelOS.SDK/Models/Cosmos/Common/Syllabus.cs
  7. 1 1
      TEAMModelOS.SDK/Models/Cosmos/School/Class.cs
  8. 14 0
      TEAMModelOS.SDK/Models/Table/tmdInfo.cs
  9. 7 0
      TEAMModelOS/ClientApp/src/api/openMgmt.js
  10. 9 4
      TEAMModelOS/ClientApp/src/components/syllabus/DragTree.vue
  11. 9 11
      TEAMModelOS/ClientApp/src/components/syllabus/InviteTeacher.vue
  12. 2 1
      TEAMModelOS/ClientApp/src/locale/lang/zh-CN/settings.js
  13. 1 1
      TEAMModelOS/ClientApp/src/view/answersheet/BaseEditor.vue
  14. 14 9
      TEAMModelOS/ClientApp/src/view/answersheet/SheetObjective.vue
  15. 3 1
      TEAMModelOS/ClientApp/src/view/evaluation/bank/TestPaperList.vue
  16. 0 1
      TEAMModelOS/ClientApp/src/view/evaluation/bank/index.vue
  17. 9 1
      TEAMModelOS/ClientApp/src/view/evaluation/index/CreateExercises.vue
  18. 4 57
      TEAMModelOS/ClientApp/src/view/settings/OpenMgmt2.css
  19. 2 71
      TEAMModelOS/ClientApp/src/view/settings/OpenMgmt2.less
  20. 180 65
      TEAMModelOS/ClientApp/src/view/settings/OpenMgmt2.vue
  21. 13 0
      TEAMModelOS/ClientApp/src/view/syllabus/Syllabus.less
  22. 85 20
      TEAMModelOS/ClientApp/src/view/syllabus/Syllabus.vue
  23. 33 6
      TEAMModelOS/Controllers/Analysis/AnalysisController.cs
  24. 1 0
      TEAMModelOS/Controllers/Analysis/ClassAys.cs
  25. 1 1
      TEAMModelOS/Controllers/Analysis/GradeAys.cs
  26. 91 23
      TEAMModelOS/Controllers/Common/ExamController.cs
  27. 0 15
      TEAMModelOS/Controllers/Syllabus/CoeditController.cs
  28. 70 61
      TEAMModelOS/Controllers/Syllabus/ShareController.cs
  29. 20 18
      TEAMModelOS/Controllers/Syllabus/SyllabusController.cs
  30. 5 5
      TEAMModelOS/Controllers/Syllabus/VolumeController.cs

+ 21 - 1
TEAMModelFunction/TriggerCorrect.cs

@@ -10,6 +10,8 @@ using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Helper.Common.CollectionHelper;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos;
+using TEAMModelOS.SDK.Models.Cosmos.Common;
+using TEAMModelOS.SDK.Models.Table;
 
 namespace TEAMModelFunction
 {
@@ -129,12 +131,30 @@ namespace TEAMModelFunction
                                     }
                                 }
                                 List<Task<bool>> tasks = new List<Task<bool>>();
+                                //初始化老师阅卷记录
+                                List<tmdInfo> tmds = new List<tmdInfo>();
+                                for (int i = 0; i < correct.num; i++) {
+                                    tmdInfo fo = new tmdInfo();
+                                    tmds.Add(fo);
+                                }
                                 foreach (ExamClassResult examClass in classResults)
                                 {
                                     foreach (string stuId in examClass.studentIds)
                                     {
                                         int index = examClass.studentIds.IndexOf(stuId);
-                                        tasks.Add(redisClient.HashSetAsync($"Exam:Scoring:{eid}-{subjectId}", stuId, new { tmdId = "" , ans = examClass.studentAnswers[index].Count > 0 ? examClass.studentAnswers[index][0] : "", score = examClass.studentScores[index] }.ToJsonString()));
+                                        if (index > -1) {
+                                            Scoring sc = new Scoring
+                                            {
+                                                blob = examClass.studentAnswers[index].Count > 0 ? examClass.studentAnswers[index][0] : "",
+                                                stuId =stuId,
+                                                examId = eid,
+                                                subjectId = subjectId,
+                                                scores = examClass.studentScores[index]
+                                            };
+                                        }
+                                        
+
+                                        tasks.Add(redisClient.HashSetAsync($"Exam:Scoring:{eid}-{subjectId}", stuId, new { tmdId = tmds, ans = examClass.studentAnswers[index].Count > 0 ? examClass.studentAnswers[index][0] : "", score = examClass.studentScores[index] }.ToJsonString()));
                                     }
 
                                 }

+ 2 - 2
TEAMModelFunction/TriggerExam.cs

@@ -222,8 +222,8 @@ namespace TEAMModelFunction
                                                             int month = DateTimeOffset.UtcNow.Month;
                                                             int day = DateTimeOffset.UtcNow.Day;
                                                             int time =  month > semester.month ?  0 :  1;
-                                                            int eyear = classroom.year - time;
-                                                            result.gradeId = (year - eyear).ToString();
+                                                            int eyear = year - time;
+                                                            result.gradeId = (eyear - classroom.year).ToString();
                                                         }
                                                     }
                                                 }

+ 8 - 0
TEAMModelOS.SDK/Models/Cosmos/Api/OpenApi.cs

@@ -45,6 +45,10 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         public string descr { get; set; }
         public int auth { get; set; }
+        /// <summary>
+        /// r,w,d,l
+        /// </summary>
+        public string type { get; set; }
     }
     [TableName(Name = "OpenApi")]
     public class Webhook : TableEntity
@@ -71,6 +75,10 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         public string descr { get; set; }
         public int auth { get; set; }
+        /// <summary>
+        /// r,w,d,l
+        /// </summary>
+        public string type { get; set; }
     }
     public class OpenApp : CosmosEntity {
         /// <summary>

+ 4 - 1
TEAMModelOS.SDK/Models/Cosmos/Common/Inner/SyllabusTree.cs

@@ -23,7 +23,10 @@ namespace TEAMModelOS.SDK.Models
         /// 册别的id
         /// </summary>
         public string volumeId { get; set; }
-       // public string code { get; set; }
+        /// <summary>
+        /// 校本课纲时传入 学校编码,私人课纲时传入醍摩豆ID
+        /// </summary>
+        public string codeval { get; set; }
         public string scope { get; set; }
         public  List<SyllabusTree>  trees  { get; set; }
 

+ 61 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/Scoring.cs

@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Models.Cosmos.Common
+{
+    public class Scoring : CosmosEntity
+    {
+        public Scoring()
+        {
+            pk = "Scoring";
+        }
+        public string stuId { get; set; }
+        public string examId { get; set; }
+        public string subjectId { get; set; }
+        public List<Item> items { get; set; } = new List<Item>();
+        public string blob { get; set; }
+        public List<string> tIds { get; set; } = new List<string>();
+        public List<string> marks { get; set; } = new List<string>();
+        public List<double> scores { get; set; } = new List<double>();
+    }
+
+    public class Item
+    {
+        public List<Info> scores { get; set; } = new List<Info>();
+        //原题的配分
+        public double ssc { get; set; }
+        //public string tmdId { get; set; }
+        public bool flag
+        {
+            get
+            {
+                if (scores.Count > 2)
+                {
+                    //List<double> sc = scores.Select(s => s.sc).ToList();
+                    double diff = Math.Abs(scores.Select(s => s.sc).ToList().Aggregate((i, j) => (i - j) * 6));
+                    if (diff > ssc)
+                    {
+                        return false;
+                    }
+                    else {
+                        return true;
+                    }
+                    
+                }
+                else
+                {
+                    return true;
+                }
+
+            }
+        }
+
+    }
+    public class Info { 
+        public double sc { get; set; }
+        public string tmdId { get; set; }
+    }
+
+}

+ 1 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/Syllabus.cs

@@ -20,6 +20,7 @@ namespace TEAMModelOS.SDK.Models
         [Required(ErrorMessage = "{0} 必须填写")]
         public List<Tnode> children { get; set; }
         public string volumeId { get; set; }
+        public string codeval { get; set; }
         public List<SyllabusAuth> auth { get; set; } = new List<SyllabusAuth>();
         public string scope { get; set; }
 }

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

@@ -41,7 +41,7 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         public string periodId { get; set; }
         /// <summary>
-        /// 年级
+        /// 年级 此字段再入学年的情况下已经无用,现阶段只是用来处理历史数据
         /// </summary>
         public string gradeId { get; set; }
         //入学年

+ 14 - 0
TEAMModelOS.SDK/Models/Table/tmdInfo.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TEAMModelOS.SDK.Models.Table
+{
+
+    public class tmdInfo
+    {
+        public string tmdId { get; set; }
+        public List<double> tScore { get; set; } = new List<double>();
+        public string mark { get; set; }
+    }
+}

+ 7 - 0
TEAMModelOS/ClientApp/src/api/openMgmt.js

@@ -43,5 +43,12 @@ export default{
      */
     delOpen: function (data) {
         return post('/open-api/delete-app', data)
+    },
+    /**
+     * 获取订阅通知
+     * @param {} data
+     */
+     getWebhook: function (data) {
+        return post('/open-api/get-webhook', data)
     }
 }

+ 9 - 4
TEAMModelOS/ClientApp/src/components/syllabus/DragTree.vue

@@ -139,7 +139,9 @@
 			},
 			/* 禁止一级节点往下级进行拖拽 */
 			allowDrop(draggingNode, dropNode, dropType) {
-				if (draggingNode.level === dropNode.level) {
+				if(dropNode.level === 3){
+					return dropType === 'prev' || dropType === 'after'
+				}else if (draggingNode.level === dropNode.level) {
 					if(draggingNode.level === 1){
 						return dropType === 'prev' || dropType === 'after'
 					}else{
@@ -187,7 +189,7 @@
 						}).then(res => {
 							if(res.status === 200){
 								this.$Message.success('操作成功!')
-								this.$parent.getShareVolumeList()
+								this.$parent.getShareVolumeList(true)
 							}
 						})
 					}
@@ -509,7 +511,10 @@
 			},
 			// 点击添加展开弹窗
 			onAddNode(node,data, e) {
-				e.stopPropagation() // 防止点击事件穿透到父层
+				if(node.level === 3){
+					this.$Message.warning('每个章节最多只能有3级!')
+					return
+				}
 				this.isEditItem = false
 				this.isEditOrAdd = true
 				this.currentParentData = data // 当前点击节点即为父节点
@@ -520,7 +525,6 @@
 			},
 			// 编辑节点操作
 			onEditItem(node, data, e) {
-				e.stopPropagation() // 防止点击事件穿透到父层
 				this.isEditOrAdd = true
 				this.isEditItem = true
 				this.currentEditData = data
@@ -564,6 +568,7 @@
 				}
 				this.isEditOrAdd = false
 				this.$parent.hasModify = true
+				console.log(this.curData.id);
 				this.$emit('addModifyId',this.getChapterIdById(this.curData.id))
 				this.$Message.success(this.isEditItem ? this.$t('syllabus.tree.editSucTip') : this.$t('syllabus.tree.addSucTip'))
 			},

+ 9 - 11
TEAMModelOS/ClientApp/src/components/syllabus/InviteTeacher.vue

@@ -193,20 +193,18 @@
 			/* 分享课纲操作 */
 			doShare(){
 				let val = this.curTeacher
-				if(this.nodeInfo.auth.map(i => i.tmdid).includes(val.id)){
-					this.$Message.warning('该章节已分享给当前教师!请勿重复分享!')
-					return
-				}
 				this.isShareLoading = true
 				this.sendShareApi(val.id,val.name,true,true).then(res => {
 					setTimeout(() => {
 						this.$Message.success('分享成功!')
-						this.nodeInfo.auth.push({
-							tmdid:val.id,
-							tmdname:val.name,
-							aggre:0,
-							type:'share'
-						})
+						if(!this.nodeInfo.auth.map(i => i.tmdid).includes(val.id)){
+							this.nodeInfo.auth.push({
+								tmdid:val.id,
+								tmdname:val.name,
+								aggre:0,
+								type:'share'
+							})
+						}
 						this.isShareLoading = false
 						this.curTeacher = null
 						this.hasSearchResult = false
@@ -272,7 +270,7 @@
 						return false
 					}else{
 						let matchItem = this.nodeInfo.auth.filter(i => i.tmdid === id)
-						if(matchItem.length && matchItem[0].coedit){
+						if(matchItem.length && matchItem[0].type === 'coedit'){
 							return true
 						}else{
 							return false

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

@@ -56,7 +56,8 @@ export default {
 	openStatus: '状态',
 	enable: '启用',
 	disable: '禁用',
-	webhook: "webhook",
+	webhook: "webhook配置",
+	authorization: "Token(authorization)",
 	domainName: "域名",
 	subNews: "订阅通知",
 	apiType1: "数据写入接口",

+ 1 - 1
TEAMModelOS/ClientApp/src/view/answersheet/BaseEditor.vue

@@ -414,7 +414,7 @@
 								document.getElementById(this.ids + 'btn').style.top = (PAPER_H - curEditorY + lastBottomGap + SVG_BORDER_PROP.y + 20) + "px";
 							}
 						} else {
-							document.getElementById(this.ids + 'btn').style.top =  "20px";
+							document.getElementById(this.ids + 'btn') && (document.getElementById(this.ids + 'btn').style.top =  "20px")
 						}
 						this.$root.$children[0].spinShow = false;
 						

+ 14 - 9
TEAMModelOS/ClientApp/src/view/answersheet/SheetObjective.vue

@@ -136,10 +136,10 @@
 				}
 				let blockList = [...new Set(itemsPositionArr.map(i => i.lineIndex))]
 				this.blockList = blockList
-
+				console.log(itemsPositionArr)
 				items.forEach((item, index) => {
 					if (index > 0 && (itemsPositionArr[index].lineIndex !== itemsPositionArr[index - 1]
-						.lineIndex)) {
+							.lineIndex)) {
 						this.leftItems = this.leftItems.slice(index, this.leftItems.length)
 					}
 					let optionX = CONTENT_START_X + MARGIN_LEFT + this.getStartX(number, this.leftItems, item.id);
@@ -181,17 +181,22 @@
 					});
 
 				});
-
-				let diff = this.leftItems.length - this.number
-				let refHeight = this.blockHeight * (blockList.length - 1)
-				let objectiveHeight = diff > 0 ? refHeight : refHeight - 26 * diff * -1
-				this.anchorRectY = startY + GAP * number + objectiveHeight
+				console.log(this.leftItems)
+				// diff代表剩余的数量  是否够排满一列
+				let diff =  this.number - this.leftItems.length
+				let refHeight = this.blockHeight * (blockList.length)
+				// 如果不够排满一列 则最后一块渲染的高度就是 差值的高度
+				let objectiveHeight = this.leftItems.length >= 0 ? refHeight : refHeight - 26 * diff
+				console.log(this.blockHeight,refHeight,this.leftItems.length);
+				console.log(startY,number,objectiveHeight);
+				this.anchorRectY = startY +  objectiveHeight
+				console.log(this.anchorRectY)
 				for (let index = 0; index < 28; index++) {
 					// 渲染选项框横向定位锚点
 					this.objectiveGroup.add(
 						snap.rect(
 							CONTENT_START_X + MARGIN_LEFT + NUMBER_ITEM_ML + optionGap * (index - 1),
-							startY + GAP * number + objectiveHeight,
+							startY +  objectiveHeight,
 							NUMBER_ITEM_W,
 							NUMBER_ITEM_H
 						)
@@ -287,7 +292,7 @@
 				return this.objectiveItems.length ? this.objectiveItems.map(i => i.score).reduce((a, b) => a + b) : 0
 			},
 			// 是否为根据试卷自动生成的答题卡
-			isAutoCreate(){
+			isAutoCreate() {
 				return this.$store.state.answerSheet.isAutoCreate
 			}
 		},

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

@@ -32,7 +32,9 @@
 						<span class="info-item">{{$t('evaluation.paperList.itemCount')}}:<span
 								class="info-bold">{{ paper.scoring ? paper.scoring.length : 0 }}</span></span>
 						<span class="info-item">{{$t('evaluation.filter.useCount')}}:<span
-								class="info-bold">{{ paper.useCount || 0 }}</span></span>		
+								class="info-bold">{{ paper.useCount || 0 }}</span></span>
+						<span class="info-item">{{$t('evaluation.updateTime')}}:<span
+								class="info-bold">{{ $tools.formatTime(paper.createTime)  || 0 }} </span></span>
 						<!-- <span class="info-item">难度系数:<span class="info-bold">{{ paper.item ? handleDiffCalc(paper.item) : 0 }}</span></span> -->
 					</div>
 					<div class="paper-item-tools" v-if="!chooseModel">

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

@@ -146,7 +146,6 @@
 		},
 		beforeRouteLeave(to, from, next) {
 			if(to.name === 'newSchoolPaper' || to.name === 'newPrivatePaper'){
-				console.error(to)
 				// 设置下一个路由的 meta
 				to.meta.isKeep = false;  // 让 A 缓存,即不刷新
 			}

+ 9 - 1
TEAMModelOS/ClientApp/src/view/evaluation/index/CreateExercises.vue

@@ -705,12 +705,20 @@
 		// 路由离开生命周期函数
 		beforeRouteLeave(to, from, next) {
 			if (this.isComplete) {
-				next()
+				if(to.name === 'schoolBank' || to.name === 'personalBank'){
+					// 设置下一个路由的 meta
+					to.meta.isKeep = false;  // 让 A 缓存,即不刷新
+				}
+				next();
 			} else {
 				this.$Modal.confirm({
 					title: this.$t('evaluation.newExercise.modalTip'),
 					content: this.$t('evaluation.newExercise.unSaveTip'),
 					onOk: () => {
+						if(to.name === 'schoolBank' || to.name === 'personalBank'){
+							// 设置下一个路由的 meta
+							to.meta.isKeep = false;  // 让 A 缓存,即不刷新
+						}
 						next();
 					}
 				});

+ 4 - 57
TEAMModelOS/ClientApp/src/view/settings/OpenMgmt2.css

@@ -59,19 +59,9 @@
 .open-mgmt .open-mgmt-right .open-right-info .open-info {
   width: 30%;
   font-size: 16px;
-  /* .ivu-input{
-                    font-size: 16px;
-                    color: #525B6F;
-                }
-                .ivu-radio-wrapper{
-                    color: #525B6F;
-                } */
 }
 .open-mgmt .open-mgmt-right .open-right-info .open-info .open-mgmt-info {
   padding: 20px 20px 0 20px;
-  /* .ivu-radio-inner{
-                        background-color: #F3F3F3;
-                    } */
 }
 .open-mgmt .open-mgmt-right .open-right-info .open-info .open-mgmt-info + p {
   color: #949494;
@@ -81,19 +71,6 @@
   border-top: 1px solid #424242;
   border-bottom: 1px solid #424242;
 }
-.open-mgmt .open-mgmt-right .open-right-info .open-info .open-mgmt-info .ivu-checkbox {
-  margin-right: 0;
-}
-.open-mgmt .open-mgmt-right .open-right-info .open-info .open-mgmt-info .ivu-checkbox-wrapper {
-  margin-left: 0;
-  margin-right: 30px;
-}
-.open-mgmt .open-mgmt-right .open-right-info .open-info .ivu-form-item:not(:first-child) {
-  margin-top: 30px;
-}
-.open-mgmt .open-mgmt-right .open-right-info .open-info .ivu-form-item:last-child {
-  margin-bottom: 70px;
-}
 .open-mgmt .open-mgmt-right .open-right-info .open-info .api-token {
   position: relative;
 }
@@ -102,48 +79,18 @@
   top: -33px;
   right: 0;
 }
-.open-mgmt .open-mgmt-right .open-right-info .open-info .open-info-disabled .ivu-input {
-  background: transparent;
-  border: none;
-  box-shadow: none;
-  font-size: 16px;
-  font-weight: 500;
-}
 .open-mgmt .open-mgmt-right .open-right-info .open-api {
   width: 70%;
-}
-.open-mgmt .open-mgmt-right .open-right-info .open-api .ivu-tabs-nav {
-  color: #a5a5a5;
-}
-.open-mgmt .open-mgmt-right .open-right-info .open-api .ivu-tabs-nav .ivu-tabs-ink-bar {
-  border-bottom: 2px solid #1cc0f3;
-}
-.open-mgmt .open-mgmt-right .open-right-info .open-api .ivu-tabs-nav .ivu-tabs-tab-active {
-  font-size: 14px;
-  color: #fff;
-}
-.open-mgmt .open-mgmt-right .open-right-info .open-api .ivu-tabs-nav .ivu-tabs-tab:hover {
-  color: #fff;
+  /* .ivu-checkbox-wrapper {
+                    margin-left: 0;
+                    margin-top: 0;
+                } */
 }
 .open-mgmt .open-mgmt-right .open-right-info .open-api .open-api-header {
   height: 40px;
 }
-.open-mgmt .open-mgmt-right .open-right-info .open-api .ivu-tabs-tab {
-  height: 40px;
-}
 .open-mgmt .open-mgmt-right .open-right-info .open-api .open-api-table {
   padding: 20px;
-  /* .ivu-table-wrapper{
-                        box-shadow: 0px 0px 10px 2px #ccc;
-                    }
-
-                    .ivu-checkbox-inner{
-                        background-color: white;
-                    } */
-}
-.open-mgmt .open-mgmt-right .open-right-info .open-api .ivu-checkbox-wrapper {
-  margin-left: 0;
-  margin-top: 0;
 }
 .open-mgmt .open-mgmt-right .open-right-info .open-api .ivu-page {
   float: right;

+ 2 - 71
TEAMModelOS/ClientApp/src/view/settings/OpenMgmt2.less

@@ -87,26 +87,6 @@
                         border-top: 1px solid #424242;
                         border-bottom: 1px solid #424242;
                     }
-
-                    .ivu-checkbox{
-                        margin-right: 0;
-                    }
-
-                    .ivu-checkbox-wrapper{
-                        margin-left: 0;
-                        margin-right: 30px;
-                    }
-
-                    /* .ivu-radio-inner{
-                        background-color: #F3F3F3;
-                    } */
-                }
-      
-                .ivu-form-item:not(:first-child){
-                    margin-top: 30px;
-                }
-                .ivu-form-item:last-child{
-                    margin-bottom: 70px;
                 }
 
                 .api-token{
@@ -118,73 +98,24 @@
 
                     }
                 }
-
-                /* .ivu-input{
-                    font-size: 16px;
-                    color: #525B6F;
-                }
-                .ivu-radio-wrapper{
-                    color: #525B6F;
-                } */
-
-                .open-info-disabled{
-                    .ivu-input{
-                        background: transparent;
-                        border: none;
-                        box-shadow: none;
-                        font-size: 16px;
-                        // color: #1e1f21;
-                        font-weight: 500;
-                    }
-                }
-
                 
             }
             
             .open-api{
                 width: 70%;
 
-                .ivu-tabs-nav{
-                    color: #a5a5a5;
-
-                    .ivu-tabs-ink-bar{
-                        border-bottom: 2px solid #1cc0f3;
-                    }
-
-                    .ivu-tabs-tab-active{
-                        font-size: 14px;
-                        color: #fff;
-                    }
-
-                    .ivu-tabs-tab:hover{
-                        color: #fff;
-                    }
-                }
-
                 .open-api-header{
                     height: 40px;
                 }
 
-                .ivu-tabs-tab{
-                    height: 40px;
-                }
-
                 .open-api-table{
                     padding: 20px;
-
-                    /* .ivu-table-wrapper{
-                        box-shadow: 0px 0px 10px 2px #ccc;
-                    }
-
-                    .ivu-checkbox-inner{
-                        background-color: white;
-                    } */
                 }
 
-                .ivu-checkbox-wrapper {
+                /* .ivu-checkbox-wrapper {
                     margin-left: 0;
                     margin-top: 0;
-                }
+                } */
 
                 .ivu-page{
                     float: right;

+ 180 - 65
TEAMModelOS/ClientApp/src/view/settings/OpenMgmt2.vue

@@ -7,9 +7,9 @@
                 <span>{{ $t("settings.openList") }}</span>
                 <div class="open-action">
                     <!-- <Icon type="md-add" size="18" style="margin-right: 10px" color="rgb(115 115 115)" @click="editOpen(true, true)" /> -->
-                    <Icon type="md-add" size="18" style="margin-right: 10px" color="#0094FF" @click="editOpen(true, true)" />
+                    <Icon type="md-add" title="新增" size="18" style="margin-right: 10px" color="#FFF" @click="editOpen(true, true)" />
                     
-                    <Icon type="md-trash" size="18" color="#0094FF" @click="delOpen" />
+                    <Icon type="md-trash" title="删除" size="18" color="#FFF" @click="delOpen" />
                 </div>
             </div>
             <vuescroll>
@@ -30,17 +30,17 @@
                 <span>{{ $t("settings.openInfo") }}</span>
                 <div class="open-action" @click="editOpen(true, false)" v-show="!isEdit">
                     <div>
-                        <Icon type="ios-create" size="18" color="#0094FF" />
+                        <Icon type="ios-create" size="18" color="#FFF" />
                         <span>{{ $t("settings.edit") }}</span>
                     </div>
                 </div>
                 <div class="open-action" v-show="isEdit">
                     <div @click="keepMgmt(true)">
-                        <Icon type="md-checkmark-circle" size="18" color="#0094FF" />
+                        <Icon type="md-checkmark-circle" size="18" color="#FFF" />
                         <span>{{ $t("settings.openKeep") }}</span>
                     </div>
                     <div @click="keepMgmt(false)">
-                        <Icon type="md-close-circle" size="18" color="#DDDDDD" />
+                        <Icon type="md-close-circle" size="18" color="rgb(115, 115, 115)" />
                         <span>{{ $t("settings.unedit") }}</span>
                     </div>
                 </div>
@@ -48,7 +48,7 @@
             <div class="open-right-info">
                 <div class="open-info">
                     <vuescroll>
-                        <div class=" dark-iview-form disabled-iview-input">
+                        <div class=" dark-iview-form">
                             <!-- <div class="open-mgmt-info"> -->
                                 <Form :model="openMgInfo" label-position="top">
                                     <div class="open-mgmt-info">
@@ -60,11 +60,11 @@
                                         <FormItem :label="$t('settings.token')" class="api-token" v-show="!isEdit">
                                             <div class="api-icon">
                                                 <!-- 隐藏 -->
-                                                <Icon :type="isTokenShow ? 'md-eye' : 'md-eye-off'" size="18" style="margin-right: 10px" color="rgb(115 115 115)" @click="isTokenShow = !isTokenShow" />
+                                                <Icon :type="isTokenShow ? 'md-eye' : 'md-eye-off'" :title="isTokenShow ? '隐藏' : '显示'" size="18" style="margin-right: 10px" color="#FFF" @click="isTokenShow = !isTokenShow" />
                                                 <!-- 刷新 -->
-                                                <Icon type="md-refresh" size="18" style="margin-right: 10px" color="rgb(115 115 115)" @click="refresh" />
+                                                <Icon type="md-refresh" title="刷新" v-show="isTokenShow" size="18" style="margin-right: 10px" color="#FFF" @click="refresh" />
                                                 <!-- 复制 -->
-                                                <Icon type="ios-copy" size="18" color="rgb(115 115 115)" @click="copyToken" />
+                                                <Icon type="ios-copy" title="复制" v-show="isTokenShow" size="18" color="#FFF" @click="copyToken" />
                                             </div>
                                             <Input
                                                 v-model="openMgInfo.token"
@@ -96,19 +96,21 @@
                                                 :class="isEdit ? '' : 'open-info-disabled'"
                                                 :readonly="isEdit ? false : true"></Input>
                                         </FormItem>
+                                        <FormItem :label="$t('settings.authorization')">
+                                            <Input v-model="openMgInfo.webhookToken"
+                                                type="textarea"
+                                                :autosize="{ minRows: 2 }"
+                                                :class="isEdit ? '' : 'open-info-disabled'"
+                                                :readonly="isEdit ? false : true"></Input>
+                                        </FormItem>
                                         <FormItem :label="$t('settings.subNews')">
-                                            <CheckboxGroup v-model="openMgInfo.news">
-                                                <Checkbox label="hhhh" :disabled="isEdit ? false : true">
-                                                    <span>订阅通知1</span>
-                                                </Checkbox>
-                                                <Checkbox label="www" :disabled="isEdit ? false : true">
-                                                    <span>订阅通知2</span>
-                                                </Checkbox>
-                                                <Checkbox label="mmm" :disabled="isEdit ? false : true">
-                                                    <span>订阅通知3</span>
-                                                </Checkbox>
-                                                <Checkbox label="wwwww" :disabled="isEdit ? false : true">
-                                                    <span>订阅通知4</span>
+                                            <CheckboxGroup v-model="openMgInfo.webhooks">
+                                                <Checkbox v-for="(item, index) in webhook"
+                                                          :label="item.auth"
+                                                          :disabled="isEdit ? false : true"
+                                                          :key="index"
+                                                >
+                                                    <span>{{ item.name}}</span>
                                                 </Checkbox>
                                             </CheckboxGroup>
                                         </FormItem>
@@ -120,39 +122,14 @@
                 </div>
                 <div class="open-api dark-iview-table dark-iview-page dark-iview-tabs-card">
                 <!-- <div class="open-api"> -->
-                    <!-- <vuescroll> -->
-                        <!-- <div class="open-api-table">
-                            <p>数据写入接口</p>
-                            <Table ref="selection"
-                                   :loading="isLoadList"
-                                   :columns="apiListCol"
-                                   :data="isEdit ? apiListSelect : apiListNow"
-                                   @on-selection-change="selectionChange"
-                            ></Table>
-                            <Page :total="pageTotal" :page-size-opts="pageSizeOpts" size="small" show-sizer show-total />
-                        </div> -->
-                    <!-- </vuescroll> -->
-                    <!-- <vuescroll> -->
-                        <!-- <div class="open-api-table">
-                            <p>数据读取接口</p>
-                            <Table ref="selection"
-                                   :loading="isLoadList"
-                                   :columns="apiListCol"
-                                   :data="isEdit ? apiListSelect : apiListNow"
-                                   @on-selection-change="selectionChange"
-                            ></Table>
-                            <Page :total="pageTotal" :page-size-opts="pageSizeOpts" size="small" show-sizer show-total />
-                        </div> -->
-                    <!-- </vuescroll> -->
-
                     <Tabs value="1">
                         <TabPane :label="$t('settings.apiType1')" name="1">
                             <div class="open-api-table">
                                 <Table ref="selection"
                                        :loading="isLoadList"
                                        :columns="apiListCol"
-                                       :data="isEdit ? apiListSelect : apiListNow"
-                                       @on-selection-change="selectionChange"
+                                       :data="isEdit ? apiListW : apiListSelW"
+                                       @on-selection-change="selectionChange1"
                                 >
                                     <template slot-scope="{ row }" slot="name">
                                         <span>{{ row.name }}</span>
@@ -169,13 +146,12 @@
                                 <Table ref="selection"
                                        :loading="isLoadList"
                                        :columns="apiListCol"
-                                       :data="isEdit ? apiListSelect : apiListNow"
-                                       @on-selection-change="selectionChange"
+                                       :data="isEdit ? apiListR : apiListSelR"
+                                       @on-selection-change="selectionChange2"
                                 >
                                     <template slot-scope="{ row }" slot="name">
                                         <span>{{ row.name }}</span>
                                         <Poptip trigger="hover" :content="row.descr" placement="right">
-                                            <!-- <Icon type="ios-alert" /> -->
                                             <Icon type="ios-alert-outline" />
                                         </Poptip>
                                     </template>
@@ -220,16 +196,21 @@ export default {
                     title: this.$t("settings.apiMethod"),
                     key: "method",
                 },
-                {
+                /* {
                     title: this.$t("settings.des"),
                     key: "descr",
-                },
+                }, */
             ],
             apiList: [], //api原有列表
-            apiListSelect: [], //api选择列表
-            apiListNow: [], //当前应用已有的api 列表
+            apiListR: [], //读取接口
+            apiListW: [], //写入接口
+            // apiListSelect: [], //api选择列表
+            // apiListNow: [], //当前应用已有的api 列表
+            apiListSelR: [], //已有的读取接口
+            apiListSelW: [], //已有的写入接口
             pageTotal: 0,
             pageSizeOpts:[5, 10, 20, 30, 40],
+            webhook: [],
             nowIndex: 0, //当前下标
             isEdit: false, //编辑状态
             isAdd: false, // 编辑/新增
@@ -238,6 +219,7 @@ export default {
     mounted () {
         this.getOpenList()
         this.getApiList()
+        this.getWebhook()
     },
     methods: {
         // 获取应用列表
@@ -285,23 +267,56 @@ export default {
                     }, 1000)
             })
         },
+        // 获取订阅通知
+        getWebhook() {
+            let reqs = {}
+            this.$api.openMgmt.getWebhook(reqs).then(res => {
+                if(res) {
+                    res.webhooks.sort(function(a, b) {
+                        return a.auth - b.auth
+                    })
+                    this.webhook = res.webhooks
+                }
+            }).catch(err => {})
+        },
         // 筛选出该应用已有的api
         selectApi() {
-            this.apiListNow = []
             let listSel = this._.cloneDeep(this.apiList)
+            let apiNow = []
             if(listSel.length > 0) {
                 if(this.openMgInfo.auths.length > 0) {
                     listSel.map(item => {
                         this.openMgInfo.auths.map(items => {
                             if(item.auth == items) {
-                                this.apiListNow.push({...item})
+                                apiNow.push({...item})
                                 item._checked = true
                             }
                         })
                     })
                 }
             }
-            this.apiListSelect = listSel
+            let listArr = this.screenType(listSel)
+            this.apiListR = listArr.listR
+            this.apiListW = listArr.listW
+            let listSelArr = this.screenType(apiNow)
+            this.apiListSelR = listSelArr.listR
+            this.apiListSelW = listSelArr.listW
+        },
+        // 分出写入和读取接口
+        screenType(arr) {
+            let list = arr
+            let listArr = {
+                listR: [],
+                listW: []
+            }
+            for (let i = 0; i < list.length; i++) {
+                if(list[i].type == "r") {
+                    listArr.listR.push(list[i])
+                } else if(list[i].type == "w") {
+                    listArr.listW.push(list[i])
+                }
+            }
+            return listArr
         },
         // 编辑、新增
         editOpen (isEdit, isAdd) {
@@ -311,7 +326,7 @@ export default {
             } else {
                 this.apiListCol.unshift({
                     type: 'selection',
-                    width: 80,
+                    width: 40,
                     align: 'center',
                 })
                 this.isEdit = isEdit
@@ -329,7 +344,9 @@ export default {
                     this.openList.unshift(defaultInfo)
                     this.openMgInfo = defaultInfo
                     this.nowIndex = 0
-                    this.apiListSelect = this._.cloneDeep(this.apiList)
+                    let listArr = this.screenType(this.apiList)
+                    this.apiListR = listArr.listR
+                    this.apiListW = listArr.listW
                 }
             }
         },
@@ -392,8 +409,9 @@ export default {
             // this.isEdit = type
             if(type) {
                 let auths = []
-                if(this.apiListNow.length > 0) {
-                    this.apiListNow.map(item => {
+                let arr = this.apiListSelR.concat(this.apiListSelW)
+                if(arr.length > 0) {
+                    arr.map(item => {
                         auths.push(item.auth)
                     })
                 }
@@ -410,8 +428,12 @@ export default {
                         name: this.openMgInfo.name,
                         school: this.schoolCode,
                         status: this.openMgInfo.status,
+                        domain: this.openMgInfo.domain,
+                        webhookToken: this.openMgInfo.webhookToken,
+                        webhooks: this.openMgInfo.webhooks
                     }
                 }
+                console.log(req);
                 this.$api.openMgmt.editOpenInfo(req).then(res => {
                         if (res) {
                             console.log(res.app);
@@ -483,9 +505,13 @@ export default {
                 );
             }
         },
-        selectionChange(selection) {
-            this.apiListNow = selection
-            console.log(selection);
+        // 写入接口
+        selectionChange1(selection) {
+            this.apiListSelW = selection
+        },
+        // 读取接口
+        selectionChange2(selection) {
+            this.apiListSelR = selection
         },
         selectMenu(name) {
             console.log(name);
@@ -497,4 +523,93 @@ export default {
 
 <style lang="less">
     @import "./OpenMgmt2.less";
+</style>
+
+<style lang="less">
+.open-mgmt{
+
+    .ivu-form-item:not(:first-child){
+        margin-top: 30px;
+    }
+    .ivu-form-item:last-child{
+        margin-bottom: 70px;
+    }
+    .ivu-radio-inner, .ivu-checkbox-inner {
+        width: 18px;
+        height: 18px;
+        border-radius: 4px;
+        background-color: #0f0f0f;
+        border-color: #4d4d4d;
+        border-width: 1px;
+        margin-right: 5px;
+    }
+    .ivu-radio-inner::after,
+    .ivu-checkbox-checked .ivu-checkbox-inner::after {
+        content: "";
+        display: block;
+        width: 10px;
+        height: 16px;
+        border-right: #ffffff solid 3px;
+        border-bottom: #ffffff solid 3px;
+        transform: rotate(35deg);
+        position: absolute;
+        top: -4px;
+        left: 4px;
+        border-radius: 0;
+        background-color: transparent;
+        border-color: #0094ff;
+    }
+
+    .ivu-checkbox-disabled .ivu-checkbox-inner{
+        background-color: #0f0f0f;
+        border-color: #4d4d4d;
+    }
+
+    .ivu-radio-wrapper,
+    .ivu-checkbox-wrapper{
+        color: #a5a5a5;
+    }
+
+    .ivu-checkbox{
+        margin-right: 0;
+    }
+
+    .ivu-checkbox-wrapper{
+        margin-left: 0;
+        margin-right: 30px;
+    }
+
+    .open-info-disabled{
+        .ivu-input{
+            background: transparent;
+            border: none;
+            box-shadow: none;
+            font-size: 16px;
+            // color: #1e1f21;
+            font-weight: 500;
+        }
+    }
+
+    .ivu-tabs-nav{
+        color: #a5a5a5;
+
+        .ivu-tabs-tab{
+            height: 40px;
+        }
+
+        .ivu-tabs-ink-bar{
+            border-bottom: 2px solid #1cc0f3;
+        }
+
+        .ivu-tabs-tab-active{
+            font-size: 14px;
+            color: #fff;
+        }
+
+        .ivu-tabs-tab:hover{
+            color: #fff;
+        }
+    }
+    
+}
 </style>

+ 13 - 0
TEAMModelOS/ClientApp/src/view/syllabus/Syllabus.less

@@ -123,6 +123,19 @@
 						margin: 10px 0;
 						padding-right: 10px;
 					}
+					
+					.status-idDel{
+						font-size: 12px;
+						display: inline-block;
+						padding: 2px 8px;
+						background-color: #424242;
+						color: #fff;
+						margin-left: 5px;
+						margin-bottom: 3px;
+						vertical-align: bottom;
+						border-radius: 4px;
+						zoom: 0.9;
+					}
 					&-info{
 						span{
 							color: #9f9f9f;

+ 85 - 20
TEAMModelOS/ClientApp/src/view/syllabus/Syllabus.vue

@@ -28,11 +28,11 @@
 					<div v-if="!isSearchVolume">
 						<span>册别清单</span>
 						<span class="syllabus-content-header-tools">
-							<Icon type="md-search" title="搜索" @click="doSearchVolume" />
-							<Icon type="md-copy" title="复制副本" @click="doCopyVolume" v-if="hasSyllabusAuth && inShareView" />
-							<Icon type="md-create" title="编辑" @click="doEditVolume" v-if="hasSyllabusAuth" />
-							<Icon type="md-trash" title="删除" @click="doDeleteVolume" v-if="hasSyllabusAuth && !inShareView" />
-							<Icon type="md-add" title="新建册别" @click="doAddVolume" v-if="hasSyllabusAuth" />
+							<Icon type="md-search" title="搜索" @click="doSearchVolume" v-if="volumeList.length"/>
+							<!-- <Icon type="md-copy" title="复制副本" @click="doCopyVolume" v-if="hasSyllabusAuth && inShareView" /> -->
+							<Icon type="md-create" title="编辑" @click="doEditVolume" v-if="hasSyllabusAuth && !inShareView && volumeList.length" />
+							<Icon type="md-trash" title="删除" @click="doDeleteVolume" v-if="hasSyllabusAuth && !inShareView && volumeList.length" />
+							<Icon type="md-add" title="新建册别" @click="doAddVolume" v-if="hasSyllabusAuth && !inShareView" />
 						</span>
 					</div>
 					<div style="width: 90%;" v-else>
@@ -46,7 +46,7 @@
 						<div v-for="(volume,volumeIndex) in volumeList" :key="volumeIndex"
 							:class="['volume-item',activeVolumeIndex === volumeIndex ? 'volume-active' : '']"
 							@click="onVolumeClick(volume,volumeIndex)">
-							<p class="volume-item-name">{{ volume.name }}</p>
+							<p class="volume-item-name">{{ volume.name }} <span class="status-idDel" v-if="volume.isDel">已失效</span> </p>
 							<p class="volume-item-info" v-if="isSchool">
 								<span>{{ getGradeName(volume.gradeId) }}</span>
 								<span>|</span>
@@ -74,7 +74,7 @@
 			<div class="syllabus-mid">
 				<div class="syllabus-content-header">
 					<span>课纲目录</span>
-					<span class="syllabus-content-header-tools">
+					<span class="syllabus-content-header-tools" v-if="volumeList.length && curVolume.id && !inShareView">
 						<Icon type="md-add" @click="isAddTreeModal = true" v-if="hasSyllabusAuth" />
 					</span>
 				</div>
@@ -133,7 +133,7 @@
 									<Icon type="md-eye" />
 									<span>查看</span>
 								</div>
-								<div class="node-resource-tool" @click="onDeleteResource(item,index)">
+								<div class="node-resource-tool" @click="onDeleteResource(item,index)" v-if="(hasSyllabusAuth || hasEditAuth(curNode)) && !inShareView">
 									<Icon type="md-trash" />
 									<span>删除</span>
 								</div>
@@ -396,12 +396,12 @@
 				this.gradeList = this.periodList[val].grades;
 				this.semesterList = this.periodList[val].semesters;
 				this.activeSubjectIndex = 0
-				this.getVolumeList()
+				this.getVolumeList(true)
 			},
 			/* 切换科目的操作 */
 			onSubjectChange(subject, index) {
 				this.activeSubjectIndex = index
-				this.getVolumeList()
+				this.getVolumeList(true)
 			},
 			/* 切换个人创建的课纲和他人分享的课纲 */
 			onChangeSyllabusTab(type) {
@@ -467,6 +467,11 @@
 									status: 1
 								}
 							})
+							shareList.forEach(i => {
+								if(i.children.length && !i.children.filter(j => j.agree !== -1).length){
+									i.isDel = true
+								}
+							})
 							this.volumeList = shareList.reverse()
 							this.originVolumeList = JSON.parse(JSON.stringify(this.volumeList))
 							let activeIndex = this.isEditVolume ? this.activeVolumeIndex : 0
@@ -490,6 +495,15 @@
 			/* 点击某个册别 */
 			onVolumeClick(volume, volumeIndex, needRefresh) {
 				console.log(volume)
+				if(volume.isDel){
+					this.$Message.warning('该册别已被创建者移除!')
+					this.treeOrigin = []
+					this.curNode = {
+						id:'',
+						rnodes:[]
+					}
+					return
+				}
 				if (!volume || (volume.id === this.curVolume.id && !this.isEditVolume && !needRefresh)) return
 				this.isLoading = true
 				this.curVolume = volume
@@ -648,13 +662,14 @@
 			},
 			/* 有章节发生变化记录章节ID */
 			addModifyId(id) {
+				console.log(id)
 				this.modifyIdArr.push(id)
 			},
 			/* 存储变更保存最新课纲数据 */
 			onSaveSyllabus() {
 				this.isSaveSyllabus = true
 				// 拿到有修改变动的章节ID集合
-				let modifyIdArr = [...new Set(this.modifyIdArr)].filter(i => i !== this.curVolume.id)
+				let modifyIdArr = [...new Set(this.modifyIdArr)].filter(i => i !== this.curVolume.id && i)
 				console.log(modifyIdArr)
 				let allChapter = this.$refs.treeRef ? this.$refs.treeRef.treeDatas : [];
 				let modifyChapters = modifyIdArr.length ? modifyIdArr.map(id => {
@@ -831,19 +846,21 @@
 				});
 			},
 			/* 校本课纲关联个人试题试卷要进行入库操作 */
-			saveItemToSchoolBlob(pItem) {
+			saveItemToBlob(pItem,privateToSchool) {
 				return new Promise(async (r, j) => {
 					pItem = await this.$editorTools.doRemoveMideaHost(pItem)
 					console.log(pItem)
 					let path = 'item/' + pItem.id + '/'
 					let privateSas = await this.$tools.getPrivateSas()
-					let privareBlobTool = new BlobTool(privateSas.url, privateSas.name, privateSas.sas,'private')
+					let privateBlobTool = new BlobTool(privateSas.url, privateSas.name, privateSas.sas,'private')
+					let toClient = privateToSchool ? this.containerClient : privateBlobTool
+					let fromClient = privateToSchool ?  privateBlobTool : this.containerClient
 					const itemJsonFile = await this.$evTools.createBlobItem(pItem);
 					let file = new File([JSON.stringify(itemJsonFile)], pItem.id + ".json", {type: "",});
 					// 先把对应试题目录下的全部复制到校本BLOB 然后再更新添加学段科目等字段后的题目Json文件
-					this.containerClient.copyFolder(path,path.slice(0,path.length - 1),privareBlobTool).then(async res => {
+					toClient.copyFolder(path,path.slice(0,path.length - 1),fromClient).then(async res => {
 						try{
-							let blobFile = await this.containerClient.upload(file, "item/" + pItem.id);
+							let blobFile = await toClient.upload(file, "item/" + pItem.id);
 							if(blobFile.blob){
 								this.saveExercise(pItem).then(result => {
 									console.log(result)
@@ -867,8 +884,9 @@
 						r(200)
 					}else{
 						let curResourceArr = this.$refs.treeRef.curData.rnodes
-						// 拿到关联的个人试题
+						// 拿到关联的个人试题和校本试题
 						let privateItems = list.filter(i => i.scope === 'private')
+						let schoolItems = list.filter(i => i.scope === 'school')
 						// 如果是在校本课纲关联的个人试题 则需要进行入库操作
 						if (this.isSchool && privateItems.length) {
 							let promiseArr = []
@@ -879,7 +897,7 @@
 								pItem.gradeIds = [this.curVolume.gradeId + '']
 								pItem.scope = 'school'
 								pItem.code = this.$store.state.userInfo.schoolCode
-								promiseArr.push(this.saveItemToSchoolBlob(pItem))
+								promiseArr.push(this.saveItemToBlob(pItem,false))
 							})
 							Promise.all(promiseArr).then(result => {
 								list.forEach(i => {
@@ -900,7 +918,37 @@
 							}).catch(err => {
 								this.$Message.error(err)
 							})
-						} else {
+						}else if(!this.isSchool && schoolItems.length){
+							let promiseArr = []
+							// 个人试题入库前需要补充必要的学段科目年级信息
+							schoolItems.forEach(pItem => {
+								pItem.periodId = null
+								pItem.subjectId = null
+								pItem.gradeIds = null
+								pItem.scope = 'private'
+								pItem.code = this.$store.state.userInfo.TEAMModelId
+								promiseArr.push(this.saveItemToBlob(pItem,true))
+							})
+							Promise.all(promiseArr).then(result => {
+								list.forEach(i => {
+									if (!curResourceArr.filter(j => j.type === 'item').map(k => k.id).includes(i
+											.id)) {
+										curResourceArr.push({
+											type: 'item',
+											title: i.question,
+											id: i.id,
+											code: 'Item-' + this.$store.state.userInfo.TEAMModelId,
+											scope: 'private',
+											cntr: this.$store.state.userInfo.TEAMModelId,
+											link: i.blob
+										})
+									}
+								})
+								r(200)
+							}).catch(err => {
+								this.$Message.error(err)
+							})
+						}else {
 						list.forEach(i => {
 							if (!curResourceArr.filter(j => j.type === 'item').map(k => k.id).includes(i.id)) {
 								curResourceArr.push({
@@ -1269,11 +1317,14 @@
 						"scope": this.curScope,
 						"syllabusIds": []
 					}
-					if ((this.isEditVolume && this.curVolume) || this.isSaveSyllabus) {
+					if ((this.isEditVolume && this.curVolume)) {
 						addVolumeParams.id = this.curVolume.id
-						// addVolumeParams.name = this.curVolume.name
+						addVolumeParams.name = this.addVolumeForm.name
 						addVolumeParams.syllabusIds = this.allChapterIds || []
 						addVolumeParams.creatorId = this.curVolume.creatorId
+					}
+					if(this.isSaveSyllabus){
+						addVolumeParams.name = this.curVolume.name
 						this.isSaveSyllabus = false
 					}
 					// 发送新增或者编辑册别请求
@@ -1383,6 +1434,20 @@
 				return !this.isSchool && this.activeTab === 'fromShare'
 			}
 		},
+		watch:{
+			volumeList:{
+				handler(n,o){
+					if(n.length === 0){
+						this.treeOrigin = []
+						this.curNode = {
+							id:'',
+							rnodes:[]
+						}
+					}
+				},
+				immediate:true
+			}
+		}
 	}
 </script>
 

+ 33 - 6
TEAMModelOS/Controllers/Analysis/AnalysisController.cs

@@ -420,6 +420,7 @@ namespace TEAMModelOS.Controllers.Analysis
                     ClassAys classAys = new ClassAys
                     {
                         gradeId = classroom.gradeId,
+                        year = classroom.year,
                         studentIds = studentIds,
                         stuCount = stuCount,
                         classId = classId,
@@ -493,19 +494,20 @@ namespace TEAMModelOS.Controllers.Analysis
                     classes.Add(classAys);
                 }
                 //处理年级
-                var tgrades = classes.GroupBy(x => x.gradeId).Select(x => x.Key);
+                var tgrades = classes.GroupBy(x => x.year).Select(x => x.Key);
                 foreach (var greade in tgrades)
                 {
-                    var clases = classes.Where(x => x.gradeId.Equals(greade));
+                    string gid = await getGId(greade, info.period.id, info.school);
+                    var clases = classes.Where(x => x.year.Equals(greade));
                     var classCount = clases.Count();
                     var stu = clases.SelectMany(x => x.studentIds).ToList();
                     var lineCount = clases.Select(x => x.lineCount).Sum();
                     var totalAverage = clases.Select(x => x.totalAverage).Sum() * 1.0 / classCount;
                     GradeAys gradeAys = new GradeAys
                     {
-                        gradeId = greade,
+                        gradeId = gid,
                         studentIds = stu,
-                        gradeName = info.grades.Where(x => x.id == greade).FirstOrDefault().name,
+                        gradeName = info.grades.Where(x => x.id.Equals(gid)).FirstOrDefault().name,
                         stuCount = stu.Count,
                         lineCount = lineCount,
                         totalAverage = totalAverage,
@@ -524,13 +526,13 @@ namespace TEAMModelOS.Controllers.Analysis
                             passPercent = passPercent,
                             average = average,
                             name = info.subjects.Where(x => x.id == key).FirstOrDefault().name,
-                            item = gscores.Where(x => x.Key == key).FirstOrDefault().Value.Where(cls => cls.Key == greade).FirstOrDefault().Value
+                            item = gscores.Where(x => x.Key == key).FirstOrDefault().Value.Where(cls => cls.Key == gid).FirstOrDefault().Value
                         };
                         gradeAys.subjects.Add(subject);
                     }
                     grades.Add(gradeAys);
                     //处理学生年级相关的pr值
-                    var studentAys = students.Where(x => x.gradeId.Equals(greade)).ToList();
+                    var studentAys = students.Where(x => x.gradeId.Equals(gid)).ToList();
                     var stuGradeTotal = studentAys.Select(x => x.total).ToList();
                     stuGradeTotal.Sort((s1, s2) => { return s2.CompareTo(s1); });
                     var stuCount = stuGradeTotal.Count;
@@ -1625,5 +1627,30 @@ namespace TEAMModelOS.Controllers.Analysis
             }
         }
 
+        public async Task<string> getGId(int cyear,string periodId,string code) {
+            var client = _azureCosmos.GetCosmosClient();
+            School sc = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<School>(code, new Azure.Cosmos.PartitionKey("Base"));
+            string gradeId = "";
+            foreach (Period period in sc.period)
+            {
+                if (period.id.Equals(periodId))
+                {
+                    foreach (Semester semester in period.semesters)
+                    {
+                        if (semester.start == 1)
+                        {
+                            int year = DateTimeOffset.UtcNow.Year;
+                            int month = DateTimeOffset.UtcNow.Month;
+                            int day = DateTimeOffset.UtcNow.Day;
+                            int time = month > semester.month ? 0 : 1;
+                            int eyear = year - time;
+                            gradeId = (eyear - cyear).ToString();
+                        }
+                    }
+                }
+            }
+            return gradeId;
+        }
+
     }
 }

+ 1 - 0
TEAMModelOS/Controllers/Analysis/ClassAys.cs

@@ -21,6 +21,7 @@ namespace TEAMModelOS.Controllers.Analysis
         public double totalAverage { get; set; }
         public double standardDeviation { get; set; }
         public string gradeId { get; set; }
+        public int year { get; set; }
         //记录班级得分率
         public double csRate { get; set; }
     }

+ 1 - 1
TEAMModelOS/Controllers/Analysis/GradeAys.cs

@@ -17,7 +17,7 @@ namespace TEAMModelOS.Controllers.Analysis
         public int lineCount { get; set; }
         public List<AysSubject> subjects { get; set; }
         public string gradeId { get; set; }
-        public string gradeName { get; set; }
+        public string? gradeName { get; set; }
         public double totalAverage { get; set; }
     }
 }

+ 91 - 23
TEAMModelOS/Controllers/Common/ExamController.cs

@@ -1517,19 +1517,24 @@ namespace TEAMModelOS.Controllers
                 ExamInfo info = await client.GetContainer("TEAMModelOS", "Common").ReadItemAsync<ExamInfo>(id.ToString(), new PartitionKey($"Exam-{code}"));
                 List<ExamClassResult> classResults = new();
                 List<dynamic> attr = new List<dynamic>();
-                //List<dynamic> all = new List<dynamic>();
                 var record = await redisClient.HashGetAllAsync($"Exam:Scoring:{id}-{subjectId}");
                 foreach (var rcd in record)
                 {
                     var value = JsonDocument.Parse(rcd.Value.ToString());
-                    value.RootElement.TryGetProperty("tmdId", out JsonElement tmdId);
-                    if (tId.ToString().Equals(tmdId.ToString()))
+                    value.RootElement.TryGetProperty("info", out JsonElement json);
+                    List<tmdInfo> tmds = json.ToObject<List<tmdInfo>>();
+                    foreach (tmdInfo tmd in tmds)
                     {
-                        attr.Add(new { stuId = rcd.Name.ToString(), info = value });
+                        if (!string.IsNullOrEmpty(tmd.tmdId) && tmd.tmdId.Equals(tId.ToString()))
+                        {
+                            attr.Add(new { stuId = rcd.Name.ToString(), info = value });
+                            break;
+                        }
                     }
-
-
-
+                    /*                    if (tId.ToString().Equals(tmdId.ToString()))
+                                        {
+                                            attr.Add(new { stuId = rcd.Name.ToString(), info = value });
+                                        }*/
                 }
                 int index = 0;
                 foreach (ExamSubject subject in info.subjects)
@@ -1576,15 +1581,29 @@ namespace TEAMModelOS.Controllers
                 foreach (var rcd in record)
                 {
                     var value = JsonDocument.Parse(rcd.Value.ToString());
-                    value.RootElement.TryGetProperty("tmdId", out JsonElement tmdId);
-                    if (tId.ToString().Equals(tmdId.ToString()))
+                    value.RootElement.TryGetProperty("info", out JsonElement json);
+                    List<tmdInfo> tmds = json.ToObject<List<tmdInfo>>();
+                    foreach (tmdInfo tmd in tmds)
+                    {
+                        if (!string.IsNullOrEmpty(tmd.tmdId) && tmd.tmdId.Equals(tId.ToString()))
+                        {
+                            recs.Add(new { stuId = rcd.Name.ToString(), info = value });
+                            break;
+                        }
+                        if (string.IsNullOrEmpty(tmd.tmdId))
+                        {
+                            all.Add(new { stuId = rcd.Name.ToString(), ans = value });
+                            break;
+                        }
+                    }
+                    /*if (tId.ToString().Equals(tmdId.ToString()))
                     {
                         recs.Add(new { stuId = rcd.Name.ToString(), ans = value });
                     }
                     if (string.IsNullOrEmpty(tmdId.ToString()))
                     {
                         all.Add(new { stuId = rcd.Name.ToString(), ans = value });
-                    }
+                    }*/
                 }
                 if (requert.TryGetProperty("stuId", out JsonElement stuId))
                 {
@@ -1594,7 +1613,17 @@ namespace TEAMModelOS.Controllers
                     //保证此学生与该老师绑定
                     value.RootElement.TryGetProperty("ans", out JsonElement blob);
                     value.RootElement.TryGetProperty("score", out JsonElement sc);
-                    await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", stuId.ToString(), new { ans = blob, score = sc, tmdId = tId }.ToJsonString());
+                    value.RootElement.TryGetProperty("info", out JsonElement json);
+                    List<tmdInfo> tmds = json.ToObject<List<tmdInfo>>();
+                    foreach (tmdInfo tmd in tmds)
+                    {
+                        if (string.IsNullOrEmpty(tmd.tmdId))
+                        {
+                            tmd.tmdId = tId.ToString();
+                            break;
+                        }
+                    }
+                    await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", stuId.ToString(), new { info = tmds, ans = blob, score = sc }.ToJsonString());
 
                     return Ok(value);
                 }
@@ -1621,8 +1650,18 @@ namespace TEAMModelOS.Controllers
                         json.RootElement.TryGetProperty("ans", out JsonElement ans);
                         ans.TryGetProperty("score", out JsonElement sc);
                         ans.TryGetProperty("ans", out JsonElement blob);
+                        ans.TryGetProperty("info", out JsonElement element);
+                        List<tmdInfo> tmds = element.ToObject<List<tmdInfo>>();
+                        foreach (tmdInfo tmd in tmds)
+                        {
+                            if (string.IsNullOrEmpty(tmd.tmdId))
+                            {
+                                tmd.tmdId = tId.ToString();
+                                break;
+                            }
+                        }
                         //选取后,缓存池相应的减少,以便于分配给其他的老师
-                        await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString(), new { ans = blob, score = sc, tmdId = tId }.ToJsonString());
+                        await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString(), new { info = tmds, ans = blob, score = sc }.ToJsonString());
                         return Ok(item);
                     }
 
@@ -1686,29 +1725,40 @@ namespace TEAMModelOS.Controllers
                 if (!requert.TryGetProperty("stuId", out JsonElement sId)) return BadRequest();
                 if (!requert.TryGetProperty("subjectId", out JsonElement subjectId)) return BadRequest();
                 if (!requert.TryGetProperty("tmdId", out JsonElement tId)) return BadRequest();
-                if (!requert.TryGetProperty("score", out JsonElement score)) return BadRequest(); 
+                if (!requert.TryGetProperty("score", out JsonElement score)) return BadRequest();
                 if (!requert.TryGetProperty("count", out JsonElement count)) return BadRequest();
                 if (!requert.TryGetProperty("code", out JsonElement code)) return BadRequest();
                 //if (!requert.TryGetProperty("mark", out JsonElement mark)) return BadRequest();
                 //requert.TryGetProperty("mark", out JsonElement mark);
                 var client = _azureCosmos.GetCosmosClient();
-				var redisClient = _azureRedis.GetRedisClient(8);
+                var redisClient = _azureRedis.GetRedisClient(8);
                 List<ExamClassResult> classResults = new();
                 List<dynamic> recs = new List<dynamic>();
                 var record = await redisClient.HashGetAllAsync($"Exam:Scoring:{id}-{subjectId}");
                 foreach (var rcd in record)
                 {
                     var values = JsonDocument.Parse(rcd.Value.ToString());
-                    values.RootElement.TryGetProperty("tmdId", out JsonElement tmdId);
-                    if (tId.ToString().Equals(tmdId.ToString()))
+                    values.RootElement.TryGetProperty("info", out JsonElement json);
+                    List<tmdInfo> tmdInfos = json.ToObject<List<tmdInfo>>();
+                    foreach (tmdInfo tmd in tmdInfos)
                     {
-                        recs.Add(new { stuId = rcd.Name.ToString(), ans = values });
+                        if (!string.IsNullOrEmpty(tmd.tmdId) && tmd.tmdId.Equals(tId.ToString()))
+                        {
+                            recs.Add(new { stuId = rcd.Name.ToString(), info = values });
+                            break;
+                        }
                     }
+                    /*if (tId.ToString().Equals(tmdId.ToString()))
+                    {
+                        recs.Add(new { stuId = rcd.Name.ToString(), ans = values });
+                    }*/
                 }
                 var stuAns = await redisClient.HashGetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString());
                 var value = JsonDocument.Parse(stuAns.ToString());
                 value.RootElement.TryGetProperty("ans", out JsonElement blob);
-                value.RootElement.TryGetProperty("mark", out JsonElement element);
+                value.RootElement.TryGetProperty("info", out JsonElement element);
+                List<tmdInfo> tmds = element.ToObject<List<tmdInfo>>();
+
                 StringBuilder builder = new StringBuilder();
                 if (requert.TryGetProperty("mark", out JsonElement mark))
                 {
@@ -1718,12 +1768,30 @@ namespace TEAMModelOS.Controllers
                     builder.Append(sId).Append("mark").Append("/");
                     builder.Append("ans.json");
                     await _azureStorage.UploadFileByContainer(code.ToString(), mark.ToJsonString(), "exam", builder.ToString(), false);
-                    await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString(), new { ans = blob, score = score, tmdId = tId, mark = builder.ToString() }.ToJsonString());
+                    foreach (tmdInfo tmd in tmds)
+                    {
+                        if (string.IsNullOrEmpty(tmd.tmdId))
+                        {
+                            tmd.tmdId = tId.ToString();
+                            tmd.mark = builder.ToString();
+                            break;
+                        }
+                    }
+                    await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString(), new { info = tmds, ans = blob, score = score }.ToJsonString());
                 }
-                else {
-                    await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString(), new { ans = blob, score = score, tmdId = tId, mark = element }.ToJsonString());
-                }                
-                
+                else
+                {
+                    foreach (tmdInfo tmd in tmds)
+                    {
+                        if (string.IsNullOrEmpty(tmd.tmdId))
+                        {
+                            tmd.tmdId = tId.ToString();
+                            break;
+                        }
+                    }
+                    await redisClient.HashSetAsync($"Exam:Scoring:{id}-{subjectId}", sId.ToString(), new { info = tmds, ans = blob, score = score }.ToJsonString());
+                }
+
                 if (recs.Count == count.GetInt32())
                 {
                     await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryIterator<ExamClassResult>(

+ 0 - 15
TEAMModelOS/Controllers/Syllabus/CoeditController.cs

@@ -1,15 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-
-namespace TEAMModelOS.Controllers
-{
-    public class CoeditController
-    {
-        public CoeditController()
-        {
-
-        }
-    }
-}

+ 70 - 61
TEAMModelOS/Controllers/Syllabus/ShareController.cs

@@ -76,7 +76,7 @@ namespace TEAMModelOS.Controllers
                 //需要判断id== req.issuer  才能进行授权操作
                 if (request.scope.Equals("school"))
                 {
-                    Syllabus syllabusD = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<Syllabus>(request.syllabusId, new PartitionKey($"Syllabus-{request.volumeId}"));
+                    Syllabus syllabusD = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<Syllabus>(request.syllabusId, new PartitionKey($"Syllabus-{request.school}"));
                     if (request.opt == "del")
                     {
                         if (syllabusD.auth.IsNotEmpty())
@@ -90,9 +90,9 @@ namespace TEAMModelOS.Controllers
                             syllabusAuths.ForEach(x => {
                                 syllabusD.auth.Remove(x);
                             });
-                            await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<Syllabus>(syllabusD, request.syllabusId, new PartitionKey($"Syllabus-{request.volumeId}"));
+                            await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<Syllabus>(syllabusD, request.syllabusId, new PartitionKey($"Syllabus-{request.school}"));
                             request.tmdInfo.ForEach(async x => {
-                                await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>(request.syllabusId, new PartitionKey($"Share-{x.tmdid}"));
+                                await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>(request.syllabusId, new PartitionKey($"Share-{request.type}-{x.tmdid}"));
                             });
 
                         }
@@ -119,14 +119,14 @@ namespace TEAMModelOS.Controllers
                             var location = _option.Location;
                             var code = await _notificationService.SendNotification(clientID, clientSecret, location, url, notification);
                         });
-                        await client.GetContainer("TEAMModelOS", "School").UpsertItemAsync<Syllabus>(syllabus, new PartitionKey($"Syllabus-{request.volumeId}"));
+                        await client.GetContainer("TEAMModelOS", "School").UpsertItemAsync<Syllabus>(syllabus, new PartitionKey($"Syllabus-{request.school}"));
 
 
                     }
                 }
                 else if (request.scope.Equals("private"))
                 {
-                    Syllabus syllabusD = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Syllabus>(request.syllabusId, new PartitionKey($"Syllabus-{request.volumeId}"));
+                    Syllabus syllabusD = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Syllabus>(request.syllabusId, new PartitionKey($"Syllabus-{request.issuer}"));
                     if (request.opt == "del")
                     {
                         if (syllabusD.auth.IsNotEmpty())
@@ -141,9 +141,9 @@ namespace TEAMModelOS.Controllers
                             syllabusAuths.ForEach(x => {
                                 syllabusD.auth.Remove(x);
                             });
-                            await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Syllabus>(syllabusD, request.syllabusId, new PartitionKey($"Syllabus-{request.volumeId}"));
+                            await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Syllabus>(syllabusD, request.syllabusId, new PartitionKey($"Syllabus-{request.issuer}"));
                             request.tmdInfo.ForEach(async x => {
-                                await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>(request.syllabusId, new PartitionKey($"Share-{x.tmdid}"));
+                                await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>(request.syllabusId, new PartitionKey($"Share-{request.type}-{x.tmdid}"));
                             });
                         }
                     }
@@ -153,7 +153,7 @@ namespace TEAMModelOS.Controllers
                         shares.ForEach(async x => {
                             await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Share>(x, new PartitionKey($"{x.code}"));
                         });
-                        await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Syllabus>(syllabusD, new PartitionKey($"Syllabus-{request.volumeId}"));
+                        await client.GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Syllabus>(syllabusD, new PartitionKey($"Syllabus-{request.issuer}"));
                     }
                 }
                 return Ok(new { code = 200 });
@@ -256,65 +256,74 @@ namespace TEAMModelOS.Controllers
             try {
                 if (!request.TryGetProperty("type", out JsonElement type)) { return BadRequest(); }
                 if (!request.TryGetProperty("code", out JsonElement code)) { return BadRequest(); }
-                if (!request.TryGetProperty("id", out JsonElement id)) { return BadRequest(); }
+                if (!request.TryGetProperty("ids", out JsonElement ids)) { return BadRequest(); }
                 if (!request.TryGetProperty("opt", out JsonElement opt)) { return BadRequest(); }
                 var client = _azureCosmos.GetCosmosClient();
-                Share share = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Share>($"{id}", new PartitionKey($"Share-{type}-{code}"));
-                if ($"{opt}".Equals("agree"))
-                {
-                    share.agree = 1;
-                    await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Share>(share, $"{id}", new PartitionKey($"Share-{type}-{code}"));
-                }
-                else if ($"{opt}".Equals("ignore"))
-                {
-                    await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>($"{id}", new PartitionKey($"Share-{type}-{code}"));
-                }
+                if (ids.ValueKind.Equals(JsonValueKind.Array)) {
+                    List<string> idss = ids.ToObject<List<string>>();
+                    foreach (var id in idss) {
+                        Share share = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Share>($"{id}", new PartitionKey($"Share-{type}-{code}"));
+                        if ($"{opt}".Equals("agree"))
+                        {
+                            share.agree = 1;
+                            await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Share>(share, $"{id}", new PartitionKey($"Share-{type}-{code}"));
+                        }
+                        else if ($"{opt}".Equals("ignore"))
+                        {
+                            await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemAsync<Share>($"{id}", new PartitionKey($"Share-{type}-{code}"));
+                        }
 
-                Syllabus syllabus = null;
-                if (share.scope == "school")
-                {
-                    try 
-                    { 
-                        syllabus = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<Syllabus>($"{id}", new PartitionKey($"Syllabus-{share.volumeId}"));
-                    } catch {
-                        //仅处理差不到数据的情况
-                    }
-                }
-                else if (share.scope == "private")
-                {
-                    try 
-                    {
-                        syllabus = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Syllabus>($"{id}", new PartitionKey($"Syllabus-{share.volumeId}"));
-                    } catch 
-                    {
-                    }
-                }
-                if (syllabus != null) {
-                    if (syllabus.auth.IsNotEmpty())
-                    {
-                        syllabus.auth.ForEach(x =>
+                        Syllabus syllabus = null;
+                        if (share.scope == "school")
                         {
-                            if (x.tmdid == $"{code}" && x.type == $"{type}")
+                            try
                             {
-                                if ($"{opt}".Equals("ignore"))
-                                {
-                                    x.agree = 0;
-                                }
-                                else if ($"{opt}".Equals("ignore"))
+                                syllabus = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<Syllabus>($"{id}", new PartitionKey($"Syllabus-{share.school}"));
+                            }
+                            catch
+                            {
+                                //仅处理差不到数据的情况
+                            }
+                        }
+                        else if (share.scope == "private")
+                        {
+                            try
+                            {
+                                syllabus = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Syllabus>($"{id}", new PartitionKey($"Syllabus-{share.issuer}"));
+                            }
+                            catch
+                            {
+                            }
+                        }
+                        if (syllabus != null)
+                        {
+                            if (syllabus.auth.IsNotEmpty())
+                            {
+                                syllabus.auth.ForEach(x =>
                                 {
-                                    x.agree = 1;
-                                }
+                                    if (x.tmdid == $"{code}" && x.type == $"{type}")
+                                    {
+                                        if ($"{opt}".Equals("ignore"))
+                                        {
+                                            x.agree = 0;
+                                        }
+                                        else if ($"{opt}".Equals("agree"))
+                                        {
+                                            x.agree = 1;
+                                        }
 
+                                    }
+                                });
                             }
-                        });
-                    }
-                    if (share.scope == "school")
-                    {
-                        syllabus = await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<Syllabus>(syllabus, $"{id}", new PartitionKey($"Syllabus-{share.volumeId}"));
-                    }
-                    else if (share.scope == "private")
-                    {
-                        syllabus = await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Syllabus>(syllabus, $"{id}", new PartitionKey($"Syllabus-{share.volumeId}"));
+                            if (share.scope == "school")
+                            {
+                                syllabus = await client.GetContainer("TEAMModelOS", "School").ReplaceItemAsync<Syllabus>(syllabus, $"{id}", new PartitionKey($"Syllabus-{share.school}"));
+                            }
+                            else if (share.scope == "private")
+                            {
+                                syllabus = await client.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Syllabus>(syllabus, $"{id}", new PartitionKey($"Syllabus-{share.issuer}"));
+                            }
+                        }
                     }
                 }
                 return Ok(new { status = 200 });
@@ -427,7 +436,7 @@ namespace TEAMModelOS.Controllers
                 {
                     code = request.school;
                     var queryslt = $"SELECT  value(c) FROM c where c.id in ({sidSql})";
-                    await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<Syllabus>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{request.volumeId}") }))
+                    await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<Syllabus>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{request.school}") }))
                     {
                         List<SyllabusTree> trees = SyllabusService.ListToTree(item.children);
                         SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope = item.scope, trees = trees, volumeId = item.volumeId, auth = item.auth };
@@ -441,7 +450,7 @@ namespace TEAMModelOS.Controllers
                 {
                     code = request.issuer;
                     var queryslt = $"SELECT  value(c) FROM c where c.id in ({sidSql})";
-                    await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Syllabus>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{request.volumeId}") }))
+                    await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Syllabus>(queryText: queryslt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{request.issuer}") }))
                     {
                         List<SyllabusTree> trees = SyllabusService.ListToTree(item.children);
                         SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope = item.scope, trees = trees, volumeId = item.volumeId, auth = item.auth };

+ 20 - 18
TEAMModelOS/Controllers/Syllabus/SyllabusController.cs

@@ -76,7 +76,7 @@ namespace TEAMModelOS.Controllers
                     {
                         try
                         {
-                            syllabus = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").ReadItemAsync<Syllabus>(syllabusTree.id, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                            syllabus = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").ReadItemAsync<Syllabus>(syllabusTree.id, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                         }
                         catch
                         {
@@ -86,25 +86,25 @@ namespace TEAMModelOS.Controllers
                             syllabus = new Syllabus();
                             syllabus.id = syllabusTree.id;
                             syllabus.children = nodes;
-                            syllabus.code = $"Syllabus-{syllabusTree.volumeId}";
+                            syllabus.code = $"Syllabus-{syllabusTree.codeval}";
                             syllabus.pk = "Syllabus";
                             syllabus.ttl = -1;
                             syllabus.volumeId = syllabusTree.volumeId;
                             syllabus.scope = syllabusTree.scope;
-                            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                         }
                         else
                         {
                             syllabus.children = nodes;
                             syllabusTree.auth = syllabus.auth;
-                            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").ReplaceItemAsync<Syllabus>(syllabus,syllabus.id, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").ReplaceItemAsync<Syllabus>(syllabus,syllabus.id, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                         }
 
                     }
                     else {
                         try
                         {
-                            syllabus = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Syllabus>(syllabusTree.id, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                            syllabus = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Syllabus>(syllabusTree.id, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                         }
                         catch
                         {
@@ -114,18 +114,18 @@ namespace TEAMModelOS.Controllers
                             syllabus = new Syllabus();
                             syllabus.id = syllabusTree.id;
                             syllabus.children = nodes;
-                            syllabus.code = $"Syllabus-{syllabusTree.volumeId}";
+                            syllabus.code = $"Syllabus-{syllabusTree.codeval}";
                             syllabus.pk = "Syllabus";
                             syllabus.ttl = -1;
                             syllabus.volumeId = syllabusTree.volumeId;
                             syllabus.scope = syllabusTree.scope;
-                            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                         }
                         else
                         {
                             syllabus.children = nodes;
                             syllabusTree.auth = syllabus.auth;
-                            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                            await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").UpsertItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                         }
                     }
                 }
@@ -134,7 +134,7 @@ namespace TEAMModelOS.Controllers
                     syllabusTree.id = id;
                     Syllabus syllabus = new Syllabus {
                         id = id,
-                        code = $"Syllabus-{syllabusTree.volumeId}",
+                        code = $"Syllabus-{syllabusTree.codeval}",
                         pk = "Syllabus",
                         ttl = -1,
                         volumeId=syllabusTree.volumeId,
@@ -142,9 +142,9 @@ namespace TEAMModelOS.Controllers
                         scope = syllabusTree.scope
                     };
                     if (syllabusTree.scope == "school") {
-                        await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                        await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                     } else {
-                        await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.volumeId}"));
+                        await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").CreateItemAsync<Syllabus>(syllabus, new Azure.Cosmos.PartitionKey($"Syllabus-{syllabusTree.codeval}"));
                     }
                 }
             }
@@ -174,25 +174,27 @@ namespace TEAMModelOS.Controllers
                 if (scope.ToString().Equals("school"))
                 {
                       volume = await client.GetContainer("TEAMModelOS", "School").ReadItemAsync<Volume>($"{volumeId}", new PartitionKey($"{volumeCode}"));
-                      await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<Syllabus>(queryText: $"select value(c) from c ",
-                    requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Syllabus-{volumeId}") }))
+                      await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<Syllabus>(queryText: $"select value(c) from c where c.volumeId='{volumeId}'",
+
+                    requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Syllabus-{volume.school}") }))
                     {
                         List<SyllabusTree> trees = SyllabusService.ListToTree(item.children);
-                        SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope =item.scope, trees = trees ,volumeId=item.volumeId,auth=item.auth};
+                        SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope =item.scope, trees = trees ,volumeId=item.volumeId,auth=item.auth,codeval=volume.school};
                         treeNodes.Add(tree);
                     }
                 }
                 else
                 {
                     volume = await client.GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Volume>($"{volumeId}", new PartitionKey($"{volumeCode}"));
-                    await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Syllabus>(queryText: $"select value(c) from c ",
-                     requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Syllabus-{volumeId}") }))
+                    await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Syllabus>(queryText: $"select value(c) from c where c.volumeId='{volumeId}'",
+                     requestOptions: new QueryRequestOptions() { PartitionKey = new Azure.Cosmos.PartitionKey($"Syllabus-{volume.creatorId}") }))
                     {
                         List<SyllabusTree> trees = SyllabusService.ListToTree(item.children);
-                        SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope = item.scope, trees = trees, volumeId = item.volumeId, auth = item.auth };
+                        SyllabusTreeNode tree = new SyllabusTreeNode() { id = item.id, scope = item.scope, trees = trees, volumeId = item.volumeId, auth = item.auth,codeval=volume.creatorId };
                         treeNodes.Add(tree);
                     }
                 }
+                //对课纲树形结构排序
                 if (volume.syllabusIds.IsNotEmpty())
                 {
                     volume.syllabusIds.ForEach(x =>
@@ -220,7 +222,7 @@ namespace TEAMModelOS.Controllers
         }
 
         /*
-            {"id":"章节id","code":"册别id","scope":"school/private"}
+            {"id":"章节id","code":"学校编码/醍摩豆id","scope":"school/private"}
          */
 
         /// <summary>

+ 5 - 5
TEAMModelOS/Controllers/Syllabus/VolumeController.cs

@@ -61,12 +61,12 @@ namespace TEAMModelOS.Controllers
                 if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
                 if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
                 var client = _azureCosmos.GetCosmosClient();
-                string sql = "select value(c) from c ";
+                string sql =$"select value(c) from c where c.volumeId='{id}'";
                 List<Syllabus> syllabus = new List<Syllabus>();
                 if (scope.ToString().Equals("school"))
                 {
                     var response = await client.GetContainer("TEAMModelOS", "School").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Volume-{code}"));
-                    await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<Syllabus>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{id}") })) {
+                    await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<Syllabus>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{code}") })) {
                         syllabus.Add(item);
                     }
                     if (syllabus.IsNotEmpty())
@@ -84,14 +84,14 @@ namespace TEAMModelOS.Controllers
                                 }
                             }
                         }
-                        var sresponse = await client.GetContainer("TEAMModelOS", "School").DeleteItemsStreamAsync(syllabus.Select(x => x.id).ToList(), $"Syllabus-{id}");
+                        var sresponse = await client.GetContainer("TEAMModelOS", "School").DeleteItemsStreamAsync(syllabus.Select(x => x.id).ToList(), $"Syllabus-{code}");
                     }
                     return Ok(new { code = response.Status });
                 }
                 else
                 {
                     var response = await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Volume-{code}"));
-                    await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Syllabus>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{id}") }))
+                    await foreach (var item in client.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<Syllabus>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Syllabus-{code}") }))
                     {
                         syllabus.Add(item);
                     }
@@ -116,7 +116,7 @@ namespace TEAMModelOS.Controllers
                                 }
                             }
                         }
-                        var sresponse = await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemsStreamAsync(syllabus.Select(x => x.id).ToList(), $"Syllabus-{id}");
+                        var sresponse = await client.GetContainer("TEAMModelOS", "Teacher").DeleteItemsStreamAsync(syllabus.Select(x => x.id).ToList(), $"Syllabus-{code}");
                     }
                     return Ok(new { code = response.Status });
                 }