Browse Source

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

ruby 1 year ago
parent
commit
4c6b18080f
74 changed files with 3353 additions and 490 deletions
  1. 5 1
      TEAMModelBI/ClientApp/src/api/index.js
  2. 156 19
      TEAMModelBI/ClientApp/src/view/areaServe/areamanage.vue
  3. 32 26
      TEAMModelBI/ClientApp/src/view/created/created.vue
  4. 2 1
      TEAMModelBI/ClientApp/src/view/ddlogin.vue
  5. 38 28
      TEAMModelBI/ClientApp/src/view/participation/index.vue
  6. 64 46
      TEAMModelBI/ClientApp/src/view/participation/setPhase.vue
  7. 91 13
      TEAMModelBI/ClientApp/src/view/schoolServe/school.vue
  8. 1 1
      TEAMModelBI/ClientApp/src/view/schoolServe/setschool.vue
  9. 4 4
      TEAMModelBI/ClientApp/src/view/systemConfig/pushmsg/createdpush.vue
  10. 9 9
      TEAMModelBI/ClientApp/src/view/userInquire/details.vue
  11. 8 8
      TEAMModelBI/ClientApp/src/view/userInquire/hita.vue
  12. 8 8
      TEAMModelBI/ClientApp/src/view/userInquire/hiteach.vue
  13. 3 3
      TEAMModelBI/ClientApp/src/view/userInquire/ticket.vue
  14. 97 16
      TEAMModelBI/Controllers/BINormal/BatchAreaController.cs
  15. 29 16
      TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs
  16. 129 17
      TEAMModelBI/Controllers/BITmid/TmidController.cs
  17. 3 3
      TEAMModelBI/TEAMModelBI.csproj
  18. 4 4
      TEAMModelBI/appsettings.Development.json
  19. 89 28
      TEAMModelOS.FunctionV4/CosmosDB/TriggerArt.cs
  20. 8 1
      TEAMModelOS.FunctionV4/CosmosDB/TriggerExam.cs
  21. 3 3
      TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj
  22. 35 25
      TEAMModelOS.SDK/Context/Attributes/Filter/ApiTokenAttribute.cs
  23. 2 0
      TEAMModelOS.SDK/Models/Cosmos/BI/BISchool/BIRelation.cs
  24. 290 0
      TEAMModelOS.SDK/Models/Cosmos/Common/Activity.cs
  25. 0 40
      TEAMModelOS.SDK/Models/Cosmos/Common/ActivityRecord.cs
  26. 4 1
      TEAMModelOS.SDK/Models/Cosmos/Common/ArtEvaluation.cs
  27. 13 0
      TEAMModelOS.SDK/Models/Cosmos/Common/GroupList.cs
  28. 6 6
      TEAMModelOS.SDK/Models/Cosmos/Common/StudentScoreRecord.cs
  29. 4 1
      TEAMModelOS.SDK/Models/Cosmos/Normal/Area.cs
  30. 3 0
      TEAMModelOS.SDK/Models/Cosmos/Normal/TMDOrder.cs
  31. 3 2
      TEAMModelOS.SDK/Models/Cosmos/School/CourseBase.cs
  32. 5 1
      TEAMModelOS.SDK/Models/Cosmos/School/School.cs
  33. 63 0
      TEAMModelOS.SDK/Models/Cosmos/Student/ArtAttachment.cs
  34. 2 5
      TEAMModelOS.SDK/Models/Cosmos/Student/StudentArtResult.cs
  35. 6 13
      TEAMModelOS.SDK/Models/Dtos/LessonRecordActivityInfo.cs
  36. 1 1
      TEAMModelOS.SDK/Models/Service/BI/BIProdAnalysis.cs
  37. 1 0
      TEAMModelOS.SDK/Models/Service/BI/BIStats.cs
  38. 1 0
      TEAMModelOS.SDK/Models/Service/Common/TeacherService.cs
  39. 3 3
      TEAMModelOS.SDK/TEAMModelOS.SDK.csproj
  40. 5 2
      TEAMModelOS/ClientApp/public/lang/en-US.js
  41. 1 1
      TEAMModelOS/ClientApp/public/lang/zh-CN.js
  42. 5 2
      TEAMModelOS/ClientApp/public/lang/zh-TW.js
  43. 1 0
      TEAMModelOS/ClientApp/src/api/http.js
  44. 4 0
      TEAMModelOS/ClientApp/src/api/index.js
  45. 1 1
      TEAMModelOS/ClientApp/src/common/BaseLayout.vue
  46. 139 0
      TEAMModelOS/ClientApp/src/icons/svg/educloudtw.svg
  47. 5 0
      TEAMModelOS/ClientApp/src/router/routes.js
  48. 1 1
      TEAMModelOS/ClientApp/src/view/areaArtExam/WorkData.vue
  49. 7 0
      TEAMModelOS/ClientApp/src/view/artexam/Create.vue
  50. 7 1
      TEAMModelOS/ClientApp/src/view/artexam/Mgt.vue
  51. 2 2
      TEAMModelOS/ClientApp/src/view/artexam/WorkData.vue
  52. 13 9
      TEAMModelOS/ClientApp/src/view/coursemgt/NewCusMgt.vue
  53. 2 2
      TEAMModelOS/ClientApp/src/view/coursemgt/components/AddTask.vue
  54. 6 2
      TEAMModelOS/ClientApp/src/view/coursemgt/components/ImportTask.vue
  55. 5 0
      TEAMModelOS/ClientApp/src/view/login/page/Student.less
  56. 11 0
      TEAMModelOS/ClientApp/src/view/login/page/Student.vue
  57. 5 0
      TEAMModelOS/ClientApp/src/view/login/page/Teacher.less
  58. 8 0
      TEAMModelOS/ClientApp/src/view/login/page/Teacher.vue
  59. 6 3
      TEAMModelOS/ClientApp/src/view/settings/SchoolMgmt.vue
  60. 168 0
      TEAMModelOS/ClientApp/src/view/sso/TmdSSO.vue
  61. 1 1
      TEAMModelOS/ClientApp/src/view/student-web/AppNew.vue
  62. 2 1
      TEAMModelOS/ClientApp/src/view/teachcontent/index.vue
  63. 0 11
      TEAMModelOS/ClientApp/src/view/user/LepeiBindPhone.vue
  64. 130 38
      TEAMModelOS/Controllers/Analysis/ArtAnalysisController.cs
  65. 8 12
      TEAMModelOS/Controllers/Both/CourseBaseController.cs
  66. 874 2
      TEAMModelOS/Controllers/Client/AClassONEController.cs
  67. 81 0
      TEAMModelOS/Controllers/Common/ActivityController.cs
  68. 6 4
      TEAMModelOS/Controllers/Common/ArtController.cs
  69. 553 0
      TEAMModelOS/Controllers/OpenApi/Business/BizSSOController.cs
  70. 30 2
      TEAMModelOS/Controllers/System/WeChatPayController.cs
  71. 2 1
      TEAMModelOS/Controllers/Teacher/InitController.cs
  72. 4 4
      TEAMModelOS/TEAMModelOS.csproj
  73. 34 34
      TEAMModelOS/appsettings.Development.json
  74. 1 1
      TEAMModelOS/appsettings.json

+ 5 - 1
TEAMModelBI/ClientApp/src/api/index.js

@@ -85,6 +85,10 @@ export default {
     getSchoolcode(data) {
         return post('/batchschool/get-schoolcode', data)
     },
+    //修改学区简码 or 苏格拉底频道简码
+    updateAreacode(data){
+        return post('/batcharea/upd-area',data)
+    },
 
 
     //区域管理和微能力点管理
@@ -472,7 +476,7 @@ export default {
     },
     //端外通知 v2
     sendPushnotify(data) {
-        return post('https://api2.teammodel.net/service/PushNotify',data)
+        return post('https://api2.teammodel.net/service/PushNotify',data) 
      },
     //第三方相关API(BI)
     //创建or保存 第三方信息

+ 156 - 19
TEAMModelBI/ClientApp/src/view/areaServe/areamanage.vue

@@ -75,7 +75,6 @@
     </div>
     <div class="traitfrom">
       <el-table :data="optionData" style="width: 100%" :highlight-current-row="true" height="74vh" v-loading="loading" :empty-text="$t(`commonMsg.nodataTable`)" element-loading-text="数据加载中...">
-        <!-- <el-table-column prop="index" :label="$t(`areaManages.areaTable.serialnum`)" type="index" sortable align="center" /> -->
         <el-table-column prop="name" :label="$t(`areaManages.areaTable.name`)" align="center" />
         <el-table-column prop="id" label="学区ID" align="center">
           <template #default="scope">
@@ -89,21 +88,38 @@
             </div>
           </template>
         </el-table-column>
-        <el-table-column prop="code" label="学区简码" align="center">
+        <el-table-column prop="code" label="频道简码" align="center">
           <template #default="scope">
-            <div class="code-idboxs">
-             <div>XXXX</div>
+            <!-- <div class="code-idboxs">
+             <div>暂无简码</div>
               <div class="code-copyicon" title="复制学区简码">
                 <el-icon @click="copyAreaID(scope.row)">
                   <CopyDocument />
                 </el-icon>
               </div>
+            </div> -->
+
+            <div>
+              <p  class="codeboxs" v-if="scope.$index !==curTarget.index  && scope.row.shortCode">
+               {{scope.row.shortCode}}
+              <el-icon  class="el-icon-edit-outline" @click="curTarget.index=scope.$index,curTarget.text=scope.row.shortCode,curTarget.name=scope.row.name,curTarget.id=scope.row.id"><Edit /></el-icon>
+              </p>
+              <p  class="codeboxs" v-else-if="scope.$index !==curTarget.index  && !scope.row.shortCode">
+              暂无简码
+              <el-icon  class="el-icon-edit-outline" @click="curTarget.index=scope.$index,curTarget.text=scope.row.shortCode,curTarget.name=scope.row.name,curTarget.id=scope.row.id"><Edit /></el-icon>
+              </p>
+            <el-input
+              type="textarea"
+              :autosize="{minRows:2,maxRows:4}"
+              v-show="scope.$index ===curTarget.index "
+              v-model="scope.row.shortCode"
+              @blur="updateShortcode(scope.row.shortCode,scope.$index)"
+            />
             </div>
           </template>
         </el-table-column>
         <el-table-column prop="schoolCount" label="区内学校数量" align="center" sortable :sort-method="areaSort" />
         <el-table-column prop="location" label="位置" align="center" />
-        <!-- <el-table-column prop="cityName" :label="$t(`areaManages.areaTable.city`)" align="center" /> -->
         <el-table-column prop="institution" :label="$t(`areaManages.areaTable.affiliation`)" align="center" />
         <el-table-column prop="standardName" :label="$t(`areaManages.areaTable.project`)" align="center" />
         <el-table-column :label="$t(`areaManages.areaTable.operate`)" align="center" v-if="PowerShow">
@@ -118,6 +134,41 @@
           </template>
         </el-table-column>
       </el-table>
+      <!--可编辑table-->
+      <!-- <el-table
+        :data="testDatas"
+        :row-class-name="tableRowClassName"
+        v-loading="loading" :empty-text="$t(`commonMsg.nodataTable`)" element-loading-text="数据加载中..."
+      >
+        <el-table-column v-for="(col, idx) in columnList" :key="col.prop" :index="idx">
+            <template #header>
+              <p v-show="col.show" class="customtable-header">
+                {{col.label}}
+
+              </p>
+        </template>
+          <template #default="{ row }">
+            <div v-if="col.prop !=='operate'">
+              <p v-show="row[col.prop].show" >
+              {{row[col.prop].content}} 
+              <el-icon v-show="col.prop ==='code' " class="el-icon-edit-outline" @click="$event => handleEdit(row[col.prop], $event.target)"><Edit /></el-icon>
+            </p>
+            <el-input
+              type="textarea"
+              :autosize="{minRows:2,maxRows:4}"
+              v-show="!row[col.prop].show"
+              v-model="row[col.prop].content"
+              @blur="row[col.prop].show=true"
+            />
+            </div>
+            <div v-else class="customtable-header">
+              <el-button   size="mini" @click="operation(scope.$index, scope.row, true)" type="primary">查看</el-button>
+            </div>
+          </template>
+        </el-table-column>
+        <el-button size="mini"  type="primary">查看</el-button>
+      </el-table>   -->
+      <!--可编辑table end-->
     </div>
     <div class="adjustmentDialog">
       <el-dialog v-model="adjustmentbox" title="" width="80%" @close="closeInfo" center class="interfacebbox">
@@ -145,14 +196,17 @@
                     </el-dropdown>
                   </div>
                   <div class="search-school">
-                    <el-input v-model="schoolSeach" placeholder="输入学校名称搜索" clearable v-if="!multiplecheck">
-                    </el-input>
-                    <el-button type="primary" v-else-if="multiplecheck" @click="multipleAdd">
+                    <div class="search-school-search">
+                      <el-input v-model="schoolSeach" placeholder="输入学校名称搜索" clearable ></el-input>
+                    </div>
+                    <div class="search-school-btn" v-show="multiplecheck">
+                      <el-button type="primary"  @click="multipleAdd" size="small">
                       <svg class="multipleicon" aria-hidden="true">
                         <use xlink:href="#icon-piliangtianjia1"></use>
                       </svg>
                       批量添加
                     </el-button>  
+                    </div>
                   </div>
                   <div class="synchronization-title" v-show="currentlySelect.cutArea"><span>已同步省平台</span></div>
                 </div>
@@ -643,7 +697,7 @@ import { useRouter } from 'vue-router'
 import Ability from '@/components/Ability.vue'
 import option from '@/static/region.json'
 import loadingsz from '@/components/loading/partial.vue'
-import { CopyDocument, ArrowRight, ArrowLeft, Search, Back, ArrowDown } from '@element-plus/icons-vue'
+import { CopyDocument, ArrowRight, ArrowLeft, Search, Back, ArrowDown,Edit } from '@element-plus/icons-vue'
 import useClipboard from 'vue-clipboard3'
 import jwt_decode from 'jwt-decode'
 const optionsData = option
@@ -656,9 +710,16 @@ export default {
     ArrowLeft,
     Search,
     Back,
-    ArrowDown
+    ArrowDown,
+    Edit
   },
   setup () {
+    let curTarget=ref({
+       index:-1,
+       text:'',
+       name:'',
+       id:'',
+    })
     let { proxy } = getCurrentInstance()
     let PowerShow = proxy.$access.identifyPosition(JSON.parse(localStorage.getItem('id_token')))
     const { toClipboard } = useClipboard()
@@ -776,16 +837,58 @@ export default {
           res.areas[i].location = res.areas[i].provName + res.areas[i].cityName
         }
         optionData.value.push(...res.areas)
-        loading.value = false
         store.commit('getPoint', res.areas)
+        loading.value = false
         originalDatas.value.push(...res.areas)
         optionData.value.forEach((item, index) => { item.name.includes('完整') ? optionData.value.splice(index, 1) : '' })
       })
     }
+    //处理API返回的学区json 符合table的呈现
+    function disposeTabledata(data){
+      let initData=data
+      initData.forEach((item)=>{
+         let pushData={
+          name:{content:item.name,show:true},
+          id:{content:item.id,show:true},
+          code:{content:'暂无简码',show:true},
+          schoolCount:{content:item.schoolCount,show:true},
+          location:{content:item.provName+item.cityName,show:true},
+          institution:{content:item.institution,show:true},
+          standardName:{content:item.standardName,show:true},
+          standardName:{content:item.standardName,show:true},
+          operate:{content:'',state:true}
+        }
+        testDatas.value.push(pushData)
+      })
+      loading.value = false
+    }
+    //修改学区简码or苏格拉底频道简码 shortCode内容
+    function updateShortcode(data,index){
+      let shortCodes=data;let dataIndex=index
+      console.log(shortCodes.length,'长度')
+      if(shortCodes.length !==6 && shortCodes.length !==0){
+        ElMessage.error('简码需6位字母或数字,请重新填写')
+        optionData.value[dataIndex].shortCode=curTarget.value.text
+      }else if(shortCodes.length ===0){
+        let data={id:curTarget.value.id,name:curTarget.value.name,shortCode:shortCodes}
+        proxy.$api.updateAreacode(data).then((res)=>{
+          console.log(res,'updateCode back')
+          res.state === 200 ? ElMessage.success('更新成功'):ElMessage.error('操作成功')
+        })
+        curTarget.value.index=-1
+      }else{
+        let data={id:curTarget.value.id,name:curTarget.value.name,shortCode:shortCodes}
+        proxy.$api.updateAreacode(data).then((res)=>{
+          console.log(res,'updateCode back')
+          res.state === 200 ? ElMessage.success('更新成功'):ElMessage.error('操作成功')
+        })
+        curTarget.value.index=-1
+      }
+    }
     //table按钮
     async function operation (index, row, state) {
       tableData.value = []
-      console.log(row)
+      console.log(index,row,state,'打开学区传输内容')
       loadingSchoolList.value = true
       currentlySelect.value = row
       let dialogData = JSON.parse(JSON.stringify(originalDatas.value))
@@ -1256,6 +1359,7 @@ export default {
         return item.name.includes(areaValues.value)
       })
       optionData.value = newArr
+      // disposeTabledata(optionData.value)
       loading.value = false
     }
     function addSelectSchool (value) {
@@ -1490,7 +1594,9 @@ export default {
       dropdownValue,
       multiplecheck,
       multipleChange,
-      multipleAdd
+      multipleAdd,
+      curTarget,
+      updateShortcode
     }
   },
 }
@@ -1874,19 +1980,24 @@ export default {
   flex-wrap: nowrap;
 }
 .select-text {
-  width: 13%;
-  padding-left: 2%;
+  width: 11%;
+  padding-left: 0%;
 }
 .select-click {
-  width: 25%;
+  width: 20%;
   line-height: 40px;
 }
 .search-school {
-  width: 45%;
+  width: 60%;
   text-align: center;
+  display: flex;
+  flex-wrap: nowrap;
 }
