Jelajahi Sumber

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

Li 2 tahun lalu
induk
melakukan
de449ac8e3

+ 3 - 3
TEAMModelBI/ClientApp/src/view/index/index.vue

@@ -2338,11 +2338,11 @@ export default {
           console.log(basicsData, standardData, majorData, 7777777)
           if (siteValue.value === 'china') {
             versionsData.value.basics.num = basicsData.length
-            versionsData.value.basics.proportion = Math.round(((basicsData.length / schoolList.length) * 100))
+            versionsData.value.basics.proportion = ((basicsData.length / schoolList.length) * 100).toFixed(1)
             versionsData.value.standard.num = standardData.length
-            versionsData.value.standard.proportion = Math.round(((standardData.length / schoolList.length) * 100))
+            versionsData.value.standard.proportion = ((standardData.length / schoolList.length) * 100).toFixed(1)
             versionsData.value.major.num = majorData.length
-            versionsData.value.major.proportion = Math.round(((majorData.length / schoolList.length) * 100))
+            versionsData.value.major.proportion = ((majorData.length / schoolList.length) * 100).toFixed(1)
             console.log(versionsData.value.standard.proportion, standardData.length, schoolList.length, '占比')
             let dataBasics = {
               title: {

+ 4 - 2
TEAMModelBI/ClientApp/src/view/systemConfig/pushmsg/createdpush.vue

@@ -372,10 +372,10 @@
                       <!-- <div class="skip-title">是否跳转地址</div> -->
                       <div class="skip-content">
                         <div>
-                          <el-switch v-model="constructorData.basic.skipstate" class="ml-2" style="--el-switch-on-color: #13ce66; --el-switch-off-color: #b2bec3" />
+                          <el-switch v-model="constructorData.basic.skipState" class="ml-2" style="--el-switch-on-color: #13ce66; --el-switch-off-color: #b2bec3" />
                         </div>
                       </div>
-                      <div class="skip-url" v-show="constructorData.basic.skipstate">
+                      <div class="skip-url" v-show="constructorData.basic.skipState">
                         <el-input v-model="constructorData.basic.skipUrl" placeholder="填写跳转地址" />
                       </div>
                     </div>
@@ -694,6 +694,8 @@ function pitchonly (val) {
   }
   console.log(val, constructorData.value.receivedata.personage)
 }
+//发布消息
+function publish () { }
 initSchool()
 </script>
 <style scoped>

+ 20 - 7
TEAMModelOS/ClientApp/src/view/artexam/Create.vue

@@ -57,7 +57,7 @@
                 </Form>
                 <!-- 高级设置 -->
                 <Form ref="seniorInfo" :model="artInfo" :rules="trainRule" :label-width="100" class="art-form" label-colon v-show="step == 1">
-                    <h1>{{ $t("train.create.advancedTitle") }}</h1>
+                    <h1 @click="test">{{ $t("train.create.advancedTitle") }}</h1>
                     <!-- 一级指标 -->
                     <CheckboxGroup v-model="artInfo.setting" @on-change="initStatus">
                         <Checkbox v-for="item in quotas" :key="item.id" :label="item.id" class="check-item" :disabled="defaultQuos.includes(item.id)">
@@ -131,8 +131,8 @@ export default {
         let _this = this
         return {
             pdTypeList: this.$GLOBAL.PERIOD_TYPE_LIST(),
-            schoolList:[],
-            examInfoList:[],
+            schoolList: [],
+            examInfoList: [],
             isArea: false,
             defaultQuos: ['quota_2'],
             subjectList: [
@@ -158,7 +158,7 @@ export default {
             step: 0,
             artInfo: {
                 name: "",
-                periodType:"",
+                periodType: "",
                 startTime: 0,
                 endTime: 0,
                 time: [],
@@ -299,6 +299,16 @@ export default {
         }
     },
     methods: {
+        test() {
+            console.log(this.settingDetail, this.getZYData())
+        },
+        getZYData() {
+            if (this.settingDetail['quota_2']?.checked?.checkedKeys?.includes('quota_22') && this.settingDetail['quota_2']?.setting) {
+                return this.settingDetail['quota_2']?.setting['quota_22']?.settings?.find(item => item.subject === "subject_music")
+            } else {
+                return undefined
+            }
+        },
         handleSetTime(value) {
             let start = value[0]
             let end = value[1]
@@ -320,6 +330,7 @@ export default {
             this.settingDetail[data.quoid]["type"] = data.data
         },
         handleSettingChange(data) {
+            console.log(data)
             if (!this.settingDetail[data.quoid])
                 this.settingDetail[data.quoid] = {}
             this.settingDetail[data.quoid]["setting"] = data.data
@@ -400,6 +411,7 @@ export default {
                                 if (this.isArea) {
                                     quoSetting.settings.forEach(setting => {
                                         let infoId = this.$jsFn.uuid()
+                                        console.error(s)
                                         s.task.push({
                                             type,
                                             subject: setting.subject,
@@ -470,7 +482,8 @@ export default {
                         id: sessionStorage.getItem("areaId"),
                         art: params,
                         artExam: this.examInfoList,
-                        schoolId: this.artInfo.schools.length ? this.artInfo.schools : undefined
+                        schoolId: this.artInfo.schools.length ? this.artInfo.schools : undefined,
+                        ArtMusic: this.getZYData()
                     })
                 } else {
                     params.period = {
@@ -479,7 +492,8 @@ export default {
                     }
                     params.periodType = this.curPeriod.periodType
                     promise = this.$api.areaArt.saveArt({
-                        art: params
+                        art: params,
+                        ArtMusic: this.getZYData()
                     })
                 }
                 promise?.then(
@@ -573,7 +587,6 @@ export default {
                             "?" + paperSas.sas,
                             "school"
                         )
-                        debugger
                         reses.forEach((res, index) => {
                             let targetFolder = "exam/" + res.exam.id + "/paper/"
                             //这里评测都是单科处理

+ 120 - 114
TEAMModelOS/ClientApp/src/view/artexam/QuoTree.vue

@@ -1,126 +1,132 @@
 <template>
-    <el-tree show-checkbox :data="treeData" :props="defaultProps" class="quo-tree" node-key="id" ref="quota-tree" :render-content="renderContent" @check="hanldeCheckChange" :render-after-expand="false"></el-tree>
+  <el-tree show-checkbox :data="treeData" :props="defaultProps" class="quo-tree" node-key="id" ref="quota-tree" :render-content="renderContent" @check="hanldeCheckChange" :render-after-expand="false"></el-tree>
 </template>
 
+
 <script>
 import ExamSubject from "./ExamSubject.vue"
 import WorkSubject from "./WorkSubject.vue"
+import SelectMusic from "./SelectMusic.vue"
 export default {
-    components: {
-        ExamSubject,
-        WorkSubject
-    },
-    props: {
-        quoid: {
-            type: String,
-            default: ""
-        },
-        treeData: {
-            type: Array,
-            default: () => {
-                return []
-            }
-        },
-        subjects: {
-            type: Array,
-            default: () => {
-                return []
-            }
-        }
+  components: {
+    ExamSubject,
+    WorkSubject,
+    SelectMusic
+  },
+  props: {
+    quoid: {
+      type: String,
+      default: ""
     },
-    data() {
-        return {
-            defaultProps: {
-                children: "children",
-                label: "name"
-            },
-            settingMap: {}
-        }
+    treeData: {
+      type: Array,
+      default: () => {
+        return []
+      }
     },
-    methods: {
-        renderContent(h, { node, data, store }) {
-            console.log(arguments)
-            let _this = this
-            // 不是最后一个节点则直接渲染label
-            if (node.childNodes.length) {
-                return h("span", {}, node.label)
-            } else {
-                return h(
-                    "div",
-                    {
-                        style: {
-                            width: "100%"
-                        }
-                    },
-                    [
-                        h("span", node.label),
-                        h('Tag', {
-                            class: "type-setting",
-                            props: {
-                                color: 'primary'
-                            },
-                            style: {
-                                display: node.checked && (node.data.type == 1 || node.data.type == 2) ? undefined : "none"
-                            }
-                        }, node.data.type == 1 ? _this.$t('ae.ae0') : node.data.type == 2 ? _this.$t('ae.ae1') : ''),
-                        node.checked && node.data.type === 1
-                            ? h(ExamSubject, {
-                                props: {
-                                    subjects: _this.subjects
-                                },
-                                on: {
-                                    "on-set-exam": (data) => {
-                                        console.log(data)
-                                        _this.$set(_this.settingMap, node.data.id, data)
-                                    }
-                                }
-                            })
-                            : undefined,
-                        node.checked && node.data.type === 2
-                            ? h(WorkSubject, {
-                                props: {
-                                    subjects: _this.subjects
-                                },
-                                on: {
-                                    "on-set-work": (data) => {
-                                        console.log(data)
-                                        _this.$set(_this.settingMap, node.data.id, data)
-                                    }
-                                }
-                            })
-                            : undefined
-                    ]
-                )
+    subjects: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    }
+  },
+  data() {
+    return {
+      defaultProps: {
+        children: "children",
+        label: "name"
+      },
+      settingMap: {}
+    }
+  },
+  methods: {
+    renderContent(h, { node, data, store }) {
+      console.log(arguments)
+      let _this = this
+      // 不是最后一个节点则直接渲染label
+      if (node.childNodes.length) {
+        return h("span", {}, node.label)
+      } else {
+        return h(
+          "div",
+          {
+            style: {
+              width: "100%"
             }
-        },
-        hanldeCheckChange(data, status) {
-            this.$emit('on-check-change', {
-                quoid: this.quoid,
-                data: status
-            })
-        }
-    },
-    mounted() {
-        let quaTree = this.$refs['quota-tree']
-        if (this.quoid === 'quota_2' && quaTree) {
-            quaTree.setCheckedKeys(['quota_21', 'quota_22'])
-            this.hanldeCheckChange(undefined, {
-                checkedKeys: quaTree.getCheckedKeys(),
-                checkedNodes: quaTree.getCheckedNodes()
-            })
-        }
-    },
-    watch: {
-        settingMap: {
-            deep: true,
-            handler(n, o) {
-                this.$emit('on-setting-change', {
-                    quoid: this.quoid,
-                    data: n
+          },
+          [
+            h("span", node.label),
+            h('Tag', {
+              class: "type-setting",
+              props: {
+                color: 'primary'
+              },
+              style: {
+                display: node.checked && (node.data.type == 1 || node.data.type == 2) ? undefined : "none"
+              }
+            }, node.data.type == 1 ? _this.$t('ae.ae0') : node.data.type == 2 ? _this.$t('ae.ae1') : ''),
+            node.checked && node.data.type === 1
+              ? h(ExamSubject, {
+                props: {
+                  subjects: _this.subjects
+                },
+                on: {
+                  "on-set-exam": (data) => {
+                    console.log(data)
+                    _this.$set(_this.settingMap, node.data.id, data)
+                  }
+                }
+              })
+              : undefined,
+            node.checked && node.data.type === 2
+              ? (
+                h(WorkSubject, {
+                  props: {
+                    subjects: _this.subjects,
+                    quoid: _this.quoid
+                  },
+                  on: {
+                    "on-set-work": (data) => {
+                      console.log(_this.settingMap)
+                      _this.$set(_this.settingMap, node.data.id, data)
+                    }
+                  }
                 })
-            }
-        },
+              )
+              : undefined
+          ]
+        )
+      }
+    },
+    hanldeCheckChange(data, status) {
+      this.$emit('on-check-change', {
+        quoid: this.quoid,
+        data: status
+      })
+    }
+  },
+  mounted() {
+    let quaTree = this.$refs['quota-tree']
+    if (this.quoid === 'quota_2' && quaTree) {
+      quaTree.setCheckedKeys(['quota_21', 'quota_22'])
+      this.hanldeCheckChange(undefined, {
+        checkedKeys: quaTree.getCheckedKeys(),
+        checkedNodes: quaTree.getCheckedNodes()
+      })
     }
+  },
+  watch: {
+    settingMap: {
+      deep: true,
+      handler(n, o) {
+        this.$emit('on-setting-change', {
+          quoid: this.quoid,
+          data: n
+        })
+      }
+    },
+  }
 
 }
 </script>
@@ -129,10 +135,10 @@ export default {
 </style>
 <style lang="less">
 .type-setting {
-    float: right;
+  float: right;
 }
 .quo-tree .el-tree-node__content {
-    height: fit-content;
-    align-items: baseline;
+  height: fit-content;
+  align-items: baseline;
 }
 </style>

File diff ditekan karena terlalu besar
+ 58 - 0
TEAMModelOS/ClientApp/src/view/artexam/SelectMusic.vue


+ 83 - 69
TEAMModelOS/ClientApp/src/view/artexam/WorkSubject.vue

@@ -1,87 +1,101 @@
 <template>
-	<div class="content-block">
-		<CheckboxGroup v-model="baseWork.subjects"  @on-change="handleSetWork">
-			<div class="check-item" v-show="subjects.includes('subject_painting')">
-				<!-- <Checkbox label="subject_painting">
+  <div class="content-block">
+    <CheckboxGroup v-model="baseWork.subjects" @on-change="handleSetWork">
+      <div class="check-item" v-show="subjects.includes('subject_painting')">
+        <!-- <Checkbox label="subject_painting">
 					<span class="subject-name">美术</span>
 				</Checkbox> -->
-				<span class="subject-name">{{$t('ae.ae11')}}</span>
-				<WorkSetting v-if="baseWork.subjects.includes('subject_painting')" subject="subject_painting" @on-set-work="handleWorkInfo"></WorkSetting>
-			</div>
-			<div v-show="subjects.includes('subject_music')">
-				<!-- <Checkbox label="subject_music">
+        <span class="subject-name">{{$t('ae.ae11')}}</span>
+        <WorkSetting v-if="baseWork.subjects.includes('subject_painting')" subject="subject_painting" @on-set-work="handleWorkInfo"></WorkSetting>
+      </div>
+      <div v-show="subjects.includes('subject_music')">
+        <!-- <Checkbox label="subject_music">
 					<span class="subject-name">音乐</span>
 				</Checkbox> -->
-				<span class="subject-name">{{$t('ae.ae10')}}</span>
-				<WorkSetting v-if="baseWork.subjects.includes('subject_music')" subject="subject_music" @on-set-work="handleWorkInfo"></WorkSetting>
-			</div>
-		</CheckboxGroup>
-	</div>
+        <span class="subject-name">{{$t('ae.ae10')}}</span>
+        <SelectMusic v-if="quoid=== 'quota_2'" subject="subject_music" @message="handleZYData"></SelectMusic>
+        <WorkSetting v-else subject="subject_music" @on-set-work="handleWorkInfo"></WorkSetting>
+      </div>
+    </CheckboxGroup>
+  </div>
 </template>
 
 <script>
+import SelectMusic from "./SelectMusic.vue"
 import WorkSetting from "./WorkSetting.vue"
 export default {
-	components:{
-		WorkSetting
-	},
-	props:{
-		subjects: {
-			type: Array,
-			default: () => {
-				return []
-			}
-		}
-	},
-	data(){
-		return{
-			baseWork:{
-				subjects:[],
-				settings:[]
-			}
-		}
-	},
-	watch:{
-		subjects:{
-			immediate:true,
-			deep:true,
-			handler(n,o){
-				if(n && n.length){
-					this.baseWork.subjects = this._.cloneDeep(n)
-				}
-			}
-		}
-	},
-	methods:{
-		handleSetWork(){
-			this.$emit('on-set-work',this.baseWork)
-		},
-		handleWorkInfo(data){
-			data = this._.cloneDeep(data)
-			let index = this.baseWork.settings.findIndex(item=>item.subject == data.subject)
-			if(index > -1){
-				this.baseWork.settings.splice(index,1,Object.assign({subject:data.subject},data.data))
-			}else{
-				this.baseWork.settings.push(Object.assign({subject:data.subject},data.data))
-			}
-			this.handleSetWork()
-		}
-	}
+  components: {
+    WorkSetting,SelectMusic
+  },
+  props: {
+    subjects: {
+      type: Array,
+      default: () => {
+        return []
+      }
+    },
+    quoid: {
+      type: String,
+      default: ""
+    }
+  },
+  data() {
+    return {
+      baseWork: {
+        subjects: [],
+        settings: []
+      }
+    }
+  },
+  watch: {
+    subjects: {
+      immediate: true,
+      deep: true,
+      handler(n, o) {
+        if (n && n.length) {
+          this.baseWork.subjects = this._.cloneDeep(n)
+        }
+      }
+    }
+  },
+  methods: {
+    handleZYData(data){
+      console.log(data)
+      this.handleWorkInfo({
+        subject:'subject_music',
+        data
+      })
+    },
+    handleSetWork() {
+      console.log(this.baseWork)
+      this.$emit('on-set-work', this.baseWork)
+    },
+    handleWorkInfo(data) {
+      data = this._.cloneDeep(data)
+      let index = this.baseWork.settings.findIndex(item => item.subject == data.subject)
+      if (index > -1) {
+        this.baseWork.settings.splice(index, 1, Object.assign({ subject: data.subject }, data.data))
+      } else {
+        this.baseWork.settings.push(Object.assign({ subject: data.subject }, data.data))
+      }
+      this.handleSetWork()
+    }
+  }
 }
 </script>
 
 <style lang="less" scoped>
-.subject-name{
-	font-weight: 600;
-	color: black;
-	margin-right: 10px;
+.subject-name {
+  font-weight: 600;
+  color: black;
+  margin-right: 10px;
 }
-.check-item{
-    margin-bottom: 10px;
+.check-item {
+  margin-bottom: 10px;
 }
-.content-block{
-	background: #f0f0f0;
-	padding: 8px 5px;
-	margin: 10px 0px;
+.content-block {
+  background: #f0f0f0;
+  padding: 8px 5px;
+  margin: 10px 0px;
 }
 </style>

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

@@ -245,7 +245,7 @@ export default {
     ]
     this.analysisText.light += addTextArr[lightMaxIndex]
 
-    // 计算学科统计
+    // 计算学科统计  
     let subArr = [...new Set(list.map(i => i.subjectName))]
     this.subjectCountArr = subArr.map(i => {
       return {

+ 24 - 0
TEAMModelOS/Controllers/Analysis/AnalysisController.cs

@@ -23,6 +23,7 @@ using System.Text;
 using Microsoft.AspNetCore.Authorization;
 using TEAMModelOS.Filter;
 using TEAMModelOS.SDK.Models.Service;
+using DocumentFormat.OpenXml.Office2010.Excel;
 
 namespace TEAMModelOS.Controllers.Analysis
 {
@@ -1820,6 +1821,29 @@ namespace TEAMModelOS.Controllers.Analysis
                 return BadRequest();
             }
         }
+        [ProducesDefaultResponseType]
+        [HttpPost("education-analysis")]
+        [Authorize(Roles = "IES")]
+        [AuthToken(Roles = "teacher,admin,student")]
+        public async Task<IActionResult> education(JsonElement request) {
+            if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
+            if (!request.TryGetProperty("period", out JsonElement period)) return BadRequest();
+            if (!request.TryGetProperty("gId", out JsonElement gId)) return BadRequest();
+
+            try {
+                var client = _azureCosmos.GetCosmosClient();
+                List<ExamInfo> infos = new List<ExamInfo>();
+                var query = $"select c.id,c.name,c.source from c where c.period.id = '{period}'";
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Common").GetItemQueryIterator<ExamInfo>(queryText: query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Exam-{code}") }))
+                {
+                    infos.Add(item);
+                }
+                return Ok();
+            } catch (Exception e) {
+                return Ok(new { code = 500});
+            }
+
+        }
 
         public async Task<string> getGId(int cyear, string periodId, string code)
         {

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

@@ -81,7 +81,7 @@ namespace TEAMModelOS.Controllers.Client
         /// </summary>
         /// <param name="request"></param>
         /// <returns></returns>
-        [Authorize(Roles = "HiTeach")]
+        //[Authorize(Roles = "HiTeach")]
         [ProducesDefaultResponseType]
         [HttpPost("update-lesson-record")]
         public async Task<IActionResult> UpdateLessonRecord(JsonElement request)

+ 22 - 12
TEAMModelOS/Controllers/Common/AreaController.cs

@@ -413,6 +413,7 @@ namespace TEAMModelOS.Controllers
                 if (!request.TryGetProperty("id", out JsonElement id)) return BadRequest();
                 if (!request.TryGetProperty("art", out JsonElement art)) return BadRequest();
                 if (!request.TryGetProperty("artExam", out JsonElement artExam)) return BadRequest();
+
                 var client = _azureCosmos.GetCosmosClient();
                 var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
                 List<string> baseIds = new();
@@ -442,6 +443,7 @@ namespace TEAMModelOS.Controllers
                 long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                 List<ArtEvaluation> arts = new();
                 ArtEvaluation areaArt = art.ToObject<ArtEvaluation>();
+                
                 areaArt.owner = "area";
                 areaArt.ttl = -1;
                 areaArt.scope = "school";
@@ -453,15 +455,22 @@ namespace TEAMModelOS.Controllers
                 {
                     areaArt.id = Guid.NewGuid().ToString();
                 }
-                ArtExam aExam = new();
-                if (string.IsNullOrWhiteSpace(aExam.id))
-                {
-                    aExam.id = Guid.NewGuid().ToString();
-                }
-                aExam.activityId = areaArt.id;
-                aExam.ttl = -1;
-                aExam.code = "ArtExam";
-                aExam.JsonElement = artExam;
+                //智音部分内容
+                if (request.TryGetProperty("ArtMusic", out JsonElement music)) {
+                    ArtMusic artMusic = music.ToObject<ArtMusic>();
+                    artMusic.code = "ArtMusic";
+                    artMusic.ttl = -1;
+                    artMusic.id = areaArt.id;
+                    await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(artMusic, new PartitionKey("ArtMusic"));
+                };             
+                //
+                ArtExam aExam = new()
+                {
+                    id = areaArt.id,
+                    ttl = -1,
+                    code = "ArtExam",
+                    JsonElement = artExam
+                };
                 await client.GetContainer("TEAMModelOS", "Common").UpsertItemAsync(aExam, new PartitionKey("ArtExam"));
 
                 foreach (string scId in baseIds)
@@ -1259,7 +1268,7 @@ namespace TEAMModelOS.Controllers
                 var client = _azureCosmos.GetCosmosClient();
                 List<string> ide = new();
                 var response = await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(id.ToString(), new PartitionKey($"Art-{code}"));
-                await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select c.id,c.code from c where c.activityId = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ArtExam") }))
+                /*await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: $"select c.id,c.code from c where c.activityId = '{id}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"ArtExam") }))
                 {
 
                     using var json = await JsonDocument.ParseAsync(item.ContentStream);
@@ -1273,8 +1282,9 @@ namespace TEAMModelOS.Controllers
                         }
                     }
 
-                }
-                await client.GetContainer("TEAMModelOS", "Common").DeleteItemsAsync<ArtExam>(ide, "ArtExam");
+                }*/
+                await client.GetContainer("TEAMModelOS", "Common").DeleteItemStreamAsync(id.ToString(), new PartitionKey("ArtExam"));
+               // await client.GetContainer("TEAMModelOS", "Common").DeleteItemsAsync<ArtExam>(ide, "ArtExam");
                 List<(string id, string name)> bascId = await getId(client, code.GetString());
                 List<(string id, string name)> ids = new();
                 foreach ((string sId, string name) in bascId)

+ 57 - 17
TEAMModelOS/Controllers/Common/ArtController.cs

@@ -6,6 +6,7 @@ using DocumentFormat.OpenXml.Office2013.Excel;
 using DocumentFormat.OpenXml.Office2016.Excel;
 using DocumentFormat.OpenXml.Spreadsheet;
 using DocumentFormat.OpenXml.Wordprocessing;
+using MathNet.Numerics.RootFinding;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
@@ -77,8 +78,18 @@ namespace TEAMModelOS.Controllers.Common
             try
             {
                 if (!request.TryGetProperty("art", out JsonElement art)) return BadRequest();
+               
                 var client = _azureCosmos.GetCosmosClient();
                 ArtEvaluation ae = art.ToObject<ArtEvaluation>();
+                bool flag = false;
+                ArtMusic music = new();
+                if (request.TryGetProperty("ArtMusic", out JsonElement am)) {
+                    music = am.ToObject<ArtMusic>();
+                    music.ttl = -1;
+                    music.code = "ArtMusic";
+                    flag = true;
+                };
+                
                 var (userid, _, _, school) = HttpContext.GetAuthTokenInfo();
                 string code = ae.school;
                 ae.ttl = -1;
@@ -95,12 +106,23 @@ namespace TEAMModelOS.Controllers.Common
                 }
                 if (string.IsNullOrEmpty(ae.id))
                 {
-                    ae.id = Guid.NewGuid().ToString();
+                   
+                    ae.id = Guid.NewGuid().ToString();                  
                     await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(ae, new PartitionKey($"{ae.code}"));
+                    if (flag)
+                    {
+                        music.id = ae.id;
+                        await client.GetContainer("TEAMModelOS", "Common").CreateItemAsync(music, new PartitionKey("ArtMusic"));
+                    }
+                    
                 }
                 else
                 {
+                    if (flag) {
+                        await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(music, music.id, new PartitionKey("ArtMusic"));
+                    }
                     await client.GetContainer("TEAMModelOS", "Common").ReplaceItemAsync(ae, ae.id, new PartitionKey($"{ae.code}"));
+
                 }
                 return Ok(new { ae });
             }
@@ -584,16 +606,41 @@ namespace TEAMModelOS.Controllers.Common
                 if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();
                 var client = _azureCosmos.GetCosmosClient();
                 ArtEvaluation art = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemAsync<ArtEvaluation>(id.GetString(), new PartitionKey($"Art-{code}"));
-
+                ArtMusic music = new();
+                ArtExam ae = new();
                 if (art != null)
                 {
                     string queryArtExam = $" select value(c) from c where c.activityId = '{art.pId}' ";
-                    List<ArtExam> aes = new List<ArtExam>();
-                    ArtExam ae = new();
-                    await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Common).GetItemQueryIterator<ArtExam>
-                         (queryText: queryArtExam, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"ArtExam") }))
+                    //List<ArtExam> aes = new List<ArtExam>();
+
+                    /* await foreach (var item in client.GetContainer(Constant.TEAMModelOS, Constant.Common).GetItemQueryIterator<ArtExam>
+                          (queryText: queryArtExam, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"ArtExam") }))
+                     {
+                         aes.Add(item);
+                     }*/
+                    if (!string.IsNullOrWhiteSpace(art.pId))
                     {
-                        aes.Add(item);
+                        var response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(art.pId, new PartitionKey("ArtMusic"));
+                        var sresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(art.pId, new PartitionKey("ArtExam"));
+                        if (sresponse.Status == 200)
+                        {
+                            using var json = await JsonDocument.ParseAsync(sresponse.ContentStream);
+                            ae = json.ToObject<ArtExam>();
+                        }
+                        if (response.Status == 200)
+                        {
+                            using var json = await JsonDocument.ParseAsync(response.ContentStream);
+                            music = json.ToObject<ArtMusic>();
+                        }
+                    }
+                    else
+                    {
+                        var response = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(art.id, new PartitionKey("ArtMusic"));
+                        if (response.Status == 200)
+                        {
+                            using var json = await JsonDocument.ParseAsync(response.ContentStream);
+                            music = json.ToObject<ArtMusic>();
+                        }
                     }
                     (List<RMember> rmembers, List<RGroupList> groups) = await GroupListService.GetMemberByListids(_coreAPIHttpService, client, _dingDing, art.classes, art.school);
                     var classes = art.classes.Select(c => new
@@ -663,18 +710,11 @@ namespace TEAMModelOS.Controllers.Common
                         {
                             responses.Add(client.GetContainer(Constant.TEAMModelOS, Constant.Student).CreateItemAsync(z, new PartitionKey(z.code)));
                         });
-                       
                         await responses.TaskPage(50);
                     }
-                    if (aes.Count > 0)
-                    {
-                        ae = aes[0];
-                        return Ok(new { art, classes, ae, code = 200 });
-                    }
-                    else
-                    {
-                        return Ok(new { art, classes, code = 200 });
-                    }
+
+                    return Ok(new { art, classes, ae, music, code = 200 });
+
 
                 }
                 else

+ 0 - 234
TEAMModelOS/Properties/Startup.cs

@@ -1,234 +0,0 @@
-using Lib.AspNetCore.ServerSentEvents;
-using Microsoft.AspNetCore.Authentication.JwtBearer;
-using Microsoft.AspNetCore.Builder;
-using Microsoft.AspNetCore.Hosting;
-using Microsoft.AspNetCore.Http;
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.SpaServices;
-using Microsoft.Azure.Cosmos.Table;
-using Microsoft.Extensions.Configuration;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Hosting;
-using Microsoft.IdentityModel.Tokens;
-using System;
-using System.Collections.Generic;
-using System.IdentityModel.Tokens.Jwt;
-using System.Linq;
-using System.Threading.Tasks;
-using TEAMModelOS.SDK.DI.Multiple;
-using TEAMModelBI.Models;
-using TEAMModelOS.Models;
-using TEAMModelOS.SDK;
-using TEAMModelOS.SDK.DI;
-using TEAMModelOS.SDK.Extension;
-using TEAMModelOS.SDK.Filter;
-using TEAMModelOS.SDK.Helper.Common.ReflectorExtensions;
-using TEAMModelOS.SDK.Models;
-using VueCliMiddleware;
-using System.Net.Http;
-
-namespace TEAMModelBI
-{
-    public class Startup
-    {
-        public IWebHostEnvironment environment { get; set; }
-        readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
-        public Startup(IConfiguration configuration,IWebHostEnvironment env)
-        {
-            Configuration = configuration;
-            environment = env;
-        }
-
-        public IConfiguration Configuration { get; }
-
-        // This method gets called by the runtime. Use this method to add services to the container.
-        public void ConfigureServices(IServiceCollection services)
-        {
-            // true,默認情況下,聲明映射將以舊格式映射聲明名稱,以適應較早的SAML應用程序,RoleClaimType = 'http://schemas.microsoft.com/ws/2008/06/identity/claims/role'
-            // false,RoleClaimType = 'roles'             
-            JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
-            services.AddAuthentication(options => options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme)
-                .AddJwtBearer(options => //AzureADJwtBearer
-                {
-                    //options.SaveToken = true; //驗證令牌由服務器生成才有效,不適用於服務重啟或分布式架構
-                    options.Authority = Configuration["Option:Authority"];
-                    options.Audience = Configuration["Option:Audience"];
-                    options.RequireHttpsMetadata = true;
-                    options.TokenValidationParameters = new TokenValidationParameters
-                    {
-                        RoleClaimType = "roles",
-                        ValidAudiences = new string[] { Configuration["Option:Audience"], $"api://{Configuration["Option:Audience"]}" }
-                    };
-                    options.Events = new JwtBearerEvents();
-                    //下列事件有需要紀錄則打開
-                    //options.Events.OnMessageReceived = async context => { await Task.FromResult(0); };
-                    //options.Events.OnForbidden = async context => { await Task.FromResult(0); };
-                    //options.Events.OnChallenge = async context => { await Task.FromResult(0); };
-                    //options.Events.OnAuthenticationFailed = async context => { await Task.FromResult(0); };
-                    options.Events.OnTokenValidated = async context =>
-                    {
-                        if (!context.Principal.Claims.Any(x => x.Type.Equals("http://schemas.microsoft.com/identity/claims/scope")) //ClaimConstants.Scope
-                        && !context.Principal.Claims.Any(y => y.Type.Equals("roles"))) //ClaimConstants.Roles //http://schemas.microsoft.com/ws/2008/06/identity/claims/role
-                        {
-                            //TODO 需處理額外授權非角色及範圍的訪問異常紀錄
-                            throw new UnauthorizedAccessException("Neither scope or roles claim was found in the bearer token.");
-                        }
-                        await Task.FromResult(0);
-                    };
-                });
-            //設定跨域請求
-            services.AddCors(options =>
-            {
-                options.AddPolicy(MyAllowSpecificOrigins,
-                builder =>
-                {
-                    builder.WithOrigins("http://teammodelos-test.chinacloudsites.cn",
-                                        "https://www.teammodel.cn", "https://localhost:5001",
-                                        "http://localhost:5000")
-                                       
-                    .AllowAnyHeader()
-                    .AllowAnyMethod();
-                });
-            });
-
-            //Table和blob注入
-            List<(string name, string connectionString)> storageConnects = new();
-            storageConnects.Add(("Default", Configuration.GetValue<string>("Azure:Storage:ConnectionString")));      //大路站ClientString
-            storageConnects.Add(("Global", Configuration.GetValue<string>("GlobalAzure:Storage:ConnectionString"))); //国际站ClientString
-
-            storageConnects.Add(("LogChina", Configuration.GetValue<string>("Azure:LogStorage:ConnectionString"))); //防火墙日志 大陆站ClientString
-            storageConnects.Add(("LogGlobal", Configuration.GetValue<string>("GlobalAzure:LogStorage:ConnectionString"))); //防火墙日志  国际站ClientString
-            services.AddMultipleAzureStorage(storageConnects);
-
-            //cosmosDB注入
-            List<(string name,string connectionString)> cosmosDBConnects = new();
-            cosmosDBConnects.Add(("Default", Configuration.GetValue<string>("Azure:Cosmos:ConnectionString")));      //大路站ClientString
-            cosmosDBConnects.Add(("Global", Configuration.GetValue<string>("GlobalAzure:Cosmos:ConnectionString"))); //国际站ClientString
-            services.AddMultipleAzureCosmos(cosmosDBConnects);
-
-            //redis注入
-            List<(string name, string connectionString)> redisConnects = new();
-            redisConnects.Add(("Default", Configuration.GetValue<string>("Azure:Redis:ConnectionString")));
-            redisConnects.Add(("Global", Configuration.GetValue<string>("GlobalAzure:Redis:ConnectionString")));
-            services.AddMultipleAzureRedis(redisConnects);
-
-            //serverBus 注入 
-            List<(string name, string connectionString)> funConnects = new();
-            funConnects.Add(("Default", Configuration.GetValue<string>("Azure:ServiceBus:ConnectionString")));
-            funConnects.Add(("Global", Configuration.GetValue<string>("GlobalAzure:ServiceBus:ConnectionString")));
-            services.AddMultipleAzureServiceBus(funConnects);
-            
-            //单一注入
-            //services.AddAzureStorage(Configuration.GetValue<string>("Azure:Storage:ConnectionString"));
-            //services.AddAzureCosmos(Configuration.GetValue<string>("Azure:Cosmos:ConnectionString"));
-            //services.AddAzureRedis(Configuration.GetValue<string>("Azure:Redis:ConnectionString"));
-            //services.AddAzureServiceBus(Configuration.GetValue<string>("Azure:ServiceBus:ConnectionString"));     
-
-            services.AddSnowflakeId(Convert.ToInt64(Configuration.GetValue<string>("Option:LocationNum")), 1);
-            services.AddHttpClient();
-            services.AddHttpClient<DingDing>();
-            //services.AddCoreAPIHttpService(Configuration);
-            services.AddHttpClient<CoreAPIHttpService>().ConfigureHttpMessageHandlerBuilder(builder =>
-            {
-                builder.PrimaryHandler = new HttpClientHandler
-                {
-                    ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
-                };
-            });
-            services.AddHttpClient<HttpTrigger>();
-            services.AddMemoryCache();
-            services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.IgnoreNullValues = false; });
-            services.Configure<SysConfig>(Configuration.GetSection("sysConfig"));  //注册连接
-            //HttpContextAccessor,并用来访问HttpContext。(提供組件或非控制器服務存取HttpContext)
-            services.AddHttpContextAccessor();
-            services.Configure<Option>(options => Configuration.GetSection("Option").Bind(options));
-            services.AddControllers();
-
-            string path = $"{ environment.ContentRootPath}/JsonFile/Core";
-            services.AddIPSearcher(path);
-            services.AddSpaStaticFiles(configuration =>
-            {
-                configuration.RootPath = "ClientApp";
-            });
-            services.AddServerSentEvents(o =>
-            {
-                o.KeepaliveMode = ServerSentEventsKeepaliveMode.Always;
-                o.OnClientConnected = async (service, client) =>
-                {
-                    //if (client.Request.Headers.TryGetValue("X-Auth-Name", out StringValues name))
-                    //{
-                    //    client.Client.SetProperty("NAME", name.ToString());
-                    //}
-                    //if (client.Request.Headers.TryGetValue("X-Auth-DID", out StringValues did))
-                    //{
-                    //    client.Client.SetProperty("DID", did.ToString());
-                    //}
-                    //if (client.Request.Headers.TryGetValue("X-Auth-CID", out StringValues cid))
-                    //{
-                    //    client.Client.SetProperty("CID", cid.ToString());
-                    //}
-                    //if (client.Request.Headers.TryGetValue("X-Auth-PIN", out StringValues pin))
-                    //{
-                    //    client.Client.SetProperty("PIN", pin.ToString());
-                    //}
-                    //if (client.Request.Headers.TryGetValue("X-Auth-APP", out StringValues app))
-                    //{
-                    //    client.Client.SetProperty("APP", app.ToString());
-                    //}
-
-                    await client.Client.SendEventAsync(new { sid = client.Client.Id.ToString() }.ToJsonString());
-                };
-            });
-            //等保安全性验证。
-            services.AddScoped<SecurityHeadersAttribute>();
-            services.AddAntiforgery(options => options.HeaderName = "X-CSRF-TOKEN");
-        }
-
-        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
-        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
-        {
-            if (env.IsDevelopment())
-            {
-                app.UseDeveloperExceptionPage();
-            }
-
-            app.UseRouting();
-            //以下需要按照順序載入中間件  如果应用调用 UseStaticFiles,请将 UseStaticFiles 置于 UseRouting之前。
-            app.UseStaticFiles();
-            app.UseSpaStaticFiles();
-            app.UseCors(MyAllowSpecificOrigins); //使用跨域設定
-            app.UseHttpsRedirection(); //開發中暫時關掉
-            //如果应用使用身份验证/授权功能(如 AuthorizePage 或 [Authorize]),请将对 UseAuthentication 和 UseAuthorization的
-            //调用放在之后、UseRouting 和 UseCors,但在 UseEndpoints之前
-            app.UseAuthentication();
-            app.UseAuthorization();
-            app.UseEndpoints(endpoints =>
-            {
-                endpoints.MapControllers();
-                endpoints.MapServerSentEvents("/service/sse", new ServerSentEventsOptions
-                {
-                    //Authorization = ServerSentEventsAuthorization.Default,
-                    OnPrepareAccept = response =>
-                    {
-                        response.Headers.Append("Cache-Control", "no-cache");
-                        response.Headers.Append("X-Accel-Buffering", "no");
-                    }
-                });
-#if DEBUG
-                endpoints.MapToVueCliProxy(
-                    "{*path}",
-                    new SpaOptions { SourcePath = "ClientApp" },
-                    npmScript: (System.Diagnostics.Debugger.IsAttached) ? "serve" : null,
-                    // regex: "Compiled successfully",
-                    forceKill: true
-                    );
-#else
-                endpoints.MapFallbackToFile("index.html");
-#endif
-
-            });
-
-
-        }
-    }
-}

+ 4 - 4
TEAMModelOS/TEAMModelOS.csproj

@@ -69,11 +69,11 @@
     <SpaRoot>ClientApp\</SpaRoot>
     <DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
     <UserSecretsId>078b5d89-7d90-4f6a-88fc-7d96025990a8</UserSecretsId>
-    <Version>5.2212.7</Version>
-    <AssemblyVersion>5.2212.14.1</AssemblyVersion>
-    <FileVersion>5.2212.14.1</FileVersion>
+    <Version>5.2212.21</Version>
+    <AssemblyVersion>5.2212.21.1</AssemblyVersion>
+    <FileVersion>5.2212.21.1</FileVersion>
     <Description>TEAMModelOS(IES5)</Description>
-    <PackageReleaseNotes>IES版本说明版本切换标记5.2212.14.1</PackageReleaseNotes>
+    <PackageReleaseNotes>IES版本说明版本切换标记5.2212.21.1</PackageReleaseNotes>
     <PackageId>TEAMModelOS</PackageId>
     <Authors>teammodel</Authors>
     <Company>醍摩豆(成都)信息技术有限公司</Company>