Browse Source

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

zhouj1203@hotmail.com 2 years ago
parent
commit
76a356c7a2
68 changed files with 3230 additions and 549 deletions
  1. 8 0
      TEAMModelBI/ClientApp/src/api/index.js
  2. 2 1
      TEAMModelBI/ClientApp/src/until/http.js
  3. 222 40
      TEAMModelBI/ClientApp/src/view/participation/copy.vue
  4. 16 9
      TEAMModelBI/ClientApp/src/view/participation/examination.vue
  5. 9 4
      TEAMModelBI/ClientApp/src/view/participation/paper.vue
  6. 1 0
      TEAMModelBI/Controllers/BIBlob/AnalyseFileController.cs
  7. 6 6
      TEAMModelBI/Controllers/BIHome/HomeStatisController.cs
  8. 1 0
      TEAMModelBI/Controllers/BIHome/OnLineController.cs
  9. 0 16
      TEAMModelBI/Controllers/BINormal/AreaRelevantController.cs
  10. 2 2
      TEAMModelBI/Controllers/BINormal/BatchAreaController.cs
  11. 28 4
      TEAMModelBI/Controllers/BISchool/SchoolController.cs
  12. 8 2
      TEAMModelBI/Controllers/BITable/TableDingDingInfoController.cs
  13. 5 2
      TEAMModelBI/Controllers/BITest/TestController.cs
  14. 4 2
      TEAMModelBI/Controllers/Census/ActivitySticsController.cs
  15. 1 1
      TEAMModelBI/Controllers/Census/BlobLogController.cs
  16. 1 0
      TEAMModelBI/Controllers/Census/ItemSticsController.cs
  17. 1 1
      TEAMModelBI/Controllers/Census/LessonSticsController.cs
  18. 110 72
      TEAMModelBI/Controllers/Census/PaperController.cs
  19. 1 0
      TEAMModelBI/Controllers/Census/ProductStatisController.cs
  20. 101 27
      TEAMModelBI/Controllers/Census/SchoolController.cs
  21. 1 7
      TEAMModelBI/Controllers/RepairApi/InitialAreaController.cs
  22. 97 0
      TEAMModelBI/Controllers/RepairApi/NormalController.cs
  23. 0 1
      TEAMModelBI/Models/AssistSchool.cs
  24. 42 0
      TEAMModelBI/Models/ForeEndModel.cs
  25. 1 0
      TEAMModelBI/Startup.cs
  26. 0 74
      TEAMModelBI/Tool/BIStatsWay/SchoolStatsWay.cs
  27. 0 77
      TEAMModelBI/Tool/BIStatsWay/StudyStatsWay.cs
  28. 11 7
      TEAMModelBI/Tool/CommonFind.cs
  29. 82 0
      TEAMModelBI/Tool/CosmosBank/JointlySingleQuery1.cs
  30. 1 0
      TEAMModelBI/Tool/CosmosBank/StatsWay.cs
  31. 456 0
      TEAMModelBI/Tool/TimeHelper1.cs
  32. 134 2
      TEAMModelOS.FunctionV4/HttpTrigger/BIHttpTrigger.cs
  33. 3 2
      TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs
  34. 1 1
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageBlobExtensions.cs
  35. 9 9
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactory.cs
  36. 0 2
      TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactoryOptions.cs
  37. 1028 0
      TEAMModelOS.SDK/DI/StudyAPI/ScsStudyApisService.cs
  38. 2 2
      TEAMModelOS.SDK/Models/Cosmos/BI/BICommon/MonthStartEnd.cs
  39. 19 17
      TEAMModelBI/Models/FrontModel.cs
  40. 12 12
      TEAMModelOS.SDK/Models/Cosmos/BI/StatsInfo.cs
  41. 9 6
      TEAMModelBI/Tool/CosmosBank/JointlySingleQuery.cs
  42. 95 47
      TEAMModelBI/Tool/TimeHelper.cs
  43. 8 5
      TEAMModelBI/Tool/BIStatsWay/ActivityStatsWay.cs
  44. 9 6
      TEAMModelBI/Tool/BIStatsWay/LessonRecordStatsWay.cs
  45. 199 0
      TEAMModelOS.SDK/Models/Service/BIStatsWay/SchoolStatsWay.cs
  46. 81 0
      TEAMModelOS.SDK/Models/Service/BIStatsWay/StudyStatsWay.cs
  47. 3 3
      TEAMModelOS.SDK/Models/Service/Third/ThirdService.cs
  48. 1 1
      TEAMModelOS/ClientApp/public/lang/en-US.js
  49. 1 1
      TEAMModelOS/ClientApp/src/common/BaseLayout.vue
  50. 9 3
      TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperViewBox/LessonTestReport.vue
  51. 13 14
      TEAMModelOS/ClientApp/src/view/dashboard/fiveEdu/FiveEdu.vue
  52. 8 8
      TEAMModelOS/ClientApp/src/view/dashboard/moral/MoralDash.vue
  53. 16 16
      TEAMModelOS/ClientApp/src/view/dashboard/study/StudyDash.vue
  54. 1 0
      TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.less
  55. 1 2
      TEAMModelOS/Controllers/Both/GroupListController.cs
  56. 3 0
      TEAMModelOS/Controllers/Common/CommonController.cs
  57. 7 3
      TEAMModelOS/Controllers/Normal/AbilityController.cs
  58. 4 2
      TEAMModelOS/Controllers/Normal/AbilitySubController.cs
  59. 26 6
      TEAMModelOS/Controllers/School/SchoolController.cs
  60. 49 0
      TEAMModelOS/Controllers/School/SchoolTeacherController.cs
  61. 5 1
      TEAMModelOS/Controllers/Third/Sc/ScDataInitController.cs
  62. 60 0
      TEAMModelOS/Controllers/XTest/FixDataController.cs
  63. 11 16
      TEAMModelOS/Controllers/XTest/TestController.cs
  64. 60 1
      TEAMModelOS/Lang/en-us.json
  65. 60 1
      TEAMModelOS/Lang/zh-cn.json
  66. 60 1
      TEAMModelOS/Lang/zh-tw.json
  67. 1 0
      TEAMModelOS/Startup.cs
  68. 4 4
      TEAMModelOS/TEAMModelOS.csproj

+ 8 - 0
TEAMModelBI/ClientApp/src/api/index.js

@@ -417,6 +417,14 @@ export default {
     getExamintionpaper(url) {
         return fetch(url, '')
     },
+    //获取所有学校进行筛选(试卷拷贝功能)
+    getschoolIntegration(data) {
+        return post('/schoolcheck/get-schools', data)
+    },
+    //拷贝试卷
+    copypaperTo(data) {
+        return post('/paper/copy-infos', data)
+    },
 
     //第三方相关API(BI)
     //创建or保存 第三方信息

+ 2 - 1
TEAMModelBI/ClientApp/src/until/http.js

@@ -17,7 +17,8 @@ axios.interceptors.request.use(
             config.url.indexOf('syscfg') != -1 ||
             config.url.indexOf('biservers') != -1 ||
             config.url.indexOf('business') != -1 ||
-            config.url.indexOf('bizconfig') != -1
+            config.url.indexOf('bizconfig') != -1 ||
+            config.url.indexOf('paper')
         ) {
             config.headers = {
                 'Content-Type': 'application/json',

+ 222 - 40
TEAMModelBI/ClientApp/src/view/participation/copy.vue

@@ -1,61 +1,176 @@
 <template>
   <div class="drawerbox">
-    <el-drawer v-model="drawer" title="拷贝试卷" :direction="direction" :before-close="handleClose">
+    <el-drawer v-model="drawer" title="拷贝试卷" :direction="direction" :before-close="eliminate" :close-on-click-modal="false">
       <div class="paperbox">
         <div class="paperbox-header">
           <p>当前试卷:</p>
           <div class="paperList">
-
+            <div class="paperitem">
+              <el-icon size="20">
+                <Document />
+              </el-icon>
+              <span>{{props.paperdata.title}}</span>
+            </div>
           </div>
         </div>
-        <div class="paperbox-target">
-          <p>分享到:</p>
-          <div>
-            <p>学校:</p>
-            <el-select v-model="target.schoolValue" multiple placeholder="Select" style="width: 240px">
-              <el-option v-for="item in optionsData.schools" :key="item.value" :label="item.label" :value="item.value" />
-            </el-select>
+        <div class="paperbox-target" v-loading="drawerloading" element-loading-text="相关数据加载中...">
+          <p class="target-title">分享到:</p>
+          <div class="target-school" v-for="item in targetData" :key="item.name">
+            <p>{{item.label}}:</p>
+            <div class="target-select">
+              <el-cascader v-model="item.modelValue" :options="item.listdata" :props="propsdata" clearable v-if="item.name ==='school'" @change="cascaderchange" :show-all-levels="true" :placeholder="item.msg" />
+              <el-select v-model="item.modelValue" :placeholder="item.msg" @change="clickschool(item,item.name)" v-else-if="item.name !=='grade'" no-data-text="无数据,请选择上一级内容">
+                <el-option v-for="items in item.listdata" :label="items.name" :value="items.id">
+                  <!-- <div class="sc-data">
+                    <div class="sc-name">{{items.name}}</div>
+                  </div> -->
+                </el-option>
+              </el-select>
+              <el-select v-model="item.modelValue" multiple :placeholder="item.msg" @change="clickschool(item,item.name)" v-else-if="item.name ==='grade'" no-data-text="无数据,请选择上一级内容">
+                <el-option v-for="(items,indexs) in item.listdata" :key="indexs" :label="items" :value="indexs" />
+                <!-- <div class="sc-data">
+                    <div class="sc-name">{{items.name}}</div>
+                  </div> -->
+              </el-select>
+            </div>
           </div>
+          <!-- <div class="target-school">
+            <p>学段:</p>
+            <div class="target-select">
+              <el-select v-model="target.phaseValue" multiple placeholder="Select">
+                <el-option v-for="item in optionsData.phases" :key="item.value" :label="item.label" :value="item.value" />
+              </el-select>
+            </div>
+          </div>
+          <div class="target-school">
+            <p>科目:</p>
+            <div class="target-select">
+              <el-select v-model="target.phaseValue" multiple placeholder="Select">
+                <el-option v-for="item in optionsData.phases" :key="item.value" :label="item.label" :value="item.value" />
+              </el-select>
+            </div>
+          </div> -->
+        </div>
+        <div class="footerbtn">
+          <el-button type="primary" @click="confirmClick">确认</el-button>
+          <el-button @click="eliminate">取消</el-button>
         </div>
       </div>
     </el-drawer>
   </div>
 </template>
 <script setup>
-import { ref } from 'vue'
-import { ElMessageBox } from 'element-plus'
+import { ref, getCurrentInstance, defineProps, watch, defineExpose, onMounted, } from 'vue'
+import { ElMessageBox, ElMessage } from 'element-plus'
+import { Document } from '@element-plus/icons-vue'
+const props = defineProps({
+  paperdata: String,
+})
+const { proxy } = getCurrentInstance()
 let drawer = ref(false)
+let drawerloading = ref(false)
 let drawer2 = ref(false)
+let papername = proxy.$parent.paperdata.title
 const direction = ref('rtl')
-let optionsData = ref({
-  schools: [
-    {
-      value: 'hbcn',
-      label: '醍摩豆学校',
-    },
-    {
-      value: 'cbcn',
-      label: 'BI测试学校',
-    },
-    {
-      value: 'cccc',
-      label: '测试学校',
-    },
-  ],
-  phases: [],
-  subjects: [],
-  grade: [],
-})
-let target = ref({
-  schoolValue: '',
-  school: [],
-  phaseValue: '',
-  phase: [],
-  subjectValue: '',
-  subject: '',
-  gradeValue: '',
-  grade: [],
-})
+let targetData = ref([
+  { label: '学校', name: 'school', modelValue: '', listdata: [], msg: '请选择分享目标学下' },
+  { label: '学段', name: 'phase', modelValue: '', listdata: [], msg: '请选择分享学段' },
+  { label: '科目', name: 'subject', modelValue: '', listdata: [], msg: '请选择分享科目' },
+  { label: '年级', name: 'grade', modelValue: '', listdata: [], msg: '请选择分享年级' },
+])
+let areaList = ref([])
+const propsdata = { value: 'id', label: 'name', children: 'child' }
+async function initdata () {
+  drawerloading.value = true
+  await getArealist()
+  proxy.$api.getschoolIntegration({}).then((res) => {
+    console.log(res, '所有学校列表')
+    if (res.state === 200) {
+      areaList.value.forEach((item) => {
+        let areaId = item.id
+        item.child = []
+        for (let i of res.scBriefs) {
+          i.areaId === areaId ? item.child.push(i) : ''
+        }
+      })
+      targetData.value[0].listdata = areaList.value
+    }
+  })
+  console.log(areaList, targetData.value[0].listdata, '处理后的数据111')
+  drawerloading.value = false
+}
+async function getArealist () {
+  await proxy.$api.getCapacity({}).then((res) => {
+    res.state === 200 ? (areaList.value = res.areas) : ''
+  }).catch((error) => {
+    ElMessage.error('获取学区学校数据失败,API异常')
+  })
+}
+//处理学校选择
+function cascaderchange (val) {
+  console.log(val, '123123')
+  if (!val) { return }
+  let nowSchooldata = val; let result = []
+  // for (let school of nowSchooldata) {
+  // console.log(school, '循环的内容')
+  let schoolId = nowSchooldata[1]
+  let areadata = areaList.value.find((item) => { return nowSchooldata[0] === item.id })
+  console.log(areadata, '获取到的学区')
+  for (let property of areadata.child) {
+    property.id === schoolId ? result.push(...property.period) : ''
+  }
+  // }
+  targetData.value[1].listdata = result
+  console.log(result, '处理的period')
+}
+//选择学段 科目 年级
+function clickschool (val, state) {
+  let data = val
+  if (state === 'phase') {
+    console.log(data, targetData.value[1].modelValue, '数据')
+    for (let item of data.listdata) {
+      item.id === targetData.value[1].modelValue ? (targetData.value[2].listdata = item.subjects, targetData.value[3].listdata = item.grades) : ''
+    }
+  }
+}
+//确认拷贝
+function confirmClick () {
+  console.log(targetData.value, props, '查看准备拷贝的目标')
+  for (let items of targetData.value) {
+    if (items.modelValue) { ElMessage.error('请选择试卷拷贝学校信息'); return }
+  }
+  let subjectText = ''
+  let result = targetData.value[2].listdata.find((item) => { return item.id === targetData.value[2].modelValue })
+  // targetData.value[3].modelValue.forEach((value) => { value = String(value) })
+  // for (let item of targetData.value[3].modelValue) {
+  //   item = item.toString()
+  // }
+  subjectText = result.name
+  let data = {
+    'papers':
+      [
+        { "oldId": props.paperdata.id, "oldSc": props.paperdata.schoolcode }
+      ],
+    newSc: [
+      { "newSc": targetData.value[0].modelValue[1], "newPrdId": targetData.value[1].modelValue, "newSubId": targetData.value[2].modelValue, "newSubName": subjectText, "newGrId": [targetData.value[3].modelValue.toString()] }
+    ]
+  }
+  console.log(data, '提交的数据')
+  proxy.$api.copypaperTo(data).then((res) => {
+    console.log(res, '拷贝后的结果')
+    res.state === 200 ? (ElMessage.success('试卷拷贝成功'), eliminate()) : ''
+  }).catch((error) => {
+    ElMessage.error('拷贝失败,API异常')
+  })
+}
+//取消或成功后 清除数据
+function eliminate () {
+  targetData.value.forEach((item, index) => {
+    index > 0 ? (item.modelValue = '', item.listdata = []) : index === 0 ? item.modelValue = '' : ''
+  })
+  drawer.value = false
+}
+initdata()
 defineExpose({ drawer });
 </script>
 <style scoped>
@@ -68,5 +183,72 @@ defineExpose({ drawer });
   font-weight: 700;
 }
 .paperList {
+  height: 35vh;
+  overflow: auto;
+}
+.target-title {
+  font-size: 16px;
+  font-weight: 700;
+  color: #3498db;
+}
+.target-school {
+  width: 100%;
+  margin-top: 2%;
+}
+.target-school p {
+  font-size: 14px;
+  color: #bdc3c7;
+}
+.target-select {
+  padding: 0% 8% 0% 2%;
+}
+.sc-data {
+  display: flex;
+  /* line-height: 40px; */
+  /* height: 50px !important; */
+  padding: 2px 0px 2px 0px !important;
+}
+.sc-img {
+  width: 25%;
+  text-align: center;
+}
+.sc-name {
+  font-size: 14px;
+  font-weight: 700;
+}
+.paperitem {
+  font-size: 16px;
+  line-height: 20px;
+  padding: 10px 5px;
+  border-radius: 4px;
+  background: #e6f7ff;
+  border-color: #91d5ff;
+  color: #579aff;
+}
+.paperitem span {
+  margin-left: 8px;
+}
+.footerbtn {
+  display: flex;
+  flex-direction: row-reverse;
+  padding: 0% 8% 0% 2%;
+  margin-top: 5%;
+}
+.footerbtn button:nth-child(2) {
+  margin-right: 2%;
+}
+</style>
+<style>
+.target-select .el-select {
+  width: 100% !important;
+}
+/* .el-select-dropdown__item {
+  height: 45px;
+} */
+.target-select .el-cascader {
+  width: 100%;
+}
+.el-checkbox__inner {
+  margin-top: 5px;
 }
 </style>

+ 16 - 9
TEAMModelBI/ClientApp/src/view/participation/examination.vue

@@ -190,8 +190,11 @@ export default {
         url: '',
         space: '',
         sas: '',
-      }
+      },
+      id: '',
+      schoolcode: ''
     })