-.search-school div {
-  width: 100%;
+.search-school .search-school-search {
+  width: 70%;
+}
+.search-school .search-school-btn{
+  width:30%;
 }
 .synchronization-title {
   float: right;
@@ -2370,6 +2481,16 @@ export default {
   color: #636e72;
   font-weight: none;
 }
+.customtable-header{
+  margin-bottom: 5px;
+  text-align: center;
+}
+.el-icon-edit-outline{
+  opacity: 0;
+}
+.codeboxs:hover .el-icon-edit-outline{
+  opacity: 1;
+}
 </style>
 <style>
 .stagebox-table-not .el-image {
@@ -2387,6 +2508,9 @@ export default {
   width: 98%;
   margin: 0 auto;
   /* padding: 1%; */
+  overflow: hidden;
+  height:80vh;
+  overflow-y: auto;
 }
 
 .traitfrom .el-form-item {
@@ -2568,6 +2692,19 @@ export default {
   border: 0px;
   box-shadow: 0px 0px 0px 0px transparent;
 }
+.select-school .el-input{
+  width:100% !important;
+}
+.traitfrom .el-scrollbar{
+  line-height: 80px;
+}
+.traitfrom .el-table .el-table__cell{
+  padding: 15px 0px;
+}
+.traitfrom .el-scrollbar .cell p{
+  margin-bottom: 0px;
+  text-align: center;
+}
 @media screen and (max-width: 2600px) {
   .select-box-items {
     width: 25%;

+ 32 - 26
TEAMModelBI/ClientApp/src/view/created/created.vue

@@ -252,11 +252,14 @@
                 <p class="repetition-hint" v-if="repetition.code">该学校简码已存在,请检查学校信息</p>
               </template>
             </el-form-item>
+            <el-form-item label="規模版本" class="school-detailedly">
+              <el-input v-model="item.scaleVersion" placeholder="規模版本" />
+            </el-form-item>
           </el-form>
           <div class="confirmarea">
             <el-button type="primary" @click="verifyBase()" v-if="verifyForstate.state ===false">数据核验</el-button>
             <el-button type="success" @click="createdSchool()" :loading="createdSchoolLoading" v-else-if="verifyForstate.state===true && verifyForstate.pass===true ">{{ $t(`schoolManages.createSchools.submit`) }}</el-button>
-            <!-- <el-button @click="closeandreturn('close', 'school')">重置</el-button> -->
+            <!-- <el-button @click="closeandreturn('close', 'school')">重置</el-button> -->            
             <el-button @click="resetForm()">重置</el-button>
           </div>
         </div>
@@ -328,7 +331,7 @@
             <div class="confirmarea virtualsubmitbtn">
               <el-button type="primary" v-if="verifyForstate.state ===false">数据核验</el-button>
               <el-button type="success" @click="createdSchool()" :loading="createdSchoolLoading" v-else-if="verifyForstate.state===true && verifyForstate.pass===true ">{{ $t(`schoolManages.createSchools.submit`) }}</el-button>
-              <!-- <el-button @click="closeandreturn('close', 'school')">重置</el-button> -->
+              <!-- <el-button @click="closeandreturn('close', 'school')">重置</el-button> -->              
               <el-button @click="resetForm()">重置</el-button>
             </div>
           </el-form>
@@ -1059,6 +1062,7 @@ export default {
     }
     //创建学校
     function createdSchool () {
+      //debugger;
       console.log(schoolForm, '创校数据')
       let langState = (schoolForm.value[0].lang === "1" || schoolForm.value[0].lang === "2" || schoolForm.value[0].lang === "3") ? true : false
       if (schoolForm.value[0].name === '' || schoolForm.value[0].name === undefined) {
@@ -1126,9 +1130,10 @@ export default {
           lang: schoolForm.value[0].lang === '1' ? 'zh-CN' : schoolForm.value[0].lang === '2' ? 'zh-TW' : schoolForm.value[0].lang === '3' ? 'en-US' : 'zh-CN',
           areaId: schoolForm.value[i].areaIdcreated,
           code: schoolForm.value[i].code,
-          modules:schoolForm.value[i].modules === 'default' ? []:['art']
+          modules:schoolForm.value[i].modules === 'default' ? []:['art'],
+          scaleVersion:schoolForm.value[i].scaleVersion
         })
-      }
+      }      
       let parameter = { biSchools: datas, lang: schoolForm.value[0].lang === '1' ? 'zh-CN' : schoolForm.value[0].lang === '2' ? 'zh-TW' : schoolForm.value[0].lang === '3' ? 'en-US' : 'zh-CN' }
       console.log(schoolForm.value[0].lang)
       console.log(parameter, '创建学校最后的数据格式')
@@ -1338,7 +1343,6 @@ export default {
       console.log(data, '提交的数据')
       proxy.$api.verifyContent(data).then((res) => {
         console.log(res, '数据验证的结果')
-        res.state === 200 ? (batchDatas.forEach((item) => { item.dataState = true }), batchVerify(presentData, loadingverify), codeShow.value = true) : ''
         if (res.state === 200) {
           //处理简码
           res.createScInfo.forEach((items) => {
@@ -1349,6 +1353,7 @@ export default {
             }
           })
         }
+        res.state === 200 ? (batchDatas.forEach((item) => { item.dataState = true }), batchVerify(presentData, loadingverify), codeShow.value = true) : ''
         if (res.state === 201) {
           codeShow.value = false
           batchTablesArr.value = true; verifyState.value = false
@@ -1680,7 +1685,7 @@ export default {
           ElMessage({ showClose: false, message: '数据存在异常,请检查表单内容', type: 'error', duration: 4000 })
         }
         verifySchool.close()
-      }).catch((error) => {
+      }).catch((error) => {        
         ElMessage.error('API异常,数据核验失败')
         verifySchool.close()
       })
@@ -1732,11 +1737,11 @@ export default {
         })
       }
 
-      let datas = { regionId: regionCodeNow, name: verifyData[0].name, nameFuzzy: false, shortCode: verifyData[0].code, shortCodeFuzzy: false }
+      let datas = { regionId: '', name: '', nameFuzzy: false, shortCode: '', shortCodeFuzzy: false, codeOrShortCode: verifyData[0].code }
       proxy.$api.verifyDatainbb(datas).then((res) => {
         console.log(res.length, '核验数据')
-        res.length == 0 ? (verifyForstate.value.state = true, verifyForstate.value.pass = true, ElMessage.success('数据已通过核验,可执行创校')) : (verifyForstate.value.state = false, verifyForstate.value.pass = false, ElMessage.error('数据未通过核验,请检查表单内容'))
-      }).catch((error) => {
+        res.length == 0 ? (verifyForstate.value.state = true, verifyForstate.value.pass = true, ElMessage.success('数据已通过核验,可执行创校')) : (verifyForstate.value.state = false, verifyForstate.value.pass = false, ElMessage.error('数据未通过核验,BB学校资料库已存在此学校代码或简码。'))
+      }).catch((error) => {        
         ElMessage.error('API异常,数据核验失败')
       })
       console.log(verifyData, '准备核验的数据')
@@ -1747,25 +1752,25 @@ export default {
       let scArr = value
       let snameList = []; let scodeList = []; let shortArr = []; let regionList = []; let regionInfoRowNow = [];
       let regionCodeTmp = ''
-      scArr.forEach((item) => {
-        snameList.push(item.name);
-        scodeList.push(item.id);
+        scArr.forEach((item) => {
+        // snameList.push(item.name);
+        // scodeList.push(item.id);
         shortArr.push(item.id);
-        regionInfoRowNow = regionInfoList.filter(function (rgitem) { return rgitem.name.includes(item.region) })
-        regionCodeTmp = (regionInfoRowNow.length > 0 && regionInfoRowNow[0].hasOwnProperty('code')) ? regionInfoRowNow[0]['code'] : ''
-        if (regionCodeTmp != '' && !regionList.includes(regionCodeTmp)) {
-          regionList.push(regionCodeTmp)
-        }
+        // regionInfoRowNow = regionInfoList.filter(function (rgitem) { return rgitem.name.includes(item.region) })
+        // regionCodeTmp = (regionInfoRowNow.length > 0 && regionInfoRowNow[0].hasOwnProperty('code')) ? regionInfoRowNow[0]['code'] : ''
+        // if (regionCodeTmp != '' && !regionList.includes(regionCodeTmp)) {
+        //   regionList.push(regionCodeTmp)
+        // }
       })
-      let data = { nameList: snameList, codeList: scodeList, shortCodeList: shortArr }
-      if (siteValue === 'cn') {
-        data['regionId'] = 'CN'
-      } else {
-        data['regionId'] = (regionList.length == 1) ? regionList[0] : ''
-        data['regionIdList'] = (regionList.length > 1) ? regionList : []
-      }
+      let data = { nameList: snameList, codeList: scodeList, codeOrShortCodeList: shortArr }
+      // if (siteValue === 'cn') {
+      //   data['regionId'] = 'CN'
+      // } else {
+      //   data['regionId'] = (regionList.length == 1) ? regionList[0] : ''
+      //   data['regionIdList'] = (regionList.length > 1) ? regionList : []
+      // }
       proxy.$api.verifyDatainbb(data).then((res) => {
-        res.length == 0 ? (ElMessage.success('数据已通过核验,可执行创校'), batchTablesArr.value = true) : (ElMessage.error('数据未通过核验,请检查表单内容'), batchTablesArr.value = true, verifyState.value = false)
+        res.length == 0 ? (ElMessage.success('数据已通过核验,可执行创校'), batchTablesArr.value = true) : (ElMessage.error('数据未通过核验,BB学校资料库已存在此学校代码或简码,请检查表单内容'), batchTablesArr.value = true, verifyState.value = false)
       }).catch((error) => {
         ElMessage.error('API异常,批量数据核验失败')
       })
@@ -2033,7 +2038,8 @@ export default {
       timer,
       selectSchoolstate,
       selectModels,
-      virtualSchoolform
+      virtualSchoolform,
+      
     }
   },
 }

+ 2 - 1
TEAMModelBI/ClientApp/src/view/ddlogin.vue

@@ -10,7 +10,8 @@ const hosts = window.location.host === 'localhost:5001' ? 'localhost:5001' :
         window.location.host === 'bi.teammodel.net' ? 'bi.teammodel.net' :
             window.location.host === 'bi-rc.teammodel.net' ? 'bi-rc.teammodel.net' :
                 'bitest.teammodel.cn'
-const appsKey = window.location.host === 'localhost:5001' || window.location.host === 'bi.teammodel.cn' || window.location.host === 'bitest.teammodel.cn' ? 'dingrucgsnt8p13rfbgd' : 'dingupjxyj1guhh5p8dt'
+    const appsKey = window.location.host === 'localhost:5001' || window.location.host === 'bi.teammodel.cn' || window.location.host === 'bitest.teammodel.cn' ? 'dingrucgsnt8p13rfbgd' : 'dingupjxyj1guhh5p8dt'
+    //const appsKey =  window.location.host === 'bi.teammodel.cn' || window.location.host === 'bitest.teammodel.cn' ? 'dingrucgsnt8p13rfbgd' : 'dingupjxyj1guhh5p8dt'
 console.log(appsKey, 'key的内容')
 import axios from 'axios'
 export default {

+ 38 - 28
TEAMModelBI/ClientApp/src/view/participation/index.vue

@@ -118,8 +118,8 @@
   <!--学校列表end-->
   <!--编辑学校页面-->
   <div class="schoolDeatils">
-    <div class="backbtn" v-if="models === 'details' && PowerShow">
-      <el-button class="changebtn" v-if="store.state.changbtnShow && changebtns" @click="getSetschool()" size="small">
+    <div class="backbtn" v-if="models === 'details'">
+      <el-button class="changebtn" v-if="store.state.changbtnShow && changebtns" @click="getSetschool()" >
         <svg class="changebtn-areaicon" aria-hidden="true">
           <use xlink:href="#icon-wenjian"></use>
         </svg>
@@ -132,10 +132,10 @@
         返回
       </el-button>
     </div>
-    <el-tabs v-if="models === 'details' && PowerShow" @tab-click="changeTabs">
+    <el-tabs v-if="models === 'details'" @tab-click="changeTabs">
       <!--基础设置-->
       <el-tab-pane :label="$t(`schoolManages.redactSet`)">
-        <div class="redactbox" v-show="models === 'details' && PowerShow">
+        <div class="redactbox" v-show="models === 'details'">
           <div class="school-formbox">
             <el-form ref="form" :model="nowPitchdata" label-width="120px">
               <el-form-item :label="$t(`schoolManages.basicSet.name`) + ':'" class="school-form-name">
@@ -436,9 +436,9 @@ export default {
         // sortable: true,
         cellRenderer: (data) => (
           <>
-            <div style="color:#409EFF" v-show={data.rowData.scale === 0 && (data.rowData.size < 100 || data.rowData.size == 100) ? true : false}>基础版</div>
-            <div style="color:#67C23A" v-show={(data.rowData.scale === 300 && data.rowData.size === 500) || (data.rowData.size > 100 && (!data.rowData.service.includes('YMPCVCIM') && !data.rowData.service.includes('VLY6J6N6') && !data.rowData.service.includes('VABAJ6NV'))) ? true : false}>标准版</div>
-            <div style="color: #e6a23c;" v-show={data.rowData.service.includes('YMPCVCIM') || data.rowData.service.includes('VLY6J6N6') || data.rowData.service.includes('VABAJ6NV') ? true : false}>专业版</div>
+            <div style="color:#e6a23c;" v-show={data.rowData.versions ==='专业版' ? true:false}>专业版</div>
+            <div style="color:#67C23A;" v-show={data.rowData.versions ==='标准版' ? true:false}>标准版</div>
+            <div style="color:#409EFF;" v-show={data.rowData.versions ==='基础版' ? true:false}>基础版</div>
           </>
         ),
       },
@@ -483,23 +483,26 @@ export default {
         headerClass: 'testclass',
         cellRenderer: (data) => (
           <>
-            <div title="学情分析" v-show={data.rowData.service.includes('YMPCVCIM') ? true : false}>
-              <svg style=" width: 1.8em;height: 1.8em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-tongjifenxi"></use></svg>
+            <div title="基础服务模组">
+              <svg style=" width: 1.6em;height: 1.6em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-jianyanbiaozhun"></use></svg>
             </div>
-            <div title="智慧学校管理服务" v-show={data.rowData.service.includes('IPDYZYLC') ? true : false}>
-              <svg style=" width: 1.8em;height: 1.8em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-zhihuixiaoyuan"></use></svg>
+            <div title="学情分析服务模组(未开启)" v-show={!data.rowData.service.includes('YMPCVCIM') ? true : false}>
+              <svg style=" width: 1.5em;height: 1.5em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-xueqinggailan"></use></svg>
             </div>
-            <div title="A Class ONE 智慧学伴" v-show={data.rowData.service.includes('3CLYJ6NP') ? true : false}>
-              <svg style=" width: 1.8em;height: 1.8em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-jxuexiao2"></use></svg>
+            <div title="学情分析服务模组" v-show={data.rowData.service.includes('YMPCVCIM') ? true : false}>
+              <svg style=" width: 1.5em;height: 1.5em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-xueqinggailan-copy"></use></svg>
             </div>
-            <div title="数据存储服务空间" v-show={data.rowData.service.includes('IPALJ6NY') ? true : false}>
-              <svg style=" width: 1.8em;height: 1.8em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-yuncunchu"></use></svg>
+            <div title="艺术评测服务(未开启)" v-show={!data.rowData.service.includes('B6V5J6NP') ? true : false}>
+              <svg style=" width: 1.5em;height: 1.5em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-yishuzhuanye"></use></svg>
             </div>
-            <div title="卷卡合一阅卷系统" v-show={data.rowData.service.includes('VABAJ6NV') ? true : false}>
-              <svg style=" width: 1.8em;height: 1.8em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-pingtai_kaoshi"></use></svg>
+            <div title="艺术评测服务" v-show={data.rowData.service.includes('B6V5J6NP') ? true : false}>
+              <svg style=" width: 1.5em;height: 1.5em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-yishuzhuanye-copy"></use></svg>
             </div>
-            <div title="教研中心模组" v-show={data.rowData.service.includes('VLY6J6N6') ? true : false}>
-              <svg style=" width: 1.8em;height: 1.8em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-jiaoyan"></use></svg>
+            <div title="五育看板服(未开启)" v-show={!data.rowData.service.includes('YPXSJ6NJ') ? true : false}>
+              <svg style=" width: 1.5em;height: 1.5em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-shuzikanban-copy"></use></svg>
+            </div>
+            <div title="五育看板服" v-show={data.rowData.service.includes('YPXSJ6NJ') ? true : false}>
+              <svg style=" width: 1.5em;height: 1.5em;vertical-align: -0.5em;fill: currentColor;overflow: hidden;cursor: pointer;" aria-hidden="true" ><use xlink:href="#icon-shuzikanban"></use></svg>
             </div>
           </>
         ),
@@ -596,7 +599,11 @@ export default {
           }
         }
         console.log(res)
-        res.state == 200 ? (tableData.value = [], originalData.value = [], tableData.value.push(...res.scInfos), (originalData.value = res.scInfos), tablesccnt.value = res.allCnt, originalNum.value = res.allCnt) : ''
+        res.state == 200 ? 
+        (tableData.value = [], originalData.value = [],
+        res.scInfos.forEach((item)=>{item.versions= item.service.includes('YPXSJ6NJ') && item.service.includes('B6V5J6NP') ? '专业版':item.service.includes('YMPCVCIM') ? '标准版':'基础版'}),
+         tableData.value.push(...res.scInfos), (originalData.value = res.scInfos), tablesccnt.value = res.allCnt, originalNum.value = res.allCnt) 
+        : ''
         loading.value = false
       })
     }
@@ -623,9 +630,11 @@ export default {
       uploadHeader.value['x-auth-authtoken'] = token
       data.areaId !== null ? (areaSelect.value.Selectvalue = data.areaId) : ''
       console.log(store.state.point, '目前现有的所有区')
-      store.state.point.length ? areaSelect.value.data.push(...store.state.point) : getoption()
+      //store.state.point.length ? areaSelect.value.data.push(...store.state.point) : getoption()
       proxy.$api.getNowscholl({ schoolId: school.id }).then((res) => {
-        res.state === 200 ? (detailsSchool.value = res.schoolAssists, nowPitchdata.value.type = res.schoolAssists.type.toString(), models.value = 'details') : ElMessage.error('详情API异常,访问失败')
+        res.state === 200 ? 
+        (detailsSchool.value = res.schoolAssists, nowPitchdata.value.type = res.schoolAssists.type.toString(), models.value = 'details') 
+        : ElMessage.error('详情API异常,访问失败')
       }).catch((error) => {
         ElMessage.error('详情API异常,访问失败')
         return
@@ -873,10 +882,10 @@ export default {
     }
     //获取所有区域,学校编辑内呈现
     function getoption () {
-      proxy.$api.getCapacity({}).then((res) => {
-        areaSelect.value.data.push(...res.areas)
-        store.commit('getPoint', res.areas)
-      })
+      // proxy.$api.getCapacity({}).then((res) => {
+      //   areaSelect.value.data.push(...res.areas)
+      //   store.commit('getPoint', res.areas)
+      // })
     }
     //修改成功后执行
     function updateSuccess () {
@@ -898,7 +907,7 @@ export default {
     }
     //关于储存变更按钮
     function changeTabs (value) {
-      console.log(value.props.label)
+      console.log(value.props.label,'目前的值')
       value.props.label == '学段管理' || value.props.label == '學段管理' ? (changebtns.value = true) : (changebtns.value = false)
     }
     //获取子页面的数据
@@ -928,7 +937,8 @@ export default {
       proxy.$api
         .updateSchoolphase(newData)
         .then((res) => {
-          res.state === 200 ? (ElMessage.success('保存成功'), (studyPhase.value = res.schoolInfo.id), (changebtns.value = false)) : ElMessage.error('保存失败')
+          res.state === 200 ? (ElMessage.success('保存成功'), (studyPhase.value = res.schoolInfo.id), (changebtns.value = true),store.commit('changeShowbtn', false)) : ElMessage.error('保存失败')
+
           loadinginfo.close()
         })
         .catch((res) => {

+ 64 - 46
TEAMModelBI/ClientApp/src/view/participation/setPhase.vue

@@ -27,10 +27,7 @@
       <div class="phaseList" v-if="nowschoolData.period">
         <div class="phaseitem" v-for="(item, index) in nowschoolData.period" :key="index" :class="{ 'checkedis': pathNowphase === index }" @click="cutPhase(index)">
           <div class="phasei-item-name">
-            <div class="namebox" v-if="item.changed === false">{{ item.name }}</div>
-            <div class="namebox" v-show="item.changed === true">
-              <el-input ref="editbox" v-model="item.name" @blur="nameChanges(index)" />
-            </div>
+            <div class="namebox">{{ item.name }}</div>
             <span class="campus">{{ item.area }}</span>
           </div>
           <p class="phasei-item-common">
@@ -418,7 +415,10 @@
           </el-form-item>
           <el-form-item label="所属阶段" class="stage-checkbox">
             <div class="checkbox-stage">
-              <el-checkbox v-for="(item,index) in stageData.checkeds" :key="index" v-model="item.state" :label="item.name" size="small" />
+              <!-- <el-checkbox v-for="(item,index) in stageData.checkeds" :key="index" v-model="item.state" :label="item.name" size="small" /> -->
+              <el-radio-group v-model="stageData.ptichValue">
+                <el-radio v-for="(item,index) in stageData.checkeds" :key="index" :label="item.name" size="small" />
+              </el-radio-group>
             </div>
           </el-form-item>
         </el-form>
@@ -758,24 +758,38 @@ export default {
       ],
     })
     //获取当前学校的信息(API)
+    // function getnowSchool (data) {
+    //   console.log(data, '进入调用API方法')
+    //   let schoolData = {}
+    //   conductData(data)
+    //   //处理学段管理api
+    //   // proxy.$api
+    //   //   .getNowscholl({ schoolId: data })
+    //   //   .then((res) => {
+    //   //     console.log(res, '返回的res内容CCCCC')
+    //   //     res.state === 200 ? ((schoolData = res.schoolAssists), conductData(res.schoolAssists), context.emit('schoolDetailInfo', res.schoolAssists)) : ''
+    //   //   })
+    //   //   .catch((res) => {
+    //   //     ElMessage.error('获取学校数据异常')
+    //   //   })
+    // }
     function getnowSchool (data) {
       console.log(data, '进入调用API方法')
       let schoolData = {}
-      conductData(data)
       //处理学段管理api
-      // proxy.$api
-      //   .getNowscholl({ schoolId: data })
-      //   .then((res) => {
-      //     console.log(res, '返回的res内容CCCCC')
-      //     res.state === 200 ? ((schoolData = res.schoolAssists), conductData(res.schoolAssists), context.emit('schoolDetailInfo', res.schoolAssists)) : ''
-      //   })
-      //   .catch((res) => {
-      //     ElMessage.error('获取学校数据异常')
-      //   })
+      proxy.$api
+        .getNowscholl({ schoolId: data.id })
+        .then((res) => {
+          console.log(res, '返回的res内容CCCCC')
+          res.state === 200 ? ((schoolData = res.schoolAssists), conductData(res.schoolAssists), context.emit('schoolDetails', res.schoolAssists)) : ''
+        })
+        .catch((res) => {
+          ElMessage.error('获取学校数据异常')
+        })
     }
     //接收到学校信息处理数据
     function conductData (data) {
-      console.log(data, '进来的数据')
+      console.log(data,pathNowphase.value, '进来的数据')
       if (!data) {
         return
       }
@@ -787,14 +801,10 @@ export default {
           datas.campuses[y].id === ids ? (datas.period[i].area = datas.campuses[y].name) : ''
         }
       }
-      //显示学段名称和校区
-      for (let i in datas.period) {
-        let ids = datas.period[i].campusId
-        datas.period[i].changed = false
-        for (let y in datas.campuses) {
-          datas.campuses[y].id === ids ? (datas.period[i].area = datas.campuses[y].name) : ''
-        }
-      }
+      // if (data.period[pathNowphase.value].semesters.length === 0 || data.period[pathNowphase.value].subjects.length === 0) {
+      //   ElMessage.error('学段管理内数据异常')
+      //   // return
+      // }
       //处理学期设置
       let phasetime = data.period[pathNowphase.value].semesters
       console.log(phasetime, '当前的学期')
@@ -810,8 +820,8 @@ export default {
           }
         }
         timesteps.value.nowitem = data.period[pathNowphase.value].semesters[0]
+        console.log(timesteps.value)
       }
-      console.log(timesteps.value, '查看这里是否执行')
       // for (let i in phasetime) {
       //     phasetime[i].start === 0 ? (phasetime[i].totaldays = proxy.$common.totalDay(topStart, downStart)) : (phasetime[i].totaldays = proxy.$common.totalDay(downStart, topStart))
       // }
@@ -946,11 +956,12 @@ export default {
             (dialogModels.value = 'semester')))
         : ''
       state === 'updateSubjects'
-        ? ((subjectsData.value.name = value.name),
-          (subjectsData.value.type = value.type.toString()),
-          (subjectsData.value.id = value.id),
-          (dialogModels.value = 'subjects'),
-          (editDialogName.value = proxy.$t(`schoolManages.gradSet.popup.updatesubject`)),
+        ? (subjectsData.value.name = value.name,
+          subjectsData.value.type = value.type.toString(),
+          subjectsData.value.id = value.id,
+          dialogModels.value = 'subjects',
+          editDialogName.value = proxy.$t(`schoolManages.gradSet.popup.compile`),
+          // editDialogName.value='编辑学科',
           (subjectsData.value.models = 'subjectsUpdate'))
         : ''
       state === 'addSubjects'
@@ -960,7 +971,18 @@ export default {
           (subjectsData.value.models = 'subjectsAdd'),
           (editDialogName.value = proxy.$t(`schoolManages.gradSet.popup.addSubject`)),
           (dialogModels.value = 'subjects'))
-        : ''
+        :
+        state === 'stage'
+          ? (
+            (editDialogName.value = '编辑学段属性'),
+            console.log(stageData, value, '属性属性'),
+            (stageData.value.checkeds.forEach((a) => { a.state = false })),
+            (stageData.value.name = value.name),
+            stageData.value.checkeds.forEach((items) => {
+              items.value == value.periodType ? stageData.value.ptichValue = items.name : ''
+            }),
+            dialogModels.value = 'stage')
+          : ''
       if (state === 'updateTimebucket') {
         let timetables = nowschoolData.value.period[pathNowphase.value].timetable
         let timeindex = timetables[index].time.indexOf('-')
@@ -991,18 +1013,6 @@ export default {
           (editDialogName.value = proxy.$t(`schoolManages.gradSet.popup.addTime`)),
           (dialogModels.value = 'timebucket'))
         : ''
-      state === 'stage'
-        ? (
-          (editDialogName.value = '编辑学段属性'),
-          (stageData.value.checkeds.forEach((a) => { a.state = false })),
-          (stageData.value.name = value.name),
-          (value.type.forEach((item) => {
-            stageData.value.checkeds.forEach((items) => {
-              item == items.value ? items.state = true : ''
-            })
-          })),
-          dialogModels.value = 'stage')
-        : ''
       console.log(form.value)
       editDialog.value = true
     }
@@ -1056,6 +1066,14 @@ export default {
           (nowschoolData.value.period[pathNowphase.value].timetable = settimeArr),
           timeSort(nowschoolData.value.period[pathNowphase.value].timetable))
         : ''
+       //编辑学段名称和阶段
+       if (dialogModels.value === 'stage') {
+        console.log(nowschoolData.value.period, '当前学段')
+        nowschoolData.value.period[pathNowphase.value].name = stageData.value.name
+        let stageTrue = ''
+        stageData.value.checkeds.forEach((item) => { item.name === stageData.value.ptichValue ? stageTrue = item.value : '' })
+        nowschoolData.value.period[pathNowphase.value].periodType = stageTrue
+      }  
       console.log(nowschoolData.value, '修改后的数据')
       store.commit('changeShowbtn', true)
       editDialog.value = false
@@ -1333,9 +1351,9 @@ export default {
     }
     watch(
       props,
-      (newdata, olddata) => {
+      (newdata) => {
         console.log(newdata, '数据')
-        newdata.detailsSchool !== undefined && newdata !== olddata ? getnowSchool(newdata.detailsSchool) : ''
+        newdata.detailsSchool !== undefined ? getnowSchool(newdata.detailsSchool) : ''
       },
       { immediate: true, deep: true }
     )
@@ -2242,7 +2260,7 @@ export default {
 
 .form-semester-name {
   width: 55%;
-  padding-left: 2.5%;
+  /* padding-left: 2.5%; */
 }
 
 .form-semester-entrance .form-radio {

+ 91 - 13
TEAMModelBI/ClientApp/src/view/schoolServe/school.vue

@@ -209,7 +209,7 @@
                     {{ $t(`schoolManages.basicSet.higherEducation`) }}</el-radio>
                 </div>
               </el-form-item>
-              <el-form-item :label="创校流程" class="school-form-grading">
+              <!-- <el-form-item :label="创校流程" class="school-form-grading">
                 <div v-if="PowerShow">
                   <el-radio v-model="nowPitchdata.modules " label="default" size="large">
                     普通创校
@@ -224,7 +224,7 @@
                   <el-radio v-model="nowPitchdata.modules " label="art" size="large" disabled>
                     评测创校</el-radio>
                 </div>
-              </el-form-item>
+              </el-form-item> -->
               <el-form-item :label="$t(`schoolManages.basicSet.nowAssistant`)" class="school-form-admin">
                 <div v-if="PowerShow" class="admin-boxs-width">
                   <el-select v-model="adminvalue" multiple @change="assistChange" :placeholder="$t(`schoolManages.basicSet.nowAssistanthint`)">
@@ -286,6 +286,9 @@
                   <el-button size="small" @click="nowPitchdata.size =500" disabled v-else>500</el-button>
                 </div>
               </el-form-item>
+              <el-form-item label="規模版本" class="school-form-name">
+                <el-input v-model="nowPitchdata.scaleVersion" placeholder="编辑規模版本"></el-input>
+              </el-form-item>
               <!-- <el-form-item label="学校状态:" class="school-form-state">
                     <el-switch v-model="value2" active-color="#13ce66" inactive-color="#ff4949" />
                 </el-form-item> -->
@@ -294,6 +297,7 @@
                   {{ $t(`schoolManages.basicSet.submit`) }}</el-button>
                 <!-- <el-button @click="schoolClose">{{ $t(`commonMsg.closes`) }}</el-button> -->
               </el-form-item>
+              
             </el-form>
           </div>
         </div>
@@ -416,6 +420,7 @@ export default {
       admin: '',
       type: 0,
       scale: 0,
+      edition:{}
     })
     let originalData = ref([])
     let originalNum = ref(0)
@@ -560,9 +565,12 @@ export default {
         // sortable: true,
          cellRenderer: (data) => (
           <>
+            <div style="color:#000000;" v-show={data.rowData.versions !=='基础版' && data.rowData.versions !=='标准版' && data.rowData.versions !=='专业版'}>{data.rowData.versions}</div>
             <div style="color:#e6a23c;" v-show={data.rowData.versions ==='专业版' ? true:false}>专业版</div>
             <div style="color:#67C23A;" v-show={data.rowData.versions ==='标准版' ? true:false}>标准版</div>
             <div style="color:#409EFF;" v-show={data.rowData.versions ==='基础版' ? true:false}>基础版</div>
+            
+            
           </>
         ),
       },
@@ -691,7 +699,8 @@ export default {
     const shouldFilter = ref({
       major: true,
       standard: true,
-      basics: true
+      basics: true,
+      custom: true
     })
     const popoverRef = ref()
     columns[3].headerCellRenderer = (props = HeaderCellSlotProps) => {
@@ -719,6 +728,9 @@ export default {
                     <ElCheckbox v-model={shouldFilter.value.basics} onChange={versionsEstimate}>
                       基础版
                     </ElCheckbox>
+                    <ElCheckbox v-model={shouldFilter.value.custom} onChange={versionsEstimate}>
+                      自訂版
+                    </ElCheckbox>
                   </div>
                   {/* <div class="el-table-v2__demo-filter">
                     <ElButton size="small">
@@ -785,7 +797,20 @@ export default {
         console.log(areaSelect, '当时的学区数据')
         res.state == 200 ? 
         (tableData.value = [], originalData.value = [], 
-        res.scInfos.forEach((item)=>{item.versions= item.service.includes('YPXSJ6NJ') && item.service.includes('B6V5J6NP') ? '专业版':item.service.includes('YMPCVCIM') ? '标准版':'基础版'}),
+        res.scInfos.forEach((item)=>{
+         // debugger;
+          //item.versions= item.service.includes('YPXSJ6NJ') && item.service.includes('B6V5J6NP') ? '专业版':item.service.includes('YMPCVCIM') ? '标准版':'基础版'}),
+          if (item.edition !== null) {
+                if (item.edition.scaleVersion !== null && item.edition.scaleVersion !== "") {
+                  item.versions = item.edition.scaleVersion;
+                } else {
+                  item.versions = item.service.includes('YPXSJ6NJ') && item.service.includes('B6V5J6NP') ? '专业版' : item.service.includes('YMPCVCIM') ? '标准版' : '基础版';
+                }
+              } else {
+                item.versions = item.service.includes('YPXSJ6NJ') && item.service.includes('B6V5J6NP') ? '专业版' : item.service.includes('YMPCVCIM') ? '标准版' : '基础版';
+              }
+          
+          }),
         tableData.value.push(...res.scInfos),originalNum.value = res.scInfos.length,
         originalData.value = res.scInfos,tablesccnt.value = res.allCnt) 
         : ''
@@ -800,6 +825,7 @@ export default {
     }
     //点击学校列表,详情
     function deleteRow (data, index) {
+      //debugger;
       console.log(index, 'INDEX')
       console.log(data, 'DATA')
       //处理的基础设置
@@ -813,6 +839,17 @@ export default {
       nowPitchdata.value.scale = data.scale
       nowPitchdata.value.standard = data.standard
       nowPitchdata.value.areaId = data.areaId
+      if (data.edition !== null) {
+        if (data.edition.scaleVersion !== null) {
+          nowPitchdata.value.scaleVersion = data.edition.scaleVersion;
+        } else {
+          nowPitchdata.value.scaleVersion = "";
+        }
+
+      } else {
+        nowPitchdata.value.scaleVersion = "";
+      }
+      
       nSchool.value.img = data.picture
       nSchool.value.name = data.name
       data.assists.length ? data.assists.forEach((element) => { adminvalue.value.push(element.id) }) : ''
@@ -1124,7 +1161,7 @@ export default {
           }
         }
       }
-      console.log(placeArr)
+      console.log(placeArr);
       //去重管家列表
       // assisArr.forEach((item) => {
       //   let ids = item.id
@@ -1132,7 +1169,9 @@ export default {
       //     assisArr[i].id === ids ? assisArr.splice(i, 1) : ''
       //   }
       // })
-      console.log(areaSelect.Selectvalue, nowPitchdata.value.areaId, '预计要更改和本来的')
+      
+      console.log(areaSelect.Selectvalue, nowPitchdata.value.areaId, '预计要更改和本来的');
+      
       let updateForm = {
         name: nowPitchdata.value.name,
         schoolId: nowPitchdata.value.id,
@@ -1147,7 +1186,8 @@ export default {
         city: placeArr[1],
         dist: placeArr[2],
         address: nowPitchdata.value.address,
-        modules:nowPitchdata.value.modules ==='default' ? [] :['art']
+        modules:nowPitchdata.value.modules ==='default' ? [] :['art'],
+        scaleVersion: nowPitchdata.value.scaleVersion
       }
       console.log(updateForm, '修改学校信息')
       console.log(nowPitchdata.value, '原本的学校信息')
@@ -1251,7 +1291,7 @@ export default {
       proxy.$api
         .updateSchoolphase(newData)
         .then((res) => {
-          res.state === 200 ? (ElMessage.success('保存成功'), (studyPhase.value = res.schoolInfo.id), (changebtns.value = false)) : ElMessage.error('保存失败')
+          res.state === 200 ? (ElMessage.success('保存成功'), (studyPhase.value = res.schoolInfo.id), (changebtns.value = true),store.commit('changeShowbtn', false)) : ElMessage.error('保存失败')
           loadinginfo.close()
         })
         .catch((res) => {
@@ -1467,11 +1507,49 @@ export default {
     function versionsEstimate (val) {
       console.log(shouldFilter.value)
       let arrState = shouldFilter.value
-      let marjorArr = []; let standardArr = []; let basicsArr = []
-      arrState.major ? originalData.value.forEach((item) => { item.service.includes('YPXSJ6NJ') && item.service.includes('B6V5J6NP') ? marjorArr.push(item) : '' }) : ''
-      arrState.standard ? originalData.value.forEach((item) => {item.service.includes('YMPCVCIM') && (!item.service.includes('YPXSJ6NJ') && !item.service.includes('B6V5J6NP'))  ? standardArr.push(item) : '' }) : ''
-      arrState.basics ? originalData.value.forEach((item) => { !item.service.includes('YMPCVCIM') && !item.service.includes('YPXSJ6NJ') && !item.service.includes('B6V5J6NP') ? basicsArr.push(item) : '' }) : ''
-      let versionArr = [...marjorArr, ...standardArr, ...basicsArr]
+      let marjorArr = []; let standardArr = []; let basicsArr = []; let customArr = [];
+      debugger;
+      // 專業版
+      arrState.major ? originalData.value.forEach((item) => { 
+        //debugger;
+        let scaleVersionbool = false
+        if(item.edition !== null){
+          if(item.edition.scaleVersion !== null && item.edition.scaleVersion !== ""){
+            scaleVersionbool = true;
+          }              
+        }
+        if(!scaleVersionbool){ item.service.includes('YPXSJ6NJ') && item.service.includes('B6V5J6NP') ? marjorArr.push(item) : ''; }       
+        }) : ''
+        // 標準版
+      arrState.standard ? originalData.value.forEach((item) => {
+        let scaleVersionbool = false
+        if(item.edition !== null){
+          if(item.edition.scaleVersion !== null && item.edition.scaleVersion !== ""){
+            scaleVersionbool = true;
+          }              
+        }
+        if(!scaleVersionbool){ item.service.includes('YMPCVCIM') && (!item.service.includes('YPXSJ6NJ') && !item.service.includes('B6V5J6NP'))  ? standardArr.push(item) : ''  }       
+        }) : '';
+        // 基礎版
+      arrState.basics ? originalData.value.forEach((item) => {         
+         let scaleVersionbool = false
+        if(item.edition !== null){
+          if(item.edition.scaleVersion !== null && item.edition.scaleVersion !== ""){
+            scaleVersionbool = true;
+          }              
+        }
+        if(!scaleVersionbool){ !item.service.includes('YMPCVCIM') && !item.service.includes('YPXSJ6NJ') && !item.service.includes('B6V5J6NP') ? basicsArr.push(item) : '' ; }     
+         }) : ''
+        // 自訂版
+      arrState.custom ? originalData.value.forEach((item) => {                 
+        if(item.edition !== null){
+          if(item.edition.scaleVersion !== null && item.edition.scaleVersion !== ""){
+            customArr.push(item)
+          }              
+        }        
+         }) : ''
+      
+      let versionArr = [...marjorArr, ...standardArr, ...basicsArr, ...customArr]
       console.log(versionArr, '合并结果')
       tableData.value = versionArr
       tablesccnt.value = versionArr.length

+ 1 - 1
TEAMModelBI/ClientApp/src/view/schoolServe/setschool.vue

@@ -2260,7 +2260,7 @@ export default {
 
 .form-semester-name {
   width: 55%;
-  padding-left: 2.5%;
+  /* padding-left: 2.5%; */
 }
 
 .form-semester-entrance .form-radio {

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

@@ -466,7 +466,7 @@
     <el-drawer v-model="drawer" title="历史消息" size="45%">
       <div class="center-table">
         <el-table :data="tableData" style="width: 100%" height="85vh" v-loading="loading" element-loading-text="数据加载中..." empty-text="暂无消息数据">
-          <el-table-column label="类型" align="center">
+          <!-- <el-table-column label="类型" align="center">
             <template #header>
               <el-select v-model="tableSelect.value" class="m-2" placeholder="类型选择" size="small" @change="changeTag">
                 <el-option v-for="item in tableSelect.options" :key="item.value" :label="item.label" :value="item.value" />
@@ -478,7 +478,7 @@
               <el-tag type="" effect="dark" v-if="scope.row.type ===3">提示</el-tag>
               <el-tag type="success" effect="dark" v-if="scope.row.type ===4">特殊</el-tag>
             </template>
-          </el-table-column>
+          </el-table-column> -->
           <el-table-column prop="theme" label="消息主题" align="center" />
           <el-table-column prop="content" label="消息内容" align="center" />
           <el-table-column prop="address" label="接收产品" align="center">
@@ -824,9 +824,9 @@ function pitchonly (val) {
 function sourceMsg(){
   let values=constructorData.value.source
   if(values ==='system'){
-    this.pushSystem()
+    pushSystem()
   }else{
-    this.publish()
+    publish()
   }
 }
 //发布消息

+ 9 - 9
TEAMModelBI/ClientApp/src/view/userInquire/details.vue

@@ -4,7 +4,7 @@
            <div class="img-name">
             <div class="topbox-images"><el-image src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg" fit="fill" /></div>
             <div class="topbox-name">
-                <div class="topbox-name-text">李雪晴</div>
+                <div class="topbox-name-text">{{usernames}}</div>
                 <div class="topbox-name-advance" @click="userdetailState=true">查看账户进阶数据<el-icon><MoreFilled /></el-icon></div>
             </div>
            </div>
@@ -55,7 +55,7 @@
             <div class="hiteachboxdiv">
                 <div  class="common-header-title">
                     <div>HiTeach</div>
-                    <div class="expire">到期日:2023-11-22</div>
+                    <div class="expire">到期日:XXXXX</div>
                 </div>
                 <el-divider />
                 <Hiteach></Hiteach>
@@ -63,7 +63,7 @@
             <div class="hitadiv">
                 <div  class="common-header-title">
                     <div>HiTA</div>
-                    <div class="expire">到期日:2023-11-22</div>
+                    <div class="expire">到期日:XXXXX</div>
                 </div>
                 <el-divider />
                 <HiTA></HiTA>
@@ -71,7 +71,7 @@
             <div class="user-size">
                 <div  class="common-header-title">
                     <div>空间与权益</div>
-                    <div class="expire">到期日:2023-11-22</div>
+                    <div class="expire">到期日:XXXXX</div>
                 </div>
                 <el-divider />
                 <div class="size-label">
@@ -414,11 +414,11 @@ let gaugelabels = ref([
     {id:6,value:0,title:'其他',color:'#58D9F9'},
 ])
 let rightsdata=ref([
-    { name: 'AI苏格拉底小数据', time: '2024/08/29', code: 'ais' },
-    { name: 'AI文句分析', time: '2024/10/29', code: 'diction' },
-    { name: 'AI苏格拉底小数据', time: '2024/08/29', code: 'ais' },
-    { name: 'AI苏格拉底小数据', time: '2024/08/29', code: 'ais' },
-    {name:'AI苏格拉底小数据',time:'2024/08/29',code:'ais'},
+    { name: 'XXXXXX', time: '2024/08/29', code: 'ais' },
+    { name: 'XXXXXX', time: '2024/10/29', code: 'diction' },
+    { name: 'XXXXXX', time: '2024/08/29', code: 'ais' },
+    { name: 'XXXXXX', time: '2024/08/29', code: 'ais' },
+    {name:'XXXXXX',time:'2024/08/29',code:'ais'},
 ])
 let detailsData = ref()
 detailsData.value = props.searchdata?.length > 0 ? props.searchdata : ''

+ 8 - 8
TEAMModelBI/ClientApp/src/view/userInquire/hita.vue

@@ -17,16 +17,16 @@
  import bars from '@/components/echarts/commonBar.vue'
  import * as echarts from 'echarts'
  let basicsdata = ref([
-      { title: '任务数', value: 58, key: 'frequency' },
-      { title: '作品数', value: 584, key: 'time' },
-      { title: '题目数', value: 55, key: 'assist' },
-      { title: '互动次数', value: 55, key: 'interact' },
+      { title: '任务数', value: 'XXXXX', key: 'frequency' },
+      { title: '作品数', value: 'XXXXX', key: 'time' },
+      { title: '题目数', value: 'XXXXX', key: 'assist' },
+      { title: '互动次数', value: 'XXXXX', key: 'interact' },
  ])
  let viceBasicsdata = ref([
-      { title: '协助课堂', value: 13, key: 'frequency' },
-      { title: '协助次数', value: 689, key: 'assist' },
-      { title: '协助总时长', value: 325, key: 'time' },
-      { title: '使用次数', value: 436, key: 'assist' },
+      { title: '协助课堂', value: 'XXXXX', key: 'frequency' },
+      { title: '协助次数', value: 'XXXXX', key: 'assist' },
+      { title: '协助总时长', value: 'XXXXX', key: 'time' },
+      { title: '使用次数', value: 'XXXXX', key: 'assist' },
  ])
  let echartsBar = ref({
     backgroundColor: 'rgba(255,255,255,.3)',

+ 8 - 8
TEAMModelBI/ClientApp/src/view/userInquire/hiteach.vue

@@ -24,15 +24,15 @@
             <div class="tnum-content">
                 <div class="selectbox">
                     <div><el-button v-for="item in buttonSelect" :key="item.value" :type="item.click ? 'primary':''" size="small" class="clickbox" @click="selectTime(item.value)">{{item.name}}</el-button></div>
-                    <div class="nowaday-time">时间:2023/07/05-2023/07/11</div>
+                    <div class="nowaday-time">时间:xxxxxxxx</div>
                 </div>
                 <div class="contentbox">
                     <!-- <div class="nowaday-time">时间:2023/07/05-2023/07/11</div> -->
                     <div class="nowaday">
                         <div class="nowaday-now">
-                            <div class="nows-box">T数据:<span class="now-value">9</span></div>
-                            <div class="nows-box">T绿灯:<span class="now-value">2</span></div>
-                            <div class="nows-box">双绿灯:<span class="now-value">1</span></div>
+                            <div class="nows-box">T数据:<span class="now-value">XXX</span></div>
+                            <div class="nows-box">T绿灯:<span class="now-value">XXX</span></div>
+                            <div class="nows-box">双绿灯:<span class="now-value">XXX</span></div>
                         </div>
                         <div class="nowaday-proportion">
                             <Pies :piesData="zb" ref="echartsb"></Pies>
@@ -205,10 +205,10 @@ let proportiondata = ref({
     ]
 })
 let tdatas = ref([
-    { title: '总时长(分)', value: 188, key: 'times' },
-    { title: '学生人次', value: 165, key: 'stundennum' },
-    { title: '互动次数', value: 500, key: 'interact' },
-    { title: '学生学习总时长', value: 1564, key: 'studentime' },
+    { title: '总时长(分)', value: 'XXXX', key: 'times' },
+    { title: '学生人次', value: 'XXXX', key: 'stundennum' },
+    { title: '互动次数', value: 'XXXX', key: 'interact' },
+    { title: '学生学习总时长', value: 'XXXX', key: 'studentime' },
 ])
 let splashesdata = ref({
 })

+ 3 - 3
TEAMModelBI/ClientApp/src/view/userInquire/ticket.vue

@@ -95,9 +95,9 @@
 import { ref, getCurrentInstance, watch, h, nextTick, onMounted,computed } from 'vue'
 let tabPosition=ref('left')
 let ticketdata = ref([
-    { title: '已使用', value: 5, key: 'use' },
-    { title: '未使用', value: 33, key: 'notuse' },
-    { title: '总计', value: 38, key: 'total' },
+    { title: '已使用', value: 'XXX', key: 'use' },
+    { title: '未使用', value: 'XXX', key: 'notuse' },
+    { title: '总计', value: 'XXX', key: 'total' },
 ])
 let ticketlist = ref([
     { code: '154dsf-454sdfds-545fg4d-552', scope: 'WebIRS 50人授權', source: '系统授予', time: '2023/11/22',type:'gain'},

+ 97 - 16
TEAMModelBI/Controllers/BINormal/BatchAreaController.cs

@@ -109,7 +109,7 @@ namespace TEAMModelBI.Controllers.BINormal
                 //    table = _azureStorage.GetCloudTableClient(BIConst.Global).GetTableReference("IESLogin");
                 //}
 
-                StringBuilder areaSql = new($"select c.id,c.code,c.pk,c.name,c.provCode,c.provName,c.cityCode,c.cityName,c.standard,c.standardName,c.institution,c.updateTime,c.quoteId from c");
+                StringBuilder areaSql = new($"select c.id,c.code,c.pk,c.shortCode,c.name,c.provCode,c.provName,c.cityCode,c.cityName,c.standard,c.standardName,c.institution,c.updateTime,c.quoteId,c.sokShortCode from c");
                 if (!string.IsNullOrEmpty($"{id}") && string.IsNullOrEmpty($"{name}"))
                     areaSql.Append($" where c.id='{id}'");
 
@@ -208,6 +208,7 @@ namespace TEAMModelBI.Controllers.BINormal
             try
             {
                 if (!jsonElement.TryGetProperty("name", out JsonElement name)) return BadRequest();
+                string shortCode = (jsonElement.TryGetProperty("shortCode", out JsonElement _shortCode)) ? _shortCode.GetString() : string.Empty;
                 jsonElement.TryGetProperty("provCode", out JsonElement provCode);
                 jsonElement.TryGetProperty("provName", out JsonElement provName);
                 jsonElement.TryGetProperty("cityCode", out JsonElement cityCode);
@@ -241,29 +242,38 @@ namespace TEAMModelBI.Controllers.BINormal
                 }
 
                 var activeTask = _configuration.GetValue<string>("Azure:ServiceBus:ActiveTask");//秘钥地址
-                //分开部署,就不需要,一站多用时,取消注释
-                //if ($"{site}".Equals(BIConst.Global))
-                //{
-                //    cosmosClient = _azureCosmos.GetCosmosClient(name: BIConst.Global);
-                //    tableClient = _azureStorage.GetCloudTableClient(BIConst.Global);
-                //    blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public", name: BIConst.Global);
-                //}
 
                 var table = tableClient.GetTableReference("IESLogin");
-
-                //查询新的是否存在
-                await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: $"select value(c) from c where c.standard='{standard}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
+                string queryText = $"SELECT value(c) from c ";
+                queryText += $"WHERE c.standard='{standard}'";
+                queryText += $" OR c.name='{name}'";
+                if(!string.IsNullOrWhiteSpace(shortCode)) queryText += $" OR c.shortCode='{shortCode}'";
+                await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: $"{queryText}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
                 {
+                    //查询新的是否存在
                     if (item.standard.Equals($"{standard}"))
                         return Ok(new { state = 1, message = "新创区的standard已存在请检查" });
+                    //查询新的区级名称是否存在
+                    if (item.name.Equals($"{name}"))
+                        return Ok(new { state = 1, message = "区级名称相同,请检测区级名称!" });
+                    //查询學區簡碼是否存在
+                    if (item.shortCode.Equals($"{shortCode}"))
+                        return Ok(new { state = 1, message = "此学区简码已存在请检查" });
                 }
 
+                //查询新的是否存在
+                //await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: $"select value(c) from c where c.standard='{standard}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
+                //{
+                //    if (item.standard.Equals($"{standard}"))
+                //        return Ok(new { state = 1, message = "新创区的standard已存在请检查" });
+                //}
+
                 //查询新的区级名称是否存在
-                await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: $"select value(c) from c where c.name='{name}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
-                {
-                    if (item.name.Equals($"{standard}"))
-                        return Ok(new { state = 1, message = "区级名称相同,请检测区级名称!" });
-                }
+                //await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: $"select value(c) from c where c.name='{name}'", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
+                //{
+                //    if (item.name.Equals($"{name}"))
+                //        return Ok(new { state = 1, message = "区级名称相同,请检测区级名称!" });
+                //}
 
                 //区级的ID
                 string areaId = Guid.NewGuid().ToString();
@@ -271,6 +281,7 @@ namespace TEAMModelBI.Controllers.BINormal
                 {
                     id = areaId,
                     code = $"Base-Area",
+                    shortCode = shortCode,
                     name = $"{name}",
                     provCode = $"{provCode}",
                     provName = $"{provName}",
@@ -623,6 +634,75 @@ namespace TEAMModelBI.Controllers.BINormal
             }
         }
 
+        /// <summary>
+        /// 修改學區
+        /// </summary>
+        /// <param name="jsonElement"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [AuthToken(Roles = "admin,rdc")]
+        [HttpPost("upd-area")]
+        public async Task<IActionResult> updArea(JsonElement jsonElement)
+        {
+            try
+            {
+                if (!jsonElement.TryGetProperty("id", out JsonElement _id)) return BadRequest();
+                string id = _id.GetString();
+                string shortCode = (jsonElement.TryGetProperty("shortCode", out JsonElement _shortCode)) ? _shortCode.GetString() : string.Empty;
+                string name = (jsonElement.TryGetProperty("name", out JsonElement _name)) ? _name.GetString() : string.Empty;
+                if(string.IsNullOrWhiteSpace(shortCode) && string.IsNullOrWhiteSpace(name))
+                {
+                    return Ok(new { state = 1, message = "输入值有误,请检查输入值" });
+                }
+                var cosmosClient = _azureCosmos.GetCosmosClient();//数据库连接
+                //學區取得
+                Area area = await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<Area>(id, new PartitionKey($"Base-Area"));
+                //輸入值重複檢驗
+                string queryText = $"SELECT value(c) from c ";
+                string queryWhere = string.Empty;
+                if (!string.IsNullOrWhiteSpace(name))
+                {
+                    if (!string.IsNullOrWhiteSpace(queryWhere)) queryWhere += " OR ";
+                    queryWhere += $"c.name='{name}'";
+                }
+                if (!string.IsNullOrWhiteSpace(shortCode))
+                {
+                    if (!string.IsNullOrWhiteSpace(queryWhere)) queryWhere += " OR ";
+                    queryWhere += $"c.shortCode='{shortCode}'";
+                }
+                queryWhere = $"WHERE ({queryWhere}) AND c.id != '{id}'";
+                queryText = $"{queryText}{queryWhere}";
+                await foreach (var item in cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: $"{queryText}", requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey($"Base-Area") }))
+                {
+                    //查询区级名称是否存在
+                    if (item.name.Equals($"{name}"))
+                        return Ok(new { state = 1, message = "区级名称相同,请检测区级名称!" });
+                    //查询學區簡碼是否存在
+                    if (item.shortCode.Equals($"{shortCode}"))
+                        return Ok(new { state = 1, message = "此学区简码已存在请检查" });
+                }
+                //DB值更新
+                if (!string.IsNullOrWhiteSpace(name)) area.name = name;
+                if (!string.IsNullOrWhiteSpace(shortCode)) area.shortCode = shortCode;
+                await cosmosClient.GetContainer(Constant.TEAMModelOS, "Normal").ReplaceItemAsync<Area>(area, id);
+                //保存操作记录
+                var (_tmdId, _tmdName, pic, did, dname, dpic) = HttpJwtAnalysis.JwtXAuthBI(HttpContext.GetXAuth("AuthToken"), _option);
+                var tableClient = _azureStorage.GetCloudTableClient();
+                var blobClient = _azureStorage.GetBlobContainerClient(containerName: "0-public");
+                string BILogContent = string.Empty;
+                BILogContent += $"学区ID:{id}, 更新资料: ";
+                if (!string.IsNullOrWhiteSpace(name)) BILogContent += $"name:{name}, ";
+                if (!string.IsNullOrWhiteSpace(shortCode)) BILogContent += $"shortCode:{shortCode}, ";
+                await AzureStorageBlobExtensions.SaveBILog(blobClient, tableClient, "upd-area", $"{_tmdName}【{_tmdId}】已更新學區資料 {BILogContent}", _dingDing, httpContext: HttpContext);
+                return Ok(new { state = 200, area = area });
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"BI,{_option.Location}  /batcharea/upd-area \n {ex.Message}\n{ex.StackTrace}", GroupNames.成都开发測試群組);
+                return BadRequest();
+            }
+        }
+
         /// <summary>
         /// 创区后切换能力点, 先删除原来的能力点,后复制新的能力点     //已对接
         /// </summary>
@@ -1288,6 +1368,7 @@ namespace TEAMModelBI.Controllers.BINormal
             public string id { get; set; }
             public string code { get; set; }
             public string pk { get; set; }
+            public string shortCode { get; set; }
             public string name { get; set; }
             public string provCode { get; set; }
             public string provName { get; set; }

+ 29 - 16
TEAMModelBI/Controllers/BISchool/BatchSchoolController.cs

@@ -193,6 +193,8 @@ namespace TEAMModelBI.Controllers.BISchool
                         if (createSchoolInfo.id != null)
                         {
                             string campusId = Guid.NewGuid().ToString();
+                            TEAMModelOS.SDK.Models.Edition edition = new();
+                            edition.scaleVersion = bischool.scaleVersion;
                             School upSchool = new()
                             {
                                 id = createSchoolInfo.id,
@@ -216,9 +218,10 @@ namespace TEAMModelBI.Controllers.BISchool
                                 period = PresetSchoolPeriod(bischool.period, foundSchools.lang, campusId),
                                 scale = bischool.size >= 300 ? 500 : 0,
                                 isinit = true,
-                                modules=bischool.modules,
+                                //modules=bischool?.modules,
                                 openLessonRecord = (_option.Location.Contains("Global")) ? false : true,
                                 createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                                edition = edition
 
                             };
                             scInfos.Add(createSchoolInfo);
@@ -1046,15 +1049,17 @@ namespace TEAMModelBI.Controllers.BISchool
                 jsonElement.TryGetProperty("address", out JsonElement address);
                 string code = (jsonElement.TryGetProperty("code", out JsonElement _code))? _code.GetString() : string.Empty;
                 jsonElement.TryGetProperty("assist", out JsonElement assist);
-                List<string> modules = null ;
-                if (!jsonElement.TryGetProperty("modules ", out JsonElement _modules))
-                {
-                    return BadRequest();
-                }
-                else {
-                    modules= _modules.ToObject<List<string>>();
-                }
-              
+                jsonElement.TryGetProperty("scaleVersion", out JsonElement scaleVersion);
+                //手動追加商業模組的部分先封印,商業模組需要經過訂單系統下單控管。
+                //List<string> modules = null ;
+                //if (!jsonElement.TryGetProperty("modules ", out JsonElement _modules))
+                //{
+                //    return BadRequest();
+                //}
+                //else {
+                //    modules= _modules.ToObject<List<string>>();
+                //}
+
                 List<IdInfo> idInfos = assist.ToObject<List<IdInfo>>();
                 //jsonElement.TryGetProperty("site", out JsonElement site);//分开部署,就不需要,一站多用时,取消注释
 
@@ -1085,9 +1090,9 @@ namespace TEAMModelBI.Controllers.BISchool
                         //});
 
                         //tempShool.period = periods;
-                        if (modules!=null) {
-                            tempShool.modules=modules;
-                        }
+                        //if (modules!=null) {
+                        //    tempShool.modules=modules;
+                        //}
                         tempShool.size = !string.IsNullOrEmpty($"{size}") ? int.Parse($"{size}") : tempShool.size;
                         tempShool.scale = !string.IsNullOrEmpty($"{scale}") ? int.Parse($"{scale}") : tempShool.scale;
                         tempShool.picture = $"{picture}";
@@ -1099,6 +1104,7 @@ namespace TEAMModelBI.Controllers.BISchool
                         tempShool.city = string.IsNullOrEmpty($"{city}") ? tempShool.city : $"{city}";
                         tempShool.dist = string.IsNullOrEmpty($"{dist}") ? tempShool.dist : $"{dist}";
                         tempShool.address = string.IsNullOrEmpty($"{address}") ? tempShool.address : $"{address}";
+                        
                         //計算學校版本
                         List<SchoolProductSumData> services = new List<SchoolProductSumData>();
                         Azure.Response productSumResponse = await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync($"{_schoolId}", new PartitionKey("ProductSum"));
@@ -1111,12 +1117,14 @@ namespace TEAMModelBI.Controllers.BISchool
                             }
                         }
                         tempShool.edition = BISchoolService.calSchoolEdition(tempShool, services.Select(s => s.prodCode).ToList());
+                        //tempShool.edition.scaleVersion = string.IsNullOrEmpty($"{scaleVersion}") ? tempShool.edition.scaleVersion : $"{scaleVersion}";
+                        tempShool.edition.scaleVersion = ($"{scaleVersion}" == null) ? tempShool.edition.scaleVersion : $"{scaleVersion}";
 
                         //修改学校
                         await cosmosClient.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<School>(tempShool, tempShool.id, new PartitionKey("Base"));
 
                         //创建学校信息中间件
-                        //await BIStats.SetSchoolBIRelation(cosmosClient, blobClient, tableClient, _dingDing, tempShool);
+                        await BIStats.SetSchoolBIRelation(cosmosClient, blobClient, tableClient, _dingDing, tempShool);
 
                         //修改学校教师关联的信息
                         string sql = $"SELECT distinct value(c) FROM c join A1 in c.schools where A1.schoolId='{tempShool.id}'";
@@ -1168,7 +1176,7 @@ namespace TEAMModelBI.Controllers.BISchool
                         biRel.scale = tempShool.scale;
                         biRel.upDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                         biRel.areaName = aName;
-                        biRel.edition = tempShool.edition;
+                        biRel.edition = tempShool.edition;                                                
                         if (idInfos.Count > 0)
                         {
                             foreach (var item in idInfos)
@@ -1971,10 +1979,15 @@ namespace TEAMModelBI.Controllers.BISchool
             /// </summary>
             public string standard { get; set; }
             /// <summary>
+            /// 規模版本
+            /// </summary>
+            public string scaleVersion { get; set; }
+            /// <summary>
             /// 手动增加的模块 ["art"]
             /// </summary>
-            public List<string> modules { get; set; } = new List<string>();
+            //public List<string> modules { get; set; } = new List<string>();
         }
+        
 
         /// <summary>
         /// 学段类型和学段名称

+ 129 - 17
TEAMModelBI/Controllers/BITmid/TmidController.cs

@@ -6,6 +6,7 @@ using Microsoft.Extensions.Options;
 using System;
 using System.Collections.Generic;
 using System.Linq;
+using System.Reflection;
 using System.Text.Json;
 using System.Threading.Tasks;
 using TEAMModelOS.Models;
@@ -55,6 +56,10 @@ namespace TEAMModelBI.Controllers.BITmid
                 if (!jsonElement.TryGetProperty("tmids", out JsonElement tmidsJobj)) return BadRequest();//TMID(array)
                 var tmids = tmidsJobj.Deserialize<List<string>>();
                 if (tmids.Count is 0) return BadRequest();
+                var datetime = DateTimeOffset.UtcNow.AddDays(-1);
+                var y = datetime.Year;
+                var m = datetime.Month;
+                var d = datetime.Day;
 
                 //服務Client端
                 var cosmosClientIes5 = _azureCosmos.GetCosmosClient(); //CosmosDB IES5
@@ -121,7 +126,13 @@ namespace TEAMModelBI.Controllers.BITmid
                             //個人服務授權
                             tmidStics.prod = await getTMIDAuthService(cosmosClientCsv2, id, "", true);
 
-                            
+                            //IOT
+                            tmidStics.iot.hiteach.year = await getTMIDIotData(cosmosClientIes5, id, "HiTeach", "year", y, 0, 0, 0, 0);
+                            tmidStics.iot.hiteach.month = await getTMIDIotData(cosmosClientIes5, id, "HiTeach", "month", y, m, 0, 0, 0);
+                            tmidStics.iot.hiteach.day = await getTMIDIotData(cosmosClientIes5, id, "HiTeach", "day", y, m, d, 0, 0);
+                            tmidStics.iot.hiteachcc.year = await getTMIDIotData(cosmosClientIes5, id, "HiTeachCC", "year", y, 0, 0, 0, 0);
+                            tmidStics.iot.hiteachcc.month = await getTMIDIotData(cosmosClientIes5, id, "HiTeachCC", "month", y, m, 0, 0, 0);
+                            tmidStics.iot.hiteachcc.day = await getTMIDIotData(cosmosClientIes5, id, "HiTeachCC", "day", y, m, d, 0, 0);
 
                             tmidDic.Add(id, tmidStics);
                         }
@@ -288,6 +299,31 @@ namespace TEAMModelBI.Controllers.BITmid
                     }
                 }
 
+                //個人權益
+                query = new QueryDefinition(@"SELECT * FROM c WHERE (ARRAY_CONTAINS(@key, c.id))")
+                      .WithParameter("@key", tmidDic.Keys.ToList());
+                await foreach (var item in cosmosClientCsv2
+                            .GetContainer("Core", "ID2")
+                            .GetItemQueryStreamIterator(query, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("benefits") }))
+                {
+                    using var json = await JsonDocument.ParseAsync(item.ContentStream);
+                    if (json.RootElement.TryGetProperty("_count", out JsonElement count) && count.GetUInt16() > 0)
+                    {
+                        foreach (var doc in json.RootElement.GetProperty("Documents").EnumerateArray())
+                        {
+                            string id = doc.GetProperty("id").GetString();
+                            if (doc.TryGetProperty("hiteach", out var elementHiteachData))
+                            {
+                                tmidDic[id].benefits.hiteach = elementHiteachData.ToObject<List<object>>();
+                            }
+                            if (doc.TryGetProperty("hiteachcc", out var elementHiteachCCData))
+                            {
+                                tmidDic[id].benefits.hiteachcc = elementHiteachCCData.ToObject<List<object>>();
+                            }
+                        }
+                    }
+                }
+
                 //蘇格拉底資料
                 query = new QueryDefinition(@"SELECT * FROM c WHERE (ARRAY_CONTAINS(@key, c.id))")
                       .WithParameter("@key", tmidDic.Keys.ToList());
@@ -303,15 +339,11 @@ namespace TEAMModelBI.Controllers.BITmid
                             string id = doc.GetProperty("id").GetString();
                             if (doc.TryGetProperty("hiteach_data", out var elementHiteachData))
                             {
-                                if (elementHiteachData.TryGetProperty("total", out var elementTotal))
-                                {
-                                    if (elementTotal.TryGetProperty("t_data", out var tDataValue)) tmidDic[id].sokrates.t_data = tDataValue.GetString();
-                                    if (elementTotal.TryGetProperty("t_green", out var tGreenValue)) tmidDic[id].sokrates.t_green = tGreenValue.GetString();
-                                    if (elementTotal.TryGetProperty("duration", out var durationValue)) tmidDic[id].sokrates.duration = durationValue.GetString();
-                                    if (elementTotal.TryGetProperty("attendance", out var attendanceValue)) tmidDic[id].sokrates.attendance = attendanceValue.GetString();
-                                    if (elementTotal.TryGetProperty("interaction", out var interactionValue)) tmidDic[id].sokrates.interaction = interactionValue.GetString();
-                                    if (elementTotal.TryGetProperty("learning_duration", out var learningDurationValue)) tmidDic[id].sokrates.learning_duration = learningDurationValue.GetString();
-                                }
+                                tmidDic[id].sokrates.hiteach_data = elementHiteachData.ToObject<object>();
+                            }
+                            if (doc.TryGetProperty("user_channels", out var elementUserChannels))
+                            {
+                                tmidDic[id].sokrates.user_channels = elementUserChannels.ToObject<object>();
                             }
                         }
                     }
@@ -449,6 +481,56 @@ namespace TEAMModelBI.Controllers.BITmid
             return data;
         }
 
+        public async Task<TmidAnalysisCal> getTMIDIotData(CosmosClient cosmosClientIes5, string tmid, string toolType, string dateUnit, int year, int month, int day, long from, long to)
+        {
+            TmidAnalysisCal result = new TmidAnalysisCal();
+            List<string> calPropList = new List<string>() { "lessonRecord", "useIES", "useIES5Resource", "useWebIrs", "useDeviceIrs", "useHaboard", "useHita", "lessonLengMin", "lessonLeng0", "stuShow", "stuLessonLengMin", "tGreen", "lTypeCoop", "lTypeIact", "lTypeMis", "lTypeTst", "lTypeDif", "lTypeNone", "lessonCnt928", "lessonCntId", "lessonCntDevice", "lessonCntIdDevice", "mission", "missionFin", "item", "interact", "sendSok" }; //要計算的ProdAnalysis欄位列表
+            string strQuery = $"SELECT * FROM c WHERE c.tmid = '{tmid}' AND c.toolType = '{toolType}'";
+            var qryOption = new QueryRequestOptions() { PartitionKey = new PartitionKey("TmidAnalysis") };
+            if (!string.IsNullOrWhiteSpace(dateUnit)) strQuery += $" AND c.dateUnit = '{dateUnit}'";
+            if (year > 0) strQuery += $" AND c.year = {year}";
+            if (month > 0) strQuery += $" AND c.month = {month}";
+            if (day > 0) strQuery += $" AND c.day = {day}";
+            if (from > 0) strQuery += $" AND c.dateTime >= {from}";
+            if (to > 0) strQuery += $" AND c.dateTime <= {to}";
+
+            await foreach (TmidAnalysisCosmos tmidAnalysis in cosmosClientIes5.GetContainer(Constant.TEAMModelOS, "Teacher").GetItemQueryIterator<TmidAnalysisCosmos>(strQuery, null, qryOption))
+            {
+                //一般項
+                result.tmid = tmidAnalysis.tmid;
+                result.dateUnit = tmidAnalysis.dateUnit;
+                result.toolType = tmidAnalysis.toolType;
+                result.date = tmidAnalysis.date;
+                if (tmidAnalysis.year > 0) result.year = tmidAnalysis.year;
+                if (tmidAnalysis.month > 0) result.month = tmidAnalysis.month;
+                if (tmidAnalysis.day > 0) result.day = tmidAnalysis.day;
+                if (result.from.Equals(0) || tmidAnalysis.dateTime <= result.from) result.from = tmidAnalysis.dateTime;
+                if (result.to.Equals(0) || tmidAnalysis.dateTime >= result.to) result.to = tmidAnalysis.dateTime;
+                //統計項
+                foreach (PropertyInfo propertyInfo in tmidAnalysis.GetType().GetProperties()) //累加項目
+                {
+                    if (calPropList.Contains(propertyInfo.Name))
+                    {
+                        var propType = propertyInfo.PropertyType;
+                        var valNow = propertyInfo.GetValue(result);
+                        var valTodo = tmidAnalysis.GetType().GetProperty(propertyInfo.Name).GetValue(tmidAnalysis);
+                        if (propType.Equals(typeof(long))) propertyInfo.SetValue(result, Convert.ToInt64(valNow.ToString(), 10) + Convert.ToInt64(valTodo.ToString(), 10));
+                        else propertyInfo.SetValue(result, Convert.ToInt32(valNow.ToString(), 10) + Convert.ToInt32(valTodo.ToString(), 10));
+                    }
+                }
+                result.deviceList = result.deviceList.Union(tmidAnalysis.deviceList).ToList();
+                result.deviceCnt = result.deviceList.Count;
+                result.deviceNoAuthList = result.deviceNoAuthList.Union(tmidAnalysis.deviceNoAuthList).ToList();
+                result.deviceNoAuth = result.deviceNoAuthList.Count;
+                result.deviceAuthList = result.deviceAuthList.Union(tmidAnalysis.deviceAuthList).ToList();
+                result.deviceAuth = result.deviceAuthList.Count;
+                result.tmidList = result.tmidList.Union(tmidAnalysis.tmidList).ToList();
+                result.tmidCnt = result.tmidList.Count;
+            }
+            if (string.IsNullOrWhiteSpace(result.tmid)) result = null;
+            return result;
+        }
+
         //Model
 
         //TMID統計 基本資訊
@@ -466,9 +548,11 @@ namespace TEAMModelBI.Controllers.BITmid
             public TmidSticsIes5 ies5 { get; set; } = new(); //IES統計資料
             public TmidPoints points { get; set; } = new();
             public TmidSokrates sokrates { get; set; } = new();
+            public TmidBenefits benefits { get; set; } = new();
             public List<TmidCoupon> coupons { get; set; } = new();
             public List<TmidLoginTime> login { get; set; } = new();
             public List<object> prod { get; set; } = new();
+            public TmidIot iot { get; set; } = new();
         }
         //TMID統計 IES5資訊
         private class TmidSticsIes5
@@ -513,12 +597,24 @@ namespace TEAMModelBI.Controllers.BITmid
         }
         private class TmidSokrates
         {
-            public string t_data { get; set; }
-            public string t_green { get; set; }
-            public string duration { get; set; }
-            public string attendance { get; set; }
-            public string interaction { get; set; }
-            public string learning_duration { get; set; }
+            public object hiteach_data { get; set; }
+            public object user_channels { get; set; }
+        }
+        private class TmidBenefits
+        {
+            public List<object> hiteach { get; set; }
+            public List<object> hiteachcc { get; set; }
+        }
+        private class TmidIot
+        {
+            public TmidIotYMD hiteach { get; set; } = new();
+            public TmidIotYMD hiteachcc { get; set; } = new();
+        }
+        private class TmidIotYMD
+        {
+            public TmidAnalysisCal year  { get; set; }
+            public TmidAnalysisCal month { get; set; }
+            public TmidAnalysisCal day { get; set; }
         }
 
         //[API輸出] 訂單履歷 
@@ -612,6 +708,22 @@ namespace TEAMModelBI.Controllers.BITmid
             { "044482b5-d024-4f23-9b55-906884243405", "IRS" },
             { "5e27b7e3-b36c-4ce9-b838-e94fd0cea080", "IRS" }
         };
+
+        //TMID IOT date
+        public class tmidIotDate
+        {
+            public string dateUnit { get; set; } //[string]日期單位:年月日 year, month, day
+            public int year { get; set; } //[Int]年
+            public int month { get; set; } //[Int]月
+            public int day { get; set; } //[Int]日
+            public long from { get; set; } //[long]UTC timestamp 起始日
+            public long to { get; set; } //[long]UTC timestamp 終止日
+        }
+        public class TmidAnalysisCal : TmidAnalysisCosmos
+        {
+            public long from { get; set; } //[long]UTC timestamp 起始日
+            public long to { get; set; } //[long]UTC timestamp 終止日
+        }
     }
-    
+
 }

