Pārlūkot izejas kodu

Merge branch 'develop5.0' into TPE/develop5.0

jeff 3 gadi atpakaļ
vecāks
revīzija
13de0ad925

+ 13 - 2
TEAMModelFunction/MonitorServicesBus.cs

@@ -167,6 +167,7 @@ namespace TEAMModelFunction
                     {   ///key不存在则正常进行计算
                         bool condition = false;
                         TimeSpan timeSpan = new TimeSpan(DateTimeOffset.UtcNow.AddMinutes(5).Ticks);
+                        timeSpan = timeSpan - new TimeSpan(DateTimeOffset.UtcNow.Ticks);
                         //准备处理Blob刷新时间
                         long action = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                         await _azureRedis.GetRedisClient(8).StringSetAsync(lockKey, action, expiry: timeSpan);
@@ -175,7 +176,10 @@ namespace TEAMModelFunction
                         var rds = await CheckLockKey(lockKey, action);
                         condition = rds.condition;
                         exist = rds.exist;
-                        await RefreshBlob(name, u);
+                        if (condition || !exist) {
+                            await RefreshBlob(name, u);
+                        }
+                        
                         //使用  CancellationToken 
                         //while (condition || !exist)
                         //{
@@ -185,6 +189,7 @@ namespace TEAMModelFunction
                     else {
                         ///key存在则,则刷新key对应的值
                         TimeSpan timeSpan = new TimeSpan(DateTimeOffset.UtcNow.AddMinutes(5).Ticks);
+                        timeSpan = timeSpan - new TimeSpan(DateTimeOffset.UtcNow.Ticks);
                         long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                         await _azureRedis.GetRedisClient(8).StringSetAsync(lockKey, now, expiry: timeSpan);
                     }
@@ -232,6 +237,7 @@ namespace TEAMModelFunction
             }
         }
         private async Task RefreshBlob(string  name ,string  u) {
+            long statr = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
             var client = _azureStorage.GetBlobContainerClient(name);
             var size = await client.GetBlobsSize(u);
             await _azureRedis.GetRedisClient(8).SortedSetRemoveAsync($"Blob:Catalog:{name}", u);
@@ -243,10 +249,15 @@ namespace TEAMModelFunction
                 foreach (var score in scores)
                 {
                     blobsize = blobsize + score.Score;
-                    //list.Add(new Dictionary<string, double?>() { { score.Element.ToString(), score.Score } });
                 }
             }
             await _azureRedis.GetRedisClient(8).HashSetAsync($"Blob:Record", new RedisValue(name), new RedisValue($"{blobsize}"));
+            long end = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+            long dis = (end - statr)/1000;
+            long timeout = 10;
+            if (dis> timeout) {
+                await _dingDing.SendBotMsg($"ServiceBus,RefreshBlob:空间计算已经超过{timeout}秒\n容器名:{name}\n文件夹:{u}\n计算时长:{dis}", GroupNames.醍摩豆服務運維群組);
+            }
         }
         /// <summary>
         /// 完善课程变更,StuListChange,  originCode是学校编码 则表示名单是学校自定义名单,如果是tmdid则表示醍摩豆的私有名单,scope=school,private。

+ 61 - 53
TEAMModelOS.SDK/Models/Service/FixDataService.cs