+    let nowScode = ref('')
     //blob相关
     let blobData = ref({
       osblob_uri: '',
@@ -200,9 +203,10 @@ export default {
     let paperloding = ref(false)
     //处理筛选
     function filterInt (data) {
-      console.log(data, '试卷数据')
+      console.log(data, '开始进入方法')
       allperiod.value = data
       nowperiod.value = data.period
+      nowScode.value = data.id
       let schoolPeriod = data.period
       for (let i in schoolPeriod) {
         filters.value.pahse.option.push({ name: schoolPeriod[i].name, id: schoolPeriod[i].id })
@@ -214,7 +218,7 @@ export default {
       filters.value.grade.option = ([...allArr, ...schoolPeriod[0].grades])
       //filters.value.grade.option.unshift('全部')
       console.log(filters.value, '结果!')
-      getExamination(filters.value.pahse.option[0].id, filters.value.subject.option[0].id, true)
+      getExamination(filters.value.pahse.option[0].id, filters.value.subject.option[0].id)
     }
     //获取相应的试卷内容
     function getExamination (pahseId, subjectId, sort) {
@@ -313,6 +317,7 @@ export default {
     }
     //获取试卷blob资源
     async function getExamblob (value) {
+      console.log(value, '试卷内容')
       let loading = ElLoading.service({
         lock: false,
         text: '正在加载试卷信息,请稍等...',
@@ -334,7 +339,7 @@ export default {
       // console.log(Blobs, urls, 'blob初始化')
       proxy.$api.getExamintionpaper(blobData.value.osblob_uri + urls + '?' + blobData.value.osblob_sas).then(async (res) => {
         console.log(res, '完整的试卷信息')
-        res.hasOwnProperty('slides') ? (await questions(res.slides, value.blob, res.name, res.score), loading.close()) : ''
+        res.hasOwnProperty('slides') ? (await questions(res.slides, value.blob, res.name, res.score, value.id), loading.close()) : ''
       })
       uistate.value = 'details'
       // router.push('/home/paperDetails')
@@ -353,7 +358,7 @@ export default {
       })
     }
     //获取试题
-    async function questions (slider, blob, name, score) {
+    async function questions (slider, blob, name, score, paperId) {
       console.log(slider, blob, '调用到了')
       let difficultyNum = 0
       let listdata = []
@@ -374,6 +379,8 @@ export default {
       paperInfo.value.blob.url = blobData.value.osblob_uri
       paperInfo.value.blob.space = blob
       paperInfo.value.blob.sas = blobData.value.osblob_sas
+      paperInfo.value.schoolcode = nowScode.value
+      paperInfo.value.id = paperId
       console.log(paperInfo.value, '试卷完整信息')
     }
     function debounce (fn, wait) {
@@ -440,7 +447,8 @@ export default {
       paperInfo,
       findValue,
       timer,
-      paperloding
+      paperloding,
+      nowScode
     }
   },
 }
@@ -583,8 +591,7 @@ export default {
 }
 .filtratebox {
   width: 100%;
-  padding: 10px 20px;
-  padding-bottom: 20px;
+  padding: 10px 20px 0px 20px;
   background: #fff;
   border-top: 1px solid #ccc;
 }
@@ -701,7 +708,7 @@ export default {
     height: 75vh !important;
   }
   .opensidebar {
-    height: 57vh !important;
+    height: 60vh !important;
   }
 }
 @media screen and (max-width: 1400px) {

+ 9 - 4
TEAMModelBI/ClientApp/src/view/participation/paper.vue

@@ -297,7 +297,7 @@
     <div class="backtop" @click="backTops">
       <img :src="backImg" />
     </div>
-    <Copy ref="copypaper"></Copy>
+    <Copy ref="copypaper" :paperdata="paperdata"></Copy>
   </div>
 </template>
 <script>
@@ -323,7 +323,9 @@ export default ({
       totalnum: 0,
       difficulty: 0,
       title: '',
-      paperList: []
+      paperList: [],
+      id: '',
+      schoolcode: '',
     })
     let unfoldAll = ref({
       text: '全部展开',
@@ -336,7 +338,7 @@ export default ({
     let affiliateUnfold = ref(-1)
     let loading = ref(false)
     let copypaper = ref(null)
-    console.log(store.state.paperData, '试卷信息')
+    let copyiconLoding = ref(false)
     onMounted(() => {
       //监听表格滚动事件
       let rolllocation = document.getElementsByClassName('paperbox')
@@ -387,6 +389,8 @@ export default ({
       paperdata.value.totalnum = vals.total
       paperdata.value.title = vals.title
       paperdata.value.difficulty = Number(vals.difficulty)
+      paperdata.value.id = val.id
+      paperdata.value.schoolcode = val.schoolcode
       vals.list.forEach((item) => {
         console.log(item, '内容111')
         item.show = false
@@ -543,7 +547,8 @@ export default ({
       checkHtml,
       affiliateUnfold,
       copypaper,
-      copyPapers
+      copyPapers,
+      copyiconLoding
     }
   },
 })

+ 1 - 0
TEAMModelBI/Controllers/BIBlob/AnalyseFileController.cs

@@ -18,6 +18,7 @@ using TEAMModelOS.SDK.Context.Constant;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service.BI;
 
 namespace TEAMModelBI.Controllers.BIBlob
 {

+ 6 - 6
TEAMModelBI/Controllers/BIHome/HomeStatisController.cs

@@ -116,7 +116,7 @@ namespace TEAMModelBI.Controllers.BIHome
                     var tempCode = provinceStics.Find(x => x.provCode == itemStandard.provCode);
                     if (tempCode != null)
                     {
-                        string sqlSc = $"select c.id from c where c.standard='{itemStandard.standard}'";
+                        string sqlSc = $"select value(c.id) from c where c.standard='{itemStandard.standard}'";
                         List<string> schoolIds = await CommonFind.FindScIds(cosmosClient, sqlSc, "Base");
                         tempCode.schoolCount += schoolIds.Count;
 
@@ -149,7 +149,7 @@ namespace TEAMModelBI.Controllers.BIHome
                         tempProvinceStics.provName = itemStandard.provName;
                         tempProvinceStics.standardCount += 1;
 
-                        string sqlSc = $"select c.id from c where c.standard='{itemStandard.standard}'";
+                        string sqlSc = $"select value(c.id) from c where c.standard='{itemStandard.standard}'";
                         List<string> schoolIds = await CommonFind.FindScIds(cosmosClient, sqlSc, "Base");
                         tempProvinceStics.schoolCount += schoolIds.Count;
                         
@@ -292,7 +292,7 @@ namespace TEAMModelBI.Controllers.BIHome
                     };
 
                     //string sqlTxt = $"select c.id from c where c.standard='{itemStandrd.standard}'";
-                    string sqlTxt = $"select c.id from c where c.areaId='{itemStandrd.id}' and c.standard='{itemStandrd.standard}'";
+                    string sqlTxt = $"select value(c.id) from c where c.areaId='{itemStandrd.id}' and c.standard='{itemStandrd.standard}'";
                     List<string> schoolIds = await CommonFind.FindScIds(cosmosClient,sqlTxt, "Base");
                     districtStics.schoolCount += schoolIds.Count;
 
@@ -361,7 +361,7 @@ namespace TEAMModelBI.Controllers.BIHome
                     if (tempCode != null)
                     {
                         //List<string> schoolIds = await CommonFind.FindSchoolIds(cosmosClient, $"select c.id from c where c.standard='{itemStandrd.standard}'", "Base");
-                        List<string> schoolIds = await CommonFind.FindScIds(cosmosClient, $"select c.id from c where c.areaId='{itemStandrd.id}' and c.standard='{itemStandrd.standard}'", "Base");
+                        List<string> schoolIds = await CommonFind.FindScIds(cosmosClient, $"select value(c.id) from c where c.areaId='{itemStandrd.id}' and c.standard='{itemStandrd.standard}'", "Base");
                         tempCode.schoolCount += schoolIds.Count;
 
                         var tempModel = sticsCitys.Where(x => x.cityCode == tempCode.cityCode).FirstOrDefault();
@@ -400,7 +400,7 @@ namespace TEAMModelBI.Controllers.BIHome
                         citySchool.cityCode = itemStandrd.cityCode;
                         citySchool.cityName = itemStandrd.cityName;
 
-                        List<string> schoolIds = await CommonFind.FindScIds(cosmosClient, $"select c.id from c where c.standard='{itemStandrd.standard}'","Base");
+                        List<string> schoolIds = await CommonFind.FindScIds(cosmosClient, $"select value(c.id) from c where c.standard='{itemStandrd.standard}'","Base");
                         citySchool.schoolCount += schoolIds.Count;
 
                         List<DistrictStics> tempDistrictStics = new();
@@ -468,7 +468,7 @@ namespace TEAMModelBI.Controllers.BIHome
 
                 //查询学校空间和学校Id
                 totalSize = await CommonFind.GetSqlValueCount(cosmosClient, "School", "select value(sum(c.size)) from c", "Base");
-                schoolId = await CommonFind.FindScIds(cosmosClient, "select c.id,c.size from c", "Base");
+                schoolId = await CommonFind.FindScIds(cosmosClient, "select value(c.id) from c", "Base");
 
                 //查询学校已使用空间大小
                 foreach (var itemId in schoolId)

+ 1 - 0
TEAMModelBI/Controllers/BIHome/OnLineController.cs

@@ -19,6 +19,7 @@ using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service.BI;
 using TEAMModelOS.SDK.Models.Table;
 
 namespace TEAMModelBI.Controllers.BIHome

+ 0 - 16
TEAMModelBI/Controllers/BINormal/AreaRelevantController.cs

@@ -21,8 +21,6 @@ using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
-using Top.Api;
-using static TEAMModelBI.Controllers.BITest.TestController;
 
 namespace TEAMModelBI.Controllers.BINormal
 {
@@ -561,20 +559,6 @@ namespace TEAMModelBI.Controllers.BINormal
 
         }
 
-        public record AreaAssist
-        {
-            public string userId { get; set; }
-            public string unionId { get; set; }
-            public string name { get; set; }
-            public string mobile { get; set; }
-            public string avatar { get; set; }
-            public string tmdId { get; set; }
-            public string tmdName { get; set; }
-            public string tmdMobile { get; set; }
-            public string picture { get; set; }
-            public string roles { get; set; }
-            public string schoolIds { get; set; }
-        }
 
         /// <summary>
         /// 通过区域ID查询学校前端暂时

+ 2 - 2
TEAMModelBI/Controllers/BINormal/BatchAreaController.cs

@@ -32,9 +32,9 @@ using System.Text;
 using DocumentFormat.OpenXml.Bibliography;
 using Microsoft.Extensions.Hosting;
 using Microsoft.AspNetCore.Hosting;
-using static TEAMModelBI.Controllers.RepairApi.InitialAreaController;
 using TEAMModelOS.SDK.Context.Constant;
 using TEAMModelOS.SDK.Models.Service.BI;
+using TEAMModelBI.Models;
 
 namespace TEAMModelBI.Controllers.BINormal
 {
@@ -956,7 +956,7 @@ namespace TEAMModelBI.Controllers.BINormal
                         await cosmosClient.GetContainer("TEAMModelOS", "Teacher").ReplaceItemAsync<Teacher>(item, item.id, new PartitionKey("Base"));
                     }
 
-                    List<string> scIds = await CommonFind.FindScIds(cosmosClient, $"select c.id from c where c.areaId='{area.id}' and c.standard ='{area.standard}'", "Base");
+                    List<string> scIds = await CommonFind.FindScIds(cosmosClient, $"select value(c.id) from c where c.areaId='{area.id}' and c.standard ='{area.standard}'", "Base");
 
                     foreach (var item in scIds)
                     {

+ 28 - 4
TEAMModelBI/Controllers/BISchool/SchoolController.cs

@@ -35,7 +35,6 @@ using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
 using TEAMModelOS.SDK.Models.Cosmos.Common;
 using TEAMModelOS.SDK.Models.Service.BI;
-using static TEAMModelBI.Controllers.BISchool.SchoolController;
 
 namespace TEAMModelBI.Controllers.BISchool
 {
@@ -1622,12 +1621,12 @@ namespace TEAMModelBI.Controllers.BISchool
 
             //if ((string.IsNullOrEmpty($"{tmdId}") && string.IsNullOrEmpty($"{schooId}")) || (!string.IsNullOrEmpty($"{tmdId}") && !string.IsNullOrEmpty($"{schooId}")))
                 
-            List<MonthStartEnd> mthStartEnds = await TimeHelper.GetYearSataMthCtMth(DateTimeOffset.UtcNow);
+            List<StartEndTime> mthStartEnds = await TimeHelper.GetYearSataMthCtMth(DateTimeOffset.UtcNow);
             if (mthStartEnds.Count > 0)
             {
                 foreach (var item in mthStartEnds)
                 {
-                    YearCnt yearCnt = new() { name = item.yearMonth };
+                    YearCnt yearCnt = new() { name = item.date };
                     string selessSql = $"{strSql} and {scSql.ToString()} and c.startTime >= {item.start} and c.startTime <= {item.end}";
                     yearCnt.lessCnt = await CommonFind.GetSqlValueCount(cosmosClient, "School", selessSql);
 
@@ -1818,6 +1817,31 @@ namespace TEAMModelBI.Controllers.BISchool
             return Ok(new { state = RespondCode.Ok, school, gradeCnt, subCnt });
         }
 
+        /// <summary>
+        /// 学校简要信息
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-schools")]
+        public async Task<IActionResult> GetSchools (JsonElement jsonElement)
+        {
+            jsonElement.TryGetProperty("areaId", out JsonElement areaId);
+            List<ScBriefInfo> scBriefs = new();
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+
+            StringBuilder sql = new("select c.id,c.name,c.picture,c.areaId,c.size,c.period from c ");
+            if (!string.IsNullOrEmpty($"{areaId}"))
+                sql.Append($" where c.areaId = '{areaId}'");
+
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS,"School").GetItemQueryIterator<ScBriefInfo>(queryText: sql.ToString(), requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")}))
+            {
+                scBriefs.Add(item);
+            }
+
+            return Ok(new { state = RespondCode.Ok, scBriefs });
+        }
+
         /// <summary>
         /// 通过tmdID 账户查询学校专业和模组   //已对接
         /// </summary>
@@ -1991,7 +2015,7 @@ namespace TEAMModelBI.Controllers.BISchool
             if (!string.IsNullOrEmpty($"{areaId}"))
             {
                 List<string> schools = new();
-                schools = await CommonFind.FindScIds(cosmosClient, $"select c.id from c where c.areaId='{areaId}'", "Base");
+                schools = await CommonFind.FindScIds(cosmosClient, $"select value(c.id) from c where c.areaId='{areaId}'", "Base");
 
                 allSize = await CommonFind.GetSqlValueCount(cosmosClient, "School", $"select value(sum(c.size)) from c where c.areaId='{areaId}'", "Base"); //区域所有学校空间
 

+ 8 - 2
TEAMModelBI/Controllers/BITable/TableDingDingInfoController.cs

@@ -418,7 +418,13 @@ namespace TEAMModelBI.Controllers.BITable
                             {
                                 if (scTch.roles.Contains("sales"))
                                 {
-                                    int index = scTch.roles.FindIndex(fi => fi.Contains("sales"));
+
+                                    //int index = scTch.roles.FindIndex(fi => fi.Equals("sales"));
+                                    //scTch.roles[index]= "assist";
+                                    //scTch.job = "顾问";
+                                    //upScTch.Add(cosmosCliet.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(scTch, scTch.id, new PartitionKey($"{scTch.code}")));
+
+                                    int index = scTch.roles.FindIndex(fi => fi.Equals("sales"));
                                     if (index >= 0)
                                     {
                                         scTch.roles[index] = "assist";
@@ -436,7 +442,7 @@ namespace TEAMModelBI.Controllers.BITable
                             {
                                 if (scTch.roles.Contains("assist"))
                                 {
-                                    int index = scTch.roles.FindIndex(fi => fi.Contains("assist"));
+                                    int index = scTch.roles.FindIndex(fi => fi.Equals("assist"));
                                     if (index >= 0) 
                                     {
                                         scTch.roles[index] = "sales";

+ 5 - 2
TEAMModelBI/Controllers/BITest/TestController.cs

@@ -680,6 +680,10 @@ namespace TEAMModelBI.Controllers.BITest
         [HttpPost("get-date")]
         public async Task<IActionResult> GetDate()
         {
+            ////计算一年每天的开始/结束时间
+            //List<StartEndTime> everyDay = TimeHelper.GetYearEveryDay(DateTimeOffset.UtcNow, isCurrDay: true);
+            //return Ok(new { state = RespondCode.Ok, dayCnt = everyDay.Count, everyDay });
+
             List<string> day7 = TimeHelper.GetNearDay(DateTimeOffset.UtcNow, 7);
             List<string> day30 = TimeHelper.GetNearDay(DateTimeOffset.UtcNow, 30);
 
@@ -714,7 +718,7 @@ namespace TEAMModelBI.Controllers.BITest
             var start = GetMonthStart(ere);
             var end = GetMonthEnd(ere);
 
-            List<MonthStartEnd> endList1 = TimeHelper.GetYearMonthlyStartEnd(DateTimeOffset.UtcNow.Year);
+            List<StartEndTime> endList1 = TimeHelper.GetYearMonthlyStartEnd(DateTimeOffset.UtcNow.Year);
             //return Ok(new { strList, dateTime, year, start, end, endList, endList1, endList2 });
 
 
@@ -1346,7 +1350,6 @@ namespace TEAMModelBI.Controllers.BITest
             //        }
             //    }
             //}
-
             var (an, saveUrl) = await BILogAnalyseService.GetPathAnalyse(_azureStorage, _ipSearcher, _dingDing, $"{path}", BIConst.LogChina, timeType: $"{jTimeType}");
 
             return Ok(new { state = RespondCode.Ok, cnt = filename.Count, filename, an, saveUrl });

+ 4 - 2
TEAMModelBI/Controllers/Census/ActivitySticsController.cs

@@ -239,7 +239,7 @@ namespace TEAMModelBI.Controllers.Census
                 monthLess = await CommonFind.GetSqlValueCount(cosmosClient, "School", $"{oftenSql} where c.pk='LessonRecord' and {comSql} and c.startTime >= {monthS} and c.startTime <= {monthE}");
 
                 //学时
-                totalTime = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", $"select value(sum(c.totalTime)) from c where c.pk='TeacherTrain' and {comSql}");
+                //totalTime = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", $"select value(sum(c.totalTime)) from c where c.pk='TeacherTrain' and {comSql}");
 
                 //活动
                 string actSpl = BICommonWay.ManyScSql(" and c.school", scIds);
@@ -260,7 +260,7 @@ namespace TEAMModelBI.Controllers.Census
                 //string stSql = $"{oftenSql} join s in c.currency where c.TeacherTrain and {comSql} and s.submitTime = 0 or s.submitTime >= {setting.submitTime}";
                 //submitCount = await CommonFind.GetSqlValueCount(cosmosClient, "Teacher", ctSql);
 
-                await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryText: $"select c.id,c.code,c.onlineTime,c.offlineTime,c.classTime,c.currency from c where c.pk='TeacherTrain' and {comSql}", requestOptions: new QueryRequestOptions() { })) 
+                await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryStreamIterator(queryText: $"select c.id,c.code,c.totalTime,c.onlineTime,c.offlineTime,c.classTime,c.currency from c where c.pk='TeacherTrain' and {comSql}", requestOptions: new QueryRequestOptions() { })) 
                 {
                     using var json = await JsonDocument.ParseAsync(item.ContentStream);
                     if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
@@ -272,6 +272,8 @@ namespace TEAMModelBI.Controllers.Census
                     }
                 }
 
+                //学时
+                totalTime = trains.Select(s => s.totalTime).Sum();
                 trains.ForEach(x =>
                 {
                     //线上研修

+ 1 - 1
TEAMModelBI/Controllers/Census/BlobLogController.cs

@@ -62,7 +62,7 @@ namespace TEAMModelBI.Controllers.Census
             List<string> schoolIds = new();
             if (!string.IsNullOrEmpty($"{areaId}"))
             {
-                string sqlTxt = $"select c.id from c where c.areaId='{areaId}'";
+                string sqlTxt = $"select value(c.id) from c where c.areaId='{areaId}'";
                 sqlSize.Append($" where c.areaId = '{areaId}'");
                 schoolIds = await CommonFind.FindScIds(cosmosClient, sqlTxt.ToString(), "Base");
                 foreach (var item in StaticValue.fileType)

+ 1 - 0
TEAMModelBI/Controllers/Census/ItemSticsController.cs

@@ -17,6 +17,7 @@ using Azure.Core;
 using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
 using TEAMModelOS.SDK.Context.Constant;
 using DocumentFormat.OpenXml.Wordprocessing;
+using TEAMModelOS.SDK.Models.Service.BI;
 
 namespace TEAMModelBI.Controllers.Census
 {

+ 1 - 1
TEAMModelBI/Controllers/Census/LessonSticsController.cs

@@ -558,7 +558,7 @@ namespace TEAMModelBI.Controllers.Census
             //if ($"{site}".Equals(BIConst.Global))
             //    cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
 
-            StringBuilder scSqlTxt = new("select c.id from c");
+            StringBuilder scSqlTxt = new("select value(c.id) from c");
             if (!string.IsNullOrEmpty($"{areaId}"))
             {
                 scSqlTxt.Append($" where c.areaId='{areaId}'");

+ 110 - 72
TEAMModelBI/Controllers/Census/PaperController.cs

@@ -15,8 +15,10 @@ using System.Linq;
 using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
+using TEAMModelBI.Filter;
 using TEAMModelBI.Models;
 using TEAMModelBI.Tool;
+using TEAMModelBI.Tool.Extension;
 using TEAMModelOS.Models;
 using TEAMModelOS.SDK.Context.BI;
 using TEAMModelOS.SDK.Context.Constant;
@@ -25,6 +27,7 @@ using TEAMModelOS.SDK.DI.AzureCosmos.Inner;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service.BI;
 
 namespace TEAMModelBI.Controllers.Census
 {
@@ -117,86 +120,111 @@ namespace TEAMModelBI.Controllers.Census
         /// <param name="jsonElement"></param>
         /// <returns></returns>
         [ProducesDefaultResponseType]
+        [AuthToken(Roles = "admin")]
         [HttpPost("copy-infos")]
         public async Task<IActionResult> CopyInfos(JsonElement jsonElement) 
         {
-            if (!jsonElement.TryGetProperty("papers", out JsonElement jsPapers)) return BadRequest();
-
-            List<CopyPaper> papers = jsPapers.ToObject<List<CopyPaper>>();
-
-            var cosmosClinet = _azureCosmos.GetCosmosClient();
-            foreach (var cItem in papers)
+            try
             {
-                Paper paper = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Paper>(cItem.oldId, new PartitionKey($"Paper-{cItem.oldSc}"));
-                paper.periodId = cItem.newPrdId;
-                paper.subjectId = cItem.newSubId;
-                paper.subjectName = cItem.newSubName;
-                paper.gradeIds = cItem.newGrId;
-                paper.code = $"Paper-{cItem.newSc}";
-
-                var resState = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(paper.id, new PartitionKey(paper.code));
-                if (resState.Status == 200)
-                    paper.id = Guid.NewGuid().ToString();
+                if (!jsonElement.TryGetProperty("papers", out JsonElement jsPapers)) return BadRequest();
+                if (!jsonElement.TryGetProperty("newSc", out JsonElement _newSchool)) return BadRequest();
 
-                paper = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<Paper>(paper, new PartitionKey(paper.code));
-
-
-                var oldBobCilent = _azureStorage.GetBlobContainerClient(containerName: $"{cItem.oldSc}");
-                var newBobCilent = _azureStorage.GetBlobContainerClient(containerName: $"{cItem.newSc}");
-
-                string blobUrl = "";
-                if (paper.blob.IndexOf('/') == 0)
-                    blobUrl = $"{paper.blob}".Substring(1, paper.blob.Length - 1);
-                else
-                    blobUrl = $"{paper.blob}";
+                var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
+                List<CopyPaper> papers = jsPapers.ToObject<List<CopyPaper>>();
+                List<newSchool> newSchools = _newSchool.ToObject<List<newSchool>>();
+                StringBuilder msg = new($"{_tmdName}[{_tmdId}]操作复制试卷:");
 
                 List<Task<CopyFromUriOperation>> filelist = new();   //可复制256M以上文件
-                await foreach (BlobItem blobItem in oldBobCilent.GetBlobsAsync(BlobTraits.None, BlobStates.None, blobUrl))
+                List<dynamic> existScPaper = new();
+                var cosmosClinet = _azureCosmos.GetCosmosClient();
+                var tableClient = _azureStorage.GetCloudTableClient();
+                var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
+                foreach (var itemSc in newSchools)
                 {
-                    var urlSas = _azureStorage.GetBlobSAS($"{cItem.oldSc}", blobItem.Name, BlobSasPermissions.Read | BlobSasPermissions.List);   //获取容器sas和有效期
-                    filelist.Add(newBobCilent.GetBlobClient(blobItem.Name).StartCopyFromUriAsync(new Uri(urlSas)));
-                    ////序列化数据修改数据
-                    //if (blobItem.Name.EndsWith(".json"))
-                    //{
-                    //    BlobClient tempClient = oldBobCilent.GetBlobClient(blobItem.Name);
-                    //    using (var meomoryStream = new MemoryStream())
-                    //    {
-                    //        StringBuilder itemStr = new();
-                    //        BlobClient tempBlobClient = oldBobCilent.GetBlobClient(blobItem.Name);
-                    //        BlobDownloadInfo download = tempBlobClient.Download();
-                    //        var content = download.Content;
-                    //        string text;
-                    //        using (var streamReader = new StreamReader(content))
-                    //        {
-                    //            while ((text = streamReader.ReadLine()) != null)
-                    //            {
-                    //                if (streamReader.EndOfStream)
-                    //                    itemStr.Append($"{text.ToString()}");
-                    //                else
-                    //                    itemStr.Append($"{text.ToString()},");
-                    //            }
-                    //            streamReader.Close();
-                    //        }
-                    //        string input = itemStr.ToString();
-                    //        BlobItemInfo blobbItemInfo = input.ToObject<BlobItemInfo>();
-
-                    //        //var response = oldBobCilent.GetBlobClient($"{blobItem.Name}").DownloadTo(meomoryStream);
-                    //        //BlobItemInfo blobbItemInfo = Encoding.UTF8.GetString(meomoryStream.ToArray()).ToString().ToObject<BlobItemInfo>();
-                    //        blobbItemInfo.exercise.periodId = cItem.newPrdId;
-                    //        blobbItemInfo.exercise.gradeIds = cItem.newGrId;
-
-                    //        blobbItemInfo.exercise.subjectId = cItem.newSubId;
+                    List<string> existPaper = new();
+                    foreach (var cItem in papers)
+                    {
+                        Paper paper = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<Paper>(cItem.oldId, new PartitionKey($"Paper-{cItem.oldSc}"));
+                        paper.periodId = itemSc.newPrdId;
+                        paper.subjectId = itemSc.newSubId;
+                        paper.subjectName = itemSc.newSubName;
+                        paper.gradeIds = itemSc.newGrId;
+                        paper.code = $"Paper-{itemSc.newSc}";
+
+                        var resState = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(paper.id, new PartitionKey(paper.code));
+                        if (resState.Status == 200)
+                            paper.id = Guid.NewGuid().ToString();
+
+                        msg.Append($"将学校[{cItem.oldSc}]中的[{cItem.oldId}]试卷复制到新学校试卷新id:{paper.id}");
+                        await foreach (var item in cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<string>(queryText: $"select value(c.name) from c where c.name='{paper.name}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Paper-{itemSc.newSc}") }))
+                        {
+                            existPaper.Add(item);
+                        }
 
-                    //        var urlSas = _azureStorage.GetBlobSAS($"{cItem.newSc}", blobItem.Name, BlobSasPermissions.Read | BlobSasPermissions.List);   //获取容器sas和有效期
+                        if (existPaper.Count == 0)
+                        {
+                            paper = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<Paper>(paper, new PartitionKey(paper.code));
+
+                            var oldBobCilent = _azureStorage.GetBlobContainerClient(containerName: $"{cItem.oldSc}");
+                            var newBobCilent = _azureStorage.GetBlobContainerClient(containerName: $"{itemSc.newSc}");
+
+                            string blobUrl = "";
+                            if (paper.blob.IndexOf('/') == 0)
+                                blobUrl = $"{paper.blob}".Substring(1, paper.blob.Length - 1);
+                            else
+                                blobUrl = $"{paper.blob}";
+
+                            await foreach (BlobItem blobItem in oldBobCilent.GetBlobsAsync(BlobTraits.None, BlobStates.None, blobUrl))
+                            {
+                                var urlSas = _azureStorage.GetBlobSAS($"{cItem.oldSc}", blobItem.Name, BlobSasPermissions.Read | BlobSasPermissions.List);   //获取容器sas和有效期
+                                filelist.Add(newBobCilent.GetBlobClient(blobItem.Name).StartCopyFromUriAsync(new Uri(urlSas)));
+                                ////序列化数据修改数据
+                                //if (blobItem.Name.EndsWith(".json"))
+                                //{
+                                //    BlobClient tempClient = oldBobCilent.GetBlobClient(blobItem.Name);
+                                //    using (var meomoryStream = new MemoryStream())
+                                //    {
+                                //        StringBuilder itemStr = new();
+                                //        BlobClient tempBlobClient = oldBobCilent.GetBlobClient(blobItem.Name);
+                                //        BlobDownloadInfo download = tempBlobClient.Download();
+                                //        var content = download.Content;
+                                //        string text;
+                                //        using (var streamReader = new StreamReader(content))
+                                //        {
+                                //            while ((text = streamReader.ReadLine()) != null)
+                                //            {
+                                //                if (streamReader.EndOfStream)
+                                //                    itemStr.Append($"{text.ToString()}");
+                                //                else
+                                //                    itemStr.Append($"{text.ToString()},");
+                                //            }
+                                //            streamReader.Close();
+                                //        }
+                                //        string input = itemStr.ToString();
+                                //        BlobItemInfo blobbItemInfo = input.ToObject<BlobItemInfo>();
+
+                                //        //var response = oldBobCilent.GetBlobClient($"{blobItem.Name}").DownloadTo(meomoryStream);
+                                //        //BlobItemInfo blobbItemInfo = Encoding.UTF8.GetString(meomoryStream.ToArray()).ToString().ToObject<BlobItemInfo>();
+                                //        blobbItemInfo.exercise.periodId = cItem.newPrdId;
+                                //        blobbItemInfo.exercise.gradeIds = cItem.newGrId;
+
+                                //        blobbItemInfo.exercise.subjectId = cItem.newSubId;
+
+                                //        var urlSas = _azureStorage.GetBlobSAS($"{cItem.newSc}", blobItem.Name, BlobSasPermissions.Read | BlobSasPermissions.List);   //获取容器sas和有效期
+
+                                //        var ster = newBobCilent.UploadFileByContainer(blobbItemInfo.ToJsonString(), blobItem.Name, blobbItemInfo.id);
+                                //    }
+                                //}
+                            }
+                        }
+                    }
+                    if (existPaper.Count > 0)
+                        existScPaper.Add(new { schoolId = itemSc.newSc, papers = existPaper });
 
-                    //        var ster = newBobCilent.UploadFileByContainer(blobbItemInfo.ToJsonString(), blobItem.Name, blobbItemInfo.id);
-                    //    }
-                    //}
+                    msg.Append($"新学校Id[{itemSc.newSc}];");
                 }
                 if (filelist.Count <= 256)
-                {
                     await Task.WhenAll(filelist);
-                }
                 else
                 {
                     int pages = (filelist.Count + 255) / 256;
@@ -208,8 +236,15 @@ namespace TEAMModelBI.Controllers.Census
                     }
                 }
 
+                //保存操作记录
+                await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "paper-copy-infos", msg.ToString(), _dingDing, httpContext: HttpContext);
+                return Ok(new { state = RespondCode.Ok , existScPaper });
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"BI,{_option.Location} /paper/copy-infos \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                return BadRequest();
             }
-            return Ok(new { state = RespondCode.Ok});
         }
 
  
@@ -361,7 +396,7 @@ namespace TEAMModelBI.Controllers.Census
             ////分开部署,就不需要,一站多用时,取消注释
             //if ($"{site}".Equals(BIConst.Global))
             //    cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
-            List<MonthStartEnd> endList1 = TimeHelper.GetYearMonthlyStartEnd(DateTimeOffset.UtcNow.Year);
+            List<StartEndTime> endList1 = TimeHelper.GetYearMonthlyStartEnd(DateTimeOffset.UtcNow.Year);
             if (string.IsNullOrEmpty($"{tmdId}"))
             {
                 Dictionary<string, long> schoolYears = new Dictionary<string, long>();
@@ -370,7 +405,7 @@ namespace TEAMModelBI.Controllers.Census
                     string sqlText = $"SELECT value(COUNT(c.id)) FROM c WHERE c.createTime >= {temp.start} and c.createTime <= {temp.end} and c.pk='Paper'";
 
                     long total = await CommonFind.GetSqlValueCount(cosmosClient, new List<string>() { "School", "Teacher" }, sqlText);
-                    schoolYears.Add(temp.yearMonth, total);
+                    schoolYears.Add(temp.date, total);
                 }
 
                 return Ok(new { state = 200, schoolYears });
@@ -398,7 +433,7 @@ namespace TEAMModelBI.Controllers.Census
                     {                        
                         string sqlTxt = $"SELECT value(COUNT(c.id)) FROM c WHERE c.code='Paper-{schoolId}' and c.createTime >= {temp.start} and c.createTime <= {temp.end} and c.pk='Paper'";
                         long totals = await CommonFind.GetSqlValueCount(cosmosClient, new List<string>() { "School", "Teacher" }, sqlTxt);
-                        yearCount.Add(temp.yearMonth, totals);
+                        yearCount.Add(temp.date, totals);
                     }
                     schoolYear.yearPaper = yearCount;
                     schoolYears.Add(schoolYear);
@@ -553,12 +588,15 @@ namespace TEAMModelBI.Controllers.Census
         {
             public string oldId { get; set; }
             public string oldSc { get; set; }
+        }
+
+        public record newSchool
+        {
             public string newSc { get; set; }
             public string newPrdId { get; set; }
             public string newSubId { get; set; }
             public string newSubName { get; set; }
             public List<string> newGrId { get; set; }
-
         }
 
     }

+ 1 - 0
TEAMModelBI/Controllers/Census/ProductStatisController.cs

@@ -13,6 +13,7 @@ using TEAMModelOS.SDK.Context.BI;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Service.BI;
 
 namespace TEAMModelBI.Controllers.Census
 {

+ 101 - 27
TEAMModelBI/Controllers/Census/SchoolController.cs

@@ -1,4 +1,5 @@
 using Azure.Cosmos;
+using DocumentFormat.OpenXml.Bibliography;
 using Microsoft.AspNetCore.Http;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.Extensions.Options;
@@ -13,7 +14,6 @@ using System.Text.Json;
 using System.Threading.Tasks;
 using TEAMModelBI.Models;
 using TEAMModelBI.Tool;
-using TEAMModelBI.Tool.BIStatsWay;
 using TEAMModelBI.Tool.CosmosBank;
 using TEAMModelOS.Models;
 using TEAMModelOS.SDK.Context.BI;
@@ -23,8 +23,7 @@ using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
 using TEAMModelOS.SDK.Models.Service.BI;
-using static TEAMModelBI.Controllers.BINormal.AreaRelevantController;
-using static TEAMModelBI.Controllers.Census.LessonSticsController;
+using TEAMModelOS.SDK.Models.Service.BIStatsWay;
 
 namespace TEAMModelBI.Controllers.Census
 {
@@ -36,13 +35,15 @@ namespace TEAMModelBI.Controllers.Census
         private readonly AzureStorageFactory _azureStorage;
         private readonly DingDing _dingDing;
         private readonly Option _option;
+        private readonly HttpTrigger _httpTrigger;
 
-        public SchoolController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option)
+        public SchoolController(AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, DingDing dingDing, IOptionsSnapshot<Option> option, HttpTrigger httpTrigger)
         {
             _azureCosmos = azureCosmos;
             _azureStorage = azureStorage;
             _dingDing = dingDing;
             _option = option?.Value;
+            _httpTrigger = httpTrigger;
         }
 
         /// <summary>
@@ -489,7 +490,8 @@ namespace TEAMModelBI.Controllers.Census
         }
 
         /// <summary>
-        /// 学校统计
+        /// 学校统计     
+        /// 新的数据结构
         /// </summary>
         /// <param name="jsonElement"></param>
         /// <returns></returns>
@@ -498,12 +500,12 @@ namespace TEAMModelBI.Controllers.Census
         public async Task<IActionResult> GetSchoolStats(JsonElement jsonElement) 
         {
             if (!jsonElement.TryGetProperty("scId", out JsonElement scId)) return BadRequest();
-            var cosmosClinet = _azureCosmos.GetCosmosClient();
+            var cosmosClient = _azureCosmos.GetCosmosClient();
 
             School school = new();
             ScStats scStats = new();
 
-            var respSc = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{scId}", new PartitionKey($"Base"));
+            var respSc = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{scId}", new PartitionKey($"Base"));
             if (respSc.Status == 200)
             {
                 using var fileJson = await JsonDocument.ParseAsync(respSc.ContentStream);
@@ -514,15 +516,19 @@ namespace TEAMModelBI.Controllers.Census
 
             try
             {
+                bool isExist = true;
                 StatsInfo statsInfo = new();
-                var scDataStats = await cosmosClinet.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{scId}", new PartitionKey("Stats"));
+                var scDataStats = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{scId}", new PartitionKey("Stats"));
                 if (scDataStats.Status == 200)
                 {
                     using var fileJson = await JsonDocument.ParseAsync(scDataStats.ContentStream);
                     statsInfo = fileJson.ToObject<StatsInfo>();
                 }
                 else
+                {
                     scStats.id = school.id;
+                    isExist = false;
+                }
 
                 bool isnew = false;
                 DateTimeOffset dateTime = DateTimeOffset.UtcNow;
@@ -574,18 +580,21 @@ namespace TEAMModelBI.Controllers.Census
                     scStats.actStats.term = statsInfo.activity.term;
                     scStats.actStats.LastYear = TimeHelper.GetYearMonth(statsInfo.activity.LastYear ,dateTime.Year,dateTime.Month);
                     scStats.actStats.year = TimeHelper.GetYearMonth(statsInfo.activity.year, dateTime.Year, dateTime.Month);
-                    scStats.srStats.learnTime = statsInfo.study.learnTime;
-                    scStats.srStats.onlineTime = statsInfo.study.onlineTime;
-                    scStats.srStats.offlineTime = statsInfo.study.offlineTime;
-                    scStats.srStats.classTime = statsInfo.study.classTime;
-                    scStats.srStats.currency = statsInfo.study.currency;
-                    scStats.srStats.notStarted = statsInfo.study.notStarted;
-                    scStats.srStats.ongoing = statsInfo.study.ongoing;
-                    scStats.srStats.finish = statsInfo.study.finish;
+                    if (statsInfo.study != null)
+                    {
+                        scStats.srStats.learnTime = statsInfo.study.learnTime;
+                        scStats.srStats.online = statsInfo.study.online;
+                        scStats.srStats.offline = statsInfo.study.offline;
+                        scStats.srStats.classRoom = statsInfo.study.classRoom;
+                        scStats.srStats.submit = statsInfo.study.submit;
+                        scStats.srStats.notStarted = statsInfo.study.notStarted;
+                        scStats.srStats.ongoing = statsInfo.study.ongoing;
+                        scStats.srStats.finish = statsInfo.study.finish;
+                    }
                 }
 
                 if(statsInfo.upTime > 0 && !isnew) {
-                    long timedis = 15 * 60 * 1000;//15分钟
+                    long timedis = 20 * 60 * 1000;//20分钟
                     if (now - statsInfo.upTime < timedis)
                         isnew = true;
                 }
@@ -593,11 +602,20 @@ namespace TEAMModelBI.Controllers.Census
                     statsInfo.upTime = now;
                 if (statsInfo.upTime == 0 && isnew)
                     statsInfo.upTime = DateTimeOffset.UtcNow.Add(new TimeSpan(-1, 0, 0, 0)).ToUnixTimeMilliseconds();
+                if (!isnew)
+                {
+                    //Function 处理Function 更新或者新增
+                    //_ = _httpTrigger.RequestHttpTrigger(new { schoolId = $"{school.id}"}, _option.Location, "stats-sc-info");
 
-                statsInfo = await SchoolStatsWay.upSingleSc(cosmosClinet, school.id);
-
-
+                    //异步方法处理 同步更新
+                    statsInfo = await SchoolStatsWay.GetSingleSc(cosmosClient, school.id);
 
+                    statsInfo.upTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                    if (isExist)
+                        statsInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<StatsInfo>(statsInfo, statsInfo.id, new PartitionKey("Stats"));
+                    else
+                        statsInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<StatsInfo>(statsInfo, new PartitionKey("Stats"));
+                }
 
                 return Ok(new { state = RespondCode.Ok, statsInfo });
             }
@@ -608,6 +626,62 @@ namespace TEAMModelBI.Controllers.Census
             }
         }
 
+        /// <summary>
+        /// 区域统计
+        /// 新的数据结构
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-areastats")]
+        public async Task<IActionResult> GetAreaStats(JsonElement jsonElement) 
+        {
+            if (!jsonElement.TryGetProperty("areaId", out JsonElement areaId)) return BadRequest();
+
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+
+            Area area = new();
+            ScStats areaScStats = new();
+
+            var respSc = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemStreamAsync($"{areaId}", new PartitionKey($"Base-Area"));
+            if (respSc.Status == 200)
+            {
+                using var fileJson = await JsonDocument.ParseAsync(respSc.ContentStream);
+                area = fileJson.ToObject<Area>();
+            }
+            else
+                return Ok(new { state = RespondCode.NotFound, msg = $"未找到id:{areaId};相关的学区,请检查!" });
+
+            List<string> scIds = new();
+            //scIds.Contains
+            string scSql = $"select value(c.id) from c where c.areaId='{areaId}'";
+
+            scIds = await CommonFind.FindScIds(cosmosClient, scSql, "Base");
+
+            //await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "School").GetItemQueryIterator<string>(queryText: scSql,requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")} ))
+            //{
+            //    scIds.Add(item);
+            //}
+
+            StringBuilder statsSql = new("select value(c) from c");
+            if (scIds.Count > 0) 
+            {
+                statsSql.Append($" where {BICommonWay.ManyScSql("c.id", scIds)}");
+            }
+
+            List<ScStats> scStats = new();
+            List<StatsInfo> statsInfos = new();
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS,"School").GetItemQueryIterator<StatsInfo>(queryText:statsSql.ToString(),requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Stats") }))
+            {
+                statsInfos.Add(item);
+            }
+
+            StatsInfo statsInfo = new();
+            statsInfo = await SchoolStatsWay.GetAreaStats(cosmosClient, _httpTrigger, _option, statsInfos, scIds);
+
+            return Ok(new { state = RespondCode.Ok ,area, statsInfo, scIds });
+        }
+
 
         /// <summary>
         /// 依据Id查询School容器  数据管理工具——查询工具
@@ -666,10 +740,10 @@ namespace TEAMModelBI.Controllers.Census
             public int size { get; set; }
             public long scCreateTime { get; set; }
             public long upTime { get; set; }
-            public ScLessStats lessStats { get; set; }
-            public ScActStats actStats { get; set; }
+            public ScLessStats lessStats { get; set; } = new ScLessStats();
+            public ScActStats actStats { get; set; } = new ScActStats();
 
-            public ScSRStats srStats { get; set; }
+            public ScSRStats srStats { get; set; } = new ScSRStats();
         }
 
         /// <summary>
@@ -722,10 +796,10 @@ namespace TEAMModelBI.Controllers.Census
         public record ScSRStats 
         { 
             public int learnTime { get; set; }
-            public int onlineTime { get; set; }
-            public int offlineTime { get; set; }
-            public int classTime { get; set; }
-            public int currency { get; set; }
+            public int online { get; set; }
+            public int offline { get; set; }
+            public int classRoom { get; set; }
+            public int submit { get; set; }
             public int notStarted { get; set; }
             public int ongoing { get; set; }
             public int finish { get; set; }

+ 1 - 7
TEAMModelBI/Controllers/RepairApi/InitialAreaController.cs

@@ -24,6 +24,7 @@ using Pipelines.Sockets.Unofficial.Arenas;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
 using TEAMModelBI.Filter;
 using HTEXLib.COMM.Helpers;
+using TEAMModelBI.Models;
 
 namespace TEAMModelBI.Controllers.RepairApi
 {
@@ -337,13 +338,6 @@ namespace TEAMModelBI.Controllers.RepairApi
         }
 
 
-        public record CopyStandard
-        {
-            public string id { get; set; }
-            public string standard { get; set; }
-            public string name { get; set; }
-        }
-
 
     }
 }

+ 97 - 0
TEAMModelBI/Controllers/RepairApi/NormalController.cs

@@ -0,0 +1,97 @@
+using Azure.Cosmos;
+using DinkToPdf;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.Options;
+using System.Net.Http;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK;
+using TEAMModelOS.SDK.Context.Constant;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.DI.CoreAPI;
+using TEAMModelOS.SDK.Models;
+
+namespace TEAMModelBI.Controllers.RepairApi
+{
+    [Route("normal")]
+    [ApiController]
+    public class NormalController : ControllerBase
+    {
+
+        private readonly AzureCosmosFactory _azureCosmos;
+        private readonly DingDing _dingDing;
+        private readonly Option _option;
+        private readonly AzureStorageFactory _azureStorage;
+        private readonly IConfiguration _configuration;
+        private readonly NotificationService _notificationService;
+        private readonly AzureServiceBusFactory _serviceBus;
+        private readonly IHttpClientFactory _http;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly IWebHostEnvironment _environment; //读取文件
+
+        public NormalController(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService, AzureServiceBusFactory serviceBus, IHttpClientFactory http, CoreAPIHttpService coreAPIHttpService, IWebHostEnvironment hostingEnvironment)
+        {
+            _azureCosmos = azureCosmos;
+            _dingDing = dingDing;
+            _azureStorage = azureStorage;
+            _option = option?.Value;
+            _configuration = configuration;
+            _notificationService = notificationService;
+            _serviceBus = serviceBus;
+            _http = http;
+            _coreAPIHttpService = coreAPIHttpService;
+            _environment = hostingEnvironment;
+        }
+
+        /// <summary>
+        /// 修改学区名称、标准名称、单位
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("set-areabase")]
+        public async Task<IActionResult> SetAreaBase(JsonElement jsonElement) 
+        {
+            if (!jsonElement.TryGetProperty("oldName", out JsonElement oldName)) return BadRequest();
+            if (!jsonElement.TryGetProperty("name", out JsonElement name)) return BadRequest();
+            if(!jsonElement.TryGetProperty("type", out JsonElement type)) return BadRequest();
+
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+            string sql = $"select value(c) from c where c.name = '{oldName}'";
+
+            Area area = new();
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: sql, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base-Area") }))
+            {
+                area = item;
+            };
+
+            if (!string.IsNullOrEmpty(area.id)) 
+            {
+                area.name = $"{name}";
+                switch ($"{type}")
+                {
+                    case "all":
+                        area.institution = $"{name}";
+                        area.standardName = $"{name}";
+                        break;
+                    case "unit":
+                        area.institution = $"{name}";
+                        break;
+                    case "standard":
+                        area.standardName = $"{name}";
+                        break;
+                }
+
+                area = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReplaceItemAsync<Area>(area, area.id, new PartitionKey("Base-Area"));
+            }
+            return Ok(new { state = RespondCode.Ok, area });
+        }
+
+
+
+    }
+}

+ 0 - 1
TEAMModelBI/Models/AssistSchool.cs

@@ -1,7 +1,6 @@
 using System;
 using System.Collections.Generic;
 using TEAMModelOS.SDK.Models;
-using static TEAMModelBI.Controllers.BISchool.BatchSchoolController;
 
 namespace TEAMModelBI.Models
 {

+ 42 - 0
TEAMModelBI/Models/ForeEndModel.cs

@@ -0,0 +1,42 @@
+using System.Collections.Generic;
+using TEAMModelOS.SDK.Models;
+
+namespace TEAMModelBI.Models
+{
+    public class ForeEndModel
+    {
+    }
+
+    public record AreaAssist
+    {
+        public string userId { get; set; }
+        public string unionId { get; set; }
+        public string name { get; set; }
+        public string mobile { get; set; }
+        public string avatar { get; set; }
+        public string tmdId { get; set; }
+        public string tmdName { get; set; }
+        public string tmdMobile { get; set; }
+        public string picture { get; set; }
+        public string roles { get; set; }
+        public string schoolIds { get; set; }
+    }
+
+    public record ScBriefInfo
+    {
+        public string id { get; set; }
+        public string name { get; set; }
+        public string picture { get; set; }
+        public string areaId { get; set; }
+        public int size { get; set; }
+        public List<Period> period { get; set; }
+    }
+
+    public record CopyStandard
+    {
+        public string id { get; set; }
+        public string standard { get; set; }
+        public string name { get; set; }
+    }
+
+}

+ 1 - 0
TEAMModelBI/Startup.cs

@@ -130,6 +130,7 @@ namespace TEAMModelBI
             services.AddHttpClient<NotificationService>();
             services.AddCoreAPIHttpService(Configuration);
             services.AddHttpClient<CoreAPIHttpService>();
+            services.AddHttpClient<HttpTrigger>();
             services.AddMemoryCache();
             services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.IgnoreNullValues = false; });
             services.Configure<SysConfig>(Configuration.GetSection("sysConfig"));  //注册连接

+ 0 - 74
TEAMModelBI/Tool/BIStatsWay/SchoolStatsWay.cs

@@ -1,74 +0,0 @@
-using System.Threading.Tasks;
-using System;
-using TEAMModelBI.Models;
-using TEAMModelBI.Tool.CosmosBank;
-using TEAMModelOS.SDK.Models.Cosmos.BI;
-using Azure.Cosmos;
-
-namespace TEAMModelBI.Tool.BIStatsWay
-{
-    public static class SchoolStatsWay
-    {
-
-        /// <summary>
-        /// 
-        /// </summary>
-        /// <param name="cosmosClient"></param>
-        /// <param name="scId"></param>
-        /// <returns></returns>
-        public static async Task<StatsInfo> upSingleSc(CosmosClient cosmosClient, string scId)
-        {
-
-            StatsInfo statsInfo = new() { id = $"{scId}" };
-
-            DateTimeOffset dateTime = DateTimeOffset.UtcNow;
-            var (dayS, dayE) = TimeHelper.GetStartOrEnd(dateTime);  //今天开始时间    13位
-            var (lastWeekS, lastWeekE) = TimeHelper.GetStartOrEnd(dateTime, "lastweek");   //计算上周开始/结束时间
-            var (weekS, weekE) = TimeHelper.GetStartOrEnd(dateTime, "week");             //计算本周开始/结束时间
-
-            var (lastTermS, lastTermE) = TimeHelper.GetStartOrEnd(dateTime, "lastterm");   //计算上学期开始/结束时间
-            var (termS, termE) = TimeHelper.GetStartOrEnd(dateTime, "term");   //计算本学期开始/结束时间
-
-            var (lastMthS, LastmthE) = TimeHelper.GetStartOrEnd(dateTime, "lastMonth");  //上月开始/结束时间
-            var (mthS, mthE) = TimeHelper.GetStartOrEnd(dateTime, "month");  //本月开始/结束时间
-
-            var (lastYearS, lastYearE) = TimeHelper.GetStartOrEnd(DateTimeOffset.Parse($"{dateTime.Year - 1}-1-1"), "year"); //计算去年开始/结束时间
-            var (yearS, yearE) = TimeHelper.GetStartOrEnd(dateTime, "year");         //计算今年开始/结束时间
-
-            string currSql = "select value(count(c.id)) from c";
-            string dayWhereSql = $"c.createTime >= {dayS} and c.createTime <= {dayE}";
-            string weekWhereSql = $"c.createTime >= {weekS} and c.createTime <= {weekE}";
-            string monthWhereSql = $"c.createTime >= {mthS} and c.createTime <= {mthE}";
-
-            ScBase scBase = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<ScBase>(statsInfo.id, new PartitionKey("Base"));
-            statsInfo.name = scBase.name;
-            statsInfo.picture = scBase.picture;
-            statsInfo.size = scBase.size;
-            statsInfo.scCreateTime = scBase.createTime;
-
-            string tchSql = $"{currSql} where ARRAY_CONTAINS(c.roles, 'teacher', true) AND c.status = 'join'";
-            statsInfo.tch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", tchSql, code: $"Teacher-{scBase.id}");
-            statsInfo.dayTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and {dayWhereSql} ", code: $"Teacher-{scBase.id}");
-            statsInfo.weekTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and  {weekWhereSql}", code: $"Teacher-{scBase.id}");
-            statsInfo.monthTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and  {monthWhereSql}", code: $"Teacher-{scBase.id}");
-
-            statsInfo.stu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", currSql, code: $"Base-{scBase.id}");
-            statsInfo.dayStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {dayWhereSql}", code: $"Base-{scBase.id}");
-            statsInfo.weekStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {weekWhereSql}", code: $"Base-{scBase.id}");
-            statsInfo.monthStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {monthWhereSql}", code: $"Base-{scBase.id}");
-
-            statsInfo.room = await JointlySingleQuery.GetValueInt(cosmosClient, "School", currSql, code: $"Room-{scBase.id}");
-            statsInfo.witRoom = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{currSql} where (c.serial != null or c.serial != '' or IS_DEFINED(c.serial) = true)", code: $"Room-{scBase.id}");
-
-
-            statsInfo.lesson = await LessonRecordStatsWay.GetLessStats(cosmosClient, statsInfo.id);
-            statsInfo.activity = await ActivityStatsWay.GetActStats(cosmosClient, statsInfo.id);
-
-
-
-
-            return statsInfo;
-        }
-
-    }
-}

+ 0 - 77
TEAMModelBI/Tool/BIStatsWay/StudyStatsWay.cs

@@ -1,77 +0,0 @@
-using Azure.Cosmos;
-using System.Collections.Generic;
-using System.Text.Json;
-using System.Threading.Tasks;
-using TEAMModelBI.Models;
-using TEAMModelOS.SDK.Models;
-using TEAMModelOS.SDK.Models.Cosmos.BI;
-
-namespace TEAMModelBI.Tool.BIStatsWay
-{
-    public static class StudyStatsWay
-    {
-        /// <summary>
-        /// 学校研修统计
-        /// </summary>
-        /// <param name="cosmosClient"></param>
-        /// <param name="scId"></param>
-        /// <returns></returns>
-        public static async Task<StudyStats> GetStudyStats(CosmosClient cosmosClient, string scId)
-        {
-            StudyStats studyStats = new();
-            List<AreaStudy> trains = new();
-
-            School rschool = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemAsync<School>($"{scId}", new PartitionKey("AreaSetting"));
-
-            AreaSetting setting = null;
-
-            var responSett = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync($"123", new PartitionKey("AreaSetting"));
-            if (responSett.Status == 200) 
-            {
-                
-            }
-            if (setting == null)
-            {
-                setting = new AreaSetting
-                {
-                    allTime = 50,
-                    classTime = 5,
-                    submitTime = 15,
-                    onlineTime = 20,
-                    offlineTime = 10,
-                    lessonMinutes = 45,
-                };
-            }
-
-            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<AreaStudy>(queryText: $"select c.id,c.code,c.onlineTime,c.offlineTime,c.classTime,c.currency from c where c.pk='TeacherTrain' and c.school='{scId}'", requestOptions: new QueryRequestOptions() { }))
-            {
-                trains.Add(item);
-            }
-
-
-
-            //trains.ForEach(x =>
-            //{
-            //    //线上研修
-            //    if (x.onlineTime == 0) studyStats++; else if (x.onlineTime >= setting.onlineTime) onLineCount++; else onLineCount++;
-
-            //    //线下研修
-            //    if (x.offlineTime == 0) offlineCount++; else if (x.onlineTime >= setting.offlineTime) offlineCount++; else offlineCount++;
-
-            //    //课堂实录
-            //    if (x.classTime == 0) classRoomCount++; else if (x.classTime >= setting.classTime) classRoomCount++; else classRoomCount++;
-
-            //    //认证材料
-            //    if (x.currency.submitTime == 0) submitCount++; else if (x.currency.submitTime >= setting.submitTime) submitCount++; else submitCount++;
-
-            //    if (x.currency.submitTime == 0 && x.classTime == 0 && x.offlineTime == 0 && x.onlineTime == 0) noCount++;
-            //    else if (x.currency.submitTime >= setting.submitTime && x.classTime >= setting.classTime && x.onlineTime >= setting.offlineTime && x.onlineTime >= setting.onlineTime) fulfilCount++;
-            //    else carryOnCount++;
-            //});
-
-
-
-            return studyStats;
-        }
-    }
-}

+ 11 - 7
TEAMModelBI/Tool/CommonFind.cs

@@ -134,16 +134,20 @@ namespace TEAMModelBI.Tool
         public static async Task<List<string>> FindScIds(CosmosClient cosmosClient, string sqlTxt, string code)
         {
             List<string> schoolIds = new();
-
-            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey(code) }))
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<string>(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey(code) }))
             {
-                using var json = await JsonDocument.ParseAsync(item.ContentStream);
-                foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
-                {
-                    schoolIds.Add(obj.GetProperty("id").GetString());
-                }
+                schoolIds.Add(item);
             }
 
+            //await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryStreamIterator(queryText: sqlTxt, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey(code) }))
+            //{
+            //    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+            //    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+            //    {
+            //        schoolIds.Add(obj.GetProperty("id").GetString());
+            //    }
+            //}
+
             return schoolIds;
         }
 

+ 82 - 0
TEAMModelBI/Tool/CosmosBank/JointlySingleQuery1.cs

@@ -0,0 +1,82 @@
+using Azure.Cosmos;
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace TEAMModelBI.Tool.CosmosBank
+{
+    public class JointlySingleQuery1
+    {
+        /// <summary>
+        /// 多个容器返回整数 使用
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="containerId"></param>
+        /// <param name="sqlTxt"></param>
+        /// <param name="code"></param>
+        /// <returns></returns>
+        public static async Task<int> GetValueInt(CosmosClient cosmosClient, List<string> containerId, string sqlTxt = null, string code = null) 
+        {
+            int totals = 0;
+            string sql = $"select value(count(c.id)) from c";
+            if (!string.IsNullOrEmpty(sqlTxt)) 
+            {
+                sql = sqlTxt;
+            }
+
+            foreach (string conId in containerId) 
+            {
+                await foreach (var itemInt in cosmosClient.GetContainer("TEAMModelOS", conId).GetItemQueryIterator<int>(queryText: sql, requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+                {
+                    totals += itemInt;
+                }
+            }
+
+            return totals;            
+        }
+
+        /// <summary>
+        /// 单个容器返回整数 统计使用
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="container"></param>
+        /// <param name="sqlTxt"></param>
+        /// <param name="code"></param>
+        /// <returns></returns>
+        public static async Task<int> GetValueInt(CosmosClient cosmosClient, string container, string sqlTxt = null, string code = null)
+        {
+            int totals = 0;
+            string sql = $"select value(count(c.id)) from c";
+            if (!string.IsNullOrEmpty(sqlTxt))
+            {
+                sql = sqlTxt;
+            }
+
+            await foreach (var itemInt in cosmosClient.GetContainer("TEAMModelOS", container).GetItemQueryIterator<int>(queryText: sql, requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+            {
+                totals += itemInt;
+            }
+
+            return totals;
+        }
+
+        /// <summary>   
+        /// 返回字符集合
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="containerId"></param>
+        /// <param name="sqlTxt"></param>
+        /// <param name="code"></param>
+        /// <returns></returns>
+        public static async Task<List<string>> GetListString(CosmosClient cosmosClient, string containerId, string sqlTxt, string code = null) 
+        {
+            List<string> strList = new();
+
+            await foreach (var itemInt in cosmosClient.GetContainer("TEAMModelOS", containerId).GetItemQueryIterator<string>(queryText: sqlTxt, requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
+            {
+                strList.Add(itemInt);
+            }
+
+            return strList;
+        }
+    }
+}

+ 1 - 0
TEAMModelBI/Tool/CosmosBank/StatsWay.cs

@@ -8,6 +8,7 @@ using System.Threading.Tasks;
 using TEAMModelBI.Models;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
 using TEAMModelOS.SDK.Models.Cosmos.BI.BITable;
+using TEAMModelOS.SDK.Models.Service.BI;
 
 namespace TEAMModelBI.Tool.CosmosBank
 {

+ 456 - 0
TEAMModelBI/Tool/TimeHelper1.cs

@@ -0,0 +1,456 @@
+using DocumentFormat.OpenXml.Bibliography;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using TEAMModelBI.Models;
+using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+
+namespace TEAMModelBI.Tool
+{
+    public static class TimeHelper1
+    {
+        /// <summary>
+        /// 平年
+        /// </summary>
+        public static List<int> flatY = new() { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+        /// <summary>
+        /// 闰年
+        /// </summary>
+        public static List<int> leapY = new() { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+
+        /// <summary>
+        /// 通过时间戳转换为时间
+        /// </summary>
+        /// <param name="timeStamp"></param>
+        /// <returns></returns>
+        public static DateTimeOffset GetDateTime(long timeStamp)
+        {
+            long begtime = timeStamp * 10000;
+            DateTimeOffset dt_1970 = new(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
+            long tricks_1970 = dt_1970.Ticks;//1970年1月1日刻度
+            long time_tricks = tricks_1970 + begtime;//日志日期刻度
+            DateTimeOffset dt = new DateTime(time_tricks);//转化为DateTime
+            return dt;
+        }
+
+        /// <summary>
+        ///  通过string装换为时间并获取时间的年、月、日、一年第几天、小时
+        /// </summary>
+        /// <param name="time">时间,例如:2022060706</param>
+        /// <param name="timeStrType">时间类型: 例如:yyyyMMddHH </param>
+        /// <returns></returns>
+        public static (int year,int month,int day, int days, int hour) GetDateTime(string time, string timeStrType = null)  
+        {
+            string type = "yyyyMMddHH";
+            if (!string.IsNullOrEmpty(timeStrType)) 
+            {
+                type = timeStrType;
+            }
+
+            int year = 0, month = 0, day = 0, days = 0, hour = 0;
+            DateTimeOffset dateTime = new();
+            dateTime = DateTime.ParseExact(time, type, System.Globalization.CultureInfo.CurrentCulture);
+            year = dateTime.Year;
+            month = dateTime.Month;
+            day = dateTime.Day;
+            DateTimeOffset dt1 = new DateTime(year, 1, 1);
+
+            days = (dateTime.Date - dt1.Date).Days + 1;
+            hour = dateTime.Hour;
+
+            return (year, month, day, days, hour);
+        }
+
+        /// <summary>
+        /// 获取月份的开始和结束时间戳   13位
+        /// </summary>
+        /// <param name="year"></param>
+        /// <param name="month"></param>
+        /// <returns></returns>
+        public static (long start, long end) GetMonthStartEnd(int year, int month, bool dateLenth = true)
+        {
+            DateTimeOffset dtNew = new(year, month, 1, 0, 0, 0, TimeSpan.Zero);
+            long start = DateTimeOffset.Parse($"{dtNew}").ToUnixTimeMilliseconds();
+            if (dateLenth == false) start = DateTimeOffset.Parse($"{dtNew}").ToUnixTimeSeconds();
+            var ste = dtNew.AddMonths(1).AddDays(-1).Day;
+            long end = new DateTimeOffset(dtNew.Year, dtNew.Month, ste, 23, 59, 59,TimeSpan.Zero).ToUnixTimeMilliseconds();
+            // DateTimeOffset.Parse($"{dt.Year}-{dt.Month}-{ste} 23:59:59").ToUnixTimeMilliseconds();
+            if (dateLenth == false) end = new DateTimeOffset(dtNew.Year, dtNew.Month, dtNew.Day, 23, 59, 59, TimeSpan.Zero).ToUnixTimeSeconds();
+            //DateTimeOffset.Parse($"{dt.Year}-{dt.Month}-{ste} 23:59:59").ToUnixTimeSeconds();
+
+            return (start, end);
+        }
+
+        /// <summary>
+        /// 通过时间获取当前年开始月份到现在月的开始时间到结束时间  现在月是当前天的结束时间
+        /// </summary>
+        /// <param name="date"></param>
+        /// <param name="dateLenth"></param>
+        /// <returns></returns>
+        public static async Task<List<StartEndTime>> GetYearSataMthCtMth(DateTimeOffset date,bool dateLenth = true) 
+        {
+            int year = date.Year;
+            int mth = date.Month;
+            int day = date.Day;
+
+            List<StartEndTime> monthStartEnds = new();
+            for (int i = 1; i <= mth; i++)
+            {
+                StartEndTime monthStartEnd = new() { date = $"{year}-{i}" };
+                //DateTime dt = DateTime.Parse($"{year}-{i}");
+                DateTimeOffset dtNew = new(year, i, 1, 0, 0, 0, TimeSpan.Zero);
+                long start = dtNew.ToUnixTimeMilliseconds();
+                if (dateLenth == false)
+                    start = DateTimeOffset.Parse($"{dtNew}").ToUnixTimeSeconds();
+                monthStartEnd.start = start;
+                long end = 0;
+                if (i == mth)
+                {
+                    end = DateTimeOffset.Parse($"{year}-{mth}-{day} 23:59:59").ToUnixTimeMilliseconds();
+                    if (dateLenth == false)
+                        end = DateTimeOffset.Parse($"{year}-{mth}-{day} 23:59:59").ToUnixTimeSeconds();
+                }
+                else
+                {
+                    var ste = dtNew.AddMonths(1).AddDays(-1).Day;
+                    end = DateTimeOffset.Parse($"{dtNew.Year}-{dtNew.Month}-{ste} 23:59:59").ToUnixTimeMilliseconds();
+                    if (dateLenth == false)
+                        end = DateTimeOffset.Parse($"{dtNew.Year}-{dtNew.Month}-{ste} 23:59:59").ToUnixTimeSeconds();
+                }
+                monthStartEnd.end = end;
+                monthStartEnds.Add(monthStartEnd);
+            }
+
+            return monthStartEnds;
+        }
+
+        /// <summary>
+        /// 获取今年12个月的月份开始和结束时间戳 13位 10位  
+        /// </summary>
+        /// <param name="year">年份</param>
+        /// <param name="dateLenth">true :13位时间戳  false:10位时间戳</param>
+        /// <returns></returns>
+        public static List<StartEndTime> GetYearMonthlyStartEnd(int year, bool dateLenth = true)
+        {
+            List<StartEndTime> monthStartEnds = new();
+            for (int i = 1; i <= 12; i++)
+            {
+                StartEndTime monthStartEnd = new StartEndTime() { date = $"{year}-{i}" };
+                //DateTime dt = DateTime.Parse($"{year}-{i}");
+                DateTimeOffset dtNew = new(year, i, 1, 0, 0, 0, TimeSpan.Zero);
+                long start = dtNew.ToUnixTimeMilliseconds();
+                if (dateLenth == false) 
+                    start = dtNew.ToUnixTimeSeconds();
+                monthStartEnd.start = start;
+                var ste = dtNew.AddMonths(1).AddDays(-1).Day;
+                long end = DateTimeOffset.Parse($"{dtNew.Year}-{dtNew.Month}-{ste} 23:59:59").ToUnixTimeMilliseconds();
+                if (dateLenth == false) 
+                    end = DateTimeOffset.Parse($"{dtNew.Year}-{dtNew.Month}-{ste} 23:59:59").ToUnixTimeSeconds();
+                monthStartEnd.end = end;
+                monthStartEnds.Add(monthStartEnd);
+            }
+
+            return monthStartEnds;
+        }
+
+        /// <summary>
+        /// 获取过去12个月的每月开始和结束的时间戳
+        /// </summary>
+        /// <param name="yearMonth">日期</param>
+        /// <param name="dateLenth">true :13位时间戳  false:10位时间戳</param>
+        /// <returns></returns>
+        public static List<StartEndTime> monthsOfYear(string yearMonth, bool dateLenth = true)
+        {
+            List<StartEndTime> monthStartEnds = new();
+            DateTime dateTime = DateTime.Parse(yearMonth);
+
+            int year = dateTime.Year;
+            int month = dateTime.Month;
+            List<string> months = new();
+            while (year > dateTime.Year - 1 || month > dateTime.Month)
+            {
+                StartEndTime monthStartEnd = new() { date = $"{year}-{month}" };
+
+                DateTimeOffset dtNew = new(year, month, 1, 0, 0, 0, TimeSpan.Zero);
+                long start = dateLenth ? dtNew.ToUnixTimeMilliseconds() : dtNew.ToUnixTimeSeconds();
+                monthStartEnd.start = start;
+                var ste = dtNew.AddMonths(1).AddDays(-1).Day;
+                long end = dateLenth ? DateTimeOffset.Parse($"{dateTime.Year}-{dateTime.Month}-{ste} 23:59:59").ToUnixTimeMilliseconds() : DateTimeOffset.Parse($"{dateTime.Year}-{dateTime.Month}-{ste} 23:59:59").ToUnixTimeSeconds();
+                monthStartEnd.end = end;
+
+                monthStartEnds.Add(monthStartEnd);
+                
+                months.Add($"{year}-{(month < 10 ? "0" : "") + month}");
+                month -= 1;
+                if (month <= 0)
+                {
+                    year -= 1;
+                    month = 12;
+                }
+            }
+
+            return monthStartEnds;
+        }
+
+        /// <summary>
+        /// 获取传过来的时间学期的开始时间戳和结束时间  
+        /// </summary>
+        /// <param name="dateTime">日期</param>
+        /// <param name="dateLenth">true :13位时间戳  false:10位时间戳 </param>
+        /// <returns></returns>
+        public static (long start, long end) GetTermStartOrEnd(DateTimeOffset dateTime, bool dateLenth = true)
+        {
+            long start = 0; 
+            long end = 0;
+            //DateTime dateTime = tempDateTime;
+            int year = dateTime.Year;
+            int month = dateTime.Month;
+            if (month <= 8 && month >= 3)
+            {
+                DateTimeOffset newStart = new(year, 3, 1, 0, 0, 0, TimeSpan.Zero);
+                start = dateLenth ? DateTimeOffset.Parse($"{newStart}").ToUnixTimeMilliseconds() : DateTimeOffset.Parse($"{newStart}").ToUnixTimeSeconds();
+
+                DateTimeOffset newEnd = new(year, 8, 31, 23, 59, 59, TimeSpan.Zero);
+                end = dateLenth ? DateTimeOffset.Parse($"{newEnd}").ToUnixTimeMilliseconds() : DateTimeOffset.Parse($"{newEnd}").ToUnixTimeSeconds();
+            }
+            else
+            {
+                //计算当前月份
+                int days = 0;
+                if (month >= 9)
+                {
+                    DateTimeOffset newStart = new(dateTime.Year, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                    start = dateLenth ? newStart.ToUnixTimeMilliseconds() : newStart.ToUnixTimeSeconds();
+
+                    DateTimeOffset newEnd = new(dateTime.Year + 1, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59, TimeSpan.Zero);
+                    end = dateLenth ? newEnd.ToUnixTimeMilliseconds() : newEnd.ToUnixTimeSeconds();
+                }
+                else
+                {
+                    DateTimeOffset newStart = new(dateTime.Year - 1, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                    start = dateLenth ? newStart.ToUnixTimeMilliseconds() : newStart.ToUnixTimeSeconds();
+
+                    DateTimeOffset newEnd = new(dateTime.Year, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59, TimeSpan.Zero);
+                    end = dateLenth ? newEnd.ToUnixTimeMilliseconds() : newEnd.ToUnixTimeSeconds();
+                }
+            }
+
+            return (start, end);
+        }
+
+        /// <summary>
+        /// 开始时间和结束时间戳
+        /// </summary>
+        /// <param name="dateTime"></param>
+        /// <param name="type"></param>
+        /// <param name="dateLenth"></param>
+        /// <returns></returns>
+        public static (long start, long end) GetStartOrEnd(DateTimeOffset dateTime, string type = "", bool dateLenth = true)
+        {
+            try
+            {
+                long start = 0;
+                long end = 0;
+                int year = dateTime.Year;
+                int month = dateTime.Month;
+                int day = dateTime.Day;
+                int hour = dateTime.Hour;
+                DateTimeOffset tempStrart = new();
+                DateTimeOffset tempEnd = new();
+                switch (type)
+                {
+                    //今年开始、结束
+                    case "yearMonth":
+                        tempStrart = new DateTimeOffset(year, 1, 1, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, month, DateTime.DaysInMonth(year, month), 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //今年开始、结束
+                    case "year":
+                        tempStrart = new DateTimeOffset(year, 1, 1, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, 12, DateTime.DaysInMonth(year, 12), 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //去年开始、结束
+                    case "lastYear":
+                        tempStrart = new DateTimeOffset(year - 1, 1, 1, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year - 1, 12, DateTime.DaysInMonth(year, 12), 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //本学期
+                    case "term":
+                        if (month <= 8 && month >= 3)
+                        {
+                            tempStrart = new DateTimeOffset(year, 3, 1, 0, 0, 0, TimeSpan.Zero);
+                            tempEnd = new DateTimeOffset(year, 8, 31, 23, 59, 59, TimeSpan.Zero);
+                        }
+                        else
+                        {
+                            //计算当前月份
+                            int days = 0;
+                            if (month >= 9)
+                            {
+                                tempStrart = new DateTimeOffset(year, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                                tempEnd = new DateTimeOffset(year + 1, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59, TimeSpan.Zero);
+                            }
+                            else
+                            {
+                                tempStrart = new DateTimeOffset(year - 1, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                                tempEnd = new DateTimeOffset(year, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59, TimeSpan.Zero);
+                            }
+                        }
+                        break;
+                    //上学期
+                    case "lastterm":
+                        DateTimeOffset tempDate = new();
+                        if (dateTime.Month > 9)
+                            tempDate = new DateTimeOffset(year, dateTime.Month - 4, 1, 0, 0, 0, TimeSpan.Zero);
+                        else tempDate = new DateTimeOffset(year - 1, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                        if (!string.IsNullOrEmpty($"{tempDate}"))
+                        {
+                            year = tempDate.Year;
+                            month = tempDate.Month;
+                            if (month <= 8 && month >= 3)
+                            {
+                                tempStrart = new DateTimeOffset(year, 3, 1, 0, 0, 0, TimeSpan.Zero);
+                                tempEnd = new DateTimeOffset(year, 8, 31, 23, 59, 59,TimeSpan.Zero);
+                            }
+                            else
+                            {
+                                //计算当前月份
+                                int days = 0;
+                                if (month >= 9)
+                                {
+                                    tempStrart = new DateTimeOffset(year, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                                    tempEnd = new DateTimeOffset(year + 1, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59,TimeSpan.Zero);
+                                }
+                                else
+                                {
+                                    tempStrart = new DateTimeOffset(year - 1, 9, 1, 0, 0, 0, TimeSpan.Zero);
+                                    tempEnd = new DateTimeOffset(year, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59, TimeSpan.Zero);
+                                }
+                            }
+                        }
+                        break;
+                    //上个月
+                    case "lastMonth":
+                        tempStrart = new DateTimeOffset(year, month - 1, 1, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, month - 1, DateTime.DaysInMonth(year, month - 1), 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //本月1号至当天
+                    case "monthDay":
+                        tempStrart = new DateTimeOffset(year, month, 1, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, month, day, 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //本月
+                    case "month":
+                        tempStrart = new DateTimeOffset(year, month, 1, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, month, DateTime.DaysInMonth(year, month), 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //上周
+                    case "week":
+                        DateTimeOffset weekStrart = dateTime.AddDays(-(int)(dateTime.DayOfWeek) + 1);
+                        DateTimeOffset weekEnd = dateTime.AddDays(7 - (int)(dateTime.DayOfWeek));
+                        tempStrart = new DateTimeOffset(weekStrart.Year, weekStrart.Month, weekStrart.Day, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(weekEnd.Year, weekEnd.Month, weekEnd.Day, 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //上周
+                    case "lastweek":
+                        var m = (dateTime.DayOfWeek == DayOfWeek.Sunday ? (DayOfWeek)7 : dateTime.DayOfWeek) - DayOfWeek.Monday;
+                        var s = (dateTime.DayOfWeek == DayOfWeek.Sunday ? (DayOfWeek)7 : dateTime.DayOfWeek) - (DayOfWeek)7;
+                        var Mon = dateTime.AddDays((-7 - m));//星期一
+                        var Sun = dateTime.AddDays((-7 - s));  //星期日
+                        tempStrart = new DateTimeOffset(Mon.Year, Mon.Month, Mon.Day, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(Sun.Year, Sun.Month, Sun.Day, 23, 59, 59, TimeSpan.Zero);
+                        break;
+                    //当前小时
+                    case "hour":
+                        tempStrart = new DateTimeOffset(year, month, day, hour, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, month, day, hour, 59, 59, TimeSpan.Zero);
+
+                        break;
+                    //当天
+                    default:
+                        tempStrart = new DateTimeOffset(year, month, day, 0, 0, 0, TimeSpan.Zero);
+                        tempEnd = new DateTimeOffset(year, month, day, 23, 59, 59, TimeSpan.Zero);
+                        //start = dateLenth ? DateTimeOffset.Parse($"{dayStart}").ToUnixTimeMilliseconds() : DateTimeOffset.Parse($"{dayStart}").ToUnixTimeSeconds();
+                        //end = dateLenth ? DateTimeOffset.Parse($"{dayEnd}").ToUnixTimeMilliseconds() : DateTimeOffset.Parse($"{dayEnd}").ToUnixTimeSeconds();
+                        break;
+                }
+
+                start = dateLenth ? tempStrart.ToUnixTimeMilliseconds() : tempStrart.ToUnixTimeSeconds();
+                end = dateLenth ? tempEnd.ToUnixTimeMilliseconds() : tempEnd.ToUnixTimeSeconds();
+
+                return (start, end);
+            }
+            catch (Exception ex)
+            {
+                throw;
+            }
+        }
+
+        /// <summary>
+        /// 将时间戳格式 转换成string类型
+        /// 例:yyyyMMdd,等string类型
+        /// </summary>
+        /// <param name="unixTime"></param>
+        /// <returns></returns>
+        public static (string timeStart,string timeEnd) GetUnixToDate(long start,long end = 0,string types="yyyyMMdd")
+        {
+            string tStart = "";
+            string tEnd = "";
+            DateTimeOffset time = System.TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1, 0, 0, 0, 0));
+            tStart = time.AddMilliseconds(start).ToString($"{types}");
+            if (end > 0) 
+            {
+                tEnd = time.AddMilliseconds(end).ToString($"{types}");
+            }
+
+            return (tStart, tEnd);
+        }
+
+        /// <summary>
+        /// 获取每天的时间
+        /// </summary>
+        /// <param name="dateTime">时间</param>
+        /// <param name="dayNumber">最近几天</param>
+        /// <returns></returns>
+        public static List<string> GetNearDay(DateTimeOffset dateTime,int dayNumber)
+        {
+            List<string> days = new();
+
+            days = Enumerable.Range(1, dayNumber).Select(i => dateTime.Date.AddDays(-i).ToString("yyyyMMdd")).ToList();
+
+            return days;
+        }
+
+
+        public static List<YearMonth> GetYearMonth(List<double> doubles, int year = 0,int month = 0) 
+        {
+            List<YearMonth> months = new();
+            DateTimeOffset dateTime = DateTimeOffset.Now;
+            if (year == 0) 
+                year = dateTime.Year;
+            if(month == 0)
+                month = dateTime.Month;
+
+            List<int> isLeapYear = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? isLeapYear = leapY : isLeapYear = flatY;
+            double[] array = doubles.ToArray();
+            double ser = doubles.Sum();
+            int moth = 1;
+            int primaryD = 0;
+            for (int i = 0; i < isLeapYear.Count; i++)
+            {
+                if (month < moth)
+                    break;
+                double[] temp = new double[isLeapYear[i]];
+                Array.ConstrainedCopy(array, primaryD, temp, 0, isLeapYear[i]);
+                months.Add(new YearMonth() { id = $"{year}-{moth}", cnt = temp.Sum() });
+                moth += 1;
+                primaryD += isLeapYear[i];
+            }
+
+            return months;
+        }
+    }
+}

+ 134 - 2
TEAMModelOS.FunctionV4/HttpTrigger/BIHttpTrigger.cs

@@ -1,9 +1,21 @@
+using System;
 using System.Collections.Generic;
+using System.Dynamic;
+using System.IO;
 using System.Net;
 using System.Net.Http;
+using System.Text.Json;
+using System.Threading.Tasks;
+using Azure.Cosmos;
+using Azure.Storage.Blobs;
+using Microsoft.AspNetCore.Http;
 using Microsoft.Azure.Functions.Worker;
 using Microsoft.Azure.Functions.Worker.Http;
+using StackExchange.Redis;
 using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service.BIStatsWay;
 
 namespace TEAMModelOS.FunctionV4.HttpTrigger
 {
@@ -15,7 +27,6 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
         private readonly AzureRedisFactory _azureRedis;
         private readonly HttpClient _httpClient;
 
-
         public BIHttpTrigger(AzureCosmosFactory azureCosmos, DingDing dingDing, AzureStorageFactory azureStorage, AzureRedisFactory azureRedis, HttpClient httpClient)
         {
             _azureCosmos = azureCosmos;
@@ -31,12 +42,133 @@ namespace TEAMModelOS.FunctionV4.HttpTrigger
         /// <param name="req"></param>
         /// <returns></returns>
         [Function("stats-sc-info")]
-        public HttpResponseData StatsSchoolInfo([HttpTrigger(AuthorizationLevel.Function, "get", Route = null)] HttpRequestData req)
+        public async Task<HttpResponseData> StatsSchoolInfo([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestData req)
+        {
+            var response = req.CreateResponse(HttpStatusCode.OK);
+
+            dynamic jsondata = new ExpandoObject();
+            try
+            {
+                string scId = null;
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+                var tableClient = _azureStorage.GetCloudTableClient();
+                var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
+                string data = await new StreamReader(req.Body).ReadToEndAsync();
+                var json = JsonDocument.Parse(data).RootElement;
+                jsondata = json;
+                if (json.TryGetProperty("schoolId", out JsonElement _schoolId))
+                {
+                    scId = $"{_schoolId}";
+                }
+                if (string.IsNullOrEmpty(scId))
+                {
+                    return response;
+                }
+
+                bool locKey = await _azureRedis.GetRedisClient(8).KeyExistsAsync($"Train:Statistics:Lock:{scId}");
+                if (!locKey)
+                {
+                    await _azureRedis.GetRedisClient(8).SetAddAsync($"Train:Statistics:Lock:{scId}", new RedisValue(scId));
+                    DateTime minutes = DateTime.UtcNow.AddMinutes(15);   //15分钟
+                    await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Train:Statistics:Lock:{scId}", minutes);
+
+                    bool isExist = true;
+                    StatsInfo statsInfo = new();
+                    var scDataStats = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{scId}", new PartitionKey("Stats"));
+                    if (scDataStats.Status == 200)
+                    {
+                        using var fileJson = await JsonDocument.ParseAsync(scDataStats.ContentStream);
+                        statsInfo = fileJson.ToObject<StatsInfo>();
+                    }
+                    else                    
+                        isExist = false;
+
+                    statsInfo = await SchoolStatsWay.GetSingleSc(cosmosClient, scId);
+                    statsInfo.upTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+
+                    if (isExist)
+                        statsInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<StatsInfo>(statsInfo, statsInfo.id, new PartitionKey("Stats"));
+                    else
+                        statsInfo = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<StatsInfo>(statsInfo, new PartitionKey("Stats"));
+                }
+
+                //保存操作记录
+                await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "trigger-schoolStats", $"触发更新统计数据库", _dingDing);
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"stats-sc-info,{ex.Message}\n{ex.StackTrace}\n{jsondata.ToJsonString()}", GroupNames.成都开发測試群組);
+            }
+
+            return response;
+        }
+
+        /// <summary>
+        /// 处理传过来的信息加入到统计信息中
+        /// </summary>
+        /// <param name="req"></param>
+        /// <returns></returns>
+        [Function("set-scstats-type")]
+        public async Task<HttpResponseData> SetSchoolStatsType([HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequestData req) 
         {
             var response = req.CreateResponse(HttpStatusCode.OK);
+            dynamic jsondata = new ExpandoObject();
+            try
+            {
+                string scId = null,type = null;
+                var cosmosClient = _azureCosmos.GetCosmosClient();
+                var tableClient = _azureStorage.GetCloudTableClient();
+                var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
+                string data = await new StreamReader(req.Body).ReadToEndAsync();
+                var json = JsonDocument.Parse(data).RootElement;
+                jsondata = json;
+                if (json.TryGetProperty("schoolId", out JsonElement _schoolId))
+                {
+                    scId = $"{_schoolId}";
+                }
+                if (json.TryGetProperty("type", out JsonElement _type))
+                {
+                    type = $"{_type}";
+                }
+                if (string.IsNullOrEmpty(scId) && string.IsNullOrEmpty(scId))
+                {
+                    await _dingDing.SendBotMsg($"set-scstats-type, {req.Body};转换后:{json}", GroupNames.成都开发測試群組);
+                    return response;
+                }
+
+                switch ($"{type}")
+                {
+                    case "Exam":
+
+                        break;
+                    case "Survey":
+
+                        break;
+                    case "Vote":
+
+                        break;
+                    case "Homework":
+
+                        break;
+                    case "Less":
+
+                        break;
+                }
 
 
+
+
+
+
+
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"stats-sc-info,{ex.Message}\n{ex.StackTrace}\n{jsondata.ToJsonString()}", GroupNames.成都开发測試群組);
+            }
+
             return response;
         }
+
     }
 }

+ 3 - 2
TEAMModelOS.FunctionV4/ServiceBus/ActiveTaskTopic.cs

@@ -52,6 +52,8 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
         public static ConcurrentQueue<(ScreenshotDto screenshotDto, List<StudentArtResult> studentArts)> concurrentQueue
           = new ConcurrentQueue<(ScreenshotDto screenshotDto, List<StudentArtResult> studentArts)>();
         public static bool busy = false;
+        private readonly int psize = 20;
+        public static SpinWait spinWait = new SpinWait(); // 构造SpinWait实例
         private readonly AzureCosmosFactory _azureCosmos;
         private readonly DingDing _dingDing;
         private readonly AzureStorageFactory _azureStorage;
@@ -775,8 +777,7 @@ namespace TEAMModelOS.FunctionV4.ServiceBus
             }
             return resUrls;
         }
-        private readonly int psize = 20;
-        public static SpinWait spinWait = new SpinWait(); // 构造SpinWait实例
+       
         private async Task GenArtStudentPdf(JsonElement json, string msg) {
             try
             {

+ 1 - 1
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageBlobExtensions.cs

@@ -159,7 +159,7 @@ namespace TEAMModelOS.SDK.DI
             if (!prefixs.IsNotEmpty()) return false;
             try
             {
-                BlobContainerClient bcc = client.GetBlobContainerClient(blobContainerName);
+                BlobContainerClient bcc = client.GetBlobContainerClient(blobContainerName.ToLower());
                 BlobBatchClient bbc = client.GetBlobBatchClient();
                 List<Uri> blobs = new List<Uri>();
                 List<Task<Azure.Response<bool>>> list = new List<Task<Response<bool>>>();

+ 9 - 9
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactory.cs

@@ -54,7 +54,7 @@ namespace TEAMModelOS.SDK.DI
             try
             {
                 var options = _optionsMonitor.Get(name);
-                return new BlobContainerClient(options.StorageAccountConnectionString, containerName);
+                return new BlobContainerClient(options.StorageAccountConnectionString, containerName.ToLower());
             }
             catch (OptionsValidationException e)
             {
@@ -97,7 +97,7 @@ namespace TEAMModelOS.SDK.DI
                 {
                     StartsOn = DateTimeOffset.UtcNow.Subtract(new TimeSpan(0, 15, 0)),
                     ExpiresOn = DateTimeOffset.UtcNow.Add(new TimeSpan(36135, 0, 0, 0)),
-                    BlobContainerName = containerName
+                    BlobContainerName = containerName.ToLower()
                 };
 
                 blobSasBuilder.SetPermissions(blobContainerSasPermissions);
@@ -107,7 +107,7 @@ namespace TEAMModelOS.SDK.DI
                 {
                     Scheme = "https",
                     Host = $"{accountname}.blob.{endpoint}",
-                    Path = containerName
+                    Path = containerName.ToLower()
                     //Query = sasQueryParameters.ToString()
                 };
 
@@ -138,7 +138,7 @@ namespace TEAMModelOS.SDK.DI
                 {
                     StartsOn = DateTimeOffset.UtcNow.Subtract(new TimeSpan(0, 15, 0)),
                     ExpiresOn = DateTimeOffset.UtcNow.Add(new TimeSpan(1, 0, 15, 0)),
-                    BlobContainerName = containerName
+                    BlobContainerName = containerName.ToLower()
                 };
 
                 blobSasBuilder.SetPermissions(blobContainerSasPermissions);
@@ -148,7 +148,7 @@ namespace TEAMModelOS.SDK.DI
                 {
                     Scheme = "https",
                     Host = $"{accountname}.blob.{endpoint}",
-                    Path = containerName
+                    Path = containerName.ToLower()
                     //Query = sasQueryParameters.ToString()
                 };
 
@@ -242,7 +242,7 @@ namespace TEAMModelOS.SDK.DI
                 {
                     StartsOn = DateTimeOffset.UtcNow.Subtract(new TimeSpan(0, 15, 0)),
                     ExpiresOn = DateTimeOffset.UtcNow.Add(new TimeSpan(1, 0, 15, 0)),
-                    BlobContainerName = containerName,
+                    BlobContainerName = containerName.ToLower(),
                     BlobName = blobName
                 };
 
@@ -253,7 +253,7 @@ namespace TEAMModelOS.SDK.DI
                 {
                     Scheme = "https",
                     Host = $"{accountname}.blob.{endpoint}",
-                    Path = $"{containerName}/{blobName}",
+                    Path = $"{containerName.ToLower()}/{blobName}",
                     Query = sasQueryParameters.ToString()
                 };
 
@@ -288,7 +288,7 @@ namespace TEAMModelOS.SDK.DI
                 {
                     StartsOn = DateTimeOffset.UtcNow.Subtract(new TimeSpan(0, 15, 0)),
                     ExpiresOn = dateTime,
-                    BlobContainerName = containerName,
+                    BlobContainerName = containerName.ToLower(),
                     BlobName = blobName
                 };
 
@@ -299,7 +299,7 @@ namespace TEAMModelOS.SDK.DI
                 {
                     Scheme = "https",
                     Host = $"{accountname}.blob.{endpoint}",
-                    Path = $"{containerName}/{blobName}",
+                    Path = $"{containerName.ToLower()}/{blobName}",
                     Query = sasQueryParameters.ToString()
                 };
                 return new BlobAuth { url = fullUri.Uri.ToString(), sas = sasQueryParameters.ToString(), timeout = time };

+ 0 - 2
TEAMModelOS.SDK/DI/AzureStorage/AzureStorageFactoryOptions.cs

@@ -9,6 +9,4 @@ namespace TEAMModelOS.SDK.DI
         public string Name { get; set; }
         public string StorageAccountConnectionString { get; set; }
     }
-
-   
 }

File diff suppressed because it is too large
+ 1028 - 0
TEAMModelOS.SDK/DI/StudyAPI/ScsStudyApisService.cs


+ 2 - 2
TEAMModelOS.SDK/Models/Cosmos/BI/BICommon/MonthStartEnd.cs

@@ -6,9 +6,9 @@ using System.Threading.Tasks;
 
 namespace TEAMModelOS.SDK.Models
 {
-    public class MonthStartEnd
+    public class StartEndTime
     {
-        public string yearMonth { get; set; }
+        public string date { get; set; }
 
         public long start { get; set; }
 

+ 19 - 17
TEAMModelBI/Models/FrontModel.cs

@@ -1,19 +1,13 @@
-using TEAMModelOS.SDK.Models;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
 
-namespace TEAMModelBI.Models
+namespace TEAMModelOS.SDK.Models.Cosmos.BI
 {
-    /// <summary>
-    /// 前端显示相关的结构
-    /// </summary>
-    public class FrontModel
-    {
-    }
-
-    public class YearMonth
+    public class CurrencyModel
     {
-        public string id { get; set; }
-
-        public double cnt { get; set; }
     }
 
     /// <summary>
@@ -29,6 +23,16 @@ namespace TEAMModelBI.Models
         public long createTime { get; set; }
     }
 
+    /// <summary>
+    /// 
+    /// </summary>
+    public class YearMonth
+    {
+        public string id { get; set; }
+
+        public double cnt { get; set; }
+    }
+
     /// <summary>
     /// 研修活动统计
     /// </summary>
@@ -38,6 +42,8 @@ namespace TEAMModelBI.Models
 
         public string code { get; set; }
 
+        public int totalTime { get; set; }
+
         /// <summary>
         /// 线上观看视频的学时
         /// </summary>
@@ -56,8 +62,4 @@ namespace TEAMModelBI.Models
         /// </summary>
         public Currency currency { get; set; } = new Currency();
     }
-
-
-
-
 }

+ 12 - 12
TEAMModelOS.SDK/Models/Cosmos/BI/StatsInfo.cs

@@ -28,6 +28,11 @@ namespace TEAMModelOS.SDK.Models.Cosmos.BI
         /// </summary>
         public string name { get; set; }
 
+        /// <summary>
+        /// 空间
+        /// </summary>
+        public int size { get; set; }
+
         /// <summary>
         /// 教师总数
         /// </summary>
@@ -78,11 +83,6 @@ namespace TEAMModelOS.SDK.Models.Cosmos.BI
         /// </summary>
         public int witRoom { get; set; }
 
-        /// <summary>
-        /// 空间
-        /// </summary>
-        public int size { get; set; }
-
         /// <summary>
         /// 学校创建时间
         /// </summary>
@@ -96,17 +96,17 @@ namespace TEAMModelOS.SDK.Models.Cosmos.BI
         /// <summary>
         /// 课例活动
         /// </summary>
-        public LessonStats lesson { get; set; }
+        public LessonStats lesson { get; set; } = new LessonStats();
 
         /// <summary>
         /// 活动
         /// </summary>
-        public ActivityStats activity { get; set; }
+        public ActivityStats activity { get; set; } = new ActivityStats();
 
         /// <summary>
         /// 研修统计
         /// </summary>
-        public StudyStats study { get; set; }
+        public StudyStats study { get; set; } = new StudyStats();
     }
 
     /// <summary>
@@ -268,19 +268,19 @@ namespace TEAMModelOS.SDK.Models.Cosmos.BI
         /// <summary>
         /// 线上研修人数
         /// </summary>
-        public int onlineTime { get; set; }
+        public int online { get; set; }
         /// <summary>
         /// 线下研修人数
         /// </summary>
-        public int offlineTime { get; set; }
+        public int offline { get; set; }
         /// <summary>
         /// 课堂实录人数
         /// </summary>
-        public int classTime { get; set; }
+        public int classRoom { get; set; }
         /// <summary>
         /// 认证材料人数
         /// </summary>
-        public int currency { get; set; }
+        public int submit { get; set; }
         /// <summary>
         /// 未开始的研修人数
         /// </summary>

+ 9 - 6
TEAMModelBI/Tool/CosmosBank/JointlySingleQuery.cs

@@ -1,8 +1,11 @@
 using Azure.Cosmos;
+using System;
 using System.Collections.Generic;
+using System.Linq;
+using System.Text;
 using System.Threading.Tasks;
 
-namespace TEAMModelBI.Tool.CosmosBank
+namespace TEAMModelOS.SDK.Models.Service.BI
 {
     public class JointlySingleQuery
     {
@@ -14,16 +17,16 @@ namespace TEAMModelBI.Tool.CosmosBank
         /// <param name="sqlTxt"></param>
         /// <param name="code"></param>
         /// <returns></returns>
-        public static async Task<int> GetValueInt(CosmosClient cosmosClient, List<string> containerId, string sqlTxt = null, string code = null) 
+        public static async Task<int> GetValueInt(CosmosClient cosmosClient, List<string> containerId, string sqlTxt = null, string code = null)
         {
             int totals = 0;
             string sql = $"select value(count(c.id)) from c";
-            if (!string.IsNullOrEmpty(sqlTxt)) 
+            if (!string.IsNullOrEmpty(sqlTxt))
             {
                 sql = sqlTxt;
             }
 
-            foreach (string conId in containerId) 
+            foreach (string conId in containerId)
             {
                 await foreach (var itemInt in cosmosClient.GetContainer("TEAMModelOS", conId).GetItemQueryIterator<int>(queryText: sql, requestOptions: string.IsNullOrEmpty($"{code}") ? new QueryRequestOptions() { } : new QueryRequestOptions() { PartitionKey = new PartitionKey($"{code}") }))
                 {
@@ -31,7 +34,7 @@ namespace TEAMModelBI.Tool.CosmosBank
                 }
             }
 
-            return totals;            
+            return totals;
         }
 
         /// <summary>
@@ -67,7 +70,7 @@ namespace TEAMModelBI.Tool.CosmosBank
         /// <param name="sqlTxt"></param>
         /// <param name="code"></param>
         /// <returns></returns>
-        public static async Task<List<string>> GetListString(CosmosClient cosmosClient, string containerId, string sqlTxt, string code = null) 
+        public static async Task<List<string>> GetListString(CosmosClient cosmosClient, string containerId, string sqlTxt, string code = null)
         {
             List<string> strList = new();
 

+ 95 - 47
TEAMModelBI/Tool/TimeHelper.cs

@@ -1,12 +1,13 @@
 using DocumentFormat.OpenXml.Bibliography;
+using Microsoft.Azure.Amqp.Framing;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Text;
 using System.Threading.Tasks;
-using TEAMModelBI.Models;
-using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
 
-namespace TEAMModelBI.Tool
+namespace TEAMModelOS.SDK.Models.Service.BI
 {
     public static class TimeHelper
     {
@@ -41,10 +42,10 @@ namespace TEAMModelBI.Tool
         /// <param name="time">时间,例如:2022060706</param>
         /// <param name="timeStrType">时间类型: 例如:yyyyMMddHH </param>
         /// <returns></returns>
-        public static (int year,int month,int day, int days, int hour) GetDateTime(string time, string timeStrType = null)  
+        public static (int year, int month, int day, int days, int hour) GetDateTime(string time, string timeStrType = null)
         {
             string type = "yyyyMMddHH";
-            if (!string.IsNullOrEmpty(timeStrType)) 
+            if (!string.IsNullOrEmpty(timeStrType))
             {
                 type = timeStrType;
             }
@@ -75,7 +76,7 @@ namespace TEAMModelBI.Tool
             long start = DateTimeOffset.Parse($"{dtNew}").ToUnixTimeMilliseconds();
             if (dateLenth == false) start = DateTimeOffset.Parse($"{dtNew}").ToUnixTimeSeconds();
             var ste = dtNew.AddMonths(1).AddDays(-1).Day;
-            long end = new DateTimeOffset(dtNew.Year, dtNew.Month, ste, 23, 59, 59,TimeSpan.Zero).ToUnixTimeMilliseconds();
+            long end = new DateTimeOffset(dtNew.Year, dtNew.Month, ste, 23, 59, 59, TimeSpan.Zero).ToUnixTimeMilliseconds();
             // DateTimeOffset.Parse($"{dt.Year}-{dt.Month}-{ste} 23:59:59").ToUnixTimeMilliseconds();
             if (dateLenth == false) end = new DateTimeOffset(dtNew.Year, dtNew.Month, dtNew.Day, 23, 59, 59, TimeSpan.Zero).ToUnixTimeSeconds();
             //DateTimeOffset.Parse($"{dt.Year}-{dt.Month}-{ste} 23:59:59").ToUnixTimeSeconds();
@@ -89,16 +90,16 @@ namespace TEAMModelBI.Tool
         /// <param name="date"></param>
         /// <param name="dateLenth"></param>
         /// <returns></returns>
-        public static async Task<List<MonthStartEnd>> GetYearSataMthCtMth(DateTimeOffset date,bool dateLenth = true) 
+        public static async Task<List<StartEndTime>> GetYearSataMthCtMth(DateTimeOffset date, bool dateLenth = true)
         {
             int year = date.Year;
             int mth = date.Month;
             int day = date.Day;
 
-            List<MonthStartEnd> monthStartEnds = new();
+            List<StartEndTime> monthStartEnds = new();
             for (int i = 1; i <= mth; i++)
             {
-                MonthStartEnd monthStartEnd = new() { yearMonth = $"{year}-{i}" };
+                StartEndTime monthStartEnd = new() { date = $"{year}-{i}" };
                 //DateTime dt = DateTime.Parse($"{year}-{i}");
                 DateTimeOffset dtNew = new(year, i, 1, 0, 0, 0, TimeSpan.Zero);
                 long start = dtNew.ToUnixTimeMilliseconds();
@@ -132,21 +133,21 @@ namespace TEAMModelBI.Tool
         /// <param name="year">年份</param>
         /// <param name="dateLenth">true :13位时间戳  false:10位时间戳</param>
         /// <returns></returns>
-        public static List<MonthStartEnd> GetYearMonthlyStartEnd(int year, bool dateLenth = true)
+        public static List<StartEndTime> GetYearMonthlyStartEnd(int year, bool dateLenth = true)
         {
-            List<MonthStartEnd> monthStartEnds = new();
+            List<StartEndTime> monthStartEnds = new();
             for (int i = 1; i <= 12; i++)
             {
-                MonthStartEnd monthStartEnd = new MonthStartEnd() { yearMonth = $"{year}-{i}" };
+                StartEndTime monthStartEnd = new() { date = $"{year}-{i}" };
                 //DateTime dt = DateTime.Parse($"{year}-{i}");
                 DateTimeOffset dtNew = new(year, i, 1, 0, 0, 0, TimeSpan.Zero);
                 long start = dtNew.ToUnixTimeMilliseconds();
-                if (dateLenth == false) 
+                if (dateLenth == false)
                     start = dtNew.ToUnixTimeSeconds();
                 monthStartEnd.start = start;
                 var ste = dtNew.AddMonths(1).AddDays(-1).Day;
                 long end = DateTimeOffset.Parse($"{dtNew.Year}-{dtNew.Month}-{ste} 23:59:59").ToUnixTimeMilliseconds();
-                if (dateLenth == false) 
+                if (dateLenth == false)
                     end = DateTimeOffset.Parse($"{dtNew.Year}-{dtNew.Month}-{ste} 23:59:59").ToUnixTimeSeconds();
                 monthStartEnd.end = end;
                 monthStartEnds.Add(monthStartEnd);
@@ -161,17 +162,17 @@ namespace TEAMModelBI.Tool
         /// <param name="yearMonth">日期</param>
         /// <param name="dateLenth">true :13位时间戳  false:10位时间戳</param>
         /// <returns></returns>
-        public static List<MonthStartEnd> monthsOfYear(string yearMonth, bool dateLenth = true)
+        public static List<StartEndTime> monthsOfYear(string yearMonth, bool dateLenth = true)
         {
-            List<MonthStartEnd> monthStartEnds = new();
+            List<StartEndTime> monthStartEnds = new();
             DateTime dateTime = DateTime.Parse(yearMonth);
 
             int year = dateTime.Year;
             int month = dateTime.Month;
-            List<string> months = new List<string>();
+            List<string> months = new();
             while (year > dateTime.Year - 1 || month > dateTime.Month)
             {
-                MonthStartEnd monthStartEnd = new MonthStartEnd() { yearMonth = $"{year}-{month}" };
+                StartEndTime monthStartEnd = new() { date = $"{year}-{month}" };
 
                 DateTimeOffset dtNew = new(year, month, 1, 0, 0, 0, TimeSpan.Zero);
                 long start = dateLenth ? dtNew.ToUnixTimeMilliseconds() : dtNew.ToUnixTimeSeconds();
@@ -181,7 +182,7 @@ namespace TEAMModelBI.Tool
                 monthStartEnd.end = end;
 
                 monthStartEnds.Add(monthStartEnd);
-                
+
                 months.Add($"{year}-{(month < 10 ? "0" : "") + month}");
                 month -= 1;
                 if (month <= 0)
@@ -202,7 +203,7 @@ namespace TEAMModelBI.Tool
         /// <returns></returns>
         public static (long start, long end) GetTermStartOrEnd(DateTimeOffset dateTime, bool dateLenth = true)
         {
-            long start = 0; 
+            long start = 0;
             long end = 0;
             //DateTime dateTime = tempDateTime;
             int year = dateTime.Year;
@@ -312,7 +313,7 @@ namespace TEAMModelBI.Tool
                             if (month <= 8 && month >= 3)
                             {
                                 tempStrart = new DateTimeOffset(year, 3, 1, 0, 0, 0, TimeSpan.Zero);
-                                tempEnd = new DateTimeOffset(year, 8, 31, 23, 59, 59,TimeSpan.Zero);
+                                tempEnd = new DateTimeOffset(year, 8, 31, 23, 59, 59, TimeSpan.Zero);
                             }
                             else
                             {
@@ -321,7 +322,7 @@ namespace TEAMModelBI.Tool
                                 if (month >= 9)
                                 {
                                     tempStrart = new DateTimeOffset(year, 9, 1, 0, 0, 0, TimeSpan.Zero);
-                                    tempEnd = new DateTimeOffset(year + 1, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59,TimeSpan.Zero);
+                                    tempEnd = new DateTimeOffset(year + 1, 2, (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? days = 29 : days = 28, 23, 59, 59, TimeSpan.Zero);
                                 }
                                 else
                                 {
@@ -388,19 +389,57 @@ namespace TEAMModelBI.Tool
             }
         }
 
+        /// <summary>
+        /// 计算每年获取开始时间
+        /// </summary>
+        /// <param name="dateTime"></param>
+        /// <param name="dateLenth"></param>
+        /// <returns></returns>
+        public static List<StartEndTime> GetYearEveryDay(DateTimeOffset dateTime, bool dateLenth = true,bool isCurrDay = false) 
+        {
+            List<StartEndTime> dayStartEen = new();
+            int year = dateTime.Year;
+            int curry = dateTime.DayOfYear;
+            List<int> isLeapYear = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? isLeapYear = leapY : isLeapYear = flatY;
+            for (int m = 1; m <= 12; m++)
+            {
+                for (int d = 1; d <= isLeapYear[m - 1]; d++)
+                {
+                    if (isCurrDay == true && (curry <= dayStartEen.Count))
+                        break;
+                    DateTimeOffset tempStrart = new(year, m, d, 0, 0, 0, TimeSpan.Zero);
+                    DateTimeOffset tempEnd = new(year, m, d, 23, 59, 59, TimeSpan.Zero);
+
+                    long longStart = dateLenth ? tempStrart.ToUnixTimeMilliseconds() : tempStrart.ToUnixTimeSeconds();
+                    long longEnd = dateLenth ? tempEnd.ToUnixTimeMilliseconds() : tempEnd.ToUnixTimeSeconds();
+
+                    dayStartEen.Add(new StartEndTime() { date = $"{year}-{m}-{d}", start = longStart, end = longEnd });
+                }
+
+                ////DateTime 有方法
+                //DateTime monthStart = new DateTime(year, i, 01);
+                //DateTime monthEnd = dateTime.AddMonths(1);
+
+                //DateTimeOffset tempStrart = new DateTimeOffset(year, i, days, 0, 0, 0, TimeSpan.Zero);
+                //DateTimeOffset tempEnd = new DateTimeOffset(year, i, days, 23, 59, 59, TimeSpan.Zero);
+            }
+
+            return dayStartEen;
+        }
+
         /// <summary>
         /// 将时间戳格式 转换成string类型
         /// 例:yyyyMMdd,等string类型
         /// </summary>
         /// <param name="unixTime"></param>
         /// <returns></returns>
-        public static (string timeStart,string timeEnd) GetUnixToDate(long start,long end = 0,string types="yyyyMMdd")
+        public static (string timeStart, string timeEnd) GetUnixToDate(long start, long end = 0, string types = "yyyyMMdd")
         {
             string tStart = "";
             string tEnd = "";
             DateTimeOffset time = System.TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1, 0, 0, 0, 0));
             tStart = time.AddMilliseconds(start).ToString($"{types}");
-            if (end > 0) 
+            if (end > 0)
             {
                 tEnd = time.AddMilliseconds(end).ToString($"{types}");
             }
@@ -414,7 +453,7 @@ namespace TEAMModelBI.Tool
         /// <param name="dateTime">时间</param>
         /// <param name="dayNumber">最近几天</param>
         /// <returns></returns>
-        public static List<string> GetNearDay(DateTimeOffset dateTime,int dayNumber)
+        public static List<string> GetNearDay(DateTimeOffset dateTime, int dayNumber)
         {
             List<string> days = new();
 
@@ -423,33 +462,42 @@ namespace TEAMModelBI.Tool
             return days;
         }
 
-
-        public static List<YearMonth> GetYearMonth(List<double> doubles, int year = 0,int month = 0) 
+        /// <summary>
+        /// 12个月
+        /// </summary>
+        /// <param name="doubles"></param>
+        /// <param name="year"></param>
+        /// <param name="month"></param>
+        /// <returns></returns>
+        public static List<YearMonth> GetYearMonth(List<double> doubles, int year = 0, int month = 0)
         {
             List<YearMonth> months = new();
-            DateTimeOffset dateTime = DateTimeOffset.Now;
-            if (year == 0) 
-                year = dateTime.Year;
-            if(month == 0)
-                month = dateTime.Month;
-
-            List<int> isLeapYear = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? isLeapYear = leapY : isLeapYear = flatY;
-            double[] array = doubles.ToArray();
-            double ser = doubles.Sum();
-            int moth = 1;
-            int primaryD = 0;
-            for (int i = 0; i < isLeapYear.Count; i++)
+            if (doubles.Count > 0)
             {
-                if (month < moth)
-                    break;
-                double[] temp = new double[isLeapYear[i]];
-                Array.ConstrainedCopy(array, primaryD, temp, 0, isLeapYear[i]);
-                months.Add(new YearMonth() { id = $"{year}-{moth}", cnt = temp.Sum() });
-                moth += 1;
-                primaryD += isLeapYear[i];
+                DateTimeOffset dateTime = DateTimeOffset.Now;
+                if (year == 0)
+                    year = dateTime.Year;
+                if (month == 0)
+                    month = dateTime.Month;
+
+                List<int> isLeapYear = (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) ? isLeapYear = leapY : isLeapYear = flatY;
+                double[] array = doubles.ToArray();
+                double ser = doubles.Sum();
+                int moth = 1;
+                int primaryD = 0;
+                for (int i = 0; i < isLeapYear.Count; i++)
+                {
+                    if (month < moth)
+                        break;
+                    double[] temp = new double[isLeapYear[i]];
+                    Array.ConstrainedCopy(array, primaryD, temp, 0, isLeapYear[i]);
+                    months.Add(new YearMonth() { id = $"{year}-{moth}", cnt = temp.Sum() });
+                    moth += 1;
+                    primaryD += isLeapYear[i];
+                }
             }
-
             return months;
         }
+
     }
 }

+ 8 - 5
TEAMModelBI/Tool/BIStatsWay/ActivityStatsWay.cs

@@ -1,10 +1,13 @@
-using System.Threading.Tasks;
+using Azure.Cosmos;
 using System;
-using TEAMModelBI.Tool.CosmosBank;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
-using Azure.Cosmos;
+using TEAMModelOS.SDK.Models.Service.BI;
 
-namespace TEAMModelBI.Tool.BIStatsWay
+namespace TEAMModelOS.SDK.Models.Service.BIStatsWay
 {
     public static class ActivityStatsWay
     {
@@ -14,7 +17,7 @@ namespace TEAMModelBI.Tool.BIStatsWay
         /// <param name="cosmosClient"></param>
         /// <param name="scId"></param>
         /// <returns></returns>
-        public static async Task<ActivityStats> GetActStats(CosmosClient cosmosClient, string scId)
+        public static async Task<ActivityStats> GetSchoolAll(CosmosClient cosmosClient, string scId)
         {
             ActivityStats actStats = new();
 

+ 9 - 6
TEAMModelBI/Tool/BIStatsWay/LessonRecordStatsWay.cs

@@ -1,12 +1,15 @@
-using System.Threading.Tasks;
+using Azure.Cosmos;
 using System;
-using TEAMModelBI.Tool.CosmosBank;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
 using TEAMModelOS.SDK.Models.Cosmos.BI;
-using Azure.Cosmos;
+using TEAMModelOS.SDK.Models.Service.BI;
 
-namespace TEAMModelBI.Tool.BIStatsWay
+namespace TEAMModelOS.SDK.Models.Service.BIStatsWay
 {
-    public  static class LessonRecordStatsWay
+    public static class LessonRecordStatsWay
     {
 
         /// <summary>
@@ -15,7 +18,7 @@ namespace TEAMModelBI.Tool.BIStatsWay
         /// <param name="cosmosClient"></param>
         /// <param name="id"></param>
         /// <returns></returns>
-        public static async Task<LessonStats> GetLessStats(CosmosClient cosmosClient, string id)
+        public static async Task<LessonStats> GetSchoolAll(CosmosClient cosmosClient, string id)
         {
             LessonStats lessStats = new();
 

+ 199 - 0
TEAMModelOS.SDK/Models/Service/BIStatsWay/SchoolStatsWay.cs

@@ -0,0 +1,199 @@
+using Azure.Cosmos;
+using DocumentFormat.OpenXml.Bibliography;
+using DocumentFormat.OpenXml.Math;
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+using TEAMModelOS.SDK.Models.Service.BI;
+
+namespace TEAMModelOS.SDK.Models.Service.BIStatsWay
+{
+    public static class SchoolStatsWay
+    {
+
+        /// <summary>
+        /// 统计单个学校
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="scId"></param>
+        /// <returns></returns>
+        public static async Task<StatsInfo> GetSingleSc(CosmosClient cosmosClient, string scId)
+        {
+            StatsInfo statsInfo = new() { id = $"{scId}" };
+
+            DateTimeOffset dateTime = DateTimeOffset.UtcNow;
+            var (dayS, dayE) = TimeHelper.GetStartOrEnd(dateTime);  //今天开始时间    13位
+            var (lastWeekS, lastWeekE) = TimeHelper.GetStartOrEnd(dateTime, "lastweek");   //计算上周开始/结束时间
+            var (weekS, weekE) = TimeHelper.GetStartOrEnd(dateTime, "week");             //计算本周开始/结束时间
+
+            var (lastTermS, lastTermE) = TimeHelper.GetStartOrEnd(dateTime, "lastterm");   //计算上学期开始/结束时间
+            var (termS, termE) = TimeHelper.GetStartOrEnd(dateTime, "term");   //计算本学期开始/结束时间
+
+            var (lastMthS, LastmthE) = TimeHelper.GetStartOrEnd(dateTime, "lastMonth");  //上月开始/结束时间
+            var (mthS, mthE) = TimeHelper.GetStartOrEnd(dateTime, "month");  //本月开始/结束时间
+
+            var (lastYearS, lastYearE) = TimeHelper.GetStartOrEnd(DateTimeOffset.Parse($"{dateTime.Year - 1}-1-1"), "year"); //计算去年开始/结束时间
+            var (yearS, yearE) = TimeHelper.GetStartOrEnd(dateTime, "year");         //计算今年开始/结束时间
+
+            string currSql = "select value(count(c.id)) from c";
+            string dayWhereSql = $"c.createTime >= {dayS} and c.createTime <= {dayE}";
+            string weekWhereSql = $"c.createTime >= {weekS} and c.createTime <= {weekE}";
+            string monthWhereSql = $"c.createTime >= {mthS} and c.createTime <= {mthE}";
+
+            ScBase scBase = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<ScBase>(statsInfo.id, new PartitionKey("Base"));
+            statsInfo.name = scBase.name;
+            statsInfo.picture = scBase.picture;
+            statsInfo.size = scBase.size;
+            statsInfo.scCreateTime = scBase.createTime;
+
+            string tchSql = $"{currSql} where ARRAY_CONTAINS(c.roles, 'teacher', true) AND c.status = 'join'";
+            statsInfo.tch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", tchSql, code: $"Teacher-{scBase.id}");
+            statsInfo.dayTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and {dayWhereSql} ", code: $"Teacher-{scBase.id}");
+            statsInfo.weekTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and  {weekWhereSql}", code: $"Teacher-{scBase.id}");
+            statsInfo.monthTch = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{tchSql} and  {monthWhereSql}", code: $"Teacher-{scBase.id}");
+
+            statsInfo.stu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", currSql, code: $"Base-{scBase.id}");
+            statsInfo.dayStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {dayWhereSql}", code: $"Base-{scBase.id}");
+            statsInfo.weekStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {weekWhereSql}", code: $"Base-{scBase.id}");
+            statsInfo.monthStu = await JointlySingleQuery.GetValueInt(cosmosClient, "Student", $"{currSql} where {monthWhereSql}", code: $"Base-{scBase.id}");
+
+            statsInfo.room = await JointlySingleQuery.GetValueInt(cosmosClient, "School", currSql, code: $"Room-{scBase.id}");
+            statsInfo.witRoom = await JointlySingleQuery.GetValueInt(cosmosClient, "School", $"{currSql} where (c.serial != null or c.serial != '' or IS_DEFINED(c.serial) = true)", code: $"Room-{scBase.id}");
+
+            statsInfo.lesson = await LessonRecordStatsWay.GetSchoolAll(cosmosClient, statsInfo.id);
+            statsInfo.activity = await ActivityStatsWay.GetSchoolAll(cosmosClient, statsInfo.id);
+            statsInfo.study = await StudyStatsWay.GetSchoolAll(cosmosClient, statsInfo.id);
+
+            return statsInfo;
+        }
+
+
+        /// <summary>
+        /// 多个学校统计
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="statsInfos"></param>
+        /// <param name="_httpTrigger"></param>
+        /// <param name="_option"></param>
+        /// <param name="area"></param>
+        /// <returns></returns>
+        public static async Task<StatsInfo> GetAreaStats(CosmosClient cosmosClient, HttpTrigger _httpTrigger, Option _option, List<StatsInfo> statsInfos, List<string> scIds = null, Area area = null) 
+        {
+            StatsInfo areaInfo = new()
+            {
+                id = area == null ? "" : area.id,
+                pk = "Stats",
+                code = "Stats",
+                name = area == null ? "" : area.name,
+                picture = "",
+                tch = statsInfos.Select(s => s.tch).Sum(),
+                dayTch = statsInfos.Select(s => s.dayTch).Sum(),
+                weekTch = statsInfos.Select(s => s.weekTch).Sum(),
+                monthTch = statsInfos.Select(s => s.monthTch).Sum(),
+                stu = statsInfos.Select(s => s.stu).Sum(),
+                dayStu = statsInfos.Select(s => s.dayStu).Sum(),
+                weekStu = statsInfos.Select(s => s.weekStu).Sum(),
+                monthStu = statsInfos.Select(s => s.monthStu).Sum(),
+                room = statsInfos.Select(s => s.room).Sum(),
+                witRoom = statsInfos.Select(s => s.witRoom).Sum(),
+                size = statsInfos.Select(s => s.size).Sum()
+            };
+            areaInfo.lesson.open = statsInfos.Select(s => s.lesson.open).Sum();
+            areaInfo.lesson.less = statsInfos.Select(s => s.lesson.less).Sum();
+            areaInfo.lesson.lastDay = statsInfos.Select(s => s.lesson.lastDay).Sum();
+            areaInfo.lesson.day = statsInfos.Select(s => s.lesson.day).Sum();
+            areaInfo.lesson.lastWeek = statsInfos.Select(s => s.lesson.lastWeek).Sum();
+            areaInfo.lesson.week = statsInfos.Select(s => s.lesson.week).Sum();
+            areaInfo.lesson.lastTerm = statsInfos.Select(s => s.lesson.lastTerm).Sum();
+            areaInfo.lesson.term = statsInfos.Select(s => s.lesson.term).Sum();
+            areaInfo.lesson.lastDayInter = statsInfos.Select(s => s.lesson.lastDayInter).Sum();
+            areaInfo.lesson.dayInter = statsInfos.Select(s => s.lesson.dayInter).Sum();
+            areaInfo.lesson.lastMonthInter = statsInfos.Select(s => s.lesson.lastMonthInter).Sum();
+            areaInfo.lesson.monthInter = statsInfos.Select(s => s.lesson.monthInter).Sum();
+            areaInfo.lesson.lastYearInter = statsInfos.Select(s => s.lesson.lastYearInter).Sum();
+            areaInfo.lesson.yearInter = statsInfos.Select(s => s.lesson.yearInter).Sum();
+
+            areaInfo.activity.cnt = statsInfos.Select(s => s.activity.cnt).Sum();
+            areaInfo.activity.exam = statsInfos.Select(s => s.activity.exam).Sum();
+            areaInfo.activity.survey = statsInfos.Select(s => s.activity.survey).Sum();
+            areaInfo.activity.vote = statsInfos.Select(s => s.activity.vote).Sum();
+            areaInfo.activity.homework = statsInfos.Select(s => s.activity.homework).Sum();
+            areaInfo.activity.lastDay = statsInfos.Select(s => s.activity.lastDay).Sum();
+            areaInfo.activity.dayCnt = statsInfos.Select(s => s.activity.dayCnt).Sum();
+            areaInfo.activity.lastWeek = statsInfos.Select(s => s.activity.lastWeek).Sum();
+            areaInfo.activity.week = statsInfos.Select(s => s.activity.week).Sum();
+            areaInfo.activity.lastTerm = statsInfos.Select(s => s.activity.lastTerm).Sum();
+            areaInfo.activity.term = statsInfos.Select(s => s.activity.term).Sum();
+
+            List<Task<ItemResponse<StatsInfo>>> taskStatsInfos = new();
+
+            foreach (var itemId in scIds)
+            {
+                bool isExist = true;
+                StatsInfo statsInfo = new();
+                var scDataStats = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{itemId}", new PartitionKey("Stats"));
+                if (scDataStats.Status == 200)
+                {
+                    using var fileJson = await JsonDocument.ParseAsync(scDataStats.ContentStream);
+                    statsInfo = fileJson.ToObject<StatsInfo>();
+                }
+                else
+                {
+                    statsInfo.id = itemId;
+                    isExist = false;
+                }
+
+                bool isnew = false;
+                DateTimeOffset dateTime = DateTimeOffset.UtcNow;
+                long now = dateTime.ToUnixTimeMilliseconds();
+
+                if (statsInfo.upTime > 0 && !isnew)
+                {
+                    long timedis = 20 * 60 * 1000;//20分钟
+                    if (now - statsInfo.upTime < timedis)
+                        isnew = true;
+                }
+                if (statsInfo.upTime == 0 && isnew)
+                    statsInfo.upTime = now;
+                if (statsInfo.upTime == 0 && isnew)
+                    statsInfo.upTime = DateTimeOffset.UtcNow.Add(new TimeSpan(-1, 0, 0, 0)).ToUnixTimeMilliseconds();
+                if (!isnew)
+                {
+                    ////Function 处理Function 更新或者新增
+                    //_ = _httpTrigger.RequestHttpTrigger(new { schoolId = $"{itemId}"}, _option.Location, "stats-sc-info");
+
+                    //异步方法处理 同步更新
+                    statsInfo = await SchoolStatsWay.GetSingleSc(cosmosClient, itemId);
+
+                    statsInfo.upTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                    if (isExist)
+                        taskStatsInfos.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<StatsInfo>(statsInfo, statsInfo.id, new PartitionKey("Stats")));
+                    else
+                        taskStatsInfos.Add(cosmosClient.GetContainer(Constant.TEAMModelOS, "School").CreateItemAsync<StatsInfo>(statsInfo, new PartitionKey("Stats")));
+                }
+            }
+
+            if (taskStatsInfos.Count < 256)
+                await Task.WhenAll(taskStatsInfos);
+            else 
+            {
+                int pages = (taskStatsInfos.Count + 256) / 256;
+                for (int i = 0; i < pages; i++)
+                {
+                    List<Task<ItemResponse<StatsInfo>>> tempStatsInfos = taskStatsInfos.Skip((i) * 256).Take(256).ToList();
+                    await Task.WhenAll(tempStatsInfos);
+                }
+            }
+
+            return areaInfo;
+        }
+    }
+}

+ 81 - 0
TEAMModelOS.SDK/Models/Service/BIStatsWay/StudyStatsWay.cs

@@ -0,0 +1,81 @@
+using Azure.Cosmos;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Text.Json;
+using System.Threading.Tasks;
+using TEAMModelOS.SDK.Extension;
+using TEAMModelOS.SDK.Models.Cosmos.BI;
+
+namespace TEAMModelOS.SDK.Models.Service.BIStatsWay
+{
+
+    public static class StudyStatsWay
+    {
+        /// <summary>
+        /// 学校研修统计
+        /// </summary>
+        /// <param name="cosmosClient"></param>
+        /// <param name="scId"></param>
+        /// <returns></returns>
+        public static async Task<StudyStats> GetSchoolAll(CosmosClient cosmosClient, string scId)
+        {
+            StudyStats studyStats = new();
+            List<AreaStudy> trains = new();
+
+            School school = await cosmosClient.GetContainer("TEAMModelOS", "School").ReadItemAsync<School>($"{scId}", new PartitionKey("Base"));
+            //cosmosClient.GetContainer("TEAMModelOS", "School").GetItemQueryIterator<string>(queryText:$"select value(c.areaId) from c where c.id='{scId}'", requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")});
+
+            AreaSetting setting = null;
+            var responSett = await cosmosClient.GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync($"{school.areaId}", new PartitionKey("AreaSetting"));
+            if (responSett.Status == 200)
+            {
+                using var fileJson = await JsonDocument.ParseAsync(responSett.ContentStream);
+                setting = fileJson.ToObject<AreaSetting>();
+
+            }
+            if (setting == null)
+            {
+                setting = new AreaSetting
+                {
+                    allTime = 50,
+                    classTime = 5,
+                    submitTime = 15,
+                    onlineTime = 20,
+                    offlineTime = 10,
+                    lessonMinutes = 45,
+                };
+            }
+
+            await foreach (var item in cosmosClient.GetContainer("TEAMModelOS", "Teacher").GetItemQueryIterator<AreaStudy>(queryText: $"select c.id,c.code,c.totalTime,c.onlineTime,c.offlineTime,c.classTime,c.currency from c where c.pk='TeacherTrain' and c.school='{scId}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"TeacherTrain-{scId}") }))
+            {
+                trains.Add(item);
+            }
+
+            studyStats.learnTime = trains.Select(s=>s.totalTime).Sum();
+            trains.ForEach(x =>
+            {
+                //线上研修
+                if (x.onlineTime == 0) studyStats.online++; else if (x.onlineTime >= setting.onlineTime) studyStats.online++; else studyStats.online++;
+
+                //线下研修
+                if (x.offlineTime == 0) studyStats.offline++; else if (x.onlineTime >= setting.offlineTime) studyStats.offline++; else studyStats.offline++;
+
+                //课堂实录
+                if (x.classTime == 0) studyStats.classRoom++; else if (x.classTime >= setting.classTime) studyStats.classRoom++; else studyStats.classRoom++;
+
+                //认证材料
+                if (x.currency.submitTime == 0) studyStats.submit++; else if (x.currency.submitTime >= setting.submitTime) studyStats.submit++; else studyStats.submit++;
+
+                if (x.currency.submitTime == 0 && x.classTime == 0 && x.offlineTime == 0 && x.onlineTime == 0) studyStats.notStarted++;
+                else if (x.currency.submitTime >= setting.submitTime && x.classTime >= setting.classTime && x.onlineTime >= setting.offlineTime && x.onlineTime >= setting.onlineTime) studyStats.finish++;
+                else studyStats.ongoing++;
+            });
+
+
+
+            return studyStats;
+        }
+    }
+}

+ 3 - 3
TEAMModelOS.SDK/Models/Service/Third/ThirdService.cs

@@ -226,7 +226,7 @@ namespace TEAMModelOS.SDK.Models
                 return (setting.accessConfig, area, setting);
             }
         }
-        public static async Task<List<Ability>> GetDiagnosisList(CosmosClient client, string standard, DingDing dingDing, AreaSetting setting, HttpTrigger httpTrigger, Teacher teacher, TEAMModelOS.Models.Option _option, AzureStorageFactory _azureStorage)
+        public static async Task<List<Ability>> GetDiagnosisList(CosmosClient client, string standard, DingDing dingDing, AreaSetting setting, ScsStudyApisService  _scsStudyApisService , Teacher teacher, TEAMModelOS.Models.Option _option, AzureStorageFactory _azureStorage)
         {
             List<string> abilityNos = new();
             var table = _azureStorage.GetCloudTableClient().GetTableReference("ScYxpt");
@@ -262,8 +262,8 @@ namespace TEAMModelOS.SDK.Models
                         dict = new Dictionary<string, object>() { { "accessConfig", setting.accessConfig }, { "pxid", pxid }, { "areaId", setting.id } };
                     }
 
-
-                    (int status, string json) = await httpTrigger.RequestHttpTrigger(dict, _option.Location, "GetDiagnosisListByProject_V2");
+                    (int status, string json) = await _scsStudyApisService.GetDiagnosisListByProject_V2(setting.id ,setting.accessConfig,pxid, teachers[0].schoolCode);
+                    //(int status, string json) = await httpTrigger.RequestHttpTrigger(dict, _option.Location, "GetDiagnosisListByProject_V2");
                     if (status == 200)
                     {
                         List<string> nos = json.ToObject<List<string>>();

+ 1 - 1
TEAMModelOS/ClientApp/public/lang/en-US.js

@@ -5203,7 +5203,7 @@ const LANG_EN_US = {
             status: 'Status',
             option: 'Option',
             answer: 'Answer',
-            no: 'No',
+            no: 'No.',
         },
         studentWeb: {
             description: 'Description',

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

@@ -528,7 +528,7 @@ export default {
             },
             {
               icon: 'iconfont icon-data-count',
-              name: '教研中心',
+              name: this.$t('system.menu.cusVideoMgt'),
               router: '/home/ResearchMgt',
               tag: '',
               role: 'admin',

+ 9 - 3
TEAMModelOS/ClientApp/src/components/student-web/EventView/EventContentTypeTemplate/PaperViewBox/LessonTestReport.vue

@@ -1034,11 +1034,17 @@
                 } else {
                     return this.getItemTitle.progress
                 } */
-                if(this.examInfo.taskStatus === 1) {
-                    return "finish"
-                } else {
+                // 艺术评测要求活动结束才能展示得分
+                if(this.getItemTitle.type === "Atr") {
                     return this.getItemTitle.progress
+                } else {
+                    if(this.examInfo.taskStatus === 1) {
+                        return "finish"
+                    } else {
+                        return this.getItemTitle.progress
+                    }
                 }
+                
             },
         },
         watch: {

+ 13 - 14
TEAMModelOS/ClientApp/src/view/dashboard/fiveEdu/FiveEdu.vue

@@ -119,7 +119,7 @@
                             <img class="img-crown" src="@/assets/dashboard/student/icon_crown.png" alt="" v-show="index === 0">
                             <img class="img-crown" src="@/assets/dashboard/student/icon_crown2.png" alt="" v-show="index === 1">
                             <img class="img-crown" src="@/assets/dashboard/student/icon_crown3.png" alt="" v-show="index === 2">
-                            <span>欧阳旭</span>
+                            <span>学生姓名{{ index + 1 }}</span>
                           </div>
                         </div>
                       </div>
@@ -247,16 +247,16 @@ export default {
         {
           label: '学生总数',
           color: '#7ec4ff',
-          val: 7944
+          val: 1944
         },
         {
           label: '年级数',
           color: '#7ec4ff',
-          val: 3
+          val: 4
         }, {
           label: '班级数',
           color: '#7ec4ff',
-          val: 44
+          val: 9
         },
         {
           label: '活动数',
@@ -279,11 +279,10 @@ export default {
       gradeRankConfig: {
         header: ['<span style="color:#32c5e9;font-weight: bold;">年级</span>', '<span style="color:#32c5e9;font-weight: bold;">最高分</span>', '<span style="color:#32c5e9;font-weight: bold;">最低分</span>', '<span style="color:#32c5e9;font-weight: bold;">综合平均分</span>'],
         data: [
-          ['一年级', '84.3 分', '84.3 分', '84.3 分'],
-          ['二年级', '82.6 分', '84.3 分', '84.3 分'],
-          ['三年级', '76.0 分', '84.3 分', '84.3 分'],
-          ['四年级', '74.1 分', '84.3 分', '84.3 分'],
-          ['五年级', '65.8 分', '84.3 分', '84.3 分'],
+          ['大一年级', '84.3 分', '52.1 分', '74.3 分'],
+          ['大二年级', '82.6 分', '54.3 分', '72.3 分'],
+          ['大三年级', '76.0 分', '43.8 分', '68.1 分'],
+          ['大四年级', '74.1 分', '40.2 分', '61.8 分'],
         ],
         align: ['center'],
         rowNum: 5,
@@ -295,11 +294,11 @@ export default {
       classRankConfig: {
         header: ['<span style="color:#32c5e9;font-weight: bold;">班级</span>', '<span style="color:#32c5e9;font-weight: bold;">最高分</span>', '<span style="color:#32c5e9;font-weight: bold;">最低分</span>', '<span style="color:#32c5e9;font-weight: bold;">综合平均分</span>'],
         data: [
-          ['一年级1班', '84.3 分', '84.3 分', '84.3 分'],
-          ['一年级2班', '82.6 分', '84.3 分', '84.3 分'],
-          ['一年级3班', '76.0 分', '84.3 分', '84.3 分'],
-          ['一年级4班', '74.1 分', '84.3 分', '84.3 分'],
-          ['一年级5班', '65.8 分', '84.3 分', '84.3 分'],
+          ['大一年级1班', '84.3 分', '65.7 分', '74.8 分'],
+          ['大一年级2班', '82.6 分', '64.3 分', '72.3 分'],
+          ['大一年级3班', '76.0 分', '60.9 分', '69.9 分'],
+          ['大一年级4班', '74.1 分', '52.6 分', '65.3 分'],
+          ['大一年级5班', '65.8 分', '48.7 分', '56.8 分'],
         ],
         align: ['center'],
         rowNum: 5,

+ 8 - 8
TEAMModelOS/ClientApp/src/view/dashboard/moral/MoralDash.vue

@@ -121,7 +121,7 @@
                   <img class="img-crown" src="@/assets/dashboard/student/icon_crown.png" alt="" v-show="index === 0">
                   <img class="img-crown" src="@/assets/dashboard/student/icon_crown2.png" alt="" v-show="index === 1">
                   <img class="img-crown" src="@/assets/dashboard/student/icon_crown3.png" alt="" v-show="index === 2">
-                  <span style="margin-top:5px">学生姓名</span>
+                  <span style="margin-top:5px">学生姓名{{ index + 1 }}</span>
                 </div>
               </div>
             </div>
@@ -162,7 +162,7 @@ export default {
         {
           label: '学生总数',
           color: '#7ec4ff',
-          val: 7944
+          val: 1944
         },
         {
           label: '教师参与数',
@@ -183,12 +183,12 @@ export default {
       classRankConfig: {
         header: ['<span style="color:#32c5e9;font-weight: bold;">班级</span>', '<span style="color:#32c5e9;font-weight: bold;">德育总分</span>', '<span style="color:#32c5e9;font-weight: bold;">流动红旗(次)</span>', '<span style="color:#32c5e9;font-weight: bold;">星级班级(次)</span>'],
         data: [
-          ['年级1班', '84.3 分', '8', '5'],
-          ['年级2班', '82.6 分', '10', '5'],
-          ['年级3班', '76.0 分', '6', '3'],
-          ['年级4班', '74.1 分', '4', '1'],
-          ['年级5班', '64.3 分', '2', '0'],
-          ['年级6班', '54.3 分', '2', '0'],
+          ['大一年级1班', '84.3 分', '8', '5'],
+          ['大一年级2班', '82.6 分', '10', '5'],
+          ['大一年级3班', '76.0 分', '6', '3'],
+          ['大一年级4班', '74.1 分', '4', '1'],
+          ['大一年级5班', '64.3 分', '2', '0'],
+          ['大一年级6班', '54.3 分', '2', '0'],
         ],
         align: ['center', 'center', 'center', 'center', 'center'],
         rowNum: 6,

+ 16 - 16
TEAMModelOS/ClientApp/src/view/dashboard/study/StudyDash.vue

@@ -74,11 +74,11 @@
                         </span>
                         <img class="img-avatar" @click="goStudent()" src="https://paas-admin.xydqq.cn/img/avatar.647bbbfe.png" alt="" width="50">
                         <div class="stu-info">
-                          <p class="name">学生姓名</p>
-                          <p class="id">140015511001</p>
+                          <p class="name">学生姓名{{ rankStuIndex + 1 }}</p>
+                          <p class="id">{{ 140015511001 + rankStuIndex }}</p>
                         </div>
                         <span class="rank-score">
-                          <span>87.63</span>
+                          <span>{{ (87.63 - 5.2 * rankStuIndex).toFixed(2) }}</span>
                           <span style="font-size:12px;display:inline-block;color:#ccc">平均分</span>
                         </span>
                       </dv-border-box-7>
@@ -147,7 +147,7 @@ export default {
         {
           label: '学生总数',
           color: '#7ec4ff',
-          val: 7944
+          val: 1944
         },
         {
           label: '评测总数',
@@ -178,18 +178,18 @@ export default {
       classRankConfig: {
         header: ['<span style="color:#32c5e9;font-weight: bold;">班级</span>', '<span style="color:#32c5e9;font-weight: bold;">最高分</span>', '<span style="color:#32c5e9;font-weight: bold;">最低分</span>', '<span style="color:#32c5e9;font-weight: bold;">综合平均分</span>'],
         data: [
-          ['年级1班', '84.3 分', '84.3 分', '84.3 分'],
-          ['年级2班', '82.6 分', '84.3 分', '84.3 分'],
-          ['年级3班', '76.0 分', '84.3 分', '84.3 分'],
-          ['年级4班', '74.1 分', '84.3 分', '84.3 分'],
-          ['年级5班', '65.8 分', '84.3 分', '84.3 分'],
-          ['年级6班', '64.3 分', '84.3 分', '84.3 分'],
-          ['五年级1班', '84.3 分', '84.3 分', '84.3 分'],
-          ['五年级2班', '82.6 分', '84.3 分', '84.3 分'],
-          ['五年级3班', '76.0 分', '84.3 分', '84.3 分'],
-          ['五年级4班', '74.1 分', '84.3 分', '84.3 分'],
-          ['五年级5班', '65.8 分', '84.3 分', '84.3 分'],
-          ['五年级6班', '64.3 分', '84.3 分', '84.3 分'],
+          ['大一年级1班', '84.3 分', '84.3 分', '84.3 分'],
+          ['大一年级2班', '82.6 分', '84.3 分', '84.3 分'],
+          ['大一年级3班', '76.0 分', '84.3 分', '84.3 分'],
+          ['大一年级4班', '74.1 分', '84.3 分', '84.3 分'],
+          ['大一年级5班', '65.8 分', '84.3 分', '84.3 分'],
+          ['大一年级6班', '64.3 分', '84.3 分', '84.3 分'],
+          ['大一年级7班', '84.3 分', '84.3 分', '84.3 分'],
+          ['大一年级8班', '82.6 分', '84.3 分', '84.3 分'],
+          ['大一年级9班', '76.0 分', '84.3 分', '84.3 分'],
+          ['大一年级10班', '74.1 分', '84.3 分', '84.3 分'],
+          ['大一年级11班', '65.8 分', '84.3 分', '84.3 分'],
+          ['大一年级12班', '64.3 分', '84.3 分', '84.3 分'],
         ],
         align: ['center'],
         rowNum: 12,

+ 1 - 0
TEAMModelOS/ClientApp/src/view/research-center/ResearchMgt.less

@@ -8,6 +8,7 @@
 		background-color: #ffffff;
 		align-items: center;
 		padding: 20px 25px;
+		padding-top: 40px;
 
 		.split-line {
 			width: 2px;

+ 1 - 2
TEAMModelOS/Controllers/Both/GroupListController.cs

@@ -186,8 +186,7 @@ namespace TEAMModelOS.Controllers
                     {
                         idNameCodes.Add(item);
                     }
-                    _coreAPIHttpService.PushNotify(idNameCodes, $"scan-join_groupList", Constant.NotifyType_IES5_Course,
-                              new Dictionary<string, object> { { "tmdid", id }, { "tmdname", name }, { "groupListName", data.stuList.name }, { "groupListId", data.stuList.id } }, _option.Location, _configuration, _dingDing, _environment.ContentRootPath);
+                  //  _coreAPIHttpService.PushNotify(idNameCodes, $"scan-join_groupList", Constant.NotifyType_IES5_Course,   new Dictionary<string, object> { { "tmdid", id }, { "tmdname", name }, { "groupListName", data.stuList.name }, { "groupListId", data.stuList.id } }, _option.Location, _configuration, _dingDing, _environment.ContentRootPath);
                 }
                 return Ok(new { data.stuList, data.status });
             }

+ 3 - 0
TEAMModelOS/Controllers/Common/CommonController.cs

@@ -98,6 +98,9 @@ namespace TEAMModelOS.Controllers.Common
                             {
                                 foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
                                 {
+                               
+                                    
+                                    
                                     if (countall.ContainsKey(key.ToLower()))
                                     {
                                         countall[key.ToLower()] = countall[key.ToLower()] + obj.GetProperty("countprivate").GetInt32();

+ 7 - 3
TEAMModelOS/Controllers/Normal/AbilityController.cs

@@ -32,7 +32,8 @@ namespace TEAMModelOS.Controllers
         private readonly Option _option;
         private readonly HttpTrigger _httpTrigger;
         private readonly AzureStorageFactory _azureStorage;
-        public AbilityController(AzureStorageFactory azureStorage,HttpTrigger httpTrigger, AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option)
+        private readonly ScsStudyApisService _scsStudyApisService;
+        public AbilityController(ScsStudyApisService scsStudyApisService, AzureStorageFactory azureStorage,HttpTrigger httpTrigger, AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option)
         {
             _azureStorage= azureStorage;
             _azureCosmos = azureCosmos;
@@ -40,6 +41,7 @@ namespace TEAMModelOS.Controllers
             _dingDing = dingDing;
             _option = option?.Value;
             _httpTrigger = httpTrigger;
+            _scsStudyApisService = scsStudyApisService;
         }
         /*
            {"abilityId":"册别id:0baf00db-0768-4b62-a8f7-280f6bcebf71","scope":"school","abilityCode":"册别分区键"}
@@ -214,7 +216,8 @@ namespace TEAMModelOS.Controllers
                         List<ScSchool> schools = await table.FindListByDict<ScSchool>(new Dictionary<string, object>() { { "PartitionKey", "ScSchool" }, { "schoolCode", $"{_code}" } });
                         if (schools.IsNotEmpty()) {
                             Dictionary<string, object> dict = new() { { "accessConfig", accessConfig },{ "schoolCode",$"{schools[0].schoolid}"}, { "areaId", setting.id } };
-                            (int status, string json) = await _httpTrigger.RequestHttpTrigger(dict, _option.Location, "GetSchoolDiagnosis");
+                            //(int status, string json) = await _httpTrigger.RequestHttpTrigger(dict, _option.Location, "GetSchoolDiagnosis");
+                            (int status, string json) = await _scsStudyApisService.GetSchoolDiagnosis(setting.id, accessConfig,$"{schools[0].schoolid}");
                             if (status == 200)
                             {
                                 List<ScsProjectDiagnosis> projectDiagnoses = json.ToObject<List<ScsProjectDiagnosis>>(new JsonSerializerOptions { PropertyNameCaseInsensitive = false });
@@ -242,7 +245,8 @@ namespace TEAMModelOS.Controllers
                     }
                     else {
                         Dictionary<string, object> dict = new Dictionary<string, object> { { "accessConfig", accessConfig }, { "areaId", setting.id } };
-                        (int status, string json) = await _httpTrigger.RequestHttpTrigger(dict, _option.Location, "GetProjectDiagnosis");
+                      //  (int status, string json) = await _httpTrigger.RequestHttpTrigger(dict, _option.Location, "GetProjectDiagnosis");
+                        (int status, string json) = await _scsStudyApisService.GetProjectDiagnosis(setting.id, accessConfig);
                         if (status == 200)
                         {
                             List<ScsProjectDiagnosis> projectDiagnoses = json.ToObject<List<ScsProjectDiagnosis>>(new JsonSerializerOptions { PropertyNameCaseInsensitive = false });

+ 4 - 2
TEAMModelOS/Controllers/Normal/AbilitySubController.cs

@@ -40,8 +40,9 @@ namespace TEAMModelOS.Controllers
         private readonly AzureServiceBusFactory _serviceBus;
         private readonly AzureStorageFactory _azureStorage;
         private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly ScsStudyApisService _scsStudyApisService;
         public IConfiguration _configuration { get; set; }
-        public AbilitySubController(CoreAPIHttpService coreAPIHttpService, AzureStorageFactory azureStorage,AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, ThirdApisService thirdApisService, HttpTrigger httpTrigge, AzureServiceBusFactory serviceBus, IConfiguration configuration)
+        public AbilitySubController(ScsStudyApisService scsStudyApisService, CoreAPIHttpService coreAPIHttpService, AzureStorageFactory azureStorage,AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, ThirdApisService thirdApisService, HttpTrigger httpTrigge, AzureServiceBusFactory serviceBus, IConfiguration configuration)
         {
             _azureCosmos = azureCosmos;
             _snowflakeId = snowflakeId;
@@ -53,6 +54,7 @@ namespace TEAMModelOS.Controllers
             _configuration = configuration;
             _azureStorage = azureStorage;
             _coreAPIHttpService = coreAPIHttpService;
+            _scsStudyApisService = scsStudyApisService;
         }
        
         /// <summary>
@@ -209,7 +211,7 @@ namespace TEAMModelOS.Controllers
                     Teacher teacher = await _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Teacher").ReadItemAsync<Teacher>(id, new PartitionKey("Base"));
                     
                     
-                    var abilitys = await ThirdService.GetDiagnosisList(client, $"{standard}", _dingDing, setting, _httpTrigger, teacher, _option,_azureStorage);
+                    var abilitys = await ThirdService.GetDiagnosisList(client, $"{standard}", _dingDing, setting, _scsStudyApisService, teacher, _option,_azureStorage);
                     if (abilitys != null)
                     {
                         abilitys.ForEach(x => { x.currency = 1; });

+ 26 - 6
TEAMModelOS/Controllers/School/SchoolController.cs

@@ -28,6 +28,9 @@ using HTEXLib.COMM.Helpers;
 using System.IdentityModel.Tokens.Jwt;
 using TEAMModelOS.SDK.DI.CoreAPI;
 using Microsoft.AspNetCore.Hosting;
+using DocumentFormat.OpenXml.Office2010.Excel;
+using static TEAMModelOS.SDK.SchoolService;
+using System.Xml;
 
 namespace TEAMModelOS.Controllers
 {
@@ -1425,10 +1428,22 @@ namespace TEAMModelOS.Controllers
                         }
                         foreach (var obj in teachers)
                         {
-                            SchoolTeacher teacher = teachersInschool.Where(t => t.id == obj.id).FirstOrDefault<SchoolTeacher>();
-                            int orgTeacherSize = teacher.size;
-                            teacher.size = obj.size;
-                            await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(teacher, obj.id, new PartitionKey($"Teacher-{school_code}"));
+                            SchoolTeacher teacher = teachersInschool.Where(t =>!string.IsNullOrWhiteSpace(t.id) && !string.IsNullOrWhiteSpace(obj.id) &&  t.id == obj.id).FirstOrDefault<SchoolTeacher>();
+                            if (teacher != null) {
+                                int orgTeacherSize = teacher.size;
+
+                                if (teacher.size != obj.size) {
+                                    int bsize=teacher.size;
+                                    int asize = obj.size;
+                                    teacher.size = obj.size;
+                                    List<IdNameCode> nameCodes = new List<IdNameCode> { new IdNameCode { id = obj.id, name = obj.name, code = obj.lang } };
+                                    var schoolData = obj.schools.Find(z => z.schoolId.Equals($"{school_code}"));
+                                    _coreAPIHttpService.PushNotify(nameCodes, "teacher_space-change", Constant.NotifyType_IES5_Management,
+                                    new Dictionary<string, object> { { "tmdname", teacher.name }, { "tmdid", teacher.id }, { "schoolName", schoolData.name },{ "bsize", bsize }, { "asize", asize } }
+                                      , _option.Location, _configuration, _dingDing, "");
+                                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(teacher, obj.id, new PartitionKey($"Teacher-{school_code}"));
+                                }
+                            }
                         }
                         return Ok(new { status, err, errTeachers });
                     case "retract": // 收回教師空間
@@ -1460,10 +1475,10 @@ namespace TEAMModelOS.Controllers
                                     var response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.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>();
+                                         Teacher teacherHimself = json.ToObject<Teacher>();
                                         // teacherHimself.size -= teacherSizeInSchool;
 
                                         // 最後一起修改
@@ -1473,6 +1488,11 @@ namespace TEAMModelOS.Controllers
                                         //,并在教师登陆的时候 一并计算个人空间和总空间大小。其中总空间大小包含(个人空间+多个学校累加的空间大小,并且如果退出或者被移除Teacher-Base 的"schools": [],为空,则已经实现自动回收)
                                         await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(teacher, teacher.id, new PartitionKey($"Teacher-{school_code}"));
                                         //await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacherHimself, teacherHimself.id, new PartitionKey("Base"));
+                                        List<IdNameCode> nameCodes = new List<IdNameCode> { new IdNameCode { id = teacherHimself.id, name = teacherHimself.name, code = teacherHimself.lang } };
+                                        var schoolData = teacherHimself.schools.Find(z => z.schoolId.Equals($"{school_code}"));
+                                        _coreAPIHttpService.PushNotify(nameCodes, "teacher_space-retract", Constant.NotifyType_IES5_Management,
+                                        new Dictionary<string, object> { { "tmdname", teacher.name }, { "tmdid", teacher.id }, { "schoolName", schoolData.name } }
+                                          , _option.Location, _configuration, _dingDing, "");
                                     }
                                     else
                                     {

+ 49 - 0
TEAMModelOS/Controllers/School/SchoolTeacherController.cs

@@ -27,6 +27,7 @@ using static TEAMModelOS.Controllers.FixDataController;
 using Microsoft.Extensions.Hosting;
 using Microsoft.AspNetCore.Hosting;
 using DocumentFormat.OpenXml.Office2010.Excel;
+using TEAMModelOS.SDK.Models.Dtos;
 
 namespace TEAMModelOS.Controllers
 {
@@ -47,6 +48,8 @@ namespace TEAMModelOS.Controllers
         private readonly CoreAPIHttpService _coreAPIHttpService;
         private readonly IWebHostEnvironment _environment;
         private readonly DingDing _dingDing;
+
+        
         public SchoolTeacherController(IWebHostEnvironment  environment,DingDing dingDing, CoreAPIHttpService coreAPIHttpService, AzureServiceBusFactory azureServiceBus, AzureCosmosFactory azureCosmos, AzureStorageFactory azureStorage, IOptionsSnapshot<Option> option, IConfiguration configuration, NotificationService notificationService)
         {
             _dingDing = dingDing;
@@ -474,6 +477,7 @@ namespace TEAMModelOS.Controllers
         {
             try
             {
+
                 var client = _azureCosmos.GetCosmosClient();
                 //參數取得
                 if (!request.TryGetProperty("school_code", out JsonElement school_code)) return BadRequest();
@@ -517,17 +521,24 @@ namespace TEAMModelOS.Controllers
                 foreach (var id in ids)
                 {
                     SchoolTeacher st = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<SchoolTeacher>(id, new PartitionKey($"Teacher-{school_code}"));
+                    Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemAsync<Teacher>(id, new PartitionKey($"Base"));
+                   var schoolData= teacher.schools.Find(z => z.schoolId.Equals($"{school_code}"));
+                    List<string> addAuthority = new List<string>();
+                    List<string> rmvAuthority = new List<string>();
                     if (permission.IsNotEmpty())
                     {
                         st.permissions = permission;
+                        addAuthority.AddRange(permission);
                     }
                     if (addPm.IsNotEmpty())
                     {
                         st.permissions.AddRange(addPm);
+                        addAuthority.AddRange(addPm);
                     }
                     if (rmvPm.IsNotEmpty())
                     {
                         st.permissions.RemoveAll(x => rmvPm.Contains(x));
+                        rmvAuthority.AddRange(rmvPm);
                     }
                     if (hasjob)
                     {
@@ -536,8 +547,46 @@ namespace TEAMModelOS.Controllers
                     //清除权限标记。
                     if (_pmClean.ValueKind.Equals(JsonValueKind.True)) {
                         st.permissions = new List<string>();
+                        rmvAuthority.AddRange(st.permissions);
+                    }
+                    List<IdNameCode> nameCodes = new List<IdNameCode> { new IdNameCode { id = teacher.id, name = teacher.name, code = teacher.lang } };
+                    string lang =_option.Location.Contains("China") ? "zh-cn" : "en-us";
+                    nameCodes.FindAll(x => string.IsNullOrWhiteSpace(x.code) || (!x.code.Equals("zh-cn") && !x.code.Equals("zh-tw") && !x.code.Equals("en-us"))).ForEach(x => { x.code = lang; });
+                    string path = Path.Combine("", $"Lang/{nameCodes.First().code}.json");
+                    var jsonAuth =System.IO. File.ReadAllText(path,Encoding.UTF8);
+                    var jsonData = jsonAuth.ToObject<JsonElement>();
+                    List<string> addText = new List<string>();
+                    List<string> rmvText = new List<string>();
+                    var authority =jsonData.GetProperty("authority");
+                    string none = nameCodes.First().code.Equals("zh-cn") ? "无" : nameCodes.First().code.Equals("zh-tw") ? "無" : "none";
+                    if (addAuthority.IsNotEmpty())
+                    {
+                        addAuthority.ForEach(z => {
+                            if (authority.TryGetProperty(z, out JsonElement text)) {
+                                addText.Add($"{text}");
+                            }
+                            
+                        });
+                    }
+                    else {
+                        addText.Add($"{none}");  
+                    }
+                    if (rmvAuthority.IsNotEmpty())
+                    {
+                        rmvAuthority.ForEach(z => {
+                            if (authority.TryGetProperty(z, out JsonElement text))
+                            {
+                                rmvText.Add($"{text}");
+                            }
+                        });
+                    }
+                    else {
+                        rmvText.Add($"{none}");
                     }
                     await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(st, id, new PartitionKey($"Teacher-{school_code}"));
+                    _coreAPIHttpService.PushNotify(nameCodes, "authority-change", Constant.NotifyType_IES5_Management,
+                      new Dictionary<string, object> { { "tmdname", teacher.name }, { "tmdid", teacher.id }, { "schoolName", schoolData.name }, { "addAuthority", $"[{string.Join(",", addText)}]" }, { "rmvAuthority", $"[{string.Join(",", rmvText)}]" } }
+                      , _option.Location, _configuration, _dingDing, "");
                     schoolTeachers.Add(st);
                 }
                 return Ok(new { teachers = schoolTeachers });

+ 5 - 1
TEAMModelOS/Controllers/Third/Sc/ScDataInitController.cs

@@ -54,6 +54,7 @@ namespace TEAMModelOS.Controllers.Third
         private readonly AzureServiceBusFactory _serviceBus;
         private readonly AzureRedisFactory _azureRedis;
         private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly ScsStudyApisService _scsStudyApisService;
         private readonly ThirdApisService _scsApisService;
         public readonly string type = "scsyxpt";
         private readonly HttpTrigger _httpTrigger;
@@ -61,7 +62,7 @@ namespace TEAMModelOS.Controllers.Third
         private readonly ThirdApisService _thirdApisService;
         public IConfiguration _configuration { get; set; }
         public ScDataInitController(ThirdApisService thirdApisService, IWebHostEnvironment environment, AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage,
-          AzureRedisFactory azureRedis, AzureServiceBusFactory serviceBus, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService, ThirdApisService scsApisService, HttpTrigger httpTrigger)
+          AzureRedisFactory azureRedis, AzureServiceBusFactory serviceBus, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService, ScsStudyApisService scsStudyApis, ThirdApisService scsApisService, HttpTrigger httpTrigger)
         {
             _azureCosmos = azureCosmos;
             _snowflakeId = snowflakeId;
@@ -72,6 +73,7 @@ namespace TEAMModelOS.Controllers.Third
             _configuration = configuration;
             _azureRedis = azureRedis;
             _coreAPIHttpService = coreAPIHttpService;
+            _scsStudyApisService = scsStudyApis;
             _scsApisService = scsApisService;
             _httpTrigger = httpTrigger;
             _environment = environment;
@@ -610,6 +612,8 @@ namespace TEAMModelOS.Controllers.Third
             int status = -1; string json = null;
             //5.3.1.1获取项目列表
             (status, json) = await _httpTrigger.RequestHttpTrigger(dict, _option.Location, "GetProjectInfoByTrainComID");
+            //新的方式  5.3.1.1获取项目列表
+            //(status, json) = await _scsStudyApisService.GetProjectInfoByTrainComID($"{areaId}", $"{accessConfig}"); 
             List<ScProject> projects = null;
             List<ScSchool> saveschools = null;
             List<ScSchool> schools = null;

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

@@ -38,6 +38,7 @@ using DocumentFormat.OpenXml.Drawing.Diagrams;
 using TEAMModelOS.SDK.Models.Dtos;
 using DocumentFormat.OpenXml.Bibliography;
 using System.Formats.Asn1;
+using System.Xml.Linq;
 
 namespace TEAMModelOS.Controllers
 {
@@ -3448,6 +3449,65 @@ namespace TEAMModelOS.Controllers
             }
         }
 
+        /// <summary>
+        /// 学校id将大写转换小写 并新增学校相关数据信息;修改教师学校的id
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [HttpPost("fix-uppertolower")]
+        public async Task<IActionResult> RepairUpperToLower(JsonElement jsonElement) 
+        {
+            string large = "GXJCXX";
+            var cosmosClient = _azureCosmos.GetCosmosClient();
+
+            List<string> containe = new() { "School", "Student", "Teacher" };
+
+            List<dynamic> noFail = new();
+            foreach (var itemC in containe)
+            {
+                await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, itemC).GetItemQueryStreamIterator(queryText: $"select value(c) from c where (contains(c.code,'{large}') or contains(c.id,'{large}'))"))
+                {
+                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                    {
+                        foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            string oldId = obj.GetProperty("id").GetString();
+                            string oldCode = obj.GetProperty("code").GetString();
+                            var jsonElm = obj.ToJsonString().Replace(large, large.ToLower()).ToObject<JsonElement>();
+                            jsonElm.TryGetProperty("code", out JsonElement code);
+                            byte[] bytes = Encoding.UTF8.GetBytes(jsonElm.GetRawText());
+                            var memoryStream = new MemoryStream(bytes);
+                            var resp = await cosmosClient.GetContainer(Constant.TEAMModelOS, itemC).CreateItemStreamAsync(memoryStream, new PartitionKey($"{code}"));
+                            if (resp.Status != 201)
+                                noFail.Add(new { container = itemC, id = oldId, code = oldCode });
+                        }
+                    }
+                }
+            }
+
+            await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryStreamIterator(queryText: $"select value(c) from c join sc in c.schools where sc.schoolId='{large}'",requestOptions:new QueryRequestOptions() { PartitionKey = new PartitionKey("Base")}))
+            {
+                using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                {
+                    foreach (var obj in json.RootElement.GetProperty("Documents").EnumerateArray())
+                    {
+                        var jsonElm = obj.ToJsonString().Replace(large, large.ToLower()).ToObject<JsonElement>();
+                        jsonElm.TryGetProperty("id", out JsonElement id);
+                        jsonElm.TryGetProperty("code", out JsonElement code);
+                        byte[] bytes = Encoding.UTF8.GetBytes(jsonElm.GetRawText());
+                        var memoryStream = new MemoryStream(bytes);
+                        var resp = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemStreamAsync(memoryStream, $"{id}", new PartitionKey($"Base"));
+                        if(resp.Status != 200)
+                          noFail.Add(new { container = "Teacher", id = id, code = code });
+                    }
+                }
+            }
+
+            return Ok(new { state = 200, noFail });
+        }
+
         public record TrainingId 
         {
             public string oldId { get; set; }

+ 11 - 16
TEAMModelOS/Controllers/XTest/TestController.cs

@@ -71,23 +71,18 @@ namespace TEAMModelOS.Controllers
             _searcher = searcher;
         }
         [ProducesDefaultResponseType]
-        [HttpPost("get-studentId")]
-        public async Task<IActionResult> GetStudentId(JsonElement json) {
-            List<string> ids = new List<string>();
-
-            await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Student")
-                .GetItemQueryStreamIterator(queryText: "  SELECT distinct value c.studentId  FROM c where c.pk='OverallEducation' and c.schoolCode='ydzt'  ", requestOptions :new QueryRequestOptions { }))
-            {
-                using var djson = await JsonDocument.ParseAsync(item.ContentStream);
-                if (djson.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
-                {
-                    foreach (var obj in djson.RootElement.GetProperty("Documents").EnumerateArray())
-                    {
-                        ids.Add(obj.ToObject<string>());
-                    }
-                }
+        [HttpPost("sendmsg")]
+        public async Task<IActionResult> Sendmsg(JsonElement json) {
+
+            byte[] bytes = Encoding.UTF8.GetBytes(json.GetRawText());
+            var memoryStream = new MemoryStream(bytes);
+            Azure .Response  res= await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).CreateItemStreamAsync(memoryStream, new PartitionKey("Base12"));
+            if (res.Status==201) {
+                return Ok(201);
             }
-            return Ok(ids);
+            //var messageBlobPDF = new ServiceBusMessage(new { userType = "tmdid", bizType = "OfflineRecord" }.ToJsonString());
+            //await _serviceBus.GetServiceBusClient().SendMessageAsync("screenpdf", messageBlobPDF);
+            return Ok();
         }
 
 

+ 60 - 1
TEAMModelOS/Lang/en-us.json

@@ -17,6 +17,9 @@
   "submitanswer-private_homework": [ "Homework submission notice", "{tmdname} has submitted a homework({homeworkName})" ],
   "expire-school_lessonRecord": [ "Lesson record expiration notice", "Your lesson record, {lessonName}, on {schoolName} will expire at {expireTime}" ],
   "expire-private_lessonRecord": [ "Lesson record expiration notice", "Your lesson record, {lessonName} will expire at {expireTime}" ],
+  "authority-change": [ "Authority change notice", "Your authority in {schoolName} has changed, add authority: {addAuthority}, remove authority: {rmvAuthority}" ],
+  "teacher_space-change": [ "School space allocation change notice", "Your space size in {schoolName} has changed, original size: {bsize}, change to: {asize}" ],
+  "teacher_space-retract": [ "School space reclamation notice", "Your space in {schoolName} has been reclaimed by the administrator" ],
   "create-school": [ "Create schools in batches", "{tmdname}You successfully created schools in batch with Bi" ],
   "copy-file_area": [ "Batch copy file start", "{tmdname}您用BI创区成功开始复制区域文件" ],
   "art-template-comment1": "{studentName}同学,你在本次艺术评测活动中整体{level}。",
@@ -25,5 +28,61 @@
   "art-template-comment4": "你在本次考核中{pointHigh}等知识点取得很好的成绩,希望继续保持。",
   "art-template-comment5": "你在本次考核中{pointLow}等知识有待提高,希望进一步加强。",
   "art-template-subject_music": "其实音乐殿堂的门槛并没有你想的那么高,对吧?希望你继续努力能够在这里欣赏到更美丽的风景!跳动的音符充满魅力,每个人的生活都离不开音乐,加油吧,相信你在音乐中会有所收获的。",
-  "art-template-subject_painting": "你敢于探素,乐于欣赏,在五彩的画笔中快乐成长,如果你再多一点耐心、仔细刻画,一定会更棒!你积极热爱美术,总是充满快乐,希望你能够坚持美术学习,永不放弃,在美术的道路上快乐地成长!"
+  "art-template-subject_painting": "你敢于探素,乐于欣赏,在五彩的画笔中快乐成长,如果你再多一点耐心、仔细刻画,一定会更棒!你积极热爱美术,总是充满快乐,希望你能够坚持美术学习,永不放弃,在美术的道路上快乐地成长!",
+  "authority": {
+    "classroom": "Classroom Settings",
+    "classroom-read": "View Classroom Information",
+    "classroom-upd": "Manage Classroom Settings",
+    "schoolSetting": "Basic Settings",
+    "schoolSetting-read": "View School Basic Settings",
+    "schoolSetting-upd": "Manage School Basic Settings",
+    "student": "Student Management",
+    "student-read": "View Student Account",
+    "student-upd": "Manage Student Account",
+    "teacher": "Teacher Management",
+    "teacher-read": "View Teacher Account",
+    "teacher-upd": "Manage Teacher Account(sub-Manager)",
+    "course": " Course Management",
+    "course-read": "View Course Setting Information",
+    "course-upd": "Manage Course Setting Information",
+    "newCoursePlan": "Course Scheduling Management",
+    "coursePlan-read": "View Course Scheduling Information",
+    "coursePlan-upd": "Manage Course Scheduling Information",
+    "serviceDriveAuth": "Authorization Management",
+    "auth-read": "View Authorization Management Information",
+    "auth-upd": "Manage Authorization Management Information",
+    "syllabus": "School Syllabus Management",
+    "syllabus-read": "View School Syllabus Information",
+    "syllabus-upd": "Manage School Syllabus Information",
+    "schoolContent": "School Content Management",
+    "content-read": "View School Content Information",
+    "content-upd": "Manage School Content Information",
+    "schoolBank": "School Question Bank Management ",
+    "exercise-read": "View School Question Bank Information",
+    "exercise-upd": "Manage School Question Bank Information",
+    "knowledge": "Key Concept Bank Management ",
+    "knowledge-read": "View Key Concept Bank Information",
+    "knowledge-upd": "Manage knowledge Key Concept Bank Information",
+    "analysis": "Learning Status Analysis",
+    "analysis-read": "View School Learning Status Analysis",
+    "scboard": "Statistical Data",
+    "scboard-read": "View Statistical Data",
+    "schoolAc": "School Activity",
+    "schoolAc-read": "View School Activity",
+    "schoolAc-upd": "Start School Activity",
+    "trainAll": "Study Center",
+    "train-read": "View Study Center Data",
+    "train-upd": "Manage Study Center Data",
+    "dashboard": "Data Board",
+    "dashboard-read": "View Data Board",
+    "research": "Lesson Management",
+    "research-read": "View Lesson Management",
+    "research-upd": "Manage Lesson Management",
+    "link": "Resource Platform",
+    "link-read": "View Resource Platform",
+    "link-upd": "Manage Resource Platform",
+    "art": "Art Assessment",
+    "art-read": "View Art Assessment",
+    "art-upd": "Manage Art Assessment"
+  }
 }

+ 60 - 1
TEAMModelOS/Lang/zh-cn.json

@@ -17,6 +17,9 @@
   "submitanswer-private_homework": [ "作业提交通知", "{tmdname}已提交作业,作业名称({homeworkName})" ],
   "expire-school_lessonRecord": [ "课例到期通知", "您在{schoolName}的课例将在{expireTime}到期,课例名称:{lessonName}" ],
   "expire-private_lessonRecord": [ "课例到期通知", "您的课例将在{expireTime}到期,课例名称:{lessonName}" ],
+  "authority-change": [ "权限变更通知", "您在{schoolName}的权限发生变更,增加权限:{addAuthority},移除权限:{rmvAuthority}" ],
+  "teacher_space-change": [ "学校空间分配变更通知", "您在{schoolName}的空间大小发生变更,变更前:{bsize},变更后:{asize}" ],
+  "teacher_space-retract": [ "学校空间回收通知", "您在{schoolName}的空间已被管理员回收" ],
   "create-school": [ "批量创建学校", "{tmdname}您用BI批量创建学校成功" ],
   "copy-file_area": [ "批复制文件开始", "{tmdname}您用BI创区成功开始复制区域文件" ],
   "art-template-comment1": "{studentName}同学,你在本次艺术评测活动中整体{level}。",
@@ -25,5 +28,61 @@
   "art-template-comment4": "你在本次考核中{pointHigh}等知识点取得很好的成绩,希望继续保持。",
   "art-template-comment5": "你在本次考核中{pointLow}等知识有待提高,希望进一步加强。",
   "art-template-subject_music": "其实音乐殿堂的门槛并没有你想的那么高,对吧?希望你继续努力能够在这里欣赏到更美丽的风景!跳动的音符充满魅力,每个人的生活都离不开音乐,加油吧,相信你在音乐中会有所收获的。",
-  "art-template-subject_painting": "你敢于探素,乐于欣赏,在五彩的画笔中快乐成长,如果你再多一点耐心、仔细刻画,一定会更棒!你积极热爱美术,总是充满快乐,希望你能够坚持美术学习,永不放弃,在美术的道路上快乐地成长!"
+  "art-template-subject_painting": "你敢于探素,乐于欣赏,在五彩的画笔中快乐成长,如果你再多一点耐心、仔细刻画,一定会更棒!你积极热爱美术,总是充满快乐,希望你能够坚持美术学习,永不放弃,在美术的道路上快乐地成长!",
+  "authority": {
+    "classroom": "教室管理",
+    "classroom-read": "检视教室资料",
+    "classroom-upd": "变更教室设定",
+    "schoolSetting": "基础设置",
+    "schoolSetting-read": "检视学校基础设定",
+    "schoolSetting-upd": "变更学校基础设定",
+    "student": "学生管理",
+    "student-read": "检视学生账号",
+    "student-upd": "变更学生账号",
+    "teacher": "教师管理",
+    "teacher-read": "检视教师账号",
+    "teacher-upd": "变更教师账号(子管理员)",
+    "course": "课程管理",
+    "course-read": "查看课程设置信息",
+    "course-upd": "修改课程设置信息",
+    "newCoursePlan": "排课管理",
+    "coursePlan-read": "查看排课信息",
+    "coursePlan-upd": "修改排课信息",
+    "serviceDriveAuth": "授权管理",
+    "auth-read": "查看授权管理信息",
+    "auth-upd": "修改授权管理信息",
+    "syllabus": "学校课纲管理",
+    "syllabus-read": "查看学校课纲信息",
+    "syllabus-upd": "修改学校课纲信息",
+    "schoolContent": "学校内容管理",
+    "content-read": "查看学校内容信息",
+    "content-upd": "修改学校内容信息",
+    "schoolBank": "学校题库管理",
+    "exercise-read": "查看学校题库信息",
+    "exercise-upd": "修改学校题库信息",
+    "knowledge": "知识点库管理",
+    "knowledge-read": "查看知识点库信息",
+    "knowledge-upd": "修改知识点库信息",
+    "analysis": "学情分析",
+    "analysis-read": "查看学校学情分析",
+    "scboard": "统计分析",
+    "scboard-read": "查看统计分析",
+    "schoolAc": "学校活动",
+    "schoolAc-read": "查看学校活动",
+    "schoolAc-upd": "发布学校活动",
+    "train": "研修中心",
+    "train-read": "查看研修中心数据",
+    "train-upd": "管理研修中心数据",
+    "dashboard": "数据看板",
+    "dashboard-read": "数据看板查看权限",
+    "research": "课例中心",
+    "research-read": "课例中心查看权限",
+    "research-upd": "课例中心管理(修改)权限",
+    "link": "资源平台",
+    "link-read": "查看资源平台",
+    "link-upd": "管理(修改)资源平台",
+    "art": "艺术评测",
+    "art-read": "艺术评测查看权限",
+    "art-upd": "艺术评测管理权限"
+  }
 }

+ 60 - 1
TEAMModelOS/Lang/zh-tw.json

@@ -17,6 +17,9 @@
   "submitanswer-private_homework": [ "作業提交通知", "{tmdname}已提交作業,作業名稱({homeworkName})" ],
   "expire-school_lessonRecord": [ "課例到期通知", "您在{schoolName}的課例將在{expireTime}到期,課例名稱:{lessonName}" ],
   "expire-private_lessonRecord": [ "課例到期通知", "您的課例將在{expireTime}到期,課例名稱:{lessonName}" ],
+  "authority-change": [ "權限變更通知", "您在{schoolName}的權限發生變更,增加權限:{addAuthority},移除權限:{rmvAuthority}" ],
+  "teacher_space-change": [ "學校空間分配變更通知", "您在{schoolName}的空間大小發生變更,變更前:{bsize},變更後:{asize}" ],
+  "teacher_space-retract": [ "學校空間回收通知", "您在{schoolName}的空間已被管理員回收" ],
   "create-school": [ "批量創建學校", "{tmdname}您用BI批量創建學校成功" ],
   "copy-file_area": [ "批復制文件開始", "{tmdname}您用BI创区成功开始复制区域文件" ],
   "art-template-comment1": "{studentName}同学,你在本次艺术评测活动中整体{level}。",
@@ -25,5 +28,61 @@
   "art-template-comment4": "你在本次考核中{pointHigh}等知识点取得很好的成绩,希望继续保持。",
   "art-template-comment5": "你在本次考核中{pointLow}等知识有待提高,希望进一步加强。",
   "art-template-subject_music": "其实音乐殿堂的门槛并没有你想的那么高,对吧?希望你继续努力能够在这里欣赏到更美丽的风景!跳动的音符充满魅力,每个人的生活都离不开音乐,加油吧,相信你在音乐中会有所收获的。",
-  "art-template-subject_painting": "你敢于探素,乐于欣赏,在五彩的画笔中快乐成长,如果你再多一点耐心、仔细刻画,一定会更棒!你积极热爱美术,总是充满快乐,希望你能够坚持美术学习,永不放弃,在美术的道路上快乐地成长!"
+  "art-template-subject_painting": "你敢于探素,乐于欣赏,在五彩的画笔中快乐成长,如果你再多一点耐心、仔细刻画,一定会更棒!你积极热爱美术,总是充满快乐,希望你能够坚持美术学习,永不放弃,在美术的道路上快乐地成长!",
+  "authority": {
+    "classroom": "教室管理",
+    "classroom-read": "檢視教室資料",
+    "classroom-upd": "變更教室設定",
+    "schoolSetting": "基礎設定",
+    "schoolSetting-read": "檢視學校基礎設定",
+    "schoolSetting-upd": "變更學校基礎設定",
+    "student": "學生管理",
+    "student-read": "檢視學生帳號",
+    "student-upd": "變更學生帳號",
+    "teacher": "教師管理",
+    "teacher-read": "檢視教師帳號",
+    "teacher-upd": "變更教師帳號(子管理員)",
+    "course": "課程管理",
+    "course-read": "查看課程設定資訊",
+    "course-upd": "修改課程設定資訊",
+    "newCoursePlan": "排課管理",
+    "coursePlan-read": "查看排課資訊",
+    "coursePlan-upd": "修改排課資訊",
+    "serviceDriveAuth": "授權管理",
+    "auth-read": "查看授權管理資訊",
+    "auth-upd": "修改授權管理資訊",
+    "syllabus": "學校課綱管理",
+    "syllabus-read": "查看學校課綱資訊",
+    "syllabus-upd": "修改學校課綱資訊",
+    "schoolContent": "學校內容管理",
+    "content-read": "查看學校內容資訊",
+    "content-upd": "修改學校內容資訊",
+    "schoolBank": "學校題庫管理",
+    "exercise-read": "查看學校題庫資訊",
+    "exercise-upd": "修改學校題庫資訊",
+    "knowledge": "知識點庫管理",
+    "knowledge-read": "查看知識點庫資訊",
+    "knowledge-upd": "修改知識點庫資訊",
+    "analysis": "學情分析",
+    "analysis-read": "查看學校學情分析",
+    "scboard": "統計數據",
+    "scboard-read": "查看統計數據",
+    "schoolAc": "學校活動",
+    "schoolAc-read": "查看學校活動",
+    "schoolAc-upd": "發布學校活動",
+    "train": "研習中心",
+    "train-read": "查看研習中心數據",
+    "train-upd": "管理研習中心數據",
+    "dashboard": "校園大數據",
+    "dashboard-read": "校園大數據查看權限",
+    "research": "課堂紀錄",
+    "research-read": "課堂紀錄查看權限",
+    "research-upd": "課堂紀錄管理(修改)權限",
+    "link": "資源平臺",
+    "link-read": "查看資源平臺",
+    "link-upd": "管理(修改)資源平臺",
+    "art": "藝術評量",
+    "art-read": "藝術評量查看權限",
+    "art-upd": "藝術評量管理權限"
+  }
 }

+ 1 - 0
TEAMModelOS/Startup.cs

@@ -111,6 +111,7 @@ namespace TEAMModelOS
             services.AddHttpClient<DingDing>();
             services.AddHttpClient<NotificationService>();
             services.AddCoreAPIHttpService(Configuration);
+            services.AddScsStudyApisService(Configuration);//
            // services.AddHttpClient<CoreAPIHttpService>();
             services.AddHttpClient<ThirdApisService>();
             services.AddHttpClient<HttpTrigger>();

+ 4 - 4
TEAMModelOS/TEAMModelOS.csproj

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