+ 3 - 3
TEAMModelBI/TEAMModelBI.csproj

@@ -65,9 +65,9 @@
 		<SpaRoot>ClientApp\</SpaRoot>
 		<DefaultItemExcludes>$(DefaultItemExcludes);$(SpaRoot)node_modules\**</DefaultItemExcludes>
 		<UserSecretsId>078b5d89-7d90-4f6a-88fc-7d96025990a8</UserSecretsId>
-		<Version>5.2309.27</Version>
-		<AssemblyVersion>5.2309.27.1</AssemblyVersion>
-		<FileVersion>5.2309.27.1</FileVersion>
+		<Version>5.2310.11</Version>
+		<AssemblyVersion>5.2310.11.1</AssemblyVersion>
+		<FileVersion>5.2310.11.1</FileVersion>
 		<Description>TEAMModelBI(BI)</Description>
 		<PackageReleaseNotes>BI版本说明版本切换标记2022000908</PackageReleaseNotes>
 		<PackageId>TEAMModelBI</PackageId>

+ 4 - 4
TEAMModelBI/appsettings.Development.json

@@ -109,18 +109,18 @@
     "proDeptId": 67690917
   },
   "CoreServiceV1": {
-	"Cosmos": {
+    "Cosmos": {
       "ConnectionString": "AccountEndpoint=https://corecosmosdbcn.documents.azure.cn:443/;AccountKey=WIFUWgnC6HiPb4yYba5iLR4ZghcA2fqrEvnX00YTA5B4sd7o89sxtbvgFDDUqT2VRkeWrWVTWZ8VbApQtwkJKQ==;" //CSV1大陸正式站(唯讀)
     }
   },
   "CoreServiceV2": {
-	"Cosmos": {
+    "Cosmos": {
       "ConnectionString": "AccountEndpoint=https://teammodelostest.documents.azure.cn:443/;AccountKey=ReGoiHuTbU4Q31YYq4NaiormE6Ci71piT7OrvTzAuhrlgt63ajdtDZmwOZKzcz6gnwR326mJp53InY7rohepQQ==;" //CSV2大陸測試站(讀寫)
     },
-	"Storage": {
+    "Storage": {
       "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodeltest;AccountKey=O2W2vadCqexDxWO+px+QK7y1sHwsYj8f/WwKLdOdG5RwHgW/Dupz9dDUb4c1gi6ojzQaRpFUeAAmOu4N9E+37A==;EndpointSuffix=core.chinacloudapi.cn" //CSV2大陸測試站
     },
-	"CosmosCnRead": {
+    "CosmosCnRead": {
       "ConnectionString": "AccountEndpoint=https://corecosmosdb.documents.azure.cn:443/;AccountKey=12C5n8IvXFqsPARUb2YBOUWiU9PksohESlLHgH6cAVajxWBBJIJ6chJusgfrYhxCKgQgSHHxVgHsFPRakhvlPw==;" //CSV2大陸正式站(唯讀)
     }
   }

+ 89 - 28
TEAMModelOS.FunctionV4/CosmosDB/TriggerArt.cs

@@ -417,7 +417,7 @@ namespace TEAMModelOS.FunctionV4.CosmosDB
                                     knoledge.Add(await getKnowledge(art.periodType, exams.Where(c => c.subjects[0].id.Equals(ss.id))?.FirstOrDefault().papers[0].code, client, ss.id, exams.Where(c => c.subjects[0].id.Equals(ss.id))?.FirstOrDefault().papers[0].periodId));
                                 }
 
-                                List<(string name, double score, double aver,string subject)> blockScore = new();
+                                List<(string name, double score, double aver, string subject)> blockScore = new();
                                 List<(List<(string name, double score, double point, string subject)> studentScore, string stuId)> studentScores = new();
                                 foreach (var exam in exams)
                                 {
@@ -456,9 +456,10 @@ namespace TEAMModelOS.FunctionV4.CosmosDB
                                     //List<(string name, double score, string subject)> pointScore = new();
                                     List<string> stus = examClassResults.Where(c => c.examId.Equals(exam.id)).SelectMany(z => z.studentIds).ToList();
                                     List<List<double>> stuScores = examClassResults.Where(c => c.examId.Equals(exam.id)).SelectMany(z => z.studentScores).ToList();
-                                    foreach (string id in stus) {
+                                    foreach (string id in stus)
+                                    {
                                         //double scores = 0;
-                                        List<(string name, double score, double point,string subject)> studentScore = new();
+                                        List<(string name, double score, double point, string subject)> studentScore = new();
                                         for (int k = 0; k < knowledgeName.Count; k++)
                                         {
                                             int n = 0;
@@ -474,13 +475,13 @@ namespace TEAMModelOS.FunctionV4.CosmosDB
                                                     if (stuScores[index][n] > 0)
                                                     {
                                                         scores += stuScores[index][n] * itemPersent;
-                                                   }
+                                                    }
                                                 }
                                                 n++;
                                             });
-                                            studentScore.Add((knowledgeName[k], Math.Round(scores,2), OnePoint, exam.subjects[0].id));                                           
+                                            studentScore.Add((knowledgeName[k], Math.Round(scores, 2), OnePoint, exam.subjects[0].id));
                                         }
-                                        studentScores.Add((studentScore,id));
+                                        studentScores.Add((studentScore, id));
                                     }
                                     for (int k = 0; k < knowledgeName.Count; k++)
                                     {
@@ -505,7 +506,7 @@ namespace TEAMModelOS.FunctionV4.CosmosDB
                                             n++;
                                         });
                                         double sc = stus.Count > 0 ? Math.Round(scores * 1.0 / stus.Count, 2) : 0;
-                                        blockScore.Add((knowledgeName[k], OnePoint,sc, exam.subjects[0].id));
+                                        blockScore.Add((knowledgeName[k], OnePoint, sc, exam.subjects[0].id));
                                         //blockScore.AddRange(pointScore);
                                     }
                                 }
@@ -520,12 +521,19 @@ namespace TEAMModelOS.FunctionV4.CosmosDB
                                     })
                                 });
                                 var subjectKnow = knoledge.Where(c => c.ptype.Equals(art.periodType)).Select(x => new { x.subId, x.knos }).ToList();
-                                List<(string subjectId, List<(string name, double score,double persent,double aver, List<string> dim)> bks)> bs = new();
+                                List<(string subjectId, List<(string name, double score, double persent, double aver, List<string> dim)> bks)> bs = new();
+                                List<(string subjectId, List<(string stuId, List<(string name, double score, double point, List<string> dim)> values)> stuBks)> sbs = new();
+                                List<(string name, double score, double av, string sId)> stuBlockScore = new();
                                 foreach (var bb in subjectKnow)
                                 {
                                     var kno1 = bls.Where(c => c.subjectId.Equals(bb.subId)).SelectMany(x => x.knoScore).ToList();
+                                    var stuInfo = studentScores.Select(c => new
+                                    {
+                                        c.stuId,
+                                        subInfo = c.studentScore.Where(x => x.subject.Equals(bb.subId)).ToList()
+                                    }).Where(z => z.subInfo.Count > 0).ToList();
                                     //var kno2 = dimensions.Where(c => c.subjectBind.Equals(bb.subId)).Select(x => new { x.dimension,x.blocks}).ToList();
-                                    List<(string name, double score,double aver)> blockScores = new();
+                                    List<(string name, double score, double aver)> blockScores = new();
                                     foreach (var k2 in bb.knos)
                                     {
                                         double bsc = 0;
@@ -538,22 +546,58 @@ namespace TEAMModelOS.FunctionV4.CosmosDB
                                                 avs += k3.aver;
                                             }
                                         }
-                                        blockScores.Add((k2.name, bsc,avs));
+                                        foreach (var stu in stuInfo)
+                                        {
+                                            double realScore = 0;
+                                            double realPoint = 0;
+                                            foreach (var subScore in stu.subInfo)
+                                            {
+                                                if (null != k2.kno && k2.kno.Contains(subScore.name))
+                                                {
+                                                    realScore = subScore.score;
+                                                    realPoint = subScore.point;
+                                                }                                             
+                                            }
+                                            stuBlockScore.Add((k2.name, realScore, realPoint, stu.stuId));
+                                        }
+                                        blockScores.Add((k2.name, bsc, avs));
                                     }
+
+
+                                    var stuBlock = stuBlockScore.GroupBy(x => (x.sId)).Select(c => new
+                                    {
+                                        stuId = c.Key,
+                                        block = c.ToList().GroupBy(b => b.name).Select(q => new
+                                        {
+                                            name = q.Key,
+                                            score = q.ToList().Sum(q => q.score),
+                                            point = q.ToList().Sum(q => q.av),
+                                            dimension = setting.dimensions.Where(s => s.blocks.Contains(q.Key)).Select(x => x.dimension).ToList()
+                                        })
+                                    }).ToList() ;
                                     var blk = blockScores.Select(x => new
                                     {
                                         x.name,
                                         x.score,
-                                        persent = Math.Round( x.aver > 0 ? x.aver / x.score : 0,2),
+                                        persent = Math.Round(x.aver > 0 ? x.aver / x.score : 0, 2),
                                         x.aver,
                                         dimension = setting.dimensions.Where(s => s.blocks.Contains(x.name)).Select(x => x.dimension)
                                     });
-                                    List<(string name, double score, double persent,double aver,List<string> dim)> bks = new();
+                                    List<(string name, double score, double persent, double aver, List<string> dim)> bks = new();
+                                    List<(string stuId, List<(string name, double score, double point, List<string> dim)> values)> stuBks = new();
                                     foreach (var bk in blk)
                                     {
-                                        bks.Add((bk.name, bk.score,bk.persent, bk.aver,bk.dimension.ToList()));
+                                        bks.Add((bk.name, bk.score, bk.persent, bk.aver, bk.dimension.ToList()));
+                                    }
+                                    foreach (var stuBlk in stuBlock) {
+                                        List<(string name, double score, double point, List<string> dim)> values = new();
+                                        foreach (var lk in stuBlk.block) {
+                                            values.Add((lk.name,lk.score,lk.point,lk.dimension));
+                                        }
+                                        stuBks.Add((stuBlk.stuId, values));
                                     }
                                     bs.Add((bb.subId, bks));
+                                    sbs.Add((bb.subId, stuBks));
                                 }
 
                                 var blocks = bs.Select(x => new
@@ -568,16 +612,31 @@ namespace TEAMModelOS.FunctionV4.CosmosDB
                                         z.dim
                                     })
                                 });
+                                var stuBlocks = sbs.Select(x => new { 
+                                    x.subjectId,
+                                    dim = x.stuBks.Select(z => new { 
+                                        z.stuId,
+                                        blk = z.values.Select(c => new { 
+                                            c.name,
+                                            c.score,
+                                            c.point,
+                                            c.dim
+                                        })
+                                    })
+                                });
                                 //获取维度得分率