@@ -68,66 +68,74 @@ namespace TEAMModelOS.SDK.Models.Service
         /// <returns></returns>
         public  static  async   Task FixBlobContent(CosmosClient client, DingDing _dingDing, AzureStorageFactory _azureStorage, JsonElement data)
         {
-           
-            if (data.TryGetProperty("name", out JsonElement _name))
-            {
-                List<string> names = _name.ToObject<List<string>>();
-                foreach (string name in names)
+            if (data.TryGetProperty("doPrivate", out JsonElement _doPrivate)&& $"{_doPrivate}".Equals("yes",StringComparison.OrdinalIgnoreCase)) {
+                foreach (var cnt in _azureStorage.GetBlobServiceClient().GetBlobContainers())
                 {
-                    List<string> prefixs = new List<string>() { "audio", "doc", "image", "other", "res", "video", "thum" };
-                    var ContainerClient = _azureStorage.GetBlobContainerClient($"{name}");
-                    string scope = "private";
-                    if (data.TryGetProperty("scope", out JsonElement _scope))
-                    {
-                        scope = $"{_scope}";
-                    }
-                    var tb = "Teacher";
-                    if (scope != "private")
+                    if (cnt.Name.Length == 10 && int.TryParse(cnt.Name, out _))
                     {
-                        tb = "School";
+                        await doFixBlob(client, _azureStorage, cnt.Name, "private");
                     }
-                    List<string> ids = new List<string>();
-                    await foreach (var item in client.GetContainer("TEAMModelOS", tb).GetItemQueryIterator<Bloblog>(queryDefinition: new QueryDefinition("select c.id from c "), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Bloblog-{name}") }))
-                    {
-                        ids.Add(item.id);
-                    }
-                    await client.GetContainer("TEAMModelOS", tb).DeleteItemsStreamAsync(ids, $"Bloblog-{name}");
-                    long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
-                    foreach (var prefix in prefixs)
+                }
+            }
+            List<School> schools = new List<School>();
+            await foreach (var item in client.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<School>(queryText: "select value(c) from c", requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey("Base") })) {
+                schools.Add(item);
+            }
+            foreach (var school in schools) {
+                await doFixBlob(client, _azureStorage, school.id, "school");
+            }
+        }
+        private static async Task doFixBlob(CosmosClient client, AzureStorageFactory _azureStorage,string name,string scope) {
+            List<string> prefixs = new List<string>() { "audio", "doc", "image", "other", "res", "video"};
+            var ContainerClient = _azureStorage.GetBlobContainerClient($"{name}");
+            var tb = "Teacher";
+            if (scope != "private")
+            {
+                tb = "School";
+            }
+            List<string> ids = new List<string>();
+            await foreach (var item in client.GetContainer("TEAMModelOS", tb).GetItemQueryIterator<Bloblog>(queryDefinition: new QueryDefinition("select c.id from c "), requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Bloblog-{name}") }))
+            {
+                ids.Add(item.id);
+            }
+            await client.GetContainer("TEAMModelOS", tb).DeleteItemsStreamAsync(ids, $"Bloblog-{name}");
+            long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+            foreach (var prefix in prefixs)
+            {
+                if (prefix.Equals("res"))
+                {
+                    List<string> itemres = await ContainerClient.List(prefix);
+                    if (itemres.IsNotEmpty())
                     {
-                        if (prefix.Equals("res"))
+                        HashSet<string> set = new HashSet<string>();
+                        itemres.ForEach(x =>
+                        {
+                            var uri = x.Split("/");
+                            set.Add($"res/{uri[1]}");
+                        });
+                        foreach (var item in set)
                         {
-                            List<string> itemres = await ContainerClient.List(prefix);
-                            if (itemres.IsNotEmpty()) {
-                                HashSet<string> set = new HashSet<string>();
-                                itemres.ForEach(x =>
-                                {
-                                    var uri = x.Split("/");
-                                    set.Add($"res/{uri[1]}");
-                                });
-                                foreach (var item in set)
-                                {
-                                    var urlsSize = await ContainerClient.GetBlobsSize(item);
-                                    var url = item;
-                                    if (!item.EndsWith(".hte", StringComparison.OrdinalIgnoreCase) && !item.EndsWith(".HTEX", StringComparison.OrdinalIgnoreCase))
-                                    {
-                                        url += ".HTEX";
-                                    }
-                                    Bloblog bloblog = new Bloblog { id = Guid.NewGuid().ToString(), code = $"Bloblog-{name}", pk = "Bloblog", time = now, url = url, size = urlsSize != null && urlsSize.HasValue ? urlsSize.Value : 0, type = prefix };
-                                    await client.GetContainer("TEAMModelOS", tb).UpsertItemAsync(bloblog, new Azure.Cosmos.PartitionKey(bloblog.code));
-                                }
+                            var urlsSize = await ContainerClient.GetBlobsSize(item);
+                            var url = item;
+                            if (!item.EndsWith(".hte", StringComparison.OrdinalIgnoreCase) && !item.EndsWith(".HTEX", StringComparison.OrdinalIgnoreCase))
+                            {
+                                url += ".HTEX";
                             }
+                            Bloblog bloblog = new Bloblog { id = Guid.NewGuid().ToString(), code = $"Bloblog-{name}", pk = "Bloblog", time = now, url = url, size = urlsSize != null && urlsSize.HasValue ? urlsSize.Value : 0, type = prefix };
+                            await client.GetContainer("TEAMModelOS", tb).UpsertItemAsync(bloblog, new Azure.Cosmos.PartitionKey(bloblog.code));
                         }
-                        else {
-                            List<string> items = await ContainerClient.List(prefix);
-                            if (items.IsNotEmpty()) {
-                                foreach (var item in items)
-                                {
-                                    var urlsSize = await ContainerClient.GetBlobsSize(item);
-                                    Bloblog bloblog = new Bloblog { id = Guid.NewGuid().ToString(), code = $"Bloblog-{name}", pk = "Bloblog", time = now, url = item, size = urlsSize != null && urlsSize.HasValue ? urlsSize.Value : 0, type = prefix };
-                                    await client.GetContainer("TEAMModelOS", tb).UpsertItemAsync(bloblog, new Azure.Cosmos.PartitionKey(bloblog.code));
-                                }
-                            }
+                    }
+                }
+                else
+                {
+                    List<string> items = await ContainerClient.List(prefix);
+                    if (items.IsNotEmpty())
+                    {
+                        foreach (var item in items)
+                        {
+                            var urlsSize = await ContainerClient.GetBlobsSize(item);
+                            Bloblog bloblog = new Bloblog { id = Guid.NewGuid().ToString(), code = $"Bloblog-{name}", pk = "Bloblog", time = now, url = item, size = urlsSize != null && urlsSize.HasValue ? urlsSize.Value : 0, type = prefix };
+                            await client.GetContainer("TEAMModelOS", tb).UpsertItemAsync(bloblog, new Azure.Cosmos.PartitionKey(bloblog.code));
                         }
                     }
                 }

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

@@ -576,6 +576,7 @@
 						localStorage.setItem('scrollDis',scrollDom.getPosition().scrollTop)
 						
 						that.$EventBus.$emit('doRefresh')
+						that.$EventBus.$emit('hasDrag')
 					}
 					// 将鼠标事件绑定到 document 上
 					document.addEventListener("mousemove", mousemove);

+ 130 - 114
TEAMModelOS/ClientApp/src/view/answersheet/index.vue

@@ -14,19 +14,19 @@
 				<div class="sheet-groups">
 					<div v-for="(group,groupIndex) in groups" :key="groupIndex" class="sheet-group-item">
 						<div v-if="group.type === 'objective'">
-							<BaseTitleEditor :ids="'titleEditor' + groupIndex"
-								:content="titleContent(groupIndex,group)" ref="objectiveTitleRef"></BaseTitleEditor>
+							<BaseTitleEditor :ids="'titleEditor' + groupIndex" :content="titleContent(groupIndex,group)"
+								ref="objectiveTitleRef"></BaseTitleEditor>
 							<SheetObjective :items="items" v-show="groupItems.objectiveItems.length"
 								@onRendered="onRendered"></SheetObjective>
 						</div>
 						<div v-else-if="group.type === 'complete'">
-							<BaseTitleEditor :ids="'titleEditor' + groupIndex"
-								:content="titleContent(groupIndex,group)" ref="completeTitleRef"></BaseTitleEditor>
+							<BaseTitleEditor :ids="'titleEditor' + groupIndex" :content="titleContent(groupIndex,group)"
+								ref="completeTitleRef"></BaseTitleEditor>
 							<SheetComplete :items="items" v-if="groupItems.completeItems.length"></SheetComplete>
 						</div>
 						<div v-else>
-							<BaseTitleEditor :ids="'titleEditor' + groupIndex"
-								:content="titleContent(groupIndex,group)" ref="subjectiveTitleRef"></BaseTitleEditor>
+							<BaseTitleEditor :ids="'titleEditor' + groupIndex" :content="titleContent(groupIndex,group)"
+								ref="subjectiveTitleRef"></BaseTitleEditor>
 							<SheetSubjective :items="groupItems.subjectiveItems"
 								v-show="groupItems.subjectiveItems.length"></SheetSubjective>
 						</div>
@@ -37,7 +37,8 @@
 		</div>
 		<div class="sheet-right">
 			<Button @click="goBack">{{ $t('answerSheet.back') }}</Button>
-			<Button @click="doDownload" class="btn-download" v-if="curPaper.id" :loading="isLoading">{{ !isLoading ? $t('answerSheet.print') : $t('answerSheet.loading') }}</Button>
+			<Button @click="doDownload" class="btn-download" v-if="curPaper.id"
+				:loading="isLoading">{{ !isLoading ? $t('answerSheet.print') : $t('answerSheet.loading') }}</Button>
 			<div>
 				<!-- <p class="sheet-right-title">基础设置</p>
 				<div>
@@ -78,23 +79,26 @@
 						<InputNumber :max="100" :min="0" v-model="addType.everyScore" @on-change="renderAddItem">
 						</InputNumber>
 						<span style="margin: 0 10px;">{{ $t('answerSheet.tip5') }}</span>
-						<span v-if="activeTab === '0' || activeTab === '1'" >
+						<span v-if="activeTab === '0' || activeTab === '1'">
 							<span>{{ $t('answerSheet.tip6') }} </span>
 							<InputNumber :max="8" :min="0" v-model="addType.everyOpts" @on-change="renderAddItem">
 							</InputNumber>
-							<span style="margin: 0 10px;">{{ $t('answerSheet.tip19') }}{{ activeTab === '0' ? $t('answerSheet.tip7') : $t('answerSheet.tip8') }}</span>
+							<span
+								style="margin: 0 10px;">{{ $t('answerSheet.tip19') }}{{ activeTab === '0' ? $t('answerSheet.tip7') : $t('answerSheet.tip8') }}</span>
 						</span>
 						<span v-if="activeTab === '3'">
 							<span>,{{ $t('answerSheet.tip9') }} </span>
-							<InputNumber :max="2000" :min="100" v-model="addType.maxWords" :active-change="false"></InputNumber>
+							<InputNumber :max="2000" :min="100" v-model="addType.maxWords" :active-change="false">
+							</InputNumber>
 							<span> {{ $t('answerSheet.tip10') }} </span>
 						</span>
 						<span v-if="activeTab === '4'">
 							<span> {{ $t('answerSheet.tip9') }} </span>
-							<InputNumber :max="30" :min="1" v-model="addType.maxLines" :active-change="false"></InputNumber>
+							<InputNumber :max="30" :min="1" v-model="addType.maxLines" :active-change="false">
+							</InputNumber>
 							<span> {{ $t('answerSheet.tip11') }}</span>
 						</span>
-						
+
 					</div>
 				</div>
 				<p v-show="indexErr" style="color: red;">* {{ $t('answerSheet.tip12') }}</p>
@@ -108,7 +112,8 @@
 								<span> {{ $t('answerSheet.tip5') }} </span>
 								<span v-if="activeTab === '0' || activeTab === '1'" style="margin-left: 10px;">
 									<InputNumber :max="100" :min="0" v-model="item.opts"></InputNumber>
-									<span> 个{{ activeTab === '0' ? $t('answerSheet.tip7') : $t('answerSheet.tip8') }}</span>
+									<span>
+										个{{ activeTab === '0' ? $t('answerSheet.tip7') : $t('answerSheet.tip8') }}</span>
 								</span>
 							</div>
 						</div>
@@ -144,9 +149,9 @@
 				type: String,
 				default: "",
 			},
-			paper:{
-				type:Object,
-				default:() => {}
+			paper: {
+				type: Object,
+				default: () => {}
 			}
 		},
 		components: {
@@ -159,30 +164,30 @@
 		},
 		data(vm) {
 			return {
-				curPaper:{
-					id:null
+				curPaper: {
+					id: null
 				},
 				indexErr: false,
-				sheetId:null,
+				sheetId: null,
 				addItems: [],
 				addType: {
 					startIndex: null,
 					endIndex: null,
 					everyScore: null,
 					everyOpts: null,
-					maxWords:800,
-					maxLines:10
+					maxWords: 800,
+					maxLines: 10
 				},
 				isShowAdd: false,
-				isShowErCode:false,
-				isShowLines:false,
+				isShowErCode: false,
+				isShowLines: false,
 				activeTab: '0',
 				groups: [],
 				isLoading: false,
 				isColumn: false,
 				isRouterAlive: true,
 				isRender: true,
-				isFromExam:false,
+				isFromExam: false,
 				pages: [],
 				items: [],
 				groupItems: {
@@ -196,12 +201,13 @@
 					objective: vm.$t('answerSheet.objective'),
 					complete: vm.$t('answerSheet.complete'),
 					subjective: vm.$t('answerSheet.subjective')
-				}
+				},
+				hasModify:false
 			};
 		},
 		created() {
 			let routerPaper = this.$route.params.paper || this.paper
-			console.log('答题卡路由数据:',routerPaper)
+			console.log('答题卡路由数据:', routerPaper)
 			this.curPaper = routerPaper
 			this.isFromExam = Boolean(routerPaper && routerPaper.examCode)
 			this.$store.commit('clearAllConfig')
@@ -209,6 +215,7 @@
 				this.$store.commit('clearFixArr')
 				this.$store.commit('clearIsNewPage')
 				this.$store.commit('setPaper', routerPaper)
+				routerPaper.sheet && this.setSheetConfig(routerPaper)
 				if (routerPaper.item === null) {
 					this.$store.commit('setCreateModal', 'diy')
 				} else {
@@ -222,7 +229,25 @@
 
 		},
 		methods: {
-			onTabClick(type){
+			
+			async setSheetConfig(routerPaper){
+				let sheetConfig = await this.getSheetConfigById(routerPaper.sheet,routerPaper.code,routerPaper.scope)
+				console.log(sheetConfig)
+			},
+
+			getSheetConfigById(id,code,scope) {
+				return new Promise((r, j) => {
+					this.$api.evaluation.findSheet({
+						"id": id,
+						"code": code.replace('Paper-',''),
+						"scope": scope
+					}).then(res => {
+						r(res.config)
+					})
+				})
+			},
+
+			onTabClick(type) {
 				this.activeTab = type
 			},
 			onAddType(type) {
@@ -233,8 +258,8 @@
 					endIndex: null,
 					everyScore: null,
 					everyOpts: (type === '0' || type === '1') ? null : 1,
-					maxWords:800,
-					maxLines:10
+					maxWords: 800,
+					maxLines: 10
 				}
 			},
 
@@ -247,7 +272,7 @@
 				this.indexErr = val < this.addType.startIndex || (!val && !this.addType.startIndex)
 				this.renderAddItem()
 			},
-			
+
 			/* 点击添加题型 */
 			doAddType() {
 				if (this.isAddInfoComplete) {
@@ -267,75 +292,55 @@
 			},
 			/* 打印答题卡 */
 			doDownload() {
-				this.isLoading = true
-				this.$EventBus.$emit('onCreateSheet')
-				this.doSaveSheet().then(async res => {
-					let paperInfo = this.$store.state.answerSheet.paperItem
-					this.sheetId = res.config.id
-					if(this.isFromExam){
-						this.$EventBus.$emit('createSheetId',res.config.id)
-					}else{
-						// await this.refreshPaperSheet(paperInfo,res.config.id)
-						// await this.relatePaperSheet(paperInfo,res.config.id)//绑定废弃
-					}
-					this.getPdf().then(r => {
-						this.isLoading = false
+				if(this.curPaper.sheet && this.hasModify){
+					this.$Modal.confirm({
+						title: '更新提示',
+						content: '检测到答题卡有更新,打印答题卡会覆盖原本答题卡数据,是否继续打印?',
+						onOk: () => {
+							this.isLoading = true
+							this.$EventBus.$emit('onCreateSheet')
+							this.doSaveSheet().then(async res => {
+								let paperInfo = this.$store.state.answerSheet.paperItem
+								this.sheetId = res.config.id
+								if (this.isFromExam) {
+									this.$EventBus.$emit('createSheetId', res.config.id)
+								}
+								this.getPdf().then(r => {
+									this.isLoading = false
+								})
+							}).catch(err => {
+								console.log(err)
+								this.isLoading = false
+							})
+						}
 					})
-				}).catch(err => {
-					console.log(err)
-					this.isLoading = false
-				})
-			},
-			
-			/* 更新试卷的sheet字段 */
-			// refreshPaperSheet(paperInfo,sheetId){
-			// 	return new Promise(async (r,j) => {
-			// 		console.log(paperInfo)
-			// 		paperInfo.sheet = sheetId
-			// 		let blobPaper = await this.$evTools.createBlobPaper(paperInfo)
-			// 		console.log(blobPaper)
-			// 		// 首先保存新题目的JSON文件到Blob 然后返回URL链接
-			// 		let paperFile = new File([JSON.stringify(blobPaper)], "index.json");
-			// 		// 获取初始化Blob需要的数据
-			// 		let sasData = paperInfo.scope === 'private' ? await this.$tools
-			// 		.getPrivateSas() : await this.$tools.getSchoolSas()
-			// 		//初始化Blob
-			// 		let containerClient = new blobTool(sasData.url, sasData.name, sasData.sas, paperInfo.scope)
-			// 		containerClient.upload(paperFile,'paper/' + paperInfo.name, undefined, false).then(res => {
-			// 			r(200)
-			// 		}).catch(e => j(e))
-			// 	})
-			// },
-			
-			/**
-			 * 关联试卷ID和答题卡ID
-			 *  已废弃liqk
-			 * */ 
-			relatePaperSheet(paperInfo,sheetId){
-				return new Promise((r,j) => {
-					this.$api.evaluation.upsertPaperSheet({
-						"id": paperInfo.id,
-						"code": paperInfo.code.replace('Paper-',''),
-						"scope": paperInfo.scope,
-						"sheet": sheetId
-					}).then(res => {
-						if(!res.error){
-							r(res)
-						}else{
-							j(res.error)
+				}else{
+					this.isLoading = true
+					this.$EventBus.$emit('onCreateSheet')
+					this.doSaveSheet().then(async res => {
+						let paperInfo = this.$store.state.answerSheet.paperItem
+						this.sheetId = res.config.id
+						if (this.isFromExam) {
+							this.$EventBus.$emit('createSheetId', res.config.id)
 						}
-					}).catch(err => j(err))
-				})
+						this.getPdf().then(r => {
+							this.isLoading = false
+						})
+					}).catch(err => {
+						console.log(err)
+						this.isLoading = false
+					})
+				}
+				
 			},
-			
 			/* 保存答题卡模板数据 */
-			doSaveSheet(){
-				return new Promise((r,j) => {
+			doSaveSheet() {
+				return new Promise((r, j) => {
 					let paperInfo = this.$store.state.answerSheet.paperItem
 					let configParams = this.$store.state.answerSheet.config
 					let curCode = paperInfo.examCode || paperInfo.code
 					let curScope = paperInfo.examScope || paperInfo.scope
-					if(paperInfo.sheet){
+					if (paperInfo.sheet) {
 						configParams.id = paperInfo.sheet
 					}
 					configParams.pageHeight = Number(configParams.pageHeight.toFixed())
@@ -343,11 +348,11 @@
 					configParams.pageCount = this.$store.state.answerSheet.pages
 					configParams.itemCount = this.$store.state.answerSheet.paperItem.item.length
 					// configParams.code = curCode.replace('Paper-','')
-					configParams.code = curCode.replace('Paper-','').replace('Exam-','') //如果是评测修改code会有问题
+					configParams.code = curCode.replace('Paper-', '').replace('Exam-', '') //如果是评测修改code会有问题
 					configParams.school = curScope === 'school' ? this.$store.state.userInfo.schoolCode : ''
 					configParams.scope = curScope
-					configParams.creatorId =  this.$store.state.userInfo.TEAMModelId
-					console.log('答题卡数据参数',configParams)
+					configParams.creatorId = this.$store.state.userInfo.TEAMModelId
+					console.log('答题卡数据参数', configParams)
 					// r(configParams)
 					/**
 					 * 这里有参数调整 liqk
@@ -358,9 +363,9 @@
 						owner: paperInfo.owner,
 						sheet: configParams
 					}).then(res => {
-						if(!res.error){
+						if (!res.error) {
 							r(res)
-						}else{
+						} else {
 							j(res.error)
 						}
 					}).catch(err => j(err))
@@ -371,13 +376,15 @@
 				let params = {}
 				let curEditPaper = localStorage.getItem('c_edit_paper')
 				// 如果是从新建试卷或者编辑试卷 跳转过来的 则返回过去的时候带上编辑的信息
-				if(this.$route.params.paper && (this.fromRouter === 'newSchoolPaper' || this.fromRouter === 'newPrivatePaper') && curEditPaper){
+				if (this.$route.params.paper && (this.fromRouter === 'newSchoolPaper' || this.fromRouter ===
+						'newPrivatePaper') && curEditPaper) {
 					params = {
-						paper:JSON.parse(curEditPaper)
+						paper: JSON.parse(curEditPaper)
 					}
 				}
+				console.log(params)
 				// 如果是从试卷库预览试卷跳转过来的 就返回试卷库
-				if(this.$route.params.paper && (this.fromRouter === 'schoolBank' || this.fromRouter === 'personalBank')){
+				if (this.$route.params.paper && (this.fromRouter === 'schoolBank' || this.fromRouter === 'personalBank')) {
 					params = {
 						tabName: 'paper'
 					}
@@ -471,9 +478,10 @@
 						score: addInfo.everyScore,
 						opts: addInfo.everyOpts,
 						blankCount: 1,
-						maxWords:this.activeTab === '3' ? addInfo.maxWords : null,
-						maxLines:this.activeTab === '4' ? addInfo.maxLines : null,
-						type: this.activeTab === '0' ? 'single' : this.activeTab === '1' ? 'complete' : 'subjective'
+						maxWords: this.activeTab === '3' ? addInfo.maxWords : null,
+						maxLines: this.activeTab === '4' ? addInfo.maxLines : null,
+						type: this.activeTab === '0' ? 'single' : this.activeTab === '1' ? 'complete' :
+							'subjective'
 					})
 				}
 				this.addItems = addItems
@@ -482,16 +490,16 @@
 		mounted: function() {
 			this.doRender()
 			this.$EventBus.$off('deleteItem')
-			this.$EventBus.$on('deleteItem',val => {
+			this.$EventBus.$on('deleteItem', val => {
 				console.log(val)
-				if(val === '0'){
+				if (val === '0') {
 					this.groups = this.groups.filter(i => i.type !== 'complete')
 					this.items = this.items.filter(i => i.type !== 'complete')
-				}else if (val === 'objective'){
+				} else if (val === 'objective') {
 					let objectiveTypes = ["single", "multiple", "judge"];
 					this.groups = this.groups.filter(i => i.type !== 'objective')
 					this.items = this.items.filter(i => !objectiveTypes.includes(i.type))
-				}else{
+				} else {
 					this.groups = this.groups.filter(i => i.items.length)
 				}
 				this.$EventBus.$emit('doRefresh')
@@ -499,14 +507,20 @@
 			this.$EventBus.$off('titleMovePage')
 			this.$EventBus.$on('titleMovePage', val => {
 				this.$nextTick(() => {
-					console.log('有标题跨页',val)
-					if(val.type === 'subjective'){
-						this.$refs.subjectiveTitleRef[0].$el.style.marginTop = SVG_BORDER_MB * 2  + val.height + 40 + 'px'
-					}else{
-						this.$refs.completeTitleRef[0].$el.style.marginTop = SVG_BORDER_MB * 2  + val.height + 40 + 'px'
+					console.log('有标题跨页', val)
+					if (val.type === 'subjective') {
+						this.$refs.subjectiveTitleRef[0].$el.style.marginTop = SVG_BORDER_MB * 2 + val
+							.height + 40 + 'px'
+					} else {
+						this.$refs.completeTitleRef[0].$el.style.marginTop = SVG_BORDER_MB * 2 + val
+							.height + 40 + 'px'
 					}
 				})
 			})
+			this.$EventBus.$off("hasDrag")
+			this.$EventBus.$on("hasDrag", () => {
+			  this.hasModify = true
+			});
 		},
 		beforeRouteEnter(to, from, next) {
 			next(vm => {
@@ -514,9 +528,10 @@
 			})
 		},
 		beforeRouteLeave(to, from, next) {
-			if(to.name === 'newSchoolPaper' || to.name === 'newPrivatePaper' || to.name === 'schoolBank' || to.name === 'personalBank'){
+			if (to.name === 'newSchoolPaper' || to.name === 'newPrivatePaper' || to.name === 'schoolBank' || to.name ===
+				'personalBank') {
 				// 设置下一个路由的 meta
-				to.meta.isKeep = true;  // 让 A 缓存,即不刷新
+				to.meta.isKeep = true; // 让 A 缓存,即不刷新
 			}
 			next();
 		},
@@ -543,7 +558,8 @@
 				return (groupIndex, group) => {
 					let totalScore = group.items.length ? group.items.map(i => i.score).reduce((a, b) => a + b) : 0
 					let type = this.typeList[group.type]
-					return this.numberConvertToUppercase(groupIndex + 1) + '、' + type + this.$t('answerSheet.tip16') + group.items.length +
+					return this.numberConvertToUppercase(groupIndex + 1) + '、' + type + this.$t('answerSheet.tip16') +
+						group.items.length +
 						this.$t('answerSheet.tip17') + totalScore + this.$t('answerSheet.tip18')
 				}
 			}

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

@@ -5,7 +5,7 @@
 		 :isFilterPaper="isFilterPaper"
 		 @onSearchChange="onSearchChange"
 		 @onCloseSearch="onCloseSearch"
-		   v-if="!isPreview"></BaseFilter>
+		   v-show="!isPreview"></BaseFilter>
 
 		<!-- 空数据展示 -->
 		<div v-if="paperList.length === 0" class="no-data-text">

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

@@ -165,18 +165,6 @@
 			}
 			next();
 		},
-		watch: {
-			paperScrollTop: {
-				handler(n) {
-					// console.log(n)
-				}
-			},
-			// $route( to , from ){   
-			//    if(from.name !== 'answerSheet' && (to.name === 'schoolBank' || to.name === 'personalBank')){
-			// 	  this.onShowPaperList()
-			//    }
-			//  }
-		}
 	}
 </script>
 <style src="./index.less" lang="less" scoped></style>

+ 7 - 5
TEAMModelOS/ClientApp/src/view/evaluation/components/BaseExerciseList.vue

@@ -63,7 +63,7 @@
 					</div>
 					<div class="item-btn-toggle" @click.stop v-show="isShowTools && !isPreview">
 						<template v-if="!isExamPaper">
-							<InputNumber v-if="item.type !== 'compose'" :max="item.score + surPlusScore" :min="0" :step="0.5" v-model="item.score" style="display: inline-block ;width: 50px;margin-right: 10px;height: 30px;"
+							<InputNumber v-if="item.type !== 'compose'" :max="item.score + surPlusScore" :min="0" :step="0.5" v-model="item.score" style="display: inline-block ;width: 60px;margin-right: 10px;height: 30px;"
 							 @click.stop></InputNumber>
 							 <span style="margin-right: 10px;" v-if="item.type === 'compose'">{{ getComposeScore(item) }}</span>
 							<span style="margin-right: 10px;">{{$t('evaluation.paperList.score')}}</span>
@@ -520,9 +520,9 @@
 							} else {
 								// 如果不能整除 则前面所有取整 最后一题加上余数 即可完成配分
 								let integerScore = parseInt(item.score / item.list.length)
-								let lastItem = exerciseIndex === item.list.length - 1
+								// let lastItem = exerciseIndex === item.list.length - 1
 								// exercise.score = lastItem ? integerScore + remainder : integerScore
-								exercise.score = exerciseIndex > remainder ? integerScore : integerScore + 1
+								exercise.score = exerciseIndex + 1 > remainder ? integerScore : integerScore + 1
 							}
 							listItem.score = exercise.score
 							
@@ -530,9 +530,9 @@
 								exercise.children.forEach((child,childIndex) => {
 									let remainder = exercise.score % exercise.children.length
 									let integerScore = parseInt(exercise.score / exercise.children.length)
-									let lastItem = childIndex === exercise.children.length - 1
+									// let lastItem = childIndex === exercise.children.length - 1
 									// child.score = lastItem ? integerScore + remainder : integerScore
-									child.score = childIndex > remainder ? integerScore : integerScore + 1
+									child.score = childIndex + 1 > remainder ? integerScore : integerScore + 1
 								})
 							}
 							
@@ -544,6 +544,8 @@
 					this.$parent.viewModel = 'type'
 					this.$parent.paperInfo.multipleRule = this.multipleRule || 1
 					this.typeScoreModel = false
+					console.log(this.groupList)
+					console.log(this.surPlusScore)
 					this.$emit('scoreUpdate', this.surPlusScore)
 				}
 

+ 12 - 5
TEAMModelOS/ClientApp/src/view/evaluation/index/CreatePaper.vue

@@ -737,7 +737,7 @@
 							this.isLoading = true
 							let isPaperExist = await this.isPaperExist(this.evaluationInfo.name)
 							let isContainerFull = await this.isContainerFull()
-							if (!isPaperExist) {
+							if (!isPaperExist || (this.isEditPaper && this.evaluationInfo.name === this.oldPaper.name)) {
 								if (list.length) {
 									// 拿到题型顺序的试题数组进行拼接
 									let arr = []
@@ -1204,9 +1204,15 @@
 			},
 			/* 渲染需要编辑的试卷信息 */
 			async doRender(paper) {
-				console.log('传进来的paper')
-				console.log(paper)
-				localStorage.setItem('c_edit_paper',JSON.stringify(paper))
+				if(paper.paperGrade){
+					console.log('传进来缓存的paper')
+					console.log(paper)
+					this.evaluationInfo = paper
+					this.oldPaper = JSON.parse(JSON.stringify(this.evaluationInfo))
+					return 
+				}
+				console.log('渲染的试卷',paper)
+				// localStorage.setItem('c_edit_paper',JSON.stringify(paper))
 				let schoolInfo = null
 				if (paper.scope === 'school') {
 					schoolInfo = await this.getSchoolBaseInfo()
@@ -1254,6 +1260,7 @@
 			this.$EventBus.$on('onBackToTop', () => {
 				this.handleBackToTop()
 			})
+			
 		},
 
 		computed: {
@@ -1286,7 +1293,7 @@
 		beforeRouteLeave(to, from, next) {
 			if(to.name === 'answerSheet'){
 				// 设置下一个路由的 meta
-				from.meta.isKeep = true;  // 让 A 缓存,即不刷新
+				// from.meta.isKeep = true;  // 让 A 缓存,即不刷新
 			}
 			if(to.name === 'schoolBank' || to.name === 'personalBank'){
 				to.meta.isKeep = false

+ 8 - 2
TEAMModelOS/ClientApp/src/view/evaluation/index/TestPaper.vue

@@ -161,13 +161,16 @@
 		},
 		methods: {
 			goAnswerSheet(){
+				if(!this.isExamPaper){
+					localStorage.setItem('c_edit_paper',JSON.stringify(this.paperInfo))
+				}
+				console.log(this.paperInfo)
 				this.$router.push({
 					name: 'answerSheet',
 					params: {
 						paper: this.paperInfo
 					}
 				})
-				// this.isShowAnswerSheet = true
 			},
 			/**
 			 * 标题切换
@@ -313,7 +316,10 @@
 			},
 			ruleType() {
 				return this.paperInfo.markConfig ? this.paperInfo.markConfig.type : 0
-			}
+			},
+			isSchool() {
+				return this.$route.name === 'newSchoolPaper'
+			},
 		},
 		watch: {
 			paper: {

+ 1 - 1
TEAMModelOS/ClientApp/src/view/settings/BaseApplyForm.vue

@@ -242,7 +242,7 @@
 		},
 		computed:{
 			isChinaSite(){
-				return this.$store.state.config.srvAdr !== 'China'
+				return this.$store.state.config.srvAdr === 'China'
 			}
 		}
 	}

+ 15 - 27
TEAMModelOS/Controllers/Paper/SheetConfigController.cs

@@ -5,25 +5,13 @@ using System;
 using System.Collections.Generic;
 using System.IdentityModel.Tokens.Jwt;
 using System.Linq;
-using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
-using TEAMModelOS.Models.Dto;
 using TEAMModelOS.SDK.Models;
-using TEAMModelOS.SDK;
-using TEAMModelOS.SDK.Context.Constant.Common;
 using TEAMModelOS.SDK.DI;
-using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
 using TEAMModelOS.SDK.Extension;
-using TEAMModelOS.SDK;
-using TEAMModelOS.SDK.Helper.Common.StringHelper;
 using TEAMModelOS.Models;
 using Microsoft.Extensions.Options;
-using TEAMModelOS.SDK.Models.Cosmos;
-using Microsoft.AspNetCore.Authorization;
-using TEAMModelOS.Filter;
-using StackExchange.Redis;
-using TEAMModelOS.SDK.Models.Cosmos.Common.Inner;
 using TEAMModelOS.Services.Common;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
 using Azure;
@@ -204,6 +192,9 @@ namespace TEAMModelOS.Controllers.Common
                 request.TryGetProperty("owner", out JsonElement _owner);
                 var client = _azureCosmos.GetCosmosClient();
                 SheetConfig sheet = _sheet.ToObject<SheetConfig>();
+                if (sheet == null) { 
+                    return BadRequest("sheet params is null!");
+                }
                 if (!sheet.code.StartsWith("SheetConfig-")) {
                     sheet.code = $"SheetConfig-{sheet.code}";
                 }
@@ -228,22 +219,19 @@ namespace TEAMModelOS.Controllers.Common
                         var ps = exam.papers.Where(p => p.id == $"{_paperId}").FirstOrDefault();
                         if (ps != null)
                         {
-                            if (string.IsNullOrEmpty(ps.sheet))
+                            if (!string.IsNullOrEmpty(ps.sheet))
                             {
-                                sheet.id = await SheetService.genSheetId(client,_dingDing,_option, sheet.code, tbname);
-                                exam.papers.ForEach(x =>
-                                {
-                                    if (x.id.Equals($"{_paperId}"))
-                                    {
-                                        x.sheet = sheet.id;
-                                    }
-                                });
-                                exam = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync<ExamInfo>(exam, $"{_examId}", new PartitionKey($"{code}"));
+                                await client.GetContainer("TEAMModelOS", tbname).DeleteItemStreamAsync($"{ps.sheet}", new PartitionKey(sheet.code));
                             }
-                            else
+                            sheet.id = await SheetService.genSheetId(client, _dingDing, _option, sheet.code, tbname);
+                            exam.papers.ForEach(x =>
                             {
-                                sheet.id = ps.sheet;
-                            }
+                                if (x.id.Equals($"{_paperId}"))
+                                {
+                                    x.sheet = sheet.id;
+                                }
+                            });
+                            exam = await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync<ExamInfo>(exam, $"{_examId}", new PartitionKey($"{code}"));
                         }
                         else
                         {
@@ -304,8 +292,8 @@ namespace TEAMModelOS.Controllers.Common
             }
             catch (Exception e)
             {
-                await _dingDing.SendBotMsg($"OS,{_option.Location},common/SheetConfig/upsert()\n{e.Message}", GroupNames.醍摩豆服務運維群組);
-                return BadRequest(e.StackTrace);
+                await _dingDing.SendBotMsg($"OS,{_option.Location},common/SheetConfig/upsert()\n{e.Message}{e.StackTrace}", GroupNames.醍摩豆服務運維群組);
+                return BadRequest(e.Message);
             }
         }
 

+ 13 - 8
TEAMModelOS/Controllers/School/SchoolController.cs

@@ -1128,11 +1128,12 @@ namespace TEAMModelOS.Controllers
                                         var json = await JsonDocument.ParseAsync(response.ContentStream);
 
                                         //軟體
-                                        Teacher teacherHimself = json.ToObject<Teacher>();
-                                        teacherHimself.size = teacherHimself.size - orgTeacherSize + teacher.size;
-
+                                        // Teacher teacherHimself = json.ToObject<Teacher>();
+                                        //teacherHimself.size = teacherHimself.size - orgTeacherSize + teacher.size;
                                         //最後一起修改
-                                        await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Teacher>(teacherHimself, teacherHimself.id, new PartitionKey("Base"));
+                                        //huanghb 2021,7.21修改 ,不用再统计到Teacher-Base中 ,Teacher-Base只记录教师自己的空间大小,并包含其他学校赠与的空间,其他学校的赠与空间放在School 表的Teacher-hbcn(SchoolTeacher)中SchoolTeacher
+                                        //,并在教师登陆的时候 一并计算个人空间和总空间大小。其中总空间大小包含(个人空间+多个学校累加的空间大小,并且如果退出或者被移除Teacher-Base 的"schools": [],为空,则已经实现自动回收)
+                                        // await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Teacher>(teacherHimself, teacherHimself.id, new PartitionKey("Base"));
                                         await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(teacher, obj.GetProperty("id").ToString(), new PartitionKey($"Teacher-{school_code}"));
                                     }
                                     else
@@ -1188,15 +1189,19 @@ namespace TEAMModelOS.Controllers
                                     var response = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReadItemStreamAsync(teacher.id, new PartitionKey("Base"));
                                     if (response.Status == 200)
                                     {
-                                        var json = await JsonDocument.ParseAsync(response.ContentStream);
+                                       // var json = await JsonDocument.ParseAsync(response.ContentStream);
 
                                         //軟體
-                                        Teacher teacherHimself = json.ToObject<Teacher>();
-                                        teacherHimself.size -= teacherSizeInSchool;
+                                       // Teacher teacherHimself = json.ToObject<Teacher>();
+                                       // teacherHimself.size -= teacherSizeInSchool;
 
                                         // 最後一起修改
+
+
+                                        //huanghb 2021,7.21修改 ,不用再统计到Teacher-Base中 ,Teacher-Base只记录教师自己的空间大小,并包含其他学校赠与的空间,其他学校的赠与空间放在School 表的Teacher-hbcn(SchoolTeacher)中SchoolTeacher
+                                        //,并在教师登陆的时候 一并计算个人空间和总空间大小。其中总空间大小包含(个人空间+多个学校累加的空间大小,并且如果退出或者被移除Teacher-Base 的"schools": [],为空,则已经实现自动回收)
                                         await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "School").ReplaceItemAsync<SchoolTeacher>(teacher, teacher.id, new PartitionKey($"Teacher-{school_code}"));
-                                        await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Teacher>(teacherHimself, teacherHimself.id, new PartitionKey("Base"));
+                                        //await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Teacher>(teacherHimself, teacherHimself.id, new PartitionKey("Base"));
                                     }
                                     else
                                     {

+ 2 - 4
TEAMModelOS/Controllers/Teacher/InitController.cs

@@ -53,8 +53,6 @@ namespace TEAMModelOS.Controllers
         [HttpPost("get-teacher-info")]
         public async Task<IActionResult> GetTeacherInfo(JsonElement request)
         {
-            //Debug
-            //string json = System.Text.Json.JsonSerializer.Serialize(id_token);
             try
             {
                 if (!request.TryGetProperty("id_token", out JsonElement id_token)) return BadRequest();
@@ -65,7 +63,6 @@ namespace TEAMModelOS.Controllers
                 jwt.Payload.TryGetValue("name", out object name);
                 jwt.Payload.TryGetValue("picture", out object picture);
                 List<object> schools = new List<object>();
-                // object schools = null;
                 string defaultschool = null;
                 //TODO 取得Teacher 個人相關數據(課程清單、虛擬教室清單、歷史紀錄清單等),學校數據另外API處理,多校切換時不同
                 var client = _azureCosmos.GetCosmosClient();
@@ -75,7 +72,9 @@ namespace TEAMModelOS.Controllers
                 int total = 0;
                 int tsize = 0;
                 try {
+                    ///教师的个人空间
                     tsize = teacher.size;
+                    ///教师的总空间 包含 个人空间和学校赠送的空间累加
                     total = teacher.size;
                     //检查是否有加入学校,如果加入学校,则当个人空间size是0G的时候,则免费获得一个G空间,但无论加入多少个学校,只能获取一次 1G的免费空间。没有加入学校则默认0G空间,除非自己购买空间
                     int joinCount = 0;
@@ -92,7 +91,6 @@ namespace TEAMModelOS.Controllers
                                 schoolExtobj.time = sc.time;
                                 schoolExtobj.picture = school.RootElement.GetProperty("picture");
                                 joinCount += 1;
-                              
                                 var sctch = await client.GetContainer("TEAMModelOS", "School").ReadItemStreamAsync(id, new PartitionKey($"Teacher-{sc.schoolId}"));
                                 if (sctch.Status == 200)
                                 {

+ 5 - 2
TEAMModelOS/Controllers/XTest/TestController.cs

@@ -105,8 +105,11 @@ namespace TEAMModelOS.Controllers.XTest
         [ProducesDefaultResponseType]
         [HttpGet("test-delete-read")]
         public async Task<IActionResult> TestDelete() {
-            string url = "1234.sse";
-            url = url.Substring(0, url.Length - 4);
+
+            foreach (var cnt in _azureStorage.GetBlobServiceClient().GetBlobContainers()) {
+               Console.WriteLine(cnt.Name);
+            }
+
             await  SendNotification();
             var client = _azureCosmos.GetCosmosClient();
             string aaa = "0";

+ 1 - 1
TEAMModelOS/Services/Common/SheetService.cs

@@ -17,7 +17,7 @@ namespace TEAMModelOS.Services.Common
             string id = $"{Utils.CreatSaltString(7, _num09)}";
             for (int i = 0; i < 10; i++)
             {
-                Response response = await client.GetContainer("TEAMModelOS", tbname).ReadItemStreamAsync($"{id}", new PartitionKey(sheetCode)); ;
+                Response response = await client.GetContainer("TEAMModelOS", tbname).ReadItemStreamAsync($"{id}", new PartitionKey(sheetCode)); 
                 if (response.Status == 404)
                 {
                     break;