-                                var dim = setting.dimensions.GroupBy(a => a.subjectBind).Select(x => new {
+                                var dim = setting.dimensions.GroupBy(a => a.subjectBind).Select(x => new
+                                {
                                     x.Key,
-                                    dim =  x.ToList().Select(c => new { 
+                                    dim = x.ToList().Select(c => new
+                                    {
                                         c.dimension,
-                                        persent = Math.Round( c.blocks.Select(z => new {
-                                            persent = Math.Round( bs.Where(z => z.subjectId.Equals(x.Key)).SelectMany(k => k.bks).Where(q => q.name.Equals(z)).Sum(h => h.score) > 0 ?
-                                            bs.Where(z => z.subjectId.Equals(x.Key)).SelectMany(k => k.bks).Where(q => q.name.Equals(z)).Sum(h => h.aver )  /
-                                            bs.Where(z => z.subjectId.Equals(x.Key)).SelectMany(k => k.bks).Where(q => q.name.Equals(z)).Sum(h => h.score) : 0 ,2)
-                                        }).Sum(o => o.persent) / c.blocks.Count,2)
+                                        persent = Math.Round(c.blocks.Select(z => new
+                                        {
+                                            persent = Math.Round(bs.Where(z => z.subjectId.Equals(x.Key)).SelectMany(k => k.bks).Where(q => q.name.Equals(z)).Sum(h => h.score) > 0 ?
+                                            bs.Where(z => z.subjectId.Equals(x.Key)).SelectMany(k => k.bks).Where(q => q.name.Equals(z)).Sum(h => h.aver) /
+                                            bs.Where(z => z.subjectId.Equals(x.Key)).SelectMany(k => k.bks).Where(q => q.name.Equals(z)).Sum(h => h.score) : 0, 2)
+                                        }).Sum(o => o.persent) / c.blocks.Count, 2)
                                     })
                                 });
 
@@ -662,15 +721,17 @@ namespace TEAMModelOS.FunctionV4.CosmosDB
                                             score = rs.subjectScores.Where(x => x.subjectId.Equals(sj.id)).FirstOrDefault().score,
                                             time = art.startTime,
                                             totalScore = 100,
-                                            id = sj.id,
-                                            block = blocks.Where(c => c.subjectId.Equals(sj.id))?.FirstOrDefault().dim,
+                                            id = sj.id,  
+                                            type = sj.id,
+                                            block = stuBlocks.Where(c => c.subjectId.Equals(sj.id)).SelectMany(x => x.dim).Where(z => z.stuId.Equals(rs.studentId)).FirstOrDefault().blk,
                                             kno = studentScores.Where(c => c.stuId.Equals(rs.studentId)).SelectMany(c => c.studentScore).Where(
-                                                p => p.subject.Equals(sj.id)).Select(z => new { 
-                                                z.name,
-                                                z.score,
-                                                z.point,
-                                                block = subjectKnow.Where(v => v.subId.Equals(sj.id)).SelectMany(k => k.knos).Where(c => null != c.kno && c.kno.Contains(z.name)).Select(x => x.name)
-                                            }),
+                                                p => p.subject.Equals(sj.id)).Select(z => new
+                                                {
+                                                    z.name,
+                                                    z.score,
+                                                    z.point,
+                                                    block = subjectKnow.Where(v => v.subId.Equals(sj.id)).SelectMany(k => k.knos).Where(c => null != c.kno && c.kno.Contains(z.name)).Select(x => x.name)
+                                                }),
                                             dim = dim.Where(c => c.Key.Equals(sj.id))?.FirstOrDefault().dim
                                         };
                                         index++;

+ 8 - 1
TEAMModelOS.FunctionV4/CosmosDB/TriggerExam.cs

@@ -507,7 +507,7 @@ namespace TEAMModelOS.FunctionV4
                                                     score = subScore.Where(c => c.subjectId.Equals(sj.id)).FirstOrDefault().score,
                                                     time = info.startTime,
                                                     totalScore = info.papers[index].point.Sum(),
-                                                    //type = sj.id
+                                                    type = sj.id
                                                 };
                                                 index++;
                                                 semesterData.itemScore.Add(item);
@@ -1542,6 +1542,10 @@ namespace TEAMModelOS.FunctionV4
                 errorItems.Add(item);
             }
             try {
+               /* bool isError =  examClassResults.SelectMany(c => c.status).ToList().Exists(z => z == 1);
+                if () { 
+                
+                }*/
                 if (errorItems.Count == 0)
                 {
                     // 新增逻辑 收集错题内容
@@ -1654,6 +1658,9 @@ namespace TEAMModelOS.FunctionV4
                             }
                             index_item++;
                         }
+                        if (index.Count == 0) {
+                            continue;
+                        }
                         //int[] item_index = ss[n];
                         foreach (var item in index)
                         {

+ 3 - 3
TEAMModelOS.FunctionV4/TEAMModelOS.FunctionV4.csproj

@@ -5,9 +5,9 @@
 		<OutputType>Exe</OutputType>
 		<_FunctionsSkipCleanOutput>true</_FunctionsSkipCleanOutput>
 		<SignAssembly>true</SignAssembly>
-		<Version>5.2309.27</Version>
-		<AssemblyVersion>5.2309.27.1</AssemblyVersion>
-		<FileVersion>5.2309.27.1</FileVersion>
+		<Version>5.2310.11</Version>
+		<AssemblyVersion>5.2310.11.1</AssemblyVersion>
+		<FileVersion>5.2310.11.1</FileVersion>
 		<PackageId>TEAMModelOS.FunctionV4</PackageId>
 		<Authors>teammodel</Authors>
 		<Company>醍摩豆(成都)信息技术有限公司</Company>

+ 35 - 25
TEAMModelOS.SDK/Context/Attributes/Filter/ApiTokenAttribute.cs

@@ -227,40 +227,49 @@ namespace TEAMModelOS.Filter
                                         //如果是商务合作模式 则需要手动获取学校编码
                                        
 
-                                        if (path.ToString().Contains("get-schools"))
+                                        if (path.ToString().Contains("get-schools") ||path.ToString().Contains("business/sso")||path.ToString().Contains("business/notify-bind"))
                                         {
                                             pass = true;
+                                            if (path.ToString().Contains("business/sso") &&  !string.IsNullOrWhiteSpace(XAuthSchool)) 
+                                            {
+                                                pass=false;
+                                            }
                                         }
                                         else
                                         {
+                                            pass=false;
+                                        }
+                                        if (pass==false)
+                                        {
+
                                             //如果访问的接口是 business/get-schools
                                             if (!string.IsNullOrWhiteSpace(XAuthSchool))
                                             {
                                                 //访问次数记录 开始
-                                                long udate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
-                                                var respon = _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync(id, new Azure.Cosmos.PartitionKey("BizVisit")).Result;
-                                                if (respon.Status == 200)
-                                                {
-                                                    BizVisitCnt bizVisit = JsonDocument.Parse(respon.Content).Deserialize<BizVisitCnt>();
-                                                    bizVisit.visit += 1;
-                                                    //var tempApi = bizVisit.apis.Find(f => f.name.Equals($"{path}"));
-                                                    //if (tempApi != null)
-                                                    //{
-                                                    //    tempApi.visit += 1;
-                                                    //    tempApi.upDate = udate;
-                                                    //}
-                                                    //else
-                                                    bizVisit.apis.Add(new APIInfo() { name = $"{path}", upDate = udate });//记录加一下
-                                                       _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Normal").ReplaceItemAsync<BizVisitCnt>(bizVisit, id, new Azure.Cosmos.PartitionKey("BizVisit"));
-                                                }
-                                                else
-                                                {
-                                                    BizVisitCnt bizVisit = new() { id = id, visit = 1, apis = new List<APIInfo>() { new APIInfo() { name = $"{path}", upDate = udate } } };
-                                                  _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Normal").CreateItemAsync<BizVisitCnt>(bizVisit, new Azure.Cosmos.PartitionKey("BizVisit"));
-                                                }
+                                                //long udate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                                                //var respon = _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync(id, new Azure.Cosmos.PartitionKey("BizVisit")).Result;
+                                                //if (respon.Status == 200)
+                                                //{
+                                                //    BizVisitCnt bizVisit = JsonDocument.Parse(respon.Content).Deserialize<BizVisitCnt>();
+                                                //    bizVisit.visit += 1;
+                                                //    //var tempApi = bizVisit.apis.Find(f => f.name.Equals($"{path}"));
+                                                //    //if (tempApi != null)
+                                                //    //{
+                                                //    //    tempApi.visit += 1;
+                                                //    //    tempApi.upDate = udate;
+                                                //    //}
+                                                //    //else
+                                                //    bizVisit.apis.Add(new APIInfo() { name = $"{path}", upDate = udate });//记录加一下
+                                                //       _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Normal").ReplaceItemAsync<BizVisitCnt>(bizVisit, id, new Azure.Cosmos.PartitionKey("BizVisit"));
+                                                //}
+                                                //else
+                                                //{
+                                                //    BizVisitCnt bizVisit = new() { id = id, visit = 1, apis = new List<APIInfo>() { new APIInfo() { name = $"{path}", upDate = udate } } };
+                                                //  _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Normal").CreateItemAsync<BizVisitCnt>(bizVisit, new Azure.Cosmos.PartitionKey("BizVisit"));
+                                                //}
                                                 //访问次数记录 结束
 
-                                                var response =    _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync(id, new Azure.Cosmos.PartitionKey("BizConfig")).Result;
+                                                var response = _azureCosmos.GetCosmosClient().GetContainer("TEAMModelOS", "Normal").ReadItemStreamAsync(id, new Azure.Cosmos.PartitionKey("BizConfig")).Result;
                                                 if (response.Status == 200)
                                                 {
                                                     BizConfig bizConfig = JsonDocument.Parse(response.Content).Deserialize<BizConfig>();
@@ -270,7 +279,8 @@ namespace TEAMModelOS.Filter
                                                         school = XAuthSchool;
                                                         pass = true;
                                                     }
-                                                    else {
+                                                    else
+                                                    {
                                                         if (bizConfig.schools.IsNotEmpty() && bizConfig.schools.Select(z => z.id).Contains(XAuthSchool))
                                                         {
                                                             if (bizConfig.jti.Equals(jti))
@@ -290,7 +300,7 @@ namespace TEAMModelOS.Filter
                                                             pass = false;
                                                         }
                                                     }
-                                                        
+
                                                 }
                                                 else
                                                 {

+ 2 - 0
TEAMModelOS.SDK/Models/Cosmos/BI/BISchool/BIRelation.cs

@@ -114,4 +114,6 @@ namespace TEAMModelOS.SDK.Models.Cosmos.BI.BISchool
         /// </summary>
         public string picture { get; set; }
     }
+
+    
 }

+ 290 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/Activity.cs

@@ -0,0 +1,290 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TEAMModelOS.SDK.Models.Cosmos.Common
+{
+    public class Activity : CosmosEntity
+    {
+        //id  活动id,
+        //code Activity-hbcn/areaId
+        public Activity() {
+            pk="Activity";
+        }
+        public string name { get; set; }
+        public string subject { get; set; }
+        public string description { get; set; }
+        public string address { get; set; }
+        public long stime { get; set; }
+        public long etime { get; set; }
+        public string poster { get; set; }
+        public List<string> attachment { get; set; } = new List<string>();
+        public List<string> zb { get; set; } = new List<string>();
+        public List<string> cb { get; set; } = new List<string>();
+        /// <summary>
+        /// "hbcn/区级id,areaId",
+        /// </summary>
+        public string owner { get; set; }
+        /// <summary>
+        /// "public公开/area区级/school校级",
+        /// </summary>
+        public string scope { get; set; }
+        /// <summary>
+        /// "enroll/报名制,invite/邀请制",
+        /// </summary>
+        public string joinMode { get; set; }
+        /// <summary>
+        /// //区级活动时允许参与的学校,如果为空则全部学校
+        /// </summary>
+        public List<IdNamePicture> schools { get; set; } = new List<IdNamePicture>();
+        /// <summary>
+        /// //邀请制,允许参加的教师
+        /// </summary>
+        public List<IdNameSchool> inviteTeachers { get; set; } = new List<IdNameSchool>();
+        /// <summary>
+        /// 模块"Contest/赛课活动",  "Training/线上培训", "Research/教研活动"
+        /// </summary>
+        public List<string> modules { get; set; } = new List<string>();
+        /// <summary>
+        /// 本次活动的评审专家
+        /// </summary>
+        public List<Expert> experts { get; set; } = new List<Expert>();
+        /// <summary>
+        /// 所属年份
+        /// </summary>
+        public int year { get; set; }
+        /// <summary>
+        /// 创建时间
+        /// </summary>
+        public long createTime {  get; set; }
+
+    }
+
+    /// <summary>
+    /// //赛课模块的数据结构
+    /// </summary>
+    public class Contest : CosmosEntity
+    {
+        //id  活动id,
+        public Contest()
+        {
+            code = "Contest";
+            pk = "Contest";
+        }
+        /// <summary>
+        ///  //参加活动获得积分。根据最后评委打分,0-100的比例获得积分,不足一分按一分计算。
+        /// </summary>
+        public int balance { get; set; }
+        /// <summary>
+        /// "sign","upload","review","score"//报名模块,上传作品模块,评审模块,成绩公布模块
+        /// </summary>
+        public List<string> modules { get; set; } = new List<string>();
+
+        public ContestSign sign { get; set; }
+        public ContestUpload upload { get; set; }
+        public ContestReview review { get; set; }
+        public ContestScore score { get; set; }
+    }
+    public class ContestScore
+    {
+        public long stime { get; set; }
+        public long etime { get; set; }
+    }
+    public class ContestReview
+    {
+        public long stime { get; set; }
+        public long etime { get; set; }
+        /// <summary>
+        ///  //default 默认,评审规则
+        /// </summary>
+        public string ruleId { get; set; }
+    }
+    public class ContestUpload
+    {
+        public long stime { get; set; }
+        public long etime { get; set; }
+        /// <summary>
+        /// ["file"], 提交作品的格式
+        /// </summary>
+        public List<string> type { get; set; }
+        public string desc { get; set;}
+    }
+    public class ContestSign
+    {
+        /// <summary>
+        ///  "name",   "phone",   "period",   "subject",  "school", "contestType",  "job"
+        /// </summary>
+        public List<string> field { get; set; } = new List<string>();
+        public long stime { get; set; }
+        public long etime { get; set; }
+        /// <summary>
+        /// //报名人数限制
+        /// </summary>
+        public int limit { get; set; }
+    }
+
+    /// <summary>
+    /// 在线培训模块的数据结构
+    /// </summary>
+    public class Training : CosmosEntity
+    {
+        //id  活动id,
+        public Training()
+        {
+            code = "Training";
+            pk = "Training";
+        }
+        /// <summary>
+        ///  //参加活动获得积分。根据最后评委打分,0-100的比例获得积分,不足一分按一分计算。
+        /// </summary>
+        public int balance { get; set; }
+        /// <summary>
+        /// "online", "submit", "exam"模块
+        /// </summary>
+        public List<string> modules { get; set; } = new List<string>();
+        public List<TrainingAbility> abilities { get; set; }= new List<TrainingAbility>();
+        public TrainingOnline online { get; set; }
+        public TrainingSubmit submit { get; set; }
+        public TrainingExam exam { get; set; }
+        public long stime { get; set; }
+        public long etime { get; set; }
+    }
+
+    public class TrainingOnline 
+    {
+        /// <summary>
+        /// //最少学习多少积分 
+        /// </summary>
+        public int least { get; set; }
+        /// <summary>
+        ///  //至少修三个能力点
+        /// </summary>
+        public int limit { get; set; }
+    }
+    public class TrainingSubmit
+    {
+        public int balance { get; set; } //单个认证合格获得的积分0-5
+    }
+    public class TrainingExam
+    {
+        public int balance { get; set; } //单个认证合格获得的积分0-5
+    }
+    /// <summary>
+    /// 教研中心技能点
+    /// </summary>
+    public class TrainingAbility
+    {
+        /// <summary>
+        /// //学习完成获得积分,0-10
+        /// </summary>
+        public int balance { get; set; } 
+        public string id { get; set; }
+        /// <summary>
+        ///新建字段 维度 对应 原来的 subjectId 学科
+        /// </summary>
+        public string dimension { get; set; }
+        /// <summary>
+        /// 标号 A1  A2 A3....
+        /// </summary>
+        public string no { get; set; }
+       
+        /// <summary>
+        /// 册别name
+        /// </summary>
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string name { get; set; }
+        public List<AbilityTask> abilityTasks { get; set; } = new List<AbilityTask>();
+       
+        public string desc { get; set; }
+        public string sug { get; set; }
+        public List<AbilityStds> stds { get; set; } = new List<AbilityStds>();
+        /// <summary>
+        ///自测练习题试卷 blob地址
+        /// </summary>
+        public string blob { get; set; }
+        /// <summary>
+        ///默认未设置0 必修1 通识2 选修3
+        /// </summary>
+        public int currency { get; set; }
+    }
+
+    public class Research : CosmosEntity
+    {
+        //id  活动id,
+        public Research()
+        {
+            code = "Research";
+            pk = "Research";
+        }
+        /// <summary>
+        ///  "sign", //关联HiTeach课例的时候,可自动关联。   "homework", //作业   "examLite", //评测   "vote", //投票  "survey" //问卷,  此处几个活动的id是 赛课大活动的id
+        /// </summary>
+        public List<string> modules { get; set; } = new List<string>();
+        public long stime { get; set; }
+        public long etime { get; set; }
+        public ResearchSign sign { get; set; }
+        public ResearchExamLite examLite { get; set; }
+        public ResearchHomework homework { get; set; }
+        public ResearchSurvey survey { get; set; }  
+        public ResearchVote vote { get; set; }
+    }
+    public class ResearchSign
+    {
+        /// <summary>
+        /// //活动签到活得0-5
+        /// </summary>
+        public int balance { get; set; }
+    }
+    public class ResearchHomework
+    {
+        public List<string> type { get; set; } = new List<string>();
+
+        /// <summary>
+        /// //活动签到活得0-5
+        /// </summary>
+        public int balance { get; set; }
+    }
+    public class ResearchExamLite
+    {
+        /// <summary>
+        /// //完成评测练习,可获取0-5
+        /// </summary>
+        public int balance { get; set; }
+    }
+    public class ResearchVote
+    {
+        /// <summary>
+        /// //完成评测练习,可获取0-5
+        /// </summary>
+        public int balance { get; set; }
+    }
+    public class ResearchSurvey
+    {
+        /// <summary>
+        /// //完成评测练习,可获取0-5
+        /// </summary>
+        public int balance { get; set; }
+    }
+
+    public class Expert { 
+        public string id { get; set; }
+        public string name { get; set; }
+        public string mobile { get; set; }
+        /// <summary>
+        /// 职称
+        /// </summary>
+        public string title { get; set; }
+        /// <summary>
+        /// 科目
+        /// </summary>
+        public string subject { get; set; }
+        /// <summary>
+        /// 学段
+        /// </summary>
+        public string period { get; set; }
+        public string picture { get; set; }
+    }
+}

+ 0 - 40
TEAMModelOS.SDK/Models/Cosmos/Common/ActivityRecord.cs

@@ -1,40 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-using System.Text.Json;
-
-namespace TEAMModelOS.SDK.Models.Cosmos.Common
-{
-    class ActivityRecord : CosmosEntity
-    {
-        /// <summary>
-        /// 源数据的发布层级 类型 school  teacher
-        /// </summary>
-        public string owner { get; set; }
-        /// <summary>
-        /// 源数据的 code
-        /// </summary>
-        public string scode { get; set; }
-        public string type { get; set; }
-        //评测模式
-        public string source { get; set; }
-        public string name { get; set; }
-        public long startTime { get; set; }
-        public long endTime { get; set; }
-        public string scope { get; set; }
-        public string school { get; set; }
-        public string creatorId { get; set; }
-        public List<string> subjects { get; set; }
-        public string blob { get; set; }
-        public string recordUrl { get; set; }
-        public List<string> classIds { get; set; } = new List<string>();
-
-        public long createTime { get; set; } = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
-        /// <summary>
-        /// 任务完成状态,-1 未参与,0,未完成, 1已完成
-        /// </summary>
-        public int taskStatus { get; set; } = -1;
-        //写入投票记录,评测作答记录等,自行定义相关规范
-        public List<JsonElement> extParam { get; set; } = new List<JsonElement>();
-    }
-}

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

@@ -55,6 +55,9 @@ namespace TEAMModelOS.SDK.Models.Cosmos.Common
         public string topic { get; set; }
         public long startTime { get; set; }
         public long endTime { get; set; }
+        public long uploadSTime { get; set; }
+        public long uploadETime { get; set; }
+        public string uploadProgress { get; set; }
         public string address { get; set; }
         //培训内容
         public string desc { get; set; }
@@ -104,7 +107,7 @@ namespace TEAMModelOS.SDK.Models.Cosmos.Common
         public int? isOrder { get; set; } = 0;
         public int? type { get; set; } = 0;
         public string workDesc { get; set; }
-        public long workEnd { get; set; }
+        public long workEnd { get; set; } 
       
     }
 }

+ 13 - 0
TEAMModelOS.SDK/Models/Cosmos/Common/GroupList.cs

@@ -487,6 +487,19 @@ namespace TEAMModelOS.SDK.Models
         public string stulist { get; set; }
         public string teacherId { get; set; }
     }
+    public class IdNamePicture
+    {
+        public string id { get; set; }
+        public string name { get; set; }
+        public string picture { get; set; }
+    }
+    public class IdNameSchool
+    {
+        public string id { get; set; }
+        public string name { get; set; }
+        public string picture { get; set; }
+        public string school { get; set; }
+    }
     public class IdNameCode
     {
         public string id { get; set; }

+ 6 - 6
TEAMModelOS.SDK/Models/Cosmos/Common/StudentScoreRecord.cs

@@ -13,12 +13,12 @@ namespace TEAMModelOS.SDK.Models.Cosmos.Common
 
     /// <summary>
     /// 
-//    Quiz : IRS問題(不論任何題型)
-//Quiz_Buzz: 搶權
-//Collate_End/Collate_Start: 任務(不論任何內容, 如果結束課堂時還開著, 會出現 Collate_Start)
-//Meteor_End: 星光評分/投票
-//MutuallyScore_End: 互評
-//SelfPace_End: 課中測驗
+    //    Quiz : IRS問題(不論任何題型)
+    //Quiz_Buzz: 搶權  抢权 ,按了反馈器的学生。 buzzHistory  , 抢权成功的学生 buzzMember
+    //Collate_End/Collate_Start: 任務(不論任何內容, 如果結束課堂時還開著, 會出現 Collate_Start)
+    //Meteor_End: 星光評分/投票
+    //MutuallyScore_End: 互評
+    //SelfPace_End: 課中測驗
 
 
     /// 互动:

+ 4 - 1
TEAMModelOS.SDK/Models/Cosmos/Normal/Area.cs

@@ -11,6 +11,10 @@ namespace TEAMModelOS.SDK.Models
             pk = "Area";
         }
         /// <summary>
+        /// 簡碼
+        /// </summary>
+        public string shortCode { get; set; }
+        /// <summary>
         /// 区域级名称
         /// </summary>
         public string name { get; set; }
@@ -43,7 +47,6 @@ namespace TEAMModelOS.SDK.Models
         /// </summary>
         public string institution { get; set; }
         public long updateTime { get; set; }
-
         /// <summary>
         /// 引用id
         /// </summary>

+ 3 - 0
TEAMModelOS.SDK/Models/Cosmos/Normal/TMDOrder.cs

@@ -23,6 +23,9 @@ namespace TEAMModelOS.SDK.Models
         public string buyer_email { get; set; }
         public string return_url { get; set; }
         public string notify_url { get; set; }
+        public string ip { get; set; }
+        public string region { get; set; }
+        public string school { get; set; }
         /// <summary>
         /// 微信支付二维码
         /// </summary>

+ 3 - 2
TEAMModelOS.SDK/Models/Cosmos/School/CourseBase.cs

@@ -347,7 +347,8 @@ namespace TEAMModelOS.SDK.Models
         /// <summary>
         /// -1未验证的,0.验证通过的,1.课程名称无效的,2.醍摩豆ID无效的,3.教学班名称无效的,4.教室编号无效的,5.开学日期无效的,6.课程结束日期无效的,
         /// 7.排课时间格式不满足[1-n]-[1|2|3|4|5|6|7]-[A|D|C],8.没有对应的上课时间段,9.上课时间不在星期一至星期日,10.自定义模式下,需要配置对应的上课周,11.自定义模式下,上课周不在1-20周
-        /// 12.班级入学年-编号不存在,13.导入的班级入学年-编号在系统中重复,请检查行政班设置,14.班级入学年-编号格式错误,15根据开学时间无法获取学期信息
+        /// 12.班级入学年-编号不存在,13.导入的班级入学年-编号在系统中重复,请检查行政班设置,14.班级入学年-编号格式错误,15根据开学时间无法获取学期信息,16学期不存在,17,修改的信息必须要有教师或名单中的一项或两项。
+        /// 18.修改的名单不存在,19修改的教师不存在,20.同一教师,同一班级,同一课程,只能有一条记录,21助教老师不存在
         /// </summary>
         public int invalidCode { get; set; } = -1;
         public string invalidMsg { get; set; }
@@ -399,7 +400,7 @@ namespace TEAMModelOS.SDK.Models
         /// -1未验证的,0.验证通过的,1.课程名称无效的,2.醍摩豆ID无效的,3.教学班名称无效的,4.教室编号无效的,5.开学日期无效的,6.课程结束日期无效的,
         /// 7.排课时间格式不满足[1-n]-[1|2|3|4|5|6|7]-[A|D|C],8.没有对应的上课时间段,9.上课时间不在星期一至星期日,10.自定义模式下,需要配置对应的上课周,11.自定义模式下,上课周不在1-20周
         /// 12.班级入学年-编号不存在,13.导入的班级入学年-编号在系统中重复,请检查行政班设置,14.班级入学年-编号格式错误,15根据开学时间无法获取学期信息,16学期不存在,17,修改的信息必须要有教师或名单中的一项或两项。
-        /// 18.修改的名单不存在,19修改的教师不存在,20.同一教师,同一班级,同一课程,只能有一条记录,21助教老师不存在
+        /// 18.修改的名单不存在,19修改的教师不存在,20.同一教师,同一班级,同一课程,只能有一条记录,21助教老师不存在,22助教限制10
         /// </summary>
         public int invalidCode { get; set; } = -1;
         //个人的课程 引用其他学校的名单

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

@@ -166,6 +166,10 @@ namespace TEAMModelOS.SDK.Models
         /// 历史最高版本  1 基础班  2标准版  3 专业版
         /// </summary>
         public int record { get; set; } = 1;
+        /// <summary>
+        /// 規模版本
+        /// </summary>
+        public string scaleVersion { get; set; }
     }
 
     /// <summary>
@@ -174,5 +178,5 @@ namespace TEAMModelOS.SDK.Models
     public class VirtualBase : School
     {
         public string areaName { get; set; }
-    } 
+    }
 }

+ 63 - 0
TEAMModelOS.SDK/Models/Cosmos/Student/ArtAttachment.cs

@@ -0,0 +1,63 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace TEAMModelOS.SDK.Models.Cosmos.Student
+{
+    public  class ArtAttachment : CosmosEntity
+    {
+        public ArtAttachment()
+        {
+            pk = "ArtAttachment";
+        }
+        public string artId { get; set; }
+        public string studentId { get; set; }
+        /// <summary>
+        /// 任务id
+        /// </summary>
+        public string taskId { get; set; }
+        /// <summary>
+        /// 任务名称
+        /// </summary>
+        public string taskName { get; set; }
+        /// <summary>
+        /// 科目id
+        /// </summary>
+        public string subjectId { get; set; }
+        /// <summary>
+        /// 科目名称
+        /// </summary>
+        public string subjectName { get; set; }
+        /// <summary>
+        /// 指标id
+        /// </summary>
+        public string quotaId { get; set; }
+        /// <summary>
+        /// 指标名称
+        /// </summary>
+        public string quotaName { get; set; }
+        /// <summary>
+        /// 指标类型-1未设定 0评分,1评测,2作业
+        /// </summary>
+        public int quotaType { get; set; }
+        public string address { get; set; }
+        public string time { get; set; }
+        public string duration { get; set; }
+        public string achievement { get; set; }
+        public string name { get; set; }
+        public string des { get; set; }
+        //0 艺术作品 1 等级证书
+        public int artType { get; set; }
+        // 0 校级 1 区级 2 市级 3 省级 4 国家级
+        public int level { get; set; }
+        public long uploadTime { get; set; }
+        public long updateTime { get; set; }
+        /// <summary>
+        /// 上传的文件
+        /// </summary>
+        public List<Attachment> files { get; set; }
+
+    }
+}

+ 2 - 5
TEAMModelOS.SDK/Models/Cosmos/Student/StudentArtResult.cs

@@ -72,12 +72,9 @@ namespace TEAMModelOS.SDK.Models
         /// <summary>
         /// 分数
         /// </summary>
-        public double score { get; set; } = -1;
-        /// <summary>
-        /// 上传的文件
-        /// </summary>
+        public double score { get; set; } = -1;      
+        public string name { get; set; }      
         public List<Attachment> files { get; set; }
-
         /// <summary>
         /// 分数结果来源    0醍摩豆系统分数结果   1智音传分数结果
         /// </summary>

+ 6 - 13
TEAMModelOS.SDK/Models/Dtos/LessonRecordActivityInfo.cs

@@ -895,17 +895,10 @@ namespace TEAMModelOS.SDK.Models.Dtos
         public MappingDictionary mappingDictionary { get; set; } = new MappingDictionary();
     }
 
-    public class MemberEliminatedDictionary
-    {
-    }
 
-    public class CompetitionAnsweredDic
-    {
-    }
+ 
 
-    public class MemberPushes
-    {
-    }
+   
 
     public class PqA_ListItem
     {
@@ -1050,13 +1043,13 @@ namespace TEAMModelOS.SDK.Models.Dtos
         /// </summary>
         public SelfPaceAnswers selfPaceAnswers { get; set; }= new SelfPaceAnswers();
         /// <summary>
-        /// 
+        /// 学生被淘汰出局的 字典
         /// </summary>
-        public MemberEliminatedDictionary memberEliminatedDictionary { get; set; } = new MemberEliminatedDictionary();
+        public Dictionary<string, SelectedItemsItem>  memberEliminatedDictionary { get; set; } = new Dictionary<string, SelectedItemsItem>();
         /// <summary>
         /// 
         /// </summary>
-        public CompetitionAnsweredDic competitionAnsweredDic { get; set; } = new CompetitionAnsweredDic();
+        public Dictionary<string, SelectedItemsItem> competitionAnsweredDic { get; set; } = new Dictionary<string, SelectedItemsItem>();
         /// <summary>
         /// 
         /// </summary>
@@ -1064,7 +1057,7 @@ namespace TEAMModelOS.SDK.Models.Dtos
         /// <summary>
         /// 
         /// </summary>
-        public MemberPushes memberPushes { get; set; } = new MemberPushes();
+        public Dictionary<string, SelectedItemsItem> memberPushes { get; set; } = new Dictionary<string, SelectedItemsItem>();
         /// <summary>
         /// 
         /// </summary>

+ 1 - 1
TEAMModelOS.SDK/Models/Service/BI/BIProdAnalysis.cs

@@ -718,7 +718,7 @@ namespace TEAMModelOS.SDK.Models.Service.BI
                         if (!string.IsNullOrWhiteSpace(tmid) && !string.IsNullOrWhiteSpace(deviceId) && !string.IsNullOrWhiteSpace(toolType))
                         {
                             bool addFlg = false;
-                            TmidAnalysis tmidAnalysisRow = TmidAnalysisList.Where(s => s.tmid.Equals(tmid)).FirstOrDefault();
+                            TmidAnalysis tmidAnalysisRow = TmidAnalysisList.Where(s => s.tmid.Equals(tmid) && s.toolType.Equals(toolType)).FirstOrDefault();
                             //無此tmid數據=>創建
                             if (tmidAnalysisRow == null)
                             {

+ 1 - 0
TEAMModelOS.SDK/Models/Service/BI/BIStats.cs

@@ -540,6 +540,7 @@ namespace TEAMModelOS.SDK.Models.Service.BI
                 bIRelation.scale = school.scale;
                 bIRelation.upDate = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                 bIRelation.areaName = aName;
+                bIRelation.edition = school.edition;
 
                 if (resBiRel.Status == 200)
                 {

+ 1 - 0
TEAMModelOS.SDK/Models/Service/Common/TeacherService.cs

@@ -350,6 +350,7 @@ namespace TEAMModelOS.Services
         //public string accessConfig { get; set; }
         public AreaSetting setting { get; set; }
         public int access { get; set; } = 0;
+        public string shortCode { get; set; }
     }
     public record TeacherInfo
     {

+ 3 - 3
TEAMModelOS.SDK/TEAMModelOS.SDK.csproj

@@ -2,9 +2,9 @@
 
   <PropertyGroup>
     <TargetFramework>net6.0</TargetFramework>
-    <Version>5.2309.27</Version>
-    <AssemblyVersion>5.2309.27.1</AssemblyVersion>
-    <FileVersion>5.2309.27.1</FileVersion>
+    <Version>5.2310.11</Version>
+    <AssemblyVersion>5.2310.11.1</AssemblyVersion>
+    <FileVersion>5.2310.11.1</FileVersion>
     <PackageReleaseNotes>发版</PackageReleaseNotes>
   </PropertyGroup>
 

+ 5 - 2
TEAMModelOS/ClientApp/public/lang/en-US.js

@@ -892,7 +892,7 @@ const LANG_EN_US = {
         assistants: 'Co-teachers (multiple)',
         tip1: 'Removing the lead teacher will clear the corresponding co-teacher',
         tip2: 'Please set the lead teacher first! ',
-        tip3: 'A maximum of 3 co-teachers can be designated!',
+        tip3: 'A maximum of 10 co-teachers can be designated!',
         normal: 'Normal and can be imported',
         tip4: 'The red mark indicates abnormal parsing of course data; please adjust the template data and reimport it. ',
         tip5: 'Data not marked in red can be imported properly.',
@@ -3424,7 +3424,8 @@ const LANG_EN_US = {
             dingding: 'DingTalk',
         },
         apiError: {
-            text1: ' User name or password incorrect'
+            text1: ' User name or password incorrect',
+            text2: 'You have graduated and cannot log in at this time!',
         },
         sse: {
             error: {
@@ -3609,6 +3610,7 @@ const LANG_EN_US = {
         delete: 'Delete',
         view: 'View',
         edit: 'Edit',
+        tableIsNaN:'No score sheet yet',
         noNotify: 'No Announcement Yet',
         notifyDetail: 'Announcement Detail',
         delNotifyTitle: 'Delete Announcement',
@@ -6118,6 +6120,7 @@ const LANG_EN_US = {
         props7: 'Not enough storage space!',
         uploadText: 'Tap or drag to upload',
         resTips: 'Format generated by HiTeach: HTEX Files',
+        space: 'Remaining Space:',
         calcing: 'Calculating...',
         blobFull: '(Full)',
         otherType: 'Other types',

+ 1 - 1
TEAMModelOS/ClientApp/public/lang/zh-CN.js

@@ -892,7 +892,7 @@ const LANG_ZH_CN = {
         assistants: '协同教师(多选)',
         tip1: '移除执教老师将会清空对应的协同教师',
         tip2: '请先设置执教老师!',
-        tip3: '协同教师最多设置3人!',
+        tip3: '协同教师最多设置10人!',
         normal: '正常可导入',
         tip4: '标红的信息代表该条课程数据解析异常,可修改模板内数据后重新导入。',
         tip5: '未标红的数据代表可正常导入。',

+ 5 - 2
TEAMModelOS/ClientApp/public/lang/zh-TW.js

@@ -892,7 +892,7 @@ const LANG_ZH_TW = {
         assistants: '協同教師(多位)',
         tip1: '移除主授課教師將會清空對應的協同教師',
         tip2: '請先設定主授課教師! ',
-        tip3: '協同教師最多指定3位! ',
+        tip3: '協同教師最多指定10位! ',
         normal: '正常可匯入',
         tip4: '標示紅色代表該筆課程資料解析異常,可修改範本內的資料後重新匯入。 ',
         tip5: '未標示紅色的資料代表可正常匯入。 ',
@@ -3426,7 +3426,8 @@ const LANG_ZH_TW = {
             dingding: '釘釘',
         },
         apiError: {
-            text1: '您的 帳號 或 密碼 不正確'
+            text1: '您的 帳號 或 密碼 不正確',
+            text2: '你已畢業,暫不能登入!',
         },
         sse: {
             error: {
@@ -3611,6 +3612,7 @@ const LANG_ZH_TW = {
         delete: '刪除',
         view: '查看',
         edit: '編輯',
+        tableIsNaN:'尚無成績表',
         noNotify: '暫無公告',
         notifyDetail: '公告詳情',
         delNotifyTitle: '刪除公告',
@@ -6119,6 +6121,7 @@ const LANG_ZH_TW = {
         props7: '儲存空間不足!',
         uploadText: '點按或者拖移上傳',
         resTips: 'HiTeach生成的教材,只支援HTEX格式',
+        space: '剩餘空間:',
         calcing: '計算中…',
         blobFull: '(已滿)',
         otherType: '其他',

+ 1 - 0
TEAMModelOS/ClientApp/src/api/http.js

@@ -17,6 +17,7 @@ const NO_ACCESS_API = [
     '/common/study/sign-in',
     'third/sso/opt-tmdid-bind',
     '/sc/bind',
+    '/business/bind',
     '/lepei/bind',
     '/core/get-short-url',
     '/core/get-long-url',

+ 4 - 0
TEAMModelOS/ClientApp/src/api/index.js

@@ -250,6 +250,10 @@ export default {
                 case 'wechat':
                     result = 'https://open.weixin.qq.com/connect/qrconnect?appid=wx207be4d5a37eca4a&redirect_uri=' + redirect_uri + '&response_type=code&scope=snsapi_login&state=wechat#wechat_redirect'
                     break;
+                case 'educloudtw':
+                    result = 'https://oidc.tanet.edu.tw/oidc/v1/azp?response_type=code&client_id=c58722f58275a8c81fcc5ed6b94f3e7b&redirect_uri=' + redirect_uri + '&scope=openid+email+profile&state=educloudtw&nonce=aaaaa'
+                    // 教育雲測試站 // result = 'https://oidc.sso.edu.tw/oidc/v1/azp?response_type=code&client_id=9d8bfb91c18efafd423433d6d21ca2f3&redirect_uri=' + redirect_uri + '&scope=openid+email+profile&state=educloudtw&nonce=aaaaa'
+                    break
             }
 
             resolve(result)

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

@@ -322,7 +322,7 @@
 					let hasStuDash = schoolVersions.productSum.service.find((i) => i.prodCode === "YPXSJ6NJ"); // 五育看板模块
 					let hasAnalysis = schoolVersions.productSum.service.find((i) => i.prodCode === "YMPCVCIM"); // 学情分析模块 代表至少是标准版
 					let isPro = hasStuDash && hasArtProd; // 同时购买了五育看板和艺术评测 代表是专业版本
-					let isArtTest = this.$store.state.user.schoolProfile.school_base.modules.includes('art') // modules里面有art代表 必定为评测版本
+					let isArtTest = this.$store.state.user.schoolProfile.school_base.modules?.includes('art') // modules里面有art代表 必定为评测版本
 					this.hasArtProd = hasArtProd;
 					if (isPro) {
 						this.isPro = true;

+ 139 - 0
TEAMModelOS/ClientApp/src/icons/svg/educloudtw.svg

@@ -0,0 +1,139 @@
+
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="217px" height="216px" viewBox="0 0 217 216" enable-background="new 0 0 217 216" xml:space="preserve">  <image id="image0" width="217" height="216" x="0" y="0"
+    href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAANkAAADYCAYAAABm4kbTAAAABGdBTUEAALGPC/xhBQAAACBjSFJN
+AAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QA/wD/AP+gvaeTAAAA
+CXBIWXMAABYlAAAWJQFJUiTwAAABIHpUWHRSYXcgcHJvZmlsZSB0eXBlIHhtcAAAKJF1UktyxSAM
+23OKHoHIxibHSR+w60yXPX5lkr6keS2e/GwjSyLp6+MzvcUSSJKHV9m8WvNszYqrLcjxbQ/rLlGT
+BthiasNgRbY9/+weAHI6YZh8jy2laisZWcWGcyOyGLrkeUF63pAjSAEEN9kKVJPabf5eDA7VlZFl
+48zhc6E7m9DnCMeQRdYIjCRZwAR4bzsIn+IrYUnbK1oMiPLJ5c5I1UpyMWFindJWutDJ8GigL+Bs
+OhEMacQvoGt4TRdRAWR/yZqc+mk33+mfNQo+9oS0ZZo4Xqk/BfwM2DScWa0csg8F0unUI52o/zfe
+vcG4urObk67uXI/2bI7DVYvazL78dVFJ30ktmxa/6wauAAAAAW9yTlQBz6J3mgAAGg1JREFUeNrt
+3XlcU1faB/DnJiSQACEQCSIo4IpsLlgEFYVW+3ZR2zpVW/tOp5tjF6kzzjufTtvx7e1iO7Yz7m2H
+amtnWrtgdUY62nbABpVdENnDooAge0hYw5bc948p8zqtrQQ49+TePN8/NZ7zPLn5meTm3nMYjuM4
+QAgRI6FdAEJihyFDiDAMGUKEYcgQIgxDhhBhGDKECMOQIUQYhgwhwjBkCBGGIUOIMAwZQoRhyBAi
+DEOGEGEYMoQIw5AhRBiGDCHCMGQIEYYhQ4gwDBlChGHIECIMQ4YQYRgyhAjDkCFEGIYMIcIwZAgR
+hiFDiDAMGUKEYcgQIgxDhhBhGDKECMOQIUQYhgwhwjBkCBHmRLsAR1ZiyIJOcy109dX84O+UzlpQ
+yLWgUgRCsDqCdqnjojcVQZe5FgAADN0l//F3MqkrqJRBIJMqYYF2Je1SiWBwO1v+5TYlQ2VTUo6x
+p+R/gZEUOCslpl9G5g8zDHAAABwHzHv5kU5gBGW/3KJ1YpTzvFQh92jcwjZNcg+V2PuLscSQBc2m
+XDD0lJ7vMtd+0D/YWmgdsjRKBvtN53uqh5PWg/W7XhmWAyakLNSpsZvxZAacIn08bnklSLs6Msp3
+Le02JgyGjGdflr9YX93y9a3b4y9W2/pvWRYkPrfP85Uy3ut8PaJYP028l70ETm8qggaDztxg1L3W
+O3j1qHbJzIYNzDHLWMY6oAsPDvBZrVsz9/XJtPuaCBgyHqXVHSo8m7svit1QOjjuwThgDmQs8PVS
+zH3eTxO/dUXAE1R6KjFkQWXT57rmjpxn2nTZFSwL1okYl00KlS9ZuDlz1YxtkVQam0gc4s2hnNuD
+SBzDxLxIZWLmbVsy6j8Z5KuXcmMhl1z2/Kl3M+f5kXptvpsZ40f7mE0EDBlPLrakcKwujuiJpiO6
+QJeP8je9VdyeSbSXtNpDLYmZMeEkewEAWJ8E0ostKbQP3bhhyHiSXv8Jx3HAkH5hAgAknov1Tana
+mz3RPZQbC7nPLm3+E+n/LP6NAyan8STtQzdu+DsZT7r6avhJGABsWX6+KePor5Z8VvjLHXpT0YSM
+WdCaCukV229/YP6h37DxacN89MHBD0/5CxGGjEfsy7zlDFgWrA/OP/RabuX/risxZI1rrHN1h4cy
+K1+eszn6TApf9QMAvAz8PV8kYcj4tCKO9+f7F4tP/i2tfHt8QWvqmP792brD1uJr78zaGpteyXft
+IWWhorhYAkPGowCopfKiSYjNTsuu3LHK1qCdrTsMJfUH525dWlBHo+4a47CzSknkhCyvMGQ8USmD
+wOjsqqQ1/9Ox2alFdW9vHO13tILWVCiufz9+a2wh7+9gI5wsMrVM6kpr+gmDIeOJTOoKTmbGk2YN
+j0T9PSn/ypvP3exxelMRZFfteCohNjuNZr1yqcxHKfemWcKEwJDxRKUIBJDJ/GnX8dDCo299Vfn6
+33/qMflXdn349NLsRNq1clYuLEwTQ7uMccOQ8SRYHQESifNS2nUwDHA9w59sLGhNbb/R36de3lde
+3dW4Gb67WJkmL9e599GuYSJgyHg0yS38Ado1AABsCC0dLKndH/X9P9d3Fg2V1H+4hK/fwX4Ky4LE
+0y1sNe06JgKGjEcat9DwpNJQOe06AAAeXvxlTVrte09e/2el9R8u+XX8JRPt2gAAPG6N9PFVR4ni
+9SmKJoRisjoKGtolc2jXMSIucMt7Ba3/+oH53NX3f3d/+J482jWNUMrUt9vLbTzjhSHjUZgmBryU
+0x+lXccIhgHuQu5z9yaXvfC17sgTb9Gu5984YKZ63vo67TImCt5PxrPUy/vgiukj+ZZF+UO0axnB
+ccAwdnCiY8S+9MhptwYfqBPDmUUAfCfjnb8mHgYHnGNp13E9ewoYAIC/etnLYgkYAIaMd8HqCJih
+ufsjlsXn/kYOpgZrZk/e+AjtOiYSHmgKgnxWT9HcGi2e/6on0NQp63aL6V0MAENGRbA6AoL9Hkjm
+7eZHgXgnfemc2b4bH6Zdx0TDkFGycvo2r2lK1XbaddgLVhfnFBH4zDdCX2PyRjBkFM0PTNh18Pyy
+2bTrsAcLtUt2L/V7MIB2HSRgyChaoF0J4VN/kbU7M0ZBuxaa3r+wdu2akJ0JtOsgBUNG2fKAJ7xm
+quMyHPX72V/y10YsmfnqSdp1kIQ/RtuJE8XbvraEN60e66q7QvRh7prQxbNeKxHj97Dr4TuZnVgX
+vu8OaYnfmcS8SBntWvjwfs59MY4QMAAMmV1ZF7ZnxXTPn1e8cz6c6h3UJHEcMB9ffChhyWw20xEC
+BoAfF+1SbnPy0IWqP9y5dXnWtwD2dcnTeOxKn+Me7v3w8Ttnv7CKdi18wpDZKb2pCMoaPvj71faz
+j9rLPV5jxXIgmZK16p55gc98EeV7j8N9esKQ2bncpmSobvx8Rw9U7N6yKL+Pdj22YFmQaFcujQrS
+3pV0x6wXptKuhxYMmUDkNiVDVeNnBzq6S99MiCu6Zm9Xzl8vMS9SaRmU3x6oWX0oSLt6kqN89/ox
+GDKBKTFkQb1B195iytnR01/7jcHqVW8Ha3IwiSmRqn7noUU+7ou3T/aMuovWfmn2CEMmYP+/5/SV
+YkNP2XEJAxntfRWVFom8bfuSLDORSTlgdmXMcZvkPGeKXOI6T+msvVPhpF2vUYW5imkL2omEIROp
+i62pzeah9gOdXSVH75q78+p4Pl6yLCu5ZaMl1Ntj0ePuysAngz0inGn3JyQYMsdQdab6wL0rZz1b
+Zus/TKnav2DlzISvAUBLuwmhwpA5kIutKU9G+tw+6pWBz9d/et8y/wdO0K5b6BzuNwtHtlC76s9f
+lD07azSPPV2VoMKATQwMmYOZrIp5YTSP8/VYs452rWKBIXMwMonyrtE8br73qnto1yoWGDIHw3Ew
+2t/UQmnXKhYYMgfTba4pH+VDrbRrFQsMmYMZtvSmj/KhVbRrFQsMmYPpNNdljuZxl1pT82nXKhYO
+ua4ELQWtqTBkufmF9CQvTxroaywdzeNau4rzQSS7qtCGIZtABa2p0DfYBl19Ne1d5trjw5a+dLO5
+ua7PYmgeskqNEmd5r6t8cNgzcrq17OVj3Esv/etSp5cBGEiLk4Ro2yR1DVJZZvUrKgYGvJVOPtNc
+XXxC3V0C1ivkPpEqZdC4A6hoUDSP5nGdfWUltJ9PscArPsYhtykZDD0lJmNX6QfG3tqTw0NdFQq1
+cweJHVvWJ4F0hVew2iJzmaNxDfn5ZHXU417uoTJb9vAqaE09sdBn1c9G89gjujiXR+J0ZC4ydjAY
+MhtlNHwKLcac083dF/Z19w3k/G5VfhdQWCKAZUGiip3n66rU3jnVK+6NqZr4STdbQ/501c4Vd8/+
+/bnRzpHe8MnVpX4POuzNlhOGQzdV3J7JHS/elvvO+eiVrC7QhfYx++ExBGbP+fDpJ4p/tfdiS8oN
+eyg3FnJskm1b6Z4se/73tJ97McCQ/YScxpPc0fxNe/eci/SlHaTRSsyLlH1ycfOKiy0p567v5XTF
+66O6nOp672Wsmk/7GIgBfly8gYLWVChtOPLHRnP+K88tq+imXc9YHdHFuXhqY6ZbrX1+w2GN39q6
+cOruzBjFqtl/6hPbVkZ8w5BdR28qgurmz7+pMp7ctH1JaQfteuxBSvXe6pUzts2gXYeQ4Sn871xo
+Sh7IqX7jtoTl2ZkgorUOx8vQXXoAAPbSrkPIMGQA8GX5iylNfd/cm7BcWEuu8aHNXPIN7RqEzqFD
+pjcVQf7lN194KPLoH+x5iTWaOFNbTUFrKtjyexz6Tw577aLeVATZVTvu/O9FR9/AgP24Z++qHjD0
+lNbQrkPIHDJkBa2pcE7/2+hHo5K/pl2LELR3lx2hXYOQOdzHRb2pCLIrf7/o6dgcXq8yZ3VxTj5y
+uZda4TVNInHXuLsEuVusfX2dAzVtckbaWFaZ38ZuKB2k/fzcSGfv5VQAeIV2HULlUCEb+YjIV8CS
+ktZLnYL9ony8Fm/3cg25/yeXq54HsKYltbi9q+SV2s7MlC2LjnXSfr5GWK2t+hJDFuDvZWNE+9dw
+Pn1wYe1WPp5TlgPJaf3r95d3FPaMtdaLLf9MOl72G7vYqJzlQJJe/wntwydYDhOy48Xb/sZxwJB+
+QaZc/sM0vbGweqLqzm08+fERXRz16yWTy56/SPsYCpVDhCyt9lCbrRfHjgFzofnkA4RaMBwve4Hq
+9ZMf5z30PO3jKFSiP7tYYsiC0rr3l5M8qcBxwJQbC19a5LP2U0JTeK2bu7NBV/NuIKkebsZovpxF
+a26hE33ILtUe3PXMiuzRrtA0Fky5sXBXsDriJcKtSOICn9RnVL9LZU16ibXncokBczYWog7Z2brD
+vX1QsYPkHEWGjEfmekb8lqeWnJfMeLIis363gqf5/m1A5t7eaa7le1pxoP15lZRyYyF38FzMbSSf
+u7P1H4dTau9bluX3P0iOA+ZUxU4L7eMqRKJ9J6tq+qz0mdisb0mNf7oqwXm5/0OjvpV/gsX/7OnM
+BD4nZBjgus21Fyj1K2iiDFmJIQvq2v7xIMlrEv29Nh0AADWtHsO8Y/aeKmUn8zmnZbg3g1a/QibK
+kFU2fZ6fsLyY2JJmX5Y+Ny3cK3oz7T6nT7nvNB+//Y1o7y0pot2zEIkuZCWGLKg3nnkMyL2LMQE+
+9yTR7hMAIFgdseBUxc44vuazMpJqPMNoO9GFrKb1y8ZtsSXFpMY/WvRYULgmZjHtPkfM8Fn9RVLS
+eikvk1ngWt9gG+2WBUdUIdObiuCaKe0xkt/FArxW7qHd5/WC1RFeirCZa/iYS6pw7jAPttJuWXBE
+FbKWzlyQyAeJnVHcn71YtdTvQXIL1Y9RoM+a9/k4pd9hVvT1DWDIbCWqkNUb0t4isUT2CH+3xaPa
+pZJvYV4xXnPWPrCQ9DxsfNqwebCV2PMrVqIJWYkhC4xdxfsJTsFo1dFv0u7zx/h63rabj3nMg22X
+aPcqNKIJWXNnbkdCXNE1UuPv0c33sOd14X3UUbFv60LdSM/DAFTS7lVoRBOyFtOFV0me8PD1jIqi
+3eNPCVZHgMo9gviSUu3dpVdo9yo0ogiZ3lQEBvOlEyTn0LiF3E+7z5vW6B72P8QnkXBXafcpNKII
+maGnFHyXhhD7qAgcMB7KoIdp93kzGvewpYl5kTKSc3AWpllvwgs/bCGKkHV0l6TYupmCLd76Z4Ty
+Ft+1zrT7vJko37VgHRwmer+ZRAqtXXjLi01EETJDd+mHJMef6jPfj3aPo6VyCZ1LcnyOY4y0exQa
+UYSsp+/KRZLjK2VTib5wJ5KLTHsLyfEHrEOC3UqKFsGHLLcpGSRgbSA5h9JFazfXKt6MyiVwOcnx
+PYZdzHhplW0EH7Kuvhp4Oq60l+Qc7opAwey2oHINiiU5/rBTvwUvrbKN4EM2aOkpJLxhBKNSBEbS
+7nO0lHJvV5Yjd1yV4D1Mu0ehEXzIjN2lRJcASMyLdApWRwjmeQrTxEBAWhyxNSbr2tqstHsUGsG8
+eH7MkNVM9KSHq0cw7ytDjZfZaZhczd7eGDIbCT5k3f11ZPfOMoCKdo+2cpX6KokNHpeGIbOR4EM2
+PGxtJzm+m9Lfk3aPtnJSyIiF7CXcT9tmgg5ZblMyKFzARHIOZ2d3D9p92kom17qSGpvhbdke8RB0
+yAAA+gcYoqfvgZN40e7RVm5SciEDfCezmeBDpnSXEt2d0st9rjftHm3GOdbmjvZO8CEbaO0kdmEw
+AADHSKhs8DAujIWf1avQqAg6ZF19NdCh8CcaMobjqO4LNiZSJ3wnsyOCDtmQpRdC2rwJf0dgyJ0O
+J8VqJflOhqc+bCTokAEAlK0/RjRkHAN2fx/ZD1g5Yu9kHJ72sJngQ0YawwD1/ZptJmGIXV/4Mr6T
+2QxDdhMcxwnu46KVg35SY4fAegyZjQQfspBjZA86w0gE93FRIuXMxAYvK5MqnYV3wpUmQYdMpQwC
+4/QrZHvgOMHd2sFxDLF3sroGqUwhx5DZQtAhk0ldYaC1k2gPHAMDtPu0ueYBK7GaXZUcsdtoxErQ
+IQMAcLZ4EP3hVcKB4Na0kMnIfSezME6Cu/WHNsGHzKIeJPqdieO4Dto92sowVNdHamzOCuooX7vb
+2MauCTpkMqkS+gclRM/+DVrNBtp92sraayZ24sNi4fALmY0EHbIF2pUgceaIbrLQ1Xu5hXafturQ
+dJD7TuaiEcwalPZC0CEDAGAsEg3hKZpo92irjqNfEdtDTOmsDaXdn9AIPmQKZ+00kuP3D7QI7Z2s
+l2WB2BIB7i5By2g3KDSCD5mrfNIskuP3gklQIcttSk4nOb5c6hZNu0ehEXzIpBK3+STHt1jrBbX2
+e99Aaxapsfefnuns5R5KdNcYMRJ8yFTKgFtJjl9ngh7aPdrCPNhWSGpsmdp1klIuvBvFaRN8yGQS
+VzWriyN2awcbnzac25QsmHWpDV1l5aTGtlrdZodpYmi3KDiCD5lKGQQeYCJ6Gr+z98rHtPscrcGB
+mkZSY6sUgXfS7k+IhB8yRSCAREJ0iYBu89WvaPc5GiWGLOtjSzOIfbzVuIU8TrtHIRJ8yILVESCX
+yheSnMPY00B0KfCJYugpPU5q843EvEilxj1McMvj2QPBhwwAQK2YTvRjzOMxx4z6ziK7vxrf2Ft6
+hNTYA33DYXjN4tiIImSebqHrgOBt8QwDnKGn7B3afd5MU0deNqmxtaqon9PuT6hEETKVMkixK30O
+0ZMfrabMv9Du86dcbE0tfjo2nchveiwHkkluoVto9yhUogiZxi0UXDj5bJJztPVnltHu86dcM+me
+IzW2Km3hdB91FP4IPUaiCFmwOgJUzjPuIjnHlkX5QxkNn9rtqfxqgy6N1NhertMew9/Hxk4UIQMA
+0LiFPAsc2eXK2ruy3qDd541kXPtsz/YlWUTuIWN1cU6B2ruJvUs6AtGEzEe9eNLurFCie4ldOnZA
+X2EqMtHu9fsuX/tqJ6mxvWXmaB+PKNG8TmgQzZMX5bsW5JxHLMk5WBasV1pObabd6/WKO7I+/cXi
+vxK7e3uyR/TeYHUE7TYFTTQhAwDwVd3yIuk56nuOn9R3FhG7KdJWetPJp0iNfTBjQcBs342RtHsU
+OlGFzEe9+JY9uvlqknNsWZQ/VNN8ahPtXgEAclu+fHbDjF2dpMb3dJm7F094jJ+oQrbU/0FwVXiv
+IT1P7pwXTuhNRXWU262r8/mI2A/ku8/M85vpu/Feyj2KgqhCBgDg7xm3m2XJ9sUyYL3UkEj0+9/N
+nK/bG7OBOUZsbzYfz9AjeBnVxBBdyIK0qydp71i2gPQ8D4a/U5/R8CmVkyD5zSkblgf+mtgCP/t0
+EWER07auotGbGIkuZMHqCPBxjUwEHrb4Wea/6f2C1pQ/89mf3lTELvK9/Rip8ZOS1ktn+W78Br+L
+TRzRhQwAYLbvxsh3M5aQX7qMAS5Zm/lMhbHocz760ncWJwar571Cco5Of2NCkM/qKXz04zA4kTpd
+sbOMI3wFyAiWZSVlxsLDJPspNxaypPvZo5sfmNN4kvahEx3RhqzcWMi9l7nqPj5CBgAAHDD5LakP
+keglr+mf60mXn5gXKTut33mN9nETI9GGjOM4Lr3+E8v+7MUq3oIGAN/oXw3iOO7KBLVQcqKQJb72
+PMcB83HepiTax0usRB0yjuO4zy5tzmM5fr97siwrOVt7aB3Hcf1jLLvt27rDt5H+KWLEkbx7E8qN
+hbQPlWiJPmTlxkLuvayVv+czZCOSktZLk8tejM5pPJk2mjrTrx797ItLCQtYjuXtP4WD52NWF7dn
+0j5MosZwHEdk4RV7UtCaCpmVO6K3xmbn0KqB1cU5TXd3n8JIXf2ZYekURsK5gRWMHDDtZktz9TWz
+xcDGp/G6de476Uujo2exWQu0K2k9LQ7BIUIGAHC27jCU1B+cszW2sJJ2Lfbg7fTFy2JmvXYeA0ae
+KH8nu5EVAU9A2NSt5ft1Ef60a6HtUPaquzBg/HGYkAEArAh4QhIRlFC5+8w8h9zIjuOA+TD33t8s
+m/PHUxgw/jjMx8Xrna07DOWNHyx+aklWLu1a+MImhcrDQ1YdDfF79H68CZNfDhkygO9OhlTteGTr
+suy/ApBZdddevKuLDpwb9HjOioAncL9nChw2ZAAAelMR5Ne8+YHc+dJTG0JLB2nXM9GSktZLe4MG
+n5s3betO/HhIj0OHbMSZK/tMZY1fxD0bm05sby+eMW9nLJk3W7vh1MqZ2/BiX8owZN8pMWRBYe2B
+A71Q+bsti/L7aNczVrvPzPML8F5xOGTq43fgdy/7gCH7ntymZLhUeyAB5MbELYvy7WbBnJvZfWae
+X4BP/N7Zkzfcj/eC2RcM2Y84W3fYXNPyjyegr/PEo/Fp/bTruRGWA4lH2vyIaZNWHJztu3Ephss+
+YchuIrcpGRo6vj14rU2369n4omtA/0wks//cgkkKmeZ+P8/4t4J8Vrvix0L7hiEbJb2pCBradY0N
+Hd++auyp+/LXtxY2ktpw7/tYFiSalQsmuzhp/muyKuolP018AJ4tFA4M2RjoTUXQ0pnb295d+q6x
+q+yrXnNj6ZTb5rZP1OpRiXmRMuvgsJazKiI83cI2adzCNk1yD5VgsIQJQzYB9KYi6DLXgqG7uNQ8
+2Ha2r7+1yDRYV8VYexukUugd6LMMW5XckJPEbdh12MSZ+xn5IOPs4uRicQGrzM3KWSdrXENnyaSu
+0Spl4N0qRZBaKfcGDJU4YMh4UNCaCkOW//xVQCZVYogcBIYMIcIc6ip8hGjAkCFEGIYMIcIwZAgR
+hiFDiDAMGUKEYcgQIgxDhhBhGDKECMOQIUQYhgwhwjBkCBGGIUOIMAwZQoRhyBAiDEOGEGEYMoQI
+w5AhRBiGDCHCMGQIEYYhQ4gwDBlChGHIECIMQ4YQYRgyhAjDkCFEGIYMIcIwZAgR9n+5cDQAZvFx
+1wAAAIRlWElmTU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEo
+AAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAACQAAAAAQAAAJAAAAABAAOgAQADAAAAAQABAACg
+AgAEAAAAAQAAANmgAwAEAAAAAQAAANgAAAAAeXQZvAAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAyMy0w
+OC0zMVQxMzo0NDoyNiswMDowMHm1cCUAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMjMtMDgtMzFUMTM6
+NDQ6MjYrMDA6MDAI6MiZAAAAKHRFWHRkYXRlOnRpbWVzdGFtcAAyMDIzLTA4LTMxVDEzOjQ0OjI2
+KzAwOjAwX/3pRgAAABF0RVh0ZXhpZjpDb2xvclNwYWNlADEPmwJJAAAAEnRFWHRleGlmOkV4aWZP
+ZmZzZXQAOTBZjN6bAAAAGHRFWHRleGlmOlBpeGVsWERpbWVuc2lvbgAyMTfDC1rWAAAAGHRFWHRl
+eGlmOlBpeGVsWURpbWVuc2lvbgAyMTYpA4s2AAAAEnRFWHR0aWZmOk9yaWVudGF0aW9uADG3q/w7
+AAAAAElFTkSuQmCC" />
+</svg>

+ 5 - 0
TEAMModelOS/ClientApp/src/router/routes.js

@@ -149,6 +149,11 @@ export const routes = [{
     path: '/lepei-sso',
     component: () => import('@/view/sso/LepeiSSO.vue')
 },
+    // 联盟-单点登录
+    {
+        path: '/tmdid-sso',
+        component: () => import('@/view/sso/TmdSSO.vue')
+    },
 //单点登录-学生端
 {
     path: '/student',

+ 1 - 1
TEAMModelOS/ClientApp/src/view/areaArtExam/WorkData.vue

@@ -214,7 +214,7 @@ export default {
           info.status = hasWork || hasZY ? 1 : 0
           info.createTime = hasWork ? work.attachments[0].createTime : hasZY ? work.createTime : 0
           info.count = hasWork ? work.attachments.length : hasZY ? 1 : 0
-          info.files = hasWork ? work.attachments : hasZY ? [{ type: 'zy', name: '评唱结果', url: work.url }] : []
+          info.files = hasZY ? [{ type: 'zy', name: '评唱结果', url: work.url }] : hasWork ? work.attachments :  []
           this.workData.push(info)
         })
       }

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

@@ -2,6 +2,10 @@
   <div class="create-art-container">
     <vuescroll>
       <div class="create-form-wrap">
+        <span style="margin-bottom: 20px;display: block;cursor: pointer;color: #2D8CF0;" @click="goBack">
+          <Icon type="md-arrow-back" />
+          <span>{{ $t('evaluation.index.backList') }}</span>
+        </span>
         <!-- 上一步 -->
         <div v-show="step > 0" class="step-handler last-step" @click="lastStep()">
           <span class="step-icon-wrap">
@@ -299,6 +303,9 @@ export default {
     }
   },
   methods: {
+    goBack(){
+      this.$router.go(-1)
+    },
     test() {
       console.log(this.settingDetail, this.getZYData())
     },

+ 7 - 1
TEAMModelOS/ClientApp/src/view/artexam/Mgt.vue

@@ -600,7 +600,13 @@ export default {
           this.subjectId = n[0].id
         }
       }
-    }
+    },
+    "$store.state.user.curSemester": {
+				deep: true,
+				handler(n, old) {
+          this.getAreaSetting()
+				}
+			}
   }
 
 }

+ 2 - 2
TEAMModelOS/ClientApp/src/view/artexam/WorkData.vue

@@ -195,7 +195,7 @@ export default {
       })
     },
     setTableData(data) {
-      console.error(data)
+      console.error(data,this.taskInfo)
       this.workData = []
       if (this.curClass && this.curClass.members) {
         let students = this._.cloneDeep(this.curClass.members)
@@ -210,7 +210,7 @@ export default {
           info.status = hasWork || hasZY ? 1 : 0
           info.createTime = hasWork ? work.attachments[0].createTime : hasZY ? work.createTime : 0
           info.count = hasWork ? work.attachments.length : hasZY ? 1 : 0
-          info.files = hasWork ? work.attachments : hasZY ? [{ type: 'zy', name: '评唱结果', url: work.url }] : []
+          info.files = hasZY ? [{ type: 'zy', name: '评唱结果', url: work.url }] : hasWork ? work.attachments :  []
           this.workData.push(info)
         })
       }

+ 13 - 9
TEAMModelOS/ClientApp/src/view/coursemgt/NewCusMgt.vue

@@ -96,7 +96,7 @@
 						<p class="bottom">
 							<Tag color="blue">{{ course.subject.name }}</Tag>
 							<Tag color="green">{{ curPeriod.grades[course.grade] }}</Tag>
-							<Tag color="orange">{{ $t("jyzx.offline.creator") }}-{{ course.creatorName }}</Tag>
+							<!-- <Tag color="orange">{{ $t("jyzx.offline.creator") }}-{{ course.creatorName }}</Tag> -->
 						</p>
 					</div>
 				</div>
@@ -301,7 +301,9 @@
 						scope: "school",
 						grant_type: "list",
 						periodId: this.$store.state.user.curPeriod.id,
-						code: this.$store.state.userInfo.schoolCode
+						code: this.$store.state.userInfo.schoolCode,
+						year: this.filterYear,
+						semesterId: this.curPeriod.semesters[this.filterSemetsterIndex].id
 					})
 					.then((res) => {
 						this.originCourseList = res.courseBases
@@ -596,16 +598,14 @@
 				this.filterGrade = -1
 				this.sortValue = 'grade'
 				this.canEmitSelectChange = false
+				this.onlyShowConfigCourse = false
 			},	
 			onFilterConfig(val){
-				console.error(val)
 				if(!this.canEmitSelectChange) return
 				let gradeCond = this.filterGrade > -1
 				let subjectCond = this.filterSubjectIndex > -1
 				let nowList = this.originCourseList.filter((i) => (gradeCond ? i.grade === this.filterGrade : true) && (subjectCond ? i.subject.id === this.curPeriod.subjects[this.filterSubjectIndex].id : true));
-				console.error(nowList)
 				this.courseList = !val ? this._.cloneDeep(nowList) : nowList.filter(i => i.count > 0)
-				console.error(this.courseList)
 				if(this.courseList.length){
 					this.onFilterSort(this.sortValue)
 					this.onCourseClick(this.courseList[0], 0);
@@ -627,7 +627,7 @@
 				if(!this.canEmitSelectChange) return
 				if (val || val === 0) {
 					let subjectCond = this.filterSubjectIndex > -1
-					this.courseList = this.originCourseList.filter((i) => i.grade === val && (subjectCond ? i.subject.id === this.curPeriod.subjects[this.filterSubjectIndex].id : true));
+					this.courseList = this.originCourseList.filter((i) => i.grade === val && (subjectCond ? i.subject.id === this.curPeriod.subjects[this.filterSubjectIndex].id : true) && (this.onlyShowConfigCourse ? i.count > 0 : true));
 					if (this.courseList.length) {
 						this.onCourseClick(this.courseList[0], 0);
 					} else {
@@ -641,7 +641,7 @@
 				if(!this.canEmitSelectChange) return
 				if (val || val === 0) {
 					let gradeCond = this.filterGrade > -1
-					this.courseList = this.originCourseList.filter((i) => i.subject.id === this.curPeriod.subjects[val].id && (gradeCond ? i.grade === this.filterGrade : true));
+					this.courseList = this.originCourseList.filter((i) => i.subject.id === this.curPeriod.subjects[val].id && (gradeCond ? i.grade === this.filterGrade : true) && (this.onlyShowConfigCourse ? i.count > 0 : true));
 					if (this.courseList.length) {
 						this.onCourseClick(this.courseList[0], 0);
 					} else {
@@ -662,8 +662,12 @@
 					return
 				}
 				this.isLoading = false;
-				this.courseList = this._.cloneDeep(this.originCourseList);
-				this.onCourseClick(this.courseList[0], 0);
+				if(this.onlyShowConfigCourse){
+					this.onFilterConfig(true)
+				}else{
+					this.courseList =  this._.cloneDeep(this.originCourseList);
+					this.onCourseClick(this.courseList[0], 0);
+				}
 			},
 			/* 课程操作 */
 			doAction(action) {

+ 2 - 2
TEAMModelOS/ClientApp/src/view/coursemgt/components/AddTask.vue

@@ -119,9 +119,9 @@
                     val.assistants = []
                     return
                 }
-                if(val.assistants.length > 3){
+                if(val.assistants.length > 10){
                     this.$Message.warning(this.$t('newCusMgt.tip3'))
-                    val.assistants = val.assistants.slice(0,3)
+                    val.assistants = val.assistants.slice(0,10)
                 }else{
                     this.$set(this.allGroups,index,val)
                 }

+ 6 - 2
TEAMModelOS/ClientApp/src/view/coursemgt/components/ImportTask.vue

@@ -37,9 +37,9 @@
 				<template slot-scope="{ row, index }" slot="grade">
 					<span>{{ curPeriod.grades[row.grade] }}</span>
 				</template>
-				<template slot-scope="{ row, index }" slot="assistants">
+				<!-- <template slot-scope="{ row, index }" slot="assistants">
 					<span>{{ row.assistants ? getTchName(row.assistants[0]) : "-" }}</span>
-				</template>
+				</template> -->
                 <template slot-scope="{ row, index }" slot="invalidCode">
 					<span :style="{ color: row.invalidCode === 0 ? '#19be6d' : '#ff0000' }">{{ errorArr.find(i => i.code === row.invalidCode).msg }}</span>
 				</template>
@@ -350,6 +350,10 @@
                     {
                         code:21,
                         msg:this.$t('newCusMgt.errorTip6')
+                    },
+					{
+                        code:22,
+                        msg:this.$t('newCusMgt.tip3')
                     },
                 ]
             }

+ 5 - 0
TEAMModelOS/ClientApp/src/view/login/page/Student.less

@@ -1,3 +1,8 @@
+.icon-educlowudtw {
+    font-size: 49px;
+    padding: 6px;
+    border-radius: 9px;
+}
 .loginDiv{
     display: flex;
     align-items: center;

+ 11 - 0
TEAMModelOS/ClientApp/src/view/login/page/Student.vue

@@ -163,22 +163,32 @@
                     <Icon custom="iconfont icon-dingding" class="other-login-icon" />
                     <p class="other-login-text">DingDing</p>
                 </div> -->
+          <!-- facebook -->
           <div class="other-login-item" @click="oauthLogin('facebook')" v-if="srvAdr == 'Global'">
             <Icon type="logo-facebook" class="other-login-icon" />
             <p class="other-login-text">
               {{$t('login.communy.fb')}}
             </p>
           </div>
+          <!-- google -->
           <div class="other-login-item" @click="oauthLogin('google')" v-if="srvAdr == 'Global'">
             <Icon custom="iconfont icon-google" class="other-login-icon" />
             <p class="other-login-text">
               {{$t('login.communy.google')}}
             </p>
           </div>
+          <!-- 微信 -->
           <div style="margin:auto" class="other-login-item" v-if="srvAdr == 'China'" @click="oauthLogin('wechat')">
             <Icon custom="iconfont icon-wechat" class="other-login-icon" />
             <p class="other-login-text">{{$t('login.communy.wechat')}}</p>
           </div>
+          <!-- 教育雲 -->
+          <div class="other-login-item" @click="oauthLogin('educloudtw')" v-if="srvAdr == 'Global'">
+            <v-icon iconClass="educloudtw" class="icon-educlowudtw"></v-icon>
+            <p class="other-login-text">
+              {{$t('教育雲')}}
+            </p>
+          </div>
         </div>
       </div>
       <!-- 醍摩豆qrcode登录 -->
@@ -266,6 +276,7 @@ import {
   mapState,
   mapGetters
 } from 'vuex'
+import "@/icons/svg/educloudtw.svg";
 
 export default {
   data() {

+ 5 - 0
TEAMModelOS/ClientApp/src/view/login/page/Teacher.less

@@ -1,3 +1,8 @@
+.icon-educlowudtw {
+    font-size: 49px;
+    padding: 6px;
+    border-radius: 9px;
+}
 .loginDiv{
     display: flex;
     align-items: center;

+ 8 - 0
TEAMModelOS/ClientApp/src/view/login/page/Teacher.vue

@@ -168,6 +168,13 @@
             {{$t('login.communy.wechat')}}
           </p>
         </div>
+        <!-- 教育雲 -->
+        <div class="other-login-item" @click="oauthLogin('educloudtw')" v-if="srvAdr == 'Global'">
+          <v-icon iconClass="educloudtw" class="icon-educlowudtw"></v-icon>
+          <p class="other-login-text">
+            {{$t('教育雲')}}
+          </p>
+        </div>
       </div>
     </div>
     <div class="right-box" v-show="qrloginFlag">
@@ -212,6 +219,7 @@ import { EventSourcePolyfill } from 'event-source-polyfill';
 import QRCode from 'qrcodejs2'
 import { User } from '@/service/User'
 import { mapState, mapGetters } from 'vuex'
+import "@/icons/svg/educloudtw.svg";
 export default {
   data() {
     const validateID = (rule, value, callback) => {

+ 6 - 3
TEAMModelOS/ClientApp/src/view/settings/SchoolMgmt.vue

@@ -462,7 +462,9 @@ export default {
     },
 
     applyJoin() {
-      this.applyModal = true
+      // this.applyModal = true C481 学校管理--调整“申请建立学校”及“申请成为管理员”为跳转官网地址
+      let url = localStorage.local === 'zh-cn' ? 'https://www.habook.com.cn/event.php?act=view&id=46' : localStorage.local === 'zh-tw' ? 'https://www.habook.com/zh-tw/event.php?act=view&id=158' : 'https://www.habook.com/en/event.php?act=view&id=158'
+      window.open(url)
     },
 
     onSelectSchool(val, item) {
@@ -471,8 +473,9 @@ export default {
         if (item.hasManager) {
           this.onJoinSchool(item)
         } else {
-          this.applyManagerModal = true
-          this.curApplySchName = item.name
+          // this.applyManagerModal = true
+          // this.curApplySchName = item.name
+          this.applyJoin()
         }
         this.searchSchoolIndex = null
         this.$refs.schoolSelect.setQuery(' ')

+ 168 - 0
TEAMModelOS/ClientApp/src/view/sso/TmdSSO.vue

@@ -0,0 +1,168 @@
+<template>
+  <div class="sso-container">
+    <img class="tmd-logo" src="/favicon.ico" alt="">
+    <p class="title">醍摩豆单点登录</p>
+  </div>
+</template>
+<script>
+import MD5 from 'js-md5'
+import jwtDecode from 'jwt-decode'
+import { User } from '@/service/User'
+export default {
+  data() {
+    return {
+      cancelToBand: false,
+      routerData: {},
+      iesLoginRes: {}
+    }
+  },
+  created() {
+    this.routerData = this.$route.query
+    if (this.routerData.status) {
+      let status = this.routerData.status
+      switch (status) {
+        case '1':
+          // 参数错误
+          this.$Message.error({
+            content: '跳转参数错误,验证失败',
+            duration: 2
+          })
+          break
+        case '200':
+          //已绑定省平台,直接登录
+          // 验证返回参数
+          if (this.routerData.id_token && this.routerData.access_token && this.routerData.expires_in && this.routerData.token_type) {
+            this.loginProcess({
+              id_token: this.routerData.id_token,
+              access_token: this.routerData.access_token,
+              expires_in: this.routerData.expires_in,
+              token_type: this.routerData.token_type
+            })
+          } else {
+            this.$Message.error({
+              content: '登录参数错误,登录失败',
+              duration: 2
+            })
+          }
+          break
+        case '4':
+          // 账号未绑定,需要登录绑定
+          this.$Modal.confirm({
+            title: '实名认定',
+            content: `是否前往手机实名认证页面?`,
+            okText: '是',
+            cancelText: '否',
+            onOk: () => {
+              if (this.routerData.param && this.routerData.type && this.routerData.bindurl) {
+                this.toLoginBanding()
+              } else {
+                this.$Message.error({
+                  content: '账号绑定参数错误',
+                  duration: 2
+                })
+              }
+            },
+            onCancel: () => {
+              this.cancelToBand = true
+            }
+          })
+          break
+        case '5':
+          // 提供的培训 ID(343609) 和教师 ID(766092)与省平台不匹配或不存在,请联系相关人员
+          let ps = decodeURIComponent(this.routerData.param)
+          let p = JSON.parse(ps || '{}')
+          this.$Modal.warning({
+            title: '信息异常',
+            content: `提供的培训 ID(${p.Pxid}) 和教师 ID(${p.tid})与省平台不匹配或不存在,请联系相关人员!`
+          })
+          break
+        default:
+          break
+      }
+    } else {
+      this.$Message.error({
+        content: '跳转参数错误,验证失败',
+        duration: 2
+      })
+    }
+  },
+  methods: {
+    clearData() {
+      let login_schoolCode = localStorage.getItem('login_schoolCode')
+      let srvAdr = localStorage.getItem('srvAdr')
+      localStorage.clear()
+      localStorage.setItem('srvAdr', srvAdr)
+      if (login_schoolCode) localStorage.setItem('login_schoolCode', login_schoolCode)
+    },
+    toLoginBanding() {
+      let queryData = this._.cloneDeep(this.$route.query)
+      queryData.loginType = 'trainsso'
+      //根据站点判断跳转路由
+      this.$router.push({
+        path: '/lepeiBandphone',
+        query: queryData
+      })
+    },
+    bandingID(idToken) {
+      this.$api.train.thirdSSO(this.routerData.bindurl, {
+        type: this.routerData.type,
+        param: this.routerData.param,
+        id_token: idToken
+      }).then(
+        res => {
+          //绑定成功
+          if (res && res.status == 200) {
+            this.$Message.success("绑定成功")
+            this.loginProcess(this.iesLoginRes)
+          } else {
+            this.$Message.error("绑定失败")
+          }
+        },
+        err => {
+
+        }
+      )
+    },
+    loginProcess(idRes) { // 登入用function
+      this.clearData() //这里暂定解决登录失败的问题
+      sessionStorage.setItem('identity', 'teacher')
+      /* 进行教师登录 */
+      this.$loginTools.teacherLogin(idRes).then(info => {
+        // 前往区级平台
+        if (info.toArea) {
+          localStorage.setItem('platform', 'area')
+          this.$router.push({ path: '/area' })
+        } else {
+          // 前往校级平台 判断是否有记录的目标地址 如果没有则按照站点来进行对应跳转固定页面
+          let targetPath = localStorage.getItem('target_path')
+          let defaultPath = '/home'
+          let homePath = targetPath ? (targetPath.includes('home/') ? targetPath : defaultPath) : defaultPath
+          localStorage.setItem('platform', 'school')
+          localStorage.setItem('target_path', '')
+          this.$router.push({ path: homePath })
+        }
+      })
+    },
+  },
+
+}
+</script>
+<style scoped lang="less">
+.sso-container {
+  display: flex;
+  flex-direction: row;
+  justify-content: center;
+  align-items: center;
+  width: 100%;
+  height: 100%;
+  background-image: url("../../assets/image/bak_light.jpg");
+  .title {
+    color: #f0f0f0;
+    margin-left: 30px;
+    font-size: 28px;
+  }
+  .tmd-logo {
+    width: 40px;
+  }
+}
+</style>

+ 1 - 1
TEAMModelOS/ClientApp/src/view/student-web/AppNew.vue

@@ -119,7 +119,7 @@
                     <div id="profile-pop">
                         <div class="profile-name">
                             <p>{{ userInfo.name }}</p>
-                            <p>ID:{{ userInfo.studentId }}</p>
+                            <p>ID:{{ userInfo.sub }}</p>
                             <template v-if="userInfo.scope != 'tmduser' && user.studentProfile.classinfo">
                                 <p>{{ $t("ae.ae6") }}:{{ user.studentProfile.classinfo.name }}</p>
                             </template>

+ 2 - 1
TEAMModelOS/ClientApp/src/view/teachcontent/index.vue

@@ -857,7 +857,7 @@ export default {
     delFileBatch() {
       if (this.selections.length == 0) {
         if (this.showType) {
-          this.$Message.warning(this.$t('teachContent.delBatchTips1'))
+          this.$Message.warning(this.$t('teachContent.delBatchTips2'))
         } else {
           this.$Message.warning(this.$t('teachContent.delBatchTips2'))
         }
@@ -897,6 +897,7 @@ export default {
               }
               this.fileListShow = this._.cloneDeep(this.fileList[this.activeType])
               this.$Message.success(this.$t('teachContent.props2'))
+              this.selections = []
               //如果是从最近删除,需要更新其他类型列表
               if (this.activeType == 'recent') {
                 this.selections.forEach(item => {

+ 0 - 11
TEAMModelOS/ClientApp/src/view/user/LepeiBindPhone.vue

@@ -175,17 +175,6 @@ export default {
           } else {
             this.$Message.error(this.$t('login.phoneerr'))
           }
-          // 新账号会返回登录信息
-          // else if (res.id_token) {
-          //     // data = {
-          //     //     id_token: res.id_token,
-          //     //     loginData: res
-          //     // }
-          //     data = {
-          //         phone: this.accFormat
-          //     }
-          // }
-          // this.bandingID(data)
         },
         err => {
           this.$Message.error(this.$t('login.phoneerr'))

+ 130 - 38
TEAMModelOS/Controllers/Analysis/ArtAnalysisController.cs

@@ -179,10 +179,16 @@ namespace TEAMModelOS.Controllers.Analysis
                     examResults.Add(item);
                 }
                 List<KeyValuePair<string, List<(string name, double score, double aver)>>> pointPersent = new();
-                (KeyValuePair<string, List<string>> key1, KeyValuePair<string, List<string>> key2, KeyValuePair<string, List<(string name, double score, double average)>> key3, KeyValuePair<string, List<(string name, double score)>> key4) = DoKnowledgePoint(examResults[0], info);
+                List<KeyValuePair<string, List<(string name, double score, double point, string sId)>>> stuPersent = new();
+                (KeyValuePair<string, List<string>> key1, KeyValuePair<string, List<string>> key2, KeyValuePair<string, List<(string name, double score, double average)>> key3,
+                    KeyValuePair<string, List<(string name, double score)>> key4, KeyValuePair<string, List<(string name, double score, double point, string cId)>> key5,
+                    KeyValuePair<string, List<(string name, double score, double point, string sId)>> key6) = DoKnowledgePoint(examResults[0], info);
                 KeyValuePair<string, List<(string id, double sta, double pass, string stu)>> key = DoSubjectScatter(examResults[0]);
                 pointPersent.Add(key3);
+                stuPersent.Add(key6);
                 List<(string name, double score, double av)> blockScore = new();
+                List<(string name, double score, double av, string sId)> stuBlockScore = new();
+                List<(string name, double score, double av, string cId)> claBlockScore = new();
                 foreach (var block in knos)
                 {
                     double sc = 0;
@@ -198,8 +204,50 @@ namespace TEAMModelOS.Controllers.Analysis
                             }
                         }
                     }
+                    foreach (var (name, score, point, sId) in key6.Value)
+                    {
+                        double realScore = 0;
+                        double realPoint = 0;
+                        if (null != block.kno && block.kno.Contains(name))
+                        {
+                            realScore = score;
+                            realPoint = point;
+                        }
+                        stuBlockScore.Add((block.name, realScore, realPoint, sId));
+                    }
+                    foreach (var (name, score, point, cId) in key5.Value)
+                    {
+                        double realScore = 0;
+                        double realPoint = 0;
+                        if (null != block.kno && block.kno.Contains(name))
+                        {
+                            realScore = score;
+                            realPoint = point;
+                        }
+                        claBlockScore.Add((block.name, realScore, realPoint, cId));
+                    }
                     blockScore.Add((block.name, sc, av));
                 }
+                var stuBlock = stuBlockScore.GroupBy(x => x.sId).Select(z => new
+                {
+                    z.Key,
+                    block = z.ToList().GroupBy(c => c.name).Select(k => new
+                    {
+                        k.Key,
+                        score = k.ToList().Sum(p => p.score),
+                        point = k.ToList().Sum(p => p.av)
+                    })
+                });
+                var claBlock = claBlockScore.GroupBy(x => x.cId).Select(z => new
+                {
+                    z.Key,
+                    block = z.ToList().GroupBy(c => c.name).Select(k => new
+                    {
+                        k.Key,
+                        score = k.ToList().Sum(p => p.score),
+                        point = k.ToList().Sum(p => p.av)
+                    })
+                });
                 var blk = blockScore.Select(x => new
                 {
                     x.name,
@@ -208,6 +256,39 @@ namespace TEAMModelOS.Controllers.Analysis
                     dimension = setting.dimensions.Where(s => s.blocks.Contains(x.name)).Select(x => x.dimension)
                 });
                 //获取维度得分率
+                List<(string stuId, double score, double point, string dim)> stuDims = new();
+                List<(string claId, double score, double point, string dim)> claDims = new();
+                foreach (var dimm in setting.dimensions)
+                {
+                    double dimScore = 0;
+                    double dimPoint = 0;
+                    if (dimm.subjectBind.Equals(subjectId.GetString()))
+                    {
+                        foreach (var stuDim in stuBlock)
+                        {
+                            foreach (var dd in stuDim.block)
+                            {
+                                if (dimm.blocks.Contains(dd.Key))
+                                {
+                                    dimScore += dd.score;
+                                    dimPoint += dd.point;
+                                }
+                            }
+                            stuDims.Add((stuDim.Key, dimScore, dimPoint, dimm.dimension));
+                        }
+                        foreach (var claDim in claBlock) {
+                            foreach (var dd in claDim.block)
+                            {
+                                if (dimm.blocks.Contains(dd.Key))
+                                {
+                                    dimScore += dd.score;
+                                    dimPoint += dd.point;
+                                }
+                            }
+                            claDims.Add((claDim.Key, dimScore, dimPoint, dimm.dimension));
+                        }
+                    }
+                }
                 var dim = setting.dimensions.Where(q => q.subjectBind.Equals(subjectId.GetString())).Select(x => new
                 {
                     x.dimension,
@@ -219,6 +300,7 @@ namespace TEAMModelOS.Controllers.Analysis
                     }).Sum(o => o.persent) / x.blocks.Count, 2)
                 });
 
+
                 var kno = key4.Value.Select(x => new
                 {
                     x.name,
@@ -237,8 +319,25 @@ namespace TEAMModelOS.Controllers.Analysis
                     key.Value.Where(c => c.id.Equals(s.sIds)).FirstOrDefault().sta,
                     key.Value.Where(c => c.id.Equals(s.sIds)).FirstOrDefault().pass,
                     key.Value.Where(c => c.id.Equals(s.sIds)).FirstOrDefault().stu,
+                    kno = key6.Value.Where(c => c.sId.Equals(s.sIds)).Select(z => new
+                    {
+                        z.name,
+                        persent = Math.Round(z.point > 0 ? z.score / z.point : 0, 2),
+                        block = knos.Where(v => null != v.kno && v.kno.Contains(z.name)).Select(x => x.name)
+                    }),
+                    block = stuBlock.Where(c => c.Key.Equals(s.sIds)).FirstOrDefault().block.Select(x => new
+                    {
+                        name = x.Key,
+                        persent = Math.Round(x.point > 0 ? x.score / x.point : 0, 2)
+                    }),
+                    dim = stuDims.Where(c => c.stuId.Equals(s.sIds)).Select(z => new
+                    {
+                        name = z.dim,
+                        persent = Math.Round(z.point > 0 ? z.score / z.point : 0, 2)
+                    })
+
                 });
-                List<(string cId, double sc, double max, double min, double excellent, double pass)> clsInfo = new();
+                List<(string cId, double sc, double max, double min, double excellent, double pass,double count)> clsInfo = new();
                 foreach (var cls in classLists)
                 {
                     double classTotal = 0;
@@ -256,7 +355,7 @@ namespace TEAMModelOS.Controllers.Analysis
                     double ex = Math.Round(excellentc / scores.Count, 2);
                     double passc = scores.Where(s => s >= 60).Count();
                     double pa = Math.Round(passc / scores.Count, 2);
-                    clsInfo.Add((cls.id, classTotal / scores.Count, maxc, minc, ex, pa));
+                    clsInfo.Add((cls.id, classTotal / scores.Count, maxc, minc, ex, pa, scores.Count));
                 }
                 //班级信息
                 var cInfo = clsInfo.Select(x => new
@@ -268,6 +367,22 @@ namespace TEAMModelOS.Controllers.Analysis
                     x.min,
                     x.excellent,
                     x.pass,
+                    kno = key5.Value.Where(c => c.cId.Equals(x.cId)).Select(z => new
+                    {
+                        z.name,
+                        persent = Math.Round(z.point > 0 ? z.score / x.count / z.point : 0, 2),
+                        block = knos.Where(v => null != v.kno && v.kno.Contains(z.name)).Select(x => x.name)
+                    }),
+                    block = claBlock.Where(c => c.Key.Equals(x.cId)).FirstOrDefault().block.Select(z => new
+                    {
+                        name = z.Key,
+                        persent = Math.Round(z.point > 0 ? z.score / x.count/ z.point : 0, 2)
+                    }),
+                    dim = claDims.Where(c => c.claId.Equals(x.cId)).Select(z => new
+                    {
+                        name = z.dim,
+                        persent = Math.Round(z.point > 0 ? z.score / x.count / z.point : 0, 2)
+                    }),
                     examResults[0].classes.Where(c => c.id.Equals(x.cId)).FirstOrDefault().gradeId
                 });
                 //年级信息
@@ -372,7 +487,8 @@ namespace TEAMModelOS.Controllers.Analysis
             }
         }
         //获取知识点得分率
-        private static (KeyValuePair<string, List<string>>, KeyValuePair<string, List<string>>, KeyValuePair<string, List<(string name, double score, double average)>>, KeyValuePair<string, List<(string name, double score)>>) DoKnowledgePoint(ExamResult exam, ExamInfo info)
+        private static (KeyValuePair<string, List<string>>, KeyValuePair<string, List<string>>, KeyValuePair<string, List<(string name, double score, double average)>>,
+            KeyValuePair<string, List<(string name, double score)>>, KeyValuePair<string, List<(string name, double score, double point, string cId)>>, KeyValuePair<string, List<(string name, double score, double point, string sId)>>) DoKnowledgePoint(ExamResult exam, ExamInfo info)
         {
 
             HashSet<string> knowledge = new HashSet<string>();
@@ -407,7 +523,7 @@ namespace TEAMModelOS.Controllers.Analysis
             }
             else
             {
-                return (default, default, default, default);
+                return (default, default, default, default, default, default);
             }
             point = info.papers[index].point;
             result = exam.studentScores;
@@ -438,8 +554,8 @@ namespace TEAMModelOS.Controllers.Analysis
             //学生得分情况
             List<double> Score = new List<double>();
             List<(string name, double score, double average)> pointScore = new();
-            List<(string name, double score,string cId)> classInfo = new();
-            List<(string name, double score, string sId)> stuInfo = new();
+            List<(string name, double score, double point, string cId)> classInfo = new();
+            List<(string name, double score, double point, string sId)> stuInfo = new();
             List<(string name, double score)> pointTScore = new();
             for (int k = 0; k < knowledgeName.Count; k++)
             {
@@ -463,15 +579,16 @@ namespace TEAMModelOS.Controllers.Analysis
                                 scores += exam.studentScores[index][n] * itemPersent;
                                 stuScore = exam.studentScores[index][n] * itemPersent;
                             }
-                            stuInfo.Add((knowledgeName[k], stuScore, id));
+                            stuInfo.Add((knowledgeName[k], stuScore, OnePoint, id));
                         }
-                        foreach (var cla in exam.classes) {
+                        foreach (var cla in exam.classes)
+                        {
                             double classScores = 0;
                             for (int i = cla.range[0]; i <= cla.range[1]; i++)
                             {
                                 classScores += exam.studentScores[i][n] * itemPersent;
                             }
-                            classInfo.Add((knowledgeName[k],classScores,cla.id));
+                            classInfo.Add((knowledgeName[k], classScores, OnePoint, cla.id));
                         }
                     }
                     n++;
@@ -495,39 +612,14 @@ namespace TEAMModelOS.Controllers.Analysis
 
             }
 
-            // 获取班级学生知识点得分
-           /* foreach (var cla in exam.classes)
-            {
-                List<(string cId, string kno, double score)> classInfo = new();
-                double classScores = 0;
-                for (int k = 0; k < knowledgeName.Count; k++)
-                {
-                    double OnePoint = 0;
-                    int n = 0;
-                    info.papers[index].knowledge.ForEach(kno =>
-                    {
-                        if (kno.Contains(knowledgeName[k]))
-                        {
-                            var itemPersent = kno.Count > 0 ? 1 / Convert.ToDouble(kno.Count) : 0;
-                            OnePoint += point[n] * itemPersent;
-                            for (int i = cla.range[0]; i < cla.range[1]; i++)
-                            {
-                                classScores += exam.studentIds[i][n] * itemPersent;
-                            }
-                        }
-                        n++;
-                    });
-                    classInfo.Add((cla.id, knowledgeName[k], classScores));
-                }
-
-            }*/
-
             KeyValuePair<string, List<string>> key1 = new(exam.subjectId, knowledgeName);
             KeyValuePair<string, List<string>> key2 = new(exam.subjectId, per);
             KeyValuePair<string, List<(string name, double score, double average)>> key3 = new(exam.subjectId, pointScore);
             KeyValuePair<string, List<(string name, double score)>> key4 = new(exam.subjectId, pointTScore);
+            KeyValuePair<string, List<(string name, double score, double point, string cId)>> key5 = new(exam.subjectId, classInfo);
+            KeyValuePair<string, List<(string name, double score, double point, string sId)>> key6 = new(exam.subjectId, stuInfo);
             //KeyValuePair<string, List<double>> key3 = new KeyValuePair<string, List<double>>(exam.subjectId, allPer);          
-            return (key1, key2, key3, key4);
+            return (key1, key2, key3, key4, key5, key6);
         }
         private KeyValuePair<string, List<(string id, double sta, double pass, string stu)>> DoSubjectScatter(ExamResult e)
         {

+ 8 - 12
TEAMModelOS/Controllers/Both/CourseBaseController.cs

@@ -16,21 +16,10 @@ using Azure;
 using Microsoft.Extensions.Configuration;
 using TEAMModelOS.Filter; 
 using HTEXLib.COMM.Helpers; 
-using System.Globalization;
 using TEAMModelOS.SDK;
-using Microsoft.AspNetCore.Authorization;
 using StackExchange.Redis;
-using Azure.Storage.Blobs.Models;
-using Microsoft.Azure.Amqp.Sasl;
-using DocumentFormat.OpenXml.Drawing.Charts;
-using FastJSON;
-using OpenXmlPowerTools;
-using DocumentFormat.OpenXml.Drawing.Spreadsheet;
+
 using System.Text.RegularExpressions;
-using System.Security.Claims;
-using DocumentFormat.OpenXml.Bibliography;
-using DocumentFormat.OpenXml.Spreadsheet;
-using static SKIT.FlurlHttpClient.Wechat.TenpayV3.Models.CreateApplyForSubjectApplymentRequest.Types;
 
 namespace TEAMModelOS.Controllers.Both
 {
@@ -1537,6 +1526,13 @@ namespace TEAMModelOS.Controllers.Both
                                 if (!string.IsNullOrWhiteSpace(item.assistants))
                                 {
                                     assistants = Regex.Split(item.assistants, "\\.|\\.|\\、|\\:|\\:|\\,|\\,|\\;|\\;");
+
+                                    if (assistants.Length>10) {
+
+                                        item.invalidCode = 22;
+                                        courseInvalidImports.Add(item);
+                                        continue;
+                                    }
                                     var invalidAssistants = assistants.Except(teachers.Select(x => x.id));
                                     if (invalidAssistants != null && invalidAssistants.Any())
                                     {

+ 874 - 2
TEAMModelOS/Controllers/Client/AClassONEController.cs

@@ -1,5 +1,11 @@
 using Azure.Cosmos;
 using Azure.Storage.Blobs.Models;
+using Azure.Storage.Sas;
+using DocumentFormat.OpenXml.Drawing.Charts;
+using DocumentFormat.OpenXml.Office2010.Excel;
+using DocumentFormat.OpenXml.Office2021.DocumentTasks;
+using DocumentFormat.OpenXml.Spreadsheet;
+using DocumentFormat.OpenXml.Wordprocessing;
 using HTEXLib.COMM.Helpers;
 using Microsoft.AspNetCore.Authorization;
 using Microsoft.AspNetCore.Http;
@@ -20,12 +26,23 @@ using System.Reflection;
 using System.Text;
 using System.Text.Json;
 using System.Threading.Tasks;
+using TEAMModelOS.Controllers.Analysis;
+using TEAMModelOS.Controllers.Both;
+using TEAMModelOS.Filter;
 using TEAMModelOS.Models;
+using TEAMModelOS.SDK;
 using TEAMModelOS.SDK.DI;
 using TEAMModelOS.SDK.Extension;
 using TEAMModelOS.SDK.Models;
+using TEAMModelOS.SDK.Models.Cosmos.Common;
+using TEAMModelOS.SDK.Models.Cosmos.Student;
+using TEAMModelOS.SDK.Models.Service;
 using TEAMModelOS.SDK.Services;
+using TEAMModelOS.Services;
 using static TEAMModelOS.SDK.Services.BlobService;
+using CourseDto = TEAMModelOS.Controllers.Both.CourseDto;
+using Period = TEAMModelOS.SDK.Models.Period;
+
 namespace TEAMModelOS.Controllers
 {
 
@@ -53,13 +70,16 @@ namespace TEAMModelOS.Controllers
         private readonly Option _option;
         private readonly SnowflakeId _snowflakeId;
         private readonly IConfiguration _configuration;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly HttpTrigger _httpTrigger;
+        private readonly IPSearcher _searcher;
         public AClassONEController(
             AzureStorageFactory azureStorage,
             AzureRedisFactory azureRedis,
             AzureCosmosFactory azureCosmos,
             DingDing dingDing,
             SnowflakeId snowflakeId,
-            IOptionsSnapshot<Option> option, IHttpClientFactory httpClient, IConfiguration configuration)
+            IOptionsSnapshot<Option> option, IHttpClientFactory httpClient, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService, IPSearcher searcher, HttpTrigger httpTrigger)
         {
             _azureStorage = azureStorage;
             _azureRedis = azureRedis;
@@ -69,6 +89,9 @@ namespace TEAMModelOS.Controllers
             _option = option?.Value;
             _httpClient = httpClient;
             _configuration = configuration;
+            _coreAPIHttpService=coreAPIHttpService;
+            _searcher=searcher;
+            _httpTrigger=httpTrigger;
         }
 
         /// <summary>
@@ -111,8 +134,527 @@ namespace TEAMModelOS.Controllers
                 return BadRequest(Content);
             }
         }
+        /// <summary>
+        /// 获取教师信息
+        /// </summary>
+        /// <param name="json"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-teacher-info")]
+#if !DEBUG
+        [Authorize(Roles = "AClassONE")]
+#endif
+        public async Task<IActionResult> GetTeacherInfo(JsonElement json)
+        {
+            string head_lang = "";
 
+            if (HttpContext.Request.Headers.TryGetValue("lang", out var _lang))
+            {
+                head_lang = $"{_lang}";
+            }
+            if (!json.TryGetProperty("code", out JsonElement _code)) return BadRequest("code is null");
+            var phoneInfo = await GetWeChatPhoneNumber(_code.ToString());
+            if (phoneInfo.code==200)
+            {
+                string _mobile = phoneInfo.phone.phoneNumber;
+                var coreUser = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", $"{_mobile}" } }, _option.Location, _configuration);
+                if (coreUser != null && coreUser.id != null)
+                {
+                    (string ip, string region) = await LoginService.LoginIp(HttpContext, _searcher);
+                    Teacher teacher = null;
+                    TeacherInfo teacherInfo = await TeacherService.TeacherInfo(_azureCosmos, teacher, $"{coreUser.name}", $"{coreUser.picture}", coreUser.id, _azureStorage, _option, _azureRedis, ip, _httpTrigger, $"{_lang}");
+                    return Ok(new
+                    {
+                        teacherInfo.auth_token,
+                        teacherInfo.blob_uri,
+                        teacherInfo.blob_sas,
+                        teacherInfo.schools,
+                        teacherInfo.defaultschool,
+                    });
+                }
+                else return Ok(new { state = 404, msg = "未找到关联账号" });
+            }
+            return Ok();
+        }
+        /// <summary>
+        /// 获取学校信息
+        /// </summary>
+        /// <param name="json"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-school-info")]
+#if !DEBUG
+        [Authorize(Roles = "AClassONE")]
+#endif
+        [AuthToken(Roles = "teacher")]
+        public async Task<IActionResult> GetSchoolInfo(JsonElement json) {
+            (string tmdid, _, _, string school) = HttpContext.GetAuthTokenInfo();
+            if (!json.TryGetProperty("school_code", out JsonElement _school_code)) return BadRequest();
+            string school_code = $"{_school_code}";
+            List<string> roles = new List<string>();
+            List<string> permissions = new List<string>();
+            var client = _azureCosmos.GetCosmosClient();
+            int size = 0;
+            Teacher teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemAsync<Teacher>(tmdid, new PartitionKey("Base"));
+            List<AreaDto> areas = new List<AreaDto>();
+            HashSet<string> areaIds = new HashSet<string>();
+            if (teacher.areas.IsNotEmpty())
+            {
+                teacher.areas.ForEach(x => {
+                    areaIds.Add(x.areaId);
+                });
+            }
+            if (teacher.schools.IsNotEmpty())
+            {
+                teacher.schools.ForEach(x => {
+                    if (!string.IsNullOrEmpty(x.areaId))
+                    {
+                        areaIds.Add(x.areaId);
+                    }
 
+                });
+            }
+            List<Area> areasDbs = new List<Area>();
+            List<AreaSetting> areaSettings = new List<AreaSetting>();
+            if (areaIds.Count > 0)
+            {
+                string queryText = $"select value(c) from c where c.id in ({string.Join(",", areaIds.Select(x => $"'{x}'"))})";
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<Area>(queryText: queryText, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("Base-Area") }))
+                {
+                    areasDbs.Add(item);
+                }
+                await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Normal").GetItemQueryIterator<AreaSetting>(queryText: queryText, requestOptions: new QueryRequestOptions() { PartitionKey = new PartitionKey("AreaSetting") }))
+                {
+                    areaSettings.Add(item);
+                }
+            }
+            if (teacher.areas.IsNotEmpty())
+            {
+                foreach (var areat in teacher.areas)
+                {
+
+                    Area area = areasDbs.Find(x => x.id.Equals(areat.areaId));
+                    AreaSetting setting = null;
+                    if (area != null)
+                    {
+                        setting = areaSettings.Find(x => x.id.Equals(areat.areaId));
+                    }
+
+                    int access = 0;
+                    if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig))
+                    {
+                        access = 1;
+                    }
+                    //if (setting != null)
+                    //{
+                    //    setting.accessConfig = null;
+                    //}
+                    areas.Add(new AreaDto { shortCode=area?.shortCode, areaId = area?.id, name = area?.name, standard = area?.standard, standardName = area?.standardName, setting = setting, access = access });
+                }
+            }
+            if (school_code.Equals(teacher.defaultSchool) && teacher.schools.IsNotEmpty() && !teacher.schools.Select(x => x.schoolId).Contains(school_code))
+            {
+                school_code = teacher.schools[0].schoolId;
+                teacher.defaultSchool = school_code;
+                teacher = await client.GetContainer(Constant.TEAMModelOS, "Teacher").ReplaceItemAsync<Teacher>(teacher, tmdid, new PartitionKey("Base"));
+            }
+            var response = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(tmdid, new PartitionKey($"Teacher-{school_code}"));
+            string defaultPeriodId = "";
+            if (response.Status == 200)
+            {
+                using var jsonData = await JsonDocument.ParseAsync(response.ContentStream);
+                if (jsonData.RootElement.TryGetProperty("size", out JsonElement _size) && _size.ValueKind == JsonValueKind.Number)
+                {
+                    size = _size.GetInt32();
+                }
+                if (jsonData.RootElement.TryGetProperty("periodId", out JsonElement _periodId))
+                {
+                    defaultPeriodId =$"{_periodId}";
+                }
+                if (jsonData.RootElement.TryGetProperty("roles", out JsonElement _roles) && _roles.ValueKind != JsonValueKind.Null)
+                {
+                    foreach (var obj in _roles.EnumerateArray())
+                    {
+                        roles.Add(obj.GetString());
+                    }
+                }
+                if (jsonData.RootElement.TryGetProperty("permissions", out JsonElement _permissions) && _permissions.ValueKind != JsonValueKind.Null)
+                {
+                    foreach (var obj in _permissions.EnumerateArray())
+                    {
+                        permissions.Add(obj.GetString());
+                    }
+                }
+                var scteacher = jsonData.RootElement.ToObject<SchoolTeacher>();
+                if (!$"{teacher.name}".Equals($"{scteacher?.name}") || !$"{teacher.picture}".Equals($"{scteacher?.picture}"))
+                {
+                    scteacher.name=teacher.name;
+                    scteacher.picture=teacher.picture;
+                    await client.GetContainer(Constant.TEAMModelOS, "School").ReplaceItemAsync<SchoolTeacher>(scteacher, scteacher.id, new PartitionKey(scteacher.code));
+                }
+            }
+            if (roles.Count == 0)
+            {
+                //助理,管家
+                //roles.Add("assist");
+                roles.Add("teacher");
+            }
+            School school_base = await client.GetContainer(Constant.TEAMModelOS, "School").ReadItemAsync<School>($"{school_code}", new PartitionKey("Base"));
+            string currAreaId = "";
+            dynamic currArea = new ExpandoObject();
+            if (!string.IsNullOrEmpty(school_base.areaId))
+            {
+                try
+                {
+                    Area area = areasDbs.Find(x => x.id.Equals(school_base.areaId));
+                    AreaSetting setting = null;
+                    if (area != null)
+                    {
+                        //setting =await client.GetContainer(Constant.TEAMModelOS, "Normal").ReadItemAsync<AreaSetting>(school_base.areaId, new PartitionKey("AreaSetting"));
+                        setting = areaSettings.Find(x => x.id.Equals(school_base.areaId));
+                    }
+
+                    int access = 0;
+                    AccessConfig accessConfig = null;
+                    if (setting != null && !string.IsNullOrWhiteSpace(setting.accessConfig))
+                    {
+                        access = 1;
+                        accessConfig = setting.accessConfig.ToObject<AccessConfig>();
+                    }
+                    //if (setting!=null&& !string.IsNullOrEmpty(setting.accessConfig)) {
+                    //    setting.accessConfig = null;
+                    //}
+                    currArea = new
+                    {
+                        shortCode = area?.shortCode,
+                        areaId = area?.id,
+                        name = area?.name,
+                        standard = area?.standard,
+                        standardName = area?.standardName,
+                        setting = setting,
+                        access = access,
+                        //submitType=accessConfig?.submitType,
+                        homeworkType = accessConfig != null && accessConfig.homeworkType.IsNotEmpty() ? accessConfig.homeworkType : new List<string> { "pdf" },
+                    };
+                    currAreaId = area?.id;
+                }
+                catch (CosmosException)
+                {
+                    //数据库捞不到数据
+
+                }
+            }
+            if (areas.Count > 0)
+            {
+                roles.Add("area");
+            }
+            areas.ForEach(x => { { if (x.setting != null) { x.setting.accessConfig = x.setting.accessConfig; } } });
+
+            var auth_token = JwtAuthExtension.CreateAuthToken(_option.HostName,teacher. id, teacher.name, teacher.picture, _option.JwtSecretKey, Website: "IES", scope: Constant.ScopeTeacher, schoolID: school_code.ToString(), areaId: currAreaId, standard: school_base.standard, roles: roles.ToArray(), permissions: permissions.ToArray(), expire: 1);
+            string school_code_blob = school_code.ToLower();
+            var container = _azureStorage.GetBlobContainerClient(school_code_blob);
+            await container.CreateIfNotExistsAsync(PublicAccessType.None); //嘗試創建School容器,如存在則不做任何事,保障容器一定存在
+            var (blob_uri, blob_sas) = (roles.Contains("admin") || permissions.Contains("schoolAc-upd")) ? _azureStorage.GetBlobContainerSAS(school_code_blob, BlobContainerSasPermissions.Write | BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Delete) : _azureStorage.GetBlobContainerSAS(school_code_blob, BlobContainerSasPermissions.Read | BlobContainerSasPermissions.List | BlobContainerSasPermissions.Write);
+
+            return Ok(new {
+                auth_token,
+                blob_uri,
+                blob_sas,
+                school_base,
+                areas,
+                currArea,
+            });
+        }
+        /// <summary>
+        /// 获取教师的教学信息
+        /// </summary>
+        /// <param name="json"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("get-teach-info")]
+#if !DEBUG
+        [Authorize(Roles = "AClassONE")]
+#endif
+        [AuthToken(Roles = "teacher")]
+        public async Task<IActionResult> GetTeachInfo(JsonElement json) {
+            (string tmdid, _, _, string school) = HttpContext.GetAuthTokenInfo();
+            List<KeyValuePair<string, CourseTask>> schoolTeacherTask = new List<KeyValuePair<string, CourseTask>>();
+            List<KeyValuePair<string, CourseTask>> schoolAssistantTask = new List<KeyValuePair<string, CourseTask>>();
+
+            List<KeyValuePair<string, CourseTask>> privateTeacherTask = new List<KeyValuePair<string, CourseTask>>();
+            List<KeyValuePair<string, CourseTask>> privateAssistantTask = new List<KeyValuePair<string, CourseTask>>();
+            List<Both.CourseDto> schoolCourses = new List<CourseDto>();
+            List<CourseDto> teahcerCourses = new List<CourseDto>();
+            List<string> groupIds = new List<string>();
+            HashSet<string> hashGroupIds = new HashSet<string>();
+            List<Class> classes = new List<Class>();
+            Period periodSchool = null;
+            if (!string.IsNullOrWhiteSpace(school)) {
+                //班主任
+                string sqlClassTeacher = $"select value c from c where c.teacher.id='{tmdid}'";
+                var resultClass =   await  _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<Class>(sqlClassTeacher, $"Class-{school}");
+                if (resultClass.list.IsNotEmpty()) 
+                {
+                    classes.AddRange(resultClass.list);
+                    hashGroupIds = new HashSet<string>(resultClass.list.Select(z=>z.id));
+                }
+                //执教
+                //协同
+                //管理员
+                string sql = $"SELECT distinct value c FROM c  join b in c.schedules where c.pk='CourseTask' and (ARRAY_CONTAINS(b.assistants,'{tmdid}')or  b.teacherId  ='{tmdid}' )";
+               
+                School schoolBase = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemAsync<School>(school, new PartitionKey("Base"));
+                JsonElement year = default, semesterId = default, _periodId = default;
+                int _year = -1;
+                string _semesterId=string.Empty;
+                if (!json.TryGetProperty("periodId", out _periodId)) return BadRequest();
+                if (json.TryGetProperty("year", out year))
+                {
+                    _year= int.Parse($"{_year}");
+                }
+                if (json.TryGetProperty("semesterId", out semesterId))
+                {
+                    _semesterId=$"{semesterId}";
+                }
+             
+                var period = schoolBase.period.Find(x => x.id.Equals($"{_periodId}"));
+                periodSchool=period;
+                if (_year==-1 || string.IsNullOrWhiteSpace(_semesterId))
+                {
+
+                    var semesterInfo = SchoolService.GetSemester(period, DateTimeOffset.UtcNow.ToUnixTimeMilliseconds());
+                    if (_year==-1) {
+                        _year=semesterInfo.studyYear;                    
+                    }
+                    if (string.IsNullOrWhiteSpace(_semesterId)) {
+                        _semesterId=semesterInfo.currSemester.id;
+                    }
+                }
+               
+                //string date = SchoolService.GetOpensByStudyYearAndSemester(period.semesters, int.Parse($"{_year}"), $"{_semesterId}");
+                sql = $"{sql} and  c.year={_year} and c.semesterId='{_semesterId}'";
+                HashSet<string> courseIds = new HashSet<string>();
+                var resultSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<CourseTask>(sql, $"CourseTask-{school}");
+                if (resultSchool.list.IsNotEmpty())
+                {
+                    resultSchool.list.ForEach(x => {
+                        var schedulesTeacher = x.schedules.Where(z => !string.IsNullOrWhiteSpace(z.teacherId)   && z.teacherId.Equals(tmdid));
+                        if (schedulesTeacher.Any())
+                        {
+                            courseIds.Add(x.courseId);
+                            CourseTask courseTask = x.ToJsonString().ToObject<CourseTask>();
+                            courseTask.schedules=schedulesTeacher.ToList();
+                            schoolTeacherTask.Add(new KeyValuePair<string, CourseTask>(x.courseId, courseTask));
+
+                            //groupIds.AddRange(schedulesTeacher.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId));
+                            var gpids=  schedulesTeacher.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId);
+                            if (gpids!=null  && gpids.Count()>0) 
+                            {
+                                foreach (var gp in gpids) {
+                                    hashGroupIds.Add(gp);
+                                }
+                            }
+                        }
+                        var schedulesAssistant = x.schedules.Where(z => z.assistants.Contains(tmdid));
+                        if (schedulesAssistant.Any())
+                        {
+                            courseIds.Add(x.courseId);
+                            CourseTask courseTask = x.ToJsonString().ToObject<CourseTask>();
+                            courseTask.schedules=schedulesAssistant.ToList();
+                            schoolAssistantTask.Add(new KeyValuePair<string, CourseTask>(x.courseId, courseTask));
+                            //groupIds.AddRange(schedulesAssistant.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId));
+                            var gpids = schedulesAssistant.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId);
+                            if (gpids!=null  && gpids.Count()>0)
+                            {
+                                foreach (var gp in gpids)
+                                {
+                                    hashGroupIds.Add(gp);
+                                }
+                            }
+                        }
+                    });
+                }
+                if (courseIds.Any())
+                {
+                    string sqlCourse = $"select value c from c where c.id in ({string.Join(",", courseIds.Select(b => $"'{b}'"))})";
+                    var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).GetList<CourseBase>(sqlCourse, $"CourseBase-{school}");
+                    if (result.list.IsNotEmpty())
+                    {
+                        foreach (var item in result.list)
+                        {
+                            List<CourseTaskDto> courseTaskDtos = new List<CourseTaskDto>();
+                            var teacher = schoolTeacherTask.Where(x => x.Key.Equals(item.id)).Select(z => new CourseTaskDto { courseTask=z.Value, type="teacher" });
+                            if (teacher.Any())
+                            {
+                                courseTaskDtos.AddRange(teacher.ToList());
+                            }
+                            var assistant = schoolAssistantTask.Where(x => x.Key.Equals(item.id)).Select(z => new CourseTaskDto { courseTask=z.Value, type="assistant" });
+                            if (assistant.Any())
+                            {
+                                courseTaskDtos.AddRange(assistant.ToList());
+                            }
+                            schoolCourses.Add(new Both.CourseDto { courseBase=item, courseTasks=courseTaskDtos });
+                        }
+                    }
+                }
+            }
+
+
+            //个人
+            {
+                HashSet<string> courseIds = new HashSet<string>();
+                string sqlCoursePrivate = $"select value c.id from c where  c.creatorId='{tmdid}'";
+                var resultCourseBasePrivate = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<string>(sqlCoursePrivate, $"CourseBase");
+                if (resultCourseBasePrivate.list.IsNotEmpty())
+                {
+                    courseIds=new HashSet<string>(resultCourseBasePrivate.list);
+                }
+                string sqlprivate = $"SELECT distinct value c FROM c  join b in c.schedules where c.pk='CourseTask' and (ARRAY_CONTAINS(b.assistants,'{tmdid}')or  b.teacherId  ='{tmdid}' )";
+                var resultTeacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<CourseTask>(sqlprivate, $"CourseTask");
+                if (resultTeacher.list.IsNotEmpty())
+                {
+
+                    resultTeacher.list.ForEach(x => {
+                        var schedulesTeacher = x.schedules.Where(z => !string.IsNullOrWhiteSpace(z.teacherId)  &&  z.teacherId.Equals(tmdid));
+                        if (schedulesTeacher.Any())
+                        {
+                            courseIds.Add(x.courseId);
+                            CourseTask courseTask = x.ToJsonString().ToObject<CourseTask>();
+                            courseTask.schedules=schedulesTeacher.ToList();
+                            privateTeacherTask.Add(new KeyValuePair<string, CourseTask>(x.courseId, courseTask));
+                            groupIds.AddRange(schedulesTeacher.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId));
+                            var gpids = schedulesTeacher.Where(z => !string.IsNullOrWhiteSpace(z.groupId));
+                            if (gpids!=null  && gpids.Count()>0)
+                            {
+                                foreach (var gp in gpids)
+                                {
+                                    if (!string.IsNullOrWhiteSpace(gp.school))
+                                    {
+                                        if (!string.IsNullOrWhiteSpace(school) && gp.school.Equals(school))
+                                        {
+                                            hashGroupIds.Add(gp.groupId);
+                                        }
+                                    }
+                                    else {
+                                        hashGroupIds.Add(gp.groupId);
+                                    }
+                                   
+                                }
+                            }
+                        }
+                        var schedulesAssistant = x.schedules.Where(z => z.assistants.Contains(tmdid));
+                        if (schedulesAssistant.Any())
+                        {
+                            courseIds.Add(x.courseId);
+                            CourseTask courseTask = x.ToJsonString().ToObject<CourseTask>();
+                            courseTask.schedules=schedulesAssistant.ToList();
+                            privateAssistantTask.Add(new KeyValuePair<string, CourseTask>(x.courseId, courseTask));
+                            groupIds.AddRange(schedulesAssistant.Where(z => !string.IsNullOrWhiteSpace(z.groupId)).Select(x => x.groupId));
+                            var gpids = schedulesAssistant.Where(z => !string.IsNullOrWhiteSpace(z.groupId));
+                            if (gpids!=null  && gpids.Count()>0)
+                            {
+                                foreach (var gp in gpids)
+                                {
+                                    if (!string.IsNullOrWhiteSpace(gp.school))
+                                    {
+                                        if (!string.IsNullOrWhiteSpace(school) && gp.school.Equals(school)) {
+                                            hashGroupIds.Add(gp.groupId);
+                                        }
+                                    }
+                                    else
+                                    {
+                                        hashGroupIds.Add(gp.groupId);
+                                    }
+                                }
+                            }
+                        }
+                    });
+
+                }
+                if (courseIds.Any())
+                {
+                    string sqlCourse = $"select distinct value c from c where c.code='CourseBase' and  ( c.creatorId='{tmdid}' or  c.id in ({string.Join(",", courseIds.Select(b => $"'{b}'"))}))";
+                    var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<CourseBase>(sqlCourse, $"CourseBase");
+                    if (result.list.IsNotEmpty())
+                    {
+                        foreach (var item in result.list)
+
+                        {
+                            List<CourseTaskDto> courseTaskDtos = new List<CourseTaskDto>();
+                            var teacher = privateTeacherTask.Where(x => x.Key.Equals(item.id)).Select(z => new CourseTaskDto { courseTask=z.Value, type="teacher" });
+                            if (teacher.Any())
+                            {
+                                courseTaskDtos.AddRange(teacher.ToList());
+                            }
+                            var assistant = privateAssistantTask.Where(x => x.Key.Equals(item.id)).Select(z => new CourseTaskDto { courseTask=z.Value, type="assistant" });
+                            if (assistant.Any())
+                            {
+                                courseTaskDtos.AddRange(assistant.ToList());
+                            }
+                            teahcerCourses.Add(new CourseDto { courseBase=item, courseTasks=courseTaskDtos });
+                        }
+                    }
+                }
+            }
+            var groupInfo = await  GroupListService.GetMemberByListids(_coreAPIHttpService, _azureCosmos.GetCosmosClient(), _dingDing, hashGroupIds.ToList(), school);
+            var groupIdsRel = groupIds.GroupBy(z => z).Select(z => new { groupId = z.Key, count = z.ToList().Count() });
+            List<dynamic> groupLists= new List<dynamic>();
+            foreach (var item in teahcerCourses)
+            {
+                
+                foreach (var z in item.courseTasks) {
+                    var groups = z.courseTask.schedules.Select(z => z.groupId);
+                    if (groups!=null) {
+                        var groupList = groupInfo.groups.Where(z => groups.Contains(z.id));
+                        if (groupList!=null)
+                        {
+                            foreach (var gp in groupList) {
+                                string subjectId = null;
+                                string subjectName = null;
+                                string subjectBindId = null;
+                                groupLists.Add(new { role = z.type,scope= "private", groupList= gp, subjectId, subjectName , subjectBindId });
+                            }
+                        }
+                    }
+                }
+            }
+            foreach (var item in schoolCourses)
+            {
+                string subjectBindId = null;
+                if (!string.IsNullOrWhiteSpace(school) && periodSchool!=null  && item.courseBase.scope.Equals("school") && !string.IsNullOrWhiteSpace(item.courseBase?.subject?.id))
+                {
+                    subjectBindId=periodSchool.subjects.Find(z => z.id.Equals(item.courseBase.subject.id))?.bindId;
+                }
+                foreach (var z in item.courseTasks)
+                {
+                    var groups = z.courseTask.schedules.Select(z => z.groupId);
+                    if (groups!=null)
+                    {
+                        var groupList = groupInfo.groups.Where(z => groups.Contains(z.id));
+                        if (groupList!=null)
+                        {
+                            foreach (var gp in groupList)
+                            {
+
+                                groupLists.Add(new { role = z.type, scope = "school", groupList = gp, subjectId = item.courseBase?.subject?.id, subjectName = item.courseBase?.subject?.name, subjectBindId });
+                            }
+                        }
+                    }
+                }
+            }
+            foreach (var item in classes) {
+                var groupList = groupInfo.groups.Where(z => item.id.Equals(z.id));
+                if (groupList!=null)
+                {
+                    foreach (var gp in groupList)
+                    {
+
+                        groupLists.Add(new { role = "charge", scope = "school", groupList = gp });
+                    }
+                }
+            }
+            return Ok(new { teahcerCourses, schoolCourses, groupIdsRel, groupLists });
+        }
         /// <summary>
         /// 根据家长手机号获取监护学生的信息
         /// </summary>
@@ -123,7 +665,7 @@ namespace TEAMModelOS.Controllers
 #if !DEBUG
         [Authorize(Roles = "AClassONE")]
 #endif
-        public async Task<IActionResult> GetStudentsByPhone(JsonElement json)
+        public async Task<IActionResult> GetChildrenByPhone(JsonElement json)
         {
             try
             {
@@ -299,6 +841,313 @@ namespace TEAMModelOS.Controllers
         }
 
 
+
+        /// <summary>
+        /// 获取当前学生参与的活动列表
+        /// </summary>
+        /// <param name="json"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [HttpPost("find-children-activity")]
+#if !DEBUG
+        [Authorize(Roles = "AClassONE")]
+#endif
+        public async Task<IActionResult> getActivity(JsonElement request) {
+            try {
+                if (!request.TryGetProperty("studentId", out JsonElement stuId)) return BadRequest();
+                if (!request.TryGetProperty("classId", out JsonElement classId)) return BadRequest();
+                if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();//学校编码
+
+                var client = _azureCosmos.GetCosmosClient();
+                StringBuilder stringBuilder = new($"select value(c) from c where (c.status<>404 or IS_DEFINED(c.status) = false )");
+                string continuationToken = string.Empty;
+                string token = default;
+                if (!string.IsNullOrWhiteSpace($"{classId}"))
+                {
+                    stringBuilder.Append($" and array_contains(c.classes,'{classId}')");
+                }             
+                stringBuilder.Append("order by c.createTime desc");
+                //是否需要进行分页查询,默认不分页
+                if (request.TryGetProperty("token", out JsonElement token_1))
+                {
+                    token = token_1.GetString();
+                };
+                //默认不指定返回大小
+                int? topcout = null;
+                if (request.TryGetProperty("count", out JsonElement jcount))
+                {
+                    if (!jcount.ValueKind.Equals(JsonValueKind.Undefined) && !jcount.ValueKind.Equals(JsonValueKind.Null) && jcount.TryGetInt32(out int data))
+                    {
+                        topcout = data;
+                    }
+                }
+
+                List<ArtEvaluation> arts = new();
+                var result=  await client.GetContainer(Constant.TEAMModelOS, Constant.Common).GetList<ArtEvaluation>(stringBuilder.ToString(), $"Art-{code}", token, 5);
+                if (result.list.IsNotEmpty()) {
+                    arts = result.list;
+                    token = result.continuationToken;
+                }
+                //await foreach (var item in client.GetContainer("TEAMModelOS", "Common").GetItemQueryStreamIterator(queryText: stringBuilder.ToString(), continuationToken: token, requestOptions: new QueryRequestOptions() { MaxItemCount = topcout, PartitionKey = new PartitionKey($"Art-{code}") }))
+                //{
+
+                //    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())
+                //        {
+                //            arts.Add(obj.ToObject<ArtEvaluation>());
+                //        }
+                //    }
+                //    if (iscontinuation)
+                //    {
+                //        continuationToken = item.GetContinuationToken();
+                //        break;
+                //    }
+                //}
+                // arts = arts.Where((x, i) => arts.FindIndex(z => z.id == x.id) == i).ToList();
+                //List<(string artId, double count)> attachments = new();
+               /* foreach (ArtEvaluation art in arts) {
+                    List<StudentArtResult> artResults = new();
+                    string stu = string.Format("{0}{1}{2}", code.GetString(), "-", stuId.GetString());
+                    string sql = $"select value(c) from c where c.artId = '{art.id}' and c.id = '{stu}' and c.pk = 'ArtResult'";
+                    await foreach (var item in client.GetContainer(Constant.TEAMModelOS, "Student").GetItemQueryStreamIterator(
+                    queryText: sql))
+                    {
+                        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())
+                            {
+                                artResults.Add(obj.ToObject<StudentArtResult>());
+                            }
+                        }
+                    }
+                    if (artResults.Count > 0)
+                    {
+                        var attCount = artResults[0].results.Where(z => z.files != null).SelectMany(c => c.files).ToList().Count;
+                        attachments.Add((art.id, attCount));
+                    }
+                    else {
+                        attachments.Add((art.id, 0));
+                    }
+                   
+                }*/
+                List<string> artIds = new();
+                artIds = arts.Select(c => c.id).ToList();
+                List<ArtAttachment> artAttachments = new();
+                string sqlTask = $"select value(c)  from c where c.studentId = '{stuId}' and c.artId in ({string.Join(",", artIds.Select(s => $"'{s}'"))})";
+                await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).
+                GetItemQueryIterator<ArtAttachment>(queryText: sqlTask, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"ArtAttachment-{code}") }))
+                {
+                    artAttachments.Add(item);
+                }
+                var newArts = arts.Select(c => new { 
+                
+                    c.id,
+                    c.name,
+                    c.school,
+                    c.createTime,
+                    c.type,
+                    c.classes,
+                    c.progress,
+                    c.scope,
+                    c.areaId,
+                    c.pId,
+                    c.topic,
+                    c.startTime,
+                    c.endTime,
+                    c.uploadSTime,
+                    c.uploadETime,
+                    c.publish,c.subjects,
+                    c.period,
+                    c.periodType,
+                    c.zymusicstds,c.code,
+                    count = artAttachments.Where(z => z.artId.Equals(c.id)).SelectMany(k => k.files).ToList().Count
+
+                });
+                return Ok(new { arts = newArts ,token});
+            } catch (Exception e) {
+                await _dingDing.SendBotMsg($"OS,{_option.Location},art/find-children-activity()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
+                return BadRequest("500错误");
+            }
+        }
+
+
+        [ProducesDefaultResponseType]
+        [HttpPost("find-summary-activity")]
+#if !DEBUG
+        [Authorize(Roles = "AClassONE")]
+#endif
+        public async Task<IActionResult> findSummaryActivity(JsonElement request)
+        {
+            try
+            {
+                if (!request.TryGetProperty("studentId", out JsonElement stuId)) return BadRequest();
+                if (!request.TryGetProperty("artId", out JsonElement artId)) return BadRequest();
+                //if (!request.TryGetProperty("acId", out JsonElement taskId)) return BadRequest();
+                if (!request.TryGetProperty("code", out JsonElement code)) return BadRequest();//学校编码
+
+                var client = _azureCosmos.GetCosmosClient();
+                StudentArtResult result = new();
+                ArtEvaluation art = new(); 
+                string stu = string.Format("{0}{1}{2}", code.GetString(), "-", stuId.GetString());
+                var res = await client.GetContainer(Constant.TEAMModelOS, "Student").ReadItemStreamAsync(stu.ToString(), new PartitionKey($"ArtResult-{artId}"));
+                if (res.Status == 200)
+                {
+                    using var json = await JsonDocument.ParseAsync(res.ContentStream);
+                    result = json.ToObject<StudentArtResult>();                 
+                  
+                }
+                List<string> taskIds = new();
+                taskIds = result.results.Select(c => c.taskId).ToList();
+                List<ArtAttachment> artAttachments = new();
+                string sqlTask = $"select value(c)  from c where c.studentId = '{stuId}' and c.taskId in ({string.Join(",", taskIds.Select(s => $"'{s}'"))})";
+                await foreach (var item in _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Student).
+                GetItemQueryIterator<ArtAttachment>(queryText: sqlTask, requestOptions: new QueryRequestOptions { PartitionKey = new PartitionKey($"ArtAttachment-{code}") }))
+                {
+                    artAttachments.Add(item);
+                }
+
+                var resArt = await client.GetContainer(Constant.TEAMModelOS, "Common").ReadItemStreamAsync(artId.ToString(), new PartitionKey($"Art-{code}"));
+                if (resArt.Status == 200)
+                {
+                    using var json = await JsonDocument.ParseAsync(resArt.ContentStream);
+                    art = json.ToObject<ArtEvaluation>();
+
+                }
+                return Ok(new { result,art, artAttachments });
+            }
+            catch (Exception e)
+            {
+                await _dingDing.SendBotMsg($"OS,{_option.Location},art/find-summary-activity()\n{e.Message}\n{e.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
+                return BadRequest("500错误");
+            }
+        }
+
+        [ProducesDefaultResponseType]
+        [HttpPost("upload-all")]
+#if !DEBUG
+        [Authorize(Roles = "AClassONE")]
+#endif
+        public async Task<IActionResult> UploadAll(JsonElement element)
+        {
+            try
+            {
+                var client = _azureCosmos.GetCosmosClient();
+                //if (!element.TryGetProperty("code", out JsonElement school)) return BadRequest();
+                if (!element.TryGetProperty("attachments", out JsonElement stus)) return BadRequest();
+                stuFiles files = stus.ToObject<stuFiles>();
+                List<string> value = new List<string>();
+                await foreach (var s in stuTask(files, client))
+                {
+                    if (s.code == 1)
+                    {
+                        value.Add(s.value);
+                    }
+                }
+                if (value.Count > 0)
+                {
+                    return Ok(new { code = 400, msg = "学生ID上传异常", value });
+                }
+                else
+                {
+                    return Ok(files);
+                }
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"OS,{_option.Location},aclassone/uploadAll()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
+                return Ok(new { code = 500, msg = ex.Message });
+            }
+
+        }
+
+        [ProducesDefaultResponseType]
+        [HttpPost("delete")]
+#if !DEBUG
+        [Authorize(Roles = "AClassONE")]
+#endif
+        public async Task<IActionResult> deleteFiels(JsonElement element)
+        {
+            try
+            {
+                var client = _azureCosmos.GetCosmosClient();
+                if (!element.TryGetProperty("id", out JsonElement id)) return BadRequest();
+                if (!element.TryGetProperty("code", out JsonElement code)) return BadRequest();
+                await client.GetContainer("TEAMModelOS", "Student").DeleteItemStreamAsync(id.GetString(), new PartitionKey($"ArtAttachment-{code}"));
+                return Ok();
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"OS,{_option.Location},aclassone/delete()\n{ex.Message}\n{ex.StackTrace}\n", GroupNames.醍摩豆服務運維群組);
+                return Ok(new { code = 500, msg = ex.Message });
+            }
+
+        }
+        private async IAsyncEnumerable<(int code, string value)> stuTask(stuFiles files, CosmosClient client)
+        {
+            string value = "";
+            int code = 0;
+            try {
+                if (string.IsNullOrEmpty(files.id))
+                {
+                    ArtAttachment attachment = new()
+                    {
+                        id = Guid.NewGuid().ToString(),
+                        artId = files.artId,
+                        achievement = files.achievement,
+                        address = files.address,
+                        studentId = files.studentId,
+                        taskId = files.taskId,
+                        subjectId = files.subjectId,
+                        quotaId = files.quotaId,
+                        quotaName = files.quotaName,
+                        uploadTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                        duration = files.duration,
+                        name = files.name,
+                        des = files.des,
+                        artType = files.artType,
+                        level = files.level,
+                        files = files.files,
+                        ttl = -1,
+                        code = "ArtAttachment-" + files.school
+
+                    };
+                    await client.GetContainer("TEAMModelOS", "Student").CreateItemAsync(attachment, new PartitionKey($"{attachment.code}"));
+                }
+                else
+                {
+                    ArtAttachment attachment = new()
+                    {
+                        artId = files.artId,
+                        achievement = files.achievement,
+                        address = files.address,
+                        studentId = files.studentId,
+                        taskId = files.taskId,
+                        subjectId = files.subjectId,
+                        quotaId = files.quotaId,
+                        quotaName = files.quotaName,
+                        updateTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                        duration = files.duration,
+                        name = files.name,
+                        des = files.des,
+                        artType = files.artType,
+                        level = files.level,
+                        files = files.files,
+                        ttl = -1,
+                        code = "ArtAttachment-" + files.school
+                    };
+                    await client.GetContainer("TEAMModelOS", "Student").ReplaceItemAsync(attachment, attachment.id, new PartitionKey($"{attachment.code}"));
+                }
+            }
+            catch (Exception e) {
+                value = files.studentId;
+                code = 1;
+            }
+            yield return (code, value);
+        }
+
         private async Task<(int code, WeChatPhone phone)> GetWeChatPhoneNumber(string phoneCode) 
         {
             var wxappid = _configuration.GetValue<string>("HaBookAuth:WXMiniAPP:appid");
@@ -377,6 +1226,29 @@ namespace TEAMModelOS.Controllers
             public string? errmsg { get; set; }
             public WeChatPhone? phone_info { get; set; }
         }
+        private class stuFiles
+        {
+            public string id { get; set; }
+            public string school { get; set; }
+            public string artId { get; set; }
+            public string taskId { get; set; }
+            public string studentId { get; set; }
+            public string quotaId { get; set; }
+            public string quotaName { get; set; }
+            public string subjectId { get; set; }
+            public string address { get; set; }
+            public string time { get; set; }
+            public string duration { get; set; }
+            public string achievement { get; set; }
+            public string name { get; set; }
+            public string des { get; set; }
+            //0 艺术特长  1 艺术体验
+            public int artType { get; set; } = -1;
+            // 0 校级 1 区级 2 市级 3 省级 4 国家级
+            public int level { get; set; } = -1;
+            public long uploadTime { get; set; }
+            public List<Attachment> files { get; set; } = new List<Attachment>();
+        }
 
     }
 }

+ 81 - 0
TEAMModelOS/Controllers/Common/ActivityController.cs

@@ -0,0 +1,81 @@
+using Azure.Cosmos;
+using Microsoft.AspNetCore.Http;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Extensions.Options;
+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.Models;
+using TEAMModelOS.SDK.DI;
+using TEAMModelOS.SDK.Extension;
+using Azure;
+using Microsoft.Extensions.Configuration;
+using TEAMModelOS.Filter;
+using HTEXLib.COMM.Helpers;
+using TEAMModelOS.SDK;
+using StackExchange.Redis;
+
+using System.Text.RegularExpressions;
+
+namespace TEAMModelOS.Controllers
+{
+ 
+
+    [ProducesResponseType(StatusCodes.Status200OK)]
+    [ProducesResponseType(StatusCodes.Status400BadRequest)]
+
+    [Route("activity")]
+    [ApiController]
+    public class ActivityController : ControllerBase
+    {
+        private AzureCosmosFactory _azureCosmos;
+        private readonly DingDing _dingDing;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+        private readonly Option _option;
+        private readonly AzureServiceBusFactory _serviceBus;
+        private readonly AzureStorageFactory _azureStorage;
+        private readonly AzureRedisFactory _azureRedis;
+        public IConfiguration _configuration { get; set; }
+        public ActivityController(AzureRedisFactory azureRedis, AzureCosmosFactory azureCosmos, DingDing dingDing, IOptionsSnapshot<Option> option, CoreAPIHttpService coreAPIHttpService, AzureServiceBusFactory serviceBus, AzureStorageFactory azureStorage, IConfiguration configuration)
+        {
+            _azureCosmos = azureCosmos;
+            _dingDing = dingDing;
+            _option = option?.Value;
+            _serviceBus = serviceBus;
+            _configuration = configuration;
+            _azureStorage = azureStorage;
+            _azureRedis = azureRedis; 
+            _coreAPIHttpService = coreAPIHttpService;
+        }
+        /// <summary>
+        /// 活动创建
+        /// </summary>
+        /// <param name="request"></param>
+        /// <returns></returns>
+        [ProducesDefaultResponseType]
+        [AuthToken(Roles = "teacher,admin,area")]
+        [HttpPost("manage")]
+#if !DEBUG
+        [Authorize(Roles = "IES")]
+#endif
+        public async Task<IActionResult> Manage(JsonElement request)
+        {
+            try
+            {
+                (string tmdid, _, _, string school) = HttpContext.GetAuthTokenInfo();
+                if (!request.TryGetProperty("grant_type", out JsonElement grant_type)) return BadRequest();
+                if (!request.TryGetProperty("scope", out JsonElement scope)) return BadRequest();
+                var client = _azureCosmos.GetCosmosClient();
+                switch (true) { }
+            }catch (Exception ex)
+            {
+
+            }
+            return Ok();
+        }
+    }
+}

+ 6 - 4
TEAMModelOS/Controllers/Common/ArtController.cs

@@ -363,7 +363,7 @@ namespace TEAMModelOS.Controllers.Common
                 try
                 {
                     long now = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
-                    ArtRecord record = new()
+                    /*ArtRecord record = new()
                     {
                         school = school,
                         stuId = request.stuId,
@@ -375,7 +375,7 @@ namespace TEAMModelOS.Controllers.Common
                         createTime = now,
                         code = "ArtRecord",
                         attachments = request.attachments
-                    };
+                    };*/
                     StudentArtResult artResult;
                     ArtEvaluation art;
                     List<string> classIds = new();
@@ -393,7 +393,7 @@ namespace TEAMModelOS.Controllers.Common
                     {
                         record = await client.GetContainer("TEAMModelOS", "Student").ReplaceItemAsync(record, record.id, new PartitionKey($"{record.code}"));
                     }*/
-                    string rId = string.Format("{0}{1}{2}", record.school, "-", record.stuId);
+                    string rId = string.Format("{0}{1}{2}", school, "-", request.stuId);
                     //首先根据大ID获取整个活动得内容
                     var aresponse = await client.GetContainer("TEAMModelOS", "Common").ReadItemStreamAsync(artId, new PartitionKey($"Art-{school}"));
                     if (aresponse.Status == 200)
@@ -412,6 +412,7 @@ namespace TEAMModelOS.Controllers.Common
                             {
                                 if (a.taskId == acId)
                                 {
+                                    a.name = request.name;
                                     a.files = files;
                                 }
                             });
@@ -448,6 +449,7 @@ namespace TEAMModelOS.Controllers.Common
                                     {
                                         if (quotaResult.taskId.Equals(acId))
                                         {
+                                            quotaResult.name = request.name;
                                             quotaResult.files = request.attachments;
                                         }
                                     }
@@ -1063,7 +1065,7 @@ namespace TEAMModelOS.Controllers.Common
                         x.artId,
                         isAnswer = string.IsNullOrWhiteSpace(x.zyanswer.thirdAnswerId) ? 0 : 1,
                         attachments = x.results.Where(c => c.taskId.Equals(taskId.GetString())).FirstOrDefault().files,
-                        zyUrl.Where(c => c.stuId.Equals(x.studentId)).FirstOrDefault().url
+                        url = x.results.Where(c => c.taskId.Equals(taskId.GetString())).FirstOrDefault().quotaId.Equals("quota_22") ? zyUrl.Where(c => c.stuId.Equals(x.studentId)).FirstOrDefault().url : ""
                     });
                     return Ok(new { works, code = 200 });
                 }

+ 553 - 0
TEAMModelOS/Controllers/OpenApi/Business/BizSSOController.cs

@@ -0,0 +1,553 @@
+using Microsoft.AspNetCore.Mvc;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using TEAMModelOS.Models;
+using TEAMModelOS.SDK.DI;
+using System.Text.Json;
+using TEAMModelOS.SDK.Models;
+using Microsoft.AspNetCore.Http;
+using TEAMModelOS.SDK.Extension;
+using Azure.Cosmos;
+using System.Text;
+using Microsoft.Extensions.Options;
+using Azure.Messaging.ServiceBus;
+using Microsoft.Extensions.Configuration;
+using HTEXLib.COMM.Helpers;
+using TEAMModelOS.SDK;
+using System.IdentityModel.Tokens.Jwt;
+using TEAMModelOS.Services;
+using TEAMModelOS.SDK.Models.Service;
+using System.IO;
+using System.Dynamic;
+using Microsoft.AspNetCore.Authorization;
+using Azure.Storage.Blobs.Models;
+using static TEAMModelOS.SDK.Models.Teacher;
+using System.Web;
+using static TEAMModelOS.Controllers.FixDataController;
+using static TEAMModelOS.SDK.SchoolService;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.Azure.Cosmos.Table;
+using System.Net.Http;
+using TEAMModelOS.SDK.Context.Attributes.Azure;
+using System.Security.Cryptography.Xml;
+using DocumentFormat.OpenXml.Office2010.Excel;
+using DocumentFormat.OpenXml.Wordprocessing;
+using Microsoft.OData.UriParser;
+using System.ComponentModel.DataAnnotations;
+using System.Runtime.Intrinsics.X86;
+using System.Security.Policy;
+using Top.Api;
+using Grpc.Core;
+using OfficeOpenXml.FormulaParsing.LexicalAnalysis;
+using System.Net.Http.Json;
+using DocumentFormat.OpenXml.EMMA; 
+using TEAMModelOS.Filter;
+
+namespace TEAMModelOS.Controllers
+{
+    [ApiController]
+    [Route("business")]
+    public class BizSSOController : ControllerBase
+    {
+        private readonly SnowflakeId _snowflakeId;
+        private readonly AzureCosmosFactory _azureCosmos;
+        private readonly DingDing _dingDing;
+        private readonly Option _option;
+        private readonly AzureStorageFactory _azureStorage;
+        private readonly AzureServiceBusFactory _serviceBus;
+        private readonly AzureRedisFactory _azureRedis;
+        private readonly CoreAPIHttpService _coreAPIHttpService;
+      
+        public readonly IHttpClientFactory _httpClientFactory;
+
+        public IConfiguration _configuration { get; set; }
+        public BizSSOController(IWebHostEnvironment environment, AzureCosmosFactory azureCosmos, SnowflakeId snowflakeId, DingDing dingDing, IOptionsSnapshot<Option> option, AzureStorageFactory azureStorage,
+          AzureRedisFactory azureRedis, AzureServiceBusFactory serviceBus, IConfiguration configuration, CoreAPIHttpService coreAPIHttpService, IHttpClientFactory httpClientFactory)
+        {
+            _azureCosmos = azureCosmos;
+            _snowflakeId = snowflakeId;
+            _dingDing = dingDing;
+            _option = option?.Value;
+            _azureStorage = azureStorage;
+            _serviceBus = serviceBus;
+            _configuration = configuration;
+            _azureRedis = azureRedis;
+            _coreAPIHttpService = coreAPIHttpService;
+            _httpClientFactory = httpClientFactory;
+        }
+       
+        [HttpPost("sso")]
+        [ApiToken(Auth = "2200", Name = "单点登录跳转", TName = "单点登录跳转", EName = "联盟单点登录跳转", RWN = "W", Limit = false)]
+        public async Task<IActionResult> Sso(BizSso sso)
+        {
+            var (tokenId, authSchool) = HttpContext.GetApiTokenInfo();
+            string HostName = HttpContext.GetHostName();
+            if (!string.IsNullOrWhiteSpace(_option.HostName))
+            {
+                HostName = _option.HostName;
+            }
+            var rurl = new StringBuilder($"https://{HostName}/tmdid-sso");
+            Teacher teacher = null;
+            int status = 4;//1项目未配置,2 账号未未关联,3账号已关联
+            string msg = "账号未关联";
+            TmdidImplicit implicit_token = null;
+            string sql = $"select value c from c  join b in c.binds where b.type='{tokenId}' and b.userid ='{sso.userid}'";
+            var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<Teacher>(sql, "Base");
+            List<Teacher> teachers = result.list;
+            if (teachers.Any())
+            {
+                teacher=teachers[0];
+                status = 3;//已关联
+                msg = "账号已关联";
+                bool change = false;
+                if (!string.IsNullOrWhiteSpace(authSchool)) {
+                    teacher.defaultSchool = authSchool;
+                    change = true;
+                }
+                if (!string.IsNullOrWhiteSpace(sso.name))
+                {
+                    change = true;
+                    teacher.name = sso.name;
+                }
+                if (!string.IsNullOrWhiteSpace(sso.picture))
+                {
+                    change = true;
+                    teacher.picture = sso.picture;
+                }
+                if (change) { await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).UpsertItemAsync(teacher, new PartitionKey("Base")); }
+            }
+            else
+            {
+                if (!string.IsNullOrWhiteSpace(sso.mobile))
+                {
+
+                    //如果沒有,則初始化Teacher基本資料到Cosmos
+                    teacher = new Teacher
+                    {
+                        createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                        pk = "Base",
+                        code = "Base",
+                        name = sso.name?.ToString(),
+                        picture = sso.picture?.ToString(),
+                        //创建账号并第一次登录IES5则默认赠送1G
+                        size = 1,
+                        defaultSchool = authSchool,
+                        schools = new List<TeacherSchool>(),
+                    };
+                    //未绑定,尝试用手机号进行关联
+                    var coreUser = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", sso.mobile } }, _option.Location, _configuration);
+                    if (coreUser != null)
+                    {
+                        var response =  await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemStreamAsync(coreUser.id, new PartitionKey("Base"));
+                        if (response.Status==200) {
+                            teacher=JsonDocument.Parse(response.Content).RootElement.ToObject<Teacher>();
+                            teacher.defaultSchool=authSchool;
+                        }
+                        teacher.id = coreUser.id;
+                        status = 3;//已关联
+                        msg = "账号已关联";
+                        if (string.IsNullOrWhiteSpace(teacher.name)) {
+                            teacher.name=coreUser.name;
+                        }
+                        if (string.IsNullOrWhiteSpace(teacher.picture))
+                        {
+                            teacher.picture=coreUser.picture;
+                        }
+                        teacher.binds.Add(new ThirdBind { type=tokenId,userid=sso.userid,username=sso.name,account=sso.mobile,data=new List<string> { sso.ToJsonString() } });
+                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).UpsertItemAsync(teacher, new PartitionKey("Base"));
+                    }
+                    else
+                    {
+                        status = 4;
+                    }
+                }
+                else
+                {
+                    status = 2;
+                    msg = "教师信息没有手机号";
+                }
+            }
+
+            if (status == 3)
+            {
+                var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
+                var location = _option.Location;
+                implicit_token = await _coreAPIHttpService.Implicit(
+                    new Dictionary<string, string>()
+                    {
+                                    { "grant_type", "implicit" },
+                                    { "client_id",clientID },
+                                    { "account",teacher.id },
+                                    { "nonce",Guid.NewGuid().ToString()}
+                    }, location, _configuration);
+                if (implicit_token != null)
+                {
+                    if (string.IsNullOrWhiteSpace(implicit_token.id_token))
+                    {
+                        await _dingDing.SendBotMsg($"OS,隐式登录获得信息为空:{_option.Location}-\n{sso.ToJsonString()} \n\n{implicit_token.ToJsonString()}", GroupNames.醍摩豆服務運維群組);
+                        status = 6;
+                        msg = "隐式登录异常";
+                    }
+                    else
+                    {
+                        status = 200;
+                        msg = "登录成功";
+                        if (!string.IsNullOrWhiteSpace(authSchool))
+                        {
+                            //检查自动加入学校
+                            Azure.Response responseSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(authSchool, new PartitionKey("Base"));
+                            if (responseSchool.Status == 200)
+                            {
+                                School school = JsonDocument.Parse(responseSchool.Content).RootElement.ToObject<School>();
+                                JwtSecurityToken jwt = new JwtSecurityToken(implicit_token.id_token);
+                                var id = jwt.Payload.Sub;
+                                jwt.Payload.TryGetValue("name", out object name);
+                                jwt.Payload.TryGetValue("picture", out object picture);
+                                JoinSchool(id, name?.ToString(), picture?.ToString(), school);
+                            }
+                        }
+                    }
+                }
+                else
+                {
+                    status = 6;
+                    msg = "隐式登录异常";
+                }
+            }
+            if (status == 200)
+            {
+                var content = new { grant_type = "code", client_id = "516148eb-6a38-4657-ba98-a3699061937f", nonce = Guid.NewGuid().ToString(), implicit_token.id_token };
+                var response = await _httpClientFactory.CreateClient().PostAsJsonAsync("https://api2.teammodel.cn/oauth2/login", content);
+                string code = string.Empty;
+                if (response.IsSuccessStatusCode)
+                {
+                    string jsonStr = await response.Content.ReadAsStringAsync();
+                    var json = jsonStr.ToObject<JsonElement>();
+                    if (json.TryGetProperty("code", out JsonElement _code))
+                    {
+                        code = _code.ToString();
+                    }
+                }
+                string callback = string.Empty;
+                if (sso.callback.Contains("https://www.habook.com.cn"))
+                {
+                    callback = $"https://account.teammodel.cn/?code={code}&callback=https%3A%2F%2Fwww.habook.com.cn%2F";
+                }
+                else if (sso.callback.Contains("https://www.teammodel.cn"))
+                {
+                    callback = $"https://www.teammodel.cn/login?code={code}&callback=https%3A%2F%2Fwww.teammodel.cn%2Flogin";
+                }
+                else {
+                    callback = $"https://account.teammodel.cn/?code={code}&callback={HttpUtility.UrlEncode(sso.callback, Encoding.UTF8)}";
+                }
+                //rurl.Append($"?status={status}&msg={HttpUtility.UrlEncode(msg, Encoding.UTF8)}&callback={HttpUtility.UrlEncode(callback)}&id_token={implicit_token?.id_token}&access_token={implicit_token?.access_token}&expires_in={HttpUtility.UrlEncode(implicit_token?.expires_in)}&token_type={HttpUtility.UrlEncode(implicit_token?.token_type)}").ToString();
+
+               // rurl.Append($"?status={status}&msg={HttpUtility.UrlEncode(msg, Encoding.UTF8)}&callback={HttpUtility.UrlEncode(callback)}").ToString();
+               // return Ok(new { code = status, message = msg, data = rurl.ToString(),tmdid= teacher.id });
+                return Ok(new { code = status, message = msg, data = callback, tmdid = teacher.id });
+            }
+            else if (status == 4)
+            {
+                msg = $"教师账号:{sso.userid},{sso.mobile}未关联";
+                sso.mobile = "";
+                sso.school=authSchool;
+                rurl.Append($"?status={status}&msg={HttpUtility.UrlEncode(msg, Encoding.UTF8)}&param={HttpUtility.UrlEncode(sso.ToJsonString(), Encoding.UTF8)}&type={tokenId}&bindurl=business/bind");
+                return Ok(new { code = 4, message = msg, data = rurl.ToString() });
+            }
+            else
+            {
+                rurl.Append($"?status={status}&msg={HttpUtility.UrlEncode(msg, Encoding.UTF8)}");
+                return Ok(new { code = 400, message = msg, data = rurl.ToString() });
+
+            }
+        }
+        [HttpPost("bind")]
+        [AllowAnonymous]
+        //[ApiToken(Auth = "2201", Name = "醍摩豆账号绑定", TName = "醍摩豆账号绑定", EName = "醍摩豆账号绑定", RWN = "W", Limit = false)]
+        public async Task<IActionResult> Bind(BizBind bind)
+        {
+            string HostName = HttpContext.GetHostName();
+            if (!string.IsNullOrWhiteSpace(_option.HostName))
+            {
+                HostName = _option.HostName;
+            }
+            if (!_option.Location.Contains("Dep") && !_option.Location.Contains("Test"))
+            {
+                HostName = "www.teammodel.cn";
+            }
+            var rurl = new StringBuilder($"https://{HostName}/tmdid-sso");
+            try
+            {
+                TmdidImplicit tmdidImplicit = null;
+                int status = 0;
+                string msg = "账号未关联";
+                Teacher teacher = null;
+                BizSso sso = HttpUtility.UrlDecode(bind.param, Encoding.UTF8).ToObject<BizSso>();
+                if (!string.IsNullOrWhiteSpace(bind.mobile))
+                {
+                    var coreUser = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", bind.mobile } }, _option.Location, _configuration);
+                    if (coreUser != null)
+                    {
+                        var clientID = _configuration.GetValue<string>("HaBookAuth:CoreService:clientID");
+                        tmdidImplicit = await _coreAPIHttpService.Implicit(new Dictionary<string, string> {   { "grant_type", "implicit" },
+                                        { "client_id",clientID },
+                                        { "account",coreUser.id },
+                                        { "nonce",Guid.NewGuid().ToString()} }, _option.Location, _configuration);
+                        if (tmdidImplicit != null && !string.IsNullOrWhiteSpace(tmdidImplicit.id_token))
+                        {
+                            bind.id_token = tmdidImplicit.id_token;
+                        }
+                        else
+                        {
+                            status = 7;
+                        }
+                    }
+                    else
+                    {
+                        status = 7;
+
+                    }
+                }
+                if (string.IsNullOrWhiteSpace(bind.id_token))
+                {
+                    status = 7;
+                }
+                else
+                {
+                    JwtSecurityToken jwt = new JwtSecurityToken(bind.id_token);
+                    var id = jwt.Payload.Sub;
+                    CoreUser coreUserById = await _coreAPIHttpService.GetUserInfo(new Dictionary<string, string> { { "key", $"{id}" } }, _option.Location, _configuration);
+                    if (coreUserById == null || string.IsNullOrWhiteSpace(coreUserById.mobile) || coreUserById.mobile.Length != 11)
+                    {
+                        status = 7;
+                    }
+                    jwt.Payload.TryGetValue("name", out object name);
+                    jwt.Payload.TryGetValue("picture", out object picture);
+
+                    string sql = $"select value c from c  join b in c.binds where b.type='{bind.type}' and b.userid ='{sso.userid}'";
+                    var result = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).GetList<Teacher>(sql, "Base");
+                    List<Teacher> teachers = result.list;
+                    if (teachers.Any())
+                    {
+                        teacher = teachers.First();
+                    }
+                    else
+                    {
+                        //如果沒有,則初始化Teacher基本資料到Cosmos
+                        teacher = new Teacher
+                        {
+                            createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                            pk = "Base",
+                            code = "Base",
+                            name = sso.name?.ToString(),
+                            picture = sso.picture?.ToString(),
+                            //创建账号并第一次登录IES5则默认赠送1G
+                            size = 1,
+                            defaultSchool = sso.school,
+                            schools = new List<TeacherSchool>(),
+                        };
+                        var response = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).ReadItemStreamAsync(coreUserById.id, new PartitionKey("Base"));
+                        if (response.Status==200)
+                        {
+                            teacher=JsonDocument.Parse(response.Content).RootElement.ToObject<Teacher>();
+                            teacher.defaultSchool=sso.school;
+                        }
+                        teacher.id = coreUserById.id;
+                        status = 3;//已关联
+                        msg = "账号已关联";
+                        if (string.IsNullOrWhiteSpace(teacher.name))
+                        {
+                            teacher.name=coreUserById.name;
+                        }
+                        if (string.IsNullOrWhiteSpace(teacher.picture))
+                        {
+                            teacher.picture=coreUserById.picture;
+                        }
+                        teacher.binds.Add(new ThirdBind { type=bind.type, userid=sso.userid, username=sso.name, account=sso.mobile, data=new List<string> { sso.ToJsonString() } });
+                        await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).UpsertItemAsync(teacher, new PartitionKey("Base"));
+                    }
+                    if (!string.IsNullOrWhiteSpace(sso.school))
+                    {
+                        Azure.Response responseSchool = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").ReadItemStreamAsync(sso.school, new PartitionKey("Base"));
+                        if (responseSchool.Status == 200)
+                        {
+                            School school = JsonDocument.Parse(responseSchool.Content).RootElement.ToObject<School>();
+                            JoinSchool(id, name?.ToString(), picture?.ToString(), school);
+                        }
+                    }
+                    status = 200;
+                }
+                if (status == 200)
+                {
+                    var content = new { grant_type = "code", client_id = "516148eb-6a38-4657-ba98-a3699061937f", nonce = Guid.NewGuid().ToString(), bind.id_token };
+                    var response = await _httpClientFactory.CreateClient().PostAsJsonAsync("https://api2.teammodel.cn/oauth2/login", content);
+                    string code = string.Empty;
+                    if (response.IsSuccessStatusCode)
+                    {
+                        string jsonStr = await response.Content.ReadAsStringAsync();
+                        var json = jsonStr.ToObject<JsonElement>();
+                        if (json.TryGetProperty("code", out JsonElement _code))
+                        {
+                            code = _code.ToString();
+                        }
+                    }
+                    string callback = string.Empty;
+                    if (sso.callback.Contains("https://www.habook.com.cn"))
+                    {
+                        callback = $"https://account.teammodel.cn/?code={code}&callback=https%3A%2F%2Fwww.habook.com.cn%2F";
+                    }
+                    else if (sso.callback.Contains("https://www.teammodel.cn"))
+                    {
+                        callback = $"https://www.teammodel.cn/login?code={code}&callback=https%3A%2F%2Fwww.teammodel.cn%2Flogin";
+                    }
+                    else
+                    {
+                        callback = $"https://account.teammodel.cn/?code={code}&callback={HttpUtility.UrlEncode(sso.callback, Encoding.UTF8)}";
+                    }
+                    // rurl.Append($"?status={status}&msg={HttpUtility.UrlEncode("登录成功", Encoding.UTF8)}&callback={callback}&id_token={implicit_token?.id_token}&access_token={implicit_token?.access_token}&expires_in={HttpUtility.UrlEncode(implicit_token?.expires_in)}&token_type={HttpUtility.UrlEncode(implicit_token?.token_type)}").ToString();
+                    // return Ok(new { url = rurl.ToString() });
+                    return Ok(new { url = callback });
+
+                }
+                else if (status == 7)
+                {
+                    msg = $"教师账号:{sso.userid},{sso.mobile}失败";
+                    rurl.Append($"?status={status}&msg={HttpUtility.UrlEncode(msg, Encoding.UTF8)}&param={HttpUtility.UrlEncode(sso.ToJsonString(), Encoding.UTF8)}");
+                    return Ok(new { url = rurl.ToString() });
+                }
+                else
+                {
+                    rurl.Append($"?status={7}&msg={HttpUtility.UrlEncode("账号未关联成功", Encoding.UTF8)}");
+                    return Ok(new { url = rurl.ToString() });
+                }
+            }
+            catch (Exception ex)
+            {
+                await _dingDing.SendBotMsg($"账号绑定账号异常,{ex.Message},{ex.StackTrace},\n{bind.ToJsonString()}", GroupNames.成都开发測試群組);
+
+            }
+            rurl.Append($"?status={7}&msg={HttpUtility.UrlEncode("账号未关联成功", Encoding.UTF8)}");
+            return Ok(new { url = rurl.ToString() });
+        }
+        [HttpPost("notify-bind")]
+        [AllowAnonymous]
+        [ApiToken(Auth = "2202", Name = "醍摩豆账号绑定通知", TName = "醍摩豆账号绑定通知", EName = "醍摩豆账号绑定", RWN = "N", Limit = false)]
+        public async Task<IActionResult> NotifyBind(BizBind bind)
+        {
+            return Ok(new {  });
+        }
+        private async void JoinSchool(string tmdid, string name, string picture, School school)
+        {
+            Teacher teacher = null;
+            Azure.Response responseTeacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "Teacher").ReadItemStreamAsync(tmdid, new PartitionKey("Base"));
+            if (responseTeacher.Status == 200)
+            {
+                teacher = JsonDocument.Parse(responseTeacher.Content).RootElement.ToObject<Teacher>();
+                var sc = teacher.schools.Find(z => z.schoolId.Equals(school.id));
+                if (sc == null)
+                {
+                    teacher.schools.Add(new TeacherSchool
+                    {
+                        schoolId = school.id,
+                        name = school.name,
+                        picture = school.picture,
+                        status = "join",
+                        time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                        areaId = school.areaId
+                    });
+                    teacher.defaultSchool = school.id;
+                }
+            }
+            else
+            {
+                teacher = new Teacher
+                {
+                    createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                    id = tmdid,
+                    pk = "Teacher",
+                    code = "Base",
+                    name = name,
+                    picture = picture?.ToString(),
+                    //创建账号并第一次登录IES5则默认赠送1G
+                    size = 1,
+                    defaultSchool = school.id,
+                    schools = new List<TeacherSchool>() { new TeacherSchool
+                    {
+                        schoolId=school.id,
+                        name=school.name,picture=school.picture,status="join",time=DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),areaId=school.areaId
+                    } },
+                };
+            }
+            await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.Teacher).UpsertItemAsync(teacher, new PartitionKey(teacher.code));
+            Azure.Response responseSchoolTeacher = await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, Constant.School).ReadItemStreamAsync(tmdid, new PartitionKey($"Teacher-{school.id}"));
+            if (responseSchoolTeacher.Status != 200)
+            {
+                SchoolTeacher schoolTeacher = new SchoolTeacher
+                {
+                    id = teacher.id,
+                    code = $"Teacher-{school.id}",
+                    roles = new List<string> { "teacher" },
+                    permissions = new List<string>(),
+                    pk = "Teacher",
+                    name = teacher.name,
+                    picture = teacher.picture,
+                    status = "join",
+                    createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
+                    ttl = -1
+                };
+                await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync(schoolTeacher, new PartitionKey(schoolTeacher.code));
+            }
+            else
+            {
+                SchoolTeacher schoolTeacher = JsonDocument.Parse(responseSchoolTeacher.Content).RootElement.ToObject<SchoolTeacher>();
+                if (schoolTeacher != null)
+                {
+                    if (!schoolTeacher.roles.IsEmpty())
+                    {
+                        if (!schoolTeacher.roles.Contains("teacher"))
+                        {
+                            schoolTeacher.roles.Add("teacher");
+                        }
+                    }
+                    else
+                    {
+                        schoolTeacher.roles = new List<string> { "teacher" };
+                    }
+                    schoolTeacher.status = "join";
+                    schoolTeacher.pk = "Teacher";
+                    schoolTeacher.name = teacher.name;
+                    schoolTeacher.picture = teacher.picture;
+                    schoolTeacher.createTime = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
+                    schoolTeacher.ttl = -1;
+                    schoolTeacher.permissions = schoolTeacher.permissions.IsNotEmpty() ? schoolTeacher.permissions : new List<string>();
+                    await _azureCosmos.GetCosmosClient().GetContainer(Constant.TEAMModelOS, "School").UpsertItemAsync(schoolTeacher, new PartitionKey(schoolTeacher.code));
+                }
+            }
+        }
+    }
+    public class BizBind
+    {
+        [Required(ErrorMessage = "{0} 必须填写")]
+        public string param { get; set; }
+        public string id_token { get; set; }
+        public string mobile { get; set; }
+        public string type { get; set; }
+    }
+
+    public class BizSso
+    {
+        /// <summary>
+        /// 必传
+        /// </summary>
+        public string userid { get; set; }
+        public string mobile { get; set; }
+        public string name { get; set; }
+        public string picture { get; set; }
+        public string callback { get; set; }
+        public string school { get; set; }
+        //https://www.teammodel.cn/login?code=Code8c8dfddd-e717-4a2a-ac83-88f480303d80&callback=https%3A%2F%2Fwww.habook.com.cn%2F
+        //https://account.teammodel.cn/?code=Code19695116-fe51-4c3f-9172-7a6ab9f69523&callback=https%3A%2F%2Fwww.habook.com.cn%2F
+    }
+}

File diff suppressed because it is too large
+ 30 - 2
TEAMModelOS/Controllers/System/WeChatPayController.cs


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

@@ -684,7 +684,7 @@ namespace TEAMModelOS.Controllers
                         //{
                         //    setting.accessConfig = null;
                         //}
-                        areas.Add(new AreaDto { areaId = area?.id, name = area?.name, standard = area?.standard, standardName = area?.standardName, setting = setting, access = access });
+                        areas.Add(new AreaDto {shortCode=area?.shortCode, areaId = area?.id, name = area?.name, standard = area?.standard, standardName = area?.standardName, setting = setting, access = access });
                     }
                 }
                 if (school_code.Equals(teacher.defaultSchool) && teacher.schools.IsNotEmpty() && !teacher.schools.Select(x => x.schoolId).Contains(school_code))
@@ -791,6 +791,7 @@ namespace TEAMModelOS.Controllers
                         //}
                         currArea = new
                         {
+                            shortCode = area?.shortCode,
                             areaId = area?.id,
                             name = area?.name,
                             standard = area?.standard,

+ 4 - 4
TEAMModelOS/TEAMModelOS.csproj

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

+ 34 - 34
TEAMModelOS/appsettings.Development.json

@@ -10,7 +10,7 @@
   "Option": {
     "Location": "China-Dep",
     "LocationNum": "1",
-    "HostName": "test.teammodel.cn",
+    "HostName": "localhost:5001",
     "AllowedHosts": [ "localhost", "*.teammodel.cn", "*.teammodel.net", "*.habookaclass.biz", "test" ],
     "Issuer": "www.teammodel.cn",
     "JwtSecretKey": "fXO6ko/qyXeYrkecPeKdgXnuLXf9vMEtnBC9OB3s+aA=",
@@ -18,52 +18,52 @@
     "IdTokenSalt": "8263692E2213497BB55E74792B7900B4",
     "HttpTrigger": "https://teammodelosfunction-test.chinacloudsites.cn/api/",
     //"HttpTrigger": "http://localhost:7071/api/"
-    "Version": "5.2309.27.1"
+    "Version": "5.2310.11.1"
   },
   "Azure": {
     // 测试站数据库
-    "Storage": {
-      "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodeltest;AccountKey=O2W2vadCqexDxWO+px+QK7y1sHwsYj8f/WwKLdOdG5RwHgW/Dupz9dDUb4c1gi6ojzQaRpFUeAAmOu4N9E+37A==;EndpointSuffix=core.chinacloudapi.cn"
-    },
-    "Cosmos": {
-      "ConnectionString": "AccountEndpoint=https://cdhabookdep-free.documents.azure.cn:443/;AccountKey=JTUVk92Gjsx17L0xqxn0X4wX2thDPMKiw4daeTyV1HzPb6JmBeHdtFY1MF1jdctW1ofgzqkDMFOtcqS46by31A==;"
-    },
-    "Redis": {
-      "ConnectionString": "52.130.252.100:6379,password=habook,ssl=false,abortConnect=False,writeBuffer=10240"
-    },
-    "ServiceBus": {
-      "ConnectionString": "Endpoint=sb://teammodelos.servicebus.chinacloudapi.cn/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=Sy4h4EQ8zP+7w/lOLi1X3tGord/7ShFHimHs1vC50Dc=",
-      "ActiveTask": "dep-active-task",
-      "ItemCondQueue": "dep-itemcond",
-      "GenPdfQueue": "dep-genpdf"
-    },
-    "SignalR": {
-      "ConnectionString": "Endpoint=https://channel.service.signalr.net;AccessKey=KrblW06tuA4a/GyqRPDU0ynFFmAWxbAvyJihHclSXbQ=;Version=1.0;"
-    }
-    // 正式站数据库
     //"Storage": {
-    //  "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodelos;AccountKey=Dl04mfZ9hE9cdPVO1UtqTUQYN/kz/dD/p1nGvSq4tUu/4WhiKcNRVdY9tbe8620nPXo/RaXxs+1F9sVrWRo0bg==;EndpointSuffix=core.chinacloudapi.cn"
+    //  "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodeltest;AccountKey=O2W2vadCqexDxWO+px+QK7y1sHwsYj8f/WwKLdOdG5RwHgW/Dupz9dDUb4c1gi6ojzQaRpFUeAAmOu4N9E+37A==;EndpointSuffix=core.chinacloudapi.cn"
     //},
     //"Cosmos": {
-    //  "ConnectionString": "AccountEndpoint=https://teammodelos.documents.azure.cn:443/;AccountKey=clF73GwPECfP1lKZTCvs8gLMMyCZig1HODFbhDUsarsAURO7TcOjVz6ZFfPqr1HzYrfjCXpMuVD5TlEG5bFGGg==;"
+    //  "ConnectionString": "AccountEndpoint=https://cdhabookdep-free.documents.azure.cn:443/;AccountKey=JTUVk92Gjsx17L0xqxn0X4wX2thDPMKiw4daeTyV1HzPb6JmBeHdtFY1MF1jdctW1ofgzqkDMFOtcqS46by31A==;"
     //},
     //"Redis": {
-    //  "ConnectionString": "CoreRedisCN.redis.cache.chinacloudapi.cn:6380,password=LyJWP1ORJdv+poXWofAF97lhCEQPg1wXWqvtzXGXQuE=,ssl=True,abortConnect=False"
+    //  "ConnectionString": "52.130.252.100:6379,password=habook,ssl=false,abortConnect=False,writeBuffer=10240"
     //},
     //"ServiceBus": {
-    //  "ConnectionString": "Endpoint=sb://coreiotservicebuscnpro.servicebus.chinacloudapi.cn/;SharedAccessKeyName=TEAMModelOS;SharedAccessKey=llRPBMDJG9w1Nnifj+pGhV0g4H2REcq0PjvX2qqpcOg=",
-    //  "ActiveTask": "active-task",
-    //  "ItemCondQueue": "itemcond",
-    //  "GenPdfQueue": "genpdf"
+    //  "ConnectionString": "Endpoint=sb://teammodelos.servicebus.chinacloudapi.cn/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=Sy4h4EQ8zP+7w/lOLi1X3tGord/7ShFHimHs1vC50Dc=",
+    //  "ActiveTask": "dep-active-task",
+    //  "ItemCondQueue": "dep-itemcond",
+    //  "GenPdfQueue": "dep-genpdf"
     //},
     //"SignalR": {
-    //  "ConnectionString": "Endpoint=https://channel.signalr.azure.cn;AccessKey=AtcB7JYFNUbUXb1rGxa3PVksQ2X5YSv3JOHZR9J88tw=;Version=1.0;"
-    //},
-    //"Speech": {
-    //  "SubscriptionKey": "a4f5f4e2e2e54c6e8b0a4a0b4a0a4a0b",
-    //  "Region": "chinanorth3",
-    //  "Endpoint": "https://chinanorth3.api.cognitive.azure.cn/sts/v1.0/issuetoken"
+    //  "ConnectionString": "Endpoint=https://channel.service.signalr.net;AccessKey=KrblW06tuA4a/GyqRPDU0ynFFmAWxbAvyJihHclSXbQ=;Version=1.0;"
     //}
+    // 正式站数据库
+    "Storage": {
+      "ConnectionString": "DefaultEndpointsProtocol=https;AccountName=teammodelos;AccountKey=Dl04mfZ9hE9cdPVO1UtqTUQYN/kz/dD/p1nGvSq4tUu/4WhiKcNRVdY9tbe8620nPXo/RaXxs+1F9sVrWRo0bg==;EndpointSuffix=core.chinacloudapi.cn"
+    },
+    "Cosmos": {
+      "ConnectionString": "AccountEndpoint=https://teammodelos.documents.azure.cn:443/;AccountKey=clF73GwPECfP1lKZTCvs8gLMMyCZig1HODFbhDUsarsAURO7TcOjVz6ZFfPqr1HzYrfjCXpMuVD5TlEG5bFGGg==;"
+    },
+    "Redis": {
+      "ConnectionString": "CoreRedisCN.redis.cache.chinacloudapi.cn:6380,password=LyJWP1ORJdv+poXWofAF97lhCEQPg1wXWqvtzXGXQuE=,ssl=True,abortConnect=False"
+    },
+    "ServiceBus": {
+      "ConnectionString": "Endpoint=sb://coreiotservicebuscnpro.servicebus.chinacloudapi.cn/;SharedAccessKeyName=TEAMModelOS;SharedAccessKey=llRPBMDJG9w1Nnifj+pGhV0g4H2REcq0PjvX2qqpcOg=",
+      "ActiveTask": "active-task",
+      "ItemCondQueue": "itemcond",
+      "GenPdfQueue": "genpdf"
+    },
+    "SignalR": {
+      "ConnectionString": "Endpoint=https://channel.signalr.azure.cn;AccessKey=AtcB7JYFNUbUXb1rGxa3PVksQ2X5YSv3JOHZR9J88tw=;Version=1.0;"
+    },
+    "Speech": {
+      "SubscriptionKey": "a4f5f4e2e2e54c6e8b0a4a0b4a0a4a0b",
+      "Region": "chinanorth3",
+      "Endpoint": "https://chinanorth3.api.cognitive.azure.cn/sts/v1.0/issuetoken"
+    }
   },
   "HaBookAuth": {
     "CoreId": {

+ 1 - 1
TEAMModelOS/appsettings.json

@@ -18,7 +18,7 @@
     "Exp": 86400,
     "IdTokenSalt": "8263692E2213497BB55E74792B7900B4",
     "HttpTrigger": "https://teammodelosfunction.chinacloudsites.cn/api/",
-    "Version": "5.2309.27.1"
+    "Version": "5.2310.11.1"
   },
   "Azure": {
     "Storage